diff --git a/.gitignore b/.gitignore index 32858aad..d33629a3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ .mtj.tmp/ # Package Files # -*.jar *.war *.ear diff --git a/Figures/Automated Analysis.png b/Figures/Automated Analysis.png new file mode 100644 index 00000000..540c050a Binary files /dev/null and b/Figures/Automated Analysis.png differ diff --git a/Figures/Formal Specification 1.png b/Figures/Formal Specification 1.png new file mode 100644 index 00000000..ca336fd3 Binary files /dev/null and b/Figures/Formal Specification 1.png differ diff --git a/Figures/Formal Specification.png b/Figures/Formal Specification.png new file mode 100644 index 00000000..ec68df9f Binary files /dev/null and b/Figures/Formal Specification.png differ diff --git a/Figures/Reasoning Approches using solvers.png b/Figures/Reasoning Approches using solvers.png new file mode 100644 index 00000000..a96bc0cb Binary files /dev/null and b/Figures/Reasoning Approches using solvers.png differ diff --git a/Figures/Tarski Architecture.png b/Figures/Tarski Architecture.png new file mode 100644 index 00000000..3469e6e9 Binary files /dev/null and b/Figures/Tarski Architecture.png differ diff --git a/Figures/Tarski Features - Intorduction.png b/Figures/Tarski Features - Intorduction.png new file mode 100644 index 00000000..2d7a7315 Binary files /dev/null and b/Figures/Tarski Features - Intorduction.png differ diff --git a/Figures/Tarski_SummerSchool_Poster.pdf b/Figures/Tarski_SummerSchool_Poster.pdf new file mode 100644 index 00000000..80031620 Binary files /dev/null and b/Figures/Tarski_SummerSchool_Poster.pdf differ diff --git a/Figures/Traceability Management.png b/Figures/Traceability Management.png new file mode 100644 index 00000000..bd7ac0ce Binary files /dev/null and b/Figures/Traceability Management.png differ diff --git a/README.md b/README.md index 07fcd038..63417f3d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,75 @@ -WP3 +Work Package 3 (Tarski Platform) === +1. Introduction +--- -Work Package 3 - Model to/from Knowledge Base (UNIT) + In this work package, we introduce a new approach with its supporting platform which enables the user to interactively configure traceable elements and trace links. The specification is supported by formalizing the semantics of traceability in first-order relational logic in order to perform automated analysis such as consistency checking, reasoning on trace relations and trace element discovery. The usefulness of the approach is demonstrated in the context of application life-cycle platform in software industry and being tested in aviation industry. + + * [`Screen cast that shows Tarski in action (latest version of the platform)`](https://youtu.be/J7qEVOG6bjg) + * [`Installation of Tarski Platform on ModelWriter (older version of the platform)`](https://youtu.be/NE7hESkaLCo) +For an example workspace, you can clone this source code repository [`Demonstrations`](https://github.com/ModelWriter/Demonstrations) and an example configuration file, you can directly get from [`HAVELSAN use case`](https://goo.gl/8Zqxi8). -Product Backlog of WP3 [https://waffle.io/modelwriter/wp3](https://waffle.io/modelwriter/wp3) +[![roject Poster presented in SAT/SMT/AR Summer School 2016](https://github.com/ModelWriter/WP3/raw/master/Screenshots/poster.png)](https://github.com/ModelWriter/WP3/blob/master/Figures/Tarski_SummerSchool_Poster.pdf) + +**Type Hierarchy after loading an Alloy specification to the system (included several annotations)** + +![Type Hierarchy](https://github.com/ModelWriter/WP3/raw/master/Screenshots/RelationNames.png) + +**Management of first-order relational model** + +![Management of first-order relational model](https://github.com/ModelWriter/WP3/raw/master/Screenshots/ModelManagement.png) + +**Assigning type to a unary relation while creating a trace element on a text file** + +![Assigning type to a unary relation while creating a trace element on a text file](https://github.com/ModelWriter/WP3/blob/master/Screenshots/AssigningTypes.png) + +**Selecting a binary relation to create link** + +![Selecting a binary relation to create link](https://github.com/ModelWriter/WP3/raw/master/Screenshots/SelectingBinaryRelation.png) + +**Selecting a range from existing trace elements for the binary relation** + +![Selecting a range from existing trace elements for the binary relation](https://github.com/ModelWriter/WP3/raw/master/Screenshots/SelectingRangeForAssigningTypes.png) + +**Automated Analysis** + +![Automated Analysis](https://github.com/ModelWriter/WP3/raw/master/Screenshots/automatedAnalysis.png) + +Work Package Objectives (from the Final Project Propsal) +--- + +The primary objective of this WP is to provide the `synchronization mechanism` of the ModelWriter platform that will keep the `user-visible models` consistent with the `KB-stored models` and vice versa. This work package addresses all problems related to the "model-to-model transformations" in ModelWriter. + +* By `user-visible models` is meant those models that have been explicitly created by a Technical Author, using e.g. a spreadsheet, a kind of UML diagram, a block diagram, a mind map, etc. or any modelling tool (part of the “Model” side of ModelWriter) he has found the most appropriate for authoring his technical information. +* By `KB-stored model` is meant a part of the Knowledge Base devoted to storing pieces of related information, disregarding whether it is represented in user-visible models, in natural-language documents, or in both. + +This mechanism will be based on `model-to-model (M2M) transformations` of two complementary categories: + +* WP3.1, for transforming a `user-visible model` to a KB-stored model (this "mirrors" WP2.1). +* WP3.2, for transforming a `KB-stored model` into a user-visible model (this "mirrors" WP2.2). + + + +Expected Results +--- + +An Eclipse-based M2M Transformation Framework, extensible so as to accommodate an increasing number of types of (user-visible) models. This will consist of the following main envisioned plug-in components: + +* `Transformation Manager`: provides the infrastructure to register and launch transformations. +* `Configuration Manager`: for personalizing the behaviour of the framework to meet the needs of a specific standard / organization / project / individual. +* `Traceability Manage`: keeps links between elements of user-visible models and elements of the KB. +* `Synchronization Manager`: triggering transformations when synchronization is needed. + +Approach for the Work Package +--- + +The main goal of this WP is to develop a M2M Transformation Framework that supports the synchronization mechanisms for the ModelWriter tool. + +These mechanisms will be based on a requirements synchronization framework that can be extended to support different requirements models (based on both textual and/or visual notations). The framework is made up of three main components: + + 1. A meta-modelling infrastructure, + 2. A DSL for model transformation specifications, and + 3. A model synchronization API. + +*final version* diff --git a/Screenshots/AssigningTypes.png b/Screenshots/AssigningTypes.png new file mode 100644 index 00000000..29748d7d Binary files /dev/null and b/Screenshots/AssigningTypes.png differ diff --git a/Screenshots/ModelManagement.png b/Screenshots/ModelManagement.png new file mode 100644 index 00000000..ed8309ab Binary files /dev/null and b/Screenshots/ModelManagement.png differ diff --git a/Screenshots/RelationNames.png b/Screenshots/RelationNames.png new file mode 100644 index 00000000..fc9a3c30 Binary files /dev/null and b/Screenshots/RelationNames.png differ diff --git a/Screenshots/Screenshot-mixed.png b/Screenshots/Screenshot-mixed.png new file mode 100644 index 00000000..88bb8897 Binary files /dev/null and b/Screenshots/Screenshot-mixed.png differ diff --git a/Screenshots/SelectingBinaryRelation.png b/Screenshots/SelectingBinaryRelation.png new file mode 100644 index 00000000..83fd8199 Binary files /dev/null and b/Screenshots/SelectingBinaryRelation.png differ diff --git a/Screenshots/SelectingRangeForAssigningTypes.png b/Screenshots/SelectingRangeForAssigningTypes.png new file mode 100644 index 00000000..1c6cecd7 Binary files /dev/null and b/Screenshots/SelectingRangeForAssigningTypes.png differ diff --git a/Screenshots/automatedAnalysis.png b/Screenshots/automatedAnalysis.png new file mode 100644 index 00000000..f9a9f448 Binary files /dev/null and b/Screenshots/automatedAnalysis.png differ diff --git a/Screenshots/poster.png b/Screenshots/poster.png new file mode 100644 index 00000000..8dc79724 Binary files /dev/null and b/Screenshots/poster.png differ diff --git a/Source/eu.modelwriter.alloyanalyzer/.classpath b/Source/eu.modelwriter.alloyanalyzer/.classpath new file mode 100644 index 00000000..1e0f342a --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/.project b/Source/eu.modelwriter.alloyanalyzer/.project new file mode 100644 index 00000000..0cb33778 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/.project @@ -0,0 +1,28 @@ + + + eu.modelwriter.alloyanalyzer + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + + diff --git a/Source/eu.modelwriter.alloyanalyzer/.settings/org.eclipse.jdt.core.prefs b/Source/eu.modelwriter.alloyanalyzer/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..3a215370 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/Source/eu.modelwriter.alloyanalyzer/META-INF/MANIFEST.MF b/Source/eu.modelwriter.alloyanalyzer/META-INF/MANIFEST.MF new file mode 100644 index 00000000..dd8e122b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/META-INF/MANIFEST.MF @@ -0,0 +1,73 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Alloyanalyzer +Bundle-SymbolicName: eu.modelwriter.alloyanalyzer +Bundle-Version: 1.0.0.qualifier +Bundle-ClassPath: alloyanalyzer.jar, + lib/alloy4.2.jar +Export-Package: LICENSES, + apple.awt, + com.apple.eawt, + com.apple.eio, + com.sun.imageio.plugins.tiff, + edu.mit.csail.sdg.alloy4, + edu.mit.csail.sdg.alloy4compiler.ast, + edu.mit.csail.sdg.alloy4compiler.parser, + edu.mit.csail.sdg.alloy4compiler.sim, + edu.mit.csail.sdg.alloy4compiler.translator, + edu.mit.csail.sdg.alloy4graph, + edu.mit.csail.sdg.alloy4viz, + edu.mit.csail.sdg.alloy4whole, + help, + help.image, + icons.ColorIcons, + icons.ShapeIcons, + icons.StyleIcons, + images, + java_cup.runtime, + kodkod.ast, + kodkod.ast.operator, + kodkod.ast.visitor, + kodkod.engine, + kodkod.engine.bool, + kodkod.engine.config, + kodkod.engine.fol2sat, + kodkod.engine.satlab, + kodkod.engine.ucore, + kodkod.instance, + kodkod.util.collections, + kodkod.util.ints, + kodkod.util.nodes, + models.book.appendixA, + models.book.appendixE, + models.book.chapter2, + models.book.chapter4, + models.book.chapter5, + models.book.chapter6, + models.book.chapter6.memory, + models.examples.algorithms, + models.examples.case_studies, + models.examples.puzzles, + models.examples.systems, + models.examples.toys, + models.examples.tutorial, + models.util, + org.sat4j, + org.sat4j.core, + org.sat4j.minisat, + org.sat4j.minisat.constraints, + org.sat4j.minisat.constraints.card, + org.sat4j.minisat.constraints.cnf, + org.sat4j.minisat.core, + org.sat4j.minisat.learning, + org.sat4j.minisat.orders, + org.sat4j.minisat.restarts, + org.sat4j.opt, + org.sat4j.reader, + org.sat4j.specs, + org.sat4j.tools, + org.sat4j.tools.encoding, + org.sat4j.tools.xplain, + target, + tmp +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/.gitignore b/Source/eu.modelwriter.alloyanalyzer/bin/.gitignore new file mode 100644 index 00000000..5e7fcc4a --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/.gitignore @@ -0,0 +1,4 @@ +/edu/ +/java_cup/ +/kodkod/ +/tmp/ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/META-INF/MANIFEST.MF b/Source/eu.modelwriter.alloyanalyzer/bin/META-INF/MANIFEST.MF new file mode 100644 index 00000000..c10f81ea --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/META-INF/MANIFEST.MF @@ -0,0 +1,4 @@ +Manifest-Version: 1.0 +Created-By: 1.5.0 (Sun Microsystems Inc.) +Main-Class: edu.mit.csail.sdg.alloy4whole.SimpleGUI + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/README.TXT b/Source/eu.modelwriter.alloyanalyzer/bin/README.TXT new file mode 100644 index 00000000..7cd623ea --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/README.TXT @@ -0,0 +1,63 @@ +The Alloy Analyzer + + The Alloy Analyzer is a tool developed by the Software Design + Group (http://sdg.csail.mit.edu/) for analyzing models written in + Alloy, a simple structural modeling language based on first-order + logic. The tool can generate instances of invariants, simulate + the execution of operations (even those defined implicitly), and + check user-specified properties of a model. Alloy and its + analyzer have been used primarily to explore abstract software + designs. Its use in analyzing code for conformance to a + specification and as an automatic test case generator are being + investigated in ongoing research projects. + + See the web page for a description of what's new in Alloy: + + http://alloy.mit.edu/ + + +Detailed Instructions: + + 1. Java 5 or later + + Java runtimes are available at no economic charge from Sun and + IBM and others. One may have come pre-installed in your OS. + Alloy does not currently work with gcj because of its limited + library support. + + 2. Running Alloy on Mac OS X + + Just double-click on the dmg file, + then drag the Alloy application into your application directory. + + 3. Running Alloy on other platforms + + Just double-click on the jar file, or type: + + java -jar alloy4.jar + +The source code for the Alloy Analyzer is available +under the MIT license. + +The Alloy Analyzer utilizes several third-party packages whose code may +be distributed under a different license (see the various LICENSE files +in the distribution for details). We are extremely grateful to the authors +of these packages for making their source code freely available. + + * Kodkod + http://web.mit.edu/~emina/www/kodkod.html + + * CUP Parser Generator for Java + http://www2.cs.tum.edu/projects/cup/ + + * JFlex scanner generator for Java + http://jflex.de/ + + * The zChaff solver + http://www.princeton.edu/~chaff/zchaff.html + + * The MiniSat solver + http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/ + + * The SAT4J solver + http://www.sat4j.org/ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/README.md b/Source/eu.modelwriter.alloyanalyzer/bin/README.md new file mode 100644 index 00000000..9942d4bc --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/README.md @@ -0,0 +1,45 @@ +Alloy Analyzer (source code mirror) +=================================== + +Summary +------- +This is a copy of the source code for [MIT's Alloy Analyzer model checking tool](http://alloy.mit.edu/alloy/). +It also includes an Ant build.xml script, which is not part of the original MIT source code. +This copy was created to facilitate modification to the core Alloy tool (the parts which fall +under the `edu.mit` package structure). + +It was created as follows (not necessarily in this order): + +1. Downloaded the JAR file located at: http://alloy.mit.edu/alloy/downloads/alloy4.2.jar +2. Extracted the JAR file. +3. Added this `README.md` file and a `build.xml` file. +3. Deleted core `.class` files (using the _clean_ target in `build.xml`) + +Building +-------- +The Ant build.xml script contains the following targets: + +- _build_: Compiles the `.java` files under the `edu` directory. + + Other directories are not touched; it is assumed that these contain libraries + which have been pre-compiled. + + The auto-generated parser and lexer `.java` files (located in the `edu/mit/csail/sdg/alloy4compiler/parser` directory) + are neither deleted nor generated by the Ant script. The directory already contains shell scripts + to re-generate them using JFlex and CUP. +- _dist_: Creates an executable JAR file in the `dist` directory. This JAR file looks essentially like the official + Alloy JAR file released by MIT. +- _all_: Runs _dist_. +- _clean_: Deletes the `dist` directory and all class files under the `edu` directory. + +Notes +----- + +- As per the manifest, the main class is `edu.mit.csail.sdg.alloy4whole.SimpleGUI`. +- The version number and build date which the tool displays are not accurate. + These are set in the `edu.mit.csail.sdg.alloy4.Version` class, and are supposed to be + updated by the build script when building a release. + This project was not intended to create official releases, so it was left as-is. +- There is a class `edu.mit.csail.sdg.alloy4.MailBug` which includes logic to email + crash reports to MIT. You should change this class if you are modifying the source code + and creating your own release. diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/amd64-linux/berkmin b/Source/eu.modelwriter.alloyanalyzer/bin/amd64-linux/berkmin new file mode 100644 index 00000000..f0aa2cee Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/amd64-linux/berkmin differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/amd64-linux/libminisat.so b/Source/eu.modelwriter.alloyanalyzer/bin/amd64-linux/libminisat.so new file mode 100644 index 00000000..d286aa4b Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/amd64-linux/libminisat.so differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/amd64-linux/libminisatprover.so b/Source/eu.modelwriter.alloyanalyzer/bin/amd64-linux/libminisatprover.so new file mode 100644 index 00000000..392474ac Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/amd64-linux/libminisatprover.so differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/amd64-linux/libzchaff.so b/Source/eu.modelwriter.alloyanalyzer/bin/amd64-linux/libzchaff.so new file mode 100644 index 00000000..dc9c229d Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/amd64-linux/libzchaff.so differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/edu/mit/csail/sdg/alloy4compiler/parser/Alloy.cup b/Source/eu.modelwriter.alloyanalyzer/bin/edu/mit/csail/sdg/alloy4compiler/parser/Alloy.cup new file mode 100644 index 00000000..1796efb0 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/edu/mit/csail/sdg/alloy4compiler/parser/Alloy.cup @@ -0,0 +1,1038 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2008, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Warning: this file alone is not enough to correctly parse Alloy4 since the actual + * language is not LALR(1); instead, we have to pre-process the token stream + * using CompFilter.java to rearrange/transform the token stream, and then we can + * parse the transformed token stream using this LALR(1) grammar. For more information, + * please refer to CompFilter.java + */ + +import java.util.Stack; +import java.util.List; +import java.util.ArrayList; +import java.util.TreeSet; +import java.util.Map; +import java.util.LinkedHashMap; +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.Reader; +import java.io.IOException; +import java.io.StringReader; +import java_cup.runtime.*; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.alloy4compiler.ast.Attr.AttrType; +import edu.mit.csail.sdg.alloy4compiler.ast.CommandScope; +import edu.mit.csail.sdg.alloy4compiler.ast.Decl; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprBadJoin; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprITE; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprLet; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprBinary; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprList; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprConstant; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprQt; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprUnary; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; + +//===========================================================================// + +parser code {: + + public CompModule alloymodule=null; + + @Override public Symbol parse() throws java.lang.Exception { + int act; // current action code + Symbol lhs_sym = null; // the Symbol/stack element returned by a reduce + short handle_size, lhs_sym_num; // information about production being reduced with + boolean logging = "yes".equals(System.getProperty("debug")); + production_tab = production_table(); + action_tab = action_table(); + reduce_tab = reduce_table(); + init_actions(); + user_init(); + // start + cur_token = scan(); + stack.removeAllElements(); + stack.push(getSymbolFactory().startSymbol("START", 0, start_state())); + tos = 0; + for (_done_parsing = false; !_done_parsing; ) { + act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym); + if (act > 0) { // "shift"; thus, we shift to the encoded state by pushing it on the stack + if (logging) System.out.println("shift " + cur_token.sym); + cur_token.parse_state = act-1; + stack.push(cur_token); + tos++; + cur_token = scan(); + } else if (act<0) { // "reduce" + if (logging) System.out.println("reduce " + ((-act)-1)); + lhs_sym = do_action((-act)-1, this, stack, tos); + lhs_sym_num = production_tab[(-act)-1][0]; + handle_size = production_tab[(-act)-1][1]; + for (int i = 0; i < handle_size; i++) { stack.pop(); tos--; } + act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num); + lhs_sym.parse_state = act; + stack.push(lhs_sym); + tos++; + } else { // "error" + if (logging) System.out.println("error"); + syntax_error(cur_token); + done_parsing(); + } + } + return lhs_sym; + } + + public void syntax_error(Symbol x) throws Err { + Map ch = new LinkedHashMap(); + ch.put(CompSym.ARROW, "->"); + ch.put(CompSym.ANY_ARROW_SOME, "->"); + ch.put(CompSym.ANY_ARROW_ONE, "->"); + ch.put(CompSym.ANY_ARROW_LONE, "->"); + ch.put(CompSym.SOME_ARROW_ANY, "some"); + ch.put(CompSym.SOME_ARROW_SOME, "some"); + ch.put(CompSym.SOME_ARROW_ONE, "some"); + ch.put(CompSym.SOME_ARROW_LONE, "some"); + ch.put(CompSym.ONE_ARROW_ANY, "one"); + ch.put(CompSym.ONE_ARROW_SOME, "one"); + ch.put(CompSym.ONE_ARROW_ONE, "one"); + ch.put(CompSym.ONE_ARROW_LONE, "one"); + ch.put(CompSym.LONE_ARROW_ANY, "lone"); + ch.put(CompSym.LONE_ARROW_SOME, "lone"); + ch.put(CompSym.LONE_ARROW_ONE, "lone"); + ch.put(CompSym.LONE_ARROW_LONE, "lone"); + ch.put(CompSym.INTADD, "fun"); + ch.put(CompSym.INTSUB, "fun"); + ch.put(CompSym.INTMUL, "fun"); + ch.put(CompSym.INTDIV, "fun"); + ch.put(CompSym.INTREM, "fun"); + ch.put(CompSym.INTMIN, "fun"); + ch.put(CompSym.INTMAX, "fun"); + ch.put(CompSym.INTNEXT, "fun"); + ch.put(CompSym.TOTALORDER, "pred"); + ch.put(CompSym.ABSTRACT, "abstract"); + ch.put(CompSym.ALL, "all"); + ch.put(CompSym.ALL2, "all"); + ch.put(CompSym.AMPERSAND, "&"); + ch.put(CompSym.AND, "&&"); + ch.put(CompSym.AS, "as"); + ch.put(CompSym.ASSERT, "assert"); + ch.put(CompSym.AT, "@"); + ch.put(CompSym.BAR, "|"); + ch.put(CompSym.BUT, "but"); + ch.put(CompSym.CARET, "^"); + ch.put(CompSym.CHECK, "check"); + ch.put(CompSym.COLON, ":"); + ch.put(CompSym.COMMA, ", "); + ch.put(CompSym.DISJ, "disj"); + ch.put(CompSym.DOMAIN, "<:"); + ch.put(CompSym.DOT, "."); + ch.put(CompSym.ELSE, "else"); + ch.put(CompSym.ENUM, "enum"); + ch.put(CompSym.EQUALS, "="); + ch.put(CompSym.EXACTLY, "exactly"); + ch.put(CompSym.EXH, "exh"); + ch.put(CompSym.EXPECT, "expect"); + ch.put(CompSym.EXTENDS, "extends"); + ch.put(CompSym.FACT, "fact"); + ch.put(CompSym.FOR, "for"); + ch.put(CompSym.FUN, "fun"); + ch.put(CompSym.GT, ">"); + ch.put(CompSym.GTE, ">="); + ch.put(CompSym.HASH, "#"); + ch.put(CompSym.IDEN, "iden"); + ch.put(CompSym.IFF, "iff"); + ch.put(CompSym.IMPLIES, "=>"); + ch.put(CompSym.IN, "in"); + ch.put(CompSym.INT, "int"); + ch.put(CompSym.LBRACE, "{"); + ch.put(CompSym.LBRACKET, "["); + ch.put(CompSym.LET, "let"); + ch.put(CompSym.LONE2, "lone"); + ch.put(CompSym.LONE, "lone"); + ch.put(CompSym.LPAREN, "("); + ch.put(CompSym.LT, "<"); + ch.put(CompSym.LTE, "<="); + ch.put(CompSym.MINUS, "-"); + ch.put(CompSym.MODULE, "module"); + ch.put(CompSym.NO2, "no"); + ch.put(CompSym.NO, "no"); + ch.put(CompSym.NONE, "none"); + ch.put(CompSym.NOT, "!"); + ch.put(CompSym.NOTEQUALS, "!"); + ch.put(CompSym.NOTGT, "!"); + ch.put(CompSym.NOTGTE, "!"); + ch.put(CompSym.NOTIN, "!"); + ch.put(CompSym.NOTLT, "!"); + ch.put(CompSym.NOTLTE, "!"); + ch.put(CompSym.ONE2, "one"); + ch.put(CompSym.ONE, "one"); + ch.put(CompSym.OPEN, "open"); + ch.put(CompSym.OR, "||"); + ch.put(CompSym.PART, "part"); + ch.put(CompSym.PLUS, "+"); + ch.put(CompSym.PLUSPLUS, "++"); + ch.put(CompSym.PRED, "pred"); + ch.put(CompSym.PRIVATE, "private"); + ch.put(CompSym.RANGE, ":>"); + ch.put(CompSym.RBRACE, "}"); + ch.put(CompSym.RBRACKET, "]"); + ch.put(CompSym.RPAREN, ")"); + ch.put(CompSym.RUN, "run"); + ch.put(CompSym.SEQ, "seq"); + ch.put(CompSym.SET, "set"); + ch.put(CompSym.SHL, "<<"); + ch.put(CompSym.SHR, ">>>"); + ch.put(CompSym.SHA, ">>"); + ch.put(CompSym.SIG, "sig"); + ch.put(CompSym.SIGINT, "Int"); + ch.put(CompSym.SLASH, "/"); + ch.put(CompSym.SOME2, "some"); + ch.put(CompSym.SOME, "some"); + ch.put(CompSym.STAR, "*"); + ch.put(CompSym.STRING, "String"); + ch.put(CompSym.SUM2, "sum"); + ch.put(CompSym.SUM, "sum"); + ch.put(CompSym.THIS, "this"); + ch.put(CompSym.TILDE, "~"); + ch.put(CompSym.UNIV, "univ"); + ch.put(CompSym.ID, "NAME"); + ch.put(CompSym.NUMBER, "NUMBER"); + ch.put(CompSym.STR, "STRING"); + TreeSet list = new TreeSet(); + Pos p=Pos.UNKNOWN; + if (x!=null && x.value instanceof Pos) p=(Pos)(x.value); + else if (x!=null && x.value instanceof Expr) p=((Expr)(x.value)).pos; + else if (x!=null) p=x.pos; + if (!stack.empty()) for(Map.Entry e:ch.entrySet()) { + int key=e.getKey(), act=get_action(((Symbol)stack.peek()).parse_state, key); + if (act==0) continue; + try { + if (act>0 || alloy_confirm(key)) list.add(e.getValue()); + } catch(Throwable ex) { + // If the parser is really really confused, alloy_confirm() could fail with array out-of-bound exception, etc. + } + } + String result="There are "+list.size()+" possible tokens that can appear here:\n"; + for(String item:list) result=result+item+" "; + throw new ErrorSyntax(p, (list.size()!=0)?result:""); + } + + private boolean alloy_confirm(int key) { + int state = ((Symbol)stack.peek()).parse_state; + Stack newstack=new Stack(); for(Object x:stack) newstack.push(x); + while(true) { + int act = get_action(state, key); + if (act>0) return true; + if (act==0) return false; + int lhs_sym_num = production_tab[(-act)-1][0]; + int handle_size = production_tab[(-act)-1][1]; + for (int i = 0; i < handle_size; i++) { if (newstack.empty()) return false; newstack.pop(); } + if (newstack.empty()) return false; + if (newstack.peek() instanceof Symbol) state=((Symbol)newstack.peek()).parse_state; + state=get_reduce(state, lhs_sym_num); + newstack.push(null); + } + } + + static CompModule alloy_parseStream (List seenDollar, + Map loaded, Map fc, CompModule root, + int lineOffset, String filename, String prefix, int initialResolutionMode) throws Err, FileNotFoundException, IOException { + Reader isr=null; + try { + if (root==null && prefix.length()!=0) throw new ErrorFatal("Internal error (parse subfile with root==null)"); + if (root!=null && prefix.length()==0) throw new ErrorFatal("Internal error (parse topfile with root!=null)"); + CompModule u = new CompModule(root, filename, prefix); + if (root == null) + u.addOpen(null, null, ExprVar.make(null, "util/integer"), null, ExprVar.make(null, "integer")); + u.resolution = initialResolutionMode; + String content = fc!=null ? fc.get(filename) : null; + if (content==null && loaded!=null) content = loaded.get(filename); + if (content==null) content = Util.readAll(filename); + if (loaded!=null) loaded.put(filename,content); + content = Util.convertLineBreak(content); + isr = new StringReader(content); + CompFilter s = new CompFilter(u, seenDollar, filename, lineOffset, new BufferedReader(isr)); + CompParser p = new CompParser(s); + p.alloymodule=u; + try {p.parse();} catch(Throwable ex) {if (ex instanceof Err) throw (Err)ex; throw new ErrorFatal("Parser Exception", ex);} + // if no sigs are defined by the user, add one + if (root == null && u.getAllSigs().isEmpty()) { + u.addGhostSig(); + } + return u; + } finally { + Util.close(isr); + } + } + +:}; + +action code {: + /** This function is needed to handle a difficult parsing ambiguity. + * + *

+ * "some EXPR", "one EXPR", and "lone EXPR" + * can be either formulas (saying the EXPR has at least 1, exactly 1, or at most 1 tuple), + * or multiplicity constraints (saying something else has this multiplicity). + * + *

+ * So we let the parser generate the former by default. + * And whenever we construct a Decl "x: y" object, + * or an binary expression "x in y", or a function return type, + * we call this method on y to convert it into a multiplicity constraint. + * + *

+ * This is safe, because in all 3 cases, a formula would be illegal. + * So the first form is always wrong. + * + *

+ * And this is sufficient, because those are the only 3 places + * where a mulitplicity constraint is allowed to appear. + * + * @return a newly formed multiplciity constraint (if this.op==SOME or LONE or ONE), + * otherwise it just returns the original node. + */ + private Expr mult(Expr x) throws Err { + if (x instanceof ExprUnary) { + ExprUnary y=(ExprUnary)x; + if (y.op==ExprUnary.Op.SOME) return ExprUnary.Op.SOMEOF.make(y.pos, y.sub); + if (y.op==ExprUnary.Op.LONE) return ExprUnary.Op.LONEOF.make(y.pos, y.sub); + if (y.op==ExprUnary.Op.ONE) return ExprUnary.Op.ONEOF.make(y.pos, y.sub); + } + return x; + } + private void nod(ExprVar name) throws Err { + if (name.label.indexOf('$')>=0) throw new ErrorSyntax(name.pos, "The name cannot contain the '$' symbol."); + } + private void nod(List names) throws Err { + if (names!=null) for(ExprVar n:names) if (n!=null && n.label.indexOf('$')>=0) throw new ErrorSyntax(n.pos, "The name cannot contain the '$' symbol."); + } + private void c(boolean follow, ExprVar o, ExprVar x, ExprVar n, Expr e, List s, ExprConstant c) throws Err { + if (n!=null) nod(n); + int bitwidth=(-1), maxseq=(-1), overall=(-1), expects=(c==null ? -1 : c.num); + Pos p = o.pos.merge(n!=null ? n.span() : e.span()); + for(int i=s.size()-1; i>=0; i--) { + Sig j=s.get(i).sig; int k=s.get(i).startingScope; + p=p.merge(j.pos); + if (j.label.equals("univ")) { overall=k; s.remove(i); continue; } + if (j.label.equals("int")) { if (bitwidth>=0) throw new ErrorSyntax(j.pos, "The bitwidth cannot be specified more than once."); bitwidth=k; s.remove(i); continue; } + if (j.label.equals("seq")) { if (maxseq>=0) throw new ErrorSyntax(j.pos, "The maximum sequence length cannot be specified more than once."); maxseq=k; s.remove(i); continue; } + } + if (n!=null) + parser.alloymodule.addCommand(follow, p, n.label, o.label.equals("c"), overall, bitwidth, maxseq, expects, s, x); + else + parser.alloymodule.addCommand(follow, p, e, o.label.equals("c"), overall, bitwidth, maxseq, expects, s, x); + } + private Expr t(Pos pos, Pos oldClosing, Expr left, Expr right, Pos close) throws Err { + if (right instanceof ExprVar) { + String n = ((ExprVar)right).label; + if (n.equals("int")) return ExprUnary.Op.CAST2INT.make(pos, left); + if (n.equals("disj")) return ExprList.makeDISJOINT(pos, close, Util.asList(left)); + if (n.equals("pred/totalOrder")) return ExprList.makeTOTALORDER(pos, close, Util.asList(left)); + } + else if (right instanceof ExprList) { + return ((ExprList)right).addArg(left); + } + return ExprBadJoin.make(pos, oldClosing, left, right); + } +:}; + +//===========================================================================// + +terminal Pos ARROW; // -> +terminal Pos ANY_ARROW_SOME; // ->some // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos ANY_ARROW_ONE; // ->one // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos ANY_ARROW_LONE; // ->lone // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos SOME_ARROW_ANY; // some-> // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos SOME_ARROW_SOME; // some->some // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos SOME_ARROW_ONE; // some->one // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos SOME_ARROW_LONE; // some->lone // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos ONE_ARROW_ANY; // one-> // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos ONE_ARROW_SOME; // one->some // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos ONE_ARROW_ONE; // one->one // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos ONE_ARROW_LONE; // one->lone // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos LONE_ARROW_ANY; // lone->any // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos LONE_ARROW_SOME; // lone->some // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos LONE_ARROW_ONE; // lone->one // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos LONE_ARROW_LONE; // lone->lone // The filter allows whitespace/comment in these 15 "*->*" tokens + +terminal Pos INTADD; +terminal Pos INTSUB; +terminal Pos INTMUL; +terminal Pos INTDIV; +terminal Pos INTREM; +terminal Pos INTMIN; +terminal Pos INTMAX; +terminal Pos INTNEXT; +terminal Pos TOTALORDER; + +terminal Pos ABSTRACT; // abstract +terminal Pos ALL; // all // The filter enables us to disambiguate +terminal Pos ALL2; // all // The filter enables us to disambiguate +terminal Pos AMPERSAND; // & +terminal Pos AND; // && and +terminal Pos AS; // as +terminal Pos ASSERT; // assert +terminal Pos AT; // @ +terminal Pos BAR; // | +terminal Pos BUT; // but +terminal Pos CARET; // ^ +terminal Pos CHECK; // check +terminal Pos COLON; // : +terminal Pos COMMA; // , +terminal Pos DISJ; // disj disjoint +terminal Pos DOMAIN; // <: +terminal Pos DOT; // . +terminal Pos ELSE; // else +terminal Pos ENUM; // enum +terminal Pos EQUALS; // = == +terminal Pos EXACTLY; // exactly +terminal Pos EXH; // exh exhaustive +terminal Pos EXPECT; // expect +terminal Pos EXTENDS; // extends +terminal Pos FACT; // fact +terminal Pos FOR; // for +terminal Pos FUN; // fun +terminal Pos GT; // > +terminal Pos GTE; // >= +terminal Pos HASH; // # +terminal Pos IDEN; // iden +terminal Pos IFF; // <=> iff +terminal Pos IMPLIES; // => implies +terminal Pos IN; // in +terminal Pos INT; // int +terminal Pos LBRACE; // { +terminal Pos LBRACKET; // [ +terminal Pos LET; // let +terminal Pos LONE2; // lone // The filter enables us to disambiguate +terminal Pos LONE; // lone // The filter enables us to disambiguate +terminal Pos LPAREN; // ( +terminal Pos LT; // < +terminal Pos LTE; // <= =< +terminal Pos MINUS; // - +terminal Pos MODULE; // module +terminal Pos NO2; // no // The filter enables us to disambiguate +terminal Pos NO; // no // The filter enables us to disambiguate +terminal Pos NONE; // none +terminal Pos NOT; // ! not +terminal Pos NOTEQUALS; // != not= // The filter allows whitespace/comment in between +terminal Pos NOTGT; // !> not> // The filter allows whitespace/comment in between +terminal Pos NOTGTE; // !>= not>= // The filter allows whitespace/comment in between +terminal Pos NOTIN; // !in notin // The filter allows whitespace/comment in between +terminal Pos NOTLT; // !< not< // The filter allows whitespace/comment in between +terminal Pos NOTLTE; // !=< not=< // The filter allows whitespace/comment in between +terminal Pos ONE2; // one // The filter enables us to disambiguate +terminal Pos ONE; // one // The filter enables us to disambiguate +terminal Pos OPEN; // open +terminal Pos OR; // || or +terminal Pos PART; // part partition +terminal Pos PLUS; // + +terminal Pos PLUSPLUS; // ++ +terminal Pos PRED; // pred +terminal Pos PRIVATE; // private +terminal Pos RANGE; // :> +terminal Pos RBRACE; // } +terminal Pos RBRACKET; // ] +terminal Pos RPAREN; // ) +terminal Pos RUN; // run +terminal Pos SEQ; // seq +terminal Pos SET; // set +terminal Pos SHL; // << +terminal Pos SHR; // >>> +terminal Pos SHA; // >> +terminal Pos SIG; // sig +terminal Pos SIGINT; // Int +terminal Pos SLASH; // / +terminal Pos SOME2; // some // The filter enables us to disambiguate +terminal Pos SOME; // some // The filter enables us to disambiguate +terminal Pos STAR; // * +terminal Pos STRING; // String +terminal Pos SUM2; // sum // The filter enables us to disambiguate +terminal Pos SUM; // sum // The filter enables us to disambiguate +terminal Pos THIS; // this +terminal Pos TILDE; // ~ +terminal Pos UNIV; // univ + +terminal ExprVar ID; + +terminal ExprConstant NUMBER, STR; + +//===========================================================================// + +nonterminal Expr AndExprA; +nonterminal Expr AndExprB; +nonterminal Expr BaseExpr; +nonterminal Expr Bind; +nonterminal Expr BracketExprA; +nonterminal Expr BracketExprB; +nonterminal Expr CompareExprA; +nonterminal Expr CompareExprB; +nonterminal Command; +nonterminal ExprVar CommandPrefix; +nonterminal Decl Decla; +nonterminal Decl Declb; +nonterminal List Declp; +nonterminal List Decls; +nonterminal List Declz; +nonterminal Expr DomainExprA; +nonterminal Expr DomainExprB; +nonterminal Expr DotExprA; +nonterminal Expr DotExprB; +nonterminal Expr EquivExprA; +nonterminal Expr EquivExprB; +nonterminal ExprConstant Expects; +nonterminal Expr Expr; +nonterminal Expr Super; +nonterminal Expr SuperOpt; +nonterminal Expr SuperP; +nonterminal Expr SuperOrBar; +nonterminal List Exprs; +nonterminal List Exprp; +nonterminal Function; +nonterminal Expr ImpliesExprA; +nonterminal Expr ImpliesExprB; +nonterminal Expr ImpliesExprCloseA; +nonterminal Expr ImpliesExprCloseB; +nonterminal Expr ImpliesExprOpenA; +nonterminal Expr ImpliesExprOpenB; +nonterminal Expr IntersectExprA; +nonterminal Expr IntersectExprB; +nonterminal Expr Let; +nonterminal Macro; +nonterminal Expr MacroBody; +nonterminal ExprVar Name; +nonterminal ExprVar NameHelper; +nonterminal List Names; +nonterminal List Namex; +nonterminal Expr NegExprA; +nonterminal Expr NegExprB; +nonterminal Expr NumUnopExprA; +nonterminal Expr NumUnopExprB; +nonterminal Expr OrExprA; +nonterminal Expr OrExprB; +nonterminal Expr OverrideExprA; +nonterminal Expr OverrideExprB; +nonterminal Predicate; +nonterminal Expr RangeExprA; +nonterminal Expr RangeExprB; +nonterminal Pair RelOp; +nonterminal Expr RelationExprA; +nonterminal Expr RelationExprB; +nonterminal List Scope; +nonterminal Sig; +nonterminal List SigIn; +nonterminal List SigQual; +nonterminal List SigQuals; +nonterminal ExprVar SigRef; +nonterminal List SigRefp; +nonterminal List SigRefs; +nonterminal List SigRefu; +nonterminal File; +nonterminal Spec; +nonterminal CommandScope TypeNumber; +nonterminal CommandScope Typescope; +nonterminal List Typescopes; +nonterminal Expr ShiftExprA; +nonterminal Expr ShiftExprB; +nonterminal Expr MulExprA; +nonterminal Expr MulExprB; +nonterminal Expr UnionDiffExprA; +nonterminal Expr UnionDiffExprB; +nonterminal Expr UnopExprA; +nonterminal Expr UnopExprB; +nonterminal Pos Vis; + +//===========================================================================// + +File ::= Spec {: parser.alloymodule.doneParsing(); :}; + +Spec ::= Spec MODULE:o Name:n {: nod(n); parser.alloymodule.addModelName(o.merge(n.pos) , n.label , new ArrayList()); :}; +Spec ::= Spec MODULE:o Name:n LBRACKET Namex:b RBRACKET:r {: nod(n); nod(b); parser.alloymodule.addModelName(o.merge(r) , n.label , b ); :}; +Spec ::= Spec Vis:p OPEN:o Name:a {: nod(a); parser.alloymodule.addOpen(o.merge(a.pos), p, a, null, null); :}; +Spec ::= Spec Vis:p OPEN:o Name:a AS Name:c {: nod(a); nod(c); parser.alloymodule.addOpen(o.merge(c.pos), p, a, null, c); :}; +Spec ::= Spec Vis:p OPEN:o Name:a LBRACKET SigRefs:b RBRACKET:c {: nod(a); parser.alloymodule.addOpen(o.merge(c), p, a, b, null); :}; +Spec ::= Spec Vis:p OPEN:o Name:a LBRACKET SigRefs:b RBRACKET AS Name:c {: nod(a); nod(c); parser.alloymodule.addOpen(o.merge(c.pos), p, a, b, c); :}; +Spec ::= Spec Vis:p ENUM:o Name:a LBRACE Names:n RBRACE:c {: nod(a); parser.alloymodule.addEnum(o.merge(c), p, a, n, c); :}; +Spec ::= Spec Vis:p ENUM:o Name:a LBRACE RBRACE:c {: nod(a); parser.alloymodule.addEnum(o.merge(c), p, a, null, c); :}; +Spec ::= Spec FACT:o Super:e {: parser.alloymodule.addFact (o , "" , e); :}; +Spec ::= Spec FACT:o Name:n Super:e {: nod(n); parser.alloymodule.addFact (o , n.label , e); :}; +Spec ::= Spec FACT:o STR:n Super:e {: parser.alloymodule.addFact (o , n.string , e); :}; +Spec ::= Spec ASSERT:o Super:e {: parser.alloymodule.addAssertion (o , "" , e); :}; +Spec ::= Spec ASSERT:o Name:n Super:e {: nod(n); parser.alloymodule.addAssertion (o , n.label , e); :}; +Spec ::= Spec ASSERT:o STR:n Super:e {: parser.alloymodule.addAssertion (o , n.string , e); :}; +Spec ::= Spec Sig ; +Spec ::= Spec Function ; +Spec ::= Spec Predicate ; +Spec ::= Spec Macro ; +Spec ::= Spec Command ; +Spec ::= ; + +CommandPrefix ::= CHECK:c {: RESULT = ExprVar.make(c, "c"); :}; +CommandPrefix ::= RUN:r {: RESULT = ExprVar.make(r, "r"); :}; + +Command ::= CommandPrefix:o Name:x Super:e Scope:s Expects:c {: c(false,o,x ,null,e ,s,c); :}; +Command ::= CommandPrefix:o Super:e Scope:s Expects:c {: c(false,o,null,null,e ,s,c); :}; +Command ::= Command IMPLIES CommandPrefix:o Name:x Super:e Scope:s Expects:c {: c(true ,o,x ,null,e ,s,c); :}; +Command ::= Command IMPLIES CommandPrefix:o Super:e Scope:s Expects:c {: c(true ,o,null,null,e ,s,c); :}; +Command ::= CommandPrefix:o Name:x Name:n Scope:s Expects:c {: c(false,o,x ,n ,null,s,c); :}; +Command ::= CommandPrefix:o Name:n Scope:s Expects:c {: c(false,o,null,n ,null,s,c); :}; +Command ::= Command IMPLIES CommandPrefix:o Name:x Name:n Scope:s Expects:c {: c(true ,o,x ,n ,null,s,c); :}; +Command ::= Command IMPLIES CommandPrefix:o Name:n Scope:s Expects:c {: c(true ,o,null,n ,null,s,c); :}; + +Expects ::= {: RESULT=null; :}; +Expects ::= EXPECT NUMBER:a {: RESULT=a; :}; + +Scope ::= FOR NUMBER:a {: RESULT=new ArrayList(); RESULT.add(new CommandScope(a.pos, new PrimSig("univ", AttrType.WHERE.make(a.pos)), true, a.num, a.num, 1)); :}; +Scope ::= FOR NUMBER:a BUT Typescopes:b {: RESULT=b; b.add(new CommandScope(a.pos, new PrimSig("univ", AttrType.WHERE.make(a.pos)), true, a.num, a.num, 1)); :}; +Scope ::= FOR Typescopes:b {: RESULT=b; :}; +Scope ::= {: RESULT=new ArrayList(); :}; + +Typescopes ::= Typescope:a {: RESULT=new ArrayList(); RESULT.add(a); :}; +Typescopes ::= Typescopes:a COMMA Typescope:b {: RESULT=a; a.add(b); :}; + +Typescope ::= TypeNumber:a Name:b {: + nod(b); + RESULT = new CommandScope(a.pos.merge(b.pos), new PrimSig(b.label, AttrType.WHERE.make(a.pos.merge(b.pos))), a.isExact, a.startingScope, a.endingScope, a.increment); +:}; + +//[AM]: INT -> SIGINT +Typescope ::= TypeNumber:a SIGINT:b {: + Pos p = a.pos.merge(b); + if (a.endingScope>a.startingScope) throw new ErrorSyntax(p, "Cannot specify a growing scope for \"Int\""); + if (a.isExact) throw new ErrorSyntax(p, "The exactly keyword is redundant here since the integer bitwidth must be exact."); + RESULT = new CommandScope(p, new PrimSig("int", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.startingScope, 1); +:}; + +Typescope ::= TypeNumber:a INT:b {: + Pos p = a.pos.merge(b); + if (a.endingScope>a.startingScope) throw new ErrorSyntax(p, "Cannot specify a growing scope for \"Int\""); + if (a.isExact) throw new ErrorSyntax(p, "The exactly keyword is redundant here since the integer bitwidth must be exact."); + RESULT = new CommandScope(p, new PrimSig("int", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.startingScope, 1); +:}; + +Typescope ::= TypeNumber:a SEQ:b {: + Pos p = a.pos.merge(b); + if (a.endingScope>a.startingScope) throw new ErrorSyntax(p, "Cannot specify a growing scope for \"seq\""); + if (a.isExact) throw new ErrorSyntax(p, "The exactly keyword is redundant here since the number of sequence index has to be exact."); + RESULT = new CommandScope(p, new PrimSig("seq", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.startingScope, 1); +:}; + +Typescope ::= TypeNumber:e UNIV:f {: if (1==1) throw new ErrorSyntax(e.pos.merge(f), "You cannot set a scope on univ."); :}; + +Typescope ::= TypeNumber:a STRING:b {: RESULT = new CommandScope(a.pos.merge(b), new PrimSig("String", AttrType.WHERE.make(a.pos.merge(b))), a.isExact, a.startingScope, a.endingScope, a.increment); :}; + +//[AM] Typescope ::= TypeNumber:e SIGINT:f {: if (1==1) throw new ErrorSyntax(e.pos.merge(f), "You can no longer set a scope on Int; the number of Int atoms is always exactly equal to 2^(integer bitwidth).\n"); :}; + +Typescope ::= TypeNumber:e NONE:f {: if (1==1) throw new ErrorSyntax(e.pos.merge(f), "You cannot set a scope on none."); :}; + +TypeNumber ::= EXACTLY:e NUMBER:a {: RESULT = new CommandScope( e.merge(a.pos), Sig.NONE, true, a.num, a.num, 1 ); :}; +TypeNumber ::= EXACTLY:e NUMBER:a DOT DOT NUMBER:b {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e.merge(b.pos), Sig.NONE, true, a.num, b.num, 1 ); :}; +TypeNumber ::= EXACTLY:e NUMBER:a DOT DOT NUMBER:b COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e.merge(i.pos), Sig.NONE, true, a.num, b.num, i.num); :}; +TypeNumber ::= EXACTLY:e NUMBER:a COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e.merge(i.pos), Sig.NONE, true, a.num, Integer.MAX_VALUE, i.num); :}; +TypeNumber ::= NUMBER:a {: RESULT = new CommandScope(a.pos , Sig.NONE, false, a.num, a.num, 1 ); :}; +TypeNumber ::= NUMBER:a DOT DOT NUMBER:b {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos.merge(b.pos), Sig.NONE, false, a.num, b.num, 1 ); :}; +TypeNumber ::= NUMBER:a DOT DOT NUMBER:b COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos.merge(i.pos), Sig.NONE, false, a.num, b.num, i.num); :}; +TypeNumber ::= NUMBER:a COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos.merge(i.pos), Sig.NONE, false, a.num, Integer.MAX_VALUE, i.num); :}; + +Macro ::= Vis:p LET:o Name:n LPAREN Names:d RPAREN MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, d , v); :}; +Macro ::= Vis:p LET:o Name:n LPAREN RPAREN MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, null , v); :}; +Macro ::= Vis:p LET:o Name:n LBRACKET Names:d RBRACKET MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, d , v); :}; +Macro ::= Vis:p LET:o Name:n LBRACKET RBRACKET MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, null , v); :}; +Macro ::= Vis:p LET:o Name:n MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, null , v); :}; + +MacroBody ::= Super:a {: RESULT=a; :}; +MacroBody ::= EQUALS Expr:a {: RESULT=a; :}; + +Function ::= Vis:p FUN:o Name:n LPAREN Decls:d RPAREN COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, d , mult(r), v); :}; +Function ::= Vis:p FUN:o Name:n LBRACKET Decls:d RBRACKET COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, d , mult(r), v); :}; +Function ::= Vis:p FUN:o Name:n COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, null , mult(r), v); :}; +Function ::= Vis:p FUN:o SigRef:f DOT Name:n LPAREN Decls:d RPAREN COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , d , mult(r), v); :}; +Function ::= Vis:p FUN:o SigRef:f DOT Name:n LBRACKET Decls:d RBRACKET COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , d , mult(r), v); :}; +Function ::= Vis:p FUN:o SigRef:f DOT Name:n COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , null , mult(r), v); :}; + +Predicate ::= Vis:p PRED:o Name:n LPAREN Decls:d RPAREN Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, d , null, v); :}; +Predicate ::= Vis:p PRED:o Name:n LBRACKET Decls:d RBRACKET Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, d , null, v); :}; +Predicate ::= Vis:p PRED:o Name:n Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, null , null, v); :}; +Predicate ::= Vis:p PRED:o SigRef:f DOT Name:n LPAREN Decls:d RPAREN Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , d , null, v); :}; +Predicate ::= Vis:p PRED:o SigRef:f DOT Name:n LBRACKET Decls:d RBRACKET Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , d , null, v); :}; +Predicate ::= Vis:p PRED:o SigRef:f DOT Name:n Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , null , null, v); :}; + +Vis ::= {: RESULT=null; :}; +Vis ::= PRIVATE:p {: RESULT=p; :}; + +Sig ::= SigQuals:a Names:b SigIn:c LBRACE Decls:d RBRACE:o SuperOpt:e + {: + if (e==null) e = ExprConstant.Op.TRUE.make(o, 0); + ExprVar cc = (c!=null && c.size()>0) ? c.remove(c.size()-1) : null; + for(ExprVar bb:b) { + parser.alloymodule.addSig(bb.label, cc, c, d, e, + AttrType.WHERE .makenull(bb.pos.merge(e==null ? o : e.span())), + AttrType.ABSTRACT.makenull(a.get(0)), + AttrType.LONE .makenull(a.get(1)), + AttrType.ONE .makenull(a.get(2)), + AttrType.SOME .makenull(a.get(3)), + AttrType.PRIVATE .makenull(a.get(4))); + } + :}; + +SigQual ::= ABSTRACT:x {: RESULT=new ArrayList(5); RESULT.add(x); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); :}; +SigQual ::= LONE:x {: RESULT=new ArrayList(5); RESULT.add(null); RESULT.add(x); RESULT.add(null); RESULT.add(null); RESULT.add(null); :}; +SigQual ::= ONE:x {: RESULT=new ArrayList(5); RESULT.add(null); RESULT.add(null); RESULT.add(x); RESULT.add(null); RESULT.add(null); :}; +SigQual ::= SOME:x {: RESULT=new ArrayList(5); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(x); RESULT.add(null); :}; +SigQual ::= PRIVATE:x {: RESULT=new ArrayList(5); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(x); :}; + +SigQuals ::= SIG {: RESULT=new ArrayList(5); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); :}; +SigQuals ::= SigQual:a SigQuals:b {: RESULT=a; for(int i=0;i<5;i++) if (a.get(i)==null) a.set(i,b.get(i)); else if (b.get(i)!=null) throw new ErrorSyntax(b.get(i), "The same qualifer cannot be specified more than once for the same sig."); :}; + +SigIn ::= EXTENDS:a SigRef:x {: RESULT=new ArrayList(2); RESULT.add(x); RESULT.add(ExprVar.make(a, "extends")); :}; +SigIn ::= IN:a SigRefu:x {: RESULT=x; x.add(ExprVar.make(a,"in")); :}; +SigIn ::= EQUALS:a SigRefu:x {: RESULT=x; x.add(ExprVar.make(a,"=")); :}; +SigIn ::= {: RESULT=null; :}; + +SigRef ::= Name:x {: RESULT=x; :}; +SigRef ::= UNIV:x {: RESULT=ExprVar.make(x, "univ"); :}; +SigRef ::= STRING:x {: RESULT=ExprVar.make(x, "String"); :}; +SigRef ::= SIGINT:x {: RESULT=ExprVar.make(x, "Int"); :}; +SigRef ::= SEQ:a SLASH SIGINT:b {: RESULT=ExprVar.make(a.merge(b), "seq/Int"); :}; +SigRef ::= NONE:x {: RESULT=ExprVar.make(x, "none"); :}; + +SigRefs ::= {: RESULT=new ArrayList(); :}; +SigRefs ::= SigRefp:x {: RESULT=x; :}; + +SigRefp ::= SigRef:x {: RESULT=new ArrayList(); RESULT.add(x); :}; +SigRefp ::= SigRefp:a COMMA SigRef:b {: a.add(b); RESULT=a; :}; + +SigRefu ::= SigRef:x {: RESULT=new ArrayList(); RESULT.add(x); :}; +SigRefu ::= SigRefu:a PLUS SigRef:b {: a.add(b); RESULT=a; :}; + +Name ::= NameHelper:x {: RESULT=x; :}; +Name ::= THIS:a SLASH NameHelper:b {: RESULT=ExprVar.make(a.merge(b.pos), "this/"+b.label); :}; +Name ::= SEQ:a SLASH NameHelper:b {: RESULT=ExprVar.make(a.merge(b.pos), "seq/"+b.label); :}; + +NameHelper ::= ID:x {: RESULT=x; :}; +NameHelper ::= NameHelper:a SLASH ID:b {: RESULT=ExprVar.make(a.pos.merge(b.pos), a.label+"/"+b.label); :}; + +Names ::= Name:x {: nod(x); RESULT=new ArrayList(); RESULT.add(x); :}; +Names ::= Names:a COMMA Name:b {: nod(b); a.add(b); RESULT=a; :}; + +Namex ::= Name:x {: nod(x); RESULT=new ArrayList(); RESULT.add(x); :}; +Namex ::= EXACTLY Name:x {: nod(x); RESULT=new ArrayList(); RESULT.add(null); RESULT.add(x); :}; +Namex ::= Namex:a COMMA Name:b {: nod(b); a.add(b); RESULT=a; :}; +Namex ::= Namex:a COMMA EXACTLY Name:b {: nod(b); a.add(null); a.add(b); RESULT=a; :}; + +Decla ::= PART:k Names COLON Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; +Decla ::= EXH:k Names COLON Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; +Decla ::= DISJ:k Names:a COLON Expr:b {: RESULT=new Decl(null, k, null, a, mult(b)); :}; +Decla ::= PRIVATE:p DISJ:k Names:a COLON Expr:b {: RESULT=new Decl(p, k, null, a, mult(b)); :}; +Decla ::= PRIVATE:p Names:a COLON Expr:b {: RESULT=new Decl(p, null, null, a, mult(b)); :}; +Decla ::= Names:a COLON Expr:b {: RESULT=new Decl(null, null, null, a, mult(b)); :}; + +Decla ::= PART:k Names COLON DISJ Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; +Decla ::= EXH:k Names COLON DISJ Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; +Decla ::= DISJ:k Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(null, k, d, a, mult(b)); :}; +Decla ::= PRIVATE:p DISJ:k Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(p, k, d, a, mult(b)); :}; +Decla ::= PRIVATE:p Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(p, null, d, a, mult(b)); :}; +Decla ::= Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(null, null, d, a, mult(b)); :}; + +Declb ::= Decla:x {: RESULT=x; :}; + +Declb ::= PART:k Names EQUALS Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; +Declb ::= EXH:k Names EQUALS Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; +Declb ::= DISJ:d Names EQUALS Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; +Declb ::= PRIVATE DISJ:d Names EQUALS Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; +Declb ::= PRIVATE:p Names:a EQUALS Expr:b {: RESULT=new Decl(p, null, null, a, ExprUnary.Op.EXACTLYOF.make(null, b)); :}; +Declb ::= Names:a EQUALS Expr:b {: RESULT=new Decl(null, null, null, a, ExprUnary.Op.EXACTLYOF.make(null, b)); :}; + +Declb ::= PART:k Names EQUALS DISJ Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; +Declb ::= EXH:k Names EQUALS DISJ Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; +Declb ::= DISJ Names EQUALS DISJ:d Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; +Declb ::= PRIVATE DISJ Names EQUALS DISJ:d Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; +Declb ::= PRIVATE Names EQUALS DISJ:d Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; +Declb ::= Names EQUALS DISJ:d Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; + +Declz ::= Declz:x COMMA Decla:y {: RESULT=x; RESULT.add(y); :}; +Declz ::= Decla:y {: RESULT=new ArrayList(); RESULT.add(y); :}; + +Declp ::= Declp:x COMMA Declb:y {: RESULT=x; RESULT.add(y); :}; +Declp ::= Declb:y {: RESULT=new ArrayList(); RESULT.add(y); :}; + +Decls ::= {: RESULT=new ArrayList(); :}; +Decls ::= Declb:x {: RESULT=new ArrayList(); RESULT.add(x); :}; +Decls ::= Declb:x COMMA Decls:y {: RESULT=y; RESULT.add(0,x); :}; +Decls ::= COMMA Decls:y {: RESULT=y; :}; + +Let ::= Name:a EQUALS:o Expr:b SuperOrBar:x {: + nod(a); + if (a.label.indexOf('/')>=0) throw new ErrorSyntax(a.pos, "Let variable name cannot contain \'/\'"); + if (a.label.indexOf('@')>=0) throw new ErrorSyntax(a.pos, "Let variable name cannot contain \'@\'"); + RESULT = ExprLet.make(o, ExprVar.make(a.pos, a.label), b, x); +:}; + +Let ::= Name:a EQUALS:o Expr:b COMMA Let:x {: + nod(a); + if (a.label.indexOf('/')>=0) throw new ErrorSyntax(a.pos, "Let variable name cannot contain \'/\'"); + if (a.label.indexOf('@')>=0) throw new ErrorSyntax(a.pos, "Let variable name cannot contain \'@\'"); + RESULT = ExprLet.make(o, ExprVar.make(a.pos, a.label), b, x); +:}; + +SuperOpt ::= {: RESULT=null; :}; +SuperOpt ::= Super:x {: RESULT=x; :}; +Super ::= LBRACE:a SuperP:x RBRACE:b {: RESULT=ExprUnary.Op.NOOP.make(a.merge(b), x); :}; +Super ::= LBRACE:a RBRACE:b {: RESULT=ExprConstant.Op.TRUE.make(a.merge(b), 0); :}; +SuperP ::= Expr:a {: RESULT=a; :}; +SuperP ::= SuperP:a Expr:b {: RESULT=ExprBinary.Op.AND.make(null, null, a, b); :}; + +SuperOrBar ::= BAR Expr:x {: RESULT=x; :}; +SuperOrBar ::= Super:x {: RESULT=x; :}; + +Exprs ::= {: RESULT=new ArrayList(); :}; +Exprs ::= Exprp:x {: RESULT=x; :}; +Exprp ::= Expr:x {: RESULT=new ArrayList(); RESULT.add(x); :}; +Exprp ::= Exprp:a COMMA Expr:b {: a.add(b); RESULT=a; :}; + +//============================================================================= + +Expr ::= OrExprA:x {: RESULT = x; :}; +Expr ::= OrExprB:x {: RESULT = x; :}; +Expr ::= Bind:x {: RESULT = x; :}; +Bind ::= LET Let:x {: RESULT = x; :}; +Bind ::= ALL2:o Declp:a SuperOrBar:b {: RESULT = ExprQt.Op.ALL .make(o, null, a, b); :}; +Bind ::= NO2:o Declp:a SuperOrBar:b {: RESULT = ExprQt.Op.NO .make(o, null, a, b); :}; +Bind ::= SOME2:o Declp:a SuperOrBar:b {: RESULT = ExprQt.Op.SOME.make(o, null, a, b); :}; +Bind ::= LONE2:o Declp:a SuperOrBar:b {: RESULT = ExprQt.Op.LONE.make(o, null, a, b); :}; +Bind ::= ONE2:o Declp:a SuperOrBar:b {: RESULT = ExprQt.Op.ONE .make(o, null, a, b); :}; +Bind ::= SUM2:o Declp:a SuperOrBar:b {: RESULT = ExprQt.Op.SUM .make(o, null, a, b); :}; + +OrExprA ::= EquivExprA:a {: RESULT=a; :}; +OrExprA ::= OrExprB:a OR:o Bind:b {: RESULT=ExprBinary.Op.OR.make(o, null, a, b); :}; +OrExprB ::= EquivExprB:b {: RESULT=b; :}; +OrExprB ::= OrExprB:a OR:o EquivExprB:b {: RESULT=ExprBinary.Op.OR.make(o, null, a, b); :}; + +EquivExprA ::= ImpliesExprA:b {: RESULT=b; :}; +EquivExprA ::= EquivExprB:a IFF:o Bind:b {: RESULT=ExprBinary.Op.IFF.make(o, null, a, b); :}; +EquivExprB ::= ImpliesExprB:b {: RESULT=b; :}; +EquivExprB ::= EquivExprB:a IFF:o ImpliesExprB:b {: RESULT=ExprBinary.Op.IFF.make(o, null, a, b); :}; + +ImpliesExprA ::= ImpliesExprCloseA:a {: RESULT=a; :}; +ImpliesExprA ::= ImpliesExprOpenA:a {: RESULT=a; :}; +ImpliesExprCloseA ::= AndExprA:a {: RESULT=a; :}; +ImpliesExprCloseA ::= AndExprB:a IMPLIES:o ImpliesExprCloseB:b ELSE ImpliesExprCloseA:c {: RESULT = ExprITE.make(o,a,b,c); :}; +ImpliesExprOpenA ::= AndExprB:a IMPLIES:o ImpliesExprCloseB:b ELSE ImpliesExprOpenA:c {: RESULT = ExprITE.make(o,a,b,c); :}; +ImpliesExprOpenA ::= AndExprB:a IMPLIES:o ImpliesExprA:b {: RESULT = ExprBinary.Op.IMPLIES.make(o, null, a, b); :}; + +ImpliesExprCloseA ::= AndExprB:a IMPLIES:o ImpliesExprCloseB:b ELSE Bind:c {: RESULT = ExprITE.make(o,a,b,c); :}; +ImpliesExprOpenA ::= AndExprB:a IMPLIES:o Bind:b {: RESULT = ExprBinary.Op.IMPLIES.make(o, null, a, b); :}; + +ImpliesExprB ::= ImpliesExprCloseB:a {: RESULT=a; :}; +ImpliesExprB ::= ImpliesExprOpenB:a {: RESULT=a; :}; +ImpliesExprCloseB ::= AndExprB:a {: RESULT=a; :}; +ImpliesExprCloseB ::= AndExprB:a IMPLIES:o ImpliesExprCloseB:b ELSE ImpliesExprCloseB:c {: RESULT = ExprITE.make(o,a,b,c); :}; +ImpliesExprOpenB ::= AndExprB:a IMPLIES:o ImpliesExprCloseB:b ELSE ImpliesExprOpenB:c {: RESULT = ExprITE.make(o,a,b,c); :}; +ImpliesExprOpenB ::= AndExprB:a IMPLIES:o ImpliesExprB:b {: RESULT = ExprBinary.Op.IMPLIES.make(o, null, a, b); :}; + +AndExprA ::= NegExprA:a {: RESULT=a; :}; +AndExprA ::= AndExprB:a AND:o Bind:b {: RESULT=ExprBinary.Op.AND.make(o, null, a, b); :}; +AndExprB ::= NegExprB:b {: RESULT=b; :}; +AndExprB ::= AndExprB:a AND:o NegExprB:b {: RESULT=ExprBinary.Op.AND.make(o, null, a, b); :}; + +NegExprA ::= CompareExprA:b {: RESULT=b; :}; +NegExprA ::= NOT:o Bind:b {: RESULT=ExprUnary.Op.NOT.make(o, b); :}; +NegExprA ::= NOT:o NegExprA:b {: RESULT=ExprUnary.Op.NOT.make(o, b); :}; +NegExprB ::= CompareExprB:b {: RESULT=b; :}; +NegExprB ::= NOT:o NegExprB:b {: RESULT=ExprUnary.Op.NOT.make(o, b); :}; + +CompareExprA ::= CompareExprB:a IN:o ShiftExprA:b {: RESULT=ExprBinary.Op.IN .make(o, null, a, mult(b)); :}; +CompareExprA ::= CompareExprB:a EQUALS:o ShiftExprA:b {: RESULT=ExprBinary.Op.EQUALS .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a LT:o ShiftExprA:b {: RESULT=ExprBinary.Op.LT .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a GT:o ShiftExprA:b {: RESULT=ExprBinary.Op.GT .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a LTE:o ShiftExprA:b {: RESULT=ExprBinary.Op.LTE .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a GTE:o ShiftExprA:b {: RESULT=ExprBinary.Op.GTE .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a NOTIN:o ShiftExprA:b {: RESULT=ExprBinary.Op.NOT_IN .make(o, null, a, mult(b)); :}; +CompareExprA ::= CompareExprB:a NOTEQUALS:o ShiftExprA:b {: RESULT=ExprBinary.Op.NOT_EQUALS.make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a NOTLT:o ShiftExprA:b {: RESULT=ExprBinary.Op.NOT_LT .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a NOTGT:o ShiftExprA:b {: RESULT=ExprBinary.Op.NOT_GT .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a NOTLTE:o ShiftExprA:b {: RESULT=ExprBinary.Op.NOT_LTE .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a NOTGTE:o ShiftExprA:b {: RESULT=ExprBinary.Op.NOT_GTE .make(o, null, a, b); :}; +CompareExprA ::= ALL:o ShiftExprA {: if (1==1) throw new ErrorSyntax(o,"The \"all x\" construct is no longer supported. If you know the range of possible values of x, consider rewriting it as \"x == set_of_all_possible_values\"."); :}; +CompareExprA ::= NO:o ShiftExprA:b {: RESULT=ExprUnary.Op.NO .make(o, b); :}; +CompareExprA ::= SOME:o ShiftExprA:b {: RESULT=ExprUnary.Op.SOME .make(o, b); :}; +CompareExprA ::= LONE:o ShiftExprA:b {: RESULT=ExprUnary.Op.LONE .make(o, b); :}; +CompareExprA ::= ONE:o ShiftExprA:b {: RESULT=ExprUnary.Op.ONE .make(o, b); :}; +CompareExprA ::= SET:o ShiftExprA:b {: RESULT=ExprUnary.Op.SETOF.make(o, b); :}; +CompareExprA ::= SEQ:o ShiftExprA:b {: RESULT=ExprBinary.Op.ISSEQ_ARROW_LONE.make(o, null, ExprVar.make(o, "seq/Int"), b); parser.alloymodule.addSeq(o); :}; +CompareExprA ::= ShiftExprA:b {: RESULT=b; :}; + +CompareExprB ::= CompareExprB:a IN:o ShiftExprB:b {: RESULT=ExprBinary.Op.IN .make(o, null, a, mult(b)); :}; +CompareExprB ::= CompareExprB:a EQUALS:o ShiftExprB:b {: RESULT=ExprBinary.Op.EQUALS .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a LT:o ShiftExprB:b {: RESULT=ExprBinary.Op.LT .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a GT:o ShiftExprB:b {: RESULT=ExprBinary.Op.GT .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a LTE:o ShiftExprB:b {: RESULT=ExprBinary.Op.LTE .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a GTE:o ShiftExprB:b {: RESULT=ExprBinary.Op.GTE .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a NOTIN:o ShiftExprB:b {: RESULT=ExprBinary.Op.NOT_IN .make(o, null, a, mult(b)); :}; +CompareExprB ::= CompareExprB:a NOTEQUALS:o ShiftExprB:b {: RESULT=ExprBinary.Op.NOT_EQUALS.make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a NOTLT:o ShiftExprB:b {: RESULT=ExprBinary.Op.NOT_LT .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a NOTGT:o ShiftExprB:b {: RESULT=ExprBinary.Op.NOT_GT .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a NOTLTE:o ShiftExprB:b {: RESULT=ExprBinary.Op.NOT_LTE .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a NOTGTE:o ShiftExprB:b {: RESULT=ExprBinary.Op.NOT_GTE .make(o, null, a, b); :}; +CompareExprB ::= ALL:o ShiftExprB {: if (1==1) throw new ErrorSyntax(o,"The \"all x\" construct is no longer supported. If you know the range of possible values of x, consider rewriting it as \"x == set_of_all_possible_values\"."); :}; +CompareExprB ::= NO:o ShiftExprB:b {: RESULT=ExprUnary.Op.NO .make(o, b); :}; +CompareExprB ::= SOME:o ShiftExprB:b {: RESULT=ExprUnary.Op.SOME .make(o, b); :}; +CompareExprB ::= LONE:o ShiftExprB:b {: RESULT=ExprUnary.Op.LONE .make(o, b); :}; +CompareExprB ::= ONE:o ShiftExprB:b {: RESULT=ExprUnary.Op.ONE .make(o, b); :}; +CompareExprB ::= SET:o ShiftExprB:b {: RESULT=ExprUnary.Op.SETOF.make(o, b); :}; +CompareExprB ::= SEQ:o ShiftExprB:b {: RESULT=ExprBinary.Op.ISSEQ_ARROW_LONE.make(o, null, ExprVar.make(o,"seq/Int"), b); parser.alloymodule.addSeq(o); :}; +CompareExprB ::= ShiftExprB:b {: RESULT=b; :}; + +ShiftExprA ::= UnionDiffExprA:b {: RESULT=b; :}; +ShiftExprA ::= ShiftExprB:a SHL:o Bind:b {: RESULT=ExprBinary.Op.SHL.make(o, null, a, b); :}; +ShiftExprA ::= ShiftExprB:a SHR:o Bind:b {: RESULT=ExprBinary.Op.SHR.make(o, null, a, b); :}; +ShiftExprA ::= ShiftExprB:a SHA:o Bind:b {: RESULT=ExprBinary.Op.SHA.make(o, null, a, b); :}; +ShiftExprB ::= UnionDiffExprB:b {: RESULT=b; :}; +ShiftExprB ::= ShiftExprB:a SHL:o UnionDiffExprB:b {: RESULT=ExprBinary.Op.SHL.make(o, null, a, b); :}; +ShiftExprB ::= ShiftExprB:a SHR:o UnionDiffExprB:b {: RESULT=ExprBinary.Op.SHR.make(o, null, a, b); :}; +ShiftExprB ::= ShiftExprB:a SHA:o UnionDiffExprB:b {: RESULT=ExprBinary.Op.SHA.make(o, null, a, b); :}; + +UnionDiffExprA ::= MulExprA:b {: RESULT=b; :}; +UnionDiffExprA ::= UnionDiffExprB:a PLUS:o Bind:b {: RESULT=ExprBinary.Op.PLUS .make(o, null, a, b); :}; +UnionDiffExprA ::= UnionDiffExprB:a MINUS:o Bind:b {: RESULT=ExprBinary.Op.MINUS.make(o, null, a, b); :}; +UnionDiffExprA ::= UnionDiffExprB:a INTADD:o Bind:b {: RESULT=ExprBinary.Op.IPLUS.make(o, null, a, b); :}; +UnionDiffExprA ::= UnionDiffExprB:a INTSUB:o Bind:b {: RESULT=ExprBinary.Op.IMINUS.make(o, null, a, b); :}; +UnionDiffExprB ::= MulExprB:b {: RESULT=b; :}; +UnionDiffExprB ::= UnionDiffExprB:a PLUS:o MulExprB:b {: RESULT=ExprBinary.Op.PLUS .make(o, null, a, b); :}; +UnionDiffExprB ::= UnionDiffExprB:a MINUS:o MulExprB:b {: RESULT=ExprBinary.Op.MINUS.make(o, null, a, b); :}; +UnionDiffExprB ::= UnionDiffExprB:a INTADD:o MulExprB:b {: RESULT=ExprBinary.Op.IPLUS.make(o, null, a, b); :}; +UnionDiffExprB ::= UnionDiffExprB:a INTSUB:o MulExprB:b {: RESULT=ExprBinary.Op.IMINUS.make(o, null, a, b); :}; + +MulExprA ::= NumUnopExprA:b {: RESULT=b; :}; +MulExprA ::= MulExprB:a INTMUL:o Bind:b {: RESULT=ExprBinary.Op.MUL .make(o, null, a, b); :}; +MulExprA ::= MulExprB:a INTDIV:o Bind:b {: RESULT=ExprBinary.Op.DIV .make(o, null, a, b); :}; +MulExprA ::= MulExprB:a INTREM:o Bind:b {: RESULT=ExprBinary.Op.REM .make(o, null, a, b); :}; +MulExprB ::= NumUnopExprB:b {: RESULT=b; :}; +MulExprB ::= MulExprB:a INTMUL:o NumUnopExprB:b {: RESULT=ExprBinary.Op.MUL .make(o, null, a, b); :}; +MulExprB ::= MulExprB:a INTDIV:o NumUnopExprB:b {: RESULT=ExprBinary.Op.DIV .make(o, null, a, b); :}; +MulExprB ::= MulExprB:a INTREM:o NumUnopExprB:b {: RESULT=ExprBinary.Op.REM .make(o, null, a, b); :}; + +NumUnopExprA ::= OverrideExprA:b {: RESULT=b; :}; +NumUnopExprA ::= HASH:o Bind:b {: RESULT=ExprUnary.Op.CARDINALITY.make(o, b); :}; +NumUnopExprA ::= SUM:o Bind:b {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); :}; +//[AM]: INT->SIGINT +NumUnopExprA ::= INT:o Bind:b {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); :}; +NumUnopExprA ::= HASH:o NumUnopExprA:b {: RESULT=ExprUnary.Op.CARDINALITY.make(o, b); :}; +NumUnopExprA ::= SUM:o NumUnopExprA:b {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); :}; +//[AM]: INT->SIGINT +NumUnopExprA ::= INT:o NumUnopExprA:b {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); :}; +NumUnopExprB ::= OverrideExprB:b {: RESULT=b; :}; +NumUnopExprB ::= HASH:o NumUnopExprB:b {: RESULT=ExprUnary.Op.CARDINALITY.make(o, b); :}; +NumUnopExprB ::= SUM:o NumUnopExprB:b {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); :}; +//[AM]: INT->SIGINT +NumUnopExprB ::= INT:o NumUnopExprB:b {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); :}; + +OverrideExprA ::= IntersectExprA:b {: RESULT=b; :}; +OverrideExprA ::= OverrideExprB:a PLUSPLUS:o Bind:b {: RESULT=ExprBinary.Op.PLUSPLUS.make(o, null, a, b); :}; +OverrideExprB ::= IntersectExprB:b {: RESULT=b; :}; +OverrideExprB ::= OverrideExprB:a PLUSPLUS:o IntersectExprB:b {: RESULT=ExprBinary.Op.PLUSPLUS.make(o, null, a, b); :}; + +IntersectExprA ::= RelationExprA:b {: RESULT=b; :}; +IntersectExprA ::= IntersectExprB:a AMPERSAND:o Bind:b {: RESULT=ExprBinary.Op.INTERSECT.make(o, null, a, b); :}; +IntersectExprB ::= RelationExprB:b {: RESULT=b; :}; +IntersectExprB ::= IntersectExprB:a AMPERSAND:o RelationExprB:b {: RESULT=ExprBinary.Op.INTERSECT.make(o, null, a, b); :}; + +RelOp ::= ARROW:o {: RESULT=new Pair(o, ExprBinary.Op.ARROW ); :}; +RelOp ::= ANY_ARROW_SOME:o {: RESULT=new Pair(o, ExprBinary.Op.ANY_ARROW_SOME ); :}; +RelOp ::= ANY_ARROW_ONE:o {: RESULT=new Pair(o, ExprBinary.Op.ANY_ARROW_ONE ); :}; +RelOp ::= ANY_ARROW_LONE:o {: RESULT=new Pair(o, ExprBinary.Op.ANY_ARROW_LONE ); :}; +RelOp ::= SOME_ARROW_ANY:o {: RESULT=new Pair(o, ExprBinary.Op.SOME_ARROW_ANY ); :}; +RelOp ::= SOME_ARROW_SOME:o {: RESULT=new Pair(o, ExprBinary.Op.SOME_ARROW_SOME); :}; +RelOp ::= SOME_ARROW_ONE:o {: RESULT=new Pair(o, ExprBinary.Op.SOME_ARROW_ONE ); :}; +RelOp ::= SOME_ARROW_LONE:o {: RESULT=new Pair(o, ExprBinary.Op.SOME_ARROW_LONE); :}; +RelOp ::= ONE_ARROW_ANY:o {: RESULT=new Pair(o, ExprBinary.Op.ONE_ARROW_ANY ); :}; +RelOp ::= ONE_ARROW_SOME:o {: RESULT=new Pair(o, ExprBinary.Op.ONE_ARROW_SOME ); :}; +RelOp ::= ONE_ARROW_ONE:o {: RESULT=new Pair(o, ExprBinary.Op.ONE_ARROW_ONE ); :}; +RelOp ::= ONE_ARROW_LONE:o {: RESULT=new Pair(o, ExprBinary.Op.ONE_ARROW_LONE ); :}; +RelOp ::= LONE_ARROW_ANY:o {: RESULT=new Pair(o, ExprBinary.Op.LONE_ARROW_ANY ); :}; +RelOp ::= LONE_ARROW_SOME:o {: RESULT=new Pair(o, ExprBinary.Op.LONE_ARROW_SOME); :}; +RelOp ::= LONE_ARROW_ONE:o {: RESULT=new Pair(o, ExprBinary.Op.LONE_ARROW_ONE ); :}; +RelOp ::= LONE_ARROW_LONE:o {: RESULT=new Pair(o, ExprBinary.Op.LONE_ARROW_LONE); :}; + +RelationExprA ::= DomainExprA:a {: RESULT=a; :}; +RelationExprA ::= DomainExprB:a RelOp:o Bind:b {: RESULT=o.b.make(o.a, null, a, b); :}; +RelationExprB ::= DomainExprB:a {: RESULT=a; :}; +RelationExprB ::= DomainExprB:a RelOp:o RelationExprB:b {: RESULT=o.b.make(o.a, null, a, b); :}; + +DomainExprA ::= RangeExprA:b {: RESULT=b; :}; +DomainExprA ::= DomainExprB:a DOMAIN:o Bind:b {: RESULT=ExprBinary.Op.DOMAIN.make(o, null, a, b); :}; +DomainExprB ::= RangeExprB:b {: RESULT=b; :}; +DomainExprB ::= DomainExprB:a DOMAIN:o RangeExprB:b {: RESULT=ExprBinary.Op.DOMAIN.make(o, null, a, b); :}; + +RangeExprA ::= BracketExprA:b {: RESULT=b; :}; +RangeExprA ::= RangeExprB:a RANGE:o Bind:b {: RESULT=ExprBinary.Op.RANGE.make(o, null, a, b); :}; +RangeExprB ::= BracketExprB:b {: RESULT=b; :}; +RangeExprB ::= RangeExprB:a RANGE:o BracketExprB:b {: RESULT=ExprBinary.Op.RANGE.make(o, null, a, b); :}; + +BracketExprA ::= DotExprA:b {: RESULT=b; :}; +BracketExprB ::= DotExprB:b {: RESULT=b; :}; +BracketExprB ::= BracketExprB:a LBRACKET Exprs:b RBRACKET:c {: Expr aa=a; for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=aa; :}; +BracketExprB ::= DISJ:a LBRACKET Exprs:b RBRACKET:c {: Expr aa=ExprVar.make(a, "disj"); for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=aa; :}; +BracketExprB ::= TOTALORDER:a LBRACKET Exprs:b RBRACKET:c {: Expr aa=ExprVar.make(a, "pred/totalOrder"); for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=aa; :}; +//[AM]: INT->SIGINT +BracketExprB ::= INT:a LBRACKET Exprs:b RBRACKET:c {: Expr aa=ExprVar.make(a, "int"); for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=ExprUnary.Op.CAST2SIGINT.make(a, aa); :}; +BracketExprB ::= SUM:a LBRACKET Exprs:b RBRACKET:c {: Expr aa=ExprVar.make(a, "int"); for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=ExprUnary.Op.CAST2SIGINT.make(a, aa); :}; + +DotExprA ::= UnopExprA:b {: RESULT=b; :}; +DotExprA ::= BracketExprB:a DOT:o Bind:b {: RESULT=t(o, null, a, b, null); :}; +DotExprB ::= UnopExprB:b {: RESULT=b; :}; +DotExprB ::= BracketExprB:a DOT:o UnopExprB:b {: RESULT=t(o, null, a, b, null); :}; +DotExprB ::= BracketExprB:a DOT:o DISJ:b {: RESULT=t(o, null, a, ExprVar.make(b, "disj"), null); :}; +DotExprB ::= BracketExprB:a DOT:o TOTALORDER:b {: RESULT=t(o, null, a, ExprVar.make(b, "pred/totalOrder"), null); :}; +//[AM]: INT->SIGINT +DotExprB ::= BracketExprB:a DOT:o INT {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, a)); :}; +DotExprB ::= BracketExprB:a DOT:o SUM {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, a)); :}; + +UnopExprA ::= TILDE:o Bind:b {: RESULT=ExprUnary.Op.TRANSPOSE.make(o,b); :}; +UnopExprA ::= STAR:o Bind:b {: RESULT=ExprUnary.Op.RCLOSURE .make(o,b); :}; +UnopExprA ::= CARET:o Bind:b {: RESULT=ExprUnary.Op.CLOSURE .make(o,b); :}; +UnopExprA ::= TILDE:o UnopExprA:b {: RESULT=ExprUnary.Op.TRANSPOSE.make(o,b); :}; +UnopExprA ::= STAR:o UnopExprA:b {: RESULT=ExprUnary.Op.RCLOSURE .make(o,b); :}; +UnopExprA ::= CARET:o UnopExprA:b {: RESULT=ExprUnary.Op.CLOSURE .make(o,b); :}; +UnopExprB ::= BaseExpr:b {: RESULT=b; :}; +UnopExprB ::= TILDE:o UnopExprB:b {: RESULT=ExprUnary.Op.TRANSPOSE.make(o,b); :}; +UnopExprB ::= STAR:o UnopExprB:b {: RESULT=ExprUnary.Op.RCLOSURE .make(o,b); :}; +UnopExprB ::= CARET:o UnopExprB:b {: RESULT=ExprUnary.Op.CLOSURE .make(o,b); :}; + +BaseExpr ::= NUMBER:x {: RESULT = x; :}; +BaseExpr ::= STR:x {: RESULT = x; :}; +BaseExpr ::= IDEN:o {: RESULT = ExprVar.make(o, "iden"); :}; +BaseExpr ::= THIS:o {: RESULT = ExprVar.make(o, "this"); :}; +BaseExpr ::= INTMIN:o {: RESULT = ExprConstant.Op.MIN.make(o, 0); :}; +BaseExpr ::= INTMAX:o {: RESULT = ExprConstant.Op.MAX.make(o, 0); :}; +BaseExpr ::= INTNEXT:o {: RESULT = ExprConstant.Op.NEXT.make(o, 0); :}; +BaseExpr ::= LPAREN Expr:x RPAREN {: RESULT = x; :}; +BaseExpr ::= SigRef:x {: RESULT = x; :}; +BaseExpr ::= AT:o Name:x {: nod(x); RESULT = ExprVar.make(o.merge(x.pos), "@"+x.label); :}; +BaseExpr ::= Super:x {: RESULT = x; :}; +BaseExpr ::= LBRACE:o Declz:a SuperOrBar:b RBRACE:c {: RESULT = ExprQt.Op.COMPREHENSION.make(o, c, a, b); :}; +BaseExpr ::= LBRACE:o Declz:a RBRACE:c {: RESULT = ExprQt.Op.COMPREHENSION.make(o, c, a, ExprConstant.TRUE); :}; + +//============================================================================= diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/edu/mit/csail/sdg/alloy4compiler/parser/Alloy.lex b/Source/eu.modelwriter.alloyanalyzer/bin/edu/mit/csail/sdg/alloy4compiler/parser/Alloy.lex new file mode 100644 index 00000000..b6f2af29 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/edu/mit/csail/sdg/alloy4compiler/parser/Alloy.lex @@ -0,0 +1,218 @@ +// Alloy Analyzer 4 -- Copyright (c) 2006-2008, Felix Chang +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files +// (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, +// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +package edu.mit.csail.sdg.alloy4compiler.parser; + +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprConstant; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import java.util.List; +import java_cup.runtime.*; + +/** Autogenerated by JFlex 1.4.1 */ + +%% + +// There are 3 sets of "special tokens" that the lexer will not output. +// But the Parser expects them. +// So a special Filter class is written that sits between Lexer and Parser. +// The Filter class observes the stream of tokens, and intelligently +// merges or changes some primitive tokens into special tokens. +// For more details, refer to the main documentation. +// +// But, very briefly, here are the 3 groups: +// +// (1) The lexer will generate only ALL, NO, LONE, ONE, SUM, SOME. +// It will not output ALL2, NO2, LONE2, ONE2, SUM2, SOME2. +// (The Filter class will change some ONE into ONE2, etc) +// +// (2) The lexer won't output NOTEQUALS, NOTIN, NOTLT, NOTLTE, NOTGT, NOTGTE. +// Instead it outputs them as separate tokens (eg. "NOT" "EQUALS"). +// (The Filter class is used to merge them into a single "NOTEQUALS" token) +// +// (3) The lexer willn't output the 15 special arrows (eg. ONE_ARROW_ONE) +// Instead it outputs them as separate tokens (eg. "ONE", "ARROW", "ONE") +// (The Filter class is used to merge them into a single "ONE_ARROW_ONE" token) + +%class CompLexer // The ordering of these directives is important +%cupsym CompSym +%cup +%eofval{ + return new Symbol(CompSym.EOF, alloy_here(" "), alloy_here(" ")); +%eofval} +%public +%final +%unicode +%line +%column +%pack + +%{ + public String alloy_filename=""; + public int alloy_lineoffset=0; // If not zero, it is added to the current LINE NUMBER + public List alloy_seenDollar; + public CompModule alloy_module; + private final Pos alloy_here(String txt) { + return new Pos(alloy_filename,yycolumn+1,yyline+1+alloy_lineoffset,yycolumn+txt.length(),yyline+1); + } + private final Symbol alloy_sym(String txt, int type) { + Pos p = alloy_here(txt); return new Symbol(type, p, p); + } + private final Symbol alloy_string(String txt) throws Err { + Pos p = alloy_here(txt); + if (!Version.experimental) throw new ErrorSyntax(p, "String literal is not currently supported."); + StringBuilder sb = new StringBuilder(txt.length()); + for(int i=0; i=txt.length()) throw new ErrorSyntax(p, "String literal cannot end with a single \\"); + c = txt.charAt(i); + if (c=='n') c='\n'; else if (c!='\'' && c!='\"' && c!='\\') throw new ErrorSyntax(p, "String literal currenty only supports\nfour escape sequences: \\\\, \\n, \\\', and \\\""); + } + sb.append(c); + } + txt = sb.toString(); + if (txt.length()==2) throw new ErrorSyntax(p, "Empty string is not allowed; try rewriting your model to use an empty set instead."); + return new Symbol(CompSym.STR, p, ExprConstant.Op.STRING.make(p, txt)); + } + private final Symbol alloy_id(String txt) throws Err { + Pos p=alloy_here(txt); + if (alloy_seenDollar.size()==0 && txt.indexOf('$')>=0) alloy_seenDollar.add(null); + return new Symbol(CompSym.ID, p, ExprVar.make(p,txt)); + } + private final Symbol alloy_num(String txt) throws Err { + Pos p=alloy_here(txt); + int n=0; + try { + n=Integer.parseInt(txt); + } catch(NumberFormatException ex) { + throw new ErrorSyntax(p, "The number "+txt+" is too large to be stored in a Java integer"); + } + return new Symbol(CompSym.NUMBER, p, ExprConstant.Op.NUMBER.make(p, n)); + } +%} + +%% + +"!" { return alloy_sym(yytext(), CompSym.NOT );} +"#" { return alloy_sym(yytext(), CompSym.HASH );} +"&&" { return alloy_sym(yytext(), CompSym.AND );} +"&" { return alloy_sym(yytext(), CompSym.AMPERSAND );} +"(" { return alloy_sym(yytext(), CompSym.LPAREN );} +")" { return alloy_sym(yytext(), CompSym.RPAREN );} +"*" { return alloy_sym(yytext(), CompSym.STAR );} +"++" { return alloy_sym(yytext(), CompSym.PLUSPLUS );} +"+" { return alloy_sym(yytext(), CompSym.PLUS );} +"," { return alloy_sym(yytext(), CompSym.COMMA );} +"->" { return alloy_sym(yytext(), CompSym.ARROW );} +"-" { return alloy_sym(yytext(), CompSym.MINUS );} +"." { return alloy_sym(yytext(), CompSym.DOT );} +"/" { return alloy_sym(yytext(), CompSym.SLASH );} +"::" { return alloy_sym(yytext(), CompSym.DOT );} +":>" { return alloy_sym(yytext(), CompSym.RANGE );} +":" { return alloy_sym(yytext(), CompSym.COLON );} +"<=>" { return alloy_sym(yytext(), CompSym.IFF );} +"<=" { return alloy_sym(yytext(), CompSym.LTE );} +"<:" { return alloy_sym(yytext(), CompSym.DOMAIN );} +"<<" { return alloy_sym(yytext(), CompSym.SHL );} +"<" { return alloy_sym(yytext(), CompSym.LT );} +"=<" { return alloy_sym(yytext(), CompSym.LTE );} +"=>" { return alloy_sym(yytext(), CompSym.IMPLIES );} +"=" { return alloy_sym(yytext(), CompSym.EQUALS );} +">>>" { return alloy_sym(yytext(), CompSym.SHR );} +">>" { return alloy_sym(yytext(), CompSym.SHA );} +">=" { return alloy_sym(yytext(), CompSym.GTE );} +">" { return alloy_sym(yytext(), CompSym.GT );} +"@" { return alloy_sym(yytext(), CompSym.AT );} +"[" { return alloy_sym(yytext(), CompSym.LBRACKET );} +"]" { return alloy_sym(yytext(), CompSym.RBRACKET );} +"^" { return alloy_sym(yytext(), CompSym.CARET );} +"{" { return alloy_sym(yytext(), CompSym.LBRACE );} +"||" { return alloy_sym(yytext(), CompSym.OR );} +"|" { return alloy_sym(yytext(), CompSym.BAR );} +"}" { return alloy_sym(yytext(), CompSym.RBRACE );} +"~" { return alloy_sym(yytext(), CompSym.TILDE );} +"abstract" { return alloy_sym(yytext(), CompSym.ABSTRACT );} +"all" { return alloy_sym(yytext(), CompSym.ALL );} +"and" { return alloy_sym(yytext(), CompSym.AND );} +"assert" { return alloy_sym(yytext(), CompSym.ASSERT );} +"as" { return alloy_sym(yytext(), CompSym.AS );} +"but" { return alloy_sym(yytext(), CompSym.BUT );} +"check" { return alloy_sym(yytext(), CompSym.CHECK );} +"disjoint" { return alloy_sym(yytext(), CompSym.DISJ );} +"disj" { return alloy_sym(yytext(), CompSym.DISJ );} +"else" { return alloy_sym(yytext(), CompSym.ELSE );} +"enum" { return alloy_sym(yytext(), CompSym.ENUM );} +"exactly" { return alloy_sym(yytext(), CompSym.EXACTLY );} +"exhaustive" { return alloy_sym(yytext(), CompSym.EXH );} +"exh" { return alloy_sym(yytext(), CompSym.EXH );} +"expect" { return alloy_sym(yytext(), CompSym.EXPECT );} +"extends" { return alloy_sym(yytext(), CompSym.EXTENDS );} +"fact" { return alloy_sym(yytext(), CompSym.FACT );} +"for" { return alloy_sym(yytext(), CompSym.FOR );} +"fun" { return alloy_sym(yytext(), CompSym.FUN );} +"iden" { return alloy_sym(yytext(), CompSym.IDEN );} +"iff" { return alloy_sym(yytext(), CompSym.IFF );} +"implies" { return alloy_sym(yytext(), CompSym.IMPLIES );} +"Int" { return alloy_sym(yytext(), CompSym.SIGINT );} +"int" { return alloy_sym(yytext(), CompSym.INT );} +"in" { return alloy_sym(yytext(), CompSym.IN );} +"let" { return alloy_sym(yytext(), CompSym.LET );} +"lone" { return alloy_sym(yytext(), CompSym.LONE );} +"module" { return alloy_sym(yytext(), CompSym.MODULE );} +"none" { return alloy_sym(yytext(), CompSym.NONE );} +"not" { return alloy_sym(yytext(), CompSym.NOT );} +"no" { return alloy_sym(yytext(), CompSym.NO );} +"one" { return alloy_sym(yytext(), CompSym.ONE );} +"open" { return alloy_sym(yytext(), CompSym.OPEN );} +"or" { return alloy_sym(yytext(), CompSym.OR );} +"partition" { return alloy_sym(yytext(), CompSym.PART );} +"part" { return alloy_sym(yytext(), CompSym.PART );} +"pred" { return alloy_sym(yytext(), CompSym.PRED );} +"private" { return alloy_sym(yytext(), CompSym.PRIVATE );} +"run" { return alloy_sym(yytext(), CompSym.RUN );} +"seq" { return alloy_sym(yytext(), CompSym.SEQ );} +"set" { return alloy_sym(yytext(), CompSym.SET );} +"sig" { return alloy_sym(yytext(), CompSym.SIG );} +"some" { return alloy_sym(yytext(), CompSym.SOME );} +"String" { return alloy_sym(yytext(), CompSym.STRING );} +"sum" { return alloy_sym(yytext(), CompSym.SUM );} +"this" { return alloy_sym(yytext(), CompSym.THIS );} +"univ" { return alloy_sym(yytext(), CompSym.UNIV );} + +[\"] ([^\\\"] | ("\\" .))* [\"] [\$0-9a-zA-Z_\'\"] [\$0-9a-zA-Z_\'\"]* { throw new ErrorSyntax(alloy_here(yytext()),"String literal cannot be followed by a legal identifier character."); } +[\"] ([^\\\"] | ("\\" .))* [\"] { return alloy_string(yytext()); } +[\"] ([^\\\"] | ("\\" .))* { throw new ErrorSyntax(alloy_here(yytext()),"String literal is missing its closing \" character"); } +[0-9][0-9]*[\$a-zA-Z_\'\"][\$0-9a-zA-Z_\'\"]* { throw new ErrorSyntax(alloy_here(yytext()),"Name cannot start with a number."); } +[0-9][0-9]* { return alloy_num (yytext()); } +[:jletter:][[:jletterdigit:]\'\"]* { return alloy_id (yytext()); } +//[\$a-zA-Z][\$0-9a-zA-Z_\'\"]* { return alloy_id (yytext()); } + +"/**" ~"*/" { } + +"/*" ~"*/" { } + +("//"|"--") [^\r\n]* [\r\n] { } + +("//"|"--") [^\r\n]* { } // This rule is shorter than the previous rule, + // so it will only apply if the final line of a file is missing the \n or \r character. + +[ \t\f\r\n] { } + +. { throw new ErrorSyntax(alloy_here(" "), "Syntax error at the "+yytext()+" character."); } diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/edu/mit/csail/sdg/alloy4compiler/parser/generate-lexer.sh b/Source/eu.modelwriter.alloyanalyzer/bin/edu/mit/csail/sdg/alloy4compiler/parser/generate-lexer.sh new file mode 100644 index 00000000..de50c662 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/edu/mit/csail/sdg/alloy4compiler/parser/generate-lexer.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +java -cp $LIB_SDG/jars-external/JFlex.jar JFlex.Main --nobak -d . Alloy.lex + +sed -i 's/public java_cup.runtime.Symbol next_token() throws java.io.IOException/public java_cup.runtime.Symbol next_token() throws java.io.IOException, Err/' CompLexer.java + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/edu/mit/csail/sdg/alloy4compiler/parser/generate-parser.sh b/Source/eu.modelwriter.alloyanalyzer/bin/edu/mit/csail/sdg/alloy4compiler/parser/generate-parser.sh new file mode 100644 index 00000000..f27fddeb --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/edu/mit/csail/sdg/alloy4compiler/parser/generate-parser.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +java -cp $LIB_SDG/jars-external/java-cup-11a.jar java_cup.Main \ + -package edu.mit.csail.sdg.alloy4compiler.parser \ + -parser CompParser \ + -progress -time -compact_red \ + -symbols CompSym < Alloy.cup \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/edu/mit/csail/sdg/alloy4compiler/parser/generate-parsing-trace-from-log.sh b/Source/eu.modelwriter.alloyanalyzer/bin/edu/mit/csail/sdg/alloy4compiler/parser/generate-parsing-trace-from-log.sh new file mode 100644 index 00000000..4c640e8d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/edu/mit/csail/sdg/alloy4compiler/parser/generate-parsing-trace-from-log.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +## ---------------------------------------------------------------------- +## +## This script takes a parsing log and from it generates a human readable +## parsing trace, i.g. a sequence of shifts and reduces that took place. +## +## To get the parsing log just set the "debug" environment variable to +## "yes" before runngin Alloy (or add "-Ddebug=yes" to the list of JVM +## arguments) +## +## This script must be invoked from exactly the folder where it resides +## because it needs to find the CompParser.java and CompSym.java files +## in the same folder. +## +## ---------------------------------------------------------------------- + +logFile=$1 + +if [[ -z $logFile ]] +then + echo "usage: $0 " + exit +fi + +if [[ ! -f $logFile ]] +then + echo "file $logFile doesn't exist" + exit +fi + +while read line +do + if [[ ! -z $(echo $line | grep "^reduce ") ]] + then + act=$(echo $line | sed 's/reduce //') + echo "reduce" + grep "case $act:" CompParser.java + elif [[ ! -z $(echo $line | grep "^shift ") ]] + then + sym=$(echo $line | sed 's/shift //') + sgn=$(grep " = $sym;" CompSym.java | sed 's/ public static final int //' | sed 's/ = '$sym';//') + echo "shift" + echo " $sgn" + else + echo $line + fi +done < $logFile \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/edu/mit/csail/sdg/alloy4compiler/translator/instance.txt b/Source/eu.modelwriter.alloyanalyzer/bin/edu/mit/csail/sdg/alloy4compiler/translator/instance.txt new file mode 100644 index 00000000..dda19365 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/edu/mit/csail/sdg/alloy4compiler/translator/instance.txt @@ -0,0 +1,26 @@ +WHOLEFILE = exactly 1 INSTANCE + 0 or more SOURCE + +INSTANCE = 0 or more PRIMSIG + 0 or more SUBSETSIG + 0 or more FIELD + 0 or more SKOLEM + +PRIMSIG = 0 or more ATOM + +SUBSETSIG = 0 or more ATOM + 1 or more TYPE + +FIELD = 0 or more TUPLE + 1 or more TYPES + +SKOLEM = 0 or more TUPLE + 1 or more TYPES + +TUPLE = 1 or more ATOM +ATOM = + +TYPES = 1 or more TYPE +TYPE = + +SOURCE = diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/help/image/error.gif b/Source/eu.modelwriter.alloyanalyzer/bin/help/image/error.gif new file mode 100644 index 00000000..d37e28b4 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/help/image/error.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/help/image/general.gif b/Source/eu.modelwriter.alloyanalyzer/bin/help/image/general.gif new file mode 100644 index 00000000..52976128 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/help/image/general.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/help/image/pref.gif b/Source/eu.modelwriter.alloyanalyzer/bin/help/image/pref.gif new file mode 100644 index 00000000..eb2fd296 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/help/image/pref.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/help/image/theme.gif b/Source/eu.modelwriter.alloyanalyzer/bin/help/image/theme.gif new file mode 100644 index 00000000..ad9e58d1 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/help/image/theme.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/help/image/toolbar.gif b/Source/eu.modelwriter.alloyanalyzer/bin/help/image/toolbar.gif new file mode 100644 index 00000000..f3cbda1b Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/help/image/toolbar.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/help/image/toolbarviz.gif b/Source/eu.modelwriter.alloyanalyzer/bin/help/image/toolbarviz.gif new file mode 100644 index 00000000..98abc4f5 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/help/image/toolbarviz.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/help/image/tree.gif b/Source/eu.modelwriter.alloyanalyzer/bin/help/image/tree.gif new file mode 100644 index 00000000..40bd56a8 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/help/image/tree.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/help/image/viz.gif b/Source/eu.modelwriter.alloyanalyzer/bin/help/image/viz.gif new file mode 100644 index 00000000..0f27b631 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/help/image/viz.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/help/image/xml.gif b/Source/eu.modelwriter.alloyanalyzer/bin/help/image/xml.gif new file mode 100644 index 00000000..45316860 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/help/image/xml.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/black.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/black.gif new file mode 100644 index 00000000..bba84da2 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/black.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/blue.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/blue.gif new file mode 100644 index 00000000..e6b2a7e9 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/blue.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/cadetblue.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/cadetblue.gif new file mode 100644 index 00000000..d01b37fe Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/cadetblue.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/chartreuse2.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/chartreuse2.gif new file mode 100644 index 00000000..0502739f Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/chartreuse2.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/cornflowerblue.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/cornflowerblue.gif new file mode 100644 index 00000000..64a86a64 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/cornflowerblue.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/cyan.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/cyan.gif new file mode 100644 index 00000000..720fb8cd Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/cyan.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/darkolivegreen2.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/darkolivegreen2.gif new file mode 100644 index 00000000..827b3f9c Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/darkolivegreen2.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/gold.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/gold.gif new file mode 100644 index 00000000..f6dc8ce8 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/gold.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/green2.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/green2.gif new file mode 100644 index 00000000..5b689651 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/green2.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/lightgoldenrod.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/lightgoldenrod.gif new file mode 100644 index 00000000..27fb805b Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/lightgoldenrod.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/lightgray.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/lightgray.gif new file mode 100644 index 00000000..b3f1bfa7 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/lightgray.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/limegreen.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/limegreen.gif new file mode 100644 index 00000000..29edc92b Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/limegreen.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/magenta.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/magenta.gif new file mode 100644 index 00000000..8d3d29ca Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/magenta.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/magic.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/magic.gif new file mode 100644 index 00000000..61598714 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/magic.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/palevioletred.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/palevioletred.gif new file mode 100644 index 00000000..1de7a229 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/palevioletred.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/red.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/red.gif new file mode 100644 index 00000000..c7604a5a Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/red.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/salmon.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/salmon.gif new file mode 100644 index 00000000..1d3dca18 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/salmon.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/white.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/white.gif new file mode 100644 index 00000000..02a767d3 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/white.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/yellow.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/yellow.gif new file mode 100644 index 00000000..a09f1c23 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ColorIcons/yellow.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/Mcircle.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/Mcircle.gif new file mode 100644 index 00000000..49a659f8 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/Mcircle.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/Mdiamond.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/Mdiamond.gif new file mode 100644 index 00000000..071f9807 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/Mdiamond.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/Msquare.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/Msquare.gif new file mode 100644 index 00000000..2db39335 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/Msquare.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/box.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/box.gif new file mode 100644 index 00000000..788dee55 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/box.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/circle.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/circle.gif new file mode 100644 index 00000000..87fe62e4 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/circle.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/diamond.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/diamond.gif new file mode 100644 index 00000000..e0a1df4b Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/diamond.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/doublecircle.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/doublecircle.gif new file mode 100644 index 00000000..33156e8c Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/doublecircle.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/doubleoctagon.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/doubleoctagon.gif new file mode 100644 index 00000000..064307f3 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/doubleoctagon.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/egg.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/egg.gif new file mode 100644 index 00000000..3d49e5a9 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/egg.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/ellipse.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/ellipse.gif new file mode 100644 index 00000000..83dc2f41 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/ellipse.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/hexagon.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/hexagon.gif new file mode 100644 index 00000000..e85ae033 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/hexagon.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/house.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/house.gif new file mode 100644 index 00000000..4812b028 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/house.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/invhouse.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/invhouse.gif new file mode 100644 index 00000000..71dc4b83 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/invhouse.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/invtrapezium.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/invtrapezium.gif new file mode 100644 index 00000000..7eaf0c04 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/invtrapezium.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/invtriangle.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/invtriangle.gif new file mode 100644 index 00000000..c3394467 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/invtriangle.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/octagon.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/octagon.gif new file mode 100644 index 00000000..7ec0b4bb Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/octagon.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/parallelogram.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/parallelogram.gif new file mode 100644 index 00000000..a4925d03 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/parallelogram.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/trapezium.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/trapezium.gif new file mode 100644 index 00000000..2381a684 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/trapezium.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/triangle.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/triangle.gif new file mode 100644 index 00000000..730a1b0c Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/triangle.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/tripleoctagon.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/tripleoctagon.gif new file mode 100644 index 00000000..1f604228 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/ShapeIcons/tripleoctagon.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/StyleIcons/bold.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/StyleIcons/bold.gif new file mode 100644 index 00000000..dda8863b Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/StyleIcons/bold.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/StyleIcons/dashed.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/StyleIcons/dashed.gif new file mode 100644 index 00000000..b12004d2 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/StyleIcons/dashed.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/StyleIcons/dotted.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/StyleIcons/dotted.gif new file mode 100644 index 00000000..be61201c Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/StyleIcons/dotted.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/icons/StyleIcons/solid.gif b/Source/eu.modelwriter.alloyanalyzer/bin/icons/StyleIcons/solid.gif new file mode 100644 index 00000000..7d837f15 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/icons/StyleIcons/solid.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/24_execute.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_execute.gif new file mode 100644 index 00000000..ddd93932 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_execute.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/24_execute_abort2.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_execute_abort2.gif new file mode 100644 index 00000000..332d42ab Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_execute_abort2.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/24_graph.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_graph.gif new file mode 100644 index 00000000..ac830a0a Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_graph.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/24_history.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_history.gif new file mode 100644 index 00000000..c18eb6b4 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_history.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/24_new.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_new.gif new file mode 100644 index 00000000..9d9f0ee2 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_new.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/24_open.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_open.gif new file mode 100644 index 00000000..de4696ce Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_open.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/24_plaintext.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_plaintext.gif new file mode 100644 index 00000000..7eace4b3 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_plaintext.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/24_reload.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_reload.gif new file mode 100644 index 00000000..2652ff48 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_reload.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/24_save.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_save.gif new file mode 100644 index 00000000..e243bd53 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_save.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings.gif new file mode 100644 index 00000000..0195f5bb Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_apply.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_apply.gif new file mode 100644 index 00000000..87fe2dc1 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_apply.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_apply2.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_apply2.gif new file mode 100644 index 00000000..b91773cb Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_apply2.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_apply3.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_apply3.gif new file mode 100644 index 00000000..7472cf1e Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_apply3.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_close.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_close.gif new file mode 100644 index 00000000..a550fa6d Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_close.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_close2.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_close2.gif new file mode 100644 index 00000000..652ad79f Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_close2.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_close3.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_close3.gif new file mode 100644 index 00000000..20f9c5fb Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_close3.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_close4.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_close4.gif new file mode 100644 index 00000000..50209486 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_close4.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_close5.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_close5.gif new file mode 100644 index 00000000..3c417b5e Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_settings_close5.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/24_texttree.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_texttree.gif new file mode 100644 index 00000000..ab735b1f Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/24_texttree.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/cb0.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/cb0.gif new file mode 100644 index 00000000..4e47578d Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/cb0.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/cb1.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/cb1.gif new file mode 100644 index 00000000..491dcb86 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/cb1.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/logo.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/logo.gif new file mode 100644 index 00000000..c23a7f05 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/logo.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/menu0.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/menu0.gif new file mode 100644 index 00000000..b1d498cd Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/menu0.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/menu1.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/menu1.gif new file mode 100644 index 00000000..f204c0b5 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/menu1.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/tcb01.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/tcb01.gif new file mode 100644 index 00000000..dd3972f8 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/tcb01.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/tcb02.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/tcb02.gif new file mode 100644 index 00000000..7755c002 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/tcb02.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/tcb03.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/tcb03.gif new file mode 100644 index 00000000..d3ad1e95 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/tcb03.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/images/tcb04.gif b/Source/eu.modelwriter.alloyanalyzer/bin/images/tcb04.gif new file mode 100644 index 00000000..d0dff531 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/bin/images/tcb04.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/addressBook1.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/addressBook1.als new file mode 100644 index 00000000..06c2abf8 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/addressBook1.als @@ -0,0 +1,19 @@ +module appendixA/addressBook1 + +abstract sig Name { + address: set Addr+Name + } + +sig Alias, Group extends Name { } + +sig Addr { } + +fact { + // the invariants should go here + } + +pred show { + // simulation constraints should go here + } + +run show for 3 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/addressBook2.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/addressBook2.als new file mode 100644 index 00000000..02ba6373 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/addressBook2.als @@ -0,0 +1,27 @@ +module appendixA/addressBook2 + +sig Addr, Name { } + +sig Book { + addr: Name -> (Name + Addr) + } + +pred inv [b: Book] { + let addr = b.addr | + all n: Name { + n not in n.^addr + some addr.n => some n.^addr & Addr + } + } + +pred add [b, b': Book, n: Name, t: Name+Addr] { + b'.addr = b.addr + n->t + } + +pred del [b, b': Book, n: Name, t: Name+Addr] { + b'.addr = b.addr - n->t + } + +fun lookup [b: Book, n: Name] : set Addr { + n.^(b.addr) & Addr + } diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/barbers.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/barbers.als new file mode 100644 index 00000000..6205b5f4 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/barbers.als @@ -0,0 +1,9 @@ +module appendixA/barbers + +sig Man { shaves: set Man } + +one sig Barber extends Man { } + +fact { + Barber.shaves = { m: Man | m not in m.shaves } + } diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/closure.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/closure.als new file mode 100644 index 00000000..6a50e404 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/closure.als @@ -0,0 +1,16 @@ +module appendixA/closure + +pred transCover [R, r: univ->univ] { + // You have to fill in the appropriate formula here +} + +pred transClosure [R, r: univ->univ] { + transCover [R, r] + // You have to fill in the appropriate formula here +} + +assert Equivalence { + all R, r: univ->univ | transClosure [R,r] iff R = ^r +} + +check Equivalence for 3 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/distribution.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/distribution.als new file mode 100644 index 00000000..6614b2e6 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/distribution.als @@ -0,0 +1,7 @@ +module appendixA/distribution + +assert union { + all s: set univ, p, q: univ->univ | s.(p+q) = s.p + s.q +} + +check union for 4 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/phones.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/phones.als new file mode 100644 index 00000000..98c13677 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/phones.als @@ -0,0 +1,6 @@ +module appendixA/phones + +sig Phone { + requests: set Phone, + connects: lone Phone + } diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/prison.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/prison.als new file mode 100644 index 00000000..42e9ea00 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/prison.als @@ -0,0 +1,17 @@ +module appendixA/prison + +sig Gang { members: set Inmate } + +sig Inmate { room: Cell } + +sig Cell { } + +pred safe { + // your constraints should go here + } + +pred show { + // your constraints should go here + } + +run show diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/properties.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/properties.als new file mode 100644 index 00000000..cc06cc1e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/properties.als @@ -0,0 +1,23 @@ +module appendixA/properties + +pred show { + some r: univ->univ { + some r -- nonempty + r.r in r -- transitive + no iden & r -- irreflexive + ~r in r -- symmetric + ~r.r in iden -- functional + r.~r in iden -- injective + univ in r.univ -- total + univ in univ.r -- onto + } + } + +run show for 4 + +assert ReformulateNonEmptinessOK { + all r: univ->univ | + some r iff (some x, y: univ | x->y in r) + } + +check ReformulateNonEmptinessOK diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/ring.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/ring.als new file mode 100644 index 00000000..ec577666 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/ring.als @@ -0,0 +1,9 @@ +module appendixA/ring + +sig Node { next: set Node } + +pred isRing { + // You have to fill in the appropriate formula here +} + +run isRing for exactly 4 Node diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/spanning.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/spanning.als new file mode 100644 index 00000000..5218e700 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/spanning.als @@ -0,0 +1,17 @@ +module appendixA/spanning + +pred isTree [r: univ->univ] { + // You have to fill in the appropriate formula here +} + +pred spans [r1, r2: univ->univ] { + // You have to fill in the appropriate formula here +} + +pred show [r, t1, t2: univ->univ] { + spans [t1,r] and isTree [t1] + spans [t2,r] and isTree [t2] + t1 != t2 +} + +run show for 3 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/tree.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/tree.als new file mode 100644 index 00000000..74750d40 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/tree.als @@ -0,0 +1,7 @@ +module appendixA/tree + +pred isTree [r:univ->univ] { + // You have to fill in the appropriate formula here +} + +run isTree for 4 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/tube.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/tube.als new file mode 100644 index 00000000..03af8de9 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/tube.als @@ -0,0 +1,21 @@ +module appendixA/tube + +abstract sig Station { + jubilee, central, circle: set Station + } + +sig Jubilee, Central, Circle in Station {} + +one sig + Stanmore, BakerStreet, BondStreet, Westminster, Waterloo, + WestRuislip, EalingBroadway, NorthActon, NottingHillGate, + LiverpoolStreet, Epping + extends Station {} + +fact { + // the constraints should go here + } + +pred show {} + +run show diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/undirected.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/undirected.als new file mode 100644 index 00000000..937cedb1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixA/undirected.als @@ -0,0 +1,11 @@ +module appendixA/undirected + +sig Node { adjs: set Node } + +pred acyclic { + adjs = ~adjs + // You have to fill in additional formula here +} + +run acyclic for 4 + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixE/hotel.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixE/hotel.thm new file mode 100644 index 00000000..fe20fbe1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixE/hotel.thm @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixE/p300-hotel.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixE/p300-hotel.als new file mode 100644 index 00000000..813846b2 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixE/p300-hotel.als @@ -0,0 +1,66 @@ +module hotel + +open util/ordering [Time] as timeOrder + +sig Key, Time {} + +sig Card { + fst, snd: Key + } + +sig Room { + key: Key one->Time + } + +one sig Desk { + issued: Key->Time, + prev: (Room->lone Key)->Time + } + +sig Guest { + cards: Card->Time + } + +pred init [t: Time] { + Desk.prev.t = key.t + no issued.t and no cards.t ------ bug! (see page 303) + } + +pred checkin [t,t': Time, r: Room, g: Guest] { + some c: Card { + c.fst = r.(Desk.prev.t) + c.snd not in Desk.issued.t + cards.t' = cards.t + g->c ------------- bug! (see page 306) + Desk.issued.t' = Desk.issued.t + c.snd + Desk.prev.t' = Desk.prev.t ++ r->c.snd + } + key.t = key.t' + } + +pred enter [t,t': Time, r: Room, g: Guest] { + some c: g.cards.t | + let k = r.key.t { + c.snd = k and key.t' = key.t + or c.fst = k and key.t' = key.t ++ r->c.snd + } + issued.t = issued.t' and (Desk<:prev).t = prev.t' + cards.t = cards.t' + } + +fact Traces { + init [first] + all t: Time - last | some g: Guest, r: Room | + checkin [t, t.next, r, g] or enter[t, t.next, r, g] + } + +assert NoIntruder { + no t1: Time, g: Guest, g': Guest-g, r: Room | + let t2=t1.next, t3=t2.next, t4=t3.next { + enter [t1, t2, r, g] + enter [t2, t3, r, g'] + enter [t3, t4, r, g] + } + } + +-- This check reveals a bug (similar to Fig E.3) in which the initial key was issued twice. +check NoIntruder for 3 but 6 Time, 1 Room, 2 Guest diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixE/p303-hotel.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixE/p303-hotel.als new file mode 100644 index 00000000..652de3d8 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixE/p303-hotel.als @@ -0,0 +1,70 @@ +module hotel + +open util/ordering [Time] as timeOrder + +sig Key, Time {} + +sig Card { + fst, snd: Key + } + +sig Room { + key: Key one->Time + } + +one sig Desk { + issued: Key->Time, + prev: (Room->lone Key)->Time + } + +sig Guest { + cards: Card->Time + } + +pred init [t: Time] { + Desk.prev.t = key.t + Desk.issued.t = Room.key.t and no cards.t + } + +pred checkin [t,t': Time, r: Room, g: Guest] { + some c: Card { + c.fst = r.(Desk.prev.t) + c.snd not in Desk.issued.t + cards.t' = cards.t + g->c ------------- bug! (see page 306) + Desk.issued.t' = Desk.issued.t + c.snd + Desk.prev.t' = Desk.prev.t ++ r->c.snd + } + key.t = key.t' + } + +pred enter [t,t': Time, r: Room, g: Guest] { + some c: g.cards.t | + let k = r.key.t { + c.snd = k and key.t' = key.t + or c.fst = k and key.t' = key.t ++ r->c.snd + } + issued.t = issued.t' and (Desk<:prev).t = prev.t' + cards.t = cards.t' + } + +fact Traces { + init [first] + all t: Time - last | some g: Guest, r: Room | + checkin [t, t.next, r, g] or enter[t, t.next, r, g] + } + +assert NoIntruder { + no t1: Time, g: Guest, g': Guest-g, r: Room | + let t2=t1.next, t3=t2.next, t4=t3.next { + enter [t1, t2, r, g] + enter [t2, t3, r, g'] + enter [t3, t4, r, g] + } + } + +-- This check now succeeds without finding any counterexample. +check NoIntruder for 3 but 6 Time, 1 Room, 2 Guest + +-- To increase our confidence, we can increase the scope. +-- This time, it finds a counterexample. +check NoIntruder for 4 but 7 Time, 1 Room, 2 Guest diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixE/p306-hotel.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixE/p306-hotel.als new file mode 100644 index 00000000..efcd7e7d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/appendixE/p306-hotel.als @@ -0,0 +1,73 @@ +module hotel + +open util/ordering [Time] as timeOrder + +sig Key, Time {} + +sig Card { + fst, snd: Key + } + +sig Room { + key: Key one->Time + } + +one sig Desk { + issued: Key->Time, + prev: (Room->lone Key)->Time + } + +sig Guest { + cards: Card->Time + } + +pred init [t: Time] { + Desk.prev.t = key.t + Desk.issued.t = Room.key.t and no cards.t + } + +pred checkin [t,t': Time, r: Room, g: Guest] { + some c: Card { + c.fst = r.(Desk.prev.t) + c.snd not in Desk.issued.t + cards.t' = cards.t ++ g->c + Desk.issued.t' = Desk.issued.t + c.snd + Desk.prev.t' = Desk.prev.t ++ r->c.snd + } + key.t = key.t' + } + +pred enter [t,t': Time, r: Room, g: Guest] { + some c: g.cards.t | + let k = r.key.t { + c.snd = k and key.t' = key.t + or c.fst = k and key.t' = key.t ++ r->c.snd + } + issued.t = issued.t' and (Desk<:prev).t = prev.t' + cards.t = cards.t' + } + +fact Traces { + init [first] + all t: Time - last | some g: Guest, r: Room | + checkin [t, t.next, r, g] or enter[t, t.next, r, g] + } + +assert NoIntruder { + no t1: Time, g: Guest, g': Guest-g, r: Room | + let t2=t1.next, t3=t2.next, t4=t3.next { + enter [t1, t2, r, g] + enter [t2, t3, r, g'] + enter [t3, t4, r, g] + } + } + +-- This check now succeeds without finding any counterexample. +check NoIntruder for 3 but 6 Time, 1 Room, 2 Guest + +-- This check now succeeds without finding any counterexample. +check NoIntruder for 4 but 7 Time, 1 Room, 2 Guest + +-- We can try to increase the scope further. +-- This check also succeeds without finding any counterexample. +check NoIntruder for 6 but 12 Time, 3 Room, 3 Guest diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1a.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1a.als new file mode 100644 index 00000000..643c0f2c --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1a.als @@ -0,0 +1,12 @@ +module tour/addressBook1a ----- Page 6 + +sig Name, Addr { } + +sig Book { + addr: Name -> lone Addr +} + +pred show { } + +// This command generates an instance similar to Fig 2.1 +run show for 3 but 1 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1b.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1b.als new file mode 100644 index 00000000..1d4255e9 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1b.als @@ -0,0 +1,14 @@ +module tour/addressBook1b ----- Page 8 + +sig Name, Addr { } + +sig Book { + addr: Name -> lone Addr +} + +pred show [b: Book] { + #b.addr > 1 +} + +// This command generates an instance similar to Fig 2.2 +run show for 3 but 1 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1c.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1c.als new file mode 100644 index 00000000..85b18616 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1c.als @@ -0,0 +1,15 @@ +module tour/addressBook1c ----- Page 8 + +sig Name, Addr { } + +sig Book { + addr: Name -> lone Addr +} + +pred show [b: Book] { + #b.addr > 1 + some n: Name | #n.(b.addr) > 1 +} + +// This command should not find any instance. +run show for 3 but 1 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1d.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1d.als new file mode 100644 index 00000000..c553a4f9 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1d.als @@ -0,0 +1,15 @@ +module tour/addressBook1d ----- Page 9 + +sig Name, Addr { } + +sig Book { + addr: Name -> lone Addr +} + +pred show [b: Book] { + #b.addr > 1 + #Name.(b.addr) > 1 +} + +// This command generates an instance similar to Fig 2.3 +run show for 3 but 1 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1e.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1e.als new file mode 100644 index 00000000..18165f34 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1e.als @@ -0,0 +1,14 @@ +module tour/addressBook1e ----- Page 11 + +sig Name, Addr { } + +sig Book { + addr: Name -> lone Addr +} + +pred add [b, b': Book, n: Name, a: Addr] { + b'.addr = b.addr + n->a +} + +// This command generates an instance similar to Fig 2.4 +run add for 3 but 2 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1f.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1f.als new file mode 100644 index 00000000..8774cd7b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1f.als @@ -0,0 +1,19 @@ +module tour/addressBook1f ----- Page 12 + +sig Name, Addr { } + +sig Book { + addr: Name -> lone Addr +} + +pred add [b, b': Book, n: Name, a: Addr] { + b'.addr = b.addr + n->a +} + +pred showAdd [b, b': Book, n: Name, a: Addr] { + add [b, b', n, a] + #Name.(b'.addr) > 1 +} + +// This command generates an instance similar to Fig 2.5 +run showAdd for 3 but 2 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1g.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1g.als new file mode 100644 index 00000000..4eeac73a --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1g.als @@ -0,0 +1,29 @@ +module tour/addressBook1g ----- Page 14 + +sig Name, Addr { } + +sig Book { + addr: Name -> lone Addr +} + +pred add [b, b': Book, n: Name, a: Addr] { + b'.addr = b.addr + n->a +} + +pred del [b, b': Book, n: Name] { + b'.addr = b.addr - n->Addr +} + +fun lookup [b: Book, n: Name] : set Addr { + n.(b.addr) +} + +assert delUndoesAdd { + all b, b', b'': Book, n: Name, a: Addr | + add [b, b', n, a] and del [b', b'', n] + implies + b.addr = b''.addr +} + +// This command generates an instance similar to Fig 2.6 +check delUndoesAdd for 3 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1h.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1h.als new file mode 100644 index 00000000..115eab78 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook1h.als @@ -0,0 +1,64 @@ +module tour/addressBook1h ------- Page 14..16 + +sig Name, Addr { } + +sig Book { + addr: Name -> lone Addr +} + +pred show [b: Book] { + #b.addr > 1 + #Name.(b.addr) > 1 +} +run show for 3 but 1 Book + +pred add [b, b': Book, n: Name, a: Addr] { + b'.addr = b.addr + n->a +} + +pred del [b, b': Book, n: Name] { + b'.addr = b.addr - n->Addr +} + +fun lookup [b: Book, n: Name] : set Addr { + n.(b.addr) +} + +pred showAdd [b, b': Book, n: Name, a: Addr] { + add [b, b', n, a] + #Name.(b'.addr) > 1 +} +run showAdd for 3 but 2 Book + +assert delUndoesAdd { + all b, b', b'': Book, n: Name, a: Addr | + no n.(b.addr) and add [b, b', n, a] and del [b', b'', n] + implies + b.addr = b''.addr +} + +assert addIdempotent { + all b, b', b'': Book, n: Name, a: Addr | + add [b, b', n, a] and add [b', b'', n, a] + implies + b'.addr = b''.addr +} + +assert addLocal { + all b, b': Book, n, n': Name, a: Addr | + add [b, b', n, a] and n != n' + implies + lookup [b, n'] = lookup [b', n'] +} + +// This command should not find any counterexample. +check delUndoesAdd for 3 + +// This command should not find any counterexample. +check delUndoesAdd for 10 but 3 Book + +// This command should not find any counterexample. +check addIdempotent for 3 + +// This command should not find any counterexample. +check addLocal for 3 but 2 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook2a.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook2a.als new file mode 100644 index 00000000..ab94951b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook2a.als @@ -0,0 +1,16 @@ +module tour/addressBook2a ----- Page 18 + +abstract sig Target { } +sig Addr extends Target { } +abstract sig Name extends Target { } + +sig Alias, Group extends Name { } + +sig Book { + addr: Name->Target +} + +pred show [b:Book] { some b.addr } + +// This command generates an instance similar to Fig 2.9 +run show for 3 but 1 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook2b.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook2b.als new file mode 100644 index 00000000..a6d1da91 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook2b.als @@ -0,0 +1,18 @@ +module tour/addressBook2b ----- Page 19 + +abstract sig Target { } +sig Addr extends Target { } +abstract sig Name extends Target { } + +sig Alias, Group extends Name { } + +sig Book { + addr: Name->Target +} { + no n: Name | n in n.^addr +} + +pred show [b:Book] { some b.addr } + +// This command generates an instance similar to Fig 2.10 +run show for 3 but 1 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook2c.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook2c.als new file mode 100644 index 00000000..33ded6b3 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook2c.als @@ -0,0 +1,18 @@ +module tour/addressBook2c ----- Page 20 + +abstract sig Target { } +sig Addr extends Target { } +abstract sig Name extends Target { } + +sig Alias, Group extends Name { } + +sig Book { + addr: Name->Target +} { + no n: Name | n in n.^addr +} + +pred show [b:Book] { some Alias.(b.addr) } + +// This command generates an instance similar to Fig 2.11 +run show for 3 but 1 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook2d.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook2d.als new file mode 100644 index 00000000..adac4fbe --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook2d.als @@ -0,0 +1,19 @@ +module tour/addressBook2d ----- Page 21 + +abstract sig Target { } +sig Addr extends Target { } +abstract sig Name extends Target { } + +sig Alias, Group extends Name { } + +sig Book { + addr: Name->Target +} { + no n: Name | n in n.^addr + all a: Alias | lone a.addr +} + +pred show [b:Book] { some Alias.(b.addr) } + +// This command generates an instance similar to Fig 2.12 +run show for 3 but 1 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook2e.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook2e.als new file mode 100644 index 00000000..3baea5ac --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook2e.als @@ -0,0 +1,56 @@ +module tour/addressBook2e --- this is the final model in Fig 2.14 + +abstract sig Target { } +sig Addr extends Target { } +abstract sig Name extends Target { } + +sig Alias, Group extends Name { } + +sig Book { + names: set Name, + addr: names->some Target +} { + no n: Name | n in n.^addr + all a: Alias | lone a.addr +} + +pred add [b, b': Book, n: Name, t: Target] { b'.addr = b.addr + n->t } +pred del [b, b': Book, n: Name, t: Target] { b'.addr = b.addr - n->t } +fun lookup [b: Book, n: Name] : set Addr { n.^(b.addr) & Addr } + +assert delUndoesAdd { + all b, b', b'': Book, n: Name, t: Target | + no n.(b.addr) and add [b, b', n, t] and del [b', b'', n, t] + implies + b.addr = b''.addr +} + +// This should not find any counterexample. +check delUndoesAdd for 3 + +assert addIdempotent { + all b, b', b'': Book, n: Name, t: Target | + add [b, b', n, t] and add [b', b'', n, t] + implies + b'.addr = b''.addr +} + +// This should not find any counterexample. +check addIdempotent for 3 + +assert addLocal { + all b, b': Book, n, n': Name, t: Target | + add [b, b', n, t] and n != n' + implies + lookup [b, n'] = lookup [b', n'] +} + +// This shows a counterexample similar to Fig 2.13 +check addLocal for 3 but 2 Book + +assert lookupYields { + all b: Book, n: b.names | some lookup [b,n] +} + +// This shows a counterexample similar to Fig 2.12 +check lookupYields for 4 but 1 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook3a.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook3a.als new file mode 100644 index 00000000..5ff9eee0 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook3a.als @@ -0,0 +1,38 @@ +module tour/addressBook3a ----- Page 25 + +open util/ordering [Book] as BookOrder + +abstract sig Target { } +sig Addr extends Target { } +abstract sig Name extends Target { } + +sig Alias, Group extends Name { } + +sig Book { + names: set Name, + addr: names->some Target +} { + no n: Name | n in n.^addr + all a: Alias | lone a.addr +} + +pred add [b, b': Book, n: Name, t: Target] { b'.addr = b.addr + n->t } +pred del [b, b': Book, n: Name, t: Target] { b'.addr = b.addr - n->t } +fun lookup [b: Book, n: Name] : set Addr { n.^(b.addr) & Addr } + +pred init [b: Book] { no b.addr } + +fact traces { + init [first] + all b: Book-last | + let b' = b.next | + some n: Name, t: Target | + add [b, b', n, t] or del [b, b', n, t] +} + +------------------------------------------------------ + +pred show { } + +// This command generates an instance similar to Fig 2.15 +run show for 4 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook3b.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook3b.als new file mode 100644 index 00000000..5c4b835d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook3b.als @@ -0,0 +1,76 @@ +module tour/addressBook3b ----- Page 26 + +open util/ordering [Book] as BookOrder + +abstract sig Target { } +sig Addr extends Target { } +abstract sig Name extends Target { } + +sig Alias, Group extends Name { } + +sig Book { + names: set Name, + addr: names->some Target +} { + no n: Name | n in n.^addr + all a: Alias | lone a.addr +} + +pred add [b, b': Book, n: Name, t: Target] { b'.addr = b.addr + n->t } +pred del [b, b': Book, n: Name, t: Target] { b'.addr = b.addr - n->t } +fun lookup [b: Book, n: Name] : set Addr { n.^(b.addr) & Addr } + +pred init [b: Book] { no b.addr } + +fact traces { + init [first] + all b: Book-last | + let b' = b.next | + some n: Name, t: Target | + add [b, b', n, t] or del [b, b', n, t] +} + +------------------------------------------------------ + +assert delUndoesAdd { + all b, b', b'': Book, n: Name, t: Target | + no n.(b.addr) and add [b, b', n, t] and del [b', b'', n, t] + implies + b.addr = b''.addr +} + +// This should not find any counterexample. +check delUndoesAdd for 3 + +------------------------------------------------------ + +assert addIdempotent { + all b, b', b'': Book, n: Name, t: Target | + add [b, b', n, t] and add [b', b'', n, t] + implies + b'.addr = b''.addr +} + +// This should not find any counterexample. +check addIdempotent for 3 + +------------------------------------------------------ + +assert addLocal { + all b, b': Book, n, n': Name, t: Target | + add [b, b', n, t] and n != n' + implies + lookup [b, n'] = lookup [b', n'] +} + +// This should not find any counterexample. +check addLocal for 3 but 2 Book + +------------------------------------------------------ + +assert lookupYields { + all b: Book, n: b.names | some lookup [b,n] +} + +// This shows a counterexample similar to Fig 2.16 +check lookupYields for 3 but 4 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook3c.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook3c.als new file mode 100644 index 00000000..284f8c36 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook3c.als @@ -0,0 +1,81 @@ +module tour/addressBook3c ----- Page 27 + +open util/ordering [Book] as BookOrder + +abstract sig Target { } +sig Addr extends Target { } +abstract sig Name extends Target { } + +sig Alias, Group extends Name { } + +sig Book { + names: set Name, + addr: names->some Target +} { + no n: Name | n in n.^addr + all a: Alias | lone a.addr +} + +pred add [b, b': Book, n: Name, t: Target] { + t in Addr or some lookup [b, Name&t] + b'.addr = b.addr + n->t +} + +pred del [b, b': Book, n: Name, t: Target] { b'.addr = b.addr - n->t } + +fun lookup [b: Book, n: Name] : set Addr { n.^(b.addr) & Addr } + +pred init [b: Book] { no b.addr } + +fact traces { + init [first] + all b: Book-last | + let b' = b.next | + some n: Name, t: Target | + add [b, b', n, t] or del [b, b', n, t] +} + +------------------------------------------------------ + +assert delUndoesAdd { + all b, b', b'': Book, n: Name, t: Target | + no n.(b.addr) and add [b, b', n, t] and del [b', b'', n, t] + implies + b.addr = b''.addr +} + +// This should not find any counterexample. +check delUndoesAdd for 3 + +------------------------------------------------------ + +assert addIdempotent { + all b, b', b'': Book, n: Name, t: Target | + add [b, b', n, t] and add [b', b'', n, t] + implies + b'.addr = b''.addr +} + +// This should not find any counterexample. +check addIdempotent for 3 + +------------------------------------------------------ + +assert addLocal { + all b, b': Book, n, n': Name, t: Target | + add [b, b', n, t] and n != n' + implies + lookup [b, n'] = lookup [b', n'] +} + +// This should not find any counterexample. +check addLocal for 3 but 2 Book + +------------------------------------------------------ + +assert lookupYields { + all b: Book, n: b.names | some lookup [b,n] +} + +// This shows a counterexample similar to Fig 2.17 +check lookupYields for 3 but 4 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook3d.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook3d.als new file mode 100644 index 00000000..aceac514 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/addressBook3d.als @@ -0,0 +1,87 @@ +module tour/addressBook3d ----- this is the final model in fig 2.18 + +open util/ordering [Book] as BookOrder + +abstract sig Target { } +sig Addr extends Target { } +abstract sig Name extends Target { } + +sig Alias, Group extends Name { } + +sig Book { + names: set Name, + addr: names->some Target +} { + no n: Name | n in n.^addr + all a: Alias | lone a.addr +} + +pred add [b, b': Book, n: Name, t: Target] { + t in Addr or some lookup [b, Name&t] + b'.addr = b.addr + n->t +} + +pred del [b, b': Book, n: Name, t: Target] { + no b.addr.n or some n.(b.addr) - t + b'.addr = b.addr - n->t +} + +fun lookup [b: Book, n: Name] : set Addr { n.^(b.addr) & Addr } + +pred init [b: Book] { no b.addr } + +fact traces { + init [first] + all b: Book-last | + let b' = b.next | + some n: Name, t: Target | + add [b, b', n, t] or del [b, b', n, t] +} + +------------------------------------------------------ + +assert delUndoesAdd { + all b, b', b'': Book, n: Name, t: Target | + no n.(b.addr) and add [b, b', n, t] and del [b', b'', n, t] + implies + b.addr = b''.addr +} + +// This should not find any counterexample. +check delUndoesAdd for 3 + +------------------------------------------------------ + +assert addIdempotent { + all b, b', b'': Book, n: Name, t: Target | + add [b, b', n, t] and add [b', b'', n, t] + implies + b'.addr = b''.addr +} + +// This should not find any counterexample. +check addIdempotent for 3 + +------------------------------------------------------ + +assert addLocal { + all b, b': Book, n, n': Name, t: Target | + add [b, b', n, t] and n != n' + implies + lookup [b, n'] = lookup [b', n'] +} + +// This should not find any counterexample. +check addLocal for 3 but 2 Book + +------------------------------------------------------ + +assert lookupYields { + all b: Book, n: b.names | some lookup [b,n] +} + +// This should not find any counterexample. +check lookupYields for 3 but 4 Book + +// This should not find any counterexample. +check lookupYields for 6 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/theme.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/theme.thm new file mode 100644 index 00000000..2b839993 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter2/theme.thm @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter4/filesystem.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter4/filesystem.als new file mode 100644 index 00000000..c45e776b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter4/filesystem.als @@ -0,0 +1,28 @@ +module chapter4/filesystem ----- The model from page 125 + +abstract sig Object {} + +sig Dir extends Object {contents: set Object} + +one sig Root extends Dir { } + +sig File extends Object {} + +fact { + Object in Root.*contents + } + +assert SomeDir { + all o: Object - Root | some contents.o + } +check SomeDir // This assertion is valid + +assert RootTop { + no o: Object | Root in o.contents + } +check RootTop // This assertion should produce a counterexample + +assert FileInDir { + all f: File | some contents.f + } +check FileInDir // This assertion is valid diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter4/grandpa1.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter4/grandpa1.als new file mode 100644 index 00000000..c05c85c9 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter4/grandpa1.als @@ -0,0 +1,44 @@ +module language/grandpa1 ---- Page 84, 85 + +abstract sig Person { + father: lone Man, + mother: lone Woman + } + +sig Man extends Person { + wife: lone Woman + } + +sig Woman extends Person { + husband: lone Man + } + +fact { + no p: Person | p in p.^(mother+father) + wife = ~husband + } + +assert NoSelfFather { + no m: Man | m = m.father + } + +// This should not find any counterexample. +check NoSelfFather + +fun grandpas [p: Person] : set Person { + p.(mother+father).father + } + +pred ownGrandpa [p: Person] { + p in p.grandpas + } + +// This should not find any instance. +run ownGrandpa for 4 Person + +assert NoSelfGrandpa { + no p: Person | p in p.grandpas + } + +// This should not find any counterexample +check NoSelfGrandpa for 4 Person diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter4/grandpa2.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter4/grandpa2.als new file mode 100644 index 00000000..08dda731 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter4/grandpa2.als @@ -0,0 +1,38 @@ +module language/grandpa2 ---- Page 86 + +abstract sig Person { + father: lone Man, + mother: lone Woman + } + +sig Man extends Person { + wife: lone Woman + } + +sig Woman extends Person { + husband: lone Man + } + +fact { + no p: Person | p in p.^(mother+father) + wife = ~husband + } + +assert NoSelfFather { + no m: Man | m = m.father + } + +// This should not find any counterexample. +check NoSelfFather + +fun grandpas [p: Person] : set Person { + let parent = mother + father + father.wife + mother.husband | + p.parent.parent & Man + } + +pred ownGrandpa [p: Person] { + p in p.grandpas + } + +// This generates an instance similar to Fig 4.2 +run ownGrandpa for 4 Person diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter4/grandpa3.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter4/grandpa3.als new file mode 100644 index 00000000..d9147cbf --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter4/grandpa3.als @@ -0,0 +1,70 @@ +module language/grandpa3 ---- the final model in fig 4.4 + +abstract sig Person { + father: lone Man, + mother: lone Woman + } + +sig Man extends Person { + wife: lone Woman + } + +sig Woman extends Person { + husband: lone Man + } + +fact Biology { + no p: Person | p in p.^(mother+father) + } + +fact Terminology { + wife = ~husband + } + +fact SocialConvention { + no (wife+husband) & ^(mother+father) + } + +------------------------------------------ + +assert NoSelfFather { + no m: Man | m = m.father + } + +// This should not find any counterexample. +check NoSelfFather + +------------------------------------------ + +fun grandpas [p: Person] : set Person { + let parent = mother + father + father.wife + mother.husband | + p.parent.parent & Man + } + +pred ownGrandpa [p: Person] { + p in p.grandpas + } + +// This generates an instance similar to Fig 4.3 +run ownGrandpa for 4 Person + +------------------------------------------ + +pred SocialConvention1 { + no (wife + husband) & ^(mother + father) + } + +pred SocialConvention2 { + let parent = mother + father { + no m: Man | some m.wife and m.wife in m.*parent.mother + no w: Woman | some w.husband and w.husband in w.*parent.father + } + } + +// This assertion was described on page 90. +assert Same { + SocialConvention1 iff SocialConvention2 + } + +// This should not find any counterexample +check Same diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter4/lights.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter4/lights.als new file mode 100644 index 00000000..24997705 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter4/lights.als @@ -0,0 +1,41 @@ +module chapter4/lights ----- The model from page 127 + +abstract sig Color {} + +one sig Red, Yellow, Green extends Color {} + +fun colorSequence: Color -> Color { + Color <: iden + Red->Green + Green->Yellow + Yellow->Red + } + +sig Light {} +sig LightState {color: Light -> one Color} +sig Junction {lights: set Light} + +fun redLights [s: LightState]: set Light { s.color.Red } + +pred mostlyRed [s: LightState, j: Junction] { + lone j.lights - redLights[s] + } + +pred trans [s, s': LightState, j: Junction] { + lone x: j.lights | s.color[x] != s'.color[x] + all x: j.lights | + let step = s.color[x] -> s'.color[x] { + step in colorSequence + step in Red->(Color-Red) => j.lights in redLights[s] + } + } + +assert Safe { + all s, s': LightState, j: Junction | + mostlyRed [s, j] and trans [s, s', j] => mostlyRed [s', j] + } + +check Safe for 3 but 1 Junction + +//assert ColorSequenceDeterministic { +// all c: Color | lone c.colorSequence +// } +// +//check ColorSequenceDeterministic diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter5/addressBook.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter5/addressBook.als new file mode 100644 index 00000000..5d7dee56 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter5/addressBook.als @@ -0,0 +1,26 @@ +module chapter5/addressBook --- the model in fig 5.1 + +abstract sig Target {} + +sig Addr extends Target {} +sig Name extends Target {} +sig Book {addr: Name -> Target} + +fact Acyclic {all b: Book | no n: Name | n in n.^(b.addr)} + +pred add [b, b': Book, n: Name, t: Target] { + b'.addr = b.addr + n -> t + } + +// This command should produce an instance similar to Fig 5.2 +run add for 3 but 2 Book + +fun lookup [b: Book, n: Name]: set Addr {n.^(b.addr) & Addr} + +assert addLocal { + all b,b': Book, n,n': Name, t: Target | + add [b,b',n,t] and n != n' => lookup [b,n'] = lookup [b',n'] + } + +// This command should produce a counterexample similar to Fig 5.3 +check addLocal for 3 but 2 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter5/lists.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter5/lists.als new file mode 100644 index 00000000..79cbd0da --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter5/lists.als @@ -0,0 +1,23 @@ +module chapter5/lists ---- page 157 + +some sig Element {} + +abstract sig List {} +one sig EmptyList extends List {} +sig NonEmptyList extends List { + element: Element, + rest: List + } + +fact ListGenerator { + all list: List, e: Element | + some list': List | list'.rest = list and list'.element = e + } + +assert FalseAssertion { + all list: List | list != list + } + +// This check finds no counterexample since +// the only possible counterexamples are infinite. +check FalseAssertion diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter5/sets1.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter5/sets1.als new file mode 100644 index 00000000..dc998820 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter5/sets1.als @@ -0,0 +1,16 @@ +module chapter5/sets1 ----- page 156 + +sig Set { + elements: set Element +} + +sig Element {} + +assert Closed { + all s0, s1: Set | + some s2: Set | + s2.elements = s0.elements + s1.elements + } + +// This check should produce a counterexample +check Closed diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter5/sets2.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter5/sets2.als new file mode 100644 index 00000000..265a1e64 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter5/sets2.als @@ -0,0 +1,21 @@ +module chapter5/sets2 ----- page 157 + +sig Set { + elements: set Element +} + +sig Element {} + +assert Closed { + all s0, s1: Set | + some s2: Set | + s2.elements = s0.elements + s1.elements + } + +fact SetGenerator { + some s: Set | no s.elements + all s: Set, e: Element | some s': Set | s'.elements = s.elements + e + } + +// This check should not produce a counterexample +check Closed for 4 Element, 16 Set diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/hotel.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/hotel.thm new file mode 100644 index 00000000..acdb8d09 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/hotel.thm @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/hotel1.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/hotel1.als new file mode 100644 index 00000000..22610689 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/hotel1.als @@ -0,0 +1,101 @@ +module chapter6/hotel1 --- the model up to the top of page 191 + +open util/ordering[Time] as to +open util/ordering[Key] as ko + +sig Key {} +sig Time {} + +sig Room { + keys: set Key, + currentKey: keys one -> Time + } + +fact DisjointKeySets { + -- each key belongs to at most one room + Room<:keys in Room lone-> Key + } + +one sig FrontDesk { + lastKey: (Room -> lone Key) -> Time, + occupant: (Room -> Guest) -> Time + } + +sig Guest { + keys: Key -> Time + } + +fun nextKey [k: Key, ks: set Key]: set Key { + min [k.nexts & ks] + } + +pred init [t: Time] { + no Guest.keys.t + no FrontDesk.occupant.t + all r: Room | FrontDesk.lastKey.t [r] = r.currentKey.t + } + +pred entry [t, t': Time, g: Guest, r: Room, k: Key] { + k in g.keys.t + let ck = r.currentKey | + (k = ck.t and ck.t' = ck.t) or + (k = nextKey[ck.t, r.keys] and ck.t' = k) + noRoomChangeExcept [t, t', r] + noGuestChangeExcept [t, t', none] + noFrontDeskChange [t, t'] + } + +pred noFrontDeskChange [t, t': Time] { + FrontDesk.lastKey.t = FrontDesk.lastKey.t' + FrontDesk.occupant.t = FrontDesk.occupant.t' + } + +pred noRoomChangeExcept [t, t': Time, rs: set Room] { + all r: Room - rs | r.currentKey.t = r.currentKey.t' + } + +pred noGuestChangeExcept [t, t': Time, gs: set Guest] { + all g: Guest - gs | g.keys.t = g.keys.t' + } + +pred checkout [t, t': Time, g: Guest] { + let occ = FrontDesk.occupant { + some occ.t.g + occ.t' = occ.t - Room ->g + } + FrontDesk.lastKey.t = FrontDesk.lastKey.t' + noRoomChangeExcept [t, t', none] + noGuestChangeExcept [t, t', none] + } + +pred checkin [t, t': Time, g: Guest, r: Room, k: Key] { + g.keys.t' = g.keys.t + k + let occ = FrontDesk.occupant { + no occ.t [r] + occ.t' = occ.t + r -> g + } + let lk = FrontDesk.lastKey { + lk.t' = lk.t ++ r -> k + k = nextKey [lk.t [r], r.keys] + } + noRoomChangeExcept [t, t', none] + noGuestChangeExcept [t, t', g] + } + +fact traces { + init [first] + all t: Time-last | let t' = t.next | + some g: Guest, r: Room, k: Key | + entry [t, t', g, r, k] + or checkin [t, t', g, r, k] + or checkout [t, t', g] + } + +assert NoBadEntry { + all t: Time, r: Room, g: Guest, k: Key | + let t' = t.next, o = FrontDesk.occupant.t[r] | + entry [t, t', g, r, k] and some o => g in o + } + +// This generates a counterexample similar to Fig 6.6 +check NoBadEntry for 3 but 2 Room, 2 Guest, 5 Time diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/hotel2.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/hotel2.als new file mode 100644 index 00000000..09378f2e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/hotel2.als @@ -0,0 +1,110 @@ +module chapter6/hotel2 --- the final model in Fig 6.7 + +open util/ordering[Time] as to +open util/ordering[Key] as ko + +sig Key {} +sig Time {} + +sig Room { + keys: set Key, + currentKey: keys one -> Time + } + +fact DisjointKeySets { + -- each key belongs to at most one room + Room<:keys in Room lone-> Key + } + +one sig FrontDesk { + lastKey: (Room -> lone Key) -> Time, + occupant: (Room -> Guest) -> Time + } + +sig Guest { + keys: Key -> Time + } + +fun nextKey [k: Key, ks: set Key]: set Key { + min [k.nexts & ks] + } + +pred init [t: Time] { + no Guest.keys.t + no FrontDesk.occupant.t + all r: Room | FrontDesk.lastKey.t [r] = r.currentKey.t + } + +pred entry [t, t': Time, g: Guest, r: Room, k: Key] { + k in g.keys.t + let ck = r.currentKey | + (k = ck.t and ck.t' = ck.t) or + (k = nextKey[ck.t, r.keys] and ck.t' = k) + noRoomChangeExcept [t, t', r] + noGuestChangeExcept [t, t', none] + noFrontDeskChange [t, t'] + } + +pred noFrontDeskChange [t, t': Time] { + FrontDesk.lastKey.t = FrontDesk.lastKey.t' + FrontDesk.occupant.t = FrontDesk.occupant.t' + } + +pred noRoomChangeExcept [t, t': Time, rs: set Room] { + all r: Room - rs | r.currentKey.t = r.currentKey.t' + } + +pred noGuestChangeExcept [t, t': Time, gs: set Guest] { + all g: Guest - gs | g.keys.t = g.keys.t' + } + +pred checkout [t, t': Time, g: Guest] { + let occ = FrontDesk.occupant { + some occ.t.g + occ.t' = occ.t - Room ->g + } + FrontDesk.lastKey.t = FrontDesk.lastKey.t' + noRoomChangeExcept [t, t', none] + noGuestChangeExcept [t, t', none] + } + +pred checkin [t, t': Time, g: Guest, r: Room, k: Key] { + g.keys.t' = g.keys.t + k + let occ = FrontDesk.occupant { + no occ.t [r] + occ.t' = occ.t + r -> g + } + let lk = FrontDesk.lastKey { + lk.t' = lk.t ++ r -> k + k = nextKey [lk.t [r], r.keys] + } + noRoomChangeExcept [t, t', none] + noGuestChangeExcept [t, t', g] + } + +fact traces { + init [first] + all t: Time-last | let t' = t.next | + some g: Guest, r: Room, k: Key | + entry [t, t', g, r, k] + or checkin [t, t', g, r, k] + or checkout [t, t', g] + } + +fact NoIntervening { + all t: Time-last | let t' = t.next, t" = t'.next | + all g: Guest, r: Room, k: Key | + checkin [t, t', g, r, k] => (entry [t', t", g, r, k] or no t") + } + +assert NoBadEntry { + all t: Time, r: Room, g: Guest, k: Key | + let t' = t.next, o = FrontDesk.occupant.t[r] | + entry [t, t', g, r, k] and some o => g in o + } + +// After adding the NoIntervening fact, +// these commands no longer generate counterexamples +check NoBadEntry for 3 but 2 Room, 2 Guest, 5 Time +check NoBadEntry for 3 but 3 Room, 3 Guest, 7 Time +check NoBadEntry for 5 but 3 Room, 3 Guest, 9 Time diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/hotel3.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/hotel3.als new file mode 100644 index 00000000..b3ad4b49 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/hotel3.als @@ -0,0 +1,92 @@ +module chapter6/hotel3 --- model in Fig 6.10 without the NonIntervening fact + +open util/ordering[Time] as to +open util/ordering[Key] as ko + +sig Key, Time {} + +sig Room { + keys: set Key, + currentKey: keys one -> Time + } + +fact { + Room <: keys in Room lone -> Key + } + +one sig FrontDesk { + lastKey: (Room -> lone Key) -> Time, + occupant: (Room -> Guest) -> Time + } + +sig Guest { + keys: Key -> Time + } + +fun nextKey [k: Key, ks: set Key]: set Key { + min [k.nexts & ks] + } + +pred init [t: Time] { + no Guest.keys.t + no FrontDesk.occupant.t + all r: Room | FrontDesk.lastKey.t [r] = r.currentKey.t + } + +abstract sig Event { + pre, post: Time, + guest: Guest + } + +abstract sig RoomKeyEvent extends Event { + room: Room, + key: Key + } + +sig Entry extends RoomKeyEvent { } { + key in guest.keys.pre + let ck = room.currentKey | + (key = ck.pre and ck.post = ck.pre) or + (key = nextKey[ck.pre, room.keys] and ck.post = key) + currentKey.post = currentKey.pre ++ room->key + } + +sig Checkin extends RoomKeyEvent { } { + keys.post = keys.pre + guest -> key + let occ = FrontDesk.occupant { + no occ.pre [room] + occ.post = occ.pre + room -> guest + } + let lk = FrontDesk.lastKey { + lk.post = lk.pre ++ room -> key + key = nextKey [lk.pre [room], room.keys] + } + } + +sig Checkout extends Event { } { + let occ = FrontDesk.occupant { + some occ.pre.guest + occ.post = occ.pre - Room -> guest + } + } + +fact Traces { + init [first] + all t: Time-last | + let t' = t.next | + some e: Event { + e.pre = t and e.post = t' + currentKey.t != currentKey.t' => e in Entry + occupant.t != occupant.t' => e in Checkin + Checkout + (lastKey.t != lastKey.t' or keys.t != keys.t') => e in Checkin + } + } + +assert NoBadEntry { + all e: Entry | + let o=FrontDesk.occupant.(e.pre) [e.room] | + some o => e.guest in o + } + +// This generates a counterexample similar to Fig 6.13 +check NoBadEntry for 5 but 3 Room, 3 Guest, 5 Time, 4 Event diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/hotel4.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/hotel4.als new file mode 100644 index 00000000..35f3566b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/hotel4.als @@ -0,0 +1,103 @@ +module chapter6/hotel4 --- model in Fig 6.10 with the NonIntervening fact + +open util/ordering[Time] as to +open util/ordering[Key] as ko + +sig Key, Time {} + +sig Room { + keys: set Key, + currentKey: keys one -> Time + } + +fact { + Room <: keys in Room lone -> Key + } + +one sig FrontDesk { + lastKey: (Room -> lone Key) -> Time, + occupant: (Room -> Guest) -> Time + } + +sig Guest { + keys: Key -> Time + } + +fun nextKey [k: Key, ks: set Key]: set Key { + min [k.nexts & ks] + } + +pred init [t: Time] { + no Guest.keys.t + no FrontDesk.occupant.t + all r: Room | FrontDesk.lastKey.t [r] = r.currentKey.t + } + +abstract sig Event { + pre, post: Time, + guest: Guest + } + +abstract sig RoomKeyEvent extends Event { + room: Room, + key: Key + } + +sig Entry extends RoomKeyEvent { } { + key in guest.keys.pre + let ck = room.currentKey | + (key = ck.pre and ck.post = ck.pre) or + (key = nextKey[ck.pre, room.keys] and ck.post = key) + currentKey.post = currentKey.pre ++ room->key + } + +sig Checkin extends RoomKeyEvent { } { + keys.post = keys.pre + guest -> key + let occ = FrontDesk.occupant { + no occ.pre [room] + occ.post = occ.pre + room -> guest + } + let lk = FrontDesk.lastKey { + lk.post = lk.pre ++ room -> key + key = nextKey [lk.pre [room], room.keys] + } + } + +sig Checkout extends Event { } { + let occ = FrontDesk.occupant { + some occ.pre.guest + occ.post = occ.pre - Room -> guest + } + } + +fact Traces { + init [first] + all t: Time-last | + let t' = t.next | + some e: Event { + e.pre = t and e.post = t' + currentKey.t != currentKey.t' => e in Entry + occupant.t != occupant.t' => e in Checkin + Checkout + (lastKey.t != lastKey.t' or keys.t != keys.t') => e in Checkin + } + } + +assert NoBadEntry { + all e: Entry | + let o=FrontDesk.occupant.(e.pre) [e.room] | + some o => e.guest in o + } + +fact NoIntervening { + all c: Checkin | + c.post = last + or some e: Entry { + e.pre = c.post + e.room = c.room + e.guest = c.guest + } + } + +// After adding the NoIntervening fact, +// this command no longer generates a counterexample +check NoBadEntry for 5 but 3 Room, 3 Guest, 9 Time, 8 Event diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/mediaAssets.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/mediaAssets.als new file mode 100644 index 00000000..668b3130 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/mediaAssets.als @@ -0,0 +1,117 @@ +module chapter6/mediaAssets + +sig ApplicationState { + catalogs: set Catalog, + catalogState: catalogs -> one CatalogState, + currentCatalog: catalogs, + buffer: set Asset + } + +sig Catalog, Asset {} + +sig CatalogState { + assets: set Asset, + disj hidden, showing: set assets, + selection: set assets + Undefined + } { + hidden+showing = assets + } + +one sig Undefined {} + +pred catalogInv [cs: CatalogState] { + cs.selection = Undefined or (some cs.selection and cs.selection in cs.showing) + } + +pred appInv [xs: ApplicationState] { + all cs: xs.catalogs | catalogInv [xs.catalogState[cs]] + } + +pred showSelected [cs, cs': CatalogState] { + cs.selection != Undefined + cs'.showing = cs.selection + cs'.selection = cs.selection + cs'.assets = cs.assets + } + +pred hideSelected [cs, cs': CatalogState] { + cs.selection != Undefined + cs'.hidden = cs.hidden + cs.selection + cs'.selection = Undefined + cs'.assets = cs.assets + } + +pred cut [xs, xs': ApplicationState] { + let cs = xs.currentCatalog.(xs.catalogState), sel = cs.selection { + sel != Undefined + xs'.buffer = sel + some cs': CatalogState { + cs'.assets = cs.assets - sel + cs'.showing = cs.showing - sel + cs'.selection = Undefined + xs'.catalogState = xs.catalogState ++ xs.currentCatalog -> cs' + } + } + xs'.catalogs = xs.catalogs + xs'.currentCatalog = xs.currentCatalog + } + +pred paste [xs, xs': ApplicationState] { + let cs = xs.currentCatalog.(xs.catalogState), buf = xs.buffer { + xs'.buffer = buf + some cs': CatalogState { + cs'.assets = cs.assets + buf + cs'.showing = cs.showing + (buf - cs.assets) + cs'.selection = buf - cs.assets + xs'.catalogState = xs.catalogState ++ xs.currentCatalog -> cs' + } + } + xs'.catalogs = xs.catalogs + xs'.currentCatalog = xs.currentCatalog + } + +assert HidePreservesInv { + all cs, cs': CatalogState | + catalogInv [cs] and hideSelected [cs, cs'] => catalogInv [cs'] + } + +// This check should not find any counterexample +check HidePreservesInv + +pred sameApplicationState [xs, xs': ApplicationState] { + xs'.catalogs = xs.catalogs + all c: xs.catalogs | sameCatalogState [c.(xs.catalogState), c.(xs'.catalogState)] + xs'.currentCatalog = xs.currentCatalog + xs'.buffer = xs.buffer + } + +pred sameCatalogState [cs, cs': CatalogState] { + cs'.assets = cs.assets + cs'.showing = cs.showing + cs'.selection = cs.selection + } + +assert CutPaste { + all xs, xs', xs": ApplicationState | + (appInv [xs] and cut [xs, xs'] and paste [xs', xs"]) => sameApplicationState [xs, xs"] + } + +// This check should find a counterexample +check CutPaste + +assert PasteCut { + all xs, xs', xs": ApplicationState | + (appInv [xs] and paste [xs, xs'] and cut [xs', xs"]) => sameApplicationState [xs, xs"] + } + +// This check should find a counterexample +check PasteCut + +assert PasteNotAffectHidden { + all xs, xs': ApplicationState | + (appInv [xs] and paste [xs, xs']) => + let c = xs.currentCatalog | xs'.catalogState[c].hidden = xs.catalogState[c].hidden + } + +// This check should not find any counterexample +check PasteNotAffectHidden diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/memory/abstractMemory.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/memory/abstractMemory.als new file mode 100644 index 00000000..3d676d50 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/memory/abstractMemory.als @@ -0,0 +1,33 @@ +module chapter6/memory/abstractMemory [Addr, Data] ----- the model from page 217 + +sig Memory { + data: Addr -> lone Data + } + +pred init [m: Memory] { + no m.data + } + +pred write [m, m': Memory, a: Addr, d: Data] { + m'.data = m.data ++ a -> d + } + +pred read [m: Memory, a: Addr, d: Data] { + let d' = m.data [a] | some d' implies d = d' + } + +fact Canonicalize { + no disj m, m': Memory | m.data = m'.data + } + +// This command should not find any counterexample +WriteRead: check { + all m, m': Memory, a: Addr, d1, d2: Data | + write [m, m', a, d1] and read [m', a, d2] => d1 = d2 + } + +// This command should not find any counterexample +WriteIdempotent: check { + all m, m', m": Memory, a: Addr, d: Data | + write [m, m', a, d] and write [m', m", a, d] => m' = m" + } diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/memory/cacheMemory.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/memory/cacheMemory.als new file mode 100644 index 00000000..c95fe22b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/memory/cacheMemory.als @@ -0,0 +1,43 @@ +module chapter6/memory/cacheMemory [Addr, Data] ----- the model from page 219 + +sig CacheSystem { + main, cache: Addr -> lone Data + } + +pred init [c: CacheSystem] { + no c.main + c.cache + } + +pred write [c, c': CacheSystem, a: Addr, d: Data] { + c'.main = c.main + c'.cache = c.cache ++ a -> d + } + +pred read [c: CacheSystem, a: Addr, d: Data] { + some d + d = c.cache [a] + } + +pred load [c, c': CacheSystem] { + some addrs: set c.main.Data - c.cache.Data | + c'.cache = c.cache ++ addrs <: c.main + c'.main = c.main + } + +pred flush [c, c': CacheSystem] { + some addrs: some c.cache.Data { + c'.main = c.main ++ addrs <: c.cache + c'.cache = c.cache - addrs -> Data + } + } + +// This command should not find any counterexample +LoadNotObservable: check { + all c, c', c": CacheSystem, a1, a2: Addr, d1, d2, d3: Data | + { + read [c, a2, d2] + write [c, c', a1, d1] + load [c', c"] + read [c", a2, d3] + } implies d3 = (a1=a2 => d1 else d2) + } diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/memory/checkCache.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/memory/checkCache.als new file mode 100644 index 00000000..8214389b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/memory/checkCache.als @@ -0,0 +1,34 @@ +module chapter6/memory/checkCache [Addr, Data] + +open chapter6/memory/cacheMemory [Addr, Data] as cache +open chapter6/memory/abstractMemory [Addr, Data] as amemory + +fun alpha [c: CacheSystem]: Memory { + {m: Memory | m.data = c.main ++ c.cache} + } + +// This check should not produce a counterexample +ReadOK: check { + // introduction of m, m' ensures that they exist, and gives witnesses if counterexample + all c: CacheSystem, a: Addr, d: Data, m: Memory | + cache/read [c, a, d] and m = alpha [c] => amemory/read [m, a, d] + } + +// This check should not produce a counterexample +WriteOK: check { + all c, c': CacheSystem, a: Addr, d: Data, m, m': Memory | + cache/write [c, c', a, d] and m = alpha [c] and m' = alpha [c'] + => amemory/write [m, m', a, d] + } + +// This check should not produce a counterexample +LoadOK: check { + all c, c': CacheSystem, m, m': Memory | + cache/load [c, c'] and m = alpha [c] and m' = alpha [c'] => m = m' + } + +// This check should not produce a counterexample +FlushOK: check { + all c, c': CacheSystem, m, m': Memory | + cache/flush [c, c'] and m = alpha [c] and m' = alpha [c'] => m = m' + } diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/memory/checkFixedSize.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/memory/checkFixedSize.als new file mode 100644 index 00000000..20d291d1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/memory/checkFixedSize.als @@ -0,0 +1,28 @@ +module chapter6/memory/checkFixedSize [Addr, Data] + +open chapter6/memory/fixedSizeMemory_H [Addr, Data] as fmemory +open chapter6/memory/abstractMemory [Addr, Data] as amemory + +// define abstraction function from history-extended concrete state to abstract state +pred alpha [fm: fmemory/Memory_H, am: amemory/Memory] { + am.data = fm.data - (fm.unwritten -> Data) + } + +// This check should not find a counterexample +initOk: check { + all fm: fmemory/Memory_H, am: amemory/Memory | + fmemory/init [fm] and alpha [fm, am] => amemory/init [am] + } + +// This check should not find a counterexample +readOk: check { + all fm: fmemory/Memory_H, a: Addr, d: Data, am: amemory/Memory | + fmemory/read [fm, a, d] and alpha [fm, am] => amemory/read [am, a, d] + } + +// This check should not find a counterexample +writeOk: check { + all fm, fm': fmemory/Memory_H, a: Addr, d: Data, am, am': amemory/Memory | + fmemory/write [fm, fm', a, d] and alpha [fm, am] and alpha [fm', am'] + implies amemory/write [am, am', a, d] + } diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/memory/fixedSizeMemory.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/memory/fixedSizeMemory.als new file mode 100644 index 00000000..df6ab2a9 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/memory/fixedSizeMemory.als @@ -0,0 +1,21 @@ +module chapter6/memory/fixedSizeMemory [Addr, Data] + +sig Memory { + data: Addr -> one Data + } + +pred init [m: Memory] { + // This predicate is empty in order to allow non-deterministic initialization + } + +pred write [m, m': Memory, a: Addr, d: Data] { + m'.data = m.data ++ a -> d + } + +pred read [m: Memory, a: Addr, d: Data] { + d = m.data [a] + } + +fact Canonicalize { + no disj m, m': Memory | m.data = m'.data + } diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/memory/fixedSizeMemory_H.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/memory/fixedSizeMemory_H.als new file mode 100644 index 00000000..15785991 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/memory/fixedSizeMemory_H.als @@ -0,0 +1,21 @@ +module chapter6/memory/fixedSizeMemory_H [Addr, Data] + +open chapter6/memory/fixedSizeMemory [Addr, Data] as memory + +sig Memory_H extends memory/Memory { + unwritten: set Addr + } + +pred init [m: Memory_H] { + memory/init [m] + m.unwritten = Addr + } + +pred read [m: Memory_H, a: Addr, d: Data] { + memory/read [m, a, d] + } + +pred write [m, m': Memory_H, a: Addr, d: Data] { + memory/write [m, m', a, d] + m'.unwritten = m.unwritten - a + } diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/ringElection.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/ringElection.thm new file mode 100644 index 00000000..0d172180 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/ringElection.thm @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/ringElection1.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/ringElection1.als new file mode 100644 index 00000000..043b6a07 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/ringElection1.als @@ -0,0 +1,57 @@ +module chapter6/ringElection1 --- the version up to the top of page 181 + +open util/ordering[Time] as TO +open util/ordering[Process] as PO + +sig Time {} + +sig Process { + succ: Process, + toSend: Process -> Time, + elected: set Time + } + +fact ring { + all p: Process | Process in p.^succ + } + +pred init [t: Time] { + all p: Process | p.toSend.t = p + } + +pred step [t, t': Time, p: Process] { + let from = p.toSend, to = p.succ.toSend | + some id: from.t { + from.t' = from.t - id + to.t' = to.t + (id - p.succ.prevs) + } + } + +fact defineElected { + no elected.first + all t: Time-first | elected.t = {p: Process | p in p.toSend.t - p.toSend.(t.prev)} + } + +fact traces { + init [first] + all t: Time-last | + let t' = t.next | + all p: Process | + step [t, t', p] or step [t, t', succ.p] or skip [t, t', p] + } + +pred skip [t, t': Time, p: Process] { + p.toSend.t = p.toSend.t' + } + +pred show { some elected } +run show for 3 Process, 4 Time +// This generates an instance similar to Fig 6.4 + +assert AtMostOneElected { lone elected.Time } +check AtMostOneElected for 3 Process, 7 Time +// This should not find any counterexample + +assert AtLeastOneElected { some t: Time | some elected.t } +check AtLeastOneElected for 3 Process, 7 Time +// This generates a counterexample in which nothing happens diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/ringElection2.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/ringElection2.als new file mode 100644 index 00000000..16bee928 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/book/chapter6/ringElection2.als @@ -0,0 +1,74 @@ +module chapter6/ringElection2 --- the final version (as depicted in Fig 6.1) + +open util/ordering[Time] as TO +open util/ordering[Process] as PO + +sig Time {} + +sig Process { + succ: Process, + toSend: Process -> Time, + elected: set Time + } + +fact ring { + all p: Process | Process in p.^succ + } + +pred init [t: Time] { + all p: Process | p.toSend.t = p + } + +pred step [t, t': Time, p: Process] { + let from = p.toSend, to = p.succ.toSend | + some id: from.t { + from.t' = from.t - id + to.t' = to.t + (id - p.succ.prevs) + } + } + +fact defineElected { + no elected.first + all t: Time-first | elected.t = {p: Process | p in p.toSend.t - p.toSend.(t.prev)} + } + +fact traces { + init [first] + all t: Time-last | + let t' = t.next | + all p: Process | + step [t, t', p] or step [t, t', succ.p] or skip [t, t', p] + } + +pred skip [t, t': Time, p: Process] { + p.toSend.t = p.toSend.t' + } + +pred show { some elected } +run show for 3 Process, 4 Time +// This generates an instance similar to Fig 6.4 + +assert AtMostOneElected { lone elected.Time } +check AtMostOneElected for 3 Process, 7 Time +// This should not find any counterexample + +pred progress { + all t: Time - TO/last | + let t' = TO/next [t] | + some Process.toSend.t => some p: Process | not skip [t, t', p] + } + +assert AtLeastOneElected { progress => some elected.Time } +check AtLeastOneElected for 3 Process, 7 Time +// This should not find any counterexample + +pred looplessPath { no disj t, t': Time | toSend.t = toSend.t' } + +// This produces an instance +run looplessPath for 3 Process, 12 Time + +// This does not produce an instance +run looplessPath for 3 Process, 13 Time + +// Therefore, we can conclude that a scope of 12 for Time is +// sufficient to reach all states of the protocol for a three-node ring. diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/dijkstra.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/dijkstra.als new file mode 100644 index 00000000..ab342811 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/dijkstra.als @@ -0,0 +1,120 @@ +module examples/algorithms/dijkstra + +/* + * Models how mutexes are grabbed and released by processes, and + * how Dijkstra's mutex ordering criterion can prevent deadlocks. + * + * For a detailed description, see: + * E. W. Dijkstra, Cooperating sequential processes. Technological + * University, Eindhoven, The Netherlands, September 1965. + * Reprinted in Programming Languages, F. Genuys, Ed., Academic + * Press, New York, 1968, 43-112. + * + * Acknowledgements to Ulrich Geilmann for finding and fixing a bug + * in the GrabMutex predicate. + * + */ + +open util/ordering [State] as so +open util/ordering [Mutex] as mo + +sig Process {} +sig Mutex {} + +sig State { holds, waits: Process -> Mutex } + + +pred Initial [s: State] { no s.holds + s.waits } + +pred IsFree [s: State, m: Mutex] { + // no process holds this mutex + no m.~(s.holds) + // all p: Process | m !in p.(this.holds) +} + +pred IsStalled [s: State, p: Process] { some p.(s.waits) } + +pred GrabMutex [s: State, p: Process, m: Mutex, s': State] { + // a process can only act if it is not + // waiting for a mutex + !s.IsStalled[p] + // can only grab a mutex we do not yet hold + m !in p.(s.holds) + // mutexes are grabbed in order + all m': p.(s.holds) | mo/lt[m',m] + s.IsFree[m] => { + // if the mutex is free, we now hold it, + // and do not become stalled + p.(s'.holds) = p.(s.holds) + m + no p.(s'.waits) + } else { + // if the mutex was not free, + // we still hold the same mutexes we held, + // and are now waiting on the mutex + // that we tried to grab. + p.(s'.holds) = p.(s.holds) + p.(s'.waits) = m + } + all otherProc: Process - p | { + otherProc.(s'.holds) = otherProc.(s.holds) + otherProc.(s'.waits) = otherProc.(s.waits) + } +} + +pred ReleaseMutex [s: State, p: Process, m: Mutex, s': State] { + !s.IsStalled[p] + m in p.(s.holds) + p.(s'.holds) = p.(s.holds) - m + no p.(s'.waits) + no m.~(s.waits) => { + no m.~(s'.holds) + no m.~(s'.waits) + } else { + some lucky: m.~(s.waits) | { + m.~(s'.waits) = m.~(s.waits) - lucky + m.~(s'.holds) = lucky + } + } + all mu: Mutex - m { + mu.~(s'.waits) = mu.~(s.waits) + mu.~(s'.holds)= mu.~(s.holds) + } +} + +/** + * for every adjacent (pre,post) pair of States, + * one action happens: either some process grabs a mutex, + * or some process releases a mutex, + * or nothing happens (have to allow this to show deadlocks) + */ +pred GrabOrRelease { + Initial[so/first] && + ( + all pre: State - so/last | let post = so/next [pre] | + (post.holds = pre.holds && post.waits = pre.waits) + || + (some p: Process, m: Mutex | pre.GrabMutex [p, m, post]) + || + (some p: Process, m: Mutex | pre.ReleaseMutex [p, m, post]) + + ) +} + +pred Deadlock { + some Process + some s: State | all p: Process | some p.(s.waits) +} + +assert DijkstraPreventsDeadlocks { + GrabOrRelease => ! Deadlock +} + + +pred ShowDijkstra { + GrabOrRelease && Deadlock + some waits +} + +run Deadlock for 3 expect 1 +run ShowDijkstra for 5 State, 2 Process, 2 Mutex expect 1 +check DijkstraPreventsDeadlocks for 5 State, 5 Process, 4 Mutex expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/dijkstra.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/dijkstra.thm new file mode 100644 index 00000000..3be2d6c2 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/dijkstra.thm @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/messaging.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/messaging.als new file mode 100644 index 00000000..0815fb44 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/messaging.als @@ -0,0 +1,228 @@ +module examples/algorithms/messaging + +/* + * Generic messaging among several nodes + * + * By default, messages can be lost (i.e. never become visible to the + * recipient node) or may be arbitrarily delayed. Also, by default + * out-of-order delivery is allowed. + */ + +open util/ordering[Tick] as ord +open util/relation as rel + +sig Node {} + +sig MsgState { + /** Node that sent the message */ + from: Node, + + /** Intended recipient(s) of a message; note that broadcasts are allowed */ + to: set Node +} + +sig Msg { + state: MsgState, + + /** Timestamp: the tick on which the message was sent */ + sentOn: Tick, + + /** tick at which node reads message, if read */ + readOn: Node -> lone Tick +}{ + readOn.Tick in state.to +} + +sig Tick { + /** The state of each node */ + state: Node -> one NodeState, + + /** + * Definition of what each node does on this tick: + * + * Typically, a node would determine + * the messages it sends and its next state, based on its current + * state and the messages it reads. + * + * Messages that the node _can_ read in this tick, i.e. messages available + * for reading at the beginning of this tick. The messages that + * the node actually reads are a subset of this set. Determined by + * constraints in this module. + */ + visible: Node -> Msg, + + /** + * Messages that the node _actually reads_ in this tick. Must be a subset + * of visible. Determined by constraints of the particular system + * that uses this module. + */ + read: Node -> Msg, + + /** + * Messages sent by the node in this tick. They become visible to + * (and can be read by) their recipients on the next tick. + */ + sent: Node -> Msg, + + /** + * Messages available for sending at this tick. A given message + * atom is only used once, and then it gets removed from the available + * set and cannot be used to represent messages sent on subsequent ticks. + * Also, two different nodes cannot send the same message atom. + * So, a message atom represents a particular single physical message + * sent by a given node on a given tick. + */ + available: set Msg, + + /** + * For each node, at each tick, the number of messages it _needs_ to send. + * Used to rule out "proofs" of liveness violations that are caused + * solely by not having enough messages available for sending. + */ + needsToSend: Node -> Msg +} + +fun MsgsSentOnTick[t: Tick]: set Msg { t.sent[Node] } +fun MsgsVisibleOnTick[t: Tick]: set Msg { t.visible[Node] } +fun MsgsReadOnTick[t: Tick]: set Msg { t.read[Node] } + +fact MsgMovementConstraints { + // At the beginning, no messages have been sent yet + no ord/first.visible[Node] + + // Messages sent on a given tick become visible to recipient(s) + // on the subsequent tick. + all pre: Tick - ord/last | + let post = ord/next[pre] | { + // messages sent on this tick are no longer available on subsequent tick + post.available = pre.available - MsgsSentOnTick[pre] + } + + all t: Tick | { + // Messages sent on a tick are taken from the pool of available + // (not-yet-sent) message atoms + MsgsSentOnTick[t] in t.available + + // Timestamps are correct + MsgsSentOnTick[t].sentOn in t + MsgsReadOnTick[t].readOn[Node] in t + + // The only new message atoms are those sent by nodes + MsgsSentOnTick[t] = t.sent[Node] + + all n: Node, m: Msg | + m.readOn[n] = t => m in t.read[n] + // Return addresses are correct + all n: Node | t.sent[n].state.from in n + + // messages sent to a node on a tick become visible to that node on some subseqent tick, + // and permanently stop being visible to that node on the tick after that node reads the message + all n: Node, m: Msg | { + // message starts being visible to node n no earlier than it is sent; + // only messages sent to this node are visible to this node. + (m in t.visible[n] => (n in m.state.to && m.sentOn in ord/prevs[t])) + // message permanently stops being visible immediately after being read + (m in t.read[n] => m !in ord/nexts[t].visible[n]) + } + } +} + +sig NodeState { +} + +fun MsgsLiveOnTick[t: Tick]: set Msg { + Msg - { future: Msg | future.sentOn in ord/nexts[t] } + - { past: Msg | all n: past.state.to | past.readOn[n] in ord/prevs[t] } +} + +pred TicksEquivalent[t1, t2: Tick] { + t1.state = t2.state + some r: (MsgsLiveOnTick[t1] - MsgsVisibleOnTick[t1]) one -> one (MsgsLiveOnTick[t2] - MsgsVisibleOnTick[t2]) | + all m1: dom[r] | let m2 = m1.r | { + m1.(Msg<:state) = m2.state + } + some r: MsgsVisibleOnTick[t1] one -> one MsgsVisibleOnTick[t2] | + all m1: dom[r] | let m2 = m1.r | { + m1.(Msg<:state) = m2.state + } +} + +pred Loop { + some t: Tick - ord/last | TicksEquivalent[t, ord/last] +} + +fact CleanupViz { + // cleans up visualization without precluding any interesting traces + + // all messages must be sent + Msg in Tick.sent[Node] +} + +pred ReadInOrder { + // + // This function ensures that messages are read in order. + // + + // for all pairs of nodes + all n1, n2: Node | + // for all pairs of messages sent from n1 to n2 + all m1, m2: Msg | + { + m1.state.from = n1 + m2.state.from = n1 + m1.state.to = n2 + m2.state.to = n2 + } => { + // if both m1 and m2 are read by n2, *and* + // n2 reads m1 before m2, then m1 must have + // been sent before m2 + (some m1.readOn[n2] && some m2.readOn[n2] && + m1.readOn[n2] in ord/prevs[m2.readOn[n2]]) => + ord/lte[m1.sentOn, m2.sentOn] + } +} + +fact ReadOnlyVisible { read in visible } + +/** + * this function ensures that messages will not + * be lost, i.e. a message send to a node will + * eventually be visible to that node + */ +pred NoLostMessages { + all m: Msg | + (m.sentOn != ord/last) => (all n: m.state.to | + some t: ord/nexts[m.sentOn] | + m in t.visible[n]) +} + +/** + * this function ensures that there will be + * no shortage of messages in the available + * message pool during the trace + */ +pred NoMessageShortage { + all t: Tick - ord/last | + (sum n: Node | # t.needsToSend[n]) =< # t.available +} + +pred SomeState { + # Node > 1 + //# Tick$read > 1 +} + +pred OutOfOrder { + ! ReadInOrder + # Msg = 2 +} + +run SomeState for 2 expect 1 +run OutOfOrder for 4 expect 1 + + + +// DEFINED VARIABLES +// Defined variables are uncalled, no-argument functions. +// They are helpful for getting good visualization. +fun FROM: Msg -> Node {{m: Msg, n: Node | n in m.state.from}} +fun TO: Msg -> Node {{m: Msg, n: Node | n in m.state.to}} diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/messaging.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/messaging.thm new file mode 100644 index 00000000..53f28d8d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/messaging.thm @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/opt_spantree.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/opt_spantree.als new file mode 100644 index 00000000..7c129325 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/opt_spantree.als @@ -0,0 +1,220 @@ +module examples/algorithms/opt_spantree + +/* + * Direct specification of a distributed spanning tree algorithm + * over arbitrary network topologies + * + * Each process has a parent and a level, both of which are + * initally null. A distinct root node exists at which the + * algorithm starts. In the first step, the root assigns itself + * the level of zero and sends its level to its neighbors. + * Subsequently, if a node reads a message with level k, it sets + * its level to k+1, records the sender of the message as its + * parent, and sends the level k+1 to its neighbors. Once a node + * has set its level and parent, it ignores subsequent messages. + * Eventually, the parent pointers will form a spanning tree, + * rooted at Root. + * + * We model communication through a state-reading model, in which + * nodes can directly read the state of their neighbors. Messages + * are not explicity modelled. This makes no difference for this + * algorithm since once a node sends a message, the state of the + * node stays the same as the contents of the message. + */ + +open util/ordering[Lvl] as lo +open util/ordering[State] as so +open util/graph[Process] as graph + +sig Process { + adj : set Process +} + +one sig Root extends Process {} + +/** + * intuitively, the depth level at which + * a process resides in the spanning tree, + * with the root at level zero + */ +sig Lvl {} + +fact processGraph { + graph/noSelfLoops[adj] // for viz + graph/undirected[adj] // adjacency is symmetric + Process in Root.*adj // everything reachable from root +} + +sig State { + /** + * the set of processes which execute in this state. + * used to allow flexibility in how many processes + * run simultaneously + */ + runs : set Process, + + /** + * the level of a process in this state + */ + lvl: Process -> lone Lvl, + + /** + * who the process thinks is its parent in this state. + * the parent pointers should eventually become + * the spanning tree + */ + parent: Process -> lone Process +} + +/** + * initially, the lvl and parent fields are blank + */ +pred Init { + let fs = so/first | { + no fs.lvl + no fs.parent + } +} + +/** + * simple NOP transition + */ +pred TRNop[p : Process, pre, post: State] { + pre.lvl[p] = post.lvl[p] + pre.parent[p] = post.parent[p] +} + +/** + * preconditions for a process to actually act + * in a certain pre-state + * used to preclude stalling of entire system + * for no reason (see TransIfPossible) + */ +pred TRActPreConds[p : Process, pre : State] { + // can't already have a level + no pre.lvl[p] + // must have a neighbor with a set level so + // p can read it + // Root doesn't need to read value from a + // neighbor + (p = Root || some pre.lvl[p.adj]) +} + +/** + * transition which changes state of a process + */ +pred TRAct[p : Process, pre, post : State] { + // can't already have a level + no pre.lvl[p] + (p = Root) => { + // the root sets its level to + // 0, and has no parent pointer + post.lvl[p] = lo/first + no post.parent[p] + } else { + // choose some adjacent process + // whose level is already set + some adjProc: p.adj | + let nLvl = pre.lvl[adjProc] | { + some nLvl + // p's parent is the adjacent + // process, and p's level is one greater than + // the level of the adjacent process (since + // its one level deeper) + post.lvl[p] = lo/next[nLvl] + post.parent[p] = adjProc + } + } +} + +pred Trans[p : Process, pre, post : State] { + TRAct[p, pre, post] || + TRNop[p, pre, post] +} + +/** + * all processes do a nop transition in some + * state only when no process can act because + * preconditions are not met + */ +fact TransIfPossible { + all s : State - so/last | + (all p : Process | TRNop[p, s, so/next[s]]) => + (all p : Process | !TRActPreConds[p,s]) +} + +fact LegalTrans { + Init + all s : State - so/last | + let s' = so/next[s] | { + all p : Process | + p in s.runs => Trans[p, s, s'] else TRNop[p,s,s'] + } +} + +pred PossTrans[s, s' : State] { + all p : Process | Trans[p,s,s'] +} + +pred SpanTreeAtState[s : State] { + // all processes reachable through inverted parent pointers + // from root (spanning) + Process in Root.*~(s.parent) + // parent relation is a tree (DAG) + // we only need to check the DAG condition since there can + // be at most one parent for a process (constrained by + // multiplicity) + graph/dag[~(s.parent)] +} + +/** + * show a run that produces a spanning tree + */ +pred SuccessfulRun { + SpanTreeAtState[so/last] + all s : State - so/last | !SpanTreeAtState[s] +} + +/** + * show a trace without a loop + */ +pred TraceWithoutLoop { + all s, s' : State | s!=s' => { + !EquivStates[s, s'] + (s' in so/nexts[s] && (s' != so/next[s])) => !PossTrans[s,s'] + } + all s: State | !SpanTreeAtState[s] +} + +/** + * defines equivalent states + */ +pred EquivStates[s, s' : State] { + s.lvl = s'.lvl + s.parent = s'.parent +} + +/** + * show a trace that violates liveness + */ +pred BadLivenessTrace { + // two different states equivalent (loop) + some s, s' : State | s!=s' && EquivStates[s, s'] + all s : State | !SpanTreeAtState[s] +} + +/** + * check that once spanning tree is constructed, + * it remains + */ +assert Closure { + all s : State - so/last | + SpanTreeAtState[s] => (s.parent = so/next[s].parent) +} + +// note that for the worst case topology and choice of root, +// the scope of Lvl must equal the scope of Process +run SuccessfulRun for 4 State, exactly 5 Process, 3 Lvl expect 1 +// run TraceWithoutLoop for 8 but 9 State expect 1 +run BadLivenessTrace for 5 but 7 State expect 0 +check Closure for 5 but 7 State expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/opt_spantree.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/opt_spantree.thm new file mode 100644 index 00000000..1254faed --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/opt_spantree.thm @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/peterson.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/peterson.als new file mode 100644 index 00000000..6e6d59e5 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/peterson.als @@ -0,0 +1,206 @@ +module examples/algorithms/peterson + +/* + * Model of Peterson's algorithm for mutual exclusion of n + * processes. The names kept similar to Murphi specification + * to make correspondence clear. + */ + +open util/ordering[priority] as po +open util/ordering[State] as so + +sig pid { +} + +sig priority { +} + +fact { + # priority = # pid + 1 +} + +abstract sig label_t {} + +// here subtyping would help +one sig L0, L1, L2, L3, L4 extends label_t {} + +sig State { + P: pid -> label_t, + Q: pid -> priority, + turn: priority -> pid, + localj: pid -> priority +} + +pred NOPTrans[i: pid, pre, post : State] { + post.P[i] = pre.P[i] + post.Q[i] = pre.Q[i] + post.localj[i] = pre.localj[i] +} + +pred L0TransPre[i : pid, pre : State] { + // precondition + pre.P[i] = L0 +} + +pred L0Trans[i: pid, pre, post : State] { + L0TransPre[i, pre] + // localj[i] := 1 + post.localj[i] = po/next[po/first] + post.P[i] = L1 + post.Q[i] = pre.Q[i] + // something for turn? + post.turn = pre.turn +} + +pred L1TransPre[i : pid, pre : State] { + // precondition + pre.P[i] = L1 +} + +pred L1Trans[i : pid, pre, post : State] { + L1TransPre[i, pre] + post.localj[i] = pre.localj[i] + post.Q[i] = pre.localj[i] + post.P[i] = L2 + // something for turn? + post.turn = pre.turn +} + +pred L2TransPre[i : pid, pre : State] { + // precondition + pre.P[i] = L2 +} + +pred L2Trans[i : pid, pre, post : State] { + L2TransPre[i, pre] + post.localj[i] = pre.localj[i] + post.Q[i] = pre.Q[i] + post.P[i] = L3 + post.turn[post.localj[i]] = i + all j : priority - post.localj[i] | + post.turn[j] = pre.turn[j] +} + +pred L3TransPre[i : pid, pre : State] { + // precondition + pre.P[i] = L3 + + all k : pid - i | + po/lt[pre.Q[k], pre.localj[i]] || + pre.turn[pre.localj[i]] != i +} + +pred L3Trans[i : pid, pre, post : State] { + L3TransPre[i, pre] + post.localj[i] = po/next[pre.localj[i]] + po/lt[post.localj[i], po/last] => + post.P[i] = L1 + else + post.P[i] = L4 + post.Q[i] = pre.Q[i] + post.turn = pre.turn +} + +pred L4TransPre[i : pid, pre : State] { + // precondition + pre.P[i] = L4 +} + +pred L4Trans[i : pid, pre, post : State] { + L4TransPre[i, pre] + + post.P[i] = L0 + post.Q[i] = po/first + post.localj[i] = pre.localj[i] + post.turn = pre.turn +} + +pred RealTrans[i : pid, pre, post : State] { + L0Trans[i,pre,post] || + L1Trans[i,pre,post] || + L2Trans[i,pre,post] || + L3Trans[i,pre,post] || + L4Trans[i,pre,post] +} + +pred SomePre[i : pid, pre : State] { + L0TransPre[i, pre] || + L1TransPre[i, pre] || + L2TransPre[i, pre] || + L3TransPre[i, pre] || + L4TransPre[i, pre] +} + +fact Init { + let firstState = so/first | { + all i : pid | { + firstState.P[i] = L0 + firstState.Q[i] = po/first + } + no firstState.turn + no firstState.localj + } +} + +fact LegalTrans { + all pre : State - so/last | + let post = so/next[pre] | { + /*some i : pid | { + // HACK: + // need to specify that if some node + // can make a non-NOP transition, it + // does, but i can't figure out how + // right now + Trans(i,pre,post) && !NOPTrans(i,pre,post) + all j : pid - i | + NOPTrans(j,pre,post) + }*/ + all i : pid | + RealTrans[i,pre,post] || NOPTrans[i,pre,post] + (all i : pid | NOPTrans[i,pre,post]) => { + all i : pid | !SomePre[i,pre] + post.turn = pre.turn + } + } +} + +assert Safety { + all i1, i2 : pid, s : State | i1!=i2 => not (s.P[i1] = L4 && s.P[i2] = L4) +} + +assert NotStuck { + all pre : State - so/last | + let post = so/next[pre] | + some i : pid | + RealTrans[i, pre, post] && !NOPTrans[i,pre,post] +} + +pred TwoRun { + some s1, s2: State, i1, i2: pid | { + s1!=s2 + i1!=i2 + s1.P[i1] = L4 + s2.P[i2] = L4 + } +} + +pred ThreeRun { + some disj s1, s2, s3: State, disj i1, i2, i3: pid | { + s1.P[i1] = L4 + s2.P[i2] = L4 + s3.P[i3] = L4 + } +} + +// 2 pids requires 8 states +// 3 pids requires 16 states +run TwoRun for 13 but 3 pid, 4 priority, 5 label_t expect 1 + +// haven't run this one successfully yet +run ThreeRun for 19 but 3 pid,4 priority,5 label_t expect 1 + +// how many states do we need for this to match murphi? +check Safety for 10 but 2 pid, 3 priority, 5 label_t expect 0 + +// this assertion is trivial because of the hack described above +check NotStuck for 10 but 2 pid, 3 priority, 5 label_t expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/ringlead.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/ringlead.als new file mode 100644 index 00000000..b5a786a8 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/ringlead.als @@ -0,0 +1,150 @@ +module examples/algorithms/ringlead + +/* + * Model of leader election on a ring + * + * Each process has a unique ID, IDs are ordered. + * The algorithm elects the process with the highest + * ID the leader, as follows. First, each process + * sends its own ID to its right neighbor. + * Then, whenever a process receives an ID, if the + * ID is greater than the process' own ID it forwards + * the ID to its right neighbor, otherwise does nothing. + * When a process receives its own ID that process + * is the leader. + */ + +open util/boolean as bool +open examples/algorithms/messaging as msg +open util/ordering[msg/Node] as nodeOrd +open util/ordering[msg/Tick] as tickOrd + +sig RingLeadNode extends msg/Node { + rightNeighbor: msg/Node +} + +fact DefineRing { + (one msg/Node || (no n: msg/Node | n = n.rightNeighbor)) + all n: msg/Node | msg/Node in n.^rightNeighbor +} + +sig RingLeadMsgState extends msg/MsgState { + id: msg/Node +} + +sig MsgViz extends msg/Msg { + vFrom: msg/Node, + vTo: set msg/Node, + vId: msg/Node +} + +fact { + MsgViz = msg/Msg + vFrom = state.from + vTo = state.to + vId = state.id +} + + +sig RingLeadNodeState extends msg/NodeState { + leader: Bool +} + + +pred RingLeadFirstTrans [self: msg/Node, pre, post: msg/NodeState, + sees, reads, sends, needsToSend: set msg/Msg] { + one sends + # needsToSend = 1 + sends.state.to = self.rightNeighbor + sends.state.id = self + post.leader = False +} + +fact InitRingLeadState { + all n: msg/Node | + tickOrd/first.state[n].leader = False +} + +pred RingLeadRestTrans [self: msg/Node, pre, post: msg/NodeState, + sees, reads, sends, needsToSend: set msg/Msg] { + RingLeadTransHelper[self, sees, reads, sends, needsToSend] + post.leader = True iff (pre.leader = True || + self in reads.state.id) +} + +/** + * we take any messages whose node ids are higher than ours, + * and we forward them to the right neighbor. we drop + * all other messages. if we get a message with our own + * id, we're the leader. + */ +pred RingLeadTransHelper[self: msg/Node, sees, reads, sends, needsToSend: set msg/Msg] { + reads = sees + + all received: reads | + (received.state.id in nodeOrd/nexts[self]) => + (one weSend: sends | (weSend.state.id = received.state.id && weSend.state.to = self.rightNeighbor)) + + all weSend: sends | { + let mID = weSend.state.id | { + mID in nodeOrd/nexts[self] + mID in reads.state.id + weSend.state.to = self.rightNeighbor + } + //weSend.sentBecauseOf = { received : reads | received.id = weSend.id } + //all otherWeSend: sends - weSend | otherWeSend.id != weSend.id + } + + # needsToSend = # { m: reads | m.state.id in nodeOrd/nexts[self] } +} +fact RingLeadTransitions { + all n: msg/Node { + all t: msg/Tick - tickOrd/last | { + t = tickOrd/first => + RingLeadFirstTrans[n, t.state[n], tickOrd/next[t].state[n], t.visible[n], t.read[n], t.sent[n], t.needsToSend[n]] + else + RingLeadRestTrans[n, t.state[n], tickOrd/next[t].state[n], t.visible[n], t.read[n], t.sent[n], t.needsToSend[n]] + } + // also constrain last tick + RingLeadTransHelper[n, tickOrd/last.visible[n], tickOrd/last.read[n], tickOrd/last.sent[n], tickOrd/last.needsToSend[n]] + } +} + +assert OneLeader { + all t: msg/Tick | + lone n: msg/Node | + t.state[n].leader = True +} + +fact CleanupViz { + RingLeadNode = msg/Node + RingLeadMsgState = msg/MsgState + RingLeadNodeState = msg/NodeState +} + +pred SomeLeaderAtTick[t: msg/Tick] { + some n: msg/Node | t.state[n].leader = True +} + +pred NeverFindLeader { + msg/Loop + all t: msg/Tick | ! SomeLeaderAtTick[t] +} + +assert Liveness { + (msg/NoLostMessages && msg/NoMessageShortage) => ! NeverFindLeader +} + +pred SomeLeader { some t: msg/Tick | SomeLeaderAtTick[t] } + +assert LeaderHighest { + all t: msg/Tick, n: msg/Node | + t.state[n].leader = True => n = nodeOrd/last +} + +run NeverFindLeader for 1 but 3 msg/Tick, 2 Bool, 2 msg/NodeState expect 1 +check Liveness for 3 but 6 msg/Msg, 2 Bool, 2 msg/NodeState expect 0 +check OneLeader for 5 but 2 Bool, 2 msg/NodeState expect 0 +run SomeLeader for 2 but 3 msg/Node, 5 msg/Msg, 5 msg/Tick, 5 msg/MsgState expect 1 +check LeaderHighest for 3 but 2 msg/NodeState, 5 msg/Msg, 5 msg/MsgState, 5 msg/Tick expect 0 + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/ringlead.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/ringlead.thm new file mode 100644 index 00000000..95977a51 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/ringlead.thm @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/s_ringlead.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/s_ringlead.als new file mode 100644 index 00000000..8f96b477 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/s_ringlead.als @@ -0,0 +1,153 @@ +module examples/algorithms/s_ringlead + +/* + * Model of leader election on a ring. + * + * Each process has a unique ID, IDs are ordered. The algorithm + * elects the process with the highest ID the leader, as follows. + * First, each process sends its own ID to its right neighbor. + * Then, whenever a process receives an ID, if the ID is greater + * than the process' own ID it forwards the ID to its right + * neighbor, otherwise does nothing. When a process receives its + * own ID that process is the leader. + * + * Note: This file needs higher order quantifiers turned on. + */ + +open util/ordering[State] as so +open util/ordering[Process] as po +open util/graph[Process] as graph + +sig Process { + rightNeighbor: Process +} + +sig State { + // buffer which the right neighbor can read from + buffer: Process -> Process, + //sends, reads: Process -> Process, + runs: set Process, + leader: set Process +} + +fact DefineRing { + graph/ring[rightNeighbor] +} + +fact InitialState { + no so/first.buffer + no so/first.leader + Process in so/first.runs +} + + +fact CleanupLast { + let ls = so/last | + no ls.runs +} + +pred ValidTrans2[s, s': State] { + all p : s.runs | VT2Helper[p,s,s'] + all p : Process - s.runs | NOP2[p,s,s'] + NoMagicMsg[s,s'] + +} + +pred NoMagicMsg[s, s' : State] { + // no magically appearing messages + all p : Process, m : s'.buffer[p] | + m in s.buffer[p] || (!NOP2[p,s,s'] && + ((s = so/first && m = p) || + (s != so/first && m in s.buffer[p.~rightNeighbor] + && m !in s'.buffer[p.~rightNeighbor] && po/gt[m,p]))) +} + +pred PossTrans[s, s' : State] { + all p : Process | VT2Helper[p,s,s'] || NOP2[p,s,s'] + NoMagicMsg[s,s'] +} + +pred VT2Helper[p : Process, s, s' : State] { + ( + let readable=s.buffer[p.~rightNeighbor] | + (s = so/first) => { + p = s'.buffer[p] + readable in s'.buffer[p.~rightNeighbor] + p !in s'.leader + } else { + (some readable) => { + some m : set readable | { + m !in s'.buffer[p.~rightNeighbor] + // nothing else gets deleted + readable - m in s'.buffer[p.~rightNeighbor] + { m': m | po/gt[m',p] } /*m & nexts(p)*/ in s'.buffer[p] + p in s'.leader iff (p in s.leader || p in m) + } + } else NOP2[p,s,s'] + } + ) +} + +pred NOP2[p : Process, s,s': State] { + p in s'.leader iff p in s.leader + // no reads + s.buffer[p.~rightNeighbor] in s'.buffer[p.~rightNeighbor] + // no sends + s'.buffer[p] in s.buffer[p] +} + +pred Preconds[p : Process, s : State] { + s = so/first || some s.buffer[p.~rightNeighbor] +} + +fact TransIfPossible { + all s : State - so/last | + (all p : Process | NOP2[p, s, so/next[s]]) => + (all p : Process | !Preconds[p,s]) +} + +fact LegalTrans { + all s : State - so/last | + let s' = so/next[s] | + ValidTrans2[s,s'] +} + +pred EquivStates[s, s': State] { + s.buffer = s'.buffer + s.leader = s'.leader +} + +assert Safety { + all s : State | lone s.leader +} + +pred Legit[s : State] { + one s.leader +} + +pred BadLivenessTrace { + all s : State | !Legit[s] + let ls = so/last | + some s : State - ls | { + EquivStates[s, ls] + Process in (so/nexts[s] + s).runs + } +} + +pred TraceWithoutLoop { + all t1, t2 : State | t1!=t2 => !EquivStates[t1,t2] + all s, s' : State | (s' in (so/nexts[s] - so/next[s])) => !PossTrans[s,s'] + all s : State | !Legit[s] +} + +pred AltTrans { + SomeLeader +} + +pred SomeLeader { some State.leader } + +run BadLivenessTrace for 3 but 8 State expect 0 +run SomeLeader for 4 but 6 State expect 1 +check Safety for 7 expect 0 +// run TraceWithoutLoop for 5 but 13 State expect 1 +run AltTrans for 5 but 8 State expect 1 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/stable_mutex_ring.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/stable_mutex_ring.als new file mode 100644 index 00000000..d4a21f12 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/stable_mutex_ring.als @@ -0,0 +1,202 @@ +module examples/algorithms/stable_mutex_ring + +/* + * Dijkstra's K-state mutual exclusion algorithm for a ring + * + * Original paper describing the algorithm: + * [1] E.W.Dijkstra, "Self-Stabilizing Systems in Spite of + * Distributed Control", Comm. ACM, vol. 17, no. 11, pp. + * 643-644, Nov. 1974 + * + * Proof of algorithm's correctness: + * [2] E.W.Dijkstra, "A Belated Proof of Self-Stabilization", + * in Distributed Computing, vol. 1, no. 1, pp. 5-6, 1986 + * + * SMV analysis of this algorithm is described in: + * [3] "Symbolic Model Checking for Self-Stabilizing Algorithms", + * by Tatsuhiro Tsuchiya, Shini'ichi Nagano, Rohayu Bt Paidi, and + * Tohru Kikuno, in IEEE Transactions on Parallel and Distributed + * Systems, vol. 12, no. 1, January 2001 + * + * Description of algorithm (adapted from [3]): + * + * Consider a distributed system that consists of n processes + * connected in the form of a ring. We assume the state-reading + * model in which processes can directly read the state of their + * neighbors. We define _privilege_ of a process as its ability to + * change its current state. This ability is based on a Boolean + * predicate that consists of its current state and the state of + * one of its neighboring processes. + * + * We then define the legitimate states as those in which the + * following two properties hold: 1) exactly one process has a + * privilege, and 2) every process will eventually have a privilege. + * These properties correspond to a form of mutual exclusion, because + * the privileged process can be regarded as the only process that is + * allowed in its critical section. + * + * In the K-state algorithm, the state of each process is in + * {0,1,2,...,K-1}, where K is an integer larger than or equal to n. + * For any process p_i, we use the symbols S and L to denote its + * state and the state of its neighbor p_{i-1}, respectively, and + * process p_0 is treated differently from all other processes. The + * K-state algorithm is described below. + * + * process p_0: if (L=S) { S := (S+1) mod K; } + * process P_i(i=1,...,n-1): if (L!=S) { S:=L; } + */ + +open util/ordering[Tick] as to +open util/graph[Process] as pg +open util/graph[Val] as vg + +sig Process { + rightNeighbor: Process +} + +sig Val { + nextVal : Val +} + +fact MoreValThanProcess { + # Val > # Process +} + +fact DefineRings { + pg/ring[rightNeighbor] + vg/ring[nextVal] + //Val$nextVal = Ord[Val].next + (Ord[Val].last -> Ord[Val].first) +} + +sig Tick { + val: Process -> one Val, + runs: set Process, // processes scheduled to run on this tick + // for visualization + priv: set Process // the set of priviledged processes on this tick +} +{ + priv = { p : Process | Privileged[p, this] } +} + +one sig FirstProc extends Process { +} + + +fun FirstProcTrans[curVal, neighborVal : Val]: Val { + (curVal = neighborVal) => curVal.nextVal else curVal +} + +fun RestProcTrans[curVal, neighborVal : Val]: Val { + (curVal != neighborVal) => neighborVal else curVal +} + +fact LegalTrans { + all tp : Tick - to/last | + let tn = to/next[tp] | { + all p: Process | + let curVal = tp.val[p], neighborVal = tp.val[p.rightNeighbor], newVal = tn.val[p] | { + p !in tp.runs => newVal = curVal else { + p = FirstProc => + newVal = FirstProcTrans[curVal, neighborVal] + else + newVal = RestProcTrans[curVal, neighborVal] + } + } + } +} + +pred TickTrans[tp, tn : Tick] { + all p : Process | + let curVal = tp.val[p], neighborVal = tp.val[p.rightNeighbor], newVal = tn.val[p] | { + p = FirstProc => + newVal = FirstProcTrans[curVal, neighborVal] + else + newVal = RestProcTrans[curVal, neighborVal] + } +} + +/** + * whether this process can enter its critical section + * on this tick + */ +pred Privileged[p : Process, t : Tick] { + p = FirstProc => + t.val[p] = t.val[p.rightNeighbor] + else + t.val[p] != t.val[p.rightNeighbor] +} + +pred IsomorphicStates[val1, val2: Process -> one Val] { + some processMap: Process one -> one Process, + valMap: Val one -> one Val | { + FirstProc.processMap = FirstProc + all p: Process, v: Val | { + p->v in val1 iff (p.processMap) -> (v.valMap) in val2 + } + all v1,v2: Val | v1->v2 in nextVal iff (v1.valMap) -> (v2.valMap) in nextVal + all p1,p2: Process | p1->p2 in rightNeighbor + iff (p1.processMap) -> (p2.processMap) in rightNeighbor + } +} + +/** + * Find a trace that goes into a loop + * containing a bad tick, i.e. a tick + * at which two distinct processes + * try to run their critical sections + * simultaneously. In such a trace the + * algorithm never "stabilizes". + */ +pred BadSafetyTrace { + let lst = to/last | + some t : Tick - lst | { + //IsomorphicStates(ft.val, lst.val) + t.val = lst.val + Process in (to/nexts[t] + t - lst).runs + some badTick : to/nexts[t] + t | + BadTick[badTick] + } +} + +/** + * Two different processes simultaneously + * try to run their critical sections at this tick + */ +pred BadTick[badTick : Tick] { + some p1 , p2 : Process | { + p1!=p2 + Privileged[p1, badTick] + Privileged[p2, badTick] + } +} + +assert Closure { + not BadTick[to/first] => (all t : Tick | not BadTick[t]) +} + +pred TwoPrivileged { + BadTick[to/first] + some p1, p2 : Process, t1, t2 : Tick - to/first | { + p1!=p2 + Privileged[p1,t1] + Privileged[p2,t2] + } +} + +pred TraceWithoutLoop { + all t1, t2 : Tick | t1!=t2 => t1.val != t2.val +} + +pred TraceShorterThanMaxSimpleLoop { + to/first.val = to/last.val + all t : Tick - to/first - to/last | + !(t.val = to/first.val) +} + +run TraceShorterThanMaxSimpleLoop for 7 but 2 Process, 3 Val expect 1 +run TwoPrivileged for 5 but 3 Process, 4 Val expect 1 +check Closure for 5 but 5 Process, 6 Val expect 0 +//run BadSafetyTrace for 16 but 3 Process, 4 Val +//run TraceWithoutLoop for 21 but 4 Process, 5 Val + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/stable_mutex_ring.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/stable_mutex_ring.thm new file mode 100644 index 00000000..5f31f3ac --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/stable_mutex_ring.thm @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/stable_orient_ring.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/stable_orient_ring.als new file mode 100644 index 00000000..c6fec3fe --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/stable_orient_ring.als @@ -0,0 +1,90 @@ +module examples/algorithms/stable_orient_ring + +/* + * A self-stabilizing algorithm for orienting uniform rings. + * Communication model is the state-reading model. + */ + +open util/boolean as bool +open util/ordering[Tick] as ord +open util/graph[Process] as graph + +sig Process { + rightNeighbor: Process, + AP1, AP2: Process +} + +fun leftNeighbor[p: Process]: Process { + p.~(rightNeighbor) +} + +fact { + all p: Process { + (p.AP1=p.rightNeighbor && p.AP2=leftNeighbor[p]) || + (p.AP2=p.rightNeighbor && p.AP1=leftNeighbor[p]) + } +} + +fact DefineRing { + graph/ring[rightNeighbor] +} + +sig Tick { + runs: set Process, + dir, S, T: Process -> one Bool, + ring_: Process -> Process +} +{ + all p: Process | p.ring_ = (p.dir=True => p.AP1 else p.AP2) +} + +pred Eq3[b1,b2,b3: Bool] { b1 = b2 && b2 = b3 } +pred Eq4[b1,b2,b3,b4: Bool] { Eq3[b1,b2,b3] && b3=b4 } + +fact Transitions { + all tp: Tick - ord/last | let tn = ord/next[tp] | + all p: Process | + let p1 = p.AP1, p2 = p.AP2, pS = tp.S, pT=tp.T, nS=tn.S, nT=tn.T | + let S1p=p1.pS, S2p=p2.pS, + T1p=p1.pT, T2p=p2.pT, + Sp = p.pS, Sn=p.nS, + Tp = p.pT, Tn=p.nT, + dirp = p.(tp.dir), dirn = p.(tn.dir) | { + p !in tp.runs => ( Sn = Sp && Tn = Tp && dirn = dirp ) else ( + S1p = S2p => ( Sn = Not[S1p] && Tn = True && dirn=dirp) else ( + (Eq3[S1p, Sp, Not[S2p]] && + Eq4[Not[T1p],Tp,T2p,True]) => + (Sn = Not[Sp] && Tn = False && dirn = True) + else ( + (Eq3[Not[S1p],Sp,S2p] && Eq4[T1p,Tp,Not[T2p],True]) => + (Sn = Not[Sp] && Tn = False && dirn = False) else ( + ((Eq3[S1p,Sp,Not[S2p]] && T1p=Tp) || + (Eq3[Not[S1p],Sp,S2p] && Tp=T2p)) => + (Tn = Not[Tp] && Sn=Sp && dirn=dirp) else ( + Sn=Sp && Tn=Tp && dirn=dirp + ) + ) + ) + ) + ) + } +} + +pred RingAtTick[t: Tick] { + let rng = t.ring_ | + graph/ring[rng] || graph/ring[~rng] +} + +assert Closure { + // if the ring is properly oriented + all t: Tick - ord/last | + RingAtTick[t] => RingAtTick[ord/next[t]] +} + +pred SomeState { + !graph/ring[ord/first.ring_] + some t: Tick | graph/ring[t.ring_] +} + +run SomeState for 1 but 2 Tick, 2 Bool, 3 Process expect 1 +check Closure for 1 but 2 Tick, 2 Bool, 3 Process expect 1 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/stable_orient_ring.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/stable_orient_ring.thm new file mode 100644 index 00000000..0a8cba73 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/stable_orient_ring.thm @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/stable_ringlead.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/stable_ringlead.als new file mode 100644 index 00000000..577257f8 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/stable_ringlead.als @@ -0,0 +1,180 @@ +module examples/algorithms/stable_ringlead + +/* + * Huang's self-stabilizing leader-election algorithm + * for rings. + */ + +open util/ordering[Process] as po +open util/ordering[Val] as vo +open util/ordering[State] as so +open util/graph[Process] as graph + +sig Process { + rightNeighbor: Process +} + +sig Val { + nextVal : Val +} + +fact { + graph/ring[rightNeighbor] + vo/next + (vo/last -> vo/first) = nextVal + # Val = # Process +} + +sig State { + val : Process -> one Val, + running : set Process + // for visualization + //leader : set Process +} { + //leader = { p : Process | LeaderAtState(p, this) } +} + +fact { + no so/last.running +} + +fun LeadersAtState[t : State] : set Process { + { p : Process | LeaderAtState[p,t] } +} + +pred LeaderAtState[p : Process, t : State] { ValAtState[p,t] = vo/first } + +fun ValAtState[p : Process, t : State] : Val { t.val[p] } + +fun LeftValAtState[p : Process, t : State] : Val { t.val[p.~rightNeighbor] } + +fun RightValAtState[p : Process, t : State] : Val { t.val[p.rightNeighbor] } + +fun XAtState[p : Process, t : State] : Int { + g[LeftValAtState[p,t],ValAtState[p,t]] +} + +fun YAtState[p : Process, t : State] : Int { + g[ValAtState[p,t],RightValAtState[p,t]] +} + +fun g[a, b : Val] : Int { + (a = b) => Int[# Val] else minus[b,a] +} + +fun minus[v1, v2 : Val] : Int { + Int[ (v1 = v2) => 0 + else vo/gt[v1, v2] => (# (vo/nexts[v2] & vo/prevs[v1] + v1)) + else (# (Val - (vo/nexts[v1] & vo/prevs[v2] + v1))) + ] +} + +fun Trans[oldVal : Val, x, y : Int] : Val { + ((int x = int y && int y = # Val) || (int x < int y)) => oldVal.nextVal else oldVal +} + +pred OneAtATimeTrans { + all tp: State - so/last | + let tn = so/next[tp] | + some p : Process | { + tp.running = p + TransHelper[p,tp,tn] + all other : Process - p | + ValAtState[other,tn] = ValAtState[other,tp] + } +} + +pred DDaemonTrans { + all tp: State - so/last | + let tn = so/next[tp] | { + some tp.running + all p : tp.running | TransHelper[p,tp,tn] + all other : Process - tp.running | + ValAtState[other,tn] = ValAtState[other,tp] + } +} + +pred TransHelper[p : Process, tp, tn : State] { + let oldVal = ValAtState[p, tp], + newVal = ValAtState[p, tn], + x = XAtState[p, tp], + y = YAtState[p,tp] | + newVal = Trans[oldVal, x, y] + +} + +pred StateTrans[s, s' : State] { + all p : Process | + TransHelper[p, s, s'] || ValAtState[p,s] = ValAtState[p,s'] +} + + + +pred CBadLivenessTrace { + OneAtATimeTrans + BadLivenessHelper +} + +pred DBadLivenessTrace { + DDaemonTrans + BadLivenessHelper +} + +pred BadLivenessHelper { + let ls = so/last | + some s : State - ls | { + s.val = ls.val + // fair + Process in (so/nexts[s] + s - ls).running + } + all s : State | ! Legit[s] + } + +pred CTraceWithoutLoop { + OneAtATimeTrans + all t, t' : State | t!=t' => t.val != t'.val +} + +pred DTraceWithoutLoop { + DDaemonTrans + all t, t' : State | t!=t' => { + t.val != t'.val + (t' in so/nexts[t] && t' != so/next[t]) => !StateTrans[t,t'] + } + all t : State | !Legit[t] +} + +pred ConvergingRun { + OneAtATimeTrans + !Legit[so/first] + some t : State | Legit[t] +} + +pred OnlyFairLoops { + OneAtATimeTrans + all s, s' : State | + (s' in so/nexts[s] && s'.val = s.val) => + (let loopStates = (so/nexts[s] & so/prevs[s']) + s + s' | Process in loopStates.running) +} + +assert CMustConverge { + OnlyFairLoops => (some s : State | Legit[s]) +} + +pred Legit [s : State] { + one LeadersAtState[s] + all p : Process | { + int XAtState[p,s] < # Val + int YAtState[p,s] < # Val + } + all p, p' : Process | { + int XAtState[p,s] = int XAtState[p',s] + int YAtState[p,s] = int YAtState[p',s] + } +} + +run ConvergingRun for 3 but 4 State expect 1 +run DTraceWithoutLoop for 3 but 4 State expect 1 +run DBadLivenessTrace for 3 but 4 State expect 1 +run CTraceWithoutLoop for 3 but 5 State expect 0 +run CBadLivenessTrace for 4 but 5 State expect 1 +check CMustConverge for 3 but 4 State expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/stable_ringlead.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/stable_ringlead.thm new file mode 100644 index 00000000..d580f3a1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/algorithms/stable_ringlead.thm @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/INSLabel.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/INSLabel.als new file mode 100644 index 00000000..9f8a2024 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/INSLabel.als @@ -0,0 +1,149 @@ +module examples/case_studies/INSLabel + +/* + * Models an Intentional Naming System (INS), a scheme for + * dynamic resource discovery in a dynamic environment. + * + * For a detailed description, see: + * http://sdg.lcs.mit.edu/pubs/2000/INS_ASE00.pdf + * + * author: Sarfraz Khurshid + */ + +sig Record {} + +sig Label {} + +sig Node { + label: Label +} + +sig LabelTree { + root: Node, + nodes: set Node, + children: nodes one -> (nodes - root) +} +{ // connected + nodes = root.*children + some root.children +} + +pred Get[db: DB, r: Record, a:Advertisement] { + root[a] = root[db] + nodes[a] = + nodes[db] & r.~(db.recs).*(~(db.children)) + anodes[a] = + anodes[db] & r.~(db.recs).*(~(db.children)) + vnodes[a] = + vnodes[db] & r.~(db.recs).*(~(db.children)) + all n: a.nodes | + n.~(a.children) = n.~(db.children) +} + +sig Attribute extends Label {} + +sig Value extends Label {} + +one sig Wildcard, Null extends Value {} + +sig AVTree extends LabelTree { + vnodes, anodes: set nodes +} +{ + root in vnodes + root.label = Null + Null !in (vnodes - root).label + anodes.label + anodes.label in Attribute + vnodes.label in Value + all n: nodes | all /* disj */ c,c': n.children | + c.label != c'.label + all a: anodes | a.children in vnodes && some a.children + all v: vnodes | v.children in anodes + no Wildcard.~label.children +} + +one sig Query extends AVTree {} +{ + all a: anodes | one a.children +} + +one sig Advertisement extends AVTree {} +{ + Wildcard !in vnodes.label +} + +one sig DB extends AVTree { + records: set Record, + recs: (vnodes - root) some -> records +} +{ + Wildcard !in vnodes.label + all a: anodes | no a.recs + all v: vnodes { + no v.children => some v.recs + no v.recs & v.^(~children).recs } + all a: anodes | all disj v,v': a.children | + (no v.*children.recs & v'.*children.recs) +} + +one sig State { + conforms: Query -> Advertisement -> Node -> Node, + lookup: DB -> Query -> Node -> Node -> Record +} + +fact ConformsFixPoint { + all q: Query | all a: Advertisement | + all nq: Node | all na: Node | + q.ConformsAux[a,nq,na] <=> + { + nq.label in Wildcard + na.label + all nq': q.children[nq] | some na': a.children[na] | + q.ConformsAux[a,nq',na'] + } +} + +pred Query.ConformsAux[a: Advertisement, nq: Node, na: Node] { + na in State.conforms[this][a][nq] +} + +pred Conforms[q: Query, a:Advertisement] { + q.ConformsAux[a, q.root, a.root] +} + +fact LookupFixPoint { + all db: DB, q: Query, T: Node, n: Node, r: Record | + r in db.LookupAux[q,T,n] <=> // record r is in the result if and only if + { + all na: n.(q.children) | all nv: na.(q.children) | // for all child av-pairs (na,nv) of av-pair n in q + some Ta: T.(db.children) { + Ta.label = na.label // Ta is a child node with attribute na + nv.label = Wildcard => // wildcard matching + r in Ta.^(db.children).(db.recs) else // r is a record of any child of Ta + (some Tv: Ta.(db.children) { // normal matching + Tv.label = nv.label // Tv is a child of Ta with value nv + no nv.(q.children) => // if Tv is a leaf-node + r in Tv.*(db.children).(db.recs) else // r is a record of Tv or of v + r in db.LookupAux[q,Tv,nv] }) } // else r is a record of the recursive call at Tv + } +} + +fun DB.LookupAux[q: Query, vd: Node, vq: Node]: set Record { // helper function for Lookup + State.lookup[this][q][vd][vq] +} + +fun Lookup[db: DB, q: Query]: set Record { // models Lookup-Name algorithm invocation + db.LookupAux[q, db.root, q.root] +} + +assert LookupConforms2 { //soundness and completeness + all q: Query | all db: DB | all r: Record | all a: Advertisement | + Get[db,r,a] => // all n: a.nodes | n.~(db.children) + {r in db.Lookup[q] <=> q.Conforms[a]} +} + +// < 10 sec +check LookupConforms2 for 4 but 1 State, 3 LabelTree, 2 Record expect 0 +// ~ 25 min +//check LookupConforms2 for 6 but 1 State, 3 LabelTree, 2 Record +//check LookupConforms2 for 6 but 1 State, 3 LabelTree, 3 Record +run Lookup for 3 expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/chord.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/chord.als new file mode 100644 index 00000000..f7a042f1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/chord.als @@ -0,0 +1,260 @@ +module examples/case_studies/chord + +/* + * Models the chord distributed hash table lookup protocol. + * + * For a detailed description, see: + * http://www.pdos.lcs.mit.edu/papers/chord:sigcomm01/ + */ + +open util/relation as rel + +sig Id {next: Id} +fact {all i: Id | Id in i.*next} + +/** + * true iff i precedes j in the order starting at from + */ +pred less_than [from, i,j: Id] { + let next' = Id<:next - (Id->from) | j in i.^next' // if from=j, returns true if # nodes > 1 + } +pred less_than_eq [from, i,j: Id] { + let next' = Id<:next - (Id->from) | j in i.*next' + } + +sig Node {id: Id} +fact {all m,n: Node | m!=n => m.id != n.id} + + +sig NodeData { + prev, next: Node, + finger: Id -> lone Node, + closest_preceding_finger: Id -> one Node, + find_predecessor: Id -> one Node, + find_successor: Id -> one Node + } + +sig State { + active: set Node, + data: active -> one NodeData + } + +/** + * node n's next node is defined to be the m where n's finger table maps the id + * that follows n.id to m + * next holds the first entry of the finger table + */ +fact {all s: State | all n: s.active | n.(s.data).next = n.(s.data).finger[n.id.next]} + +pred NextCorrect [s: State] { + all n: s.active { + -- no intervening node (ie, close enough) + no n': s.active - n | less_than [n.id, n'.id, n.(s.data).next.id] + -- can reach all other active nodes (ie, far enough) + -- need this because can't rule out case of next being node itself (because of 1-node ring) + -- s.active in n.*(s.data.next) + n.(s.data).next != n || #s.active = 1 + } + } + +pred NextCorrect' [s: State] { +-- next seems to be correct for 1,2,3 nodes + all n: s.active | let nd = (s.data)[n] { + let next' = Id<:next - (Id -> nd.next.id) { + no n' : s.active { n'.id in n.id.^next' } + }} + } + +// valid +assert Same1 {all s: State | NextCorrect[s] => NextCorrect'[s]} +check Same1 for 3 but 1 State expect 0 + +// valid unless active condition removed +assert Same2 {all s: State | s.active = Node => (NextCorrect'[s] => NextCorrect[s])} +check Same2 for 3 but 1 State expect 0 + +-- assert NextInFinger {all s: State | all n: s.active | some n.s.data.finger[n.id.next] } + + +-- says that finger entry maps an id to a node so that there are no intervening nodes +-- between the id and the node +pred FingersCorrect [s: State] { + all nd: s.active.(s.data) | all start:nd.finger.univ | + nd.finger[start] in s.active && + (no n' : s.active | less_than [start, n'.id, nd.finger[start].id]) + } + + +pred FingersCorrect' [s: State] { + all n: s.active | let nd = (s.data)[n] | all start: Node.~(nd.finger) { + nd.finger[start] in s.active && + (let next' = Id<:next - (nd.finger[start].id -> Id) { + no n' : s.active - nd.finger[start] { + n'.id in start.*next' + } + }) + } + } + + +assert SameFC {all s: State | FingersCorrect [s] iff FingersCorrect'[s]} +check SameFC for 3 but 1 State expect 0 + + +pred ShowMeFC { + all s : State | s.active = Node && FingersCorrect[s] +} + +run ShowMeFC for 2 but 1 State expect 1 + +pred ClosestPrecedingFinger[s: State] { + all n: s.active | let nd = n.(s.data) | + all i: Id | let cpf = nd.closest_preceding_finger[i] { + no n': nd.finger[Id] + n - cpf | less_than [cpf.id, n'.id, i] + cpf in nd.finger[Id] + n + cpf.id != i || # s.active = 1 + //less_than (n.id, cpf.id, i) + } + } + + +pred ClosestPrecedingFinger'[s: State] { + all n: s.active | let nd = (s.data)[n] | all i: Id { + let next' = Id<:next - (Id -> i) { + nd.next.id in n.id.^next' => + // nd.closest_preceding_finger[i] = nd.next, + (some n1: nd.finger[Id] { + nd.closest_preceding_finger[i] = n1 + //n1 in nd.finger[Id] + n1.id in n.id.^next' + no n2: nd.finger[Id] | n2.id in n1.id.^next' + }) else + nd.closest_preceding_finger[i] = n + }} + } + + +assert SameCPF {all s: State | FingersCorrect[s] => (ClosestPrecedingFinger [s] iff ClosestPrecedingFinger' [s])} +assert SameCPF1 {all s: State | FingersCorrect[s] => (ClosestPrecedingFinger [s] => ClosestPrecedingFinger' [s])} +assert SameCPF2 { + all s: State | ((s.active = Node && FingersCorrect[s] && ClosestPrecedingFinger' [s]) + => ClosestPrecedingFinger [s]) } + +check SameCPF for 3 but 1 State expect 0 +check SameCPF1 for 2 but 1 State expect 0 +check SameCPF2 for 3 but 1 State expect 0 + + +pred ShowMeCPF { + all s : State | s.active = Node && FingersCorrect[s] && + // not ClosestPrecedingFinger(s) && ClosestPrecedingFinger'(s) + ClosestPrecedingFinger[s] + //all s : State | all nd : s.active.s.data | nd.finger[Id] = Node + # Node = 2 + # State = 1 +} + + +run ShowMeCPF for 2 but 1 State expect 1 + + +pred FindPredecessor[s: State] { + all n: s.active | let nd = n.(s.data) | all i: Id { + nd.find_predecessor[i] = + (less_than_eq [n.id, i, nd.next.id] && (n.id != i || # s.active = 1) + => n + else (nd.closest_preceding_finger[i].(s.data).find_predecessor)[i]) + } + } + + +assert FPisActive { + all s: State | FingersCorrect[s] && ClosestPrecedingFinger[s] && FindPredecessor[s] + => (all n: s.active | all nd: n.(s.data) | nd.find_predecessor[Id] in s.active) } +check FPisActive for 3 but 1 State expect 1 + + +pred FindPredecessor'[s: State] { + all n: s.active | let nd = (s.data)[n] | all i: Id { + let next' = Id<:next - (nd.next.id -> Id) { + one s.active or i in n.id.^next' => // *next' -> ^next' 1/8/02 + nd.find_predecessor[i] = n else + nd.find_predecessor[i] = + ((s.data)[nd.closest_preceding_finger[i]]).find_predecessor[i] + }} + } + + +assert SameFP {all s: State | FingersCorrect[s] // && s.active = Node + => (FindPredecessor [s] iff FindPredecessor' [s])} + +assert SameFP1 { + all s: State | FingersCorrect[s] && s.active = Node + => (FindPredecessor [s] => FindPredecessor' [s])} +assert SameFP2 { + all s: State | FingersCorrect[s] && s.active = Node + => (FindPredecessor' [s] => FindPredecessor [s])} + +check SameFP for 3 but 1 State expect 1 +check SameFP1 for 3 but 1 State expect 0 +check SameFP2 for 3 but 1 State expect 0 + + +pred FindSuccessor[s: State] { + all n: s.active | let nd = (s.data)[n] | all i: Id { + nd.find_successor[i] = ((s.data)[nd.find_predecessor[i]]).next + }} + + +// should be able to check that closest_p_f, etc returns +// only active nodes if FingersCorrect. + + +pred ShowMe1Node { + #Node = 1 + all s : State | NextCorrect[s] + State.active = Node +} + +run ShowMe1Node for 2 but 1 State, 1 Node expect 1 + +pred ShowMe1 { + #Node = 2 + #State = 1 + all s : State | NextCorrect[s] + State.active = Node +} + + +pred ShowMe2 { + #Node = 3 + #State = 1 + all s : State | NextCorrect[s] && FingersCorrect[s] + State.active = Node + //all n: NodeData | one n.finger[Id] +} + + +assert OK1 { + #Node = 3 && + #State = 1 && + (all s : State | NextCorrect[s] && FingersCorrect[s]) && + State.active = Node +} + + +run ShowMe1 for 3 expect 1 +run ShowMe2 for 3 expect 1 + +assert InjectiveIds {all i, j: Id | i!=j => i.next != j.next} +check InjectiveIds for 5 expect 0 + + +assert FindSuccessorWorks { + all s: State, i: Id | + let nd = s.active.(s.data) | + let succ = nd.find_successor [i] | + FingersCorrect [s] // && s.active = Node + => (no n': s.active | less_than [i, n'.id, succ.id]) + } +check FindSuccessorWorks for 3 but 1 State expect 1 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/chord2.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/chord2.als new file mode 100644 index 00000000..ea7c3429 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/chord2.als @@ -0,0 +1,274 @@ +module examples/case_studies/chord2 + +/* + * Models the chord distributed hash table lookup protocol. + * + * For a detailed description, see: + * http://www.pdos.lcs.mit.edu/papers/chord:sigcomm01/ + */ + +open util/relation as rel + +sig Id {next: Id} +fact {all i: Id | Id in i.*next} + +/** + * true iff i precedes j in the order starting at from + */ +pred less_than [from, i,j: Id] { + let next' = Id<:next - (Id->from) | j in i.^next' // if from=j, returns true if # nodes > 1 + } +pred less_than_eq [from, i,j: Id] { + let next' = Id<:next - (Id->from) | j in i.*next' + } + +sig Node {id: Id} +fact {all m,n: Node | m!=n => m.id != n.id} + +sig NodeData { + prev, next: Node, + finger: Id -> lone Node, + closest_preceding_finger: Id -> one Node, + find_predecessor: Id -> one Node, + find_successor: Id -> one Node + } + +sig State { + active: set Node, + data: active -> one NodeData + } + +/** + * node n's next node is defined to be the m where n's finger table maps the id + * that follows n.id to m + * next holds the first entry of the finger table + */ +fact {all s: State | all n: s.active | n.(s.data).next = n.(s.data).finger[n.id.next]} + +pred NextCorrect [s: State] { + all n: s.active { + -- no intervening node (ie, close enough) + no n': s.active - n | less_than [n.id, n'.id, n.(s.data).next.id] + -- can reach all other active nodes (ie, far enough) + -- need this because can't rule out case of next being node itself (because of 1-node ring) + -- s.active in n.*(s.data.next) + n.(s.data).next != n || #s.active = 1 + } + } + +/* +-- abortive attempt at simplifying next condition +fun NextCorrect" (s: State) { + all n: s.active | let nx = s.data.next { + s.active in n.*nx + less_than (n.id, n.id, n.nx.id) + } + } +*/ + +pred NextCorrect' [s: State] { +-- next seems to be correct for 1,2,3 nodes + all n: s.active | let nd = (s.data)[n] { + let next' = Id<:next - (Id -> nd.next.id) { + no n' : s.active { n'.id in n.id.^next' } + }} + } + +assert Same1 {all s: State | NextCorrect[s] => NextCorrect'[s]} +//check Same1 for 3 but 1 State -- valid +assert Same2 {all s: State | s.active = Node => (NextCorrect'[s] => NextCorrect[s])} +//check Same2 for 3 but 1 State -- invalid if active condition removed + +-- assert NextInFinger {all s: State | all n: s.active | some n.s.data.finger[n.id.next] } + +/** + * says that finger entry maps an id to a node so that there are no intervening nodes + * between the id and the node + */ +pred FingersCorrect [s: State] { + all nd: s.active.(s.data) | all start:nd.finger.univ | + nd.finger[start] in s.active && + (no n' : s.active | less_than [start, n'.id, nd.finger[start].id]) + } + +pred FingersCorrect' [s: State] { + all n: s.active | let nd = (s.data)[n] | all start: Node.~(nd.finger) { + nd.finger[start] in s.active && + (let next' = Id<:next - (nd.finger[start].id -> Id) { + no n' : s.active - nd.finger[start] { + n'.id in start.*next' + }})} + } + +assert SameFC {all s: State | FingersCorrect [s] iff FingersCorrect'[s]} +//check SameFC for 3 but 1 State + +pred ShowMeFC { + all s : State | s.active = Node && FingersCorrect[s] +} + +//run ShowMeFC for 2 but 1 State + +/* +fun ClosestPrecedingFinger(s: State) { + all n: s.active | let nd = n.s.data | + all i: Id | let cpf = nd.closest_preceding_finger[i] { + no n': nd.finger[Id] | less_than (cpf.id, n'.id, i) + cpf in nd.finger[Id] + n + less_than (n.id, cpf.id, i) + } + } +*/ + +pred ClosestPrecedingFinger_SAVE [s: State] { + all n: s.active | let nd = n.(s.data) | + all i: Id | let cpf = nd.closest_preceding_finger[i] { + no n': (nd.finger[Id] + n) - cpf | less_than [cpf.id, n'.id, i] + cpf in nd.finger[Id] + n + cpf.id != i || # s.active = 1 + //less_than (n.id, cpf.id, i) + } + } + +pred CPFBody [s: State, n: Node, nd: NodeData, i: Id, cpf: Node] { + no n': (nd.finger[Id] + n) - cpf | less_than [cpf.id, n'.id, i] + cpf in nd.finger[Id] + n + cpf.id != i || # s.active = 1 + } +pred ClosestPrecedingFinger[s: State] { + all n: s.active | let nd = n.(s.data) | + all i: Id | + some cpf: Node | CPFBody [s,n,nd,i,cpf] => CPFBody [s,n,nd,i,nd.closest_preceding_finger[i]] + } + +pred ClosestPrecedingFinger'[s: State] { + all n: s.active | let nd = (s.data)[n] | all i: Id { + let next' = Id<:next - (Id -> i) { + nd.next.id in n.id.^next' => + // nd.closest_preceding_finger[i] = nd.next, + (some n1: nd.finger[Id] { + nd.closest_preceding_finger[i] = n1 + //n1 in nd.finger[Id] + n1.id in n.id.^next' + no n2: nd.finger[Id] | n2.id in n1.id.^next' + }) else + nd.closest_preceding_finger[i] = n + }} + } + +assert SameCPF {all s: State | FingersCorrect[s] => (ClosestPrecedingFinger [s] iff ClosestPrecedingFinger' [s])} +assert SameCPF1 {all s: State | FingersCorrect[s] => (ClosestPrecedingFinger [s] => ClosestPrecedingFinger' [s])} +assert SameCPF2 { + all s: State | ((s.active = Node && FingersCorrect[s] && ClosestPrecedingFinger' [s]) + => ClosestPrecedingFinger [s]) } +//check SameCPF for 3 but 1 State +//check SameCPF1 for 2 but 1 State +//check SameCPF2 for 3 but 1 State + +pred ShowMeCPF { + all s : State | s.active = Node && FingersCorrect[s] && + // not ClosestPrecedingFinger(s) && ClosestPrecedingFinger'(s) + ClosestPrecedingFinger[s] + //all s : State | all nd : s.active.s.data | nd.finger[Id] = Node + # Node = 2 + # State = 1 +} + +//run ShowMeCPF for 2 but 1 State + +pred FindPredecessor[s: State] { + all n: s.active | let nd = n.(s.data) | all i: Id { + nd.find_predecessor[i] = + ((less_than_eq [n.id, i, nd.next.id] && (n.id != i || # s.active = 1)) + => n + else (nd.closest_preceding_finger[i].(s.data).find_predecessor)[i]) + } + } +-- problem : could return node that's inactive ??? + +assert FPisActive { + all s: State | FingersCorrect[s] && ClosestPrecedingFinger[s] && FindPredecessor[s] + => (all n: s.active | all nd: n.(s.data) | nd.find_predecessor[Id] in s.active) +} + +//check FPisActive for 3 but 1 State + +pred FindPredecessor'[s: State] { + all n: s.active | let nd = (s.data)[n] | all i: Id { + let next' = Id<:next - (nd.next.id -> Id) { + one s.active or i in n.id.^next' => + nd.find_predecessor[i] = n else + nd.find_predecessor[i] = + ((s.data)[nd.closest_preceding_finger[i]]).find_predecessor[i] + }} + } + +assert SameFP {all s: State | FingersCorrect[s] && s.active = Node + => (FindPredecessor [s] iff FindPredecessor' [s])} +assert SameFP1 { + all s: State | FingersCorrect[s] && s.active = Node + => (FindPredecessor [s] => FindPredecessor' [s])} +assert SameFP2 { + all s: State | FingersCorrect[s] && s.active = Node + => (FindPredecessor' [s] => FindPredecessor [s])} +//check SameFP for 3 but 1 State +//check SameFP1 for 3 but 1 State +//check SameFP2 for 3 but 1 State + +pred FindSuccessor[s: State] { + all n: s.active | let nd = (s.data)[n] | all i: Id { + nd.find_successor[i] = ((s.data)[nd.find_predecessor[i]]).next + }} + +fact { all s : State { + ClosestPrecedingFinger[s] + FindPredecessor[s] + FindSuccessor[s] + }} + +// should be able to //check that closest_p_f, etc returns +// only active nodes if FingersCorrect. + +pred ShowMe1Node { + #Node = 1 + all s : State | NextCorrect[s] + State.active = Node +} + +//run ShowMe1Node for 2 but 1 State, 1 Node +-- does the expected correct thing for 1 node. + +pred ShowMe1 { + #Node = 2 + #State = 1 + all s : State | NextCorrect[s] + State.active = Node +} + +pred ShowMe2 { + #Node = 3 + #State = 1 + all s : State | NextCorrect[s] && FingersCorrect[s] + State.active = Node + //all n: NodeData | one n.finger[Id] +} + +assert OK1 { + #Node = 3 && + #State = 1 && + (all s : State | NextCorrect[s] && FingersCorrect[s]) && + State.active = Node +} + +assert FindSuccessorWorks { + all s: State, i: Id | + let nd = s.active.(s.data) | + let succ = nd.find_successor [i] | + FingersCorrect [s] + => { + no n': s.active | less_than [i, n'.id, succ.id] + succ in s.active + } + } + +check FindSuccessorWorks for 4 but 1 State, 3 Node, 3 NodeData expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/chordbugmodel.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/chordbugmodel.als new file mode 100644 index 00000000..de6c36bb --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/chordbugmodel.als @@ -0,0 +1,232 @@ +module examples/case_studies/chord + +/* + * Models the chord distributed hash table lookup protocol. + * + * For a detailed description, see: + * http://www.pdos.lcs.mit.edu/papers/chord:sigcomm01/ + */ + +sig Id {next: Id} +fact {all i: Id | Id in i.*next} + +pred less_than [from, i,j: Id] { + let next' = Id<:next - (Id->from) | j in i.^next' +} + +pred less_than_eq [from, i,j: Id] { + let next' = Id<:next - (Id->from) | j in i.*next' +} + +sig Node {id: Id} +fact {all m,n: Node | m!=n => m.id != n.id} + +sig NodeData { + next: Node, + finger: Id -> lone Node, + closest_preceding_finger: Id -> one Node, + find_successor: Id -> one Node +} + +sig State { + active: set Node, + data: active -> one NodeData +} + +fact { + all s: State | all n: s.active | + n.(s.data).next = n.(s.data).finger[n.id.next] +} + +pred NextCorrect [s: State] { + all n: s.active | let succ = n.(s.data).next { + no n': s.active - n | less_than [n.id, n'.id, succ.id] + succ != n || #s.active = 1 + succ in s.active + } +} + +pred FingersCorrect [s: State] { + all nd: s.active.(s.data) | all start: (nd.finger).Node | + nd.finger[start] in s.active && + (no n' : s.active | less_than [start, n'.id, nd.finger[start].id]) +} + +pred save_ClosestPrecedingFinger [s: State] { + all n: s.active | let nd = n.(s.data) | + all i: Id | let cpf = nd.closest_preceding_finger[i] { + no n': (nd.finger[Id] + n) - cpf | less_than [cpf.id, n'.id, i] + cpf in nd.finger[Id] + n + cpf.id != i || # s.active = 1 + } +} + +pred save_FindSuccessor[s: State] { + all n: s.active | let nd = n.(s.data) | all i: Id { + nd.find_successor[i] = + (((less_than_eq [n.id, i, nd.next.id] && n.id != i) || # s.active = 1) + => nd.next + else + (nd.closest_preceding_finger[i].(s.data).find_successor)[i]) + } +} + +pred IrrelevantFact1 { + all s : State { + ClosestPrecedingFinger[s] + FindSuccessor[s] + } +} + +pred ShowMe1Node { + #Node = 1 + all s : State | NextCorrect[s] && FingersCorrect[s] + State.active = Node +} + +run ShowMe1Node for 2 but 1 State, 1 Node expect 1 + +pred ShowMeGood { + #Id = 4 + all s : State | NextCorrect[s] && FingersCorrect[s] + State.active = Node +} + +run ShowMeGood for 4 but 1 State, 2 Node expect 1 + +pred FindSuccessorIsCorrect[s: State] { + all i: Id | all n: s.active | + let succ = (n.(s.data)).find_successor [i] { + succ in s.active + no n': s.active | less_than [i, n'.id, succ.id] + } +} + +pred ShowMeCorrectSuccessorEg { + #Node = 3 + State.active = Node + all s: State | FingersCorrect[s] && FindSuccessorIsCorrect[s] +} + +run ShowMeCorrectSuccessorEg for 3 but 1 State expect 1 + +pred ShowMe3 { + #Id = 5 + #Node = 3 + #State = 1 + all s : State | NextCorrect[s] && !FingersCorrect[s] + State.active = Node +} + +run ShowMe3 for 5 but 1 State expect 1 + +pred FindSuccessorWorks { + IrrelevantFact1 + ! ( + all s: State | FingersCorrect[s] + => FindSuccessorIsCorrect[s] + ) +} + +assert StrongerFindSuccessorWorks { + all s: State | NextCorrect[s] => FindSuccessorIsCorrect[s] +} + +run FindSuccessorWorks for 4 but 1 State expect 0 +check StrongerFindSuccessorWorks for 4 but 1 State expect 1 + +/* +\section Variations + +In the pseudocode presented in [\cite{chord1}, +\cite{chord2}], there is some ambiguity as to what the +expression \tt<(n, n.successor]> means in boundary cases +where there is exactly one node and \tt. +The intention of the authors is that the set includes +\tt. We consider variations of the alloy model with the +bug where the set \tt<(n, n]> does not include \tt, and +observe how it affects the \tt and +the \tt routines. + +\subsection faulty \tt + +Suppose we change \tt as follows: + +\code +*/ + +pred ClosestPrecedingFinger [s: State] { + all n: s.active | let nd = n.(s.data) | + all i: Id | let cpf = nd.closest_preceding_finger[i] { + no n': (nd.finger[Id] + n) - cpf | less_than [cpf.id, n'.id, i] + cpf in nd.finger[Id] + n + cpf.id != i + } +} + +/* +The only change here is in the last line +\cite{cpf-variation}, where we removed the clause \tt< || # +s.active=1>. The assertion \tt will +still hold for scope up to 4, but \tt will fail +to generate an example! This is an example of a +over-constraint, where the inconsistency only shows up when +there is exactly one node. What happens here is that the +model requires that a closest preceding finger node has a +distinct identifier from the input identifier, but this +cannot happen if there is exactly one node and if the input +identifer equals that of the node. + +\subsection faulty \tt + +Consider the following pseudocode segment from [\cite{chord2}]: + +n.find_successor(id) + if (id in (n, n.successor]) + return n.successor; + else + n' = closest_preceding_finger(id); + return n'.find_successor(id); + +In the buggy scenario with a single node, the \tt loop +always terminates at \cite{if-condition1}, leading to an +infinite loop. + +Consider the corresponding change to \tt as follows: + +*/ + +pred FindSuccessor[s: State] { + all n: s.active | let nd = n.(s.data) | all i: Id { + nd.find_successor[i] = + ((less_than_eq [n.id, i, nd.next.id] && n.id != i) + => nd.next + else + (nd.closest_preceding_finger[i].(s.data).find_successor)[i]) + } +} + +/* +The only change here is in the fourth line +\cite{sf-variation}, where we removed the clause \tt< || # +s.active = 1>. For the same reason, the \tt loop +in this case always proceeds to the \tt clause, +and since \tt always returns +\tt (the only node in the network), we end up +with a tautological statement: + +\code + nd.find_successor[i] = n.s.data.find_successor)[i] + +This means that there is no additional constraint placed on +\tt, other than that its return type is +\tt. Now, if there is no distinction between active +and inactive nodes, that is, we have exactly one active node +in the network and no inactive ones, \tt +will return the right answer due to the type constraint, +therefore obscuring the bug. On the other hand, since we +have introduced inactive nodes, the assertion +\tt now fails with exactly one active +node and some inactive node(s), with \tt +returning an inactive node. +*/ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/com.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/com.als new file mode 100644 index 00000000..8cf6f08c --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/com.als @@ -0,0 +1,96 @@ +module examples/case_studies/com + +/* + * Model of Microsoft Component Object Model (COM) query + * interface and aggregation mechanism. + * + * For a detailed description, see: + * http://sdg.lcs.mit.edu/~dnj/publications/com-fse00.pdf + * + * author: Daniel Jackson + */ + +open util/relation as rel + +sig IID {} + +sig Interface { + qi : IID -> lone Interface, + iids : set IID, + // next two lines should use domain() or range() functions + iidsKnown : IID, + reaches : Interface +}{ + iidsKnown = dom[qi] + reaches = ran[qi] +} + +sig Component { + interfaces : set Interface, + iids : set IID, // can't do iids = interfaces.Interface$iids + first, identity : interfaces, + eqs: set Component, + aggregates : set Component +} + +fact defineEqs { + all c1, c2: Component | + c1->c2 in eqs <=> c1.identity = c2.identity +} + +fact IdentityAxiom { + some unknown : IID | all c : Component | + all i : c.interfaces | unknown.(i.qi) = c.identity +} + +fact ComponentProps { + all c : Component { + c.iids = c.interfaces.iids + all i : c.interfaces | all x : IID | x.(i.qi) in c.interfaces + } +} + +sig LegalInterface extends Interface { } +fact { all i : LegalInterface | all x : i.iidsKnown | x in x.(i.qi).iids} + +sig LegalComponent extends Component { } +fact { LegalComponent.interfaces in LegalInterface } + +fact Reflexivity { all i : LegalInterface | i.iids in i.iidsKnown } +fact Symmetry { all i, j : LegalInterface | j in i.reaches => i.iids in j.iidsKnown } +fact Transitivity { all i, j : LegalInterface | j in i.reaches => j.iidsKnown in i.iidsKnown } + +fact Aggregation { + no c : Component | c in c.^aggregates + all outer : Component | all inner : outer.aggregates | + (some inner.interfaces & outer.interfaces) + && (some o: outer.interfaces | all i: inner.interfaces - inner.first | all x: Component | (x.iids).(i.qi) = (x.iids).(o.qi)) + } + +assert Theorem1 { + all c: LegalComponent | all i: c.interfaces | i.iidsKnown = c.iids + } + +assert Theorem2 { + all outer: Component | all inner : outer.aggregates | + inner in LegalComponent => inner.iids in outer.iids + } + +assert Theorem3 { + all outer: Component | all inner : outer.aggregates | inner in outer.eqs + } + +assert Theorem4a { + all c1: Component, c2: LegalComponent | + some (c1.interfaces & c2.interfaces) => c2.iids in c1.iids + } + +assert Theorem4b { + all c1, c2: Component | some (c1.interfaces & c2.interfaces) => c1 in c2.eqs + } + +check Theorem1 for 3 expect 0 +check Theorem2 for 3 expect 0 +check Theorem3 for 3 expect 0 +check Theorem4a for 3 expect 0 +check Theorem4b for 3 expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/firewire.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/firewire.als new file mode 100644 index 00000000..5de1afaf --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/firewire.als @@ -0,0 +1,384 @@ +module examples/case_studies/firewire + +/* + * A model of leader election in the Firewire protocol. + * + * Adapted from: + * [DG+01] M.C.A. Devillers, W.O.D. GriAEoen, J.M.T Romijn, and F.W. Vaandrager. + * Verification of a leader election protocol -- formal methods applied to IEEE + * 1394. Technical Report CSI-R9728, Computing Science Institute, University of + * Nijmegen, December 1997. Also, Formal Methods in System Design, 2001. + * + * This model describes a leader election protocol used in Firewire, an IEEE + * standard for connecting consumer electronic devices. The model is a + * straightforward translation into Alloy of a model [DG+01] developed in Lynch's + * IO Automata which has been analyzed using PVS, a theorem prover, but which, as + * far as we know, has not been subjected to fully automatic analysis. We are able + * to express the key correctness property -- that exactly one leader is elected + * -- more directly, as a trace property rather than a refinement property, and + * can check it without the need for the 15 invariants used in the more + * traditional proof. And the analysis does not hardwire + * a particular topology, so would be tricky to do with a standard model checker. + * + * The network is assumed to consist of a collection of nodes connected by + * links. Each link between a pair of nodes is matched by a link in the other + * direction. Viewing a link and its dual as a single, undirected edge, the + * network as a whole is assumed to form a tree. The purpose of the algorithm is + * to construct such a tree; in the model, this is achieved by labelling some + * subset of the links as parent links (each pointing from a node to its parent), + * and by marking a single node as the root. + * + * The algorithm, described in detail elsewhere [DG+01], works briefly as + * follows. When a node detects that all of its incoming links (or all but one) + * has been marked as a parent link, it sends a message on each outgoing link, + * either an acknowledgment (indicating its willingness to act as parent), or a + * request (indicating its desire to be a child), according to whether the dual of + * the outgoing link has been marked or not. Leaf nodes (with only one incoming + * link) may thus initiate the algorithm by sending requests to their adjacent + * nodes. Performing this action changes a node's status from {\em waiting} to + * {\em active}. A node that is still waiting, and which receives a message on a + * link, may label that link a parent link. Once active, a node that receives an + * acknowledgment on a link may also label the link, but if it receives a request, + * instead changes its node status to {\em contending}. The resolving of + * contentions is modelled simplistically by a single action that arbitrarily + * labels one of the two links a pair of contending nodes. Finally, a node all of + * whose incoming links are parent links designates itself a root. + * + * The specification is given below. Each signature introduces a basic type + * and some relations whose first column has that type: + * + * \begin{itemize} + * + * \item {\em Msg} represents the type of messages. {\em Req} is the request + * message and {\em Ack} is the acknowledgment message; these are actually + * declared as singleton (keyword {\em static}) subsets of {\em Msg}, the set of + * all messages, that form a partition (keyword {\em part}). + * + * \item {\em Node} represents the nodes of the network. The relations {\em to} + * and {\em from} associate each node with a set of incoming and outgoing links + * respectively. + * + * \item {\em Link} represents the links. The relations {\em target} and {\em + * source} map a link to its end nodes; {\em reverse} maps a link to its dual. The + * facts in the signatures {\em Node} and {\em Link} ensure that all these + * relations are consistent with one another: that the incoming links of a node + * are those whose target is that node, etc. + * + * \item {\em Op} introduces a set of names for the operations of the + * protocol. This is merely for convenience; it allows us to ask for an execution + * in which named operations occur, or example. + * + * \item {\em State} represents the global states. Each state has a partition of + * the nodes into one of four statuses: {\em waiting} to participate, {\em active} + * (having sent messages on outgoing links), {\em contending} (having sent a + * request on a link and received a request on its dual), and {\em elected} + * (having designated itself as a root). A set of links are labelled as parent + * links. There is a message queue associated with each link. Finally, the state + * is associated with the operation that produced it. + * + * \item {\em Queue} represents the message queues. Each queue has a slot that + * optionally contains a message; the relation {\em slot} is a partial function + * from queues to messages. In our first attempt at a model, we represented a + * queue as a sequence (a partial function from a prefix of the integers to + * messages), but having checked that no queue ever contained more than one + * message, we simplified the model. The {\em overflow} field is included just in + * case this was a mistake; a write to a queue that already contains a message + * puts an arbitrary value there, which is easily detected. + * + * \end{itemize} + * + * The {\em facts} record the assumptions about the topology. The one named {\em + * Topology} says that there is some partial function on nodes and some root such + * that (1) every node is reachable from the root ({\tt *r} being the reflexive + * transitive closure of the relation {\tt r}); (2) there are no cycles (expressed + * by saying that the transitive closure has no intersection with the identity + * relation on nodes); and (3) the relation obtained by following the {\em source} + * relation backwards (from a node to the link for which it is a source), and then + * the {\em target} relation forwards (from the link to its target) is this + * relation, plus its transpose (so that each tree edge becomes two + * links). Although the quantifier appears to be higher-order, it will be + * skolemized away by the analyzer. + * + * The {\em functions} of the model are parameterized formulas. The function {\em + * Trans} relates a pre-state {\tt s} to a post-state {\tt s'}. It has a case for + * each operation. Look at the clause for the operation {\em WriteReqOrAck}, for + * example. If this operation is deemed to have occurred, each of the constraints + * in the curly braces must hold. The first says that the labelling of links as + * parent links is unchanged. The second constraint (the quantified formula) + * constrains with respect to the node at which the operation occurs. The + * subformulas, from first to last, say that the node belongs to the waiting set + * before and the active set afterwards; that there is at most one ({\em sole}) + * link that is incoming but not a parent link in the pre-state; that there are no + * changes to node status except at this node; that a message is queued onto each + * outgoing link; and that queues on all other links are unchanged. + * + * An 'invoked' function is simply short for the formula in its body with the + * formal arguments replaced by the actual expressions. {\em WriteQueue}, for + * example, says that if the queue's slot is not filled in the pre-state, then the + * new queue in the post-state (given the local name {\tt q}) contains the message + * {\tt m} in its slot, and has no message in its overflow. Otherwise, some + * message is placed arbitrarily in the overflow, and the slot is + * unconstrained. In {\em WriteReqOrAck}, the arguments {\tt s} and {\tt s'} are + * bound to the {\tt s} and {\tt s'} of {\em Trans}; {\tt x} is bound to one of + * the outgoing links from the set {\tt n.from}; and {\tt msg} is bound either to + * the acknowledgment or request message. + * + * The function {\em Execution} constrains the set of states. It makes use of a + * library module that defines a polymorphic ordering relation. The expression + * {\tt Ord[State]} gives an ordering on all states. The two formulas of the + * function say that {\tt Initialization} holds in the first state, and that any + * pair of adjacent states is related by {\tt Trans}. The function {\em NoRepeats} + * adds the constraints that there are no equivalent states in the trace, and that + * no stuttering occurs. + * + * The three assertions are theorems for which the analyzer will search for + * counterexamples. They assert respectively that: in every state of the trace, + * there is at most one node that has been elected; that there is some state in + * which a node has been elected; and that no queue overflows. + * + * The rest of the model is a collection of commands executed to find instances of + * the functions or counterexamples to the theorems. We started by presenting a + * variety of functions as a sanity check; here, only one is given, that asks for + * an execution involving 2 nodes, 4 links, 4 queues and a trace of 6 states. The + * standard semantics of these {\em scope} declarations in Alloy is that the + * numbers represent an upper bound, so an instance may involve fewer than 4 + * queues, for example. The ordering module (not shown here), however, for + * technical reasons, constrains the ordered set to match its scope, so a trace + * with fewer than 6 states will not be acceptable. + * + * We then established some bounds on the diameter of the state machine for + * various topology bounds. For 2 nodes and 2 links, for example, there are no + * non-repeating traces of length 4; checking traces of length 3 is thus + * sufficient in this case. The number of queues was limited to 5, to accommodate + * the empty queue, a queue containing an {\tt Ack} or {\tt Req}, and each of + * these with overflow. For 3 nodes and 6 links, a trace length of 8 suffices. + * + * We then checked that for these various topology bounds, the queues never + * overflow. Finally, we checked the correctness properties, taken advantage of + * the earlier results that justify the short traces and queues. We are thus able + * to verify the properties for all topologies involving the given number of nodes + * and links, without any assumptions about trace length, queue size or the + * particular topological structure. + * + * author: Daniel Jackson + * visualization: Robert Seater + */ + +open util/ordering[State] as ord + +abstract sig Msg {} +one sig Req, Ack extends Msg {} + +sig Node {to, from: set Link} { + to = {x: Link | x.target = this} + from = {x: Link | x.source = this} + } + +sig Link {target, source: Node, reverse: Link} { + reverse.@source = target + reverse.@target = source + } + +/** + * at most one link between a pair of nodes in a given direction + */ +fact {no x,y: Link | x!=y && x.source = y.source && x.target = y.target} + +/** + * topology is tree-like: acyclic when viewed as an undirected graph + */ +fact Topology { +some tree: Node lone -> Node, root: Node { + Node in root.*tree + no ^tree & iden & Node->Node + tree + ~tree = ~source.target + } +} + +sig Op {} +one sig Init, AssignParent, ReadReqOrAck, Elect, WriteReqOrAck, +ResolveContention, Stutter extends Op {} + +sig State { + disj waiting, active, contending, elected: set Node, + parentLinks: set Link, + queue: Link -> one Queue, + op: Op -- the operation that produced the state + } { + waiting + active + contending + elected = Node +} + +pred SameState [s, s': State] { + s.waiting = s'.waiting + s.active = s'.active + s.contending = s'.contending + s.elected = s'.elected + s.parentLinks = s'.parentLinks + all x: Link | SameQueue [s.queue[x], s'.queue[x]] + } + +pred Trans [s, s': State] { + s'.op != Init + s'.op = Stutter => SameState [s, s'] + s'.op = AssignParent => { + some x: Link { + x.target in s.waiting & s'.waiting + NoChangeExceptAt [s, s', x.target] + ! IsEmptyQueue [s, x] + s'.parentLinks = s.parentLinks + x + ReadQueue [s, s', x] + }} + s'.op = ReadReqOrAck => { + s'.parentLinks = s.parentLinks + some x: Link { + x.target in s.(active + contending) & (PeekQueue [s, x, Ack] => s'.contending else s'.active) + NoChangeExceptAt [s, s', x.target] + ! IsEmptyQueue [s, x] + ReadQueue [s', s, x] + }} + s'.op = Elect => { + s'.parentLinks = s.parentLinks + some n: Node { + n in s.active & s'.elected + NoChangeExceptAt [s, s', n] + n.to in s.parentLinks + QueuesUnchanged [s, s', Link] + }} + s'.op = WriteReqOrAck => { + -- note how this requires access to child ptr + s'.parentLinks = s.parentLinks + some n: Node { + n in s.waiting & s'.active + lone n.to - s.parentLinks + NoChangeExceptAt [s, s', n] + all x: n.from | + let msg = (x.reverse in s.parentLinks => Ack else Req) | + WriteQueue [s, s', x, msg] + QueuesUnchanged [s, s', Link - n.from] + }} + s'.op = ResolveContention => { + some x: Link { + let contenders = x.(source + target) { + contenders in s.contending & s'.active + NoChangeExceptAt [s, s', contenders] + } + s'.parentLinks = s.parentLinks + x + } + QueuesUnchanged [s, s', Link] + } +} + +pred NoChangeExceptAt [s, s': State, nodes: set Node] { + let ns = Node - nodes { + ns & s.waiting = ns & s'.waiting + ns & s.active = ns & s'.active + ns & s.contending = ns & s'.contending + ns & s.elected = ns & s'.elected + }} + +sig Queue {slot: lone Msg, overflow: lone Msg} + +pred SameQueue [q, q': Queue] { + q.slot = q'.slot && q.overflow = q'.overflow + } + +pred ReadQueue [s, s': State, x: Link] { +-- let q = s'.queue[x] | no q.(slot + overflow) + no s'.queue[x].(slot + overflow) + all x': Link - x | s'.queue[x'] = s.queue[x'] + } + +pred PeekQueue [s: State, x: Link, m: Msg] { + m = s.queue[x].slot + } + +pred WriteQueue [s, s': State, x: Link, m: Msg] { + let q = s'.queue[x] | + no s.queue[x].slot => + ( q.slot = m && no q.overflow) else + some q.overflow + } + +pred QueuesUnchanged [s, s': State, xs: set Link] { + all x: xs | s'.queue[x] = s.queue[x] + } + +pred IsEmptyQueue [s: State, x: Link] { + no s.queue[x].(slot + overflow) +-- let q = s.queue[x] | no q.(slot + overflow) + } + +pred Initialization [s: State] { + s.op = Init + Node in s.waiting + no s.parentLinks + all x: Link | IsEmptyQueue [s, x] + } + +pred Execution { + Initialization [ord/first] + all s: State - ord/last | let s' = ord/next[s] | Trans [s, s'] + } + +pred ElectionHappens { + Execution + some s: State | some s.elected + some s: State | no s.elected +} + +pred NoRepeats { + Execution + no s, s': State | s!=s' && SameState [s, s'] + no s: State | s.op = Stutter + } + +pred NoShortCuts { + all s: State | -- remove this to speed up analysis - Ord[State].last - OrdPrev (Ord[State].last) | + ! Trans [s, ord/next[ord/next[s]]] + } + +assert AtMostOneElected { + Execution => (all s: State | lone s.elected) + } + +assert OneEventuallyElected { + Execution => (some s: State | some s.elected) + } + +assert NoOverflow { + Execution => (all s: State, x: Link | no s.queue[x].overflow) + } + +run Execution for 7 Op, 2 Msg, + 2 Node, 4 Link, 4 Queue, 6 State expect 1 + +run ElectionHappens for 7 Op, 2 Msg, + exactly 3 Node, 6 Link, 3 Queue, 7 State expect 1 + +-- solution for 3 State but not for 4 State +run NoRepeats for 7 Op, 2 Msg, + 2 Node, 2 Link, 2 Queue, 4 State expect 0 + +-- solution for 8 but not 9 State +run NoRepeats for 7 Op, 2 Msg, + 3 Node, 6 Link, 6 Queue, 8 State expect 0 + +-- only 5 queues needed: just count +-- no solution: establishes at most 3 queues needed +check NoOverflow for 7 Op, 2 Msg, + 3 Node, 6 Link, 5 Queue, 9 State expect 0 + +check AtMostOneElected for 7 Op, 2 Msg, + 3 Node, 6 Link, 3 Queue, 9 State expect 0 + +check OneEventuallyElected for 7 Op, 2 Msg, + 3 Node, 6 Link, 3 Queue, 9 State expect 1 + + + +// DEFINED VARIABLES +// Defined variables are uncalled, no-argument functions. +// They are helpful for getting good visualization. +fun queued: State -> Link -> Msg { + {s: State, L: Link, m: Msg | m in L.(s.queue).slot} +} diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/firewire.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/firewire.thm new file mode 100644 index 00000000..04793a40 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/firewire.thm @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/ins.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/ins.als new file mode 100644 index 00000000..e5596229 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/ins.als @@ -0,0 +1,115 @@ +module examples/case_studies/ins + +/* + * Models an Intentional Naming System (INS), a scheme for + * dynamic resource discovery in a dynamic environment. + * + * For a detailed description, see: + * http://sdg.lcs.mit.edu/pubs/2000/INS_ASE00.pdf + * + * author: Sarfraz Khurshid + */ + +open util/relation as rel + +sig Attribute {} +sig Value {} +sig Record {} + +one sig Wildcard extends Value {} + +sig AVTree { + values: set Value, + attributes: set Attribute, + root: values - Wildcard, + av: attributes one -> some (values - root), + va: (values - Wildcard) one -> attributes +}{ + // values (and attributes) of tree are those reachable from root + values = root.*(va.av) +} + +sig Query extends AVTree {} {all a:attributes | one a.av} + +sig DB extends AVTree { + records : set Record, + recs: (values - root) some -> records, + lookup : Query -> (values -> records) +}{ + Wildcard !in values +} + +fact AddInvariants { + all db: DB { + all v: db.values | no v.(db.recs) & v.^(~(db.av).~(db.va)).(db.recs) + all a: db.attributes | all disj v1, v2: a.(db.av) | + (some rr: *((db.va).(db.av)).(db.recs) | no v1.rr & v2.rr) + } +} + +pred Get [db: DB, r: Record, q: Query] { + q.values = r.~(db.recs).*(~(db.av).~(db.va)) + q.attributes = q.values.~(db.av) + q.root = db.root + all a : attributes| a.~(q.va) = a.~(db.va) + all v : values | v.~(q.av) = v.~(db.av) +} + +pred Conforms [db: DB, q: Query, r: Record] { + some p: Query { + db.Get[r, p] + q.va in p.va + (q.av - Attribute -> Wildcard) in p.av + } +} + +pred indSubset[db : DB, q: Query, r: set Record, v: Value] { + all a : v.(q.va) | + (a.(q.av) in a.(db.av) => r in (a.(q.av)).(q.(db.lookup))) && + (a.(q.av) = Wildcard => r in a.(db.av).*((db.va).(db.av)).(db.recs)) +} + +pred Lookup[db: DB, q: Query, found: set Record] { + all v: Value | not v.(q.va) in v.(db.va) => no v.(q.(db.lookup)) + all v: Value | all a : v.(q.va) | + a.(q.av) != Wildcard && not a.(q.av) in a.(db.av) => no v.(q.(db.lookup)) + all v: Value - Wildcard | + no v.(q.va) => v.(q.(db.lookup)) = v.*((db.va).(db.av)).(db.recs) + all v: Value | + some v.(q.va) => indSubset[db, q, v.(q.(db.lookup)), v] && + (no r: Record - v.(q.(db.lookup)) | indSubset[db, q, v.(q.(db.lookup)) + r, v]) + found = db.root.(q.(db.lookup)) +} + +assert CorrectLookup { + all db: DB | all q : Query | all r : Record | + Conforms [db,q,r] <=> db.Lookup[q, r] +} + +pred Add [me: DB, adv: Query, r: Record, db: DB] { + // restricted version - only advertisements with fresh attributes and values added + no me.attributes & adv.attributes + me.values & adv.values = me.root + me.root = adv.root + Wildcard !in adv.values + r !in me.records + db.values = me.values + adv.values + db.attributes = me.attributes + adv.attributes + db.root = me.root + db.av = me.av + adv.av + db.va = me.va + adv.va + db.recs = me.recs + ((db.values - dom[db.va]) -> r) +} + +pred RemoveWildCard[me: Query, q: Query] { + q.values = me.values - Wildcard + q.attributes = me.attributes - Wildcard.~(me.av) + q.root = me.root + q.av = me.av - Attribute -> Wildcard + q.va = me.va - Value -> Wildcard.~(me.av) +} + +assert MissingAttributeAsWildcard { + all db : DB, q, q' : Query, found: set Record | + db.Lookup[q, found] && q.RemoveWildCard[q'] => db.Lookup[q', found] +} diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/iolus.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/iolus.als new file mode 100644 index 00000000..cc27ba39 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/iolus.als @@ -0,0 +1,320 @@ +module examples/case_studies/iolus + +/* + * This is a model of Iolus, a scheme for secure multicasting. + * In this scheme, nodes multicast messages to other nodes + * within a group whose membership changes dynamically. The + * group is partitioned into subgroups, arranged in a tree, + * each with its own Key Distribution Server (KDS). + * + * For a detailed description, see: + * Mana Taghdiri, "Lightweight Modelling and Automatic Analysis + * of Multicast Key Management Schemes", Masters Thesis, Dept. + * of EECS, MIT, Dec. 2002. + * http://sdg.lcs.mit.edu/pubs/theses/taghdiri_masters.pdf + * + * author: Mana Taghdiri + */ + +open util/ordering[Tick] as ord + +sig Tick {} + +/** + * It can be abstract, since the fact below says Key=GroupKey + */ +abstract sig Key {} + +/** + * It can be abstract, since the fact below says Message=DataMessage + */ +abstract sig Message { + sender : Member, + sentTime : Tick, + key : Key +} + +/** + * It can be abstract, since the fact below says KDS=GSA + */ +abstract sig KDS { + keys : Tick -> Key, + members : Tick -> Member +}{ + Monotonic[keys] + all t : Tick | let t' = ord/prev[t] { + all m : members[t]-members[t'] | Join[m, t, this] + all m : members[t']-members[t] | Leave[m, t] + } +} + +/** + * It can be abstract, since the fact below says "Member=Client" + */ +abstract sig Member { + ownedKeys : Tick -> Key, + receivedMessages : Tick -> Message +}{ + Monotonic[ownedKeys] + Monotonic[receivedMessages] +} + +fact MemberBehavior { + Init[ord/first] + all m : Member, t : Tick - ord/first | + (some msg : Message | + SendMessage[m, t, msg] || ReceiveMessage[m, t, msg]) || + (some kds : KDS | Join[m, t, kds]) || + Leave[m, t] || MemberInactive[m, t] +} + +pred Monotonic[r : Tick -> univ] { + all t : Tick | ord/prev[t].r in t.r +} + +---------------------------------------------- +sig GroupKey extends Key { + generator : GSA, + generatedTime : Tick +}{ + some c : Client | + (Join[c, generatedTime, c.server] || Leave[c, generatedTime]) && + c.server = generator +} + +sig DataMessage extends Message { + gsaID : GSA, + retransmitTime : Tick } +{ SendMessage[sender, sentTime, this] || + (some msg' : DataMessage | + Remulticast[gsaID, msg', retransmitTime, this]) } + +sig GSA extends KDS { + parent : lone GSA } +{ keys[Tick].generator = this + all t : Tick, k : keys[t] - keys[ord/prev[t]] | + k.generatedTime = t } + +sig Client extends Member { + server : GSA } +{ all t : Tick, k : ownedKeys[t] - ownedKeys[ord/prev[t]] | + k.generator = server && k.generatedTime = t } + +fact IolusProperties { + no k, k' : GroupKey | k!=k' && k.generator = k'.generator && k.generatedTime = k'.generatedTime + all g : GSA, msg : DataMessage, t : Tick | RemulticastConditions[g, msg, t] => + (some msg': DataMessage | Remulticast[g, msg, t, msg']) +} + +fact GSATree { + let root = {g : GSA | no g.parent} { + one root + GSA in root.*~parent }} + +fact { + Member = Client + KDS = GSA + Message = DataMessage + Key = GroupKey + no m, m' : DataMessage { + m!=m' + m.sender = m'.sender + m.sentTime = m'.sentTime + m.key = m'.key + m.gsaID = m'.gsaID + m.retransmitTime = m'.retransmitTime } +} + +---------------------------------------------- +pred Init[t : Tick] { + no Member.receivedMessages[t] + no Member.ownedKeys[t] + no KDS.keys[t] + no KDS.members[t] } + +pred Join[m : Member, t : Tick, kds : KDS] { + kds = m.server + JoinRequest[m, kds, t] + NoChange[m.receivedMessages, t] +} +pred JoinRequest[c : Client, gsa : GSA, t : Tick] { + c !in gsa.members[ord/prev[t]] + KeyUpdate[gsa, t] + c in gsa.members[t] } + +pred Leave[m : Member, t : Tick] { + LeaveRequest[m, m.server, t] + NoChange[m.receivedMessages, t] } + +pred LeaveRequest[c : Client, gsa : GSA, t : Tick] { + c in gsa.members[ord/prev[t]] + KeyUpdate[gsa, t] + c !in gsa.members[t] } + +pred SendMessage[m : Member, t : Tick, msg : Message] { + SendRequest[m, m.server, t, msg] + m.receivedMessages[t] = m.receivedMessages[ord/prev[t]] + msg + ConstantMembership[m, t] } + +pred SendRequest[c : Client, gsa : GSA, t : Tick, msg : DataMessage] { + c in gsa.members[t] + msg.sender = c + msg.sentTime = t + NewestKey[gsa.keys[t], msg.key] + msg.gsaID = gsa + msg.retransmitTime = t + (some gsa.parent.members[t]) => + (some msg' : DataMessage | Remulticast[gsa, msg, t, msg']) } + +pred ReceiveMessage[m : Member, t : Tick, msg : Message] { + ReceiveConditions[m, t, msg] + m.receivedMessages[t] = m.receivedMessages[ord/prev[t]] + msg } + +pred MemberInactive[m : Member, t : Tick] { + NoChange[m.receivedMessages, t] --does not constrain owned keys + ConstantMembership[m, t] } + +pred ReceiveConditions[m : Member, t : Tick, msg : Message] { + ConstantMembership[m, t] + msg !in m.receivedMessages[ord/prev[t]] + msg.retransmitTime in ord/prevs[t] + msg.key in m.ownedKeys[t] } + +pred CanReceive[m : Member, t : Tick, msg : Message] { + some msg' : DataMessage { + msg'.sentTime = msg.sentTime + msg'.sender = msg.sender + msg' in m.receivedMessages[ord/prev[t]] || ReceiveConditions[m, t, msg'] }} + +pred IsMember[m : Member, t : Tick] { + some kds : KDS | m in kds.members[t] +} + +------------------------------------------- +pred RemulticastConditions[g : GSA, msg : DataMessage, t : Tick] { + msg.retransmitTime in ord/prevs[t] + msg.key in g.keys[t] + g.parent.keys[t] + some g.parent + g - msg.gsaID } + +pred Remulticast[g : GSA, msg : DataMessage, t : Tick, msg': lone DataMessage] { + RemulticastConditions[g, msg, t] + let g' = g.parent + g - msg.gsaID | NewestKey[g'.keys[msg.sentTime], msg'.key] + msg'.sender = msg.sender + msg'.sentTime = msg.sentTime + msg'.retransmitTime = t + msg'.gsaID = g +} + +pred KeyUpdate[g : GSA, t : Tick] { + some k : Key { + GeneratedKey[g, t, k] + all c : Client | c in g.members[t] <=> k in c.ownedKeys[t] + k in g.keys[t] }} + +pred NewestKey[keys : set GroupKey, newest: lone GroupKey] { + some keys <=> some newest + newest in keys + no ord/nexts[newest.generatedTime] & keys.generatedTime } + +pred GeneratedKey[g : GSA, t : Tick, key : GroupKey] { + key.generator = g + key.generatedTime = t +} + +pred ConstantMembership[c : Client, t : Tick] { + IsMember[c, t] <=> IsMember[c, ord/prev[t]] } + + +pred NoChange[r : Tick -> univ, t : Tick] { + r[ord/prev[t]] = r[t] +} + +-------------------------------------------- +assert Acyclic { + all g : GSA | g !in g.^parent } + +//check Acyclic for 6 -- one min + +assert Connected { + all g, g' : GSA | g in g'.*(parent + ~parent) } + +//check Connected for 6 + +assert TimeProceeds { + no msg : DataMessage | msg.retransmitTime in ord/prevs[msg.sentTime] } + +//check TimeProceeds for 6 + +pred LoopFree { + no t, t' : Tick { + t!=t' + all k : KDS | k.members[t] = k.members[t'] -- no constraint on keys + all m : Member | m.receivedMessages[t] = m.receivedMessages[t'] + all m : DataMessage | m.retransmitTime = t => + (some m' : DataMessage { + m'.retransmitTime = t' + m.sender = m'.sender + m.sentTime = m'.sentTime + m.gsaID = m'.gsaID + m.key = m'.key }) + }} + +//fact NoLoop { LoopFree() } -- Property-specific diameter + +------------------------------------------------ +assert loop { + !LoopFree } +//check loop for 13 but 2 Member, 1 KDS, 1 Message + +assert NonLinearTopology { + (no g : GSA | #g.~parent > 1) || + !(some m, m' : DataMessage | Remulticast[m.gsaID, m', m.retransmitTime, m] + && !SendMessage[m.sender, m.sentTime, m] + && (some c : Client | m in c.receivedMessages[ord/nexts[m.retransmitTime]]))} + +//check NonLinearTopology for 5 but 3 KDS, 3 Member, 2 Message -- > good scenario + +assert NotOutside { + no msg : DataMessage | !IsMember[msg.sender, msg.sentTime] } + +//check NotOutside for 5 + +assert Trivial { + 0 = 1 } + +//check Trivial for 2 but 1 KDS + +assert x { + !(LoopFree && some DataMessage && + (some t : Tick | some m, m' : Member | + m!=m' && IsMember[m, t] && IsMember[m', t] && t != ord/next[ord/first])) +} + +//check x for 3 but 2 Member, 2 KDS, 2 Message + ------------------------------------------- +assert OutsiderCantRead { + no msg : Message, m : Member, t : Tick { + IsMember[msg.sender, msg.sentTime] + !IsMember[m, msg.sentTime] + CanReceive[m, t, msg] + } +} +assert OutsiderCantSend { + no msg : Message, m : Member, t : Tick { + !IsMember[msg.sender, msg.sentTime] + IsMember[m, t] + msg !in m.receivedMessages[ord/prev[t]] + CanReceive[m, t, msg] + } +} +assert InsiderCanRead { + all msg : Message, m : Member | + some t : Tick - ord/last | all t' : ord/nexts[t] | + (IsMember[msg.sender, msg.sentTime] && + IsMember[m, msg.sentTime]) => CanReceive[m, t', msg] +} + +check OutsiderCantRead for 5 but 3 Member expect 0 +//check OutsiderCantSend for 5 but 3 Member -- 5 min +//check InsiderCanRead for 9 but 2 Member, 1 KDS, 1 Message +//check InsiderCanRead for 10 but 2 Member, 2 KDS, 2 Message -- not able to check diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/sync.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/sync.als new file mode 100644 index 00000000..b79c5b5d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/sync.als @@ -0,0 +1,134 @@ +module examples/case_studies/sync + +/* + * Model of a generic file synchronizer. + * + * Adapted from: + * Reference: S. Balasubramaniam and Benjamin C. Pierce, + * "What is a File Synchronizer", Indiana University CSCI + * Technical Report #507, April 22, 1998 + * + * For a detailed description, see: + * http://sdg.lcs.mit.edu/pubs/theses/tnolte_masters.pdf + * + * author: Tina Nolte + */ + +private open util/graph[Name] as graph + +/** + * The Name atom represents the hierarchy of all name sequences + * used in the model. A Name atom represents the name, and the path + * in the sequence of names to the root excluding the RootName. + */ +sig Name { + children: set Name +} + +fact { graph/tree[children] } + +one sig RootName extends Name { } + +fact { Name in RootName.*children } + +// We assume that the empty path always + +sig FileContents { } +one sig Dir extends FileContents { } + +pred IsValidFS[fs: Name -> lone FileContents] { + all n: Name - RootName | { + // files don't have children + n.fs != Dir => no (n.^children).fs + // if a path maps to something non-nil, all prefixes do also + some n.fs => some (n.~children).fs + } + // the root of a file system must be a directory + RootName.fs = Dir +} + +pred IsValidDirty[dirty: set Name] { + all n: dirty | n.~children in dirty + RootName in dirty => some dirty - RootName +} + +pred DirtiesValid[A, B: Name -> lone FileContents, Adirty, Bdirty: set Name] { + some O: Name -> lone FileContents | { + IsValidFS[O] + { n: Name | n.O != n.A } in Adirty + { n: Name | n.O != n.B } in Bdirty + } +} + +fun RestrictFS[fs: Name -> lone FileContents, p: Name]: Name -> lone FileContents { + fs & (p.*children -> FileContents) +} + +fun RestrictFSComplement[fs: Name -> lone FileContents, p: Name]: Name -> lone FileContents { + fs & ((Name - p.*children) -> FileContents) +} + +/** + * The following function test whether a particular synchronizer + * operation satisfies the "reasonableness" conditions. + * The arguments are: + * O - the original filesystem. + * A,B - separately modified copies + * Adirty, Bdirty - sets of paths modified in A and B, respectively, from O. + * + * A',B' - results of synchronizer operation + */ +pred SyncSpec[A, B, A', B': Name -> lone FileContents, Adirty, Bdirty: set Name] { + { + IsValidFS[A] + IsValidFS[B] + IsValidDirty[Adirty] + IsValidDirty[Bdirty] + } => { + { + all p: Name | IsRelevantPath[p, A, B] => { + SyncSpecForPath[p, A, B, A', B', Adirty, Bdirty] + } + } + IsValidFS[A'] + IsValidFS[B'] + } +} + +pred SyncSpecForPath[p: Name, A, B, A', B': Name -> lone FileContents, Adirty, Bdirty: set Name] { + (p.A = p.B => (p.A' = p.A && p.B' = p.B)) + (p !in Adirty => (RestrictFS[A', p] = RestrictFS[B, p] && RestrictFS[B', p] = RestrictFS[B, p])) + (p !in Bdirty => (RestrictFS[B', p] = RestrictFS[A, p] && RestrictFS[A', p] = RestrictFS[A, p])) + ((p in Adirty && p in Bdirty && p.A != p.B) => (RestrictFS[A',p] = RestrictFS[A,p] && RestrictFS[B',p] = RestrictFS[B,p])) +} + +pred IsRelevantPath[p: Name, A, B: Name -> lone FileContents] { + p = RootName || { + (p.~children).A = Dir + (p.~children).B = Dir + } +} + +pred SyncSpecExample[A, B, A', B': Name -> lone FileContents, Adirty, Bdirty: set Name] { + IsValidFS[A] + IsValidFS[B] + IsValidDirty[Adirty] + IsValidDirty[Bdirty] + SyncSpec[A, B, A', B', Adirty, Bdirty] + A != A' +} + +//run SyncSpecExample for 3 + +pred SyncSpecNotUnique { + some A, B, A1', B1', A2', B2': Name -> lone FileContents, Adirty, Bdirty: set Name | { + IsValidFS[A] && IsValidFS[B] + IsValidDirty[Adirty] && IsValidDirty[Bdirty] + //DirtiesValid(A, B, Adirty, Bdirty) + (A1' != A2' || B1' != B2') + SyncSpec[A, B, A1', B1', Adirty, Bdirty] + SyncSpec[A, B, A2', B2', Adirty, Bdirty] + } +} + +run SyncSpecNotUnique for 5 expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/syncimpl.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/syncimpl.als new file mode 100644 index 00000000..fe20377e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/case_studies/syncimpl.als @@ -0,0 +1,107 @@ +module examples/case_studies/syncimpl + +/* + * Model of a file synchronizer reconciliation algorithm. + * + * Adapted from: + * Reference: S. Balasubramaniam and Benjamin C. Pierce, + * "What is a File Synchronizer", Indiana University CSCI + * Technical Report #507, April 22, 1998 + * + * For a detailed description, see: + * http://sdg.lcs.mit.edu/pubs/theses/tnolte_masters.pdf + * + * author: Tina Nolte + */ + +open examples/case_studies/sync as sync +open util/ordering[sync/Name] as ord +open util/relation as rel + +// Model the reconciliation algorithm + +sig ReconName extends Name { + Ain, Bin, Aout, Bout: Name->FileContents, + p_children: set Name, + first_p_child, last_p_child: lone Name, + prev_p_child: (p_children - first_p_child) -> p_children +} + +fact { + all x: ReconName { + x.p_children = ChildrenAB[x.Ain, x.Bin, x] + x.first_p_child = { pc: x.p_children | x.p_children in (pc + nexts[pc]) } + x.last_p_child = { pc: x.p_children | x.p_children in (pc + prevs[pc]) } + all p_child: x.p_children - x.first_p_child | { + let earlierChildren = prevs[p_child] & x.p_children | + p_child . (x.prev_p_child) = { earlierChild: earlierChildren | earlierChildren in (earlierChild + @prevs[earlierChild]) } + } + } +} + +fact { ReconName = Name } + +fun ChildrenAB[A, B: Name -> lone FileContents, p: Name]: set Name { + p.children & (dom[A] + dom[B]) +} + +pred reconHelper[Adirty, Bdirty: set Name] { + all p: Name { + let A = p.Ain, B = p.Bin, A' = p.Aout, B' = p.Bout | { + some p.(A+B) => { + (p !in Adirty && p !in Bdirty) => (A' = A && B' = B) else { + (p.A = Dir && p.B = Dir) => { + no p_children => { + p.Aout = p.Ain + p.Bout = p.Bin + } else { + p.first_p_child.Ain = p.Ain + p.first_p_child.Bin = p.Bin + p.Aout = p.last_p_child.Aout + p.Bout = p.last_p_child.Bout + all pchild: p.p_children - p.first_p_child | { + pchild.Ain = (pchild.(p.prev_p_child)).Aout + pchild.Bin = (pchild.(p.prev_p_child)).Bout + } + } // some p_children + } else { // !(p.A = Dir && p.B = Dir) + p !in Adirty => { + A' = RestrictFS[B, p] + RestrictFSComplement[A, p] + B' = B + } else { + p !in Bdirty => { + A' = A + B' = RestrictFS[A, p] + RestrictFSComplement[B, p] + } else { + A' = A + B' = B + } + } // not "p !in Adirty" + } // not case 2 i.e. not both are dirs + } // not both clean + } // some p.(A+B) + } // let A =, B=, A'=, B'= + } // all p: Name +} // reconHelper() + +pred recon[A, B, A', B': Name -> lone FileContents, Adirty, Bdirty: set Name] { + A = ReconName.Ain + B = ReconName.Bin + A' = ReconName.Aout + B' = ReconName.Bout + reconHelper[Adirty, Bdirty] +} + +assert Correctness { + all A, B, A', B': Name -> lone FileContents, Adirty, Bdirty: set Name | { + { + DirtiesValid[A, B, Adirty, Bdirty] + recon[A, B, A', B', Adirty, Bdirty] + //no Adirty + Bdirty + } + => + SyncSpec[A, B, A', B', Adirty, Bdirty] + } +} + +check Correctness for 4 but 2 FileContents expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/puzzles/farmer.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/puzzles/farmer.als new file mode 100644 index 00000000..d3636486 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/puzzles/farmer.als @@ -0,0 +1,92 @@ +module examples/puzzles/farmer + +/* + * The classic river crossing puzzle. A farmer is carrying a fox, a + * chicken, and a sack of grain. He must cross a river using a boat + * that can only hold the farmer and at most one other thing. If the + * farmer leaves the fox alone with the chicken, the fox will eat the + * chicken; and if he leaves the chicken alone with the grain, the + * chicken will eat the grain. How can the farmer bring everything + * to the far side of the river intact? + * + * authors: Greg Dennis, Rob Seater + * + * Acknowledgements to Derek Rayside and his students for finding and + * fixing a bug in the "crossRiver" predicate. + */ + +open util/ordering[State] as ord + +/** + * The farmer and all his possessions will be represented as Objects. + * Some objects eat other objects when the Farmer's not around. + */ +abstract sig Object { eats: set Object } +one sig Farmer, Fox, Chicken, Grain extends Object {} + +/** + * Define what eats what when the Farmer' not around. + * Fox eats the chicken and the chicken eats the grain. + */ +fact eating { eats = Fox->Chicken + Chicken->Grain } + +/** + * The near and far relations contain the objects held on each + * side of the river in a given state, respectively. + */ +sig State { + near: set Object, + far: set Object +} + +/** + * In the initial state, all objects are on the near side. + */ +fact initialState { + let s0 = ord/first | + s0.near = Object && no s0.far +} + +/** + * Constrains at most one item to move from 'from' to 'to'. + * Also constrains which objects get eaten. + */ +pred crossRiver [from, from', to, to': set Object] { + // either the Farmer takes no items + (from' = from - Farmer - from'.eats and + to' = to + Farmer) or + // or the Farmer takes one item + (one x : from - Farmer | { + from' = from - Farmer - x - from'.eats + to' = to + Farmer + x }) +} + +/** + * crossRiver transitions between states + */ +fact stateTransition { + all s: State, s': ord/next[s] { + Farmer in s.near => + crossRiver[s.near, s'.near, s.far, s'.far] else + crossRiver[s.far, s'.far, s.near, s'.near] + } +} + +/** + * the farmer moves everything to the far side of the river. + */ +pred solvePuzzle { + ord/last.far = Object +} + +run solvePuzzle for 8 State expect 1 + +/** + * no Object can be in two places at once + * this is implied by both definitions of crossRiver + */ +assert NoQuantumObjects { + no s : State | some x : Object | x in s.near and x in s.far +} + +check NoQuantumObjects for 8 State expect 0 \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/puzzles/farmer.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/puzzles/farmer.thm new file mode 100644 index 00000000..41d7ada7 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/puzzles/farmer.thm @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/puzzles/handshake.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/puzzles/handshake.als new file mode 100644 index 00000000..8fce6178 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/puzzles/handshake.als @@ -0,0 +1,64 @@ +module examples/puzzles/handshake + +/* + * Alloy model of the Halmos handshake problem + * + * Hilary and Jocelyn are married. They invite four couples who are friends for dinner. When + * they arrive, they shake hands with each other. Nobody shakes hands with him or herself + * or with his or her spouse. After there has been some handshaking, Jocelyn jumps up on + * a chair and says "Stop shaking hands!", and then asks how many hands each person has + * shaken. All the answers are different. How many hands has Hilary shaken? + * + * The Alloy model represents the problem as a set of constraints. Properties of the spouse + * relationship and of handshaking in general are given as facts. The particular situation + * is cast as a function. + * + * There are 9 people answering, and all answers are different. Nobody can shake more than + * 8 hands. So answers must be 0..8. The one (p8 say) who answered 8 has shaken everybody's + * hand except for his or her own, and his or her spouse's. Now consider the person who shook + * 0 hands (p0 say). The persons p0 and p8 are distinct. If they are not married, then p8 cannot + * have shaken 8 hands, because he or she did not shake the hand of p0 or of his or her spouse. + * So p8's spouse to p0. Now imagine Jocelyn asking the question again, with p0 and p8 out of + * the room, and excluding hand shakes with them. Since p8 shook hands with everyone else + * except p0 and p8, everyone gives an answer one smaller than they did before, giving 0..6. + * The argument now applies recursively. So Hilary is left alone, having shaken 4 hands. + * + * author: Daniel Jackson, 11/15/01 + */ + +sig Person {spouse: Person, shaken: set Person} +one sig Jocelyn, Hilary extends Person {} + +fact ShakingProtocol { + // nobody shakes own or spouse's hand + all p: Person | no (p + p.spouse) & p.shaken + // if p shakes q, q shakes p + all p, q: Person | p in q.shaken => q in p.shaken + } + +fact Spouses { + all p, q: Person | p!=q => { + // if q is p's spouse, p is q's spouse + p.spouse = q => q.spouse = p + // no spouse sharing + p.spouse != q.spouse + } + all p: Person { + // a person is his or her spouse's spouse + p.spouse.spouse = p + // nobody is his or her own spouse + p != p.spouse + } + } + +pred Puzzle { + // everyone but Jocelyn has shaken a different number of hands + all p,q: Person - Jocelyn | p!=q => #p.shaken != #q.shaken + // Hilary's spouse is Jocelyn + Hilary.spouse = Jocelyn + } + +P10: run Puzzle for exactly 10 Person, 5 int expect 1 +P12: run Puzzle for exactly 12 Person, 5 int expect 1 +P14: run Puzzle for exactly 14 Person, 5 int expect 1 +P16: run Puzzle for exactly 16 Person, 6 int expect 1 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/puzzles/handshake.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/puzzles/handshake.thm new file mode 100644 index 00000000..0bc070b1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/puzzles/handshake.thm @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/puzzles/hanoi.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/puzzles/hanoi.als new file mode 100644 index 00000000..f936fa5f --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/puzzles/hanoi.als @@ -0,0 +1,140 @@ +module examples/puzzles/hanoi + +/* + * Towers of Hanoi model + * + * Description of problem from http://www.cut-the-knot.com/recurrence/hanoi.html + * + * The Tower of Hanoi puzzle was invented by the French mathematician Edouard Lucas + * in 1883. We are given a tower of eight disks, initially stacked in decreasing size on + * one of three pegs. The objective is to transfer the entire tower to one of the other + * pegs, moving only one disk at a time and never a larger one onto a smaller. + * + * The Alloy model below is written so that a solution to the model is a complete + * sequence of valid moves solving an instance of the problem. We define constraints + * for the initial state (all discs on left stake), the final state (all discs on right stake), + * and each pair of adjacent states (the top disc is moved from one stake to another, + * not putting larger discs on smaller discs), and let Alloy Analyzer solve for the + * sequence of states satisfying these constraints. Since each adjacent pair of states is + * constrained to be related by a single move, it is easy to see the sequence of moves + * once you have the sequence of states. + * + * For n discs, 2^n states are needed for a solution + * (including the initial state and the final state). + * + * Performance: currently, the problem can be solved for up to 5 discs; this takes + * several minutes with the Chaff solver. + * + * author: Ilya Shlyakhter + */ + +open util/ordering[State] as states +open util/ordering[Stake] as stakes +open util/ordering[Disc] as discs + +sig Stake { } + +sig Disc { } + +/** + * sig State: the complete state of the system -- + * which disc is on which stake. An solution is a + * sequence of states. + */ +sig State { + on: Disc -> one Stake // _each_ disc is on _exactly one_ stake + // note that we simply record the set of discs on each stake -- + // the implicit assumption is that on each stake the discs + // on that stake are ordered by size with smallest disc on top + // and largest on bottom, as the problem requires. +} + +/** + * compute the set of discs on the given stake in this state. + * ~(this.on) map the stake to the set of discs on that stake. + */ +fun discsOnStake[st: State, stake: Stake]: set Disc { + stake.~(st.on) +} + +/** + * compute the top disc on the given stake, or the empty set + * if the stake is empty + */ +fun topDisc[st: State, stake: Stake]: lone Disc { + { d: st.discsOnStake[stake] | st.discsOnStake[stake] in discs/nexts[d] + d } +} + +/** + * Describes the operation of moving the top disc from stake fromStake + * to stake toStake. This function is defined implicitly but is + * nevertheless deterministic, i.e. the result state is completely + * determined by the initial state and fromStake and toStake; hence + * the "det" modifier above. (It's important to use the "det" modifier + * to tell the Alloy Analyzer that the function is in fact deterministic.) + */ +pred Move [st: State, fromStake, toStake: Stake, s': State] { + let d = st.topDisc[fromStake] | { + // all discs on toStake must be larger than d, + // so that we can put d on top of them + st.discsOnStake[toStake] in discs/nexts[d] + // after, the fromStake has the discs it had before, minus d + s'.discsOnStake[fromStake] = st.discsOnStake[fromStake] - d + // after, the toStake has the discs it had before, plus d + s'.discsOnStake[toStake] = st.discsOnStake[toStake] + d + // the remaining stake afterwards has exactly the discs it had before + let otherStake = Stake - fromStake - toStake | + s'.discsOnStake[otherStake] = st.discsOnStake[otherStake] + } +} + +/** + * there is a leftStake that has all the discs at the beginning, + * and a rightStake that has all the discs at the end + */ +pred Game1 { + Disc in states/first.discsOnStake[stakes/first] + some finalState: State | Disc in finalState.discsOnStake[stakes/last] + + // each adjacent pair of states are related by a valid move of one disc + all preState: State - states/last | + let postState = states/next[preState] | + some fromStake: Stake | { + // must have at least one disk on fromStake to be able to move + // a disc from fromStake to toStake + some preState.discsOnStake[fromStake] + // post- results from pre- by making one disc move + some toStake: Stake | preState.Move[fromStake, toStake, postState] + } +} + +/** + * there is a leftStake that has all the discs at the beginning, + * and a rightStake that has all the discs at the end + */ +pred Game2 { + Disc in states/first.discsOnStake[stakes/first] + some finalState: State | Disc in finalState.discsOnStake[stakes/last] + + // each adjacent pair of states are related by a valid move of one disc + all preState: State - states/last | + let postState = states/next[preState] | + some fromStake: Stake | + let d = preState.topDisc[fromStake] | { + // must have at least one disk on fromStake to be able to move + // a disc from fromStake to toStake + some preState.discsOnStake[fromStake] + postState.discsOnStake[fromStake] = preState.discsOnStake[fromStake] - d + some toStake: Stake | { + // post- results from pre- by making one disc move + preState.discsOnStake[toStake] in discs/nexts[d] + postState.discsOnStake[toStake] = preState.discsOnStake[toStake] + d + // the remaining stake afterwards has exactly the discs it had before + let otherStake = Stake - fromStake - toStake | + postState.discsOnStake[otherStake] = preState.discsOnStake[otherStake] + } + } + } + +run Game1 for 1 but 3 Stake, 5 Disc, 32 State expect 1 +run Game2 for 1 but 3 Stake, 3 Disc, 8 State expect 1 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/puzzles/hanoi.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/puzzles/hanoi.thm new file mode 100644 index 00000000..f56b5722 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/puzzles/hanoi.thm @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/file_system.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/file_system.als new file mode 100644 index 00000000..60fd959b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/file_system.als @@ -0,0 +1,59 @@ +module examples/systems/file_system + +/* + * Model of a generic file system. + */ + +abstract sig Object {} + +sig Name {} + +sig File extends Object {} { some d: Dir | this in d.entries.contents } + +sig Dir extends Object { + entries: set DirEntry, + parent: lone Dir +} { + parent = this.~@contents.~@entries + all e1, e2 : entries | e1.name = e2.name => e1 = e2 + this !in this.^@parent + this != Root => Root in this.^@parent +} + +one sig Root extends Dir {} { no parent } + +lone sig Cur extends Dir {} + +sig DirEntry { + name: Name, + contents: Object +} { + one this.~entries +} + + +/** + * all directories besides root have one parent + */ +pred OneParent_buggyVersion { + all d: Dir - Root | one d.parent +} + +/** + * all directories besides root have one parent + */ +pred OneParent_correctVersion { + all d: Dir - Root | (one d.parent && one contents.d) +} + +/** + * Only files may be linked (that is, have more than one entry) + * That is, all directories are the contents of at most one directory entry + */ +pred NoDirAliases { + all o: Dir | lone o.~contents +} + +check { OneParent_buggyVersion => NoDirAliases } for 5 expect 1 + +check { OneParent_correctVersion => NoDirAliases } for 5 expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/file_system.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/file_system.thm new file mode 100644 index 00000000..4b740ad3 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/file_system.thm @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/javatypes_soundness.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/javatypes_soundness.als new file mode 100644 index 00000000..6bf50ed7 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/javatypes_soundness.als @@ -0,0 +1,140 @@ +module examples/systems/javatypes + +/* + * Model of the Java type system. The TypeSoundness assertion + * claims that if a Java program type checks successfully, + * then a field will cannot be assigned an incorrect type. + * + * author: Daniel Jackson + */ + +open util/graph[Type] as graph + +abstract sig Type { + xtends: set Type + } +sig Interface extends Type {} + { xtends in Interface } +sig Class extends Type { + implements: set Interface, + fields: set Field + } { lone xtends && xtends in Class } +-- optional: best omitted to allow private etc +-- {xtends.@fields in fields} +sig Field { + declType: Type + } + +fact { + graph/dag[xtends] + } + +abstract sig Value {} +one sig Null extends Value {} +sig Object extends Value { + type: Class, + slot: Field lone -> lone Slot + } {slot.Slot = type.fields} +sig Slot {} + +abstract sig Statement {} +sig Assignment extends Statement { + var: Variable, + expr: Expr + } +sig Setter extends Statement { + field: Field, + lexpr, rexpr: Expr + } + +abstract sig Expr { + type: Type, + subexprs: set Expr + } {subexprs = this + this.^@expr} +sig Variable extends Expr { + declType: Type + } {type = declType} +sig Constructor extends Expr { + class: Class + } +sig Getter extends Expr { + field: Field, + expr: Expr + } {type = field.declType} + +sig State { + objects: set Object, + reaches: Object -> Object, + vars: set Variable, + holds: (Slot + Variable) -> lone Value, + val: Expr -> lone Value + } { + all o: Object | o.reaches = holds[o.slot[Field]] & Object + holds.Value & Variable = vars + objects = holds[vars].^reaches + all e: Expr | let v = val[e] { + e in Variable => v = holds[e] + e in Getter => v = holds[(val[e.expr]).slot[e.field]] + e in Constructor => v in Object and v.type = e.type } + } + +pred RuntimeTypesOK [s: State] { + all o: s.objects, f: o.type.fields | + let v = s.holds [o.slot [f]] | HasType [v, f.declType] + all var: s.vars | + let v = s.holds [var] | HasType [v, var.declType] + } + +pred HasType [v: Value, t: Type] { + v in Null or Subtype [v.type, t] + } + +pred Subtype [t, t': Type] { + t in Class => + (let supers = (t & Class).*(Class<:xtends) | + t' in (supers + supers.implements.*(Interface<:xtends))) + t in Interface => t' in (t & Interface).*(Interface<:xtends) + } + +pred TypeChecksSetter [stmt: Setter] { + all g: Getter & stmt.(lexpr+rexpr).subexprs | g.field in g.expr.type.fields + stmt.field in stmt.lexpr.type.fields + Subtype [stmt.rexpr.type, stmt.field.declType] + } + +pred ExecuteSetter [s, s': State, stmt: Setter] { + stmt.(rexpr+lexpr).subexprs & Variable in s.vars + s'.objects = s.objects and s'.vars = s.vars + let rval = s.val [stmt.rexpr], lval = s.val [stmt.lexpr] { + no lval & Null + s'.holds = s.holds ++ (lval.slot[stmt.field] -> rval) + } + } + +assert TypeSoundness { + all s, s': State, stmt: Setter | + {RuntimeTypesOK[s] + ExecuteSetter [s, s', stmt] + TypeChecksSetter[stmt] + } => RuntimeTypesOK[s'] + } + +fact {all o, o': Object | some o.slot[Field] & o'.slot[Field] => o = o'} +fact {all g: Getter | no g & g.^subexprs} + +fact ScopeFact { + #Assignment =< 1 + #Class =< 5 + #Interface =< 5 +} + +check TypeSoundness for 3 expect 0 + +check TypeSoundness for 2 State, 1 Assignment, +1 Statement, 5 Interface, 5 Class, 1 Null, +7 Object, 12 Expr, 3 Field, 3 Slot expect 0 + +// very slow +// check TypeSoundness for 2 State, 1 Statement, +// 10 Type, 8 Value, 12 Expr, +// 3 Field, 3 Slot expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/lists.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/lists.als new file mode 100644 index 00000000..aabd5f63 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/lists.als @@ -0,0 +1,48 @@ +/* + * a simple list module + * which demonstrates how to create predicates and fields that mirror each other + * thus allowing recursive constraints (even though recursive predicates are not + * currently supported by Alloy) + * author: Robert Seater + */ + +module list + +sig Thing {} +fact NoStrayThings {Thing in List.car} + +abstract sig List { + equivTo: set List, + prefixes: set List + } +sig NonEmptyList extends List { + car: one Thing, + cdr: one List + } +sig EmptyList extends List {} + +pred isFinite [L:List] {some e: EmptyList | e in L.*cdr} +fact finite {all L: List | isFinite[L]} + +fact Equivalence { + all a,b: List | (a in b.equivTo) <=> ((a.car = b.car and b.cdr in a.cdr.equivTo) and (#a.*cdr = #b.*cdr)) + } +assert reflexive {all L: List | L in L.equivTo} +check reflexive for 6 expect 0 +assert symmetric {all a,b: List | a in b.equivTo <=> b in a.equivTo} +check symmetric for 6 expect 0 +assert empties {all a,b: EmptyList | a in b.equivTo} +check empties for 6 expect 0 + +fact prefix { //a is a prefix of b + all e: EmptyList, L:List | e in L.prefixes + all a,b: NonEmptyList | (a in b.prefixes) <=> (a.car = b.car + and a.cdr in b.cdr.prefixes + and #a.*cdr < #b.*cdr) +} + +pred show { + some a, b: NonEmptyList | a!=b && b in a.prefixes + } +run show for 4 expect 1 + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/lists.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/lists.thm new file mode 100644 index 00000000..6da43857 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/lists.thm @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/marksweepgc.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/marksweepgc.als new file mode 100644 index 00000000..b8081e3f --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/marksweepgc.als @@ -0,0 +1,83 @@ +module examples/systems/marksweepgc + +/* + * Model of mark and sweep garbage collection. + */ + +// a node in the heap +sig Node {} + +sig HeapState { + left, right : Node -> lone Node, + marked : set Node, + freeList : lone Node +} + +pred clearMarks[hs, hs' : HeapState] { + // clear marked set + no hs'.marked + // left and right fields are unchanged + hs'.left = hs.left + hs'.right = hs.right +} + +/** + * simulate the recursion of the mark() function using transitive closure + */ +fun reachable[hs: HeapState, n: Node] : set Node { + n + n.^(hs.left + hs.right) +} + +pred mark[hs: HeapState, from : Node, hs': HeapState] { + hs'.marked = hs.reachable[from] + hs'.left = hs.left + hs'.right = hs.right +} + +/** + * complete hack to simulate behavior of code to set freeList + */ +pred setFreeList[hs, hs': HeapState] { + // especially hackish + hs'.freeList.*(hs'.left) in (Node - hs.marked) + all n: Node | + (n !in hs.marked) => { + no hs'.right[n] + hs'.left[n] in (hs'.freeList.*(hs'.left)) + n in hs'.freeList.*(hs'.left) + } else { + hs'.left[n] = hs.left[n] + hs'.right[n] = hs.right[n] + } + hs'.marked = hs.marked +} + +pred GC[hs: HeapState, root : Node, hs': HeapState] { + some hs1, hs2: HeapState | + hs.clearMarks[hs1] && hs1.mark[root, hs2] && hs2.setFreeList[hs'] +} + +assert Soundness1 { + all h, h' : HeapState, root : Node | + h.GC[root, h'] => + (all live : h.reachable[root] | { + h'.left[live] = h.left[live] + h'.right[live] = h.right[live] + }) +} + +assert Soundness2 { + all h, h' : HeapState, root : Node | + h.GC[root, h'] => + no h'.reachable[root] & h'.reachable[h'.freeList] +} + +assert Completeness { + all h, h' : HeapState, root : Node | + h.GC[root, h'] => + (Node - h'.reachable[root]) in h'.reachable[h'.freeList] +} + +check Soundness1 for 3 expect 0 +check Soundness2 for 3 expect 0 +check Completeness for 3 expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/views.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/views.als new file mode 100644 index 00000000..3a5ab82b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/systems/views.als @@ -0,0 +1,217 @@ +module examples/systems/views + +/* + * Model of views in object-oriented programming. + * + * Two object references, called the view and the backing, + * are related by a view mechanism when changes to the + * backing are automatically propagated to the view. Note + * that the state of a view need not be a projection of the + * state of the backing; the keySet method of Map, for + * example, produces two view relationships, and for the + * one in which the map is modified by changes to the key + * set, the value of the new map cannot be determined from + * the key set. Note that in the iterator view mechanism, + * the iterator is by this definition the backing object, + * since changes are propagated from iterator to collection + * and not vice versa. Oddly, a reference may be a view of + * more than one backing: there can be two iterators on the + * same collection, eg. A reference cannot be a view under + * more than one view type. + * + * A reference is made dirty when it is a backing for a view + * with which it is no longer related by the view invariant. + * This usually happens when a view is modified, either + * directly or via another backing. For example, changing a + * collection directly when it has an iterator invalidates + * it, as does changing the collection through one iterator + * when there are others. + * + * More work is needed if we want to model more closely the + * failure of an iterator when its collection is invalidated. + * + * As a terminological convention, when there are two + * complementary view relationships, we will give them types + * t and t'. For example, KeySetView propagates from map to + * set, and KeySetView' propagates from set to map. + * + * author: Daniel Jackson + */ + +open util/ordering[State] as so +open util/relation as rel + +sig Ref {} +sig Object {} + +-- t->b->v in views when v is view of type t of backing b +-- dirty contains refs that have been invalidated +sig State { + refs: set Ref, + obj: refs -> one Object, + views: ViewType -> refs -> refs, + dirty: set refs +-- , anyviews: Ref -> Ref -- for visualization + } +-- {anyviews = ViewType.views} + +sig Map extends Object { + keys: set Ref, + map: keys -> one Ref + }{all s: State | keys + Ref.map in s.refs} +sig MapRef extends Ref {} +fact {State.obj[MapRef] in Map} + +sig Iterator extends Object { + left, done: set Ref, + lastRef: lone done + }{all s: State | done + left + lastRef in s.refs} +sig IteratorRef extends Ref {} +fact {State.obj[IteratorRef] in Iterator} + +sig Set extends Object { + elts: set Ref + }{all s: State | elts in s.refs} +sig SetRef extends Ref {} +fact {State.obj[SetRef] in Set} + +abstract sig ViewType {} +one sig KeySetView, KeySetView', IteratorView extends ViewType {} +fact ViewTypes { + State.views[KeySetView] in MapRef -> SetRef + State.views[KeySetView'] in SetRef -> MapRef + State.views[IteratorView] in IteratorRef -> SetRef + all s: State | s.views[KeySetView] = ~(s.views[KeySetView']) + } + +/** + * mods is refs modified directly or by view mechanism + * doesn't handle possibility of modifying an object and its view at once? + * should we limit frame conds to non-dirty refs? + */ +pred modifies [pre, post: State, rs: set Ref] { + let vr = pre.views[ViewType], mods = rs.*vr { + all r: pre.refs - mods | pre.obj[r] = post.obj[r] + all b: mods, v: pre.refs, t: ViewType | + b->v in pre.views[t] => viewFrame [t, pre.obj[v], post.obj[v], post.obj[b]] + post.dirty = pre.dirty + + {b: pre.refs | some v: Ref, t: ViewType | + b->v in pre.views[t] && !viewFrame [t, pre.obj[v], post.obj[v], post.obj[b]] + } + } + } + +pred allocates [pre, post: State, rs: set Ref] { + no rs & pre.refs + post.refs = pre.refs + rs + } + +/** + * models frame condition that limits change to view object from v to v' when backing object changes to b' + */ +pred viewFrame [t: ViewType, v, v', b': Object] { + t in KeySetView => v'.elts = dom [b'.map] + t in KeySetView' => b'.elts = dom [v'.map] + t in KeySetView' => (b'.elts) <: (v.map) = (b'.elts) <: (v'.map) + t in IteratorView => v'.elts = b'.left + b'.done + } + +pred MapRef.keySet [pre, post: State, setRefs: SetRef] { + post.obj[setRefs].elts = dom [pre.obj[this].map] + modifies [pre, post, none] + allocates [pre, post, setRefs] + post.views = pre.views + KeySetView->this->setRefs + KeySetView'->setRefs->this + } + +pred MapRef.put [pre, post: State, k, v: Ref] { + post.obj[this].map = pre.obj[this].map ++ k->v + modifies [pre, post, this] + allocates [pre, post, none] + post.views = pre.views + } + +pred SetRef.iterator [pre, post: State, iterRef: IteratorRef] { + let i = post.obj[iterRef] { + i.left = pre.obj[this].elts + no i.done + i.lastRef + } + modifies [pre,post,none] + allocates [pre, post, iterRef] + post.views = pre.views + IteratorView->iterRef->this + } + +pred IteratorRef.remove [pre, post: State] { + let i = pre.obj[this], i' = post.obj[this] { + i'.left = i.left + i'.done = i.done - i.lastRef + no i'.lastRef + } + modifies [pre,post,this] + allocates [pre, post, none] + pre.views = post.views + } + +pred IteratorRef.next [pre, post: State, ref: Ref] { + let i = pre.obj[this], i' = post.obj[this] { + ref in i.left + i'.left = i.left - ref + i'.done = i.done + ref + i'.lastRef = ref + } + modifies [pre, post, this] + allocates [pre, post, none] + pre.views = post.views + } + +pred IteratorRef.hasNext [s: State] { + some s.obj[this].left + } + +assert zippishOK { + all + ks, vs: SetRef, + m: MapRef, + ki, vi: IteratorRef, + k, v: Ref | + let s0=so/first, + s1=so/next[s0], + s2=so/next[s1], + s3=so/next[s2], + s4=so/next[s3], + s5=so/next[s4], + s6=so/next[s5], + s7=so/next[s6] | + ({ + precondition [s0, ks, vs, m] + no s0.dirty + ks.iterator [s0, s1, ki] + vs.iterator [s1, s2, vi] + ki.hasNext [s2] + vi.hasNext [s2] + ki.this/next [s2, s3, k] + vi.this/next [s3, s4, v] + m.put [s4, s5, k, v] + ki.remove [s5, s6] + vi.remove [s6, s7] + } => no State.dirty) + } + +pred precondition [pre: State, ks, vs, m: Ref] { + // all these conditions and other errors discovered in scope of 6 but 8,3 + // in initial state, must have view invariants hold + (all t: ViewType, b, v: pre.refs | + b->v in pre.views[t] => viewFrame [t, pre.obj[v], pre.obj[v], pre.obj[b]]) + // sets are not aliases +-- ks != vs + // sets are not views of map +-- no (ks+vs)->m & ViewType.pre.views + // no iterator currently on either set +-- no Ref->(ks+vs) & ViewType.pre.views + } + +check zippishOK for 6 but 8 State, 3 ViewType expect 1 + +/** + * experiment with controlling heap size + */ +fact {all s: State | #s.obj < 5} diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/birthday.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/birthday.als new file mode 100644 index 00000000..092097f0 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/birthday.als @@ -0,0 +1,68 @@ +module examples/toys/birthday + +/* + * Birthday Book + * + * A classic Z example to explain the basic form of an Alloy model. For the original, + * see J.M. Spivey, The Z Notation, Second Edition, Prentice Hall, 1992. + * + * A birthday book has two fields: known, a set of names (of persons whose birthdays are known), + * and date, a function from known names to dates. The operation AddBirthday adds an association + * between a name and a date; it uses the relational override operator (++), so any existing + * mapping from the name to a date is replaced. DelBirthday removes the entry for a given name. + * FindBirthday obtains the date d for a name n. The argument d is declared to be optional (that is, + * a singleton or empty set), so if there is no entry for n, d will be empty. Remind gives the set + * of names whose birthdays fall on a particular day. + * + * The assertion AddWorks says that if you add an entry, then look it up, you get back what you + * just entered. DelIsUndo says that doing DelBirthday after AddBirthday undoes it, as if the add + * had never happened. The first of these assertions is valid; the second isn't. + * + * The function BusyDay shows a case in which Remind produces more than one card. + * + * author: Daniel Jackson, 11/14/01 + */ + +sig Name {} +sig Date {} +sig BirthdayBook {known: set Name, date: known -> one Date} + +pred AddBirthday [bb, bb': BirthdayBook, n: Name, d: Date] { + bb'.date = bb.date ++ (n->d) + } + +pred DelBirthday [bb, bb': BirthdayBook, n: Name] { + bb'.date = bb.date - (n->Date) + } + +pred FindBirthday [bb: BirthdayBook, n: Name, d: lone Date] { + d = bb.date[n] + } + +pred Remind [bb: BirthdayBook, today: Date, cards: set Name] { + cards = (bb.date).today + } + +pred InitBirthdayBook [bb: BirthdayBook] { + no bb.known + } + +assert AddWorks { + all bb, bb': BirthdayBook, n: Name, d: Date, d': lone Date | + AddBirthday [bb,bb',n,d] && FindBirthday [bb',n,d'] => d = d' + } + +assert DelIsUndo { + all bb1,bb2,bb3: BirthdayBook, n: Name, d: Date| + AddBirthday [bb1,bb2,n,d] && DelBirthday [bb2,bb3,n] + => bb1.date = bb3.date + } + +check AddWorks for 3 but 2 BirthdayBook expect 0 +check DelIsUndo for 3 but 2 BirthdayBook expect 1 + +pred BusyDay [bb: BirthdayBook, d: Date]{ + some cards: set Name | Remind [bb,d,cards] && !lone cards + } + +run BusyDay for 3 but 1 BirthdayBook expect 1 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/birthday.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/birthday.thm new file mode 100644 index 00000000..3c3b050b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/birthday.thm @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/ceilingsAndFloors.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/ceilingsAndFloors.als new file mode 100644 index 00000000..e02fe438 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/ceilingsAndFloors.als @@ -0,0 +1,46 @@ +module models/examples/toys/CeilingsAndFloors + +/* + * In his 1973 song, Paul Simon said "One Man's Ceiling Is Another Man's Floor". + * Does it follow that "One Man's Floor Is Another Man's Ceiling"? + * + * To see why not, check the assertion BelowToo. + * + * Perhaps simply preventing man's own floor from being his ceiling is enough, + * as is done in the Geometry constraint. BelowToo' shows that there are still + * cases where Geometry holds but the implication does not, although now + * the smallest solution has 3 Men and 3 Platforms instead of just 2 of each. + * + * What if we instead prevent floors and ceilings from being shared, + * as is done in the NoSharing constraint? The assertion BelowToo'' + * has no counterexamples, demonstrating that the implication now + * holds for all small examples. + * + * model author: Daniel Jackson (11/2001) + * modified by Robert Seater (11/2004) + */ + +sig Platform {} +sig Man {ceiling, floor: Platform} + +fact PaulSimon {all m: Man | some n: Man | n.Above[m]} + +pred Above[m, n: Man] {m.floor = n.ceiling} + +assert BelowToo { all m: Man | some n: Man | m.Above[n] } + +check BelowToo for 2 expect 1 + +pred Geometry {no m: Man | m.floor = m.ceiling} + +assert BelowToo' { Geometry => (all m: Man | some n: Man | m.Above[n]) } +check BelowToo' for 2 expect 0 +check BelowToo' for 3 expect 1 + +pred NoSharing { + no m,n: Man | m!=n && (m.floor = n.floor || m.ceiling = n.ceiling) +} + +assert BelowToo'' { NoSharing => (all m: Man | some n: Man | m.Above[n]) } +check BelowToo'' for 6 expect 0 +check BelowToo'' for 10 expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/ceilingsAndFloors.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/ceilingsAndFloors.thm new file mode 100644 index 00000000..b58a5b0d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/ceilingsAndFloors.thm @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/genealogy.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/genealogy.als new file mode 100644 index 00000000..2a9e2134 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/genealogy.als @@ -0,0 +1,74 @@ +module examples/toys/genealogy + +/* + * Toy model of genealogical relationships + * + * The purpose of this model is to introduce basic concepts in Alloy. + * The signature Person introduces a set of persons; this is paritioned into + * two subsets, Man and Woman. The subsignature Adam declares a set of men + * with one element -- that is, a scalar. Similarly, Eve declares a single + * woman. + * + * The Person signature declares two fields: a person has one or zero spouses + * and a set of parents. + * + * The facts should be self-explanatory. Note that the constraint that + * spouse is a symmetric relation (that is, p is a spouse of q if q is a spouse + * of p) is written by equating the field, viewed as a relation, to its + * transpose. Since signatures have their own namespaces, and the same field + * name can refer to different fields in different relations, it is necessary + * to indicate which signature the field belongs to. This is not necessary when + * dereferencing a field, because the appropriate field is automatically + * determined by the type of the referencing expression. + * + * The command has no solutions. Given only 5 persons, it's not possible + * to have a couple distinct from Adam and Eve without incest. To understand + * the model, try weakening the constraints by commenting lines out (just + * put two hyphens at the start of a line) and rerunning the command. + * + * author: Daniel Jackson, 11/13/01 + */ + +abstract sig Person {spouse: lone Person, parents: set Person} +sig Man, Woman extends Person {} +one sig Eve extends Woman {} +one sig Adam extends Man {} + +fact Biology { + -- nobody is his or her own ancestor + no p: Person | p in p.^parents + } + +fact Bible { + -- every person except Adam and Eve has a mother and father + all p: Person - (Adam + Eve) | one mother: Woman, father: Man | + p.parents = mother + father + -- Adam and Eve have no parents + no (Adam + Eve).parents + -- Adam's spouse is Eve + Adam.spouse = Eve + } + +fact SocialNorms { + -- nobody is his or her own spouse + no p: Person | p.spouse = p + -- spouse is symmetric + spouse = ~spouse + -- a man's spouse is a woman and vice versa + Man.spouse in Woman && Woman.spouse in Man + } + +fact NoIncest { + -- can't marry a sibling + no p: Person | some p.spouse.parents & p.parents + -- can't marry a parent + no p: Person | some p.spouse & p.parents + } + +pred Show { + some p: Person - (Adam + Eve) | some p.spouse + } +run Show for 6 expect 1 + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/genealogy.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/genealogy.thm new file mode 100644 index 00000000..fbeb5cad --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/genealogy.thm @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/grandpa.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/grandpa.als new file mode 100644 index 00000000..099cd0d5 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/grandpa.als @@ -0,0 +1,88 @@ +module grandpa + +/* + * An Alloy model of the song "I Am My Own Grandpa" + * by Dwight B. Latham and Moe Jaffe + * + * The challenge is to produce a man who is his own grandfather + * without resorting to incest or time travel. Executing the predicate + * "ownGrandpa" will demonstrate how such a thing can occur. + * + * The full song lyrics, which describe an isomorophic solution, + * are included at the end of this file. + * + * model author: Daniel Jackson + */ + +abstract sig Person { + father: lone Man, + mother: lone Woman + } + +sig Man extends Person { wife: lone Woman } + +sig Woman extends Person { husband: lone Man } + +fact Biology { no p: Person | p in p.^(mother+father) } + +fact Terminology { wife = ~husband } + +fact SocialConvention { + no wife & *(mother+father).mother + no husband & *(mother+father).father + } + +fun grandpas [p: Person]: set Person { + let parent = mother + father + father.wife + mother.husband | + p.parent.parent & Man + } + +pred ownGrandpa [m: Man] { m in grandpas[m] } + +run ownGrandpa for 4 Person expect 1 + +/* defined variables: + * + * spouse = husband+wife + */ + +/* +I Am My Own Grandpa +by Dwight B. Latham and Moe Jaffe + +Many many years ago, when I was twenty-three, +I was married to a widow as pretty as can be, +This widow had a grown-up daughter who had hair of red, +My father fell in love with her and soon the two were wed. + + I'm my own grandpa, I'm my own grandpa. + It sounds funny, I know, but it really is so + I'm my own grandpa. + +This made my dad my son-in-law and changed my very life, +For my daughter was my mother, for she was my father's wife. +To complicate the matter, even though it brought me joy, +I soon became the father of a bouncing baby boy. + +My little baby thus became a brother-in-law to dad, +And so became my uncle, though it made me very sad, +For if he was my uncle then that also made him brother +To the widow's grown-up daughter, who of course was my step-mother. + +Father's wife then had a son who kept them on the run. +And he became my grandchild for he was my daughter's son. +My wife is now my mother's mother and it makes me blue, +Because although she is my wife, she's my grandmother, too. + +Oh, if my wife's my grandmother then I am her grandchild. +And every time I think of it, it nearly drives me wild. +For now I have become the strangest case you ever saw +As the husband of my grandmother, I am my own grandpa. + + I'm my own grandpa, I'm my own grandpa. + It sounds funny, I know, but it really is so + I'm my own grandpa. + I'm my own grandpa, I'm my own grandpa. + It sounds funny, I know, but it really is so + I'm my own grandpa. +*/ diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/grandpa.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/grandpa.thm new file mode 100644 index 00000000..781b6c9f --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/grandpa.thm @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/javatypes.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/javatypes.als new file mode 100644 index 00000000..2e60d64d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/javatypes.als @@ -0,0 +1,46 @@ +module examples/toys/javatypes + +/* + * A simple model of typing in Java. + * + * This model describes the basic notions of typing in Java. + * It ignores primitive types and null references. Each type has + * some set of subtypes. Types are partitioned into class and + * interface types. Object is a particular class. + * + * The fact TypeHierarchy says that every type is a direct or + * indirect subtype of Object; that no type is a direct or indirect + * of itself; and every type is a subtype of at most one class. + * + * An object instance has a type (its creation type) that is a class. + * A variable may hold an instance, and has a declared type. The + * fact TypeSoundness says that all instances held by a variable + * have types that are direct or indirect subtypes of the variable's + * declared type. + * + * The function Show specifies a case in which there is a class + * distinct from Object; there is some interface; and some variable + * has a declared type that is an interface. + * + * author: Daniel Jackson, 11/13/01 + */ + +abstract sig Type {subtypes: set Type} +sig Class, Interface extends Type {} +one sig Object extends Class {} +fact TypeHierarchy { + Type in Object.*subtypes + no t: Type | t in t.^subtypes + all t: Type | lone t.~subtypes & Class + } +sig Instance {type: Class} +sig Variable {holds: lone Instance, type: Type} +fact TypeSoundness { + all v: Variable | v.holds.type in v.type.*subtypes + } +pred Show { + some Class - Object + some Interface + some Variable.type & Interface + } +run Show for 3 expect 1 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/life.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/life.als new file mode 100644 index 00000000..5ee1b159 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/life.als @@ -0,0 +1,94 @@ +module examples/toys/life + +/* + * John Conway's Game of Life + * + * For a detailed description, see: + * http://www.math.com/students/wonders/life/life.html + * + * authors: Bill Thies, Manu Sridharan + */ + +open util/ordering[State] as ord + +sig Point { + right: lone Point, + below: lone Point +} + +fact Acyclic { + all p: Point | p !in p.^(right + below) +} + +one sig Root extends Point {} + +fact InnerSquaresCommute { + all p: Point { + p.below.right = p.right.below + some p.below && some p.right => some p.below.right + } +} + +fact TopRow { + all p: Point - Root | no p.~below => # p.*below = # Root.*below +} + +fact Connected { + Root.*(right + below) = Point +} + +pred Square { + # Root.*right = # Root.*below +} + +run Square for 6 Point, 3 State expect 1 + +pred Rectangle {} + +sig State { + live : set Point +} + +fun Neighbors[p : Point] : set Point { + p.right + p.right.below + p.below + + p.below.~right + p.~right + + p.~right.~below + p.~below + + p.~below.right +} + +fun LiveNeighborsInState[p : Point, s : State] : set Point { + Neighbors[p] & s.live +} + +pred Trans[pre, post: State, p : Point] { + let preLive = LiveNeighborsInState[p,pre] | + // dead cell w/ 3 live neighbors becomes live + (p !in pre.live && # preLive = 3) => + p in post.live + else ( + // live cell w/ 2 or 3 live neighbors stays alive + (p in pre.live && (# preLive = 2 || # preLive = 3)) => + p in post.live else p !in post.live + ) +} + +fact ValidTrans { + all pre : State - ord/last | + let post = ord/next[pre] | + all p : Point | + Trans[pre,post,p] +} + +pred Show {} + +// slow +run Show for exactly 12 Point, 3 State expect 1 + +// a small but interesting example +pred interesting { + some State.live + some Point - State.live + some right + some below +} +run interesting for exactly 6 Point, 3 State expect 1 \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/life.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/life.thm new file mode 100644 index 00000000..3a015d56 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/life.thm @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/numbering.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/numbering.als new file mode 100644 index 00000000..f8c9b5f3 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/numbering.als @@ -0,0 +1,129 @@ +module examples/toys/numbering + +/* + * Alloy model of paragraph numbering + * + * This model addresses some issues that arose in the design of a text tagging tool. The + * tool receives as input a text stream in which paragraphs are tagged with style names, + * along with a style sheet that indicates how paragraphs of a given style are to be numbered. + * In practice, the style sheet includes such details as what symbols to use for numbering (eg, + * roman numericals, letters of the alphabet, etc), but these details are uninteresting. + * + * In the simplest case, the styles are organized into chains. For example, there may be a + * single chain, chapter-section-subsection, so that chapters are numbered 1, 2, 3, etc, + * sections are numbered 1.1, 1.2, 1.3, etc, and subsections are numbered 1.1.1, 1.1.2, + * etc, each paragraph being numbered according to a number associated with its own + * style, and a number for each ancestor. + * + * Some styles, however, should be numbered independently of one another, but still + * according to the same ancestors. For example, we might also have a figure style + * that is numbered, like section, according to its chapter, with figures and sections in + * some arbitrary interleaving, the numbering of one not affecting the other. + * + * So in our style hierarchy, a style can have more than one "child". A more tricky complication + * allows multiple parents. We might want to have an appendix style, for example, with a + * different numbering from the chapter style, but would want section and subsection to work + * within appendix exactly as they would work within chapter. So the first section in an + * appendix numbered A might be numbered A.1, but if placed in a chapter numbered 1, + * it would be numbered 1.1 instead. + * + * To account for this, styles are organized into replacement classes. Chapter and appendix, + * for example, are replacements of one another. When a chapter style is encountered, it + * is as if the style hierarchy contains only chapter, with children section, figure and so on; + * when appendix is encountered subsequently, chapter is replaced, and figure and section + * become children of appendix. We'll call the set of styles active in the tree at a given time + * the "context". + * + * The first part focuses on the replacement mechanism. It characterizes a well-formed + * style sheet (with the fact StyleSheet), and a well-formed state (with the fact Forest). An + * operation addStyleToContext describes how the context is altered, and includes a + * precondition requiring that, for example, a child is not encountered before its parents + * (a document can't start with subsection, eg). The assertion PreservesForest checks that the + * operation preserves the well-formedness of the state; it was analyzing this that helped + * determine an appropriate precondition and the appropriate constraints in the invariant. + * + * The second part adds the numbering of styles. Note the idiom of declaring a subsignature + * and then equating it to the supersignature, thus essentially retrofitting the new fields to the + * old signature. A second operation describes how numbers are assigned; the conjunction of the + * two operations is what happens when a style is encountered. The assertion AddNeverReduces + * checks that when a style is encountered the number associated with each style in the context is + * not decreased. The first assertion is valid; the second isn't. + * + * author: Daniel Jackson, 11/15/01 + */ + +open util/relation as rel + +sig Style { + replaces, parents: set Style + } + +fact StyleSheet { + equivalence [replaces, Style] + acyclic [parents, Style] + all x: Style { + x.replaces.parents.replaces = x.parents + all y,z: x.parents | y in z.replaces + } + } + +sig State { + context: set Style, + ancestors: Style -> Style + } + +fact DefineAncestors { + all s: State, x: Style | s.ancestors [x] = x.*parents & s.context + } + +pred Forest [s: State] { + all x: s.context | + some root: s.ancestors[x] { + no root.parents + all y: s.ancestors[x] - root | one y.parents & s.context + } + all x: Style | lone x.replaces & s.context + } + +pred AddStyleToContext [s, s': State, style: Style] { + all x: style.^parents | some x.replaces & s.context + s'.context = s.context - style.replaces + style + } + +assert PreserveForest { + all s,s': State, z: Style | + Forest[s] && AddStyleToContext [s,s',z] => Forest[s'] + } + +check PreserveForest for 4 expect 0 + +sig Value {next: Value} +sig NumberedStyle extends Style { + initial: Value + } +sig NumberedState extends State { + value: Style -> one Value + } +fact {Style = NumberedStyle} +fact {State = NumberedState} + +pred AddStyleToNumbering [s, s': State, style: Style] { + s'.value[style] = (style in s.context => s.value[style].next else style.initial) + s'.context = s.context - style.replaces + style + all x: Style - style | + s'.value[x] = (style in x.^parents => x.initial else s.value[x]) + } + +pred AddStyle [s, s': State, style: Style] { + AddStyleToContext [s,s',style] + AddStyleToNumbering [s,s',style] + } + +assert AddNeverReduces { + all s,s': State, z: Style | + Forest[s] && AddStyle [s,s',z] => + (all y: s'.context | s'.value[y] in s.value[y].*next) + } + +check AddNeverReduces for 5 expect 1 + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/railway.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/railway.als new file mode 100644 index 00000000..549bdb92 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/railway.als @@ -0,0 +1,64 @@ +module examples/toys/railway + +/* + * A simple model of a railway system. Trains sit on segments of tracks + * and segments overlap one another. It shows a that simple gate policy + * does not ensure train safety. + * + * author: Daniel Jackson + */ + +sig Seg {next, overlaps: set Seg} +fact {all s: Seg | s in s.overlaps} +fact {all s1, s2: Seg | s1 in s2.overlaps => s2 in s1.overlaps} + +sig Train {} +sig GateState {closed: set Seg} +sig TrainState {on: Train -> lone Seg, occupied: set Seg} +fact {all x: TrainState | + x.occupied = {s: Seg | some t: Train | t.(x.on) = s} + } + +pred Safe [x: TrainState] {all s: Seg | lone s.overlaps.~(x.on)} + +pred MayMove [g: GateState, x: TrainState, ts: set Train] { + no ts.(x.on) & g.closed + } + +pred TrainsMove [x, x': TrainState, ts: set Train] { + all t: ts | t.(x'.on) in t.(x.on).next + all t: Train - ts | t.(x'.on) = t.(x.on) + } + +pred GatePolicy [g: GateState, x: TrainState] { + x.occupied.overlaps.~next in g.closed + all s1, s2: Seg | some s1.next.overlaps & s2.next => lone (s1+s2) - g.closed +} + +assert PolicyWorks { + all x, x': TrainState, g: GateState, ts: set Train | + {MayMove [g, x, ts] + TrainsMove [x, x', ts] + Safe [x] + GatePolicy [g, x] + } => Safe [x'] + } + +-- has counterexample in scope of 4 +check PolicyWorks for 2 Train, 1 GateState, 2 TrainState, 4 Seg expect 1 + +pred TrainsMoveLegal [x, x': TrainState, g: GateState, ts: set Train] { + TrainsMove [x, x', ts] + MayMove [g, x, ts] + GatePolicy [g, x] + } +run TrainsMoveLegal for 3 expect 1 + + + +// DEFINED VARIABLES +// Defined variables are uncalled, no-argument functions. +// They are helpful for getting good visualization. +fun contains [] : TrainState -> Seg -> Train { + {state: TrainState, seg: Seg, train: Train | seg = train.(state.on)} +} diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/railway.thm b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/railway.thm new file mode 100644 index 00000000..40baef57 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/railway.thm @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/trivial.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/trivial.als new file mode 100644 index 00000000..71f19d3d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/toys/trivial.als @@ -0,0 +1,8 @@ +//a trivial model whose command has no solution +module trivial + +sig S {} + +fact { 1=2 } + +run {some S} expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/tutorial/farmer.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/tutorial/farmer.als new file mode 100644 index 00000000..94ea0d5d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/examples/tutorial/farmer.als @@ -0,0 +1,92 @@ +module examples/tutorial/farmer + +/* + * The classic river crossing puzzle. A farmer is carrying a fox, a + * chicken, and a sack of grain. He must cross a river using a boat + * that can only hold the farmer and at most one other thing. If the + * farmer leaves the fox alone with the chicken, the fox will eat the + * chicken; and if he leaves the chicken alone with the grain, the + * chicken will eat the grain. How can the farmer bring everything + * to the far side of the river intact? + * + * authors: Greg Dennis, Rob Seater + * + * Acknowledgements to Derek Rayside and his students for finding and + * fixing a bug in the "crossRiver" predicate. + */ + +open util/ordering[State] as ord + +/** + * The farmer and all his possessions will be represented as Objects. + * Some objects eat other objects when the Farmer's not around. + */ +abstract sig Object { eats: set Object } +one sig Farmer, Fox, Chicken, Grain extends Object {} + +/** + * Define what eats what when the Farmer' not around. + * Fox eats the chicken and the chicken eats the grain. + */ +fact eating { eats = Fox->Chicken + Chicken->Grain } + +/** + * The near and far relations contain the objects held on each + * side of the river in a given state, respectively. + */ +sig State { + near: set Object, + far: set Object +} + +/** + * In the initial state, all objects are on the near side. + */ +fact initialState { + let s0 = ord/first | + s0.near = Object && no s0.far +} + +/** + * Constrains at most one item to move from 'from' to 'to'. + * Also constrains which objects get eaten. + */ +pred crossRiver [from, from', to, to': set Object] { + // either the Farmer takes no items + (from' = from - Farmer - from'.eats and + to' = to + Farmer) or + // or the Farmer takes one item + (one x : from - Farmer | { + from' = from - Farmer - x - from'.eats + to' = to + Farmer + x }) +} + +/** + * crossRiver transitions between states + */ +fact stateTransition { + all s: State, s': ord/next[s] { + Farmer in s.near => + crossRiver[s.near, s'.near, s.far, s'.far] else + crossRiver[s.far, s'.far, s.near, s'.near] + } +} + +/** + * the farmer moves everything to the far side of the river. + */ +pred solvePuzzle { + ord/last.far = Object +} + +run solvePuzzle for 8 State expect 1 + +/** + * no Object can be in two places at once + * this is implied by both definitions of crossRiver + */ +assert NoQuantumObjects { + no s : State | some x : Object | x in s.near and x in s.far +} + +check NoQuantumObjects for 8 State expect 0 \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/util/boolean.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/boolean.als new file mode 100644 index 00000000..61d8744e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/boolean.als @@ -0,0 +1,43 @@ +module util/boolean + +/* + * Creates a Bool type with two singleton subtypes: True + * and False. Provides common boolean operations. + * + * author: Greg Dennis + */ + +abstract sig Bool {} +one sig True, False extends Bool {} + +pred isTrue[b: Bool] { b in True } + +pred isFalse[b: Bool] { b in False } + +fun Not[b: Bool] : Bool { + Bool - b +} + +fun And[b1, b2: Bool] : Bool { + subset_[b1 + b2, True] +} + +fun Or[b1, b2: Bool] : Bool { + subset_[True, b1 + b2] +} + +fun Xor[b1, b2: Bool] : Bool { + subset_[Bool, b1 + b2] +} + +fun Nand[b1, b2: Bool] : Bool { + subset_[False, b1 + b2] +} + +fun Nor[b1, b2: Bool] : Bool { + subset_[b1 + b2, False] +} + +fun subset_[s1, s2: set Bool] : Bool { + (s1 in s2) => True else False +} diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/util/graph.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/graph.als new file mode 100644 index 00000000..b722ac13 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/graph.als @@ -0,0 +1,78 @@ +module util/graph[node] + +/* + * Utilities for some common operations and contraints + * on graphs. + * + * author: Greg Dennis + */ + +open util/relation as rel + +/** graph in undirected */ +pred undirected [r: node->node] { + symmetric[r] +} + +/** graph has no self-loops */ +pred noSelfLoops[r: node->node] { + irreflexive[r] +} + +/** graph is weakly connected */ +pred weaklyConnected[r: node->node] { + all n1, n2: node | n1 in n2.*(r + ~r) // Changed from ^ to * to permit singleton +} + +/** graph is strongly connected */ +pred stronglyConnected[r: node->node] { + all n1, n2: node | n1 in n2.*r // Changed from ^ to * to permit singleton +} + +/** graph is rooted at root */ +pred rootedAt[r: node->node, root: node] { + node in root.*r +} + +/** graph is a ring */ +pred ring [r: node->node] { + all n: node | one n.r && rootedAt[r, n] +} + +/** graph is a dag */ +pred dag [r: node->node] { + acyclic[r, node] +} + +/** graph is a forest */ +pred forest [r: node->node] { + dag[r] + all n: node | lone r.n +} + +/** graph is a tree */ +pred tree [r: node->node] { + forest[r] + lone root: node | no r.root +} + +/** graph is a tree rooted at root */ +pred treeRootedAt[r: node->node, root: node] { + forest[r] + rootedAt[r, root] +} + +/** returns the roots of the graph */ +fun roots [r: node->node] : set node { + node - node.^r +} + +/** returns the leaves of the grpah */ +fun leaves [r: node->node] : set node { + node - node.^~r +} + +/** returns the inner nodes (non-leaves) of the graph */ +fun innerNodes [r: node->node] : set node { + node - leaves[r] +} diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/util/integer.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/integer.als new file mode 100644 index 00000000..488c25e2 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/integer.als @@ -0,0 +1,112 @@ +module util/integer + +/* + * A collection of utility functions for using Integers in Alloy. + * Note that integer overflows are silently truncated to the current bitwidth + * using the 2's complement arithmetic, unless the "forbid overfows" option is + * turned on, in which case only models that don't have any overflows are + * analyzed. + */ + +fun add [n1, n2: Int] : Int { this/plus[n1, n2] } +fun plus [n1, n2: Int] : Int { n1 fun/add n2 } + +fun sub [n1, n2: Int] : Int { this/minus[n1, n2] } +fun minus [n1, n2: Int] : Int { n1 fun/sub n2 } + +fun mul [n1, n2: Int] : Int { n1 fun/mul n2 } + +/** + * Performs the division with "round to zero" semantics, except the following 3 cases + * 1) if a is 0, then it returns 0 + * 2) else if b is 0, then it returns 1 if a is negative and -1 if a is positive + * 3) else if a is the smallest negative integer, and b is -1, then it returns a + */ +fun div [n1, n2: Int] : Int { n1 fun/div n2 } + +/** answer is defined to be the unique integer that satisfies "a = ((a/b)*b) + remainder" */ +fun rem [n1, n2: Int] : Int { n1 fun/rem n2 } + +/** negate */ +fun negate [n: Int] : Int { 0 fun/sub n } + +/** equal to */ +pred eq [n1, n2: Int] { int[n1] = int[n2] } + +/** greater than */ +pred gt [n1, n2: Int] { n1 > n2 } + +/** less then */ +pred lt [n1, n2: Int] { n1 < n2 } + +/** greater than or equal */ +pred gte [n1, n2: Int] { n1 >= n2 } + +/** less than or equal */ +pred lte [n1, n2: Int] { n1 <= n2 } + +/** integer is zero */ +pred zero [n: Int] { n = 0 } + +/** positive */ +pred pos [n: Int] { n > 0 } + +/** negative */ +pred neg [n: Int] { n < 0 } + +/** non-positive */ +pred nonpos [n: Int] { n <= 0 } + +/** non-negative */ +pred nonneg [n: Int] { n >= 0 } + +/** signum (aka sign or sgn) */ +fun signum [n: Int] : Int { n<0 => (0 fun/sub 1) else (n>0 => 1 else 0) } + +/** + * returns the ith element (zero-based) from the set s + * in the ordering of 'next', which is a linear ordering + * relation like that provided by util/ordering + */ +fun int2elem[i: Int, next: univ->univ, s: set univ] : lone s { + {e: s | #^next.e = int i } +} + +/** + * returns the index of the element (zero-based) in the + * ordering of next, which is a linear ordering relation + * like that provided by util/ordering + */ +fun elem2int[e: univ, next: univ->univ] : lone Int { + Int[#^next.e] +} + +/** returns the largest integer in the current bitwidth */ +fun max:one Int { fun/max } + +/** returns the smallest integer in the current bitwidth */ +fun min:one Int { fun/min } + +/** maps each integer (except max) to the integer after it */ +fun next:Int->Int { fun/next } + +/** maps each integer (except min) to the integer before it */ +fun prev:Int->Int { ~next } + +/** given a set of integers, return the largest element */ +fun max [es: set Int]: lone Int { es - es.^prev } + +/** given a set of integers, return the smallest element */ +fun min [es: set Int]: lone Int { es - es.^next } + +/** given an integer, return all integers prior to it */ +fun prevs [e: Int]: set Int { e.^prev } + +/** given an integer, return all integers following it */ +fun nexts [e: Int]: set Int { e.^next } + +/** returns the larger of the two integers */ +fun larger [e1, e2: Int]: Int { let a=int[e1], b=int[e2] | (a b else a) } + +/** returns the smaller of the two integers */ +fun smaller [e1, e2: Int]: Int { let a=int[e1], b=int[e2] | (a a else b) } diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/util/natural.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/natural.als new file mode 100644 index 00000000..5d9f6246 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/natural.als @@ -0,0 +1,78 @@ +module util/natural + +/* + * Utility function and predicates for using the set of + * nonnegative integers (0, 1, 2, . . .). The number of + * naturals present in an analysis will be equal to the + * scope on Natural. Specifically, if the scope on Natural + * is N, then the naturals 0 through N-1 will be present. + * + * Note that the functions that return Naturals, such as + * 'add' and 'div', may return an empty set if no such + * Natural exists for that integer value. + * + * To write an Alloy model that makes use of negative + * integers, use the util/integer module instead. + * + * @author Greg Dennis + */ + +private open util/ordering[Natural] as ord +private open util/integer as integer + +sig Natural {} + +/** the integer zero */ +one sig Zero in Natural {} + +/** the integer one will be the empty set if the scope on Natural is less than two */ +lone sig One in Natural {} + +fact { + first in Zero + next[first] in One +} + +/** returns n + 1 */ +fun inc [n: Natural] : lone Natural { ord/next[n] } + +/** returns n - 1 */ +fun dec [n: Natural] : lone Natural { ord/prev[n] } + +/** returns n1 + n2 */ +fun add [n1, n2: Natural] : lone Natural { + {n: Natural | #ord/prevs[n] = #ord/prevs[n1] + #ord/prevs[n2]} +} + +/** returns n1 - n2 */ +fun sub [n1, n2: Natural] : lone Natural { + {n: Natural | #ord/prevs[n1] = #ord/prevs[n2] + #ord/prevs[n]} +} + +/** returns n1 * n2 */ +fun mul [n1, n2: Natural] : lone Natural { + {n: Natural | #ord/prevs[n] = #(ord/prevs[n1]->ord/prevs[n2])} +} + +/** returns n1 / n2 */ +fun div [n1, n2: Natural] : lone Natural { + {n: Natural | #ord/prevs[n1] = #(ord/prevs[n2]->ord/prevs[n])} +} + +/** returns true iff n1 is greater than n2 */ +pred gt [n1, n2: Natural] { ord/gt [n1, n2] } + +/** returns true iff n1 is less than n2 */ +pred lt [n1, n2: Natural] { ord/lt [n1, n2] } + +/** returns true iff n1 is greater than or equal to n2 */ +pred gte [n1, n2: Natural] { ord/gte[n1, n2] } + +/** returns true iff n1 is less than or equal to n2 */ +pred lte [n1, n2: Natural] { ord/lte[n1, n2] } + +/** returns the maximum integer in ns */ +fun max [ns: set Natural] : lone Natural { ord/max[ns] } + +/** returns the minimum integer in ns */ +fun min [ns: set Natural] : lone Natural { ord/min[ns] } diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/util/ordering.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/ordering.als new file mode 100644 index 00000000..e26d7bd0 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/ordering.als @@ -0,0 +1,106 @@ +module util/ordering[exactly elem] + +/* + * Creates a single linear ordering over the atoms in elem. It also constrains all + * the atoms to exist that are permitted by the scope on elem. That is, if the scope + * on a signature S is 5, opening util/ordering[S] will force S to have 5 elements + * and create a linear ordering over those five elements. The predicates and + * functions below provide access to properties of the linear ordering, such as + * which element is first in the ordering, or whether a given element precedes + * another. You cannotcreate multiple linear orderings over the same signature with + * this model. If you that functionality, try using the util/sequence module instead. + * + * Technical comment: + * An important constraint: elem must contain all atoms permitted by the scope. + * This is to let the analyzer optimize the analysis by setting all fields of each + * instantiation of Ord to predefined values: e.g. by setting 'last' to the highest + * atom of elem and by setting 'next' to {,,...}, where n is + * the scope of elem. Without this constraint, it might not be true that Ord.last is + * a subset of elem, and that the domain and range of Ord.next lie inside elem. + * + * author: Ilya Shlyakhter + * revisions: Daniel jackson + */ + +private one sig Ord { + First: set elem, + Next: elem -> elem +} { + pred/totalOrder[elem,First,Next] +} + +/** first */ +fun first: one elem { Ord.First } + +/** last */ +fun last: one elem { elem - (next.elem) } + +/** return a mapping from each element to its predecessor */ +fun prev : elem->elem { ~(Ord.Next) } + +/** return a mapping from each element to its successor */ +fun next : elem->elem { Ord.Next } + +/** return elements prior to e in the ordering */ +fun prevs [e: elem]: set elem { e.^(~(Ord.Next)) } + +/** return elements following e in the ordering */ +fun nexts [e: elem]: set elem { e.^(Ord.Next) } + +/** e1 is less than e2 in the ordering */ +pred lt [e1, e2: elem] { e1 in prevs[e2] } + +/** e1 is greater than e2 in the ordering */ +pred gt [e1, e2: elem] { e1 in nexts[e2] } + +/** e1 is less than or equal to e2 in the ordering */ +pred lte [e1, e2: elem] { e1=e2 || lt [e1,e2] } + +/** e1 is greater than or equal to e2 in the ordering */ +pred gte [e1, e2: elem] { e1=e2 || gt [e1,e2] } + +/** returns the larger of the two elements in the ordering */ +fun larger [e1, e2: elem]: elem { lt[e1,e2] => e2 else e1 } + +/** returns the smaller of the two elements in the ordering */ +fun smaller [e1, e2: elem]: elem { lt[e1,e2] => e1 else e2 } + +/** + * returns the largest element in es + * or the empty set if es is empty + */ +fun max [es: set elem]: lone elem { es - es.^(~(Ord.Next)) } + +/** + * returns the smallest element in es + * or the empty set if es is empty + */ +fun min [es: set elem]: lone elem { es - es.^(Ord.Next) } + +assert correct { + let mynext = Ord.Next | + let myprev = ~mynext | { + ( all b:elem | (lone b.next) && (lone b.prev) && (b !in b.^mynext) ) + ( (no first.prev) && (no last.next) ) + ( all b:elem | (b!=first && b!=last) => (one b.prev && one b.next) ) + ( !one elem => (one first && one last && first!=last && one first.next && one last.prev) ) + ( one elem => (first=elem && last=elem && no myprev && no mynext) ) + ( myprev=~mynext ) + ( elem = first.*mynext ) + (all disj a,b:elem | a in b.^mynext or a in b.^myprev) + (no disj a,b:elem | a in b.^mynext and a in b.^myprev) + (all disj a,b,c:elem | (b in a.^mynext and c in b.^mynext) =>(c in a.^mynext)) + (all disj a,b,c:elem | (b in a.^myprev and c in b.^myprev) =>(c in a.^myprev)) + } +} +run {} for exactly 0 elem expect 0 +run {} for exactly 1 elem expect 1 +run {} for exactly 2 elem expect 1 +run {} for exactly 3 elem expect 1 +run {} for exactly 4 elem expect 1 +check correct for exactly 0 elem +check correct for exactly 1 elem +check correct for exactly 2 elem +check correct for exactly 3 elem +check correct for exactly 4 elem +check correct for exactly 5 elem diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/util/relation.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/relation.als new file mode 100644 index 00000000..d648a77c --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/relation.als @@ -0,0 +1,101 @@ +module util/relation + +/* + * Utilities for some common operations and constraints + * on binary relations. The keyword 'univ' represents the + * top-level type, which all other types implicitly extend. + * Therefore, all the functions and predicates in this model + * may be applied to binary relations of any type. + * + * author: Greg Dennis + */ + +/** returns the domain of a binary relation */ +fun dom [r: univ->univ] : set (r.univ) { r.univ } + +/** returns the range of a binary relation */ +fun ran [r: univ->univ] : set (univ.r) { univ.r } + +/** r is total over the domain s */ +pred total [r: univ->univ, s: set univ] { + all x: s | some x.r +} + +/** r is a partial function over the domain s */ +pred functional [r: univ->univ, s: set univ] { + all x: s | lone x.r +} + +/** r is a total function over the domain s */ +pred function [r: univ->univ, s: set univ] { + all x: s | one x.r +} + +/** r is surjective over the codomain s */ +pred surjective [r: univ->univ, s: set univ] { + all x: s | some r.x +} + +/** r is injective */ +pred injective [r: univ->univ, s: set univ] { + all x: s | lone r.x +} + +/** r is bijective over the codomain s */ +pred bijective[r: univ->univ, s: set univ] { + all x: s | one r.x +} + +/** r is a bijection over the domain d and the codomain c */ +pred bijection[r: univ->univ, d, c: set univ] { + function[r, d] && bijective[r, c] +} + +/** r is reflexive over the set s */ +pred reflexive [r: univ -> univ, s: set univ] {s<:iden in r} + +/** r is irreflexive */ +pred irreflexive [r: univ -> univ] {no iden & r} + +/** r is symmetric */ +pred symmetric [r: univ -> univ] {~r in r} + +/** r is anti-symmetric */ +pred antisymmetric [r: univ -> univ] {~r & r in iden} + +/** r is transitive */ +pred transitive [r: univ -> univ] {r.r in r} + +/** r is acyclic over the set s */ +pred acyclic[r: univ->univ, s: set univ] { + all x: s | x !in x.^r +} + +/** r is complete over the set s */ +pred complete[r: univ->univ, s: univ] { + all x,y:s | (x!=y => x->y in (r + ~r)) +} + +/** r is a preorder (or a quasi-order) over the set s */ +pred preorder [r: univ -> univ, s: set univ] { + reflexive[r, s] + transitive[r] +} + +/** r is an equivalence relation over the set s */ +pred equivalence [r: univ->univ, s: set univ] { + preorder[r, s] + symmetric[r] +} + +/** r is a partial order over the set s */ +pred partialOrder [r: univ -> univ, s: set univ] { + preorder[r, s] + antisymmetric[r] +} + +/** r is a total order over the set s */ +pred totalOrder [r: univ -> univ, s: set univ] { + partialOrder[r, s] + complete[r, s] +} diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/util/seqrel.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/seqrel.als new file mode 100644 index 00000000..1fe3802d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/seqrel.als @@ -0,0 +1,108 @@ +module util/seqrel[elem] + +/* + * A sequence utility for modeling sequences as just a + * relation as opposed to reifying them into sequence + * atoms like the util/sequence module does. + * + * @author Greg Dennis + */ + +open util/integer +open util/ordering[SeqIdx] as ord + +sig SeqIdx {} + +/** sequence covers a prefix of SeqIdx */ +pred isSeq[s: SeqIdx -> elem] { + s in SeqIdx -> lone elem + s.inds - ord/next[s.inds] in ord/first +} + +/** returns all the elements in this sequence */ +fun elems [s: SeqIdx -> elem]: set elem { SeqIdx.s } + +/** returns the first element in the sequence */ +fun first [s: SeqIdx -> elem]: lone elem { s[ord/first] } + +/** returns the last element in the sequence */ +fun last [s: SeqIdx -> elem]: lone elem { s[lastIdx[s]] } + +/** returns the cdr of the sequence */ +fun rest [s: SeqIdx -> elem] : SeqIdx -> elem { + (ord/next).s +} + +/** returns all but the last element of the sequence */ +fun butlast [s: SeqIdx -> elem] : SeqIdx -> elem { + (SeqIdx - lastIdx[s]) <: s +} + +/** true if the sequence is empty */ +pred isEmpty [s: SeqIdx -> elem] { no s } + +/** true if this sequence has duplicates */ +pred hasDups [s: SeqIdx -> elem] { # elems[s] < # inds[s] } + +/** returns all the indices occupied by this sequence */ +fun inds [s: SeqIdx -> elem]: set SeqIdx { s.elem } + +/** returns last index occupied by this sequence */ +fun lastIdx [s: SeqIdx -> elem]: lone SeqIdx { ord/max[inds[s]] } + +/** + * returns the index after the last index + * if this sequence is empty, returns the first index, + * if this sequence is full, returns empty set + */ +fun afterLastIdx [s: SeqIdx -> elem] : lone SeqIdx { + ord/min[SeqIdx - inds[s]] +} + +/** returns first index at which given element appears or the empty set if it doesn't */ +fun idxOf [s: SeqIdx -> elem, e: elem] : lone SeqIdx { ord/min[indsOf[s, e]] } + +/** returns last index at which given element appears or the empty set if it doesn't */ +fun lastIdxOf [s: SeqIdx -> elem, e: elem] : lone SeqIdx { ord/max[indsOf[s, e]] } + +/** returns set of indices at which given element appears or the empty set if it doesn't */ +fun indsOf [s: SeqIdx -> elem, e: elem] : set SeqIdx { s.e } + +/** + * return the result of appending e to the end of s + * just returns s if s exhausted SeqIdx + */ +fun add [s: SeqIdx -> elem, e: elem] : SeqIdx -> elem { + setAt[s, afterLastIdx[s], e] +} + +/** returns the result of setting the value at index i in sequence to e */ +fun setAt [s: SeqIdx -> elem, i: SeqIdx, e: elem] : SeqIdx -> elem { + s ++ i -> e +} + +/** returns the result of inserting value e at index i */ +fun insert [s: SeqIdx -> elem, i: SeqIdx, e: elem] : SeqIdx -> elem { + (ord/prevs[i] <: s) + (i->e) + (~(ord/next)).((ord/nexts[i] + i) <: s) +} + +/** returns the result of deleting the value at index i */ +fun delete[s: SeqIdx -> elem, i: SeqIdx] : SeqIdx -> elem { + (ord/prevs[i] <: s) + (ord/next).(ord/nexts[i] <: s) +} + +/** appended is the result of appending s2 to s1 */ +fun append [s1, s2: SeqIdx -> elem] : SeqIdx -> elem { + let shift = {i', i: SeqIdx | #ord/prevs[i'] = add[#ord/prevs[i], add[#ord/prevs[lastIdx[s1]], 1]] } | + s1 + shift.s2 +} + +/** returns the subsequence of s between from and to, inclusive */ +fun subseq [s: SeqIdx -> elem, from, to: SeqIdx] : SeqIdx -> elem { + let shift = {i', i: SeqIdx | #ord/prevs[i'] = sub[#ord/prevs[i], #ord/prevs[from]] } | + shift.((SeqIdx - ord/nexts[to]) <: s) +} + +fun firstIdx: SeqIdx { ord/first } + +fun finalIdx: SeqIdx { ord/last } \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/util/sequence.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/sequence.als new file mode 100644 index 00000000..524e3cf7 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/sequence.als @@ -0,0 +1,166 @@ +module util/sequence[elem] + +/* + * Creates sequences (or lists) of elements. The ordered signature SeqIdx + * represents the indexes at which elements can be located, and a sequence + * is modeled as a mapping from indexes to elements. Empty sequences are + * allowed, and a sequence may have a single element appear multiple times. + * Maximum length of a sequence is determined by the scope of SeqIdx. + * + * Sequences always cover an initial segment of SeqIdx. That is, every + * sequence (except the empty sequence) begins at the first SeqIdx and does + * not have gaps in indexes that it covers. In other words, if a sequence has + * its last element at index i, then the sequence has elements at all the + * indexes that precede i. + * + * Oftentimes, a model will need to require that all sequences that could + * exist, do exist. Calling the allExist predicate will ensure that that there is + * a Seq atom for each possible sequences of elements with length less than + * or equal to the scope of SeqIdx. + * + * The functions and predicates at the bottom of this module provide all + * functionality of util/ordering on SeqIdx. + * + * revisions: Greg Dennis + */ + +open util/ordering[SeqIdx] as ord + +sig SeqIdx {} + +sig Seq { + seqElems: SeqIdx -> lone elem +} +{ + // Ensure that elems covers only an initial segment of SeqIdx, + // equal to the length of the signature + all i: SeqIdx - ord/first | some i.seqElems => some ord/prev[i].seqElems +} + +/** no two sequences are identical */ +fact canonicalizeSeqs { + no s1, s2: Seq | s1!=s2 && s1.seqElems=s2.seqElems +} + +/** invoke if you want none of the sequences to have duplicates */ +pred noDuplicates { + all s: Seq | !s.hasDups +} + +/** invoke if you want all sequences within scope to exist */ +pred allExist { + (some s: Seq | s.isEmpty) && + (all s: Seq | SeqIdx !in s.inds => (all e: elem | some s': Seq | s.add[e, s'])) +} + +/** invoke if you want all sequences within scope with no duplicates */ +pred allExistNoDuplicates { + some s: Seq | s.isEmpty + all s: Seq { + !s.hasDups + SeqIdx !in s.inds => (all e: elem - s.elems | some s': Seq | s.add[e, s']) + } +} + +/** returns element at the given index */ +fun at [s: Seq, i: SeqIdx]: lone elem { i.(s.seqElems) } + +/** returns all the elements in this sequence */ +fun elems [s: Seq]: set elem { SeqIdx.(s.seqElems) } + +/** returns the first element in the sequence */ +fun first [s:Seq]: lone elem { s.at[ord/first] } + +/** returns the last element in the sequence */ +fun last [s:Seq]: lone elem { s.at[s.lastIdx] } + +/** + * true if the argument is the "cdr" of this sequence + * false if this sequence is empty + */ +pred rest [s, r: Seq] { + !s.isEmpty + all i: SeqIdx | r.at[i] = s.at[ord/next[i]] +} + +/** true if the sequence is empty */ +pred isEmpty [s:Seq] { no s.elems } + +/** true if this sequence has duplicates */ +pred hasDups [s:Seq] { # elems[s] < # inds[s] } + +/** returns all the indices occupied by this sequence */ +fun inds [s:Seq] : set SeqIdx { elem.~(s.seqElems) } + +/** returns last index occupied by this sequence */ +fun lastIdx [s:Seq] : lone SeqIdx { ord/max[s.inds] } + +/** + * returns the index after the last index + * if this sequence is empty, returns the first index, + * if this sequence is full, returns empty set + */ +fun afterLastIdx [s:Seq] : lone SeqIdx { + ord/min[SeqIdx - s.inds] +} + +/** returns first index at which given element appears or the empty set if it doesn't */ +fun idxOf [s: Seq, e: elem] : lone SeqIdx { ord/min[s.indsOf[e]] } + +/** returns last index at which given element appears or the empty set if it doesn't */ +fun lastIdxOf [s: Seq, e: elem] : lone SeqIdx { ord/max[s.indsOf[e]] } + +/** returns set of indices at which given element appears or the empty set if it doesn't */ +fun indsOf [s: Seq, e: elem] : set SeqIdx { (s.seqElems).e } + +/** true if this starts with prefix */ +pred startsWith [s, prefix: Seq] { + all i: prefix.inds | s.at[i] = prefix.at[i] +} + +/** added is the result of appending e to the end of s */ +pred add [s: Seq, e: elem, added: Seq] { + added.startsWith[s] + added.seqElems[s.afterLastIdx] = e + #added.inds = #s.inds.add[1] +} + +/** setted is the result of setting value at index i to e */ +pred setAt [s: Seq, idx: SeqIdx, e: elem, setted: Seq] { + setted.seqElems = s.seqElems ++ idx->e +} + +/** inserts is the result of inserting value e at index i */ +pred insert [s: Seq, idx: SeqIdx, e: elem, inserted: Seq] { + inserted.at[idx] = e + all i: ord/prevs[idx] | inserted.at[i] = s.at[i] + all i: ord/nexts[idx] | inserted.at[i] = s.at[ord/prev[i]] + #inserted.inds = #s.inds.add[1] +} + +/** copies source into dest starting at destStart */ +pred copy [source, dest: Seq, destStart: SeqIdx] { + all sourceIdx : source.inds | some destIdx: SeqIdx { + ord/gte[destIdx, destStart] + dest.at[destIdx] = source.at[sourceIdx] + #ord/prevs[sourceIdx] = #(ord/prevs[destIdx] - ord/prevs[destStart]) + } +} + +/** appended is the result of appending s2 to s1 */ +pred append [s1, s2, appended: Seq] { + appended.startsWith[s1] + copy[s2, appended, s1.afterLastIdx] + #appended.inds = #s1.inds.add[#s2.inds] +} + +/** sub is the subsequence of s between from and to, inclusive */ +pred subseq [s, sub: Seq, from, to: SeqIdx] { + ord/lte[from, to] + copy[sub, s, from] + #sub.inds = #(to + ord/prevs[to] - ord/prevs[from]) +} + +fun firstIdx: SeqIdx { ord/first } + +fun finalIdx: SeqIdx { ord/last } diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/util/sequniv.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/sequniv.als new file mode 100644 index 00000000..efa8bf42 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/sequniv.als @@ -0,0 +1,137 @@ +module util/sequniv + +open util/integer as ui + +/* + * NOTE: Do not include this module manually. + * Instead, use the "seq" keyword which will automatically + * import this module with the correct additional constraints as needed. + */ + +/* + * A sequence utility for modeling sequences as just a + * relation as opposed to reifying them into sequence + * atoms like the util/sequence module does. + * + * Precondition: each input sequence must range over a prefix + * of seq/Int. + * + * Postcondition: we guarantee the returned sequence + * also ranges over a prefix of seq/Int. + * + * @author Greg Dennis + */ + +/** sequence covers a prefix of seq/Int */ +pred isSeq[s: Int -> univ] { + s in seq/Int -> lone univ + s.inds - ui/next[s.inds] in 0 +} + +/** returns all the elements in this sequence */ +fun elems [s: Int -> univ]: set (Int.s) { seq/Int . s } + +/** + * returns the first element in the sequence + * (Returns the empty set if the sequence is empty) + */ +fun first [s: Int -> univ]: lone (Int.s) { s[0] } + +/** + * returns the last element in the sequence + * (Returns the empty set if the sequence is empty) + */ +fun last [s: Int -> univ]: lone (Int.s) { s[lastIdx[s]] } + +/** + * returns the cdr of the sequence + * (Returns the empty sequence if the sequence has 1 or fewer element) + */ +fun rest [s: Int -> univ] : s { seq/Int <: ((ui/next).s) } + +/** returns all but the last element of the sequence */ +fun butlast [s: Int -> univ] : s { + (seq/Int - lastIdx[s]) <: s +} + +/** true if the sequence is empty */ +pred isEmpty [s: Int -> univ] { no s } + +/** true if this sequence has duplicates */ +pred hasDups [s: Int -> univ] { # elems[s] < # inds[s] } + +/** returns all the indices occupied by this sequence */ +fun inds [s: Int -> univ]: set Int { s.univ } + +/** + * returns last index occupied by this sequence + * (Returns the empty set if the sequence is empty) + */ +fun lastIdx [s: Int -> univ]: lone Int { ui/max[inds[s]] } + +/** + * returns the index after the last index + * if this sequence is empty, returns 0 + * if this sequence is full, returns empty set + */ +fun afterLastIdx [s: Int -> univ] : lone Int { ui/min[seq/Int - inds[s]] } + +/** returns first index at which given element appears or the empty set if it doesn't */ +fun idxOf [s: Int -> univ, e: univ] : lone Int { ui/min[indsOf[s, e]] } + +/** returns last index at which given element appears or the empty set if it doesn't */ +fun lastIdxOf [s: Int -> univ, e: univ] : lone Int { ui/max[indsOf[s, e]] } + +/** returns set of indices at which given element appears or the empty set if it doesn't */ +fun indsOf [s: Int -> univ, e: univ] : set Int { s.e } + +/** + * return the result of appending e to the end of s + * (returns s if s exhausted seq/Int) + */ +fun add [s: Int -> univ, e: univ] : s + (seq/Int->e) { + setAt[s, afterLastIdx[s], e] +} + +/** + * returns the result of setting the value at index i in sequence to e + * Precondition: 0 <= i < #s + */ +fun setAt [s: Int -> univ, i: Int, e: univ] : s + (seq/Int->e) { + s ++ i -> e +} + +/** + * returns the result of inserting value e at index i + * (if sequence was full, the original last element will be removed first) + * Precondition: 0 <= i <= #s + */ +fun insert [s: Int -> univ, i: Int, e: univ] : s + (seq/Int->e) { + seq/Int <: ((ui/prevs[i] <: s) + (i->e) + ui/prev.((ui/nexts[i] + i) <: s)) +} + +/** + * returns the result of deleting the value at index i + * Precondition: 0 <= i < #s + */ +fun delete[s: Int -> univ, i: Int] : s { + (ui/prevs[i] <: s) + (ui/next).(ui/nexts[i] <: s) +} + +/** + * appended is the result of appending s2 to s1 + * (If the resulting sequence is too long, it will be truncated) + */ +fun append [s1, s2: Int -> univ] : s1+s2 { + let shift = {i', i: seq/Int | int[i'] = ui/add[int[i], ui/add[int[lastIdx[s1]], 1]] } | + no s1 => s2 else (s1 + shift.s2) +} + +/** + * returns the subsequence of s between from and to, inclusive + * Precondition: 0 <= from <= to < #s + */ +fun subseq [s: Int -> univ, from, to: Int] : s { + let shift = {i', i: seq/Int | int[i'] = ui/sub[int[i], int[from]] } | + shift.((seq/Int - ui/nexts[to]) <: s) +} diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/util/ternary.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/ternary.als new file mode 100644 index 00000000..6dbc0881 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/ternary.als @@ -0,0 +1,50 @@ +module util/ternary + +/* + * Utilities for some common operations and constraints + * on ternary relations. The keyword 'univ' represents the + * top-level type, which all other types implicitly extend. + * Therefore, all the functions and predicates in this model + * may be applied to ternary relations of any type. + * + * author: Greg Dennis + */ + +/** returns the domain of a ternary relation */ +fun dom [r: univ->univ->univ] : set ((r.univ).univ) { (r.univ).univ } + +/** returns the range of a ternary relation */ +fun ran [r: univ->univ->univ] : set (univ.(univ.r)) { univ.(univ.r) } + +/** returns the "middle range" of a ternary relation */ +fun mid [r: univ->univ->univ] : set (univ.(r.univ)) { univ.(r.univ) } + +/** returns the first two columns of a ternary relation */ +fun select12 [r: univ->univ->univ] : r.univ { + r.univ +} + +/** returns the first and last columns of a ternary relation */ +fun select13 [r: univ->univ->univ] : ((r.univ).univ) -> (univ.(univ.r)) { + {x: (r.univ).univ, z: univ.(univ.r) | some (x.r).z} +} + +/** returns the last two columns of a ternary relation */ +fun select23 [r: univ->univ->univ] : univ.r { + univ.r +} + +/** flips the first two columns of a ternary relation */ +fun flip12 [r: univ->univ->univ] : (univ.(r.univ))->((r.univ).univ)->(univ.(univ.r)) { + {x: univ.(r.univ), y: (r.univ).univ, z: univ.(univ.r) | y->x->z in r} +} + +/** flips the first and last columns of a ternary relation */ +fun flip13 [r: univ->univ->univ] : (univ.(univ.r))->(univ.(r.univ))->((r.univ).univ) { + {x: univ.(univ.r), y: univ.(r.univ), z: (r.univ).univ | z->y->x in r} +} + +/** flips the last two columns of a ternary relation */ +fun flip23 [r: univ->univ->univ] : ((r.univ).univ)->(univ.(univ.r))->(univ.(r.univ)) { + {x: (r.univ).univ, y: univ.(univ.r), z: univ.(r.univ) | x->z->y in r} +} diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/models/util/time.als b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/time.als new file mode 100644 index 00000000..b6f9d8ca --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/models/util/time.als @@ -0,0 +1,53 @@ +open util/ordering[Time] + +sig Time { } + +let dynamic[x] = x one-> Time + +let dynamicSet[x] = x -> Time + +let then [a, b, t, t'] { + some x:Time | a[t,x] && b[x,t'] +} + +let while = while3 + +let while9 [cond, body, t, t'] { + some x:Time | (cond[t] => body[t,x] else t=x) && while8[cond,body,x,t'] +} + +let while8 [cond, body, t, t'] { + some x:Time | (cond[t] => body[t,x] else t=x) && while7[cond,body,x,t'] +} + +let while7 [cond, body, t, t'] { + some x:Time | (cond[t] => body[t,x] else t=x) && while6[cond,body,x,t'] +} + +let while6 [cond, body, t, t'] { + some x:Time | (cond[t] => body[t,x] else t=x) && while5[cond,body,x,t'] +} + +let while5 [cond, body, t, t'] { + some x:Time | (cond[t] => body[t,x] else t=x) && while4[cond,body,x,t'] +} + +let while4 [cond, body, t, t'] { + some x:Time | (cond[t] => body[t,x] else t=x) && while3[cond,body,x,t'] +} + +let while3 [cond, body, t, t'] { + some x:Time | (cond[t] => body[t,x] else t=x) && while2[cond,body,x,t'] +} + +let while2 [cond, body, t, t'] { + some x:Time | (cond[t] => body[t,x] else t=x) && while1[cond,body,x,t'] +} + +let while1 [cond, body, t, t'] { + some x:Time | (cond[t] => body[t,x] else t=x) && while0[cond,body,x,t'] +} + +let while0 [cond, body, t, t'] { + !cond[t] && t=t' +} diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/org/sat4j/messages.properties b/Source/eu.modelwriter.alloyanalyzer/bin/org/sat4j/messages.properties new file mode 100644 index 00000000..2b3f0f00 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/org/sat4j/messages.properties @@ -0,0 +1,8 @@ +Lanceur.wrong.framework=Wrong framework: try minisat or ubcsat +MoreThanSAT.0=Satisfiable \! +MoreThanSAT.1=BackBone: +MoreThanSAT.2=Counting solutions... +MoreThanSAT.3=Number of solutions: +MoreThanSAT.4=Unsatisfiable\! +MoreThanSAT.5=Unsatisfiable (trivial)\! +MoreThanSAT.6=Timeout, sorry\! diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/sat4j.version b/Source/eu.modelwriter.alloyanalyzer/bin/sat4j.version new file mode 100644 index 00000000..a27f8f26 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/sat4j.version @@ -0,0 +1 @@ +2.3.2.v20120709 diff --git a/Source/eu.modelwriter.alloyanalyzer/bin/target/META-INF/MANIFEST.MF b/Source/eu.modelwriter.alloyanalyzer/bin/target/META-INF/MANIFEST.MF new file mode 100644 index 00000000..f14a9926 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/bin/target/META-INF/MANIFEST.MF @@ -0,0 +1,31 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %bundleName +Bundle-SymbolicName: org.sat4j.core +Bundle-Version: 2.3.2.v20120709 +Export-Package: org.sat4j;version="2.3.2.v20120709", + org.sat4j.core;version="2.3.2.v20120709", + org.sat4j.minisat;version="2.3.2.v20120709", + org.sat4j.minisat.constraints;version="2.3.2.v20120709", + org.sat4j.minisat.constraints.card;version="2.3.2.v20120709", + org.sat4j.minisat.constraints.cnf;version="2.3.2.v20120709", + org.sat4j.minisat.core;version="2.3.2.v20120709", + org.sat4j.minisat.learning;version="2.3.2.v20120709", + org.sat4j.minisat.orders;version="2.3.2.v20120709", + org.sat4j.minisat.restarts;version="2.3.2.v20120709", + org.sat4j.opt;version="2.3.2.v20120709", + org.sat4j.reader;version="2.3.2.v20120709", + org.sat4j.specs;version="2.3.2.v20120709", + org.sat4j.tools;version="2.3.2.v20120709", + org.sat4j.tools.xplain;version="2.3.2.v20120709" +Bundle-Vendor: %providerName +Bundle-Localization: plugin +Built-By: Daniel Le Berre +Main-Class: org.sat4j.BasicLauncher +Specification-Title: SAT4J +Specification-Version: NA +Specification-Vendor: Daniel Le Berre +Implementation-Title: SAT4J +Implementation-Version: 2.3.2.v20120709 +Implementation-Vendor: CRIL CNRS UMR 8188 - Universite d'Artois +Bundle-RequiredExecutionEnvironment: J2SE-1.5 diff --git a/Source/eu.modelwriter.alloyanalyzer/build.properties b/Source/eu.modelwriter.alloyanalyzer/build.properties new file mode 100644 index 00000000..20001ebb --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/build.properties @@ -0,0 +1,9 @@ +source.alloyanalyzer.jar = src/ +bin.includes = META-INF/,\ + lib/alloy4.2.jar,\ + alloyanalyzer.jar,\ + bin/,\ + build.properties,\ + .settings/,\ + .project,\ + .classpath diff --git a/Source/eu.modelwriter.alloyanalyzer/lib/alloy4.2.jar b/Source/eu.modelwriter.alloyanalyzer/lib/alloy4.2.jar new file mode 100644 index 00000000..3be21612 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/lib/alloy4.2.jar differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/META-INF/MANIFEST.MF b/Source/eu.modelwriter.alloyanalyzer/src/META-INF/MANIFEST.MF new file mode 100644 index 00000000..c10f81ea --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/META-INF/MANIFEST.MF @@ -0,0 +1,4 @@ +Manifest-Version: 1.0 +Created-By: 1.5.0 (Sun Microsystems Inc.) +Main-Class: edu.mit.csail.sdg.alloy4whole.SimpleGUI + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/README.TXT b/Source/eu.modelwriter.alloyanalyzer/src/README.TXT new file mode 100644 index 00000000..7cd623ea --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/README.TXT @@ -0,0 +1,63 @@ +The Alloy Analyzer + + The Alloy Analyzer is a tool developed by the Software Design + Group (http://sdg.csail.mit.edu/) for analyzing models written in + Alloy, a simple structural modeling language based on first-order + logic. The tool can generate instances of invariants, simulate + the execution of operations (even those defined implicitly), and + check user-specified properties of a model. Alloy and its + analyzer have been used primarily to explore abstract software + designs. Its use in analyzing code for conformance to a + specification and as an automatic test case generator are being + investigated in ongoing research projects. + + See the web page for a description of what's new in Alloy: + + http://alloy.mit.edu/ + + +Detailed Instructions: + + 1. Java 5 or later + + Java runtimes are available at no economic charge from Sun and + IBM and others. One may have come pre-installed in your OS. + Alloy does not currently work with gcj because of its limited + library support. + + 2. Running Alloy on Mac OS X + + Just double-click on the dmg file, + then drag the Alloy application into your application directory. + + 3. Running Alloy on other platforms + + Just double-click on the jar file, or type: + + java -jar alloy4.jar + +The source code for the Alloy Analyzer is available +under the MIT license. + +The Alloy Analyzer utilizes several third-party packages whose code may +be distributed under a different license (see the various LICENSE files +in the distribution for details). We are extremely grateful to the authors +of these packages for making their source code freely available. + + * Kodkod + http://web.mit.edu/~emina/www/kodkod.html + + * CUP Parser Generator for Java + http://www2.cs.tum.edu/projects/cup/ + + * JFlex scanner generator for Java + http://jflex.de/ + + * The zChaff solver + http://www.princeton.edu/~chaff/zchaff.html + + * The MiniSat solver + http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/ + + * The SAT4J solver + http://www.sat4j.org/ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/README.md b/Source/eu.modelwriter.alloyanalyzer/src/README.md new file mode 100644 index 00000000..9942d4bc --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/README.md @@ -0,0 +1,45 @@ +Alloy Analyzer (source code mirror) +=================================== + +Summary +------- +This is a copy of the source code for [MIT's Alloy Analyzer model checking tool](http://alloy.mit.edu/alloy/). +It also includes an Ant build.xml script, which is not part of the original MIT source code. +This copy was created to facilitate modification to the core Alloy tool (the parts which fall +under the `edu.mit` package structure). + +It was created as follows (not necessarily in this order): + +1. Downloaded the JAR file located at: http://alloy.mit.edu/alloy/downloads/alloy4.2.jar +2. Extracted the JAR file. +3. Added this `README.md` file and a `build.xml` file. +3. Deleted core `.class` files (using the _clean_ target in `build.xml`) + +Building +-------- +The Ant build.xml script contains the following targets: + +- _build_: Compiles the `.java` files under the `edu` directory. + + Other directories are not touched; it is assumed that these contain libraries + which have been pre-compiled. + + The auto-generated parser and lexer `.java` files (located in the `edu/mit/csail/sdg/alloy4compiler/parser` directory) + are neither deleted nor generated by the Ant script. The directory already contains shell scripts + to re-generate them using JFlex and CUP. +- _dist_: Creates an executable JAR file in the `dist` directory. This JAR file looks essentially like the official + Alloy JAR file released by MIT. +- _all_: Runs _dist_. +- _clean_: Deletes the `dist` directory and all class files under the `edu` directory. + +Notes +----- + +- As per the manifest, the main class is `edu.mit.csail.sdg.alloy4whole.SimpleGUI`. +- The version number and build date which the tool displays are not accurate. + These are set in the `edu.mit.csail.sdg.alloy4.Version` class, and are supposed to be + updated by the build script when building a release. + This project was not intended to create official releases, so it was left as-is. +- There is a class `edu.mit.csail.sdg.alloy4.MailBug` which includes logic to email + crash reports to MIT. You should change this class if you are modifying the source code + and creating your own release. diff --git a/Source/eu.modelwriter.alloyanalyzer/src/amd64-linux/berkmin b/Source/eu.modelwriter.alloyanalyzer/src/amd64-linux/berkmin new file mode 100644 index 00000000..f0aa2cee Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/amd64-linux/berkmin differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/amd64-linux/libminisat.so b/Source/eu.modelwriter.alloyanalyzer/src/amd64-linux/libminisat.so new file mode 100644 index 00000000..d286aa4b Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/amd64-linux/libminisat.so differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/amd64-linux/libminisatprover.so b/Source/eu.modelwriter.alloyanalyzer/src/amd64-linux/libminisatprover.so new file mode 100644 index 00000000..392474ac Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/amd64-linux/libminisatprover.so differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/amd64-linux/libzchaff.so b/Source/eu.modelwriter.alloyanalyzer/src/amd64-linux/libzchaff.so new file mode 100644 index 00000000..dc9c229d Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/amd64-linux/libzchaff.so differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/A4Reporter.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/A4Reporter.java new file mode 100644 index 00000000..85f61920 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/A4Reporter.java @@ -0,0 +1,186 @@ +/* + * Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +/** + * This class receives diagnostic, progress, and warning messages from Alloy4. (This default + * implementation ignores all calls; you should subclass it to do the appropriate screen output) + */ + +public class A4Reporter { + + /** If nonnull, then we will forward requests to this reporter. */ + private final A4Reporter parent; + + /** This is a pre-constructed instance that simply ignores all calls. */ + public static final A4Reporter NOP = new A4Reporter(); + + /** Constructs a default A4Reporter object that does nothing. */ + public A4Reporter() { + parent = null; + } + + /** Constructs an A4Reporter that forwards each method to the given A4Reporter. */ + public A4Reporter(A4Reporter reporter) { + parent = reporter; + } + + /** + * This method is called at various points to report the current progress; it is intended as a + * debugging aid for the developers; the messages are generally not useful for end users. + */ + public void debug(String msg) { + if (parent != null) + parent.debug(msg); + } + + /** This method is called by the parser to report parser events. */ + public void parse(String msg) { + if (parent != null) + parent.parse(msg); + } + + /** + * This method is called by the typechecker to report the type for each + * field/function/predicate/assertion, etc. + */ + public void typecheck(String msg) { + if (parent != null) + parent.typecheck(msg); + } + + /** This method is called by the typechecker to report a nonfatal type error. */ + public void warning(ErrorWarning msg) { + if (parent != null) + parent.warning(msg); + } + + /** This method is called by the ScopeComputer to report the scope chosen for each sig. */ + public void scope(String msg) { + if (parent != null) + parent.scope(msg); + } + + /** + * This method is called by the BoundsComputer to report the bounds chosen for each sig and each + * field. + */ + public void bound(String msg) { + if (parent != null) + parent.bound(msg); + } + + /** + * This method is called by the translator just before it begins generating CNF. + * + * @param solver - the solver chosen by the user (eg. SAT4J, MiniSat...) + * @param bitwidth - the integer bitwidth chosen by the user + * @param maxseq - the scope on seq/Int chosen by the user + * @param skolemDepth - the skolem function depth chosen by the user (0, 1, 2...) + * @param symmetry - the amount of symmetry breaking chosen by the user (0...) + */ + public void translate(String solver, int bitwidth, int maxseq, int skolemDepth, int symmetry) { + if (parent != null) + parent.translate(solver, bitwidth, maxseq, skolemDepth, symmetry); + } + + /** + * This method is called by the translator just after it generated the CNF. + * + * @param primaryVars - the total number of primary variables + * @param totalVars - the total number of variables including the number of primary variables + * @param clauses - the total number of clauses + */ + public void solve(int primaryVars, int totalVars, int clauses) { + if (parent != null) + parent.solve(primaryVars, totalVars, clauses); + } + + /** + * If solver==KK or solver==CNF, this method is called by the translator after it constructed the + * Kodkod or CNF file. + * + * @param filename - the Kodkod or CNF file generated by the translator + */ + public void resultCNF(String filename) { + if (parent != null) + parent.resultCNF(filename); + } + + /** + * If solver!=KK and solver!=CNF, this method is called by the translator if the formula is + * satisfiable. + * + * @param command - this is the original Command used to generate this solution + * @param solvingTime - this is the number of milliseconds the solver took to obtain this result + * @param solution - the satisfying A4Solution object + */ + public void resultSAT(Object command, long solvingTime, Object solution) { + if (parent != null) + parent.resultSAT(command, solvingTime, solution); + } + + /** + * If solver!=KK and solver!=CNF, this method is called by the translator before starting the + * unsat core minimization. + * + * @param command - this is the original Command used to generate this solution + * @param before - the size of the unsat core before calling minimization + */ + public void minimizing(Object command, int before) { + if (parent != null) + parent.minimizing(command, before); + } + + /** + * If solver!=KK and solver!=CNF, this method is called by the translator after performing the + * unsat core minimization. + * + * @param command - this is the original Command used to generate this solution + * @param before - the size of the unsat core before calling minimization + * @param after - the size of the unsat core after calling minimization + */ + public void minimized(Object command, int before, int after) { + if (parent != null) + parent.minimized(command, before, after); + } + + /** + * If solver!=KK and solver!=CNF, this method is called by the translator if the formula is + * unsatisfiable. + * + * @param command - this is the original Command used to generate this solution + * @param solvingTime - this is the number of milliseconds the solver took to obtain this result + * @param solution - the unsatisfying A4Solution object + */ + public void resultUNSAT(Object command, long solvingTime, Object solution) { + if (parent != null) + parent.resultUNSAT(command, solvingTime, solution); + } + + /** + * This method is called by the A4SolutionWriter when it is writing a particular sig, field, or + * skolem. + */ + public void write(Object expr) { + if (parent != null) + parent.write(expr); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ByteBuffer.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ByteBuffer.java new file mode 100644 index 00000000..265f9e19 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ByteBuffer.java @@ -0,0 +1,130 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.io.UnsupportedEncodingException; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.zip.Deflater; + +/** Mutable; implements a growable array of bytes. + * + *

This class is more efficient than Java's ByteArrayOutputStream when writing large amount of data, + * because ByteArrayOutputStream will resize and copy entire existing contents every time the array needs to grow, + * whereas this class maintains a linked list of arrays (so when capacity is expanded we don't need to copy old data) + */ + +public final class ByteBuffer { + + /** The size per chunk. */ + private static final int SIZE = 65536; + + /** The list of chunks allocated so far; always has at least one chunk; every chunk is always exactly of size SIZE. */ + private final LinkedList list = new LinkedList(); + + /** The number of bytes stored in the latest chunk; every chunk before that is always fully filled. */ + private int n = 0; + + /** Construct an empty byte buffer. */ + public ByteBuffer() { list.add(new byte[SIZE]); } + + /** Write the given byte into this byte buffer. */ + private ByteBuffer w(int b) { + if (n==SIZE) { list.add(new byte[SIZE]); n=0; } + byte[] array = list.getLast(); + array[n] = (byte)b; + n++; + return this; + } + + /** Write the given array of bytes into this byte buffer. */ + private ByteBuffer write(byte[] b, int offset, int len) { + if (b==null || len<=0) return this; else if (n==SIZE) { list.add(new byte[SIZE]); n=0; } + while(true) { // loop invariant: len>0 and SIZE>n + byte[] array = list.getLast(); + if (len <= (SIZE-n)) { System.arraycopy(b, offset, array, n, len); n += len; return this; } + System.arraycopy(b, offset, array, n, SIZE-n); + offset += (SIZE-n); + len -= (SIZE-n); + n = 0; + list.add(new byte[SIZE]); + } + } + + /** Write the given String into this byte buffer (by converting the String into its UTF-8 representation) */ + public ByteBuffer write(String string) { + if (string.length() == 0) return this; + byte[] b; + try { b = string.getBytes("UTF-8"); } catch(UnsupportedEncodingException ex) { return this; } // exception not possible + return write(b, 0, b.length); + } + + /** Write the given number into this byte buffer, followed by a space. */ + public ByteBuffer writes(long x) { + return write(Long.toString(x)).w(' '); + } + + /** Write the given number into this byte buffer (truncated to the range -32767..+32767), followed by a space. */ + public strictfp ByteBuffer writes(double x) { + // These extreme values shouldn't happen, but we want to protect against them + if (Double.isNaN(x)) return write("0 "); else if (x>32767) return write("32767 "); else if (x<-32767) return write("-32767 "); + long num = (long)(x * 1000000); + if (num>=32767000000L) return write("32767 "); else if (num<=(-32767000000L)) return write("-32767 "); + // Now, regular doubles... let's allow up to 6 digits after the decimal point + if (num<0) { w('-'); num = -num; } + String str = Long.toString(num); + int len = str.length(); + if (len<=6) { + w('.'); + while(len<6) { w('0'); len++; } + return write(str).w(' '); + } + return write(str.substring(0, str.length()-6)).w('.').write(str.substring(str.length()-6)).w(' '); + } + + /** Write the entire content into the given file using Flate compression (see RFC1951) then return the number of bytes written. */ + public long dumpFlate(RandomAccessFile os) throws IOException { + Deflater zip = new Deflater(Deflater.BEST_COMPRESSION); + byte[] output = new byte[8192]; + Iterator it = list.iterator(); // when null, that means we have told the Deflater that no more input would be coming + long ans = 0; // the number of bytes written out so far + while(true) { + if (it!=null && zip.needsInput() && it.hasNext()) { + byte[] in = it.next(); + if (in == list.getLast()) { zip.setInput(in, 0, n); it=null; zip.finish(); } else { zip.setInput(in, 0, SIZE); } + } + if (it==null && zip.finished()) break; + int count = zip.deflate(output); + if (count > 0) { + ans = ans + count; + if (ans < 0) throw new IOException("Data too large to be written to the output file."); + os.write(output, 0, count); + } + } + return ans; + } + + /** Write the entire content into the given file as-is, then return the number of bytes written. */ + public long dump(RandomAccessFile os) throws IOException { + if (list.size() >= (Long.MAX_VALUE / SIZE)) throw new IOException("Data too large to be written to the output file."); + byte[] last = list.getLast(); + for(byte[] x: list) if (x!=last) os.write(x); + if (n>0) os.write(last, 0, n); + return ((long)(list.size()-1)) * SIZE + n; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Computer.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Computer.java new file mode 100644 index 00000000..3e490f45 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Computer.java @@ -0,0 +1,26 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +/** This defines a compute() method that takes an Object input and produces a String output. */ + +public interface Computer { + + /** This method takes an Object input and produces a String output. + * @throws Exception if an error occurred during the computation. + */ + public String compute (Object input) throws Exception; +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ConstList.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ConstList.java new file mode 100644 index 00000000..ffdfcae7 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ConstList.java @@ -0,0 +1,154 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.io.Serializable; +import java.util.AbstractList; +import java.util.Collection; +import java.util.List; +import java.util.ArrayList; +import java.util.RandomAccess; + +/** Immutable; implements a list based on equals(); null values are allowed. + * + * @param - the type of element + */ + +public final class ConstList extends AbstractList implements Serializable, RandomAccess { + + /** Mutable; this implements a modifiable list that can be used to construct a ConstList; null values are allowed. + * + * @param - the type of element + */ + public static final class TempList { + + /** The underlying list. */ + private final ArrayList list; + + /** Nonnull iff this list is no longer modifiable. */ + private ConstList clist; + + /** Construct an empty TempList. */ + public TempList() { list = new ArrayList(); } + + /** Construct an empty TempList with initial capacity of n (if n<=0, the list will be given a default capacity of 0) */ + public TempList(int n) { list = new ArrayList(n>=0 ? n : 0); } + + /** Construct a new TempList whose initial content is n references to the given elem (if n<=0, the created list is empty) */ + public TempList(int n, T elem) { list = new ArrayList(n>0 ? n : 0); while(n>0) { list.add(elem); n--; } } + + /** Construct a new TempList whose initial content is equal to the given collection. */ + public TempList(Collection all) { list = new ArrayList(all); } + + /** Construct a new TempList whose initial content is equal to the given array. */ + public TempList(T... all) { list = new ArrayList(all.length); for(int i=0; i clear() { chk(); list.clear(); return this; } + + /** Appends the given element to the list, then return itself. */ + public TempList add(T elem) { chk(); list.add(elem); return this; } + + /** Appends the elements in the given collection to the list, then return itself. */ + public TempList addAll(Iterable all) { + chk(); + if (all instanceof Collection) list.addAll((Collection)all); else if (all!=null) { for(T x: all) list.add(x); } + return this; + } + + /** Changes the i-th element to be the given element, then return itself. */ + public TempList set(int index, T elem) { chk(); list.set(index, elem); return this; } + + /** Makes this TempList unmodifiable, then construct a ConstList backed by this TempList. */ + @SuppressWarnings("unchecked") + public ConstList makeConst() { if (clist==null) clist=(list.isEmpty() ? emptylist : new ConstList(list)); return clist; } + } + + /** This ensures this class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** The underlying unmodifiable list. */ + private final List list; + + /** This caches an unmodifiable empty list. */ + @SuppressWarnings("unchecked") + private static final ConstList emptylist = new ConstList(new ArrayList(0)); + + /** Construct a ConstList with the given list as its backing store. */ + private ConstList(List list) { + this.list = list; + } + + /** Return an unmodifiable empty list. */ + @SuppressWarnings("unchecked") + public static ConstList make() { + return (ConstList) emptylist; + } + + /** Return an unmodifiable list consisting of "n" references to "elem". + * (If n<=0, we'll return an unmodifiable empty list) + */ + public static ConstList make(int n, T elem) { + if (n <= 0) return make(); + ArrayList ans = new ArrayList(n); + while(n > 0) { ans.add(elem); n--; } + return new ConstList(ans); + } + + /** Return an unmodifiable list with the same elements as the given collection. + * (If collection==null, we'll return an unmodifiable empty list) + */ + public static ConstList make(Iterable collection) { + if (collection == null) return make(); + if (collection instanceof ConstList) return (ConstList) collection; + if (collection instanceof Collection) { + Collection col = (Collection)collection; + if (col.isEmpty()) return make(); else return new ConstList(new ArrayList(col)); + } + ArrayList ans = null; + for(T x: collection) { + if (ans == null) ans = new ArrayList(); + ans.add(x); + } + if (ans==null) return make(); else return new ConstList(ans); + } + + /** Returns the i-th element + * @throws ArrayIndexOutOfBoundsException if the given index doesn't exist + */ + @Override public T get(int index) { return list.get(index); } + + /** Returns the number of elements in this list. */ + @Override public int size() { return list.size(); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ConstMap.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ConstMap.java new file mode 100644 index 00000000..601922da --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ConstMap.java @@ -0,0 +1,83 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.util.Collection; +import java.util.Collections; +import java.util.Set; +import java.util.AbstractMap; +import java.util.Map; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.io.Serializable; + +/** Immutable; implements a map based on hashCode() and equals(); null key and values are allowed. + * + * @param - the type of key + * @param - the type of value + */ + +public final class ConstMap extends AbstractMap implements Serializable { + + /** This ensures this class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** The underlying Collections.unmodifiableMap map. */ + private final Map map; + + /** This caches a read-only empty map. */ + private static final ConstMap emptymap = new ConstMap(new HashMap(0)); + + /** Constructs an unmodifiable map with the given map as the backing store. */ + private ConstMap(Map map) { + this.map = Collections.unmodifiableMap(map); + } + + /** Returns an unmodifiable empty map. */ + @SuppressWarnings("unchecked") + public static ConstMap make() { + return (ConstMap) emptymap; + } + + /** Returns an unmodifiable map with the same entries and traversal order as the given map. + * (If map==null, we'll return an unmodifiable empty map) + */ + public static ConstMap make(Map map) { + if (map instanceof ConstMap) return (ConstMap)map; + if (map == null || map.isEmpty()) return make(); else return new ConstMap(new LinkedHashMap(map)); + } + + /** Returns an unmodifiable view of the mappings in this map. */ + @Override public Set> entrySet() { return map.entrySet(); } + + /** Returns an unmodifiable view of the keys in this map. */ + @Override public Set keySet() { return map.keySet(); } // overridden for performance + + /** Returns an unmodifiable view of the values in this map. */ + @Override public Collection values() { return map.values(); } // overridden for performance + + /** Returns the number of (key, value) mapping in this map. */ + @Override public int size() { return map.size(); } // overridden for performance + + /** Returns true if exists at least one (k, v) mapping where (k==null ? key==null : k.equals(key)) */ + @Override public boolean containsKey(Object key) { return map.containsKey(key); } // overridden for performance + + /** Returns true if exists at least one (k, v) mapping where (v==null ? value==null : v.equals(value)) */ + @Override public boolean containsValue(Object value) { return map.containsValue(value); } // overridden for performance + + /** Returns the value associated with the key (or null if not found); null is also returned if the given key maps to null. */ + @Override public V get(Object key) { return map.get(key); } // overridden for performance +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ConstSet.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ConstSet.java new file mode 100644 index 00000000..f7d79121 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ConstSet.java @@ -0,0 +1,74 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.util.AbstractSet; +import java.util.Collections; +import java.util.Set; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Iterator; +import java.io.Serializable; + +/** Immutable; implements a set based on hashCode() and equals(); null value is allowed. + * + * @param - the type of element + */ + +public final class ConstSet extends AbstractSet implements Serializable { + + /** This ensures this class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** The underlying Collections.unmodifiableSet set. */ + private final Set set; + + /** This caches a readonly empty Set. */ + private static final ConstSet emptyset = new ConstSet(new HashSet(0)); + + /** Constructs an unmodifiable map with the given set as the backing store. */ + private ConstSet(Set set) { + this.set = Collections.unmodifiableSet(set); + } + + /** Returns an unmodifiable empty set. */ + @SuppressWarnings("unchecked") + public static ConstSet make() { + return (ConstSet) emptyset; + } + + /** Returns an unmodifiable set with the same elements and traversal order as the given set. + * (If set==null, we'll return an unmodifiable empty set) + */ + public static ConstSet make(Iterable collection) { + if (collection instanceof ConstSet) return (ConstSet)collection; + LinkedHashSet ans = null; + if (collection != null) for(K element: collection) { + if (ans == null) ans = new LinkedHashSet(); + ans.add(element); + } + if (ans==null) return make(); else return new ConstSet(ans); + } + + /** Returns the number of objects in this set. */ + @Override public int size() { return set.size(); } + + /** Returns a read-only iterator over this set. */ + @Override public Iterator iterator() { return set.iterator(); } + + /** Returns true if the given object is in this set. */ + @Override public boolean contains(Object element) { return set.contains(element); } // overridden for performance +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/DirectedGraph.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/DirectedGraph.java new file mode 100644 index 00000000..319e3278 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/DirectedGraph.java @@ -0,0 +1,80 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.IdentityHashMap; + +/** Mutable; implements a directed graph; null node is allowed. + * + *

Note: it uses n1==n2 for comparing nodes rather than using n1.equals(n2) + * + * @param - the type of node + */ + +public final class DirectedGraph { + + /** This substitutes for null nodes. This allows hasPath() method to use put() to both insert and test membership in one step. */ + private static final Object NULL = new Object(); + + /** This field maps each node X to a list of "neighbor nodes" that X can reach by following directed edges zero or more times. */ + private final Map> nodeToTargets = new IdentityHashMap>(); + + /** Constructs an empty graph. */ + public DirectedGraph () { } + + /** Add a directed edge from start node to end node (if there wasn't such an edge already). */ + public void addEdge (N start, N end) { + if (start == end) return; + Object a = (start==null ? NULL : start); + Object b = (end==null ? NULL : end); + List targets = nodeToTargets.get(a); + if (targets == null) { + targets = new ArrayList(); + targets.add(b); + nodeToTargets.put(a, targets); + } else { + for (int i = targets.size()-1; i >= 0; i--) if (targets.get(i) == b) return; + targets.add(b); + } + } + + /** Returns whether there is a directed path from start node to end node by following directed edges 0 or more times (breath-first). */ + public boolean hasPath (N start, N end) { + if (start == end) return true; + Object a = (start==null ? NULL : start); + Object b = (end==null ? NULL : end); + List todo = new ArrayList(); + Map visited = new IdentityHashMap(); + // The correctness and guaranteed termination relies on following three invariants: + // (1) Every time we add X to "visited", we also simultaneously add X to "todo". + // (2) Every time we add X to "todo", we also simultaneously add X to "visited". + // (3) Nothing is ever removed. + visited.put(a, a); + todo.add(a); + for(int k = 0; k < todo.size(); k++) { // use an integer loop since we will be adding to the "todo" list as we iterate + List targets = nodeToTargets.get(todo.get(k)); + if (targets != null) for (int i = targets.size()-1; i >= 0; i--) { + Object next = targets.get(i); + if (next == b) { addEdge(start, end); return true; } // Cache so that later hasPath(start,end) returns true immediately + if (visited.put(next, next) == null) todo.add(next); + } + } + return false; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Env.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Env.java new file mode 100644 index 00000000..be5e1643 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Env.java @@ -0,0 +1,106 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.util.LinkedList; +import java.util.Map; +import java.util.LinkedHashMap; + +/** Mutable; implements a undoable map based on hashCode() and equals(); null key and values are allowed. + * + *

To be more precise, every key is internally mapped to a list of values. + *
The put(X,Y) method appends Y onto the end of X's list. + *
The get(X) method returns the last element in X's list. + *
The remove(X) method removes the last element in X's list. + * + *

This is very useful for representing lexical scoping: when a local + * variable is introduced with the same name as an existing variable, + * the new variable "hides" the old mapping; and when the new variable falls + * out of scope, the previous mapping is once again "revealed". + * + * @param - the type for Value + */ + +public final class Env { + + /** If a key is bound to one or more values, this stores the first value. + *

+ * For example: if key K is bound to list of values V1,V2,V3...Vn, then map1.get(K) returns V1 + *

+ * Invariant: map2.containsKey(x) implies (map1.containsKey(x) && map2.get(x).size()>0) + */ + private final Map map1 = new LinkedHashMap(); + + /** If a key is bound to more than one value, this stores every value except the first value. + *

+ * For example: if key K is bound to list of values V1,V2,V3...Vn, then map2.get(K) returns the sublist V2..Vn + *

+ * Invariant: map2.containsKey(x) implies (map1.containsKey(x) && map2.get(x).size()>0) + */ + private final Map> map2 = new LinkedHashMap>(); + + /** Constructs an initially empty environment. */ + public Env () { } + + /** Returns true if the key is mapped to one or more values. */ + public boolean has (K key) { return map1.containsKey(key); } + + /** Returns the latest value associated with the key (and returns null if none). + * + *

Since null is also a possible value, if you get null as the answer, + * you need to call has(key) to determine whether the key really has a mapping or not. + */ + public V get (K key) { + LinkedList list = map2.get(key); + return (list != null) ? list.getLast() : map1.get(key); + } + + /** Associates the key with the value (which can be null). */ + public void put (K key, V value) { + LinkedList list = map2.get(key); + if (list != null) { + list.add(value); + } else if (!map1.containsKey(key)) { + map1.put(key, value); + } else { + list = new LinkedList(); + list.add(value); + map2.put(key, list); + } + } + + /** Removes the latest mapping for the key (and if the key had previous mappings, they become visible). + * If there are no mappings for the key, then this method does nothing. + */ + public void remove (K key) { + LinkedList list = map2.get(key); + if (list == null) map1.remove(key); else if (list.size() == 1) map2.remove(key); else list.removeLast(); + } + + /** Removes all mappings. */ + public void clear() { + map1.clear(); + map2.clear(); + } + + /** Make a shallow copy of this environment. */ + public Env dup() { + Env ans = new Env(); + ans.map1.putAll(map1); + for(Map.Entry> e: map2.entrySet()) ans.map2.put(e.getKey(), new LinkedList(e.getValue())); + return ans; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Err.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Err.java new file mode 100644 index 00000000..af8f7c53 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Err.java @@ -0,0 +1,56 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +/** Immutable; this is the abstract parent class of the various possible errors. */ + +public abstract class Err extends Exception { + + /** This ensures this class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** This stores the filename/line/column information (Pos.UNKNOWN if unknown) (never null) */ + public final Pos pos; + + /** The actual error message (never null) */ + public final String msg; + + /** Constructs a new Err object. + * @param pos - the filename/line/row information (can be null if unknown) + * @param msg - the actual error message (can be null) + * @param cause - if nonnull, it will be recorded as the cause of this exception + */ + Err(Pos pos, String msg, Throwable cause) { + super((msg==null ? "" : msg), cause); + this.pos = (pos==null ? Pos.UNKNOWN : pos); + this.msg = (msg==null ? "" : msg); + } + + /** Two Err objects are equal if the type, position, and message are the same. */ + @Override public final boolean equals(Object other) { + if (this==other) return true; else if (other==null || getClass()!=other.getClass()) return false; + Err that = (Err) other; + return pos.equals(that.pos) && msg.equals(that.msg); + } + + /** Returns a hash code consistent with equals() */ + @Override public final int hashCode() { + return msg.hashCode(); + } + + /** Returns this exception type, its error message, and its complete stack trace as a String. */ + public final String dump() { return MailBug.dump(this); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ErrorAPI.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ErrorAPI.java new file mode 100644 index 00000000..01e62c05 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ErrorAPI.java @@ -0,0 +1,48 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +/** Immutable; this represents an API usage error. */ + +public final class ErrorAPI extends Err { + + /** This ensures this class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** Constructs a new API usage error. + * @param msg - the actual error message (can be null) + */ + public ErrorAPI(String msg) { super(null, msg, null); } + + /** Constructs a new API usage error with "cause" as the underlying cause. + * @param msg - the actual error message (can be null) + * @param cause - if nonnull, it is the cause of this exception + */ + public ErrorAPI(String msg, Throwable cause) { super(null, msg, cause); } + + /** Constructs a new API usage error. + * @param pos - the filename/line/row information (can be null if unknown) + * @param msg - the actual error message (can be null) + */ + public ErrorAPI(Pos pos, String msg) { super(pos, msg, null); } + + /** Returns a textual description of the error. */ + @Override public String toString() { + if (pos==Pos.UNKNOWN) return "API usage error:\n"+msg; + if (pos.filename.length()>0) return "API usage error in "+pos.filename+" at line "+pos.y+" column "+pos.x+":\n"+msg; + return "API usage error at line " + pos.y + " column " + pos.x + ":\n" + msg; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ErrorFatal.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ErrorFatal.java new file mode 100644 index 00000000..812b4da3 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ErrorFatal.java @@ -0,0 +1,48 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +/** Immutable; this represents a fatal error. */ + +public final class ErrorFatal extends Err { + + /** This ensures this class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** Constructs a new fatal error. + * @param msg - the actual error message (can be null) + */ + public ErrorFatal(String msg) { super(null, msg, null); } + + /** Constructs a new fatal error with "cause" as the underlying cause. + * @param msg - the actual error message (can be null) + * @param cause - if nonnull, it is the cause of this exception + */ + public ErrorFatal(String msg, Throwable cause) { super(null, msg, cause); } + + /** Constructs a new fatal error. + * @param pos - the filename/line/row information (can be null if unknown) + * @param msg - the actual error message (can be null) + */ + public ErrorFatal(Pos pos, String msg) { super(pos, msg, null); } + + /** Returns a textual description of the error. */ + @Override public String toString() { + if (pos==Pos.UNKNOWN) return "Fatal error:\n"+msg; + if (pos.filename.length()>0) return "Fatal error in "+pos.filename+" at line "+pos.y+" column "+pos.x+":\n"+msg; + return "Fatal error at line " + pos.y + " column " + pos.x + ":\n" + msg; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ErrorSyntax.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ErrorSyntax.java new file mode 100644 index 00000000..11497995 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ErrorSyntax.java @@ -0,0 +1,48 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +/** Immutable; this represents a syntax error that should be reported to the user. */ + +public final class ErrorSyntax extends Err { + + /** This ensures this class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** Constructs a new syntax error. + * @param msg - the actual error message (can be null) + */ + public ErrorSyntax(String msg) { super(null, msg, null); } + + /** Constructs a new syntax error with "cause" as the underlying cause. + * @param msg - the actual error message (can be null) + * @param cause - if nonnull, it is the cause of this exception + */ + public ErrorSyntax(String msg, Throwable cause) { super(null, msg, cause); } + + /** Constructs a new syntax error. + * @param pos - the filename/line/row information (can be null if unknown) + * @param msg - the actual error message (can be null) + */ + public ErrorSyntax(Pos pos, String msg) { super(pos, msg, null); } + + /** Returns a textual description of the error. */ + @Override public String toString() { + if (pos==Pos.UNKNOWN) return "Syntax error:\n"+msg; + if (pos.filename.length()>0) return "Syntax error in "+pos.filename+" at line "+pos.y+" column "+pos.x+":\n"+msg; + return "Syntax error at line " + pos.y + " column " + pos.x + ":\n" + msg; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ErrorType.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ErrorType.java new file mode 100644 index 00000000..518a720d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ErrorType.java @@ -0,0 +1,48 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +/** Immutable; this represents a type error that should be reported to the user. */ + +public final class ErrorType extends Err { + + /** This ensures this class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** Constructs a new type error. + * @param msg - the actual error message (can be null) + */ + public ErrorType(String msg) { super(null, msg, null); } + + /** Constructs a new type error with "cause" as the underlying cause. + * @param msg - the actual error message (can be null) + * @param cause - if nonnull, it is the cause of this exception + */ + public ErrorType(String msg, Throwable cause) { super(null, msg, cause); } + + /** Constructs a new type error. + * @param pos - the filename/line/row information (can be null if unknown) + * @param msg - the actual error message (can be null) + */ + public ErrorType(Pos pos, String msg) { super(pos, msg, null); } + + /** Returns a textual description of the error. */ + @Override public String toString() { + if (pos==Pos.UNKNOWN) return "Type error:\n"+msg; + if (pos.filename.length()>0) return "Type error in "+pos.filename+" at line "+pos.y+" column "+pos.x+":\n"+msg; + return "Type error at line " + pos.y + " column " + pos.x + ":\n" + msg; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ErrorWarning.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ErrorWarning.java new file mode 100644 index 00000000..959b8314 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/ErrorWarning.java @@ -0,0 +1,48 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +/** Immutable; this represents a nonfatal warning that should be reported to the user. */ + +public final class ErrorWarning extends Err { + + /** This ensures this class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** Constructs a new warning. + * @param msg - the actual error message (can be null) + */ + public ErrorWarning(String msg) { super(null, msg, null); } + + /** Constructs a new warning with "cause" as the underlying cause. + * @param msg - the actual error message (can be null) + * @param cause - if nonnull, it is the cause of this exception + */ + public ErrorWarning(String msg, Throwable cause) { super(null, msg, cause); } + + /** Constructs a new warning. + * @param pos - the filename/line/row information (can be null if unknown) + * @param msg - the actual error message (can be null) + */ + public ErrorWarning(Pos pos, String msg) { super(pos, msg, null); } + + /** Returns a textual description of the error. */ + @Override public String toString() { + if (pos==Pos.UNKNOWN) return msg; + if (pos.filename.length()>0) return "Line "+pos.y+" column "+pos.x+" in "+pos.filename+":\n"+msg; + return "Line " + pos.y + " column " + pos.x + ":\n" + msg; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/JoinableList.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/JoinableList.java new file mode 100644 index 00000000..e7bf4b42 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/JoinableList.java @@ -0,0 +1,92 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.io.Serializable; +import java.util.AbstractList; + +/** Immutable; implements a list where it is combine them; null values are NOT allowed. */ + +public final class JoinableList extends AbstractList implements Serializable { + + /** This ensures the class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** The number of items stored in this list. + *

Invariant: count == (pre!=null ? pre.count : 0) + (item!=null ? 1 : 0) + (post!=null ? post.count : 0) + */ + private final int count; + + /** The list of items before "this.item"; may be null. */ + private final JoinableList pre; + + /** The list of items after "this.item"; may be null. */ + private final JoinableList post; + + /** If nonnull, it stores an item. */ + private final E item; + + /** Construct a JoinableList object. */ + private JoinableList(int count, JoinableList pre, E item, JoinableList post) { + this.count = count; + this.pre = pre; + this.item = item; + this.post = post; + } + + /** Construct an empty list. */ + public JoinableList() { this(0, null, null, null); } + + /** Construct a list containing a single item, or return an empty list if item==null. */ + public JoinableList(E item) { this((item!=null ? 1 : 0), null, item, null); } + + /** Returns a list that represents the concatenation of this list and that list. */ + public JoinableList make(JoinableList that) { + if (that == null || that.count == 0) return this; else if (count == 0) return that; + int sum = count + that.count; + if (sum < count) throw new OutOfMemoryError(); // integer overflow + if (post != null) return new JoinableList(sum, this, null, that); else return new JoinableList(sum, pre, item, that); + } + + /** Returns a list that represents the result of appending newItem onto this list; if newItem==null we return this list as-is. */ + public JoinableList make(E newItem) { + if (newItem == null) return this; + int sum = count + 1; // integer overflow + if (sum < 1) throw new OutOfMemoryError(); + if (post != null) return new JoinableList(sum, this, newItem, null); + if (item != null) return new JoinableList(sum, pre, item, new JoinableList(newItem)); + return new JoinableList(sum, pre, newItem, null); + } + + /** If the list if nonempty, arbitrarily return one of the item, otherwise throw ArrayIndexOutOfBoundsException. */ + public E pick() { if (item!=null) return item; else return get(0); } + + /** Return the i-th element + * @throws ArrayIndexOutOfBoundsException if the given index doesn't exist + */ + @Override public E get(int i) { + if (i < 0 || i >= count) throw new ArrayIndexOutOfBoundsException(); + JoinableList x = this; + while(true) { + int pre = (x.pre == null) ? 0 : x.pre.count; + if (i < pre) { x = x.pre; continue; } + if (x.item == null) { i = i - pre; x = x.post; } else if (i != pre) { i = i - pre - 1; x = x.post; } else return x.item; + } + } + + /** Returns the number of elements in this list. */ + @Override public int size() { return count; } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Listener.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Listener.java new file mode 100644 index 00000000..b992f1de --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Listener.java @@ -0,0 +1,30 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +/** This defines an interface for receiving events. */ + +public interface Listener { + + /** This defines the list of possible events. */ + enum Event { CLICK, STATUS_CHANGE, FOCUSED, CTRL_PAGE_UP, CTRL_PAGE_DOWN, CARET_MOVED}; + + /** This method is called when the given zero-argument-event occurs. */ + public Object do_action(Object sender, Event event); + + /** This method is called when the given single-argument-event occurs. */ + public Object do_action(Object sender, Event event, Object arg); +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Listeners.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Listeners.java new file mode 100644 index 00000000..2f559505 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Listeners.java @@ -0,0 +1,46 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.util.ArrayList; +import edu.mit.csail.sdg.alloy4.Listener.Event; + +/** This stores a list of listeners. */ + +public final class Listeners { + + /** The actual list of listeners. */ + private final ArrayList listeners = new ArrayList(); + + /** Construct a empty list of listeners. */ + public Listeners() { } + + /** Add a listener to this group of listeners (if not already in the list) */ + public void add(Listener listener) { + for(Listener x: listeners) if (x == listener) return; + listeners.add(listener); + } + + /** Send the following zero-argument event to every listener. */ + public void fire(Object sender, Event event) { + for(Listener x: listeners) x.do_action(sender, event); + } + + /** Send the following one-argument event to every listener. */ + public void fire(Object sender, Event event, Object arg) { + for(Listener x: listeners) x.do_action(sender, event, arg); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/MacUtil.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/MacUtil.java new file mode 100644 index 00000000..fa9bc391 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/MacUtil.java @@ -0,0 +1,77 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import javax.swing.SwingUtilities; +import com.apple.eawt.Application; +import com.apple.eawt.ApplicationAdapter; +import com.apple.eawt.ApplicationEvent; +import com.apple.eawt.ApplicationListener; + +/** This class provides better integration on Mac OS X. + * + *

You must not call any methods here if you're not on Mac OS X, + * since that triggers the loading of com.apple.eawt.* which are not available on other platforms. + * + *

Thread Safety: Safe. + */ + +public final class MacUtil { + + /** Constructor is private, since this class never needs to be instantiated. */ + private MacUtil() { } + + /** The cached Application object. */ + private static Application app = null; + + /** The previous ApplicationListener (or null if there was none). */ + private static ApplicationListener listener = null; + + /** Register a Mac OS X "ApplicationListener"; if there was a previous listener, it will be removed first. + * @param reopen - when the user clicks on the Dock icon, we'll call reopen.run() using SwingUtilities.invokeLater + * @param about - when the user clicks on About Alloy4, we'll call about.run() using SwingUtilities.invokeLater + * @param open - when a file needs to be opened, we'll call open.run(filename) using SwingUtilities.invokeLater + * @param quit - when the user clicks on Quit, we'll call quit.run() using SwingUtilities.invokeAndWait + */ + public synchronized static void registerApplicationListener + (final Runnable reopen, final Runnable about, final Runner open, final Runnable quit) { + if (app == null) app = new Application(); else if (listener != null) app.removeApplicationListener(listener); + listener = new ApplicationAdapter() { + @Override public void handleReOpenApplication(ApplicationEvent arg) { + SwingUtilities.invokeLater(reopen); + } + @Override public void handleAbout(ApplicationEvent arg) { + arg.setHandled(true); + SwingUtilities.invokeLater(about); + } + @Override public void handleOpenFile(ApplicationEvent arg) { + final String filename = arg.getFilename(); + SwingUtilities.invokeLater(new Runnable() { + public void run() { open.run(filename); } + }); + } + @Override public void handleQuit(ApplicationEvent arg) { + try { + if (SwingUtilities.isEventDispatchThread()) quit.run(); else SwingUtilities.invokeAndWait(quit); + } catch (Throwable e) { + // Nothing we can do; we're already trying to quit! + } + arg.setHandled(false); + } + }; + app.addApplicationListener(listener); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/MailBug.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/MailBug.java new file mode 100644 index 00000000..334e56f4 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/MailBug.java @@ -0,0 +1,276 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.lang.Thread.UncaughtExceptionHandler; +import java.util.Map; +import java.util.prefs.BackingStoreException; +import java.util.prefs.Preferences; +import java.io.BufferedInputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.URL; +import java.net.URLConnection; +import java.awt.Color; +import java.awt.Dimension; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.border.EmptyBorder; +import javax.swing.border.LineBorder; + +/** This class asks the user for permission to email a bug report when an uncaught exception occurs. */ + +public final class MailBug implements UncaughtExceptionHandler, Runnable { + + /** The version number of the most recent Alloy4 (as queried from alloy.mit.edu); -1 if alloy.mit.edu has not replied yet. */ + private static int latestAlloyVersion = -1; + + /** The name of the most recent Alloy4 (as queried from alloy.mit.edu); "unknown" if alloy.mit.edu has not replied yet. */ + private static String latestAlloyVersionName = "unknown"; + + /** The URL where the bug report should be sent. */ + private static final String ALLOY_URL = "http://alloy.mit.edu/postbug4.php"; + + /** The URL where the current version info can be queried. */ + private static final String ALLOY_NOW = "http://alloy.mit.edu/alloy4/download/alloy4.txt"; + + /** If alloy.mit.edu has replied, then return the latest Alloy build number, else return -1. */ + public static int latestBuildNumber() { synchronized(MailBug.class) { return latestAlloyVersion; } } + + /** If alloy.mit.edu has replied, then return the latest Alloy build name, else return "unknown" */ + public static String latestBuildName() { synchronized(MailBug.class) { return latestAlloyVersionName; } } + + /** Construct a new MailBug object. */ + private MailBug() { } + + /** Setup the uncaught-exception-handler and use a separate thread to query alloy.mit.edu for latest version number. */ + public static void setup() { + if (Thread.getDefaultUncaughtExceptionHandler() != null) return; + MailBug x = new MailBug(); + Thread.setDefaultUncaughtExceptionHandler(x); + new Thread(x).start(); + } + + /** This method concatenates a Throwable's message and stack trace and all its causes into a single String. */ + public static String dump (Throwable ex) { + StringBuilder sb = new StringBuilder(); + while(ex != null) { + sb.append(ex.getClass()).append(": ").append(ex.getMessage()).append('\n'); + StackTraceElement[] trace = ex.getStackTrace(); + if (trace != null) for(int n = trace.length, i = 0; i < n; i++) sb.append(trace[i]).append('\n'); + ex = ex.getCause(); + if (ex != null) sb.append("caused by...\n"); + } + return sb.toString().trim(); + } + + /** This method returns true if the exception appears to be a Sun Java GUI bug. */ + private static boolean isGUI(Throwable ex) { + // If the root of the stack trace is within Java framework itself, + // and no where is Alloy, Kodkod, or SAT4J anywhere along the trace, + // then it's almost *always* a Sun Java GUI bug from what we've seen. + // And it's better to ignore it rather than kill the file that the user is editing. + while(ex != null) { + StackTraceElement[] trace = ex.getStackTrace(); + for(int n=(trace==null ? 0 : trace.length), i=0; i 0) { + connection.setDoOutput(true); + out = connection.getOutputStream(); + out.write(send.getBytes("UTF-8")); + out.close(); + out = null; + } + in = connection.getInputStream(); + bis = new BufferedInputStream(in); + StringBuilder sb = new StringBuilder(); + int i; + while((i = bis.read()) >= 0) { sb.append((char)(i<=0x7F ? i : '?')); } + ans = Util.convertLineBreak(sb.toString()); + } catch (Throwable ex) { + ans = failure; + } finally { + Util.close(bis); + Util.close(in); + Util.close(out); + } + return ans; + } + + /** This method will query alloy.mit.edu for the latest version number. */ + public void run() { + String result = readAll(ALLOY_NOW + "?buildnum=" + Version.buildNumber() + "&builddate=" + Version.buildDate(), "", ""); + if (!result.startsWith("Alloy Build ")) return; + // Now that we know we're online, try to remove the old ill-conceived "Java WebStart" versions of Alloy4 BETA1..BETA7 + //Subprocess.exec(20000, new String[]{ + // "javaws", "-silent", "-offline", "-uninstall", "http://alloy.mit.edu/alloy4/download/alloy4.jnlp"}); + // Now parse the result + int num = 0; + boolean found = false; + for(int i=0, len=result.length(); ; i++) { + if (i >= len) return; // malformed + char c = result.charAt(i); + if (!(c>='0' && c<='9')) { if (!found) continue; else { result = result.substring(i).trim(); break; } } + found = true; + num = num*10 + (c - '0'); + } + synchronized(MailBug.class) { latestAlloyVersionName = result; latestAlloyVersion = num; } + } + + /** This method sends the crash report then displays alloy.mit.edu's reply in a text window. */ + private static void sendCrashReport (Thread thread, Throwable ex, String email, String problem) { + try { + final String report = prepareCrashReport(thread, ex, email, problem); + final String alt = "Sorry. An error has occurred in posting the bug report.\n" + + "Please email this report to alloy@mit.edu directly.\n\n" + dump(ex); + final JTextArea status = OurUtil.textarea("Sending the bug report... please wait...", + 10, 40, false, true, new LineBorder(Color.GRAY)); + new Thread(new Runnable() { + public void run() { + final String output = readAll(ALLOY_URL, report, alt); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + status.setText(output); + status.setCaretPosition(0); + } + }); + } + }).start(); + OurDialog.showmsg("Sending the bug report... please wait...", status); + } finally { + System.exit(1); + } + } + + /** This method is an exception handler for uncaught exceptions. */ + public void uncaughtException (Thread thread, Throwable ex) { + if (isGUI(ex)) return; + final int ver; + final String name; + synchronized(MailBug.class) { ver = latestAlloyVersion; name = latestAlloyVersionName; } + if (ex!=null) { + System.out.flush(); + System.err.flush(); + System.err.println("Exception: " + ex.getClass()); + System.err.println("Message: " + ex); + System.err.println("Stacktrace:"); + System.err.println(dump(ex)); + System.err.flush(); + } + final String yes = "Send the Bug Report", no = "Don't Send the Bug Report"; + final JTextField email = OurUtil.textfield("", 20, new LineBorder(Color.DARK_GRAY)); + final JTextArea problem = OurUtil.textarea("", 50, 50, true, false, new EmptyBorder(0,0,0,0)); + final JScrollPane scroll = OurUtil.scrollpane(problem, new LineBorder(Color.DARK_GRAY), new Dimension(300, 200)); + for(Throwable ex2 = ex; ex2 != null; ex2 = ex2.getCause()) { + if (ex2 instanceof StackOverflowError) OurDialog.fatal(new Object[] { + "Sorry. The Alloy Analyzer has run out of stack space.", + " ", + "Try simplifying your model or reducing the scope.", + "And try reducing Options->SkolemDepth to 0.", + "And try increasing Options->Stack.", + " ", + "There is no way for Alloy to continue execution, so pressing OK will shut down Alloy." + }); + if (ex2 instanceof OutOfMemoryError) OurDialog.fatal(new Object[] { + "Sorry. The Alloy Analyzer has run out of memory.", + " ", + "Try simplifying your model or reducing the scope.", + "And try reducing Options->SkolemDepth to 0.", + "And try increasing Options->Memory.", + " ", + "There is no way for Alloy to continue execution, so pressing OK will shut down Alloy." + }); + } + if (ver > Version.buildNumber()) OurDialog.fatal(new Object[] { + "Sorry. A fatal error has occurred.", + " ", + "You are running Alloy Analyzer " + Version.version(), + "but the most recent is Alloy Analyzer "+ name, + " ", + "Please try to upgrade to the newest version", + "as the problem may have already been fixed.", + " ", + "There is no way for Alloy to continue execution, so pressing OK will shut down Alloy." + }); + if (OurDialog.yesno(new Object[] { + "Sorry. A fatal internal error has occurred.", + " ", + "You may submit a bug report (via HTTP).", + "The error report will include your system", + "configuration, but no other information.", + " ", + "If you'd like to be notified about a fix,", + "please describe the problem and enter your email address.", + " ", + OurUtil.makeHT("Email:", 5, email, null), + OurUtil.makeHT("Problem:", 5, scroll, null) + }, yes, no)) sendCrashReport(thread, ex, email.getText(), problem.getText()); + System.exit(1); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurAntiAlias.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurAntiAlias.java new file mode 100644 index 00000000..9fe1d854 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurAntiAlias.java @@ -0,0 +1,86 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.util.WeakHashMap; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JTextPane; +import javax.swing.text.DefaultHighlighter; + +/** Graphical convenience methods for managing and constructing antialias-capable components. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final class OurAntiAlias { + + /** This constructor is private, since this utility class never needs to be instantiated. */ + private OurAntiAlias() { } + + /** Use anti-alias or not. */ + private static boolean antiAlias = Util.onMac() || Util.onWindows(); + + /** Stores weak references of all objects that need to be redrawn when anti-alias setting changes. */ + private static WeakHashMap map = new WeakHashMap(); + + /** Changes whether anti-aliasing should be done or not (when changed, we will automatically repaint all affected components). */ + public static void enableAntiAlias(boolean enableAntiAlias) { + if (antiAlias == enableAntiAlias || Util.onMac() || Util.onWindows()) return; + antiAlias = enableAntiAlias; + for(JComponent x: map.keySet()) if (x!=null) { x.invalidate(); x.repaint(); x.validate(); } + } + + /** Constructs an antialias-capable JLabel. + * @param attributes - see {@link edu.mit.csail.sdg.alloy4.OurUtil#make OurUtil.make(component, attributes...)} + */ + public static JLabel label(String label, Object... attributes) { + JLabel ans = new JLabel(label) { + static final long serialVersionUID = 0; + @Override public void paint(Graphics gr) { + if (antiAlias && gr instanceof Graphics2D) { + ((Graphics2D)gr).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + } + super.paint(gr); + } + }; + OurUtil.make(ans, attributes); + map.put(ans, Boolean.TRUE); + return ans; + } + + /** Constructs an antialias-capable JTextPane with a DefaultHighlighter associated with it. + * @param attributes - see {@link edu.mit.csail.sdg.alloy4.OurUtil#make OurUtil.make(component, attributes...)} + */ + public static JTextPane pane(Object... attributes) { + JTextPane ans = new JTextPane() { + static final long serialVersionUID = 0; + @Override public void paint(Graphics gr) { + if (antiAlias && gr instanceof Graphics2D) { + ((Graphics2D)gr).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + } + super.paint(gr); + } + }; + OurUtil.make(ans, attributes); + ans.setHighlighter(new DefaultHighlighter()); + map.put(ans, Boolean.TRUE); + return ans; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurBorder.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurBorder.java new file mode 100644 index 00000000..3338ea76 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurBorder.java @@ -0,0 +1,89 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; +import javax.swing.border.Border; + +/** Graphical border on zero, one, two, three, or all four sides of a component. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final class OurBorder implements Border { + + /** non-null if we want to draw a border line of that Color above the component. */ + private final Color top; + + /** non-null if we want to draw a border line of that Color to the left of the component. */ + private final Color left; + + /** non-null if we want to draw a border line of that Color below the component. */ + private final Color bottom; + + /** non-null if we want to draw a border line of that Color to the right of the component. */ + private final Color right; + + /** Construct a Border object that draws a border on 0, 1, 2, 3, or all 4 sides of the component. + * Note: it paints the borders top, bottom, left, then right. + * @param top - nonnull if we want to draw a border line (with that color) above the component + * @param left - nonnull if we want to draw a border line (with that color) to the left of the component + * @param bottom - nonnull if we want to draw a border line (with that color) below the component + * @param right - nonnull if we want to draw a border line (with that color) to the right of the component + */ + public OurBorder (Color top, Color left, Color bottom, Color right) { + this.top = top; + this.left = left; + this.bottom = bottom; + this.right = right; + } + + /** Construct a Border object that draws a light gray line on 0, 1, 2, 3, or all 4 sides of the component. + * Note: it paints the borders top, bottom, left, then right. + * @param top - true if we want to draw a Color.LIGHT_GRAY border line above the component + * @param left - true if we want to draw a Color.LIGHT_GRAY border line to the left of the component + * @param bottom - true if we want to draw a Color.LIGHT_GRAY border line below the component + * @param right - true if we want to draw a Color.LIGHT_GRAY border line to the right of the component + */ + public OurBorder (boolean top, boolean left, boolean bottom, boolean right) { + this.top = top ? Color.LIGHT_GRAY : null; + this.left = left ? Color.LIGHT_GRAY : null; + this.bottom = bottom ? Color.LIGHT_GRAY : null; + this.right = right ? Color.LIGHT_GRAY : null; + } + + /** This method is called by Swing to actually draw the borders. */ + public void paintBorder (Component component, Graphics graphics, int x, int y, int width, int height) { + if (width<1 || height<1) return; + Color old = graphics.getColor(); + if (top != null) { graphics.setColor(top); graphics.drawLine(x, y, x+width-1, y ); } + if (bottom != null) { graphics.setColor(bottom); graphics.drawLine(x, y+height-1, x+width-1, y+height-1); } + if (left != null) { graphics.setColor(left); graphics.drawLine(x, y, x, y+height-1); } + if (right != null) { graphics.setColor(right); graphics.drawLine(x+width-1, y, x+width-1, y+height-1); } + graphics.setColor(old); + } + + /** This method is called by Swing to retrieve the dimension of the border. */ + public Insets getBorderInsets (Component c) { + return new Insets(top!=null?1:0, left!=null?1:0, bottom!=null?1:0, right!=null?1:0); + } + + /** This method is called by Swing to find out whether this border object needs to fill in its own background. */ + public boolean isBorderOpaque() { return true; } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurCheckbox.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurCheckbox.java new file mode 100644 index 00000000..34109763 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurCheckbox.java @@ -0,0 +1,99 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.BoxLayout; +import javax.swing.Icon; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JPanel; + +/** Graphical checkbox. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public abstract class OurCheckbox extends JPanel { + + /** This ensures the class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** The icon to use when the checkbox is off. */ + public static final Icon OFF = OurUtil.loadIcon("images/cb0.gif"); + + /** The icon to use when the checkbox is on. */ + public static final Icon ON = OurUtil.loadIcon("images/cb1.gif"); + + /** The icon to use when the checkbox is off entirely. */ + public static final Icon ALL_OFF = OurUtil.loadIcon("images/tcb01.gif"); + + /** The icon to use when the checkbox is on entirely. */ + public static final Icon ALL_ON = OurUtil.loadIcon("images/tcb02.gif"); + + /** The icon to use when the checkbox is off due to inheritance. */ + public static final Icon INH_OFF = OurUtil.loadIcon("images/tcb03.gif"); + + /** The icon to use when the checkbox is on due to inheritance. */ + public static final Icon INH_ON = OurUtil.loadIcon("images/tcb04.gif"); + + /** The underlying JCheckBox object. */ + private final JCheckBox jbox; + + /** The JLabel object for displaying a label next to the checkbox. */ + private final JLabel jlabel; + + /** Constructs a OurCheckbox object. + * @param label - the label to display next to the checkbox + * @param tooltip - the tool tip to show when the mouse hovers over this checkbox + * @param icon - the initial icon to display (should be one of ON/OFF/ALL_ON/ALL_OFF/INH_ON/INH_OFF) + */ + public OurCheckbox(String label, String tooltip, Icon icon) { + setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); + jbox = new JCheckBox(icon); + jbox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + Icon icon = do_action(); + if (icon != jbox.getIcon()) jbox.setIcon(icon); + } + }); + jbox.setMaximumSize(jbox.getPreferredSize()); + jbox.setToolTipText(tooltip); + jlabel = OurUtil.label(label, tooltip); + if (icon==ON || icon==OFF) { add(jbox); add(jlabel); } else { add(jlabel); add(jbox); } + setAlignmentX(RIGHT_ALIGNMENT); + } + + /** This method is called when the user clicks on the checkbox; subclasses should override this to provide the custom behavior. */ + public abstract Icon do_action(); + + /** This method is called by Swing to enable/disable a component. */ + @Override public final void setEnabled(boolean enabled) { + if (jbox != null) jbox.setEnabled(enabled); + if (jlabel != null) jlabel.setEnabled(enabled); + // jbox and jlabel may be null if during the constructor, some method call causes Swing to call this method early + } + + /** This method is called by Swing to change its background color. */ + @Override public final void setBackground(Color color) { + super.setBackground(color); + if (jbox != null) jbox.setBackground(color); + if (jlabel != null) jlabel.setBackground(color); + // jbox and jlabel may be null if during the constructor, some method call causes Swing to call this method early + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurCombobox.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurCombobox.java new file mode 100644 index 00000000..3b25d327 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurCombobox.java @@ -0,0 +1,97 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import java.util.Vector; +import javax.swing.Icon; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.ListCellRenderer; +import javax.swing.border.EmptyBorder; + +/** Graphical combobox. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public class OurCombobox extends JComboBox { + + /** This ensures the class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** This caches a preconstructed JLabel that is used for the rendering of each Combo value. */ + private static JLabel jlabel; + + /** Subclass can override this method to provide the custom text for any given value (It should return "" if no text is needed) */ + public String do_getText(Object value) { return String.valueOf(value); } + + /** Subclass can override this method to provide the custom icon for any given value (It should return null if no icon is needed) */ + public Icon do_getIcon(Object value) { return null; } + + /** Subclass can override this method to react upon selection change. */ + public void do_changed(Object newValue) { } + + /** This helper method makes a copy of the list, and then optionally prepend null at the beginning of the list. */ + private static Vector do_copy (Object[] list, boolean addNull) { + Vector answer = new Vector(list.length + (addNull ? 1 : 0)); + if (addNull) answer.add(null); + for(int i=0; i 25) height = 25; // Otherwise, the height is too big on Windows + setPreferredSize(new Dimension(width, height)); + setMaximumSize(new Dimension(width, height)); + if (!Util.onWindows() && !Util.onMac()) setBorder(new EmptyBorder(4, 3, 4, 0)); + } + if (initialValue != null) { setSelectedItem(initialValue); } + addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { do_changed(getSelectedItem()); } + }); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurConsole.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurConsole.java new file mode 100644 index 00000000..1bf57a79 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurConsole.java @@ -0,0 +1,279 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Event; +import java.awt.Font; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import javax.swing.AbstractAction; +import javax.swing.JPanel; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.JTextPane; +import javax.swing.KeyStroke; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.Caret; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledDocument; + +/** Graphical input/output prompt. + * + *

This class's constructor takes a Computer object, then constructs a JScrollPane + * in which the user can type commands, and the output from the Computer object will be displayed. + * Empty input lines are ignored. + * This interactive prompt supports UP and DOWN arrow command histories and basic copy/cut/paste editing. + * + *

For each user input, if the Computer object returns a String, it is displayed in blue. + * But if the Computer object throws an exception, the exception will be displayed in red. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final class OurConsole extends JScrollPane { + + /** This ensures the class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** The style for default text. */ + private final AttributeSet plain = style("Verdana", 14, false, Color.BLACK, 0); + + /** The style for bold text. */ + private final AttributeSet bold = style("Verdana", 14, true, Color.BLACK, 0); + + /** The style for successful result. */ + private final AttributeSet good = style("Verdana", 14, false, Color.BLUE, 15); + + /** The style for failed result. */ + private final AttributeSet bad = style("Verdana", 14, false, Color.RED, 15); + + /** The number of characters that currently exist above the horizontal divider bar. + * (The interactive console is composed of a JTextPane which contains 0 or more input/output pairs, followed + * by a horizontal divider bar, followed by an embedded sub-JTextPane (where the user can type in the next input)) + */ + private int len = 0; + + /** The main JTextPane containing 0 or more input/output pairs, followed by a horizontal bar, followed by this.sub */ + private final JTextPane main = do_makeTextPane(false, 5, 5, 5); + + /** The sub JTextPane where the user can type in the next command. */ + private final JTextPane sub = do_makeTextPane(true, 10, 10, 0); + + /** The history of all commands entered so far, plus an extra String representing the user's next command. */ + private final List history = new ArrayList(); { history.add(""); } + + /** The position in this.history that is currently showing. */ + private int browse = 0; + + /** Helper method that construct a mutable style with the given font name, font size, boldness, color, and left indentation. */ + static MutableAttributeSet style(String fontName, int fontSize, boolean boldness, Color color, int leftIndent) { + MutableAttributeSet s = new SimpleAttributeSet(); + StyleConstants.setFontFamily(s, fontName); + StyleConstants.setFontSize(s, fontSize); + StyleConstants.setBold(s, boldness); + StyleConstants.setForeground(s, color); + StyleConstants.setLeftIndent(s, leftIndent); + return s; + } + + /** Construct a JScrollPane that allows the user to interactively type in commands and see replies. + * + * @param computer - this object is used to evaluate the user input + * + * @param syntaxHighlighting - if true, the "input area" will be syntax-highlighted + * + * @param initialMessages - this is a list of String and Boolean; each String is printed to the screen as is, + * and Boolean.TRUE will turn subsequent text bold, and Boolean.FALSE will turn subsequent text non-bold. + */ + public OurConsole(final Computer computer, boolean syntaxHighlighting, Object... initialMessages) { + super(VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED); + if (syntaxHighlighting) { sub.setDocument(new OurSyntaxUndoableDocument("Verdana", 14)); } + setViewportView(main); + // show the initial message + AttributeSet st = plain; + for(Object x: initialMessages) { + if (x instanceof Boolean) st = (Boolean.TRUE.equals(x) ? bold : plain); else do_add(-1, String.valueOf(x), st); + } + do_add(-1, "\n", plain); // we must add a linebreak to ensure that subsequent text belong to a "different paragraph" + // insert the divider and the sub JTextPane + StyledDocument doc = main.getStyledDocument(); + JPanel divider = new JPanel(); divider.setBackground(Color.LIGHT_GRAY); divider.setPreferredSize(new Dimension(1,1)); + MutableAttributeSet dividerStyle = new SimpleAttributeSet(); StyleConstants.setComponent(dividerStyle, divider); + MutableAttributeSet inputStyle = new SimpleAttributeSet(); StyleConstants.setComponent(inputStyle, sub); + len = doc.getLength(); + do_add(-1, " \n", dividerStyle); // The space character won't be displayed; it will instead be drawn as a divider + do_add(-1, " \n", inputStyle); // The space character won't be displayed; it will instead display the input buffer + final Caret subCaret = sub.getCaret(), mainCaret = main.getCaret(); + // When caret moves in the sub JTextPane, we cancel any active selection in the main JTextPane + subCaret.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + if (mainCaret.getMark() != mainCaret.getDot()) mainCaret.setDot(mainCaret.getDot()); + } + }); + // When caret moves in the main JTextPane, we cancel any active selection in the sub JTextPane + mainCaret.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + if (subCaret.getMark() != subCaret.getDot()) subCaret.setDot(subCaret.getDot()); + } + }); + // now, create the paste/copy/cut actions + AbstractAction alloy_paste = new AbstractAction("alloy_paste") { + static final long serialVersionUID = 0; + public void actionPerformed(ActionEvent x) { sub.paste(); } + }; + AbstractAction alloy_copy = new AbstractAction("alloy_copy") { + static final long serialVersionUID = 0; + public void actionPerformed(ActionEvent x) { + if (sub.getSelectionStart() != sub.getSelectionEnd()) sub.copy(); else main.copy(); + } + }; + AbstractAction alloy_cut = new AbstractAction("alloy_cut") { + static final long serialVersionUID = 0; + public void actionPerformed(ActionEvent x) { + if (sub.getSelectionStart() != sub.getSelectionEnd()) sub.cut(); else main.copy(); + } + }; + // create the keyboard associations: ctrl-{c,v,x,insert} and shift-{insert,delete} + for(JTextPane x: Arrays.asList(main, sub)) { + x.getActionMap().put("alloy_paste", alloy_paste); + x.getActionMap().put("alloy_copy", alloy_copy); + x.getActionMap().put("alloy_cut", alloy_cut); + x.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_V, Event.CTRL_MASK), "alloy_paste"); + x.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_C, Event.CTRL_MASK), "alloy_copy"); + x.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_X, Event.CTRL_MASK), "alloy_cut"); + x.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, Event.SHIFT_MASK), "alloy_paste"); + x.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, Event.CTRL_MASK), "alloy_copy"); + x.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, Event.SHIFT_MASK), "alloy_cut"); + } + // configure so that, upon receiving focus, we automatically focus and scroll to the sub-JTextPane + FocusAdapter focus = new FocusAdapter() { + public void focusGained(FocusEvent e) { + sub.requestFocusInWindow(); + sub.scrollRectToVisible(new Rectangle(0, sub.getY(), 1, sub.getHeight())); + } + }; + addFocusListener(focus); + sub.addFocusListener(focus); + main.addFocusListener(focus); + // configure so that mouse clicks in the main JTextPane will immediately transfer focus to the sub JTextPane + main.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent e) { sub.requestFocusInWindow(); } + public void mouseClicked(MouseEvent e) { sub.requestFocusInWindow(); } + }); + // configure the behavior for PAGE_UP, PAGE_DOWN, UP, DOWN, TAB, and ENTER + sub.addKeyListener(new KeyListener() { + public void keyTyped(KeyEvent e) { + if (e.getKeyChar() == '\t') { e.consume(); } + if (e.getKeyChar() == '\n') { e.consume(); String cmd = sub.getText(); sub.setText(""); do_command(computer, cmd); } + } + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER || e.getKeyCode()==KeyEvent.VK_TAB) e.consume(); + if (e.getKeyCode() == KeyEvent.VK_PAGE_UP) { e.consume(); do_pageup(); } + if (e.getKeyCode() == KeyEvent.VK_PAGE_DOWN) { e.consume(); do_pagedown(); } + if (e.getKeyCode() == KeyEvent.VK_UP) { + e.consume(); + if (browse == history.size() - 1) { history.set(browse, sub.getText()); } + if (browse > 0 && browse - 1 < history.size()) { browse--; sub.setText(history.get(browse)); } + } + if (e.getKeyCode() == KeyEvent.VK_DOWN) { + e.consume(); + if (browse < history.size() - 1) { browse++; sub.setText(history.get(browse)); } + } + } + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER || e.getKeyCode() == KeyEvent.VK_TAB) e.consume(); + } + }); + } + + /** This helper method constructs a JTextPane with the given settings. */ + private static JTextPane do_makeTextPane(boolean editable, int topMargin, int bottomMargin, int otherMargin) { + JTextPane x = OurAntiAlias.pane(Color.BLACK, Color.WHITE, new Font("Verdana", Font.PLAIN, 14)); + x.setEditable(editable); + x.setAlignmentX(0); + x.setAlignmentY(0); + x.setCaretPosition(0); + x.setMargin(new Insets(topMargin, otherMargin, bottomMargin, otherMargin)); + return x; + } + + /** This method processes a user command. */ + private void do_command(Computer computer, String cmd) { + cmd = cmd.trim(); + if (cmd.length()==0) return; + StyledDocument doc = main.getStyledDocument(); + if (history.size()>=2 && cmd.equals(history.get(history.size()-2))) { + // If the user merely repeated the most recent command, then don't grow the history + history.set(history.size()-1, ""); + } else { + // Otherwise, grow the history + history.set(history.size()-1, cmd); + history.add(""); + } + browse = history.size()-1; + // display the command + int old = doc.getLength(); do_add(len, cmd+"\n\n", plain); len += (doc.getLength() - old); + // perform the computation + boolean isBad = false; + try { cmd = computer.compute(cmd); } catch(Throwable ex) { cmd = ex.toString(); isBad = true; } + int savePosition = len; + // display the outcome + old = doc.getLength(); do_add(len, cmd.trim()+"\n\n", (isBad ? bad : good)); len += (doc.getLength() - old); + // indent the outcome + main.setSelectionStart(savePosition+1); main.setSelectionEnd(len); main.setParagraphAttributes(good, false); + // redraw then scroll to the bottom + invalidate(); + repaint(); + validate(); + sub.scrollRectToVisible(new Rectangle(0, sub.getY(), 1, sub.getHeight())); + do_pagedown(); // need to do this after the validate() so that the scrollbar knows the new limit + } + + /** Performs "page up" in the JScrollPane. */ + private void do_pageup() { + JScrollBar bar = getVerticalScrollBar(); + bar.setValue(bar.getValue() - 200); + } + + /** Performs "page down" in the JScrollPane. */ + private void do_pagedown() { + JScrollBar bar = getVerticalScrollBar(); + bar.setValue(bar.getValue() + 200); + } + + /** Insert the given text into the given location and with the given style if where>=0; append the text if where<0. */ + private void do_add(int where, String text, AttributeSet style) { + StyledDocument doc = main.getStyledDocument(); + try { doc.insertString(where >= 0 ? where : doc.getLength(), text, style); } catch(BadLocationException ex) { } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurDialog.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurDialog.java new file mode 100644 index 00000000..9246113f --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurDialog.java @@ -0,0 +1,247 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.io.File; +import java.io.FilenameFilter; +import java.util.Locale; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.FileDialog; +import java.awt.Frame; +import java.awt.GraphicsEnvironment; +import java.awt.HeadlessException; +import java.awt.event.KeyListener; +import java.awt.event.KeyEvent; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.filechooser.FileFilter; +import static javax.swing.JOptionPane.YES_NO_OPTION; +import static javax.swing.JOptionPane.QUESTION_MESSAGE; +import static javax.swing.JOptionPane.WARNING_MESSAGE; +import static javax.swing.JOptionPane.ERROR_MESSAGE; + +/** Graphical dialog methods for asking the user some questions. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final class OurDialog { + + /** The constructor is private, since this utility class never needs to be instantiated. */ + private OurDialog() { } + + /** Helper method for constructing an always-on-top modal dialog. */ + private static Object show(String title, int type, Object message, Object[] options, Object initialOption) { + if (options == null) { options = new Object[]{"Ok"}; initialOption = "Ok"; } + JOptionPane p = new JOptionPane(message, type, JOptionPane.DEFAULT_OPTION, null, options, initialOption); + p.setInitialValue(initialOption); + JDialog d = p.createDialog(null, title); + p.selectInitialValue(); + d.setAlwaysOnTop(true); + d.setVisible(true); + d.dispose(); + return p.getValue(); + } + + /** Popup the given informative message, then ask the user to click Close to close it. */ + public static void showmsg(String title, Object... msg) { + JButton dismiss = new JButton(Util.onMac() ? "Dismiss" : "Close"); + Object[] objs = new Object[msg.length + 1]; + System.arraycopy(msg, 0, objs, 0, msg.length); + objs[objs.length - 1] = OurUtil.makeH(null, dismiss, null); + JOptionPane about = new JOptionPane(objs, JOptionPane.PLAIN_MESSAGE, JOptionPane.DEFAULT_OPTION, null, new Object[]{}); + JDialog dialog = about.createDialog(null, title); + dismiss.addActionListener(Runner.createDispose(dialog)); + dialog.setAlwaysOnTop(true); + dialog.setVisible(true); + dialog.dispose(); + } + + /** Popup the given error message. */ + public static void alert(Object message) { + show("Error", ERROR_MESSAGE, message, null, null); + } + + /** Popup the given error message, then terminate the program. */ + public static void fatal(Object message) { + try { show("Fatal Error", ERROR_MESSAGE, message, null, null); } finally { System.exit(1); } + } + + /** Ask if the user wishes to save the file, discard the file, or cancel the entire operation (default is cancel). + * @return 'c' if cancel, 's' if save, 'd' if discard + */ + public static char askSaveDiscardCancel(String description) { + description = description + " has not been saved. Do you want to"; + Object ans = show( + "Warning", WARNING_MESSAGE, + new String[] {description, "cancel the operation, close the file without saving, or save it and close?"}, + new Object[] {"Save", "Don't Save", "Cancel"}, + "Cancel" + ); + return (ans == "Save") ? 's' : (ans == "Don't Save" ? 'd' : 'c'); + } + + /** Ask if the user really wishes to overwrite the file (default is no). + * @return true if the user wishes to overwrite the file, false if the user does not wish to overwrite the file. + */ + public static boolean askOverwrite(String filename) { + return "Overwrite" == show("Warning: file already exists", WARNING_MESSAGE, + new String[] {"The file \"" + filename + "\"", "already exists. Do you wish to overwrite it?"}, + new String[] {"Overwrite", "Cancel"}, + "Cancel" + ); + } + + /** This caches the result of the call to get all fonts. */ + private static String[] allFonts = null; + + /** Returns true if a font with that name exists on the system (comparison is case-insensitive). */ + public synchronized static boolean hasFont(String fontname) { + if (allFonts == null) allFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); + for(int i = 0; i < allFonts.length; i++) if (fontname.compareToIgnoreCase(allFonts[i]) == 0) return true; + return false; + } + + /** Asks the user to choose a font; returns "" if the user cancels the request. */ + public synchronized static String askFont() { + if (allFonts == null) allFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); + JComboBox jcombo = new OurCombobox(allFonts); + Object ans = show("Font", JOptionPane.INFORMATION_MESSAGE, + new Object[] {"Please choose the new font:", jcombo}, new Object[] {"Ok", "Cancel"}, "Cancel" + ); + Object value = jcombo.getSelectedItem(); + if (ans=="Ok" && (value instanceof String)) return (String)value; else return ""; + } + + /** True if we should use AWT (instead of Swing) to display the OPEN and SAVE dialog. */ + private static boolean useAWT = Util.onMac(); + + /** Use the platform's preferred file chooser to ask the user to select a file. + *
Note: if it is a save operation, and the user didn't include an extension, then we'll add the extension. + * @param isOpen - true means this is an Open operation; false means this is a Save operation + * @param dir - the initial directory (or null if we want to use the default) + * @param ext - the file extension (including "."; using lowercase letters; for example, ".als") or "" + * @param description - the description for the given extension + * @return null if the user didn't choose anything, otherwise it returns the selected file + */ + public static File askFile (boolean isOpen, String dir, final String ext, final String description) { + if (dir == null) dir = Util.getCurrentDirectory(); + if (!(new File(dir).isDirectory())) dir = System.getProperty("user.home"); + dir = Util.canon(dir); + String ans; + if (useAWT) { + Frame parent = new Frame("Alloy File Dialog"); // this window is unused and not shown; needed by FileDialog and nothing more + FileDialog open = new FileDialog(parent, isOpen ? "Open..." : "Save..."); + open.setAlwaysOnTop(true); + open.setMode(isOpen ? FileDialog.LOAD : FileDialog.SAVE); + open.setDirectory(dir); + if (ext.length()>0) open.setFilenameFilter(new FilenameFilter() { + public boolean accept(File dir, String name) { return name.toLowerCase(Locale.US).endsWith(ext); } + }); + open.setVisible(true); // This method blocks until the user either chooses something or cancels the dialog. + parent.dispose(); + if (open.getFile() == null) return null; else ans = open.getDirectory() + File.separatorChar + open.getFile(); + } else { + try { + JFileChooser open = new JFileChooser(dir) { + private static final long serialVersionUID = 0; + public JDialog createDialog(Component parent) throws HeadlessException { + JDialog dialog = super.createDialog(null); + dialog.setAlwaysOnTop(true); + return dialog; + } + }; + open.setDialogTitle(isOpen ? "Open..." : "Save..."); + open.setApproveButtonText(isOpen ? "Open" : "Save"); + open.setDialogType(isOpen ? JFileChooser.OPEN_DIALOG : JFileChooser.SAVE_DIALOG); + if (ext.length()>0) open.setFileFilter(new FileFilter() { + public boolean accept(File file) { return !file.isFile() || file.getPath().toLowerCase(Locale.US).endsWith(ext); } + public String getDescription() { return description; } + }); + if (open.showDialog(null, null) != JFileChooser.APPROVE_OPTION || open.getSelectedFile() == null) return null; + ans = open.getSelectedFile().getPath(); + } catch(Exception ex) { + // Some combination of Windows version and JDK version will trigger this failure. + // In such a case, we'll fall back to using the "AWT" file open dialog + useAWT = true; + return askFile(isOpen, dir, ext, description); + } + } + if (!isOpen) { + int lastSlash = ans.lastIndexOf(File.separatorChar); + int lastDot = (lastSlash>=0) ? ans.indexOf('.', lastSlash) : ans.indexOf('.'); + if (lastDot < 0) ans = ans + ext; + } + return new File(Util.canon(ans)); + } + + /** Display "msg" in a modal dialog window, and ask the user to choose "yes" versus "no" (default is "no"). */ + public static boolean yesno(Object msg, String yes, String no) { + return show("Question", WARNING_MESSAGE, msg, new Object[]{yes, no}, no) == yes; + } + + /** Display "msg" in a modal dialog window, and ask the user to choose "Yes" versus "No" (default is "no"). */ + public static boolean yesno(Object msg) { return yesno(msg, "Yes", "No"); } + + /** Display a modal dialog window containing the "objects"; returns true iff the user clicks Ok. */ + public static boolean getInput(String title, Object... objects) { + // If there is a JTextField or a JTextArea here, then let the first JTextField or JTextArea be the initially focused widget + Object main = "Ok"; + for(Object obj: objects) if (obj instanceof JTextField || obj instanceof JTextArea) { main = obj; break; } + // Construct the dialog panel + final JOptionPane pane = new JOptionPane(objects, QUESTION_MESSAGE, YES_NO_OPTION, null, new Object[]{"Ok", "Cancel"}, main); + final JDialog dialog = pane.createDialog(null, title); + // For each JTextField and JCheckBox, add a KeyListener that detects VK_ENTER and treat it as if the user clicked OK + for(Object obj: objects) if (obj instanceof JTextField || obj instanceof JCheckBox) { + ((JComponent)obj).addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent e) { if (e.getKeyCode()==KeyEvent.VK_ENTER) { pane.setValue("Ok"); dialog.dispose(); } } + public void keyReleased(KeyEvent e) { } + public void keyTyped(KeyEvent e) { } + }); + } + dialog.setAlwaysOnTop(true); + dialog.setVisible(true); // This method blocks until the user either chooses something or cancels the dialog. + dialog.dispose(); + return pane.getValue() == "Ok"; + } + + /** Display a simple non-modal window showing some text. */ + public static JFrame showtext(String title, String text) { + JFrame window = new JFrame(title); + JButton done = new JButton("Close"); + done.addActionListener(Runner.createDispose(window)); + JScrollPane scrollPane = OurUtil.scrollpane(OurUtil.textarea(text, 20, 60, false, false)); + window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + window.getContentPane().setLayout(new BorderLayout()); + window.getContentPane().add(scrollPane, BorderLayout.CENTER); + window.getContentPane().add(done, BorderLayout.SOUTH); + window.pack(); + window.setSize(500, 500); + window.setLocationRelativeTo(null); + window.setVisible(true); + return window; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurHighlighter.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurHighlighter.java new file mode 100644 index 00000000..183ff4d9 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurHighlighter.java @@ -0,0 +1,58 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.Shape; +import javax.swing.text.BadLocationException; +import javax.swing.text.Highlighter; +import javax.swing.text.JTextComponent; + +/** Graphica highlighter. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final class OurHighlighter implements Highlighter.HighlightPainter { + + /** The color to use when drawing highlights. */ + public final Color color; + + /** Construct a highlighter with the given color. */ + public OurHighlighter(Color color) { this.color = color; } + + /** This method is called by Swing to draw highlights. */ + public void paint(Graphics gr, int start, int end, Shape shape, JTextComponent text) { + Color old = gr.getColor(); + gr.setColor(color); + try { + Rectangle box = shape.getBounds(), a = text.getUI().modelToView(text, start), b = text.getUI().modelToView(text, end); + if (a.y == b.y) { + // same line (Note: furthermore, if start==end, then we draw all the way to the right edge) + Rectangle r = a.union(b); + gr.fillRect(r.x, r.y, (r.width<=1 ? (box.x + box.width - r.x) : r.width), r.height); + } else { + // Multiple lines; (Note: on first line we'll draw from "start" and extend to rightmost) + gr.fillRect(a.x, a.y, box.x + box.width - a.x, a.height); + if (a.y + a.height < b.y) gr.fillRect(box.x, a.y + a.height, box.width, b.y - (a.y + a.height)); + gr.fillRect(box.x, b.y, b.x - box.x, b.height); + } + } catch (BadLocationException e) { } // Failure to highlight is not fatal + gr.setColor(old); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurPDFWriter.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurPDFWriter.java new file mode 100644 index 00000000..7346cb72 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurPDFWriter.java @@ -0,0 +1,277 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.awt.Color; +import java.awt.Polygon; +import java.awt.Shape; +import java.awt.geom.PathIterator; +import java.io.IOException; +import java.io.RandomAccessFile; + +/** Graphical convenience methods for producing PDF files. + * + *

This implementation explicitly generates a very simple 8.5 inch by 11 inch one-page PDF consisting of graphical operations. + * Hopefully this class will no longer be needed in the future once Java comes with better PDF support. + */ + +public final strictfp class OurPDFWriter { + + /** The filename. */ + private final String filename; + + /** The page width (in terms of dots). */ + private final long width; + + /** The page height (in terms of dots). */ + private final long height; + + /** Latest color expressed as RGB (-1 if none has been explicitly set so far) */ + private int color = -1; + + /** Latest line style (0=normal, 1=bold, 2=dotted, 3=dashed) */ + private int line = 0; + + /** The buffer that will store the list of graphical operations issued so far (null if close() has been called successfully) */ + private ByteBuffer buf = new ByteBuffer(); + + /** Begin a blank PDF file with the given dots-per-inch and the given scale (the given file, if existed, will be overwritten) + * @throws IllegalArgumentException if dpi is less than 50 or is greater than 3000 + */ + public OurPDFWriter(String filename, int dpi, double scale) { + if (dpi<50 || dpi>3000) throw new IllegalArgumentException("The DPI must be between 50 and 3000"); + this.filename = filename; + width = dpi*8L + (dpi/2L); // "8.5 inches" + height = dpi*11L; // "11 inches" + // Write the default settings, and flip (0, 0) into the top-left corner of the page, scale the page, then leave 0.5" margin + buf.write("q\n" + "1 J\n" + "1 j\n" + "[] 0 d\n" + "1 w\n" + "1 0 0 -1 0 ").writes(height).write("cm\n"); + buf.writes(scale).write("0 0 ").writes(scale).writes(dpi/2.0).writes(dpi/2.0).write("cm\n"); + buf.write("1 0 0 1 ").writes(dpi/2.0).writes(dpi/2.0).write("cm\n"); + } + + /** Changes the color for subsequent graphical drawing. */ + public OurPDFWriter setColor(Color color) { + int rgb = color.getRGB() & 0xFFFFFF, r = (rgb>>16), g = (rgb>>8) & 0xFF, b = (rgb & 0xFF); + if (this.color == rgb) return this; else this.color = rgb; // no need to change + buf.writes(r/255.0).writes(g/255.0).writes(b/255.0).write("RG\n"); + buf.writes(r/255.0).writes(g/255.0).writes(b/255.0).write("rg\n"); + return this; + } + + /** Changes the line style to be normal. */ + public OurPDFWriter setNormalLine() { if (line!=0) buf.write("1 w [] 0 d\n"); line=0; return this; } + + /** Changes the line style to be bold. */ + public OurPDFWriter setBoldLine() { if (line!=1) buf.write("2 w [] 0 d\n"); line=1; return this; } + + /** Changes the line style to be dotted. */ + public OurPDFWriter setDottedLine() { if (line!=2) buf.write("1 w [1 3] 0 d\n"); line=2; return this; } + + /** Changes the line style to be dashed. */ + public OurPDFWriter setDashedLine() { if (line!=3) buf.write("1 w [6 3] 0 d\n"); line=3; return this; } + + /** Shifts the coordinate space by the given amount. */ + public OurPDFWriter shiftCoordinateSpace(int x, int y) { buf.write("1 0 0 1 ").writes(x).writes(y).write("cm\n"); return this; } + + /** Draws a line from (x1, y1) to (x2, y2). */ + public OurPDFWriter drawLine(int x1, int y1, int x2, int y2) { + buf.writes(x1).writes(y1).write("m ").writes(x2).writes(y2).write("l S\n"); return this; + } + + /** Draws a circle of the given radius, centered at (0, 0). */ + public OurPDFWriter drawCircle(int radius, boolean fillOrNot) { + double k = (0.55238 * radius); // Approximate a circle using 4 cubic bezier curves + buf.writes( radius).write("0 m "); + buf.writes( radius).writes( k).writes( k).writes( radius).write("0 ") .writes( radius).write("c "); + buf.writes( -k).writes( radius).writes(-radius).writes( k).writes(-radius).write("0 c "); + buf.writes(-radius).writes( -k).writes( -k).writes(-radius).write("0 ") .writes(-radius).write("c "); + buf.writes( k).writes(-radius).writes( radius).writes( -k).writes(radius) .write(fillOrNot ? "0 c f\n" : "0 c S\n"); + return this; + } + + /** Draws a shape. */ + public OurPDFWriter drawShape(Shape shape, boolean fillOrNot) { + if (shape instanceof Polygon) { + Polygon obj = (Polygon)shape; + for(int i = 0; i < obj.npoints; i++) buf.writes(obj.xpoints[i]).writes(obj.ypoints[i]).write(i==0 ? "m\n" : "l\n"); + buf.write("h\n"); + } else { + double moveX = 0, moveY = 0, nowX = 0, nowY = 0, pt[] = new double[6]; + for(PathIterator it = shape.getPathIterator(null); !it.isDone(); it.next()) switch(it.currentSegment(pt)) { + case PathIterator.SEG_MOVETO: + nowX = moveX = pt[0]; nowY = moveY = pt[1]; buf.writes(nowX).writes(nowY).write("m\n"); break; + case PathIterator.SEG_CLOSE: + nowX = moveX; nowY = moveY; buf.write("h\n"); break; + case PathIterator.SEG_LINETO: + nowX = pt[0]; nowY = pt[1]; buf.writes(nowX).writes(nowY).write("l\n"); break; + case PathIterator.SEG_CUBICTO: + nowX = pt[4]; nowY = pt[5]; + buf.writes(pt[0]).writes(pt[1]).writes(pt[2]).writes(pt[3]).writes(nowX).writes(nowY).write("c\n"); break; + case PathIterator.SEG_QUADTO: // Convert quadratic bezier into cubic bezier using de Casteljau algorithm + double px = nowX + (pt[0] - nowX)*(2.0/3.0), qx = px + (pt[2] - nowX)/3.0; + double py = nowY + (pt[1] - nowY)*(2.0/3.0), qy = py + (pt[3] - nowY)/3.0; + nowX = pt[2]; nowY = pt[3]; + buf.writes(px).writes(py).writes(qx).writes(qy).writes(nowX).writes(nowY).write("c\n"); break; + } + } + buf.write(fillOrNot ? "f\n" : "S\n"); + return this; + } + + /* PDF File Structure Summary: + * =========================== + * + * File should ideally start with the following 13 bytes: "%PDF-1.3" 10 "%" -127 10 10 + * Now comes one or more objects. + * One simple single-page arrangement is to have exactly 5 objects in this order: FONT, CONTENT, PAGE, PAGES, and CATALOG. + * + * Font Object (1 because FONT is #1) + * ================================== + * + * 1 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >> endobj\n\n + * + * Content Object (2 because CONTENT is #2) (${LEN} is the number of bytes in ${CONTENT} when compressed) + * ====================================================================================================== + * + * 2 0 obj << /Length ${LEN} /Filter /FlateDecode >> stream\r\n${CONTENT}endstream endobj\n\n + * + * Here is a quick summary of various PDF Graphics operations + * ========================================================== + * + * $x $y m --> begins a new path at the given coordinate + * $x $y l --> add the segment (LASTx,LASTy)..($x,$y) to the current path + * $cx $cy $x $y v --> add the bezier curve (LASTx,LASTy)..(LASTx,LASTy)..($cx,$cy)..($x,$y) to the current path + * $cx $cy $x $y y --> add the bezier curve (LASTx,LASTy)....($cx,$cy).....($x,$y)...($x,$y) to the current path + * $ax $ay $bx $by $x $y c --> add the bezier curve (LASTx,LASTy)....($ax,$ay)....($bx,$by)..($x,$y) to the current path + * h --> close the current subpath by straightline segment from current point to the start of this subpath + * $x $y $w $h re --> append a rectangle to the current path as a complete subpath with lower-left corner at $x $y + * + * S --> assuming we've just described a path, draw the path + * f --> assuming we've just described a path, fill the path + * B --> assuming we've just described a path, fill then draw the path + * + * q --> saves the current graphics state + * 1 J --> sets the round cap + * 1 j --> sets the round joint + * [] 0 d --> sets the dash pattern as SOLID + * [4 6] 0 d --> sets the dash pattern as 4 UNITS ON then 6 UNITS OFF + * 5 w --> sets the line width as 5 UNITS + * $a $b $c $d $e $f cm --> appends the given matrix; for example, [1 0 0 1 dx dy] means "translation to dx dy" + * $R $G $B RG --> sets the stroke color (where 0 <= $R <= 1, etc) + * $R $G $B rg --> sets the fill color (where 0 <= $R <= 1, etc) + * Q --> restores the current graphics state + * + * Page Object (3 because PAGE is #3) (4 beacuse PAGES is #4) (2 because CONTENTS is #2) + * ===================================================================================== + * + * 3 0 obj << /Type /Page /Parent 4 0 R /Contents 2 0 R >> endobj\n\n + * + * Pages Object (4 because PAGES is #4) (3 because PAGE is #3) (${W} is 8.5*DPI, ${H} is 11*DPI) (1 because FONT is #1) + * ==================================================================================================================== + * + * 4 0 obj << /Type /Pages /Count 1 /Kids [3 0 R] /MediaBox [0 0 ${W} ${H}] /Resources << /Font << /F1 1 0 R >> >> >> endobj\n\n + * + * Catalog Object (5 because CATALOG is #5) (4 because PAGES is #4) + * ================================================================ + * + * 5 0 obj << /Type /Catalog /Pages 4 0 R >> endobj\n\n + * + * END_OF_FILE format (assuming we have obj1 obj2 obj3 obj4 obj5 where obj5 is the "PDF Catalog") + * ============================================================================================== + * + * xref\n + * 0 6\n // 6 is because it's the number of objects plus 1 + * 0000000000 65535 f\r\n + * ${offset1} 00000 n\r\n // ${offset1} is byte offset of start of obj1, left-padded-with-zero until you get exactly 10 digits + * ${offset2} 00000 n\r\n // ${offset2} is byte offset of start of obj2, left-padded-with-zero until you get exactly 10 digits + * ${offset3} 00000 n\r\n // ${offset3} is byte offset of start of obj3, left-padded-with-zero until you get exactly 10 digits + * ${offset4} 00000 n\r\n // ${offset4} is byte offset of start of obj4, left-padded-with-zero until you get exactly 10 digits + * ${offset5} 00000 n\r\n // ${offset5} is byte offset of start of obj5, left-padded-with-zero until you get exactly 10 digits + * trailer\n + * <<\n + * /Size 6\n // 6 is because it's the number of objects plus 1 + * /Root 5 0 R\n // 5 is because it's the Catalog Object's object ID + * >>\n + * startxref\n + * ${xref}\n // $xref is the byte offset of the start of this entire "xref" paragraph + * %%EOF\n + */ + + /** Helper method that writes the given String to the output file, then return the number of bytes written. */ + private static int out(RandomAccessFile file, String string) throws IOException { + byte[] array = string.getBytes("UTF-8"); + file.write(array); + return array.length; + } + + /** Close and save this PDF object. */ + public void close() throws IOException { + if (buf == null) return; // already closed + final boolean compressOrNot = true; + RandomAccessFile out = null; + try { + String space = " "; // reserve 20 bytes for the file size, which is far far more than enough + final long fontID = 1, contentID = 2, pageID = 3, pagesID = 4, catalogID = 5, offset[] = new long[6]; + // Write %PDF-1.3, followed by a non-ASCII comment to force the PDF into binary mode + out = new RandomAccessFile(filename, "rw"); + out.setLength(0); + byte[] head = new byte[]{'%', 'P', 'D', 'F', '-', '1', '.', '3', 10, '%', -127, 10, 10}; + out.write(head); + long now = head.length; + // Font + offset[1] = now; + now += out(out, fontID + " 0 obj << /Type /Font /Subtype /Type1 /BaseFont" + + " /Helvetica /Encoding /WinAnsiEncoding >> endobj\n\n"); + // Content + offset[2] = now; + now += out(out, contentID + " 0 obj << /Length " + space + + (compressOrNot ? " /Filter /FlateDecode" : "") + " >> stream\r\n"); + buf.write("Q\n"); + final long ct = compressOrNot ? buf.dumpFlate(out) : buf.dump(out); + now += ct + out(out, "endstream endobj\n\n"); + // Page + offset[3] = now; + now += out(out, pageID + " 0 obj << /Type /Page /Parent " + pagesID + " 0 R /Contents " + contentID + " 0 R >> endobj\n\n"); + // Pages + offset[4] = now; + now += out(out, pagesID + " 0 obj << /Type /Pages /Count 1 /Kids [" + pageID + " 0 R] /MediaBox [0 0 " + + width + " " + height + "] /Resources << /Font << /F1 " + fontID + " 0 R >> >> >> endobj\n\n"); + // Catalog + offset[5] = now; + now += out(out, catalogID + " 0 obj << /Type /Catalog /Pages " + pagesID + " 0 R >> endobj\n\n"); + // Xref + String xr = "xref\n" + "0 " + offset.length + "\n"; + for(int i = 0; i < offset.length; i++) { + String txt = Long.toString(offset[i]); + while(txt.length() < 10) txt = "0" + txt; // must be exactly 10 characters long + if (i==0) xr = xr + txt + " 65535 f\r\n"; else xr = xr + txt + " 00000 n\r\n"; + } + // Trailer + xr = xr + "trailer\n<<\n/Size " + offset.length + "\n/Root " + catalogID + " 0 R\n>>\n" + "startxref\n" + now + "\n%%EOF\n"; + out(out, xr); + out.seek(offset[2]); + out(out, contentID + " 0 obj << /Length " + ct); // move the file pointer back so we can write out the real Content Size + out.close(); + buf = null; // only set buf to null if the file was saved successfully and no exception was thrown + } catch(Throwable ex) { + Util.close(out); + if (ex instanceof IOException) throw (IOException)ex; + if (ex instanceof OutOfMemoryError) throw new IOException("Out of memory trying to save the PDF file to " + filename); + if (ex instanceof StackOverflowError) throw new IOException("Out of memory trying to save the PDF file to " + filename); + throw new IOException("Error writing the PDF file to " + filename + " (" + ex + ")"); + } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurPNGWriter.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurPNGWriter.java new file mode 100644 index 00000000..c22bad08 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurPNGWriter.java @@ -0,0 +1,148 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.io.IOException; +import java.io.File; +import java.io.RandomAccessFile; +import java.awt.image.BufferedImage; +import javax.imageio.ImageIO; + +/** Graphical convenience methods for producing PNG files. */ + +public final strictfp class OurPNGWriter { + + /** The constructor is private, since this utility class never needs to be instantiated. */ + private OurPNGWriter () { } + + /** Writes the image as a PNG file with the given horizontal and vertical dots-per-inch. */ + public static void writePNG (BufferedImage image, String filename, double dpiX, double dpiY) throws IOException { + try { + ImageIO.write(image, "PNG", new File(filename)); // some versions of Java sometimes throws an exception during saving... + setDPI(filename, dpiX, dpiY); + } catch(Throwable ex) { + if (ex instanceof IOException) throw (IOException)ex; + if (ex instanceof StackOverflowError) throw new IOException("Out of memory trying to save the PNG file to " + filename); + if (ex instanceof OutOfMemoryError) throw new IOException("Out of memory trying to save the PNG file to " + filename); + throw new IOException("Error writing the PNG file to " + filename + " (" + ex + ")"); + } + } + + /* PNG consists of a "8 byte header" followed by one or more CHUNK... + * + * Each CHUNK: + * =========== + * 4 bytes: an integer N expressed with most-significant-byte first + * 4 bytes: Chunk Type + * N bytes: Chunk Data + * 4 bytes: Checksum (this checksum is computed over the Chunk Type and Chunk Data) + * + * Each PNG must contain an IDAT chunk (this is the actual pixels of the image) + * + * Each PNG may contain an optional pHYs chunk that describes the horizontal and vertical dots-per-meter information. + * If such a chunk exists, it must come before (though not necessarily immediately before) the IDAT chunk. + * + * pHYs CHUNK: + * =========== + * 4 bytes: 0 , 0 , 0 , 9 + * 4 bytes: 'p' , 'H' , 'Y' , 's' + * 4 bytes: horizontal dots per meter (most-significant-byte first) + * 4 bytes: vertical dots per meter (most-significant-byte first) + * 1 byte: 1 + * 4 bytes: Checksum + */ + + /** Modifies the given PNG file to have the given horizontal and vertical dots-per-inch. */ + private static void setDPI (String filename, double dpiX, double dpiY) throws IOException { + RandomAccessFile f = null; + try { + f = new RandomAccessFile(filename, "rw"); + for(long total=f.length(), pos=8; pos>>24, x>>>16, x>>>8, x, y>>>24, y>>>16, y>>>8, y, 1}); + } + + /** Write the given chunk into the given file; Note: data.length must be at least 4. */ + private static void writeChunk (RandomAccessFile file, int[] data) throws IOException { + int crc = (-1), len = data.length - 4; + file.write((len>>>24) & 255); file.write((len>>>16) & 255); file.write((len>>>8) & 255); file.write(len & 255); + for(int i=0; i>> 8); file.write(x & 255); } + crc = crc ^ (-1); + file.write((crc>>>24) & 255); file.write((crc>>>16) & 255); file.write((crc>>>8) & 255); file.write(crc & 255); + } + + /** This precomputed table makes it faster to calculate CRC; this is based on the suggestion in the PNG specification. */ + private static final int[] table = new int[] { + 0,1996959894,-301047508,-1727442502,124634137,1886057615,-379345611,-1637575261,249268274 + ,2044508324,-522852066,-1747789432,162941995,2125561021,-407360249,-1866523247,498536548,1789927666 + ,-205950648,-2067906082,450548861,1843258603,-187386543,-2083289657,325883990,1684777152,-43845254 + ,-1973040660,335633487,1661365465,-99664541,-1928851979,997073096,1281953886,-715111964,-1570279054 + ,1006888145,1258607687,-770865667,-1526024853,901097722,1119000684,-608450090,-1396901568,853044451 + ,1172266101,-589951537,-1412350631,651767980,1373503546,-925412992,-1076862698,565507253,1454621731 + ,-809855591,-1195530993,671266974,1594198024,-972236366,-1324619484,795835527,1483230225,-1050600021 + ,-1234817731,1994146192,31158534,-1731059524,-271249366,1907459465,112637215,-1614814043,-390540237 + ,2013776290,251722036,-1777751922,-519137256,2137656763,141376813,-1855689577,-429695999,1802195444 + ,476864866,-2056965928,-228458418,1812370925,453092731,-2113342271,-183516073,1706088902,314042704 + ,-1950435094,-54949764,1658658271,366619977,-1932296973,-69972891,1303535960,984961486,-1547960204 + ,-725929758,1256170817,1037604311,-1529756563,-740887301,1131014506,879679996,-1385723834,-631195440 + ,1141124467,855842277,-1442165665,-586318647,1342533948,654459306,-1106571248,-921952122,1466479909 + ,544179635,-1184443383,-832445281,1591671054,702138776,-1328506846,-942167884,1504918807,783551873 + ,-1212326853,-1061524307,-306674912,-1698712650,62317068,1957810842,-355121351,-1647151185,81470997 + ,1943803523,-480048366,-1805370492,225274430,2053790376,-468791541,-1828061283,167816743,2097651377 + ,-267414716,-2029476910,503444072,1762050814,-144550051,-2140837941,426522225,1852507879,-19653770 + ,-1982649376,282753626,1742555852,-105259153,-1900089351,397917763,1622183637,-690576408,-1580100738 + ,953729732,1340076626,-776247311,-1497606297,1068828381,1219638859,-670225446,-1358292148,906185462 + ,1090812512,-547295293,-1469587627,829329135,1181335161,-882789492,-1134132454,628085408,1382605366 + ,-871598187,-1156888829,570562233,1426400815,-977650754,-1296233688,733239954,1555261956,-1026031705 + ,-1244606671,752459403,1541320221,-1687895376,-328994266,1969922972,40735498,-1677130071,-351390145 + ,1913087877,83908371,-1782625662,-491226604,2075208622,213261112,-1831694693,-438977011,2094854071 + ,198958881,-2032938284,-237706686,1759359992,534414190,-2118248755,-155638181,1873836001,414664567 + ,-2012718362,-15766928,1711684554,285281116,-1889165569,-127750551,1634467795,376229701,-1609899400 + ,-686959890,1308918612,956543938,-1486412191,-799009033,1231636301,1047427035,-1362007478,-640263460 + ,1088359270,936918000,-1447252397,-558129467,1202900863,817233897,-1111625188,-893730166,1404277552 + ,615818150,-1160759803,-841546093,1423857449,601450431,-1285129682,-1000256840,1567103746,711928724 + ,-1274298825,-1022587231,1510334235,755167117 + }; +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurSyntaxDocument.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurSyntaxDocument.java new file mode 100644 index 00000000..f2b7c051 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurSyntaxDocument.java @@ -0,0 +1,259 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.awt.Color; +import java.awt.Font; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.List; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultEditorKit; +import javax.swing.text.DefaultStyledDocument; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.text.TabSet; +import javax.swing.text.TabStop; +import static edu.mit.csail.sdg.alloy4.OurConsole.style; + +/** Graphical syntax-highlighting StyledDocument. + * + *

Thread Safety: Can be called only by the AWT event thread + */ + +class OurSyntaxDocument extends DefaultStyledDocument { + + /** This ensures the class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** The "comment mode" at the start of each line (0 = no comment) (1 = block comment) (2 = javadoc comment) (-1 = unknown) */ + private final List comments = new ArrayList(); + + /** Whether syntax highlighting is currently enabled or not. */ + private boolean enabled = true; + + /** The current font name is. */ + private String font = "Monospaced"; + + /** The current font size. */ + private int fontSize = 14; + + /** The current tab size. */ + private int tabSize = 4; + + /** The list of font+color styles (eg. regular text, symbols, keywords, comments, etc). */ + private final List all = new ArrayList(); + + /** The character style for regular text. */ + private final MutableAttributeSet styleNormal = style(font, fontSize, false, Color.BLACK, 0); { all.add(styleNormal); } + + /** The character style for symbols. */ + private final MutableAttributeSet styleSymbol = style(font, fontSize, true, Color.BLACK, 0); { all.add(styleSymbol); } + + /** The character style for integer constants. */ + private final MutableAttributeSet styleNumber = style(font, fontSize, true, new Color(0xA80A0A), 0); { all.add(styleNumber); } + + /** The character style for keywords. */ + private final MutableAttributeSet styleKeyword = style(font, fontSize, true, new Color(0x1E1EA8), 0); { all.add(styleKeyword); } + + /** The character style for string literals. */ + private final MutableAttributeSet styleString = style(font, fontSize, false, new Color(0xA80AA8), 0); { all.add(styleString); } + + /** The character style for up-to-end-of-line-style comment. */ + private final MutableAttributeSet styleComment = style(font, fontSize, false, new Color(0x0A940A), 0); { all.add(styleComment); } + + /** The character style for non-javadoc-style block comment. */ + private final MutableAttributeSet styleBlock = style(font, fontSize, false, new Color(0x0A940A), 0); { all.add(styleBlock); } + + /** The character style for javadoc-style block comment. */ + private final MutableAttributeSet styleJavadoc = style(font, fontSize, true, new Color(0x0A940A), 0); { all.add(styleJavadoc); } + + /** The paragraph style for indentation. */ + private final MutableAttributeSet tabset = new SimpleAttributeSet(); + + /** This stores the currently recognized set of reserved keywords. */ + private static final String[] keywords = new String[] {"abstract", "all", "and", "as", "assert", "but", "check", "disj", + "disjoint", "else", "enum", "exactly", "exh", "exhaustive", "expect", "extends", "fact", "for", "fun", "iden", + "iff", "implies", "in", "Int", "int", "let", "lone", "module", "no", "none", "not", "one", "open", "or", "part", + "partition", "pred", "private", "run", "seq", "set", "sig", "some", "String", "sum", "this", "univ" + }; + + /** Returns true if array[start .. start+len-1] matches one of the reserved keyword. */ + private static final boolean do_keyword(String array, int start, int len) { + if (len >= 2 && len <= 10) for(int i = keywords.length - 1; i >= 0; i--) { + String str = keywords[i]; + if (str.length()==len) for(int j=0; ;j++) if (j==len) return true; else if (str.charAt(j) != array.charAt(start+j)) break; + } + return false; + } + + /** Returns true if "c" can be in the start or middle or end of an identifier. */ + private static final boolean do_iden(char c) { + return (c>='A' && c<='Z') || (c>='a' && c<='z') || c=='$' || (c>='0' && c<='9') || c=='_' || c=='\'' || c=='\"'; + } + + /** Constructor. */ + public OurSyntaxDocument(String fontName, int fontSize) { + putProperty(DefaultEditorKit.EndOfLineStringProperty, "\n"); + tabSize++; + do_setFont(fontName, fontSize, tabSize - 1); // assigns the given font, and also forces recomputation of the tab size + } + + /** Enables or disables syntax highlighting. */ + public final void do_enableSyntax (boolean flag) { + if (enabled == flag) return; else { enabled = flag; comments.clear(); } + if (flag) do_reapplyAll(); else setCharacterAttributes(0, getLength(), styleNormal, false); + } + + /** Return the number of lines represented by the current text (where partial line counts as a line). + *

For example: count("")==1, count("x")==1, count("x\n")==2, and count("x\ny")==2 + */ + public final int do_getLineCount() { + String txt = toString(); + for(int n=txt.length(), ans=1, i=0; ; i++) if (i>=n) return ans; else if (txt.charAt(i)=='\n') ans++; + } + + /** Return the starting offset of the given line (If "line" argument is too large, it will return the last line's starting offset) + *

For example: given "ab\ncd\n", start(0)==0, start(1)==3, start(2...)==6. Same thing when given "ab\ncd\ne". + */ + public final int do_getLineStartOffset(int line) { + String txt = toString(); + for(int n=txt.length(), ans=0, i=0, y=0; ; i++) if (i>=n || y>=line) return ans; else if (txt.charAt(i)=='\n') {ans=i+1; y++;} + } + + /** Return the line number that the offset is in (If "offset" argument is too large, it will just return do_getLineCount()-1). + *

For example: given "ab\ncd\n", offset(0..2)==0, offset(3..5)==1, offset(6..)==2. Same thing when given "ab\ncd\ne". + */ + public final int do_getLineOfOffset(int offset) { + String txt = toString(); + for(int n=txt.length(), ans=0, i=0; ; i++) if (i>=n || i>=offset) return ans; else if (txt.charAt(i)=='\n') ans++; + } + + /** This method is called by Swing to insert a String into this document. + * We intentionally ignore "attr" and instead use our own coloring. + */ + @Override public void insertString(int offset, String string, AttributeSet attr) throws BadLocationException { + if (string.indexOf('\r')>=0) string = Util.convertLineBreak(string); // we don't want '\r' + if (!enabled) { super.insertString(offset, string, styleNormal); return; } + int startLine = do_getLineOfOffset(offset); + for(int i = 0; i < string.length(); i++) { // For each inserted '\n' we need to shift the values in "comments" array down + if (string.charAt(i)=='\n') { if (startLine < comments.size()-1) comments.add(startLine+1, -1); } + } + super.insertString(offset, string, styleNormal); + try { do_update(startLine); } catch(Exception ex) { comments.clear(); } + } + + /** This method is called by Swing to delete text from this document. */ + @Override public void remove(int offset, int length) throws BadLocationException { + if (!enabled) { super.remove(offset, length); return; } + int i = 0, startLine = do_getLineOfOffset(offset); + for(String oldText = toString(); i 0) this.remove(offset, length); + if (string != null && string.length() > 0) this.insertString(offset, string, styleNormal); + } + + /** Reapply styles assuming the given line has just been modified */ + private final void do_update(int line) throws BadLocationException { + String content = toString(); + int lineCount = do_getLineCount(); + while(line>0 && (line>=comments.size() || comments.get(line)<0)) line--; // "-1" in comments array are always contiguous + int comment = do_reapply(line==0 ? 0 : comments.get(line), content, line); + for (line++; line < lineCount; line++) { // update each subsequent line until it already starts with its expected comment mode + if (line < comments.size() && comments.get(line) == comment) break; else comment = do_reapply(comment, content, line); + } + } + + /** Re-color the given line assuming it starts with a given comment mode, then return the comment mode for start of next line. */ + private final int do_reapply(int comment, final String txt, final int line) { + while (line >= comments.size()) comments.add(-1); // enlarge array if needed + comments.set(line, comment); // record the fact that this line starts with the given comment mode + for(int n = txt.length(), i = do_getLineStartOffset(line); i < n;) { + final int oldi = i; + final char c = txt.charAt(i); + if (c=='\n') break; + if (comment==0 && c=='/' && i0) { + AttributeSet style = (comment==1 ? styleBlock : styleJavadoc); + while(i='0' && c<='9') ? styleNumber : (do_keyword(txt, oldi, i-oldi) ? styleKeyword : styleNormal); + setCharacterAttributes(oldi, i-oldi, style, false); + } else { + for(i++; i 100) tabSize = 100; + if (fontName.equals(this.font) && fontSize == this.fontSize && tabSize == this.tabSize) return; + this.font = fontName; + this.fontSize = fontSize; + this.tabSize = tabSize; + for(MutableAttributeSet s: all) { StyleConstants.setFontFamily(s, fontName); StyleConstants.setFontSize(s, fontSize); } + do_reapplyAll(); + BufferedImage im = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB); // this is used to derive the tab width + int gap = tabSize * im.createGraphics().getFontMetrics(new Font(fontName, Font.PLAIN, fontSize)).charWidth('X'); + TabStop[] pos = new TabStop[100]; + for(int i=0; i<100; i++) { pos[i] = new TabStop(i*gap + gap); } + StyleConstants.setTabSet(tabset, new TabSet(pos)); + setParagraphAttributes(0, getLength(), tabset, false); + } + + /** Overriden to return the full text of the document. + * @return the entire text + */ + @Override public String toString() { + try { return getText(0, getLength()); } catch(BadLocationException ex) { return ""; } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurSyntaxUndoableDocument.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurSyntaxUndoableDocument.java new file mode 100644 index 00000000..a489ae38 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurSyntaxUndoableDocument.java @@ -0,0 +1,139 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.SimpleAttributeSet; +import static java.lang.System.arraycopy; + +/** Graphical syntax-highlighting StyledDocument with undo+redo support. + * + *

Thread Safety: Can be called only by the AWT event thread + */ + +final class OurSyntaxUndoableDocument extends OurSyntaxDocument { + + /** This ensures the class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** The maximum number of UNDO actions we want to keep. */ + private static final int MAXUNDO = 100; + + /** For each i = 0..now-1, insert[i] means whether the i-th operation was an insertion or not. */ + private boolean insert[] = new boolean[MAXUNDO]; + + /** For each i = 0..now-1, text[i] means the i-th operation was an insertion/deletion of that text. */ + private String text[] = new String[MAXUNDO]; + + /** For each i = 0..now-1, where[i] means the i-th operation was an insertion/deletion at that offset. */ + private int where[] = new int[MAXUNDO]; + + /** The number of undoable operations currently remembered in insert[], text[], and where[]. */ + private int now; + + /** The number of undoable opeartions that are currently "undone". */ + private int undone; + + /** Caches a default AttributeSet (just so that we don't pass null as a AttributeSet. */ + private final AttributeSet attr = new SimpleAttributeSet(); + + /** Constructor. */ + public OurSyntaxUndoableDocument(String fontName, int fontSize) { super(fontName, fontSize); } + + /** Clear the undo history. */ + public void do_clearUndo() { now = undone = 0; } + + /** Returns true if we can perform undo right now. */ + public boolean do_canUndo() { return undone < now; } + + /** Returns true if we can perform redo right now. */ + public boolean do_canRedo() { return undone > 0 ; } + + /** Perform undo then return where the new desired caret location should be (or return -1 if undo is not possible right now) */ + public int do_undo() { + if (undone >= now) return -1; else undone++; + boolean insert = this.insert[now - undone]; + String text = this.text[now - undone]; + int where = this.where[now - undone]; + try { + if (insert) { super.remove(where, text.length()); return where; } + else { super.insertString(where, text, attr); return where + text.length(); } + } catch(BadLocationException ex) { return -1; } + } + + /** Perform redo then return where the new desired caret location should be (or return -1 if redo is not possible right now) */ + public int do_redo() { + if (undone <= 0) return -1; + boolean insert = this.insert[now - undone]; + String text = this.text[now - undone]; + int where = this.where[now - undone]; + undone--; + try { + if (insert) { super.insertString(where, text, attr); return where + text.length(); } + else { super.remove(where, text.length()); return where; } + } catch(BadLocationException ex) { return -1; } + } + + /** This method is called by Swing to insert a String into this document. */ + @Override public void insertString(int offset, String string, AttributeSet attr) throws BadLocationException { + if (string.length()==0) return; else if (string.indexOf('\r')>=0) string = Util.convertLineBreak(string); // we don't want '\r' + if (undone > 0) { now = now - undone; undone = 0; } // clear the REDO entries + super.insertString(offset, string, attr); + if (now > 0 && insert[now-1]) { // merge with last edit if possible + if (where[now-1] == offset - text[now-1].length()) { text[now - 1] += string; return; } + } + if (now >= MAXUNDO) { + arraycopy(insert, 1, insert, 0, MAXUNDO-1); + arraycopy(text, 1, text, 0, MAXUNDO-1); + arraycopy(where, 1, where, 0, MAXUNDO-1); + now--; + } + insert[now]=true; text[now]=string; where[now]=offset; now++; + } + + /** This method is called by Swing to delete text from this document. */ + @Override public void remove(int offset, int length) throws BadLocationException { + if (length==0) return; + if (undone > 0) { now = now - undone; undone = 0; } // clear the REDO entries + String string = toString().substring(offset, offset+length); + super.remove(offset, length); + if (now > 0 && !insert[now-1]) { // merge with last edit if possible + if (where[now-1] == offset) { text[now-1] += string; return; } + if (where[now-1] == offset+length) { where[now-1] = offset; text[now-1] = string + text[now-1]; return; } + } + if (now >= MAXUNDO) { + arraycopy(insert, 1, insert, 0, MAXUNDO-1); + arraycopy(text, 1, text, 0, MAXUNDO-1); + arraycopy(where, 1, where, 0, MAXUNDO-1); + now--; + } + insert[now]=false; text[now]=string; where[now]=offset; now++; + } + + /** This method is called by Swing to replace text in this document. */ + @Override public void replace(int offset, int length, String string, AttributeSet attrs) throws BadLocationException { + if (length > 0) this.remove(offset, length); + if (string != null && string.length() > 0) this.insertString(offset, string, this.attr); + } + + /** Overriden to return the full text of the document. + * @return the entire text + */ + @Override public String toString() { + try { return getText(0, getLength()); } catch(BadLocationException ex) { return ""; } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurSyntaxWidget.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurSyntaxWidget.java new file mode 100644 index 00000000..8dee1630 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurSyntaxWidget.java @@ -0,0 +1,299 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.io.File; +import java.util.Collection; +import javax.swing.AbstractAction; +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import javax.swing.JTextPane; +import javax.swing.KeyStroke; +import javax.swing.border.EmptyBorder; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.AbstractDocument; +import javax.swing.text.BoxView; +import javax.swing.text.Document; +import javax.swing.text.Element; +import javax.swing.text.StyledEditorKit; +import javax.swing.text.View; +import javax.swing.text.ViewFactory; +import edu.mit.csail.sdg.alloy4.Listener.Event; + +/** Graphical syntax-highlighting editor. + * + *

Thread Safety: Can be called only by the AWT event thread + */ + +public final class OurSyntaxWidget { + + /** The current list of listeners; possible events are { STATUS_CHANGE, FOCUSED, CTRL_PAGE_UP, CTRL_PAGE_DOWN, CARET_MOVED }. */ + public final Listeners listeners = new Listeners(); + + /** The JScrollPane containing everything. */ + private final JScrollPane component = OurUtil.make(new JScrollPane(), new EmptyBorder(0, 0, 0, 0)); + + /** This is an optional JComponent annotation. */ + public final JComponent obj1; + + /** This is an optional JComponent annotation. */ + public final JComponent obj2; + + /** The underlying StyledDocument being displayed (changes will trigger the STATUS_CHANGE event) */ + private final OurSyntaxUndoableDocument doc = new OurSyntaxUndoableDocument("Monospaced", 14); + + /** The underlying JTextPane being displayed. */ + private final JTextPane pane = OurAntiAlias.pane(Color.BLACK, Color.WHITE, new EmptyBorder(1, 1, 1, 1)); + + /** The filename for this JTextPane (changes will trigger the STATUS_CHANGE event) */ + private String filename = ""; + + /** Whether this JTextPane has been modified since last load/save (changes will trigger the STATUS_CHANGE event) */ + private boolean modified; + + /** Whether this JTextPane corresponds to an existing disk file (changes will trigger the STATUS_CHANGE event) */ + private boolean isFile; + + /** Caches the most recent background painter if nonnull. */ + private OurHighlighter painter; + + /** Constructs a syntax-highlighting widget. */ + public OurSyntaxWidget() { this(true, "", "Monospaced", 14, 4, null, null); } + + /** Constructs a syntax-highlighting widget. */ + @SuppressWarnings("serial") + public OurSyntaxWidget + (boolean enableSyntax, String text, String fontName, int fontSize, int tabSize, JComponent obj1, JComponent obj2) { + this.obj1 = obj1; + this.obj2 = obj2; + final OurSyntaxWidget me = this; + final ViewFactory defaultFactory = (new StyledEditorKit()).getViewFactory(); + doc.do_enableSyntax(enableSyntax); + doc.do_setFont(fontName, fontSize, tabSize); + pane.setEditorKit(new StyledEditorKit() { // Prevents line-wrapping up to width=30000, and tells it to use our Document obj + @Override public Document createDefaultDocument() { return doc; } + @Override public ViewFactory getViewFactory() { + return new ViewFactory() { + public View create(Element x) { + if (!AbstractDocument.SectionElementName.equals(x.getName())) return defaultFactory.create(x); + return new BoxView(x, View.Y_AXIS) { // 30000 is a good width to use here; value > 32767 appears to cause errors + @Override public final float getMinimumSpan(int axis) { return super.getPreferredSpan(axis); } + @Override public final void layout(int w, int h) { try {super.layout(30000, h);} catch(Throwable ex) {} } + }; + } + }; + } + }); + if (text.length()>0) { pane.setText(text); pane.setCaretPosition(0); } + doc.do_clearUndo(); + pane.getActionMap().put("alloy_copy", new AbstractAction("alloy_copy") { + public void actionPerformed(ActionEvent e) { pane.copy(); } + }); + pane.getActionMap().put("alloy_cut", new AbstractAction("alloy_cut") { + public void actionPerformed(ActionEvent e) { pane.cut(); } + }); + pane.getActionMap().put("alloy_paste", new AbstractAction("alloy_paste") { + public void actionPerformed(ActionEvent e) { pane.paste(); } + }); + pane.getActionMap().put("alloy_ctrl_pageup", new AbstractAction("alloy_ctrl_pageup") { + public void actionPerformed(ActionEvent e) { listeners.fire(me, Event.CTRL_PAGE_UP); } + }); + pane.getActionMap().put("alloy_ctrl_pagedown", new AbstractAction("alloy_ctrl_pagedown") { + public void actionPerformed(ActionEvent e) { listeners.fire(me, Event.CTRL_PAGE_DOWN); } + }); + pane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK), "alloy_copy"); + pane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_MASK), "alloy_cut"); + pane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK), "alloy_paste"); + pane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, InputEvent.CTRL_MASK), "alloy_copy"); + pane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, InputEvent.SHIFT_MASK), "alloy_paste"); + pane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, InputEvent.SHIFT_MASK), "alloy_cut"); + pane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, InputEvent.CTRL_MASK), "alloy_ctrl_pageup"); + pane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, InputEvent.CTRL_MASK), "alloy_ctrl_pagedown"); + doc.addDocumentListener(new DocumentListener() { + public void insertUpdate(DocumentEvent e) { modified=true; listeners.fire(me, Event.STATUS_CHANGE); } + public void removeUpdate(DocumentEvent e) { modified=true; listeners.fire(me, Event.STATUS_CHANGE); } + public void changedUpdate(DocumentEvent e) { } + }); + pane.addFocusListener(new FocusAdapter() { + @Override public void focusGained(FocusEvent e) { listeners.fire(me, Event.FOCUSED); } + }); + pane.addCaretListener(new CaretListener() { + public void caretUpdate(CaretEvent e) { listeners.fire(me, Event.CARET_MOVED); } + }); + component.addFocusListener(new FocusAdapter() { + @Override public void focusGained(FocusEvent e) { pane.requestFocusInWindow(); } + }); + component.setFocusable(false); + component.setMinimumSize(new Dimension(50, 50)); + component.setViewportView(pane); + modified = false; + } + + /** Add this object into the given container. */ + public void addTo(JComponent newParent, Object constraint) { newParent.add(component, constraint); } + + /** Returns true if this textbox is currently shaded. */ + boolean shaded() { return pane.getHighlighter().getHighlights().length > 0; } + + /** Remove all shading. */ + void clearShade() { pane.getHighlighter().removeAllHighlights(); } + + /** Shade the range of text from start (inclusive) to end (exclusive). */ + void shade(Color color, int start, int end) { + int c = color.getRGB() & 0xFFFFFF; + if (painter==null || (painter.color.getRGB() & 0xFFFFFF)!=c) painter = new OurHighlighter(color); + try { pane.getHighlighter().addHighlight(start, end, painter); } catch(Throwable ex) { } // exception is okay + } + + /** Returns the filename. */ + public String getFilename() { return filename; } + + /** Returns the modified-or-not flag. */ + public boolean modified() { return modified; } + + /** Returns whether this textarea is based on an actual disk file. */ + public boolean isFile() { return isFile; } + + /** Changes the font name, font size, and tab size for the document. */ + void setFont(String fontName, int fontSize, int tabSize) { if (doc!=null) doc.do_setFont(fontName, fontSize, tabSize); } + + /** Enables or disables syntax highlighting. */ + void enableSyntax(boolean flag) { if (doc!=null) doc.do_enableSyntax(flag); } + + /** Return the number of lines represented by the current text (where partial line counts as a line). + *

For example: count("")==1, count("x")==1, count("x\n")==2, and count("x\ny")==2 + */ + public int getLineCount() { return doc.do_getLineCount(); } + + /** Return the starting offset of the given line (If "line" argument is too large, it will return the last line's starting offset) + *

For example: given "ab\ncd\n", start(0)==0, start(1)==3, start(2...)==6. Same thing when given "ab\ncd\ne". + */ + public int getLineStartOffset(int line) { return doc.do_getLineStartOffset(line); } + + /** Return the line number that the offset is in (If "offset" argument is too large, it will just return do_getLineCount()-1). + *

For example: given "ab\ncd\n", offset(0..2)==0, offset(3..5)==1, offset(6..)==2. Same thing when given "ab\ncd\ne". + */ + public int getLineOfOffset(int offset) { return doc.do_getLineOfOffset(offset); } + + /** Returns true if we can perform undo right now. */ + public boolean canUndo() { return doc.do_canUndo(); } + + /** Returns true if we can perform redo right now. */ + public boolean canRedo() { return doc.do_canRedo(); } + + /** Perform undo if possible. */ + public void undo() { int i = doc.do_undo(); if (i>=0 && i<=pane.getText().length()) moveCaret(i, i); } + + /** Perform redo if possible. */ + public void redo() { int i = doc.do_redo(); if (i>=0 && i<=pane.getText().length()) moveCaret(i, i); } + + /** Clear the undo history. */ + public void clearUndo() { doc.do_clearUndo(); } + + /** Return the caret position. */ + public int getCaret() { return pane.getCaretPosition(); } + + /** Select the content between offset a and offset b, and move the caret to offset b. */ + public void moveCaret(int a, int b) { + try { pane.setCaretPosition(a); pane.moveCaretPosition(b); } catch(Exception ex) { if (a!=0 || b!=0) moveCaret(0, 0); } + } + + /** Return the entire text. */ + public String getText() { return pane.getText(); } + + /** Change the entire text to the given text (and sets the modified flag) */ + public void setText(String text) { pane.setText(text); } + + /** Copy the current selection into the clipboard. */ + public void copy() { pane.copy(); } + + /** Cut the current selection into the clipboard. */ + public void cut() { pane.cut(); } + + /** Paste the current clipboard content. */ + public void paste() { pane.paste(); } + + /** Discard all; if askUser is true, we'll ask the user whether to save it or not if the modified==true. + * @return true if this text buffer is now a fresh empty text buffer + */ + boolean discard(boolean askUser, Collection bannedNames) { + char ans = (!modified || !askUser) ? 'd' : OurDialog.askSaveDiscardCancel("The file \"" + filename + "\""); + if (ans=='c' || (ans=='s' && save(false, bannedNames)==false)) return false; + for(int i=1; ;i++) if (!bannedNames.contains(filename = Util.canon("Untitled " + i + ".als"))) break; + pane.setText(""); clearUndo(); modified=false; isFile=false; listeners.fire(this, Event.STATUS_CHANGE); + return true; + } + + /** Discard current content then read the given file; return true if the entire operation succeeds. */ + boolean load(String filename) { + String x; + try { + x = Util.readAll(filename); + } catch(Throwable ex) { OurDialog.alert("Error reading the file \"" + filename + "\""); return false; } + pane.setText(x); moveCaret(0,0); clearUndo(); modified=false; isFile=true; this.filename=filename; + listeners.fire(this, Event.STATUS_CHANGE); + return true; + } + + /** Discard (after confirming with the user) current content then reread from disk file. */ + void reload() { + if (!isFile) return; // "untitled" text buffer does not have a on-disk file to refresh from + if (modified && !OurDialog.yesno("You have unsaved changes to \"" + filename + "\"\nAre you sure you wish to discard " + + "your changes and reload it from disk?", "Discard your changes", "Cancel this operation")) return; + String t; + try { t=Util.readAll(filename); } catch(Throwable ex) { OurDialog.alert("Cannot read \""+filename+"\""); return; } + if (modified==false && t.equals(pane.getText())) return; // no text change nor status change + int c=pane.getCaretPosition(); pane.setText(t); moveCaret(c,c); modified=false; listeners.fire(this, Event.STATUS_CHANGE); + } + + /** Save the current tab content to the file system, and return true if successful. */ + boolean saveAs(String filename, Collection bannedNames) { + filename = Util.canon(filename); + if (bannedNames.contains(filename)) { + OurDialog.alert("The filename \""+filename+"\"\nis already open in another tab."); + return false; + } + try { Util.writeAll(filename, pane.getText()); } + catch (Throwable e) { OurDialog.alert("Error writing to the file \""+filename+"\""); return false; } + this.filename = Util.canon(filename); // a new file's canonical name may change + modified=false; isFile=true; listeners.fire(this, Event.STATUS_CHANGE); return true; + } + + /** Save the current tab content to the file system and return true if successful. + * @param alwaysPickNewName - if true, it will always pop up a File Selection dialog box to ask for the filename + */ + boolean save(boolean alwaysPickNewName, Collection bannedNames) { + String n = this.filename; + if (alwaysPickNewName || isFile==false || n.startsWith(Util.jarPrefix())) { + File f = OurDialog.askFile(false, null, ".als", ".als files"); if (f==null) return false; + n = Util.canon(f.getPath()); if (f.exists() && !OurDialog.askOverwrite(n)) return false; + } + if (saveAs(n, bannedNames)) {Util.setCurrentDirectory(new File(filename).getParentFile()); return true;} else return false; + } + + /** Transfer focus to this component. */ + public void requestFocusInWindow() { if (pane!=null) pane.requestFocusInWindow(); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurTabbedSyntaxWidget.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurTabbedSyntaxWidget.java new file mode 100644 index 00000000..202887ca --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurTabbedSyntaxWidget.java @@ -0,0 +1,298 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Font; +import java.awt.Rectangle; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.LinkedHashMap; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import edu.mit.csail.sdg.alloy4.Listener.Event; + +/** Graphical multi-tabbed syntax-highlighting editor. + * + *

Thread Safety: Can be called only by the AWT event thread. + * + *

Invariant: each tab has distinct file name. + */ + +public final class OurTabbedSyntaxWidget { + + /** The current list of listeners; possible events are { STATUS_CHANGE, FOCUSED, CARET_MOVED }. */ + public final Listeners listeners = new Listeners(); + + /** The JScrollPane containing everything. */ + private final JPanel component = OurUtil.make(new JPanel()); + + /** Background color for the list of tabs. */ + private static final Color GRAY = new Color(0.9f, 0.9f, 0.9f); + + /** Background color for an inactive tab. */ + private static final Color INACTIVE = new Color(0.8f, 0.8f, 0.8f); + + /** Background color for a inactive and highlighted tab. */ + private static final Color INACTIVE_HIGHLIGHTED = new Color(0.7f, 0.5f, 0.5f); + + /** Foreground color for a active and highlighted tab. */ + private static final Color ACTIVE_HIGHLIGHTED = new Color(0.5f, 0.2f, 0.2f); + + /** Default border color for each tab. */ + private static final Color BORDER = Color.LIGHT_GRAY; + + /** The font name to use in the JTextArea */ + private String fontName = "Monospaced"; + + /** The font size to use in the JTextArea */ + private int fontSize = 14; + + /** The tabsize to use in the JTextArea */ + private int tabSize = 4; + + /** Whether syntax highlighting is current enabled or not. */ + private boolean syntaxHighlighting; + + /** The list of clickable tabs. */ + private final JPanel tabBar; + + /** The scrollPane that wraps around this.tabbar */ + private final JScrollPane tabBarScroller; + + /** The list of tabs. */ + private final List tabs = new ArrayList(); + + /** The currently selected tab from 0 to list.size()-1 (This value must be 0 if there are no tabs) */ + private int me = 0; + + /** This object receives messages from sub-JTextPane objects. */ + private final Listener listener = new Listener() { + public Object do_action(Object sender, Event e) { + final OurTabbedSyntaxWidget me = OurTabbedSyntaxWidget.this; + if (sender instanceof OurSyntaxWidget) switch(e) { + case FOCUSED: listeners.fire(me, e); break; + case CARET_MOVED: listeners.fire(me, Event.STATUS_CHANGE); break; + case CTRL_PAGE_UP: prev(); break; + case CTRL_PAGE_DOWN: next(); break; + case STATUS_CHANGE: + clearShade(); + OurSyntaxWidget t = (OurSyntaxWidget)sender; + String n = t.getFilename(); + t.obj1.setToolTipText(n); + int i = n.lastIndexOf('/'); if (i >= 0) n = n.substring(i + 1); + i = n.lastIndexOf('\\'); if (i >= 0) n = n.substring(i + 1); + i = n.lastIndexOf('.'); if (i >= 0) n = n.substring(0, i); + if (n.length() > 14) { n = n.substring(0, 14) + "..."; } + if (t.obj1 instanceof JLabel) { ((JLabel)(t.obj1)).setText(" " + n + (t.modified() ? " * " : " ")); } + listeners.fire(me, Event.STATUS_CHANGE); + break; + } + return true; + } + public Object do_action(Object sender, Event e, Object arg) { return true; } + }; + + /** Constructs a tabbed editor pane. */ + public OurTabbedSyntaxWidget(String fontName, int fontSize, int tabSize) { + component.setBorder(null); + component.setLayout(new BorderLayout()); + JPanel glue = OurUtil.makeHB(new Object[]{null}); + glue.setBorder(new OurBorder(null, null, BORDER, null)); + tabBar = OurUtil.makeHB(glue); + if (!Util.onMac()) { tabBar.setOpaque(true); tabBar.setBackground(GRAY); } + tabBarScroller = new JScrollPane(tabBar, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + tabBarScroller.setFocusable(false); + tabBarScroller.setBorder(null); + setFont(fontName, fontSize, tabSize); + newtab(null); + tabBarScroller.addComponentListener(new ComponentListener() { + public final void componentResized(ComponentEvent e) { select(me); } + public final void componentMoved(ComponentEvent e) { select(me); } + public final void componentShown(ComponentEvent e) { select(me); } + public final void componentHidden(ComponentEvent e) { } + }); + } + + /** Add this object into the given container. */ + public void addTo(JComponent newParent, Object constraint) { newParent.add(component, constraint); } + + /** Adjusts the background and foreground of all labels. */ + private void adjustLabelColor() { + for(int i=0; i= tabs.size()) return; else { me=i; component.revalidate(); adjustLabelColor(); component.removeAll(); } + if (tabs.size() > 1) component.add(tabBarScroller, BorderLayout.NORTH); + tabs.get(me).addTo(component, BorderLayout.CENTER); + component.repaint(); + tabs.get(me).requestFocusInWindow(); + tabBar.scrollRectToVisible(new Rectangle(0,0,0,0)); // Forces recalculation + tabBar.scrollRectToVisible(new Rectangle(tabs.get(me).obj2.getX(), 0, tabs.get(me).obj2.getWidth()+200, 1)); + listeners.fire(this, Event.STATUS_CHANGE); + } + + /** Refresh all tabs. */ + public void reloadAll() { for(OurSyntaxWidget t: tabs) t.reload(); } + + /** Return the list of all filenames except the filename in the i-th tab. */ + private List getAllNamesExcept(int i) { + ArrayList ans = new ArrayList(); + for(int x=0; ;x++) if (x == tabs.size()) return ans; else if (x != i) ans.add(tabs.get(x).getFilename()); + } + + /** Save the current tab content to the file system. + * @param alwaysPickNewName - if true, it will always pop up a File Selection dialog box to ask for the filename + * @return null if an error occurred (otherwise, return the filename) + */ + public String save(boolean alwaysPickNewName) { + if (me < 0 || me >= tabs.size() || !tabs.get(me).save(alwaysPickNewName, getAllNamesExcept(me))) return null; + return tabs.get(me).getFilename(); + } + + /** Close the i-th tab (if there are no more tabs afterwards, we'll create a new empty tab). + * + *

If the text editor content is not modified since the last save, then return true; otherwise, ask the user. + *

If the user says to save it, we will attempt to save it, then return true iff the save succeeded. + *

If the user says to discard it, this method returns true. + *

If the user says to cancel it, this method returns false (and the original tab and its contents will not be harmed). + */ + private boolean close(int i) { + clearShade(); + if (i<0 || i>=tabs.size()) return true; else if (!tabs.get(i).discard(true, getAllNamesExcept(i))) return false; + if (tabs.size() > 1) { tabBar.remove(i); tabs.remove(i); if (me >= tabs.size()) me = tabs.size() - 1; } + select(me); + return true; + } + + /** Close the current tab (then create a new empty tab if there were no tabs remaining) */ + public void close() { close(me); } + + /** Close every tab then create a new empty tab; returns true iff success. */ + public boolean closeAll() { + for(int i=tabs.size()-1; i>=0; i--) if (tabs.get(i).modified()==false) close(i); // first close all the unmodified files + for(int i=tabs.size()-1; i>=0; i--) if (close(i)==false) return false; // then attempt to close modified files one-by-one + return true; + } + + /** Returns the number of tabs. */ + public int count() { return tabs.size(); } + + /** Return a modifiable map from each filename to its text content (Note: changes to the map does NOT affect this object) */ + public Map takeSnapshot() { + Map map = new LinkedHashMap(); + for(OurSyntaxWidget t: tabs) { map.put(t.getFilename(), t.getText()); } + return map; + } + + /** Returns the list of filenames corresponding to each text buffer. */ + public List getFilenames() { return getAllNamesExcept(-1); } + + /** Changes the font name, font size, and tabsize of every text buffer. */ + public void setFont(String name, int size, int tabSize) { + fontName=name; fontSize=size; this.tabSize=tabSize; for(OurSyntaxWidget t: tabs) t.setFont(name, size, tabSize); + } + + /** Enables or disables syntax highlighting. */ + public void enableSyntax(boolean flag) { syntaxHighlighting=flag; for(OurSyntaxWidget t: tabs) t.enableSyntax(flag); } + + /** Returns the JTextArea of the current text buffer. */ + public OurSyntaxWidget get() { return (me>=0 && me=0 && i=2) select(me==0 ? tabs.size()-1 : (me-1)); } + + /** Switches to the next tab. */ + public void next() { if (tabs.size()>=2) select(me==tabs.size()-1 ? 0 : (me+1)); } + + /** Create a new tab with the given filename (if filename==null, we'll create a blank tab instead) + *

If a text buffer with that filename already exists, we will just switch to it; else we'll read that file into a new tab. + * @return false iff an error occurred + */ + public boolean newtab(String filename) { + if (filename!=null) { + filename = Util.canon(filename); + for(int i=0; i=0; i--) if (!tabs.get(i).isFile() && tabs.get(i).getText().length()==0) { + tabs.get(i).discard(false, getFilenames()); close(i); break; // Remove the rightmost untitled empty tab + } + } + select(tabs.size() - 1); // Must call this to switch to the new tab; and it will fire STATUS_CHANGE message which is important + return true; + } + + /** Highlights the text editor, based on the location information in the set of Pos objects. */ + public void shade(Iterable set, Color color, boolean clearOldHighlightsFirst) { + if (clearOldHighlightsFirst) clearShade(); + OurSyntaxWidget text = null; + int c = 0, d; + for(Pos p: set) if (p!=null && p.filename.length()>0 && p.y>0 && p.x>0 && newtab(p.filename)) { + text = get(); + c = text.getLineStartOffset(p.y-1) + p.x - 1; + d = text.getLineStartOffset(p.y2-1) + p.x2 - 1; + text.shade(color, c, d+1); + } + if (text!=null) { text.moveCaret(0, 0); text.moveCaret(c, c); } // Move to 0 ensures we'll scroll to the highlighted section + get().requestFocusInWindow(); + adjustLabelColor(); + listeners.fire(this, Event.STATUS_CHANGE); + } + + /** Highlights the text editor, based on the location information in the Pos object. */ + public void shade(Pos pos) { shade(Util.asList(pos), new Color(0.9f, 0.4f, 0.4f), true); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurTree.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurTree.java new file mode 100644 index 00000000..26f959bb --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurTree.java @@ -0,0 +1,164 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.util.IdentityHashMap; +import java.util.List; +import javax.swing.JLabel; +import javax.swing.JTree; +import javax.swing.UIManager; +import javax.swing.border.EmptyBorder; +import javax.swing.event.TreeModelListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; +import edu.mit.csail.sdg.alloy4.OurUtil; + +/** Graphical tree. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public abstract class OurTree extends JTree { + + /** The current list of listeners; whenever a node X is selected we'll send (Event.CLICK, X) to each listener. */ + public final Listeners listeners = new Listeners(); + + /** Custom TreeCellRenderer to print the tree nodes better. (The idea of using JLabel is inspired by DefaultTreeCellRenderer) */ + private final class OurTreeRenderer extends JLabel implements TreeCellRenderer { + /** This ensures the class can be serialized reliably. */ + private static final long serialVersionUID = 0; + /** This stores the height of one line of text. */ + private int height; + /** If preferredHeight > 0, then preferredWidth is the desired width for the current object being drawn. */ + private int preferredWidth = 0; + /** If preferredHeight > 0, then preferredHeight is the desired height for the current object being drawn. */ + private int preferredHeight = 0; + /** Whether the current object is selected or not. */ + private boolean isSelected; + /** Whether the current object is focused or not. */ + private boolean isFocused; + /** Constructs this renderer. */ + public OurTreeRenderer(int fontSize) { + super("Anything"); // This ensures that the height is calculated properly + setFont(OurUtil.getVizFont().deriveFont((float)fontSize)); + setVerticalAlignment(JLabel.BOTTOM); + setBorder(new EmptyBorder(0, 3, 0, 3)); + setText("Anything"); // So that we can derive the height + height = super.getPreferredSize().height; + } + /** This method is called by Swing to return an object to be drawn. */ + public Component getTreeCellRendererComponent + (JTree tree, Object value, boolean isSelected, boolean expanded, boolean isLeaf, int row, boolean isFocused) { + String string = tree.convertValueToText(value, isSelected, expanded, isLeaf, row, isFocused); + this.isFocused = isFocused; + this.isSelected = isSelected; + setText(string); + setForeground(UIManager.getColor(isSelected ? "Tree.selectionForeground" : "Tree.textForeground")); + preferredHeight = 0; // By default, don't override width/height + if (do_isDouble(value)) { Dimension d = super.getPreferredSize(); preferredWidth=d.width+3; preferredHeight=d.height*2; } + return this; + } + /** We override the getPreferredSize() method to return a custom size if do_isDouble() returns true for that value. */ + @Override public Dimension getPreferredSize() { + if (preferredHeight > 0) return new Dimension(preferredWidth, preferredHeight); + Dimension d = super.getPreferredSize(); + return new Dimension(d.width+3, d.height); + } + /** We override the paint() method to avoid drawing the box around the "extra space" (if height is double height) */ + @Override public void paint(Graphics g) { + int w=getWidth(), h=getHeight(), y=h-height; + Color background = isSelected ? UIManager.getColor("Tree.selectionBackground") : Color.WHITE; + Color border = isFocused ? UIManager.getColor("Tree.selectionBorderColor") : null; + if (background!=null) { g.setColor(background); g.fillRect(0, y, w, h-y); } + if (border!=null && isSelected) { g.setColor(border); g.drawRect(0, y, w-1, h-1-y); } + super.paint(g); + } + } + + /** This ensures the class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** Subclass should implement this method to return the root of the tree. */ + public abstract Object do_root(); + + /** Subclass should implement this method to return the list of children nodes given a particular node. */ + public abstract List do_ask(Object parent); + + /** Subclass should override this method to return whether a given item should be double-height or not (default = no). */ + protected boolean do_isDouble(Object object) { return false; } + + /** Subclass should call this when all fields are initialized; we won't call do_root() and do_ask() until subclass calls this. */ + protected final void do_start() { + // Create a custom TreeModel that calls do_root() and do_ask() whenever the tree needs expansion + setModel(new TreeModel() { + // Cache the parent->child list so that we always get the exact same OBJECT REFERENCE when navigating the tree + private final IdentityHashMap> map = new IdentityHashMap>(); + public Object getChild(Object parent, int index) { + List ans = map.get(parent); + if (ans==null) { ans = do_ask(parent); map.put(parent, ans); } + return (index >= 0 && index < ans.size()) ? ans.get(index) : null; + } + public int getIndexOfChild(Object parent, Object child) { + getChild(parent, 0); + List ans = map.get(parent); + for(int i=0; ;i++) if (i==ans.size()) return -1; else if (ans.get(i)==child) return i; + } + public Object getRoot() { return do_root(); } + public int getChildCount(Object node) { getChild(node, 0); return map.get(node).size(); } + public boolean isLeaf(Object node) { getChild(node, 0); return map.get(node).isEmpty(); } + public void valueForPathChanged(TreePath path, Object newValue) { } + public void addTreeModelListener(TreeModelListener l) { } + public void removeTreeModelListener(TreeModelListener l) { } + }); + } + + /** This method is called by Swing to figure out what text should be displayed for each node in the tree. */ + @Override public abstract String convertValueToText(Object v, boolean select, boolean expand, boolean leaf, int i, boolean focus); + + /** Construct a Tree object with the given font size. */ + public OurTree(int fontSize) { + Font font = OurUtil.getVizFont().deriveFont((float)fontSize); + OurTreeRenderer renderer = new OurTreeRenderer(fontSize); + renderer.setFont(font); + renderer.invalidate(); + renderer.validate(); + setRowHeight(0); // To allow variable row height on Mac OS X + setCellRenderer(renderer); + setFont(font); + setBorder(new EmptyBorder(8, 8, 2, 2)); + getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + putClientProperty("JTree.lineStyle", "Angled"); + setRootVisible(true); + setForeground(Color.BLACK); + setBackground(Color.WHITE); + setOpaque(true); + addTreeSelectionListener(new TreeSelectionListener() { + public void valueChanged(TreeSelectionEvent e) { + TreePath path = OurTree.this.getSelectionPath(); + if (path!=null) OurTree.this.listeners.fire(OurTree.this, Listener.Event.CLICK, path.getLastPathComponent()); + } + }); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurUtil.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurUtil.java new file mode 100644 index 00000000..b41959ac --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/OurUtil.java @@ -0,0 +1,327 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Toolkit; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.image.BufferedImage; +import java.net.URL; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.JSplitPane; +import javax.swing.KeyStroke; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; +import javax.swing.plaf.basic.BasicSplitPaneUI; + +/** Graphical convenience methods. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final class OurUtil { + + /** This constructor is private, since this utility class never needs to be instantiated. */ + private OurUtil() { } + + /** Assign the given attributes to the given JComponent, then return the JComponent again. + *

If Font x is given in the list, we call obj.setFont(x) + *

If String x is given in the list, we call obj.setToolTipText(x) + *

If Border x is given in the list, we call obj.setBorder(x) + *

If Dimension x is given in the list, we call obj.setPreferredSize(x) + *

If Color x is given in the list, and it's the first color, we call obj.setForeground(x) + *

If Color x is given in the list, and it's not the first color, we call obj.setBackground(x) then obj.setOpaque(true) + *

(If no Font is given, then after all these changes have been applied, we will call obj.setFont() will a default font) + */ + public static X make(X obj, Object... attributes) { + boolean hasFont = false, hasForeground = false; + if (attributes!=null) for(Object x: attributes) { + if (x instanceof Font) { obj.setFont((Font)x); hasFont=true; } + if (x instanceof String) { obj.setToolTipText((String)x); } + if (x instanceof Border) { obj.setBorder((Border)x); } + if (x instanceof Dimension) { obj.setPreferredSize((Dimension)x); } + if (x instanceof Color && !hasForeground) { obj.setForeground((Color)x); hasForeground=true; continue; } + if (x instanceof Color) { obj.setBackground((Color)x); obj.setOpaque(true); } + } + if (!hasFont) obj.setFont(getVizFont()); + return obj; + } + + /** Make a JLabel, then call Util.make() to apply a set of attributes to it. + * @param attributes - see {@link edu.mit.csail.sdg.alloy4.OurUtil#make OurUtil.make(component, attributes...)} + */ + public static JLabel label (String label, Object... attributes) { return make(new JLabel(label), attributes); } + + /** Make a JTextField with the given text and number of columns, then call Util.make() to apply a set of attributes to it. + * @param attributes - see {@link edu.mit.csail.sdg.alloy4.OurUtil#make OurUtil.make(component, attributes...)} + */ + public static JTextField textfield (String text, int columns, Object... attributes) { + return make(new JTextField(text, columns), attributes); + } + + /** Make a JTextArea with the given text and number of rows and columns, then call Util.make() to apply a set of attributes to it. + * @param attributes - see {@link edu.mit.csail.sdg.alloy4.OurUtil#make OurUtil.make(component, attributes...)} + */ + public static JTextArea textarea (String text, int rows, int columns, boolean editable, boolean wrap, Object... attributes) { + JTextArea ans = make(new JTextArea(text, rows, columns), Color.BLACK, Color.WHITE, new EmptyBorder(0,0,0,0)); + ans.setEditable(editable); + ans.setLineWrap(wrap); + ans.setWrapStyleWord(wrap); + return make(ans, attributes); + } + + /** Make a JScrollPane containing the given component (which can be null), then apply a set of attributes to it. + * @param attributes - see {@link edu.mit.csail.sdg.alloy4.OurUtil#make OurUtil.make(component, attributes...)} + */ + public static JScrollPane scrollpane (Component component, Object... attributes) { + JScrollPane ans = make(new JScrollPane(), new EmptyBorder(0,0,0,0)); + if (component!=null) ans.setViewportView(component); + ans.setMinimumSize(new Dimension(50, 50)); + return make(ans, attributes); + } + + /** Returns the recommended font to use in the visualizer, based on the OS. */ + public static Font getVizFont() { + return Util.onMac() ? new Font("Lucida Grande", Font.PLAIN, 11) : new Font("Dialog", Font.PLAIN, 12); + } + + /** Returns the screen width (in pixels). */ + public static int getScreenWidth() { return Toolkit.getDefaultToolkit().getScreenSize().width; } + + /** Returns the screen height (in pixels). */ + public static int getScreenHeight() { return Toolkit.getDefaultToolkit().getScreenSize().height; } + + /** Make a graphical button + * @param label - the text to show beneath the button + * @param tip - the tooltip to show when the mouse hovers over the button + * @param iconFileName - if nonnull, it's the filename of the icon to show (it will be loaded from an accompanying jar file) + * @param func - if nonnull, it's the function to call when the button is pressed + */ + public static JButton button (String label, String tip, String iconFileName, ActionListener func) { + JButton button = new JButton(label, (iconFileName!=null && iconFileName.length()>0) ? loadIcon(iconFileName) : null); + if (func != null) button.addActionListener(func); + button.setVerticalTextPosition(JButton.BOTTOM); + button.setHorizontalTextPosition(JButton.CENTER); + button.setBorderPainted(false); + button.setFocusable(false); + if (!Util.onMac()) button.setBackground(new Color(0.9f, 0.9f, 0.9f)); + button.setFont(button.getFont().deriveFont(10.0f)); + if (tip != null && tip.length() > 0) button.setToolTipText(tip); + return button; + } + + /** Load the given image file from an accompanying JAR file, and return it as an Icon object. */ + public static Icon loadIcon(String pathname) { + URL url = OurUtil.class.getClassLoader().getResource(pathname); + if (url!=null) return new ImageIcon(Toolkit.getDefaultToolkit().createImage(url)); + return new ImageIcon(new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB)); + } + + /** Make a JPanel with horizontal or vertical BoxLayout, then add the list of components to it (each aligned by xAlign and yAlign) + *
If a component is Color, it's the background of this JPanel and every component after it (until we see another Color) + *
If a component is Dimension, we will set it as the newly constructed JPanel's preferedSize and MaximumSize. + *
If a component is String, we will insert a JLabel with it as the label. + *
If a component is Integer, we will insert an "n*1" (or "1*n") rigid area instead. + *
If a component is null, we will insert a horizontal (or vertical) glue instead. + */ + private static JPanel makeBox(boolean horizontal, float xAlign, float yAlign, Object[] components) { + JPanel ans = new JPanel(); + ans.setLayout(new BoxLayout(ans, horizontal ? BoxLayout.X_AXIS : BoxLayout.Y_AXIS)); + ans.setAlignmentX(0.0f); + ans.setAlignmentY(0.0f); + Color color = null; + for(Object x: components) { + Component c = null; + if (x instanceof Color) { color = (Color)x; ans.setBackground(color); continue; } + if (x instanceof Dimension) { ans.setPreferredSize((Dimension)x); ans.setMaximumSize((Dimension)x); continue; } + if (x instanceof Component) { c = (Component)x; } + if (x instanceof String) { c = label((String)x, Color.BLACK); } + if (x instanceof Integer) { int i = (Integer)x; c = Box.createRigidArea(new Dimension(horizontal?i:1, horizontal?1:i)); } + if (x==null) { c = horizontal ? Box.createHorizontalGlue() : Box.createVerticalGlue(); } + if (c==null) continue; + if (color!=null) c.setBackground(color); + if (c instanceof JComponent) { ((JComponent)c).setAlignmentX(xAlign); ((JComponent)c).setAlignmentY(yAlign); } + ans.add(c); + } + return ans; + } + + /** Make a JPanel using horizontal BoxLayout, and add the components to it (each component will be center-aligned). + *
If a component is Color, it's the background of this JPanel and every component after it (until we see another Color) + *
If a component is Dimension, we will set it as the newly constructed JPanel's preferedSize and MaximumSize. + *
If a component is String, we will insert a JLabel with it as the label. + *
If a component is Integer, we will insert an "n*1" (or "1*n") rigid area instead. + *
If a component is null, we will insert a horizontal (or vertical) glue instead. + */ + public static JPanel makeH(Object... components) { return makeBox(true, 0.5f, 0.5f, components); } + + /** Make a JPanel using horizontal BoxLayout, and add the components to it (each component will be top-aligned). + *
If a component is Color, it's the background of this JPanel and every component after it (until we see another Color) + *
If a component is Dimension, we will set it as the newly constructed JPanel's preferedSize and MaximumSize. + *
If a component is String, we will insert a JLabel with it as the label. + *
If a component is Integer, we will insert an "n*1" (or "1*n") rigid area instead. + *
If a component is null, we will insert a horizontal (or vertical) glue instead. + */ + public static JPanel makeHT(Object... components) { return makeBox(true, 0.5f, 0.0f, components); } + + /** Make a JPanel using horizontal BoxLayout, and add the components to it (each component will be bottom-aligned). + *
If a component is Color, it's the background of this JPanel and every component after it (until we see another Color) + *
If a component is Dimension, we will set it as the newly constructed JPanel's preferedSize and MaximumSize. + *
If a component is String, we will insert a JLabel with it as the label. + *
If a component is Integer, we will insert an "n*1" (or "1*n") rigid area instead. + *
If a component is null, we will insert a horizontal (or vertical) glue instead. + */ + public static JPanel makeHB(Object... components) { return makeBox(true, 0.5f, 1.0f, components); } + + /** Make a JPanel using vertical BoxLayout, and add the components to it (each component will be left-aligned). + *
If a component is Color, it's the background of this JPanel and every component after it (until we see another Color) + *
If a component is Dimension, we will set it as the newly constructed JPanel's preferedSize and MaximumSize. + *
If a component is String, we will insert a JLabel with it as the label. + *
If a component is Integer, we will insert an "n*1" (or "1*n") rigid area instead. + *
If a component is null, we will insert a horizontal (or vertical) glue instead. + */ + public static JPanel makeVL(Object... components) { return makeBox(false, 0.0f, 0.5f, components); } + + /** Make a JPanel using vertical BoxLayout, and add the components to it (each component will be right-aligned). + *
If a component is Color, it's the background of this JPanel and every component after it (until we see another Color) + *
If a component is Dimension, we will set it as the newly constructed JPanel's preferedSize and MaximumSize. + *
If a component is String, we will insert a JLabel with it as the label. + *
If a component is Integer, we will insert an "n*1" (or "1*n") rigid area instead. + *
If a component is null, we will insert a horizontal (or vertical) glue instead. + */ + public static JPanel makeVR(Object... components) { return makeBox(false, 1.0f, 0.5f, components); } + + /** Constructs a new SplitPane containing the two components given as arguments + * @param orientation - the orientation (HORIZONTAL_SPLIT or VERTICAL_SPLIT) + * @param first - the left component (if horizontal) or top component (if vertical) + * @param second - the right component (if horizontal) or bottom component (if vertical) + * @param initialDividerLocation - the initial divider location (in pixels) + */ + public static JSplitPane splitpane (int orientation, Component first, Component second, int initialDividerLocation) { + JSplitPane x = make(new JSplitPane(orientation, first, second), new EmptyBorder(0,0,0,0)); + x.setContinuousLayout(true); + x.setDividerLocation(initialDividerLocation); + x.setOneTouchExpandable(false); + x.setResizeWeight(0.5); + if (Util.onMac() && (x.getUI() instanceof BasicSplitPaneUI)) { + boolean h = (orientation != JSplitPane.HORIZONTAL_SPLIT); + ((BasicSplitPaneUI)(x.getUI())).getDivider().setBorder(new OurBorder(h,h,h,h)); // Makes the border look nicer on Mac OS X + } + return x; + } + + /** Convenience method that recursively enables every JMenu and JMenuItem inside "menu". + * @param menu - the menu to start the recursive search + */ + public static void enableAll (JMenu menu) { + for(int i = 0; i < menu.getMenuComponentCount(); i++) { + Component x = menu.getMenuComponent(i); + if (x instanceof JMenuItem) ((JMenuItem)x).setEnabled(true); else if (x instanceof JMenu) enableAll((JMenu)x); + } + } + + /** Construct a new JMenu and add it to an existing JMenuBar. + *

Note: every time the user expands then collapses this JMenu, we automatically enable all JMenu and JMenuItem objects in it. + * + * @param parent - the JMenuBar to add this Menu into (or null if we don't want to add it to a JMenuBar yet) + * @param label - the label to show on screen (if it contains '&' followed by 'a'..'z', we'll remove '&' and use it as mnemonic) + * @param func - if nonnull we'll call its "run()" method right before expanding this menu + */ + public static JMenu menu (JMenuBar parent, String label, final Runnable func) { + final JMenu x = new JMenu(label.replace("&", ""), false); + if (!Util.onMac()) { + int i = label.indexOf('&'); + if (i>=0 && i+1='a' && i<='z') x.setMnemonic((i-'a')+'A'); else if (i>='A' && i<='Z') x.setMnemonic(i); + } + x.addMenuListener(new MenuListener() { + public void menuSelected (MenuEvent e) { if (func != null) func.run(); } + public void menuDeselected (MenuEvent e) { OurUtil.enableAll(x); } + public void menuCanceled (MenuEvent e) { OurUtil.enableAll(x); } + }); + if (parent!=null) parent.add(x); + return x; + } + + /** Construct a new JMenuItem then add it to an existing JMenu. + * @param parent - the JMenu to add this JMenuItem into (or null if you don't want to add it to any JMenu yet) + * @param label - the text to show on the menu + * @param attrs - a list of attributes to apply onto the new JMenuItem + *

If one positive number a is supplied, we call setMnemonic(a) + *

If two positive numbers a and b are supplied, and a!=VK_ALT, and a!=VK_SHIFT, we call setMnemoic(a) and setAccelerator(b) + *

If two positive numbers a and b are supplied, and a==VK_ALT or a==VK_SHIFT, we call setAccelerator(a | b) + *

If an ActionListener is supplied, we call addActionListener(x) + *

If an Boolean x is supplied, we call setEnabled(x) + *

If an Icon x is supplied, we call setIcon(x) + */ + public static JMenuItem menuItem (JMenu parent, String label, Object... attrs) { + JMenuItem m = new JMenuItem(label, null); + int accelMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); + boolean hasMnemonic = false; + for(Object x: attrs) { + if (x instanceof Character || x instanceof Integer) { + int k = (x instanceof Character) ? ((int)((Character)x)) : ((Integer)x).intValue(); + if (k < 0) continue; + if (k==KeyEvent.VK_ALT) { hasMnemonic = true; accelMask = accelMask | InputEvent.ALT_MASK; continue; } + if (k==KeyEvent.VK_SHIFT) { hasMnemonic = true; accelMask = accelMask | InputEvent.SHIFT_MASK; continue; } + if (!hasMnemonic) { m.setMnemonic(k); hasMnemonic=true; } else m.setAccelerator(KeyStroke.getKeyStroke(k, accelMask)); + } + if (x instanceof ActionListener) m.addActionListener((ActionListener)x); + if (x instanceof Icon) m.setIcon((Icon)x); + if (x instanceof Boolean) m.setEnabled((Boolean)x); + } + if (parent!=null) parent.add(m); + return m; + } + + /** This method minimizes the window. */ + public static void minimize(JFrame frame) { frame.setExtendedState(JFrame.ICONIFIED); } + + /** This method alternatingly maximizes or restores the window. */ + public static void zoom(JFrame frame) { + int both = JFrame.MAXIMIZED_BOTH; + frame.setExtendedState((frame.getExtendedState() & both)!=both ? both : JFrame.NORMAL); + } + + /** Make the frame visible, non-iconized, and focused. */ + public static void show(JFrame frame) { + frame.setVisible(true); + frame.setExtendedState(frame.getExtendedState() & ~JFrame.ICONIFIED); + frame.requestFocus(); + frame.toFront(); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Pair.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Pair.java new file mode 100644 index 00000000..d243eb5d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Pair.java @@ -0,0 +1,67 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.io.Serializable; + +/** Immutable; stores a pair of object references; Pair.equals() compares by calling equals() on both components. + * + *

Thread Safety: Safe (since objects of this class are immutable). + */ + +public final class Pair implements Serializable { + + /** This ensures the class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** The first half of the pair. */ + public final A a; + + /** The second half of the pair. */ + public final B b; + + /** Constructs a new Pair object (a,b). */ + public Pair(A a, B b) { + this.a = a; + this.b = b; + } + + /** If "a" and "b" are both String, concatename them with a space; if only one is, return it; else call toString() on them. */ + @Override public String toString() { + if (a instanceof String) { if (b instanceof String) return a+" "+b; else return (String)a; } + if (b instanceof String) return (String)b; + if (a==null) { + return (b!=null) ? b.toString() : ""; + } else { + return (b!=null) ? (a+" "+b) : a.toString(); + } + } + + /** Returns a hashcode based on (a==null?0:a.hashCode()) and (b==null?0:b.hashCode()). */ + @Override public int hashCode() { + int i = (a==null) ? 0 : a.hashCode(); + int j = (b==null) ? 0 : b.hashCode(); + return i*173123 + j; + } + + /** Pairs (a1, b1) and (a2, b2) are equal iff (a1==null ? a2==null : a1.equals(a2)) and (b1==null ? b2==null : b1.equals(b2)) */ + @Override public boolean equals(Object that) { + if (this==that) return true; + if (!(that instanceof Pair)) return false; + Pair p = (Pair)that; + return (a==null ? p.a==null : a.equals(p.a)) && (b==null ? p.b==null : b.equals(p.b)); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Pos.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Pos.java new file mode 100644 index 00000000..1e83c76d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Pos.java @@ -0,0 +1,138 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.io.Serializable; + +/** Immutable; stores the filename and line/column position. + * + *

Invariant: filename!=null && x>0 && y>0 && ((y2>y && x2>0) || (y2==y && x2>=x)) + * + *

Thread Safety: Safe (since objects of this class are immutable). + */ + +public final class Pos implements Serializable { + + /** To make sure the serialization form is stable. */ + private static final long serialVersionUID = 0; + + /** The filename (it can be an empty string if unknown) */ + public final String filename; + + /** The starting column position (from 1..) */ + public final int x; + + /** The starting row position (from 1..) */ + public final int y; + + /** The ending column position (from 1..) */ + public final int x2; + + /** The ending row position (from 1..) */ + public final int y2; + + /** The default "unknown" location. */ + public static final Pos UNKNOWN = new Pos("",1,1); + + /** Constructs a new Pos object. + * @param filename - the filename (it can be an empty string if unknown) + * @param x - the column position (from 1..) + * @param y - the row position (from 1..) + */ + public Pos(String filename, int x, int y) { + this.filename = (filename==null ? "" : filename); + this.x = (x>0 ? x : 1); + this.y = (y>0 ? y : 1); + this.x2 = this.x; + this.y2 = this.y; + } + + /** Constructs a new Pos object. + * @param filename - the filename (it can be an empty string if unknown) + * @param x - the starting column position (from 1..) + * @param y - the starting row position (from 1..) + * @param x2 - the ending column position (from 1..) + * @param y2 - the ending row position (from 1..) + */ + public Pos(String filename, int x, int y, int x2, int y2) { + this.filename = (filename==null ? "" : filename); + this.x = (x>0 ? x : 1); + this.y = (y>0 ? y : 1); + if (y2<(this.y)) y2=this.y; + if (y2==this.y) { + if (x2<(this.x)) x2=this.x; + } else { + if (x2<1) x2=1; + } + this.x2 = x2; + this.y2 = y2; + } + + /** Return a new position that merges this and that (it is assumed that the two Pos objects have same filename) + * @param that - the other position object + */ + public Pos merge(Pos that) { + if (that==null || that==UNKNOWN || that==this) return this; + if (this==UNKNOWN) return that; + int x=this.x, y=this.y, x2=that.x2, y2=that.y2; + if (that.yy2 || (this.y2==y2 && this.x2>x2)) { + x2=this.x2; + y2=this.y2; + } + if (x==this.x && y==this.y && x2==this.x2 && y2==this.y2) return this; // avoid creating unnecessary new object + if (x==that.x && y==that.y && x2==that.x2 && y2==that.y2) return that; // avoid creating unnecessary new object + return new Pos(filename, x, y, x2, y2); + } + + /** Returns true if neither argument is null nor UNKNOWN, + * and that the ending position of "a" is before the starting position of "b". + */ + public static boolean before(Pos a, Pos b) { + if (a==null || a==Pos.UNKNOWN || b==null || b==Pos.UNKNOWN || !a.filename.equals(b.filename)) return false; + return a.y2=0) f=f.substring(a+1); + if (f.length()==0) return "line "+y+", column "+x; else return "line "+y+", column "+x+", filename="+f; + } + + /** Returns a String representation of this position value. */ + @Override public String toString() { + if (filename.length()==0) return "line "+y+", column "+x; else return "line "+y+", column "+x+", filename="+filename; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Runner.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Runner.java new file mode 100644 index 00000000..eed69b79 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Runner.java @@ -0,0 +1,96 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.WindowListener; +import java.awt.event.WindowEvent; +import javax.swing.AbstractAction; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; + +/** This class converts a Runnable into an AbstractAction, WindowListener, CaretListener, and MenuListener also. */ + +public abstract class Runner extends AbstractAction implements Runnable, WindowListener, MenuListener, CaretListener, FocusListener { + + /** This ensures the class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** Constructs a new runner; you should override the run() and run(arg) method to customize it. */ + public Runner() { } + + /** This method should be overriden to provide the default action that this Runner would perform. */ + public abstract void run(); + + /** This method should be overriden to provide the default action that this Runner would perform given an argument. */ + public abstract void run(Object arg); + + /** This method is defined in java.awt.event.ActionListener; (this implementation calls this.run()) */ + public final void actionPerformed(ActionEvent e) { run(); } + + /** This method is defined in javax.swing.event.MenuListener; (this implementation calls this.run()) */ + public final void menuSelected(MenuEvent e) { run(); } + + /** This method is defined in javax.swing.event.MenuListener; (this implementation does nothing) */ + public final void menuDeselected(MenuEvent e) { } + + /** This method is defined in javax.swing.event.MenuListener; (this implementation does nothing) */ + public final void menuCanceled(MenuEvent e) { } + + /** This method is defined in java.awt.event.CaretListener; (this implementation calls this.run()) */ + public final void caretUpdate(CaretEvent e) { run(); } + + /** This method is defined in java.awt.event.FocusListener; (this implementation calls this.run()) */ + public final void focusGained(FocusEvent e) { run(); } + + /** This method is defined in java.awt.event.FocusListener; (this implementation does nothing) */ + public final void focusLost(FocusEvent e) { } + + /** This method is defined in java.awt.event.WindowListener; (this implementation calls this.run()) */ + public final void windowClosing(WindowEvent e) { run(); } + + /** This method is defined in java.awt.event.WindowListener; (this implementation does nothing) */ + public final void windowClosed(WindowEvent e) { } + + /** This method is defined in java.awt.event.WindowListener; (this implementation does nothing) */ + public final void windowOpened(WindowEvent e) { } + + /** This method is defined in java.awt.event.WindowListener; (this implementation does nothing) */ + public final void windowIconified(WindowEvent e) { } + + /** This method is defined in java.awt.event.WindowListener; (this implementation does nothing) */ + public final void windowDeiconified(WindowEvent e) { } + + /** This method is defined in java.awt.event.WindowListener; (this implementation does nothing) */ + public final void windowActivated(WindowEvent e) { } + + /** This method is defined in java.awt.event.WindowListener; (this implementation does nothing) */ + public final void windowDeactivated(WindowEvent e) { } + + /** This helper method returns a Runnable whose run() method will call window.dispose() */ + public static final Runner createDispose(final Window window) { + return new Runner() { + private static final long serialVersionUID = 0; + public final void run() { window.dispose(); } + public final void run(Object arg) { window.dispose(); } + }; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/SafeList.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/SafeList.java new file mode 100644 index 00000000..1584e1ff --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/SafeList.java @@ -0,0 +1,221 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import edu.mit.csail.sdg.alloy4.ConstList.TempList; + +/** This list allows add() but disallows remove() and set(); null values are allowed. + * + *

+ * By making this sacrifice, we are able to provide a very cheap "duplicate method" + * that simulates making a copy without actually making a copy. + * + *

+ * Furthermore, this class's iterator allows concurrent insertion and iteration + * (that is, we can iterate over the list while adding elements to the list at the same time). + * The iterator is guaranteed to iterate over exactly the elements + * that existed at the time that the iterator was created. + * + *

Thread Safety: Safe. + * + * @param - the type of element + */ + +public final class SafeList implements Serializable, Iterable { + + /** This ensures the class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** The actual list of elements; it will be shared by an original SafeList and all its unmodifiable copies. */ + private final List list; + + /** If negative, that means this instance is mutable; otherwise, it is the list size at the time of the copy. */ + private final int max; + + /** Constructs a modifiable empty list. */ + public SafeList() { + list = new ArrayList(); + max = (-1); + } + + /** Constructs a modifiable empty list with the initial capacity. */ + public SafeList(int initialCapacity) { + list = new ArrayList(initialCapacity); + max = (-1); + } + + /** Constructs a modifiable list containing the elements from the given collection. */ + public SafeList(Collection initialValue) { + list = new ArrayList(initialValue); + max = (-1); + } + + /** Constructs a modifiable list containing the elements from the given iterable. */ + public SafeList(Iterable initialValue) { + list = new ArrayList(); + max = (-1); + for(T obj: initialValue) list.add(obj); + } + + /** Private constructor for assigning exact values to "list" and "max". */ + private SafeList(List list, int max) { + this.list = list; + this.max = max; + } + + /** Constructs an unmodifiable copy of an existing SafeList. */ + public SafeList dup() { + synchronized(SafeList.class) { return new SafeList(list, size()); } + } + + /** Constructs a modifiable ArrayList containing the same elements as this list. */ + public List makeCopy() { + synchronized(SafeList.class) { + int n = size(); + ArrayList ans = new ArrayList(n); + for(int i=0; i makeConstList() { + synchronized(SafeList.class) { + int n = size(); + TempList ans = new TempList(n); + for(int i=0; i b; + if (that instanceof List) { n=((List)that).size(); if (n!=size()) return false; b=((List)that).iterator(); } + else if (that instanceof SafeList) { n=((SafeList)that).size(); if (n!=size()) return false; b=((SafeList)that).iterator(); } + else return false; + Iterator a=iterator(); + for(int i=0; i=0) throw new UnsupportedOperationException(); else return list.add(item); + } + } + + /** Add a collection of elements into the list. */ + public void addAll(Collection items) { + synchronized(SafeList.class) { + if (max>=0) throw new UnsupportedOperationException(); + list.addAll(items); + } + } + + /** Get an element from the list. */ + public T get(int i) { + synchronized(SafeList.class) { + if (max>=0 && i>=max) throw new IndexOutOfBoundsException(); else return list.get(i); + } + } + + /** Returns the size of the list. */ + public int size() { + synchronized(SafeList.class) { + if (max>=0) return max; else return list.size(); + } + } + + /** Returns true if the list is empty. */ + public boolean isEmpty() { + return size()==0; + } + + /** Returns an iterator that iterates over elements in this list + * (in the order that they were inserted). + * + *

Note: This iterator's remove() method always throws UnsupportedOperationException. + * + *

Note: This iterator always returns exactly the list of elements that existed + * at the time that the iterator was created (even if the list is modified after that point). + */ + public Iterator iterator() { + synchronized(SafeList.class) { + return new Iterator() { + private final int imax = (max>=0 ? max : list.size()); + private int now = 0; + public final T next() { + if (now >= imax) throw new NoSuchElementException(); + synchronized(SafeList.class) { + T answer = list.get(now); + now++; + return answer; + } + } + public final boolean hasNext() { return now < imax; } + public final void remove() { throw new UnsupportedOperationException(); } + }; + } + } + + /** Returns a String representation of this list. */ + @Override public String toString() { + StringBuilder sb = new StringBuilder("["); + boolean first = true; + for(Object x: this) { + if (first) first=false; else sb.append(", "); + if (x==this) sb.append("(this collection)"); else sb.append(x); + } + return sb.append(']').toString(); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Subprocess.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Subprocess.java new file mode 100644 index 00000000..f0b600e0 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Subprocess.java @@ -0,0 +1,94 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.io.InputStream; +import java.util.Timer; +import java.util.TimerTask; + +/** This provides a convenience wrapper around a Process object. + * + *

To launch a subprocess, simply write Subprocess.exec(timeout, args); + * + *

Thread Safety: Safe. + */ + +public final class Subprocess { + + /** Timer used to schedule a timeout for the process. */ + private static final Timer stopper = new Timer(); + + /** This field will store the program output (or "" if an error occurred) */ + private String stdout = null; + + /** This field will store an error message (or "" if no error occurred) */ + private String stderr = null; + + /** Constructor is private since we only allow the static method exec() to construct objects of this class. */ + private Subprocess() { } + + /** Executes the given command line, wait for its completion, then return its output. + * @param timeLimit - we will attempt to terminate the process after that many milliseconds have passed + * @param p - preconstructed Process object + */ + private static String exec (final long timeLimit, final Process p) throws Exception { + final Subprocess pro = new Subprocess(); + final InputStream f1 = p.getInputStream(), f2 = p.getErrorStream(); + TimerTask stoptask = new TimerTask() { + public void run() { + synchronized(pro) { if (pro.stdout!=null && pro.stderr!=null) return; pro.stdout=""; pro.stderr="Error: timeout"; } + p.destroy(); + } + }; + synchronized(Subprocess.class) { stopper.schedule(stoptask, timeLimit); } + new Thread(new Runnable() { + public void run() { + String err = null; + try { if (f2.read()>=0) err="Error: stderr"; } catch(Throwable ex) { err="Error: "+ex; } + synchronized(pro) { if (err!=null) {pro.stdout=""; pro.stderr=err;} else if (pro.stderr==null) pro.stderr=""; } + } + }).start(); + p.getOutputStream().close(); + StringBuilder output = new StringBuilder(); + byte[] buf = new byte[8192]; + while(true) { + int n = f1.read(buf); + if (n<0) break; else for(int i=0; iThread Safety: Safe. + */ + +public final class UniqueNameGenerator { + + /** This stores the set of names we've generated so far. */ + private final Set names = new HashSet(); + + /** Construct a UniqueNameGenerator with a blank history. */ + public UniqueNameGenerator() { } + + /** Regard the provided name as "seen". + *

For convenience, it returns the argument as the return value. + */ + public synchronized String seen(String name) { names.add(name); return name; } + + /** Queries whether the provided name has been "seen" or not. */ + public synchronized boolean hasSeen(String name) { return names.contains(name); } + + /** Clear the history of previously generated names. */ + public synchronized void clear() { names.clear(); } + + /** Generate a unique name based on the input name. + * + *

Specifically: if the name has not been generated/seen already by this generator, + * then it is returned as is. Otherwise, we append ' to it until the name becomes unique. + */ + public synchronized String make(String name) { + while(!names.add(name)) name=name+"'"; + return name; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Util.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Util.java new file mode 100644 index 00000000..c621bdcd --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Util.java @@ -0,0 +1,601 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.io.Closeable; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.Charset; +import java.nio.charset.CodingErrorAction; +import java.util.Comparator; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Locale; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.prefs.Preferences; +import edu.mit.csail.sdg.alloy4.ConstList.TempList; + +/** This provides useful static methods for I/O and XML operations. + * + *

Thread Safety: Safe. + */ + +public final class Util { + + /** This constructor is private, since this utility class never needs to be instantiated. */ + private Util() { } + + /** This reads and writes String-valued Java persistent preferences. + *

Thread Safety: Safe. + */ + public static final class StringPref { + /** The id associated with this preference. */ + private final String id; + /** The default value for this preference. */ + private final String defaultValue; + /** Constructs a new StringPref object with the given id. */ + public StringPref (String id) {this.id=id; this.defaultValue="";} + /** Constructs a new StringPref object with the given id and the given default value. */ + public StringPref (String id, String defaultValue) {this.id=id; this.defaultValue=defaultValue;} + /** Sets the value for this preference. */ + public void set (String value) { Preferences.userNodeForPackage(Util.class).put(id, value); } + /** Reads the value for this preference; if not set or is empty, we return the default value. */ + public String get () { + String ans=Preferences.userNodeForPackage(Util.class).get(id, ""); + return (ans==null || ans.length()==0) ? defaultValue : ans; + } + } + + /** This reads and writes boolean-valued Java persistent preferences. + *

Thread Safety: Safe. + */ + public static final class BooleanPref { + /** The id associated with this preference. */ + private final String id; + /** Constructurs a new BooleanPref object with the given id. */ + public BooleanPref (String id) { this.id=id; } + /** Sets the value for this preference. */ + public void set (boolean value) { Preferences.userNodeForPackage(Util.class).put(id, value ? "y" : ""); } + /** Reads the value for this preference; if not set, we return false. */ + public boolean get () { return "y".equals(Preferences.userNodeForPackage(Util.class).get(id, "")); } + } + + /** This reads and writes integer-valued Java persistent preferences. + *

Thread Safety: Safe. + */ + public static final class IntPref { + /** The id associated with this preference. */ + private final String id; + /** The minimum value for this preference. */ + private final int min; + /** The maximum value for this preference. */ + private final int max; + /** The default value for this preference. */ + private final int def; + /** If min>n, we return min; else if n>max, we return max; otherwise we return n. */ + private int bound (int n) { return nmax? max : n); } + /** Make a new IntPref object with the given id; you must ensure max >= min, but def does not have to be between min..max */ + public IntPref (String id, int min, int def, int max) {this.id=id; this.min=min; this.def=def; this.max=max;} + /** Sets the value for this preference. */ + public void set (int value) { Preferences.userNodeForPackage(Util.class).putInt(id, bound(value)); } + /** Reads the value for this preference; if not set, we return the default value. */ + public int get () { + int n; + String t = Preferences.userNodeForPackage(Util.class).get(id, ""); + if (t==null || t.length()==0) return def; + try { n=Integer.parseInt(t); } catch(NumberFormatException ex) { return def; } + return bound(n); + } + } + + /** Copy the input list, append "element" to it, then return the result as an unmodifiable list. */ + public static ConstList append(List list, T element) { + TempList ans = new TempList(list.size()+1); + ans.addAll(list).add(element); + return ans.makeConst(); + } + + /** Copy the input array, append "element" to it, then return the result as a new array. */ + @SuppressWarnings("unchecked") + public static T[] append(T[] list, T element) { + T[] ans = (T[]) java.lang.reflect.Array.newInstance(list.getClass().getComponentType(), list.length+1); + System.arraycopy(list, 0, ans, 0, list.length); + ans[ans.length-1] = element; + return ans; + } + + /** Copy the input list, prepend "element" to it, then return the result as an unmodifiable list. */ + public static ConstList prepend(List list, T element) { + TempList ans = new TempList(list.size()+1); + ans.add(element).addAll(list); + return ans.makeConst(); + } + + /** Returns an unmodifiable List with same elements as the array. */ + public static ConstList asList(T... array) { + return (new TempList(array)).makeConst(); + } + + /** Returns a newly created LinkedHashSet containing the given elements in the given order. */ + public static LinkedHashSet asSet(V... values) { + LinkedHashSet ans = new LinkedHashSet(); + for(int i=0; i LinkedHashMap asMap(K[] keys, V... values) { + LinkedHashMap ans = new LinkedHashMap(); + for(int i=0; i Iterable fastJoin(final Iterable collection1, final Iterable collection2) { + return new Iterable() { + public Iterator iterator() { + return new Iterator () { + private Iterator a=collection1.iterator(), b=collection2.iterator(); + public boolean hasNext() { + if (a!=null) { if (a.hasNext()) return true; a=null; } + if (b!=null) { if (b.hasNext()) return true; b=null; } + return false; + } + public E next() { + if (a!=null) { if (a.hasNext()) return a.next(); a=null; } + if (b!=null) { if (b.hasNext()) return b.next(); b=null; } + throw new NoSuchElementException(); + } + public void remove() { throw new UnsupportedOperationException(); } + }; + } + }; + } + + /** Converts Windows/Mac/Unix linebreaks into '\n', and replace non-tab non-linebreak control characters into space. */ + public static String convertLineBreak(String input) { + return input.replace("\r\n","\n").replace('\r','\n').replaceAll("[\000-\010\013\014\016-\037]"," "); + } + + /** Attempt to close the file/stream/reader/writer and return true if and only if we successfully closed it. + * (If object==null, we return true right away) + */ + public static boolean close(Closeable object) { + if (object==null) return true; + boolean ans=true; + try { + if (object instanceof PrintStream && ((PrintStream)object).checkError()) ans=false; + if (object instanceof PrintWriter && ((PrintWriter)object).checkError()) ans=false; + object.close(); + return ans; + } catch(Throwable ex) { + return false; + } + } + + /** This synchronized field stores the current "default directory" which is used by the FileOpen and FileSave dialogs. */ + private static String currentDirectory = null; + + /** Modifies the current "default directory" which is used by the FileOpen and FileSave dialogs. */ + public synchronized static void setCurrentDirectory(File newDirectory) { + if (newDirectory==null) // this can actually happen + currentDirectory = canon(System.getProperty("user.home")); + else + currentDirectory = canon(newDirectory.getAbsolutePath()); + } + + /** Returns the current "default directory" which is used by the FileOpen and FileSave dialogs. */ + public synchronized static String getCurrentDirectory() { + if (currentDirectory == null) currentDirectory = canon(System.getProperty("user.home")); + return currentDirectory; + } + + /** This returns the constant prefix to denote whether Util.readAll() should read from a JAR or read from the file system. + * (The reason we made this into a "method" rather than a constant String is that it is used + * by Util.canon() which is called by many static initializer blocks... so if we made this into a static field + * of Util, then it may not be initialized yet when we need it!) + */ + public static String jarPrefix() { return File.separator + "$alloy4$" + File.separator; } + + /** Read everything into a String; throws IOException if an error occurred. + * (If filename begins with Util.jarPrefix() then we read from the JAR instead) + */ + public static String readAll(String filename) throws FileNotFoundException, IOException { + String JAR = jarPrefix(); + boolean fromJar=false; + if (filename.startsWith(JAR)) { fromJar=true; filename=filename.substring(JAR.length()).replace('\\', '/'); } + InputStream fis=null; + int now=0, max=4096; + if (!fromJar) { + long maxL = new File(filename).length(); + max = (int)maxL; + if (max != maxL) throw new IOException("File too big to fit in memory"); + } + byte[] buf; + try { + buf = new byte[max]; + fis = fromJar ? Util.class.getClassLoader().getResourceAsStream(filename) : new FileInputStream(filename); + if (fis==null) throw new FileNotFoundException("File \""+filename+"\" cannot be found"); + while(true) { + if (now >= max) { + max = now + 4096; + if (max0) System.arraycopy(buf, 0, buf2, 0, now); + buf = buf2; + } + int r = fis.read(buf, now, max-now); + if (r<0) break; + now = now + r; + } + } catch(OutOfMemoryError ex) { + System.gc(); + throw new IOException("There is insufficient memory."); + } finally { + close(fis); + } + CodingErrorAction r = CodingErrorAction.REPORT; + CodingErrorAction i = CodingErrorAction.IGNORE; + ByteBuffer bbuf; + String ans = ""; + try { + // We first try UTF-8; + bbuf=ByteBuffer.wrap(buf, 0, now); + ans=Charset.forName("UTF-8").newDecoder().onMalformedInput(r).onUnmappableCharacter(r).decode(bbuf).toString(); + } catch(CharacterCodingException ex) { + try { + // if that fails, we try using the platform's default charset + bbuf=ByteBuffer.wrap(buf, 0, now); + ans=Charset.defaultCharset().newDecoder().onMalformedInput(r).onUnmappableCharacter(r).decode(bbuf).toString(); + } catch(CharacterCodingException ex2) { + // if that also fails, we try using "ISO-8859-1" which should always succeed but may map some characters wrong + bbuf=ByteBuffer.wrap(buf, 0, now); + ans=Charset.forName("ISO-8859-1").newDecoder().onMalformedInput(i).onUnmappableCharacter(i).decode(bbuf).toString(); + } + } + return convertLineBreak(ans); + } + + /** Open then overwrite the file with the given content; throws Err if an error occurred. */ + public static long writeAll(String filename, String content) throws Err { + final FileOutputStream fos; + try { + fos=new FileOutputStream(filename); + } catch(IOException ex) { + throw new ErrorFatal("Cannot write to the file "+filename); + } + // Convert the line break into the UNIX line break, and remove ^L, ^F... and other characters that confuse JTextArea + content = convertLineBreak(content); + // If the last line does not have a LINEBREAK, add it + if (content.length()>0 && content.charAt(content.length()-1)!='\n') content=content+"\n"; + // Now, convert the line break into the local platform's line break, then write it to the file + try { + final String NL = System.getProperty("line.separator"); + byte[] array = content.replace("\n",NL).getBytes("UTF-8"); + fos.write(array); + fos.close(); + return array.length; + } catch(IOException ex) { + close(fos); + throw new ErrorFatal("Cannot write to the file "+filename, ex); + } + } + + /** Returns the canonical absolute path for a file. + * If an IO error occurred, or if the file doesn't exist yet, + * we will at least return a noncanonical but absolute path for it. + *

Note: if filename=="", we return "". + */ + public static final String canon(String filename) { + if (filename==null || filename.length()==0) return ""; + if (filename.startsWith(jarPrefix())) { + char sep = File.separatorChar, other = (sep=='/' ? '\\' : '/'); + return filename.replace(other, sep); + } + File file = new File(filename); + try { return file.getCanonicalPath(); } catch(IOException ex) { return file.getAbsolutePath(); } + } + + /** Sorts two strings for optimum module order; we guarantee slashComparator(a,b)==0 iff a.equals(b). + *
(1) First of all, the builtin names "extend" and "in" are sorted ahead of other names + *
(2) Else, if one string starts with "this/", then it is considered smaller + *
(3) Else, if one string has fewer '/' than the other, then it is considered smaller. + *
(4) Else, we compare them lexically without case-sensitivity. + *
(5) Finally, we compare them lexically with case-sensitivity. + */ + public static final Comparator slashComparator = new Comparator() { + public final int compare(String a, String b) { + if (a==null) return (b==null)?0:-1; else if (b==null) return 1; else if (a.equals(b)) return 0; + if (a.equals("extends")) return -1; else if (b.equals("extends")) return 1; + if (a.equals("in")) return -1; else if (b.equals("in")) return 1; + if (a.startsWith("this/")) { + if (!b.startsWith("this/")) return -1; + } else if (b.startsWith("this/")) { + return 1; + } + int acount=0, bcount=0; + for(int i=0; i0) return false; + boolean result = true; + InputStream in = null; + FileOutputStream out = null; + try { + in = Util.class.getClassLoader().getResourceAsStream(sourcename); + if (in==null) return false; // This means the file is not relevant for this setup, so we don't pop up a fatal dialog + out = new FileOutputStream(destname); + byte[] b = new byte[16384]; + while(true) { + int numRead = in.read(b); + if (numRead < 0) break; + if (numRead > 0) out.write(b, 0, numRead); + } + } catch (IOException e) { + result=false; + } + if (!close(out)) result=false; + if (!close(in)) result=false; + if (!result) OurDialog.fatal("Error occurred in creating the file \""+destname+"\""); + return true; + } + + /** Copy the list of files from JAR into the destination directory, + * then set the correct permissions on them if possible. + * + * @param executable - if true, we will attempt to set the file's "executable" permission (failure to do this is ignored) + * @param keepPath - if true, the full path will be created for the destination file + * @param destdir - the destination directory + * @param names - the files to copy from the JAR + */ + public static void copy(boolean executable, boolean keepPath, String destdir, String... names) { + String[] args = new String[names.length+2]; + args[0] = "/bin/chmod"; // This does not work on Windows, but the "executable" bit is not needed on Windows anyway. + args[1] = (executable ? "700" : "600"); // 700 means read+write+executable; 600 means read+write. + int j=2; + for(int i=0; i=0) destname=destname.substring(ii+1); } + destname=(destdir+'/'+destname).replace('/', File.separatorChar); + int last=destname.lastIndexOf(File.separatorChar); + new File(destname.substring(0,last+1)).mkdirs(); // Error will be caught later by the file copy + if (copy(name, destname)) { args[j]=destname; j++; } + } + if (onWindows() || j<=2) return; + String[] realargs = new String[j]; + for(int i=0; i If (from > to), this means we simply delete the portion of the file beginning at "to" and up to but excluding "from". + *

If (from < to), this means we insert (to-from) number of ARBITRARY bytes into the "from" location + * and shift the original file content accordingly. + *

Note: after this operation, the file's current position will be moved to the start of the file. + * @throws IOException if (from < 0) || (to < 0) || (from >= file.length()) + */ + public static void shift (RandomAccessFile file, long from, long to) throws IOException { + long total = file.length(); + if (from<0 || from>=total || to<0) throw new IOException(); else if (from==to) {file.seek(0); return;} + final byte buf[] = new byte[4096]; + int res; + if (from>to) { + while(true) { + file.seek(from); + if ((res=file.read(buf)) <= 0) { file.setLength(to); file.seek(0); return; } + file.seek(to); file.write(buf, 0, res); from=from+res; to=to+res; + } + } else { + file.seek(total); + for(long todo=to-from; todo>0;) { + if (todo >= buf.length) {file.write(buf); todo = todo - buf.length;} else {file.write(buf, 0, (int)todo); break;} + } + for(long todo=total-from; todo>0; total=total-res, todo=todo-res) { + if (todo > buf.length) res=buf.length; else res=(int)todo; + file.seek(total - res); + for(int done=0; done + * In particular, it changes LESS THAN, GREATER THAN, AMPERSAND, SINGLE QUOTE, and DOUBLE QUOTE + * into "&lt;" "&gt;" "&amp;" "&apos;" and "&quot;" and turns any characters + * outside of the 32..126 range into the "&#xHHHH;" encoding + * (where HHHH is the 4 digit lowercase hexadecimal representation of the character value). + * + * @param out - the PrintWriter to write into + * @param str - the String to write out + */ + public static void encodeXML(PrintWriter out, String str) { + int n=str.length(); + for(int i=0; i') { out.write(">"); continue; } + if (c=='&') { out.write("&"); continue; } + if (c=='\'') { out.write("'"); continue; } + if (c=='\"') { out.write("""); continue; } + if (c>=32 && c<=126) { out.write(c); continue; } + out.write("&#x"); + String v=Integer.toString(c, 16); + for(int j=v.length(); j<4; j++) out.write('0'); + out.write(v); + out.write(';'); + } + } + + /** Write a String into a StringBuilder, and encode special characters using XML-specific encoding. + * + *

+ * In particular, it changes LESS THAN, GREATER THAN, AMPERSAND, SINGLE QUOTE, and DOUBLE QUOTE + * into "&lt;" "&gt;" "&amp;" "&apos;" and "&quot;" and turns any characters + * outside of the 32..126 range into the "&#xHHHH;" encoding + * (where HHHH is the 4 digit lowercase hexadecimal representation of the character value). + * + * @param out - the StringBuilder to write into + * @param str - the String to write out + */ + public static void encodeXML(StringBuilder out, String str) { + int n=str.length(); + for(int i=0; i') { out.append(">"); continue; } + if (c=='&') { out.append("&"); continue; } + if (c=='\'') { out.append("'"); continue; } + if (c=='\"') { out.append("""); continue; } + if (c>=32 && c<=126) { out.append(c); continue; } + out.append("&#x"); + String v=Integer.toString(c, 16); + for(int j=v.length(); j<4; j++) out.append('0'); + out.append(v).append(';'); + } + } + + /** Encode special characters of a String using XML/HTML encoding. + * + *

+ * In particular, it changes LESS THAN, GREATER THAN, AMPERSAND, SINGLE QUOTE, and DOUBLE QUOTE + * into "&lt;" "&gt;" "&amp;" "&apos;" and "&quot;" and turns any characters + * outside of the 32..126 range into the "&#xHHHH;" encoding + * (where HHHH is the 4 digit lowercase hexadecimal representation of the character value). + */ + public static String encode(String str) { + if (str.length() == 0) return str; + StringBuilder sb = new StringBuilder(); + encodeXML(sb, str); + return sb.toString(); + } + + /** Write a list of Strings into a PrintWriter, where strs[2n] are written as-is, and strs[2n+1] are XML-encoded. + * + *

For example, if you call encodeXML(out, A, B, C, D, E), it is equivalent to the following: + *
out.print(A); + *
encodeXML(out, B); + *
out.print(C); + *
encodeXML(out, D); + *
out.print(E); + *
In other words, it writes the even entries as-is, and writes the odd entries using XML encoding. + * + * @param out - the PrintWriter to write into + * @param strs - the list of Strings to write out + */ + public static void encodeXMLs(PrintWriter out, String... strs) { + for(int i=0; i For example, if you call encodeXML(out, A, B, C, D, E), it is equivalent to the following: + *
out.append(A); + *
encodeXML(out, B); + *
out.append(C); + *
encodeXML(out, D); + *
out.append(E); + *
In other words, it writes the even entries as-is, and writes the odd entries using XML encoding. + * + * @param out - the StringBuilder to write into + * @param strs - the list of Strings to write out + */ + public static void encodeXMLs(StringBuilder out, String... strs) { + for(int i=0; ismall within big. + * @param big - the String that we want to perform the search on + * @param small - the pattern we are looking forward + * @param start - the offset within "big" to start (for example: 0 means to start from the beginning of "big") + * @param forward - true if the search should go forward; false if it should go backwards + * @param caseSensitive - true if the search should be done in a case-sensitive manner + * + * @return 0 or greater if found, -1 if not found (Note: if small=="", then we always return -1) + */ + public static int indexOf(String big, String small, int start, boolean forward, boolean caseSensitive) { + int len=big.length(), slen=small.length(); + if (slen==0) return -1; + while(start>=0 && start=slen) return start; + if (start+i>=len) break; + int b=big.charAt(start+i), s=small.charAt(i); + if (!caseSensitive && b>='A' && b<='Z') b=(b-'A')+'a'; + if (!caseSensitive && s>='A' && s<='Z') s=(s-'A')+'a'; + if (b!=s) break; + } + if (forward) start++; else start--; + } + return -1; + } + + /** Returns true iff running on Windows **/ + public static boolean onWindows() { + return System.getProperty("os.name").toLowerCase(Locale.US).startsWith("windows"); + }; + + /** Returns true iff running on Mac OS X. **/ + public static boolean onMac() { + return System.getProperty("mrj.version")!=null || System.getProperty("os.name").toLowerCase(Locale.US).startsWith("mac "); + } + + /** Returns the substring after the last "/" */ + public static String tail(String string) { int i=string.lastIndexOf('/'); return (i<0) ? string : string.substring(i+1); } + + /** Returns the largest allowed integer, or -1 if no integers are allowed (bitwidth < 1). */ + public static int max(int bitwidth) { return bitwidth < 1 ? -1 : (1<<(bitwidth-1))-1; } + + /** Returns the smallest allowed integer, or 0 if no integers are allowed (bitwidth < 1)*/ + public static int min(int bitwidth) { return bitwidth < 1 ? 0 : 0-(1<<(bitwidth-1)); } + + /** Returns a mask of the form 000..0011..11 where the number of 1s is equal to the number of significant bits of the highest integer withing the given bitwidth */ + public static int shiftmask(int bitwidth) { return bitwidth < 1 ? 0 : (1 << (32 - Integer.numberOfLeadingZeros(bitwidth-1))) - 1; } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Version.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Version.java new file mode 100644 index 00000000..1ba1f34b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/Version.java @@ -0,0 +1,42 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +/** This holds the buildDate String. + * + * The release build script will generate a customized Version.java with the correct buildnumber and date. + * + *

Thread Safety: Safe. + */ + +public final class Version { + + /** The constructor is private, since this class never needs to be instantiated. */ + private Version() { } + + /** This is true if this is an experimental version rather than a release version. */ + public static final boolean experimental = true; + + /** Returns the build number. */ + public static int buildNumber() { return Integer.MAX_VALUE; } + + /** Returns the version string. */ + public static String version() { return "4.2.?"; } + + /** Returns the build date. */ + public static String buildDate() { return "unknown"; } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/WorkerEngine.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/WorkerEngine.java new file mode 100644 index 00000000..90a5c679 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/WorkerEngine.java @@ -0,0 +1,296 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.Serializable; +import java.lang.Thread.UncaughtExceptionHandler; + +/** This class allows you to execute tasks in a subprocess, and receive its outputs via callback. + * + *

By executing the task in a subprocess, we can always terminate a runaway task explicitly by calling stop(), + * and we can control how much memory and stack space to give to the subprocess. + * + *

Only one task may execute concurrently at any given time; if you try to issue a new task + * when the previous task hasn't finished, then you will get an IOException. + * + *

As long as the subprocess hasn't terminated either due to crashing or due to user calling stop(), + * then the same subprocess is reused to execute each subsequent task; however, if the subprocess crashed, + * the crash will be reported to the parent process via callback, and if we try to execute another task, + * then a new subprocess will be spawned automatically. + */ + +public final class WorkerEngine { + + /** This defines an interface for performing tasks in a subprocess. */ + public interface WorkerTask extends Serializable { + /** The task should send zero or more non-null Objects to out.callback(msg) to report progress to the parent process. */ + public void run(WorkerCallback out) throws Exception; + } + + /** This defines an interface for receiving results from a subprocess. */ + public interface WorkerCallback { + /** The task would send zero or more non-null Objects to this handler + * (the objects will be serialized by the sub JVM and deserialized in the parent JVM). */ + public void callback(Object msg); + /** If the task completed successfully, this method will be called. */ + public void done(); + /** If the task terminated with an error, this method will be called. */ + public void fail(); + } + + /** This wraps the given InputStream such that the resulting object's "close()" method does nothing; + * if stream==null, we get an InputStream that always returns EOF. */ + private static InputStream wrap(final InputStream stream) { + return new InputStream() { + public int read(byte b[], int off, int len) throws IOException { + if (len==0) return 0; else if (stream==null) return -1; else return stream.read(b, off, len); + } + public int read() throws IOException { if (stream==null) return -1; else return stream.read(); } + public long skip(long n) throws IOException { if (stream==null) return 0; else return stream.skip(n); } + }; + } + + /** This wraps the given OutputStream such that the resulting object's "close()" method simply calls "flush()"; + * if stream==null, we get an OutputStream that ignores all writes. */ + private static OutputStream wrap(final OutputStream stream) { + return new OutputStream() { + public void write(int b) throws IOException { if (stream!=null) stream.write(b); } + public void write(byte b[], int off, int len) throws IOException { if (stream!=null) stream.write(b, off, len); } + public void flush() throws IOException { if (stream!=null) stream.flush(); } + public void close() throws IOException { if (stream!=null) stream.flush(); } + // The close() method above INTENTIONALLY does not actually close the file + }; + } + + /** If nonnull, it is the latest sub JVM. */ + private static Process latest_sub = null; + + /** If nonnull, it is the latest worker thread talking to the sub JVM. + * (If latest_sub==null, then we guarantee latest_manager is also null) */ + private static Thread latest_manager = null; + + /** Constructor is private since this class does not need to be instantiated. */ + private WorkerEngine() { } + + /** This terminates the subprocess, and prevent any further results from reaching the parent's callback handler. */ + public static void stop() { + synchronized(WorkerEngine.class) { + try { if (latest_sub!=null) latest_sub.destroy(); } finally { latest_manager=null; latest_sub=null; } + } + } + + /** This returns true iff the subprocess is still busy processing the last task. */ + public static boolean isBusy() { + synchronized(WorkerEngine.class) { return latest_manager!=null && latest_manager.isAlive(); } + } + + /** This executes a task using the current thread. + * @param task - the task that we want to execute + * @param callback - the handler that will receive outputs from the task + * @throws IOException - if a previous task is still busy executing + */ + public static void runLocally(final WorkerTask task, final WorkerCallback callback) throws Exception { + synchronized(WorkerEngine.class) { + if (latest_manager!=null && latest_manager.isAlive()) throw new IOException("Subprocess still performing the last task."); + try { task.run(callback); callback.done(); } catch(Throwable ex) { callback.callback(ex); callback.fail(); } + } + } + + /** This issues a new task to the subprocess; + * if subprocess hasn't been constructed yet or has terminated abnormally, this method will launch a new subprocess. + * @param task - the task that we want the subprocess to execute + * @param newmem - the amount of memory (in megabytes) we want the subprocess to have + * (if the subproces has not terminated, then this parameter is ignored) + * @param newstack - the amount of stack (in kilobytes) we want the subprocess to have + * (if the subproces has not terminated, then this parameter is ignored) + * @param jniPath - if nonnull and nonempty, then it specifies the subprocess's default JNI library location + * @param classPath - if nonnull and nonempty, then it specifies the subprocess's default CLASSPATH, + * else we'll use System.getProperty("java.class.path") + * @param callback - the handler that will receive outputs from the task + * @throws IOException - if a previous task is still busy executing + * @throws IOException - if an error occurred in launching a sub JVM or talking to it + */ + public static void run + (final WorkerTask task, int newmem, int newstack, String jniPath, String classPath, final WorkerCallback callback) + throws IOException { + if (classPath==null || classPath.length()==0) classPath = System.getProperty("java.class.path"); + synchronized(WorkerEngine.class) { + final Process sub; + if (latest_manager!=null && latest_manager.isAlive()) throw new IOException("Subprocess still performing the last task."); + try { + if (latest_sub!=null) latest_sub.exitValue(); latest_manager=null; latest_sub=null; + } catch(IllegalThreadStateException ex) { } + if (latest_sub==null) { + String java = "java", javahome = System.getProperty("java.home"); + if (javahome!=null && javahome.length()>0) { + // First try "[JAVAHOME]/bin/java" + File f = new File(javahome + File.separatorChar + "bin" + File.separatorChar + "java"); + // Then try "[JAVAHOME]/java" + if (!f.isFile()) f = new File(javahome + File.separatorChar + "java"); + // All else, try "java" (and let the Operating System search the program path...) + if (f.isFile()) java = f.getAbsolutePath(); + } + String debug = "yes".equals(System.getProperty("debug")) ? "yes" : "no"; + if (jniPath!=null && jniPath.length()>0) + sub = Runtime.getRuntime().exec(new String[] { + java, + "-Xmx" + newmem + "m", + "-Xss" + newstack + "k", + "-Djava.library.path=" + jniPath, + "-Ddebug=" + debug, + "-cp", classPath, WorkerEngine.class.getName(), + Version.buildDate(), ""+Version.buildNumber() + }); + else + sub = Runtime.getRuntime().exec(new String[] { + java, + "-Xmx" + newmem + "m", + "-Xss" + newstack + "k", + "-Ddebug=" + debug, + "-cp", classPath, WorkerEngine.class.getName(), + Version.buildDate(), ""+Version.buildNumber() + }); + latest_sub = sub; + } else { + sub = latest_sub; + } + latest_manager = new Thread(new Runnable() { + public void run() { + ObjectInputStream sub2main = null; + ObjectOutputStream main2sub = null; + try { + main2sub = new ObjectOutputStream(wrap(sub.getOutputStream())); main2sub.writeObject(task); main2sub.close(); + sub2main = new ObjectInputStream(wrap(sub.getInputStream())); + } catch(Throwable ex) { + sub.destroy(); Util.close(main2sub); Util.close(sub2main); + synchronized(WorkerEngine.class) { if (latest_sub != sub) return; callback.fail(); return; } + } + while(true) { + synchronized(WorkerEngine.class) { if (latest_sub != sub) return; } + Object x; + try { + x = sub2main.readObject(); + } catch(Throwable ex) { + sub.destroy(); Util.close(sub2main); + synchronized(WorkerEngine.class) { if (latest_sub != sub) return; callback.fail(); return; } + } + synchronized(WorkerEngine.class) { + if (latest_sub != sub) return; if (x==null) {callback.done(); return;} else callback.callback(x); + } + } + } + }); + latest_manager.start(); + } + } + + /** This is the entry point for the sub JVM. + * + *

Behavior is very simple: it reads a WorkerTask object from System.in, then execute it, then read another... + * If any error occurred, or if it's disconnected from the parent process's pipe, it then terminates itself + * (since we assume the parent process will notice it and react accordingly) + */ + public static void main(String[] args) { + // To prevent people from accidentally invoking this class, or invoking it from an incompatible version, + // we add a simple sanity check on the command line arguments + if (args.length!=2) halt("#args should be 2 but instead is "+args.length, 1); + if (!args[0].equals(Version.buildDate())) halt("BuildDate mismatch: "+args[0]+" != "+Version.buildDate(), 1); + if (!args[1].equals("" + Version.buildNumber())) halt("BuildNumber mismatch: "+args[1]+" != "+Version.buildNumber(), 1); + // To prevent a zombie process, we set a default handler to terminate itself if something does slip through our detection + Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() { + public void uncaughtException(Thread t, Throwable e) { halt("UncaughtException: "+e, 1); } + }); + // Redirect System.in, System.out, System.err to no-op (so that if a task tries to read/write to System.in/out/err, + // those reads and writes won't mess up the ObjectInputStream/ObjectOutputStream) + System.setIn(wrap((InputStream)null)); + System.setOut(new PrintStream(wrap((OutputStream)null))); + System.setErr(new PrintStream(wrap((OutputStream)null))); + final FileInputStream in = new FileInputStream(FileDescriptor.in); + final FileOutputStream out = new FileOutputStream(FileDescriptor.out); + // Preload these 3 libraries; on MS Windows with JDK 1.6 this seems to prevent freezes + try { System.loadLibrary("minisat"); } catch(Throwable ex) { } + try { System.loadLibrary("minisatprover"); } catch(Throwable ex) { } + try { System.loadLibrary("zchaff"); } catch(Throwable ex) { } + // Now we repeat the following read-then-execute loop + Thread t = null; + while(true) { + final WorkerTask task; + try { + System.gc(); // while we're waiting for the next task, we might as well encourage garbage collection + ObjectInputStream oin = new ObjectInputStream(wrap(in)); + task = (WorkerTask) oin.readObject(); + oin.close(); + } catch(Throwable ex) { + halt("Can't read task: "+ex, 1); + return; + } + // Our main thread has a loop that keeps "attempting" to read bytes from System.in, + // and delegate the actual task to a separate "worker thread". + // This way, if the parent process terminates, then this subprocess should see it almost immediately + // (since the inter-process pipe will be broken) and will terminate (regardless of the status of the worker thread) + if (t!=null && t.isAlive()) { + // We only get here if the previous subtask has informed the parent that the job is done, and that the parent + // then issued another job. So we wait up to 5 seconds for the worker thread to confirm its termination. + // If 5 seconds is up, then we assume something terrible has happened. + try {t.join(5000); if (t.isAlive()) halt("Timeout", 1);} catch (Throwable ex) {halt("Timeout: "+ex, 1);} + } + t = new Thread(new Runnable() { + public void run() { + ObjectOutputStream x = null; + Throwable e = null; + try { + x = new ObjectOutputStream(wrap(out)); + final ObjectOutputStream xx = x; + WorkerCallback y = new WorkerCallback() { + public void callback(Object x) { try {xx.writeObject(x);} catch(IOException ex) {halt("Callback: "+ex, 1);} } + public void done() { } + public void fail() { } + }; + task.run(y); + x.writeObject(null); + x.flush(); + } catch(Throwable ex) { + e=ex; + } + for(Throwable t=e; t!=null; t=t.getCause()) if (t instanceof OutOfMemoryError || t instanceof StackOverflowError) { + try { System.gc(); x.writeObject(t); x.flush(); } catch(Throwable ex2) { } finally { halt("Error: "+e, 2); } + } + if (e instanceof Err) { + try { System.gc(); x.writeObject(e); x.writeObject(null); x.flush(); } catch(Throwable t) { halt("Error: "+e, 1); } + } + if (e!=null) { + try { System.gc(); x.writeObject(e); x.flush(); } catch(Throwable t) { } finally { halt("Error: "+e, 1); } + } + Util.close(x); // avoid memory leaks + } + }); + t.start(); + } + } + + /** This method terminates the caller's process. */ + private static void halt(String reason, int exitCode) { Runtime.getRuntime().halt(exitCode); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/XMLNode.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/XMLNode.java new file mode 100644 index 00000000..11b2398b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4/XMLNode.java @@ -0,0 +1,479 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.Map.Entry; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; + +/** Immutable; this class represents an XML element node. */ + +public final class XMLNode implements Iterable { + + /** The type of the element; never null. */ + private String type = ""; + + /** If type is text, this is the text. */ + private String text = ""; + + /** The set of (key,value) pairs; never null. */ + private final Map map = new LinkedHashMap(); + + /** The list of direct children nodes. */ + private final List sub = new ArrayList(); + + /** Constructs an empty XMLNode object. */ + private XMLNode() { } + + /** Returns the number of direct subnodes. */ + public int count() { return sub.size(); } + + /** Returns an unmodifiable view of the attributes. */ + public Set> attributes() { return Collections.unmodifiableMap(map).entrySet(); } + + /** Dump the content to a String. */ + @Override public String toString() { + StringBuilder sb = new StringBuilder(); + toString(sb, 0); + return sb.toString(); + } + + /** Dump the content to a StringBuilder. */ + public void toString(StringBuilder sb, int indent) { + for(int i=0; i0) { Util.encodeXML(sb, text); sb.append('\n'); return; } + Util.encodeXMLs(sb, "<", type); + for(Map.Entry e: map.entrySet()) { + Util.encodeXMLs(sb, " ", e.getKey(), "=\"", e.getValue(), "\""); + } + if (sub.size()==0) { sb.append("/>\n"); return; } + sb.append(">\n"); + for(XMLNode x:sub) x.toString(sb, indent+2); + for(int i=0; i\n"); + } + + /** Simple parser based on XML Specification 1.0 taking into account XML Specification Errata up to 2008/Jan/18. */ + private static final class XMLParser { + + /** True if we want to read text data also. */ + private final boolean wantText; + + /** The reader for the input XML file. */ + private final Reader reader; + + /** The current x position in the file. */ + private int x = 1; + + /** The current y position in the file. */ + private int y = 1; + + /** The current "readahead" character; -2 if the readahead cache is empty; -1 if EOF is detected; otherwise it is one char. */ + private int read = (-2); + + /** Constructor is private, since we want only XMLNode to be able to construct an instance of this class. */ + private XMLParser(Reader reader, boolean wantText) { + this.wantText = wantText; + if (reader instanceof BufferedReader) this.reader = reader; else this.reader = new BufferedReader(reader); + } + + /** Throws an IOException with the given msg, and associate with it the current line and column location. */ + private void malform(String msg) throws IOException { throw new IOException("Error at line "+y+" column "+x+": "+msg); } + + /** Read the next character. + * @throws IOException if end-of-file is reached. + * @throws IOException if an I/O error occurred. + */ + private int read() throws IOException { + if (read<(-1)) read=reader.read(); + if (read<0) { malform("Unexpected end of file."); } else if (read=='\n') { x=1; y++; } else { x++; } + int ans = read; + read = -2; + return ans; + } + + /** Peek without consuming the next character, or return -1 if end-of-file is reached. + * @throws IOException if an I/O error occurred. + */ + private int peek() throws IOException { + if (read<(-1)) read=reader.read(); + return read; + } + + /** Consume up to and including the consecutive characters "char1" and "char2". + * @throws IOException if we reached end-of-file without seeing the pattern. + * @throws IOException if an I/O error occurred. + */ + private void skipUntil(int char1, int char2) throws IOException { + while(true) { + int ch = read(); + if (ch==char1 && peek()==char2) { read=(-2); return; } + } + } + + /** If the next N characters match the given string (where N == length of string), then consume them, else throw IOException. + * @throws IOException if the next N characters do not match the given string. + * @throws IOException if an I/O error occurred. + */ + private void expect(String string) throws IOException { + int saveX=x, saveY=y; + for(int i=0; i' + * AttlistDecl ::= '' + * elementdecl ::= '' + * EntityDecl ::= '' + * PI ::= '' + * Comment ::= '' + * Misc ::= Comment | PI | S + * doctypedecl ::= '' + * intSubset ::= (elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment | PEReference | S)* + * + * SkipNondata(false) will skip zero or more instance of the below, and thus it will consume (Misc | doctypedecl)* + * SPACE TAB CR LF + * + * + * '' + * + * SkipNondata(true) will skip zero or more instances of the below, and thus it will consume intSubset* + * SPACE TAB CR LF + * + * + * '' + * '[' followed by SkipNondata(true) followed by ']' + * '...' + * "..." + * any char that is not '<' nor '>' nor '[' nor ']' nor ''' nor '"' + */ + + /** Skip as much nondata as possible, then return the first character after that (or -1 if we end up at end-of-file). + *

Specifically, skipNondata(false) consumes (Misc | doctypedecl)* from XML specification + *

Likewise, skipNondata(true) consumes (intSubset)* from XML specification + * @throws IOException if the XML input is malformed. + * @throws IOException if an I/O error occurred. + */ + private int skipNondata(boolean inner) throws IOException { + while(true) { + int ch = peek(); + if (ch<0) return -1; + read = -2; + if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') continue; + if (ch == '<') { + ch = read(); + if (ch == '?') { skipUntil('?', '>'); continue; } + if (ch != '!') { read = ch ; return '<'; } + if (peek() == '-') { + read = -2; + if (read()!='-') malform("Expects start of "); + skipUntil('-', '-'); + if (read()!='>') malform("Expects end of "); + continue; + } + if (skipNondata(true)!='>') malform("Expects end of "); + } + else if (!inner || ch == ']' || ch=='>') { return ch; } + else if (ch == '[') { if (skipNondata(true)!=']') malform("Expects end of [...]"); } + else if (ch == '\'' || ch == '\"') { while(read()!=ch) { } } + } + } + + /** Parse an element name or attribute name. + * @throws IOException if the XML input is malformed. + * @throws IOException if an I/O error occurred. + */ + private String parseName() throws IOException { + StringBuilder sb = new StringBuilder(); + while(true) { + int ch = read(); + if (ch==' ' || ch=='\t' || ch=='\r' || ch=='\n' || ch=='=' || ch=='/' || ch=='<' || ch=='>' || ch=='[' || ch==']') { + read=ch; + return sb.toString(); + } + sb.append((char)ch); + } + } + + /** Parse a value up to delim (which is always either ' or "), assuming the initial ' or " has already been consumed. + * @throws IOException if the XML input is malformed. + * @throws IOException if an I/O error occurred. + */ + private String parseValue(int delim) throws IOException { + StringBuilder sb = new StringBuilder(), sb2 = null; + while(true) { + int ch=read(); + if (ch==delim) return sb.toString(); + if (ch=='&') { + if (sb2==null) sb2=new StringBuilder(); else sb2.setLength(0); + while((ch=read()) != ';') sb2.append((char)ch); + if (sb2.length()>2 && sb2.charAt(0)=='#' && sb2.charAt(1)=='x') { + try { ch=Integer.parseInt(sb2.substring(2), 16); } catch(NumberFormatException ex) { ch=(-1); } + } else if (sb2.length()>1 && sb2.charAt(0)=='#'){ + try { ch=Integer.parseInt(sb2.substring(1)); } catch(NumberFormatException ex) { ch=(-1); } + } else { + String name = sb2.toString(); + if (name.equals("amp")) ch='&'; + else if (name.equals("quot")) ch='"'; + else if (name.equals("apos")) ch='\''; + else if (name.equals("lt")) ch='<'; + else if (name.equals("gt")) ch='>'; + else ch=(-1); + } + if (ch<0) malform("The entity \"&"+sb2.toString()+";\" is unknown."); + } + sb.append((char)ch); + } + } + + /* + * Below are the grammar rules for "element": + * ========================================== + * + * element ::= '<' Name (S Name S? '=' S? AttValue)* S? '/>' + * | '<' Name (S Name S? '=' S? AttValue)* S? '>' content '' + * + * content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)* + * CDSect ::= '' Char*)) ']]>' + * CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) + */ + + /** Parse an element (and all its subelements), assuming the initial "less than" sign has already been consumed. + * @throws IOException if the XML input is malformed. + * @throws IOException if an I/O error occurred. + */ + private void parseElement(XMLNode target) throws IOException { + target.type = parseName(); + while(true) { + boolean space = false; + int ch = read(); + if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') { space=true; ch=skipSpace(); } + if (ch == '=') malform("Unexpected '='"); + if (ch == '/') { + if (read()!='>') malform("Expects '/>'"); + break; + } + if (ch == '>') { + parseContent(target); + if (!target.type.equals(parseName())) malform("Start tag and end tag must have matching types."); + if (skipSpace()!='>') malform("Expects ''"); + break; + } + if (!space) malform("Whitespace needed before a (key,value) pair."); + read = ch; + String key = parseName(); + if (key.length()==0) malform("Attribute name cannot be empty."); + if (skipSpace()!='=') malform("Expects = after the attribute name."); + ch = skipSpace(); + if (ch != '\'' && ch != '\"') malform("Expects \' or \" as the start of the attribute value."); + String value = parseValue(ch); + target.map.put(key, value); + } + } + + /** Parses the content until the rightful closing "LESS THAN SIGN followed by FORWARD SLASH" are both consumed. + * @throws IOException if the XML input is malformed. + * @throws IOException if an I/O error occurred. + */ + private void parseContent(XMLNode parent) throws IOException { + StringBuilder sb = wantText ? new StringBuilder() : null; + again: + while(true) { + if (sb==null) { + while(read()!='<') {} + } else { + sb.append(parseValue('<').replace('\r',' ').replace('\n', ' ')); + parent.addText(sb); + } + int ch=read(); + if (ch=='/') return; + if (ch=='?') { skipUntil('?', '>'); continue; } + if (ch=='!') { + ch=read(); + if (ch=='-') { + if (read()!='-') malform("Expects start of "); + skipUntil('-', '-'); + if (read()!='>') malform("Expects end of "); + continue; + } + if (ch!='[') malform("Expects "); + expect("CDATA["); + for(int ah=0,bh=0; ;) { + ch=read(); + if (ah==']' && bh==']' && ch=='>') { + parent.addText(sb); + continue again; + } else { + if (ah>0 && sb!=null) sb.append((char)ah); + ah=bh; bh=ch; + } + } + } + read = ch; + XMLNode newElem = new XMLNode(); + parseElement(newElem); + parent.sub.add(newElem); + } + } + } + + /** Add a text node by removing all contents from the given StringBuilder and clearing that StringBuilder. */ + private void addText(StringBuilder stringBuilder) { + if (stringBuilder==null || stringBuilder.length()==0) return; + XMLNode x = new XMLNode(); + x.text = stringBuilder.toString(); + stringBuilder.setLength(0); + sub.add(x); + } + + /** Constructs the root XMLNode by parsing an entire XML document, then close the reader afterwards. */ + public XMLNode(Reader reader, boolean parseText) throws IOException { + try { + // document ::= Misc* doctypedecl? Misc* element Misc* + XMLParser parser = new XMLParser(reader, parseText); + if (parser.skipNondata(false)!='<') parser.malform("Expects start of root element."); + parser.parseElement(this); + if (parser.skipNondata(false)!=(-1)) parser.malform("Expects end of file."); + } finally { + Util.close(reader); + } + } + + /** Constructs the root XMLNode by parsing an entire XML document, then close the reader afterwards. */ + public XMLNode(Reader reader) throws IOException { + try { + // document ::= Misc* doctypedecl? Misc* element Misc* + XMLParser parser = new XMLParser(reader, false); + if (parser.skipNondata(false)!='<') parser.malform("Expects start of root element."); + parser.parseElement(this); + if (parser.skipNondata(false)!=(-1)) parser.malform("Expects end of file."); + } finally { + Util.close(reader); + } + } + + /** Constructs the root XMLNode by parsing an entire XML document. */ + public XMLNode(File file) throws IOException { + FileInputStream fis = null; + InputStreamReader reader = null; + try { + // document ::= Misc* doctypedecl? Misc* element Misc* + fis = new FileInputStream(file); + reader = new InputStreamReader(fis, "UTF-8"); + XMLParser parser = new XMLParser(reader, false); + if (parser.skipNondata(false)!='<') parser.malform("Expects start of root element."); + parser.parseElement(this); + if (parser.skipNondata(false)!=(-1)) parser.malform("Expects end of file."); + } finally { + Util.close(reader); + Util.close(fis); + } + } + + /** Returns the type of the element. */ + public String getType() { return type; } + + /** Returns the text if this is a text node, returns "" otherwise. */ + public String getText() { return text; } + + /** Returns true if the type of this element is equal to the given type. */ + public boolean is(String type) { return this.type.equals(type); } + + /** Returns a read-only iterator over the immediate subelements. */ + public Iterator iterator() { return Collections.unmodifiableList(sub).iterator(); } + + /** Returns a read-only iteration of the immediate subelements whose type is equal to the given type. */ + public Iterable getChildren(final String type) { + return new Iterable() { + public Iterator iterator() { + return new Iterator() { + private final Iterator it = sub.iterator(); + private XMLNode peek = null; + public boolean hasNext() { + while(true) { + if (peek!=null && peek.type.equals(type)) return true; + if (!it.hasNext()) return false; else peek=it.next(); + } + } + public XMLNode next() { if (!hasNext()) throw new NoSuchElementException(); XMLNode ans=peek; peek=null; return ans; } + public void remove() { throw new UnsupportedOperationException(); } + }; + } + }; + } + + /** Returns the value associated with the given attribute name; if the attribute doesn't exist, return "". */ + public String getAttribute(String name) { + String ans = map.get(name); + return (ans==null) ? "" : ans; + } + + /** Returns the value associated with the given attribute name; if the attribute doesn't exist, return the defaultValue. */ + public String getAttribute(String name, String defaultValue) { + String ans = map.get(name); + return (ans==null) ? defaultValue : ans; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Attr.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Attr.java new file mode 100644 index 00000000..0b576d74 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Attr.java @@ -0,0 +1,133 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import edu.mit.csail.sdg.alloy4.Pos; + +/** Immutable; represents attributes that can be associated with Signatures and some other AST objects. */ + +public final class Attr { + + /** This class contains all possible attribute types. */ + public enum AttrType { + + /** WHERE; if a Sig has a WHERE attribute, it defines where the sig was declared in the user model. */ + WHERE("where"), + + /** ABSTRACT; if a PrimSig is abstract, it is equal to the union of its subsigs. */ + ABSTRACT("abstract"), + + /** SOME; if a Sig is some, it has at least one atom. */ + SOME("some"), + + /** ONE; if a Sig is one, it has exactly one atom. */ + ONE("one"), + + /** LONE; if a Sig is lone, it has at most one atom. */ + LONE("lone"), + + /** EXACT; if a SubsetSig is exact, it is equal to the union of its parents. */ + EXACT("exact"), + + /** SUBSIG; every PrimSig (including the builtin sigs) has the SUBSIG attribute set, and the SUBSET attribute unset. */ + SUBSIG("subsig"), + + /** SUBSET; every SubsetSig has the SUBSET attribute set, and the SUBSIG attribute unset. */ + SUBSET("subset"), + + /** META; if a Sig has the META attribute, it means it is a META atom corresponding to some real signature or field. */ + META("meta"), + + /** PRIVATE; if a Sig has the PRIVATE attribute, it means its label is private within the same module. */ + PRIVATE("private"), + + /** BUILTIN; every builtin Sig has the BUILTIN attribute, and every non-builtin Sig does not. */ + BUILTIN("builtin"), + + /** ENUM; if a PrimSig has the ENUM attribute, it is toplevel and abstract and has only singleton children. */ + ENUM("enum"); + + /** The label for this attribute type. */ + private final String label; + + /** Constructor for this attribute type. */ + private AttrType(String label) { this.label = label; } + + /** Construct an attribute of this type with this position; if pos==null, it is treated as Pos.UNKNOWN. */ + public final Attr make(Pos pos) { return new Attr(this, pos); } + + /** Construct an attribute of this type with this position; if pos==null, this method returns null. */ + public final Attr makenull(Pos pos) { return pos==null ? null : new Attr(this, pos); } + + /** Returns the combined position for all Attribute of this type in the given array; null entries in the collection are ignored; if none are found we return null. */ + public Pos find(Attr... attributes) { + Pos p = null; + if (attributes!=null) for(Attr a: attributes) if (a!=null && a.type==this) p = a.pos.merge(p); + return p; + } + + /** {@inheritDoc} */ + @Override public final String toString() { return label; } + } + + /** The type of this attribute. */ + public final AttrType type; + + /** The position associated with this attribute. */ + public final Pos pos; + + /** ABSTRACT; if a PrimSig is abstract, it is equal to the union of its subsigs. */ + public static final Attr ABSTRACT = new Attr(AttrType.ABSTRACT, null); + + /** SOME; if a Sig is some, it has at least one atom. */ + public static final Attr SOME = new Attr(AttrType.SOME, null); + + /** ONE; if a Sig is one, it has exactly one atom. */ + public static final Attr ONE = new Attr(AttrType.ONE, null); + + /** LONE; if a Sig is lone, it has at most one atom. */ + public static final Attr LONE = new Attr(AttrType.LONE, null); + + /** EXACT; if a SubsetSig is exact, it is equal to the union of its parents. */ + public static final Attr EXACT = new Attr(AttrType.EXACT, null); + + /** SUBSIG; every PrimSig (including the builtin sigs) has the SUBSIG attribute set, and the SUBSET attribute unset. */ + public static final Attr SUBSIG = new Attr(AttrType.SUBSIG, null); + + /** SUBSET; every SubsetSig has the SUBSET attribute set, and the SUBSIG attribute unset. */ + public static final Attr SUBSET = new Attr(AttrType.SUBSET, null); + + /** META; if a Sig has the META attribute, it means it is a META atom corresponding to some real signature or field. */ + public static final Attr META = new Attr(AttrType.META, null); + + /** PRIVATE; if a Sig has the PRIVATE attribute, it means its label is private within the same module. */ + public static final Attr PRIVATE = new Attr(AttrType.PRIVATE, null); + + /** BUILTIN; every builtin Sig has the BUILTIN attribute, and every non-builtin Sig does not. */ + public static final Attr BUILTIN = new Attr(AttrType.BUILTIN, null); + + /** ENUM; if a PrimSig has the ENUM attribute, it is toplevel and abstract and has only singleton children. */ + public static final Attr ENUM = new Attr(AttrType.ENUM, null); + + /** Construct an attribute of the given type with the given position; if pos==null, it is treated as Pos.UNKNOWN. */ + private Attr(AttrType type, Pos pos) { + this.type = type; + this.pos = (pos==null ? Pos.UNKNOWN : pos); + } + + /** {@inheritDoc} */ + @Override public final String toString() { return type.label; } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Browsable.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Browsable.java new file mode 100644 index 00000000..a95b7a57 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Browsable.java @@ -0,0 +1,107 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import java.awt.BorderLayout; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.util.ArrayList; +import java.util.List; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.border.EmptyBorder; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Listener; +import edu.mit.csail.sdg.alloy4.OurTree; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Util; + +/** This abstract class represents a node that can be browsed in the graphical parse tree viewer. */ + +public abstract class Browsable { + + /** Returns a Pos object representing the position of this Expr. */ + public Pos pos() { return Pos.UNKNOWN; } + + /** Returns a Pos object representing the entire span of this Expr and all its subexpressions. */ + public Pos span() { return pos(); } + + /** Returns the description (as HTML) to show for this node. */ + public abstract String getHTML(); + + /** Returns a list of subnodes for this node. */ + public abstract List getSubnodes(); + + /** Construct a Browsable node with the given HTML description and the given single subnode. */ + public static final Browsable make(final Pos pos, final Pos span, final String html, Browsable subnode) { + return make(pos, span, html, Util.asList(subnode)); + } + + /** Construct a Browsable node with the given HTML description and the given single subnode. */ + public static final Browsable make(final String html, Browsable subnode) { + return make(Pos.UNKNOWN, Pos.UNKNOWN, html, Util.asList(subnode)); + } + + /** Construct a Browsable node with the given HTML description and the given 0 or more subnodes. */ + public static final Browsable make(final String html, final List subnodes) { + return make(Pos.UNKNOWN, Pos.UNKNOWN, html, subnodes); + } + + /** Construct a Browsable node with the given HTML description and the given 0 or more subnodes. */ + public static final Browsable make(final Pos pos, final Pos span, final String html, final List subnodes) { + final ConstList constlist = ConstList.make(subnodes); + return new Browsable() { + @Override public Pos pos() { return pos; } + @Override public Pos span() { return span; } + @Override public String getHTML() { return html; } + @Override public List getSubnodes() { return constlist; } + }; + } + + /** Display this node and its subnodes as a tree; if listener!=null, it will receive OurTree.Event.SELECT events when nodes are selected. */ + public final JFrame showAsTree(Listener listener) { + final OurTree tree = new OurTree(12) { + private static final long serialVersionUID = 0; + private final boolean onWindows = Util.onWindows(); + {do_start();} + @Override public String convertValueToText(Object val, boolean selected, boolean expanded, boolean leaf, int row, boolean focus) { + String c = ">"; + String x = (val instanceof Browsable) ? ((Browsable)val).getHTML() : Util.encode(String.valueOf(val)); + if (onWindows) c = selected ? " style=\"color:#ffffff;\">" : " style=\"color:#000000;\">"; + return ""; + } + @Override public List do_ask(Object parent) { + if (parent instanceof Browsable) return ((Browsable)parent).getSubnodes(); else return new ArrayList(); + } + @Override public Object do_root() { return Browsable.this; } + }; + tree.setBorder(new EmptyBorder(3, 3, 3, 3)); + final JScrollPane scr = new JScrollPane(tree, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + scr.addFocusListener(new FocusListener() { + public void focusGained(FocusEvent e) { tree.requestFocusInWindow(); } + public void focusLost(FocusEvent e) { } + }); + final JFrame x = new JFrame("Parse Tree"); + x.setLayout(new BorderLayout()); + x.add(scr, BorderLayout.CENTER); + x.pack(); + x.setSize(500, 500); + x.setLocationRelativeTo(null); + x.setVisible(true); + if (listener!=null) tree.listeners.add(listener); + return x; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Command.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Command.java new file mode 100644 index 00000000..f6a92038 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Command.java @@ -0,0 +1,207 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.ConstList.TempList; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; + +/** Immutable; reresents a "run" or "check" command. + * + *

Invariant: expects == -1, 0, or 1 + *

Invariant: overall >= -1 + *

Invariant: bitwidth >= -1 + *

Invariant: maxseq >= -1 + *

Invariant: maxstring >= -1 + */ + +public final class Command extends Browsable { + + /** If nonnull, it means this command depends on this parent command. */ + public final Command parent; + + /** The position in the original file where this command was declared; never null. */ + public final Pos pos; + + /** The label for the command; it is just for pretty-printing and does not have to be unique. */ + public final String label; + + /** true if this is a "check"; false if this is a "run". */ + public final boolean check; + + /** The overall scope (0 or higher) (Or -1 if there is no overall scope). */ + public final int overall; + + /** The integer bitwidth (0 or higher) (Or -1 if it was not specified). */ + public final int bitwidth; + + /** The maximum sequence length (0 or higher) (Or -1 if it was not specified). */ + public final int maxseq; + + /** The number of String atoms to allocate (0 or higher) (Or -1 if it was not specified). */ + public final int maxstring; + + /** The expected answer (either 0 or 1) (Or -1 if there is no expected answer). */ + public final int expects; + + /** The formula associated with this command. */ + public final Expr formula; + + /** The list of scopes. */ + public final ConstList scope; + + /** This stores a list of Sig whose scope shall be considered "exact", but we may or may not know what its scope is yet. */ + public final ConstList additionalExactScopes; + + /** Returns a human-readable string that summarizes this Run or Check command. */ + @Override public final String toString() { + if (parent!=null) { Command p=parent; while(p.parent!=null) p=p.parent; return p.toString(); } + boolean first=true; + StringBuilder sb=new StringBuilder(check?"Check ":"Run ").append(label); + if (overall>=0 && (bitwidth>=0 || maxseq>=0 || scope.size()>0)) + sb.append(" for ").append(overall).append(" but"); + else if (overall>=0) + sb.append(" for ").append(overall); + else if (bitwidth>=0 || maxseq>=0 || scope.size()>0) + sb.append(" for"); + if (bitwidth>=0) { sb.append(" ").append(bitwidth).append(" int"); first=false; } + if (maxseq>=0) { sb.append(first?" ":", ").append(maxseq).append(" seq"); first=false; } + for(CommandScope e:scope) { + sb.append(first?" ":", ").append(e); + first=false; + } + if (expects>=0) sb.append(" expect ").append(expects); + return sb.toString(); + } + + /** Constructs a new Command object. + * + * @param check - true if this is a "check"; false if this is a "run" + * @param overall - the overall scope (0 or higher) (-1 if no overall scope was specified) + * @param bitwidth - the integer bitwidth (0 or higher) (-1 if it was not specified) + * @param maxseq - the maximum sequence length (0 or higher) (-1 if it was not specified) + * @param formula - the formula that must be satisfied by this command + */ + public Command(boolean check, int overall, int bitwidth, int maxseq, Expr formula) throws ErrorSyntax { + this(null, "", check, overall, bitwidth, maxseq, -1, null, null, formula, null); + } + + /** Constructs a new Command object. + * + * @param pos - the original position in the file (must not be null) + * @param label - the label for this command (it is only for pretty-printing and does not have to be unique) + * @param check - true if this is a "check"; false if this is a "run" + * @param overall - the overall scope (0 or higher) (-1 if no overall scope was specified) + * @param bitwidth - the integer bitwidth (0 or higher) (-1 if it was not specified) + * @param maxseq - the maximum sequence length (0 or higher) (-1 if it was not specified) + * @param expects - the expected value (0 or 1) (-1 if no expectation was specified) + * @param scope - a list of scopes (can be null if we want to use default) + * @param additionalExactSig - a list of sigs whose scope shall be considered exact though we may or may not know what the scope is yet + * @param formula - the formula that must be satisfied by this command + */ + public Command(Pos pos, String label, boolean check, int overall, int bitwidth, int maxseq, int expects, Iterable scope, Iterable additionalExactSig, Expr formula, Command parent) { + if (pos==null) pos = Pos.UNKNOWN; + this.formula = formula; + this.pos = pos; + this.label = (label==null ? "" : label); + this.check = check; + this.overall = (overall<0 ? -1 : overall); + this.bitwidth = (bitwidth<0 ? -1 : bitwidth); + this.maxseq = (maxseq<0 ? -1 : maxseq); + this.maxstring = (-1); + this.expects = (expects<0 ? -1 : (expects>0 ? 1 : 0)); + this.scope = ConstList.make(scope); + this.additionalExactScopes = ConstList.make(additionalExactSig); + this.parent = parent; + } + + /** Constructs a new Command object where it is the same as the current object, except with a different formula. */ + public Command change(Expr newFormula) { + return new Command(pos, label, check, overall, bitwidth, maxseq, expects, scope, additionalExactScopes, newFormula, parent); + } + + /** Constructs a new Command object where it is the same as the current object, except with a different scope. */ + public Command change(ConstList scope) { + return new Command(pos, label, check, overall, bitwidth, maxseq, expects, scope, additionalExactScopes, formula, parent); + } + + /** Constructs a new Command object where it is the same as the current object, except with a different list of "additional exact sigs". */ + public Command change(Sig... additionalExactScopes) { + return new Command(pos, label, check, overall, bitwidth, maxseq, expects, scope, Util.asList(additionalExactScopes), formula, parent); + } + + /** Constructs a new Command object where it is the same as the current object, except with a different scope for the given sig. */ + public Command change(Sig sig, boolean isExact, int newScope) throws ErrorSyntax { return change(sig, isExact, newScope, newScope, 1); } + + /** Constructs a new Command object where it is the same as the current object, except with a different scope for the given sig. */ + public Command change(Sig sig, boolean isExact, int startingScope, int endingScope, int increment) throws ErrorSyntax { + for(int i=0; i(scope).set(i, sc).makeConst()); + } + CommandScope sc = new CommandScope(Pos.UNKNOWN, sig, isExact, startingScope, endingScope, increment); + return change(Util.append(scope, sc)); + } + + /** Helper method that returns the scope corresponding to a given sig (or return null if the sig isn't named in this command) */ + public CommandScope getScope(Sig sig) { + for(int i=0; i getGrowableSigs() { + TempList answer = new TempList(); + for(CommandScope sc: scope) if (sc.startingScope != sc.endingScope) answer.add(sc.sig); + return answer.makeConst(); + } + + /** Return a modifiable copy of the set of all String constants used in this command or in any facts embedded in this command. */ + public Set getAllStringConstants(Iterable sigs) throws Err { + final Set set = new HashSet(); + final VisitQuery findString = new VisitQuery() { + @Override public final Object visit(ExprConstant x) throws Err { + if (x.op==ExprConstant.Op.STRING) set.add(x.string); + return null; + } + }; + for(Command c=this; c!=null; c=c.parent) c.formula.accept(findString); + for(Sig s: sigs) { + for(Expr e: s.getFacts()) e.accept(findString); + for(Decl d: s.getFieldDecls()) d.expr.accept(findString); + } + return set; + } + + /** {@inheritDoc} */ + @Override public final Pos pos() { return pos; } + + /** {@inheritDoc} */ + @Override public final Pos span() { return pos; } + + /** {@inheritDoc} */ + @Override public String getHTML() { return (check?"check ":"run ") + label; } + + /** {@inheritDoc} */ + @Override public List getSubnodes() { return formula==null ? (new ArrayList(0)) : Util.asList(formula); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/CommandScope.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/CommandScope.java new file mode 100644 index 00000000..5ab2cf84 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/CommandScope.java @@ -0,0 +1,93 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Util; + +/** Immutable; reresents a scope in a "run" or "check" command. + * + *

Invariant: sig != null + *

Invariant: endingScope >= startingScope >= 0 + *

Invariant: increment > 0 + */ + +public class CommandScope { + + /** The position in the original source file where this scope was declared; can be Pos.UNKNOWN if unknown. */ + public final Pos pos; + + /** The sig whose scope is being given by this CommandScope object. */ + public final Sig sig; + + /** True iff the scope is an exact scope. */ + public final boolean isExact; + + /** The starting scope. */ + public final int startingScope; + + /** The ending scope; if this sig is not a growing sig, then this.startingScope==this.endingScope. */ + public final int endingScope; + + /** The scope increment; if this sig is not a growing sig, then this.increment is ignored. */ + public final int increment; + + /** Construct a new CommandScope object. + * @param sig - the sig for this scope + * @param isExact - true iff the scope is intended to be exact + * @param scope - the scope + * @throws ErrorSyntax if scope is less than zero + */ + public CommandScope(Sig sig, boolean isExact, int scope) throws ErrorSyntax { this(null, sig, isExact, scope, scope, 1); } + + /** Construct a new CommandScope object. + * @param pos - the position where this scope is given + * @param sig - the sig for this scope + * @param isExact - true iff the scope is intended to be exact + * @param startingScope - the starting scope + * @param endingScope - the ending scope (if this sig is not intended to be growable, then startingScope should equal endingScope) + * @param increment - the scope increment (if this sig is not intended to be growable, then this field is ignored) + * @throws ErrorSyntax if startingScope is less than zero + * @throws ErrorSyntax if endingScope is less than startingScope + * @throws ErrorSyntax if increment is less than one + */ + public CommandScope(Pos pos, Sig sig, boolean isExact, int startingScope, int endingScope, int increment) throws ErrorSyntax { + if (pos == null) pos = Pos.UNKNOWN; + if (sig == null) throw new NullPointerException(); + if (startingScope < 0) throw new ErrorSyntax(pos, "Sig "+sig+" cannot have a negative starting scope ("+startingScope+")"); + if (endingScope < 0) throw new ErrorSyntax(pos, "Sig "+sig+" cannot have a negative ending scope ("+endingScope+")"); + if (endingScope < startingScope) throw new ErrorSyntax(pos, "Sig "+sig+" cannot have an ending scope ("+endingScope+") smaller than its starting scope ("+startingScope+")"); + if (startingScope == endingScope) increment = 1; + if (increment < 1) throw new ErrorSyntax(pos, "Sig "+sig+"'s increment value cannot be "+increment+".\nThe increment must be 1 or greater."); + this.pos = pos; + this.sig = sig; + this.isExact = isExact; + this.startingScope = startingScope; + this.endingScope = endingScope; + this.increment = increment; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return (isExact ? "exactly " : "") + + startingScope + + (endingScope!=startingScope ? (".."+endingScope) : "") + + (increment > 1 ? (":"+increment) : "") + + " " + + Util.tail(sig.label); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Decl.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Decl.java new file mode 100644 index 00000000..46a6df10 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Decl.java @@ -0,0 +1,88 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import java.util.List; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.ConstList; + +/** Immutable; this declaration binds a list of names to an expression. */ + +public final class Decl { + + /** If nonnull, then this decl is private (and this.isPrivate is the location of the "private" keyword) */ + public final Pos isPrivate; + + /** If nonnull, then each name is disjoint (and this.disjoint is the location of the "disjoint" keyword) */ + public final Pos disjoint; + + /** If nonnull, then each atom of this sig has disjoint value for this field (and this.disjoint2 is the location of the "disjoint" keyword) */ + public final Pos disjoint2; + + /** The list of names. */ + public final ConstList names; + + /** The value that the list of names are bound to. */ + public final Expr expr; + + /** Caches the span() result. */ + private Pos span; + + /** Returns a Pos object representing the entire span of this expression and all its subexpressions. */ + public Pos span() { + Pos p = span; + if (p == null) { + p = expr.span().merge(disjoint).merge(disjoint2); + for(ExprHasName n: names) p = p.merge(n.span()); + span = p; + } + return p; + } + + /** This constructs a declaration; the list of names must not be empty. */ + public Decl(Pos isPrivate, Pos disjoint, Pos disjoint2, List names, Expr expr) { + if (names.size()==0) throw new NullPointerException(); + this.isPrivate = isPrivate; + this.disjoint = (names.size()>1 ? disjoint : null); + this.disjoint2 = disjoint2; + this.names = ConstList.make(names); + this.expr = expr; + } + + /** Return the first variable in this declaration. */ + public ExprHasName get() { + return names.get(0); + } + + /** If the list of declaration contains a duplicate name, return one such duplicate name, else return null. */ + public static ExprHasName findDuplicateName (List list) { + for(int i=0; i Invariant: pos!=null + *
Invariant: type!=null + *
Invariant: type==EMPTY iff errors.size()>0 + *
Invariant: mult==0 || mult==1 || mult==2 + *
Invariant: weight>0 + */ + +public abstract class Expr extends Browsable { + + /** The filename, line, and column position in the original Alloy model file (cannot be null). */ + public final Pos pos; + + /** The filename, line, and column position in the original Alloy model file of the closing bracket). */ + public final Pos closingBracket; + + /** The type for this node; EMPTY if it is not well-typed. */ + final Type type; + + /** Return the type for this node; EMPTY if it is not well-typed. */ + public final Type type() { return type; } + + /** The list of errors on this node; nonempty iff this.type==EMPTY */ + public final JoinableList errors; + + /** This field records whether the node is a multiplicity constraint. + * + *
If it's 2, that means it is an arrow multiplicity constraint (X ?->? X), + * or has the form (A -> B) where A and/or B is an arrow multiplicity constraint. + * + *
If it's 1, that means it is a multiplicity constraint of the form (? X) + * + *
If it's 0, that means it does not have either form. + */ + public final int mult; + + /** Each leaf Expr has a weight value (which can be 0 or higher); + * by default, each nonleaf Expr's weight is the sum of its children's weights. + */ + public final long weight; + + /** True if this expression is not fully resolved. */ + public final boolean ambiguous; + + /** This is an unmodifiable empty list of Err objects. */ + static final JoinableList emptyListOfErrors = new JoinableList(); + + //================================================================================================================// + + /** Constructs a new expression node + * + * @param pos - the original position in the file (can be null if unknown) + * + * @param closingBracket - the original position of the closing bracket (can be null if unknown) + * + * @param ambiguous - true if this node is ExprChoice or it contains an ExprChoice subnode + * + * @param type - the type + * + * @param mult - the multiplicity (which must be 0, 1, or 2) + *
If it's 2, that means it is a multiplicity constraint (X ?->? X), + * or has the form (A -> B) where A and/or B is a multiplicity constraint. + *
If it's 1, that means it is a multiplicity constraint of the form (? X) + *
If it's 0, that means it does not have either form. + * + * @param weight - the weight of this node and all subnodes + * + * @param errors - the list of errors associated with this Expr node (can be null if there are none) + */ + Expr (Pos pos, Pos closingBracket, boolean ambiguous, Type type, int mult, long weight, JoinableList errors) { + this.pos = (pos==null ? Pos.UNKNOWN : pos); + this.closingBracket = (closingBracket==null ? Pos.UNKNOWN : closingBracket); + this.ambiguous = ambiguous; + if (errors==null) errors = emptyListOfErrors; + if (type==EMPTY && errors.size()==0) + errors = errors.make(new ErrorType(pos, "This expression failed to be typechecked")); + this.mult = (mult<0 || mult>2) ? 0 : mult; + this.type = (errors.size()>0 || type==null) ? EMPTY : type; + this.weight = (weight>0) ? weight : 0; + this.errors = errors; + } + + /** This must only be called by Sig's constructor. */ + Expr (Pos pos, Type type) { + this.closingBracket = Pos.UNKNOWN; + this.ambiguous = false; + this.errors = emptyListOfErrors; + this.pos = (pos==null ? Pos.UNKNOWN : pos); + this.type = (type==null || type==EMPTY) ? Type.make((PrimSig)this) : type; + this.mult = 0; + this.weight = 0; + } + + /** {@inheritDoc} */ + @Override public final Pos pos() { return pos; } + + /** Print a textual description of it and all subnodes to a StringBuilder, with the given level of indentation. + * (If indent<0, it will be printed in one line without line break) + */ + public abstract void toString(StringBuilder out, int indent); + + /** Print a brief text description of it and all subnodes. */ + @Override public String toString() { StringBuilder sb = new StringBuilder(); toString(sb,-1); return sb.toString(); } + + /** {@inheritDoc} */ + @Override public final int hashCode() { return super.hashCode(); } + + /** {@inheritDoc} */ + @Override public final boolean equals(Object other) { return super.equals(other); } + + //================================================================================================================// + + /** Accepts the return visitor. */ + public abstract T accept(VisitReturn visitor) throws Err; + + /** Converts this into a "formula" if possible; otherwise, returns an Expr with a nonempty error list */ + public final Expr typecheck_as_formula() { + if (!errors.isEmpty() || type.is_bool) return this; + String msg = "This must be a formula expression.\nInstead, it has the following possible type(s):\n" + type; + return NOOP.make(null, this, new ErrorType(span(), msg), 0); + } + + /** Converts this into an "integer expression" if possible; otherwise, returns an Expr with a nonempty error list */ + public final Expr typecheck_as_int() { + if (!errors.isEmpty()) + return this; + if (type.is_small_int()) + return this; + if (type.is_int()) { + return cast2int(); + } + // else: error + String msg = "This must be an integer expression.\nInstead, it has the following possible type(s):\n"+type; + return NOOP.make(null, this, new ErrorType(span(), msg), 0); + } + + /** Converts this into a "set or relation" if possible; otherwise, returns an Expr with a nonempty error list */ + public final Expr typecheck_as_set() { + if (!errors.isEmpty()) + return this; + if (type.is_small_int()) + return cast2sigint(); + if (type.is_int()) + return this; + if (type.size()>0) + return this; + // else: error + String msg = "This must be a set or relation.\nInstead, it has the following possible type(s):\n"+type; + return NOOP.make(null, this, new ErrorType(span(), msg), 0); + } + + //================================================================================================================// + + /** Resolves this expression if ambiguous. + * (And if t.size()>0, it represents the set of tuples whose presence/absence is relevent to the parent expression) + * (Note: it's possible for t to be EMPTY, or even ambiguous!) + * + *

On success: the return value will be well-typed and unambiguous + *

On failure: the return value's "errors" list will be nonempty + * + *

If we detect any type warnings, we will add the type warnings to the "warnings" collection. + * + * @param warnings - the list that will receive any warning we generate; can be null if we wish to ignore warnings + */ + public abstract Expr resolve(Type t, Collection warnings); + + /** Converts this into a "formula" if possible, then resolves it if ambiguous. + * + *

On success: the return value will be a well-typed unambiguous formula expression + *

On failure: the return value's "errors" list will be nonempty + * + *

If we detect any type warnings, we will add the type warnings to the "warnings" collection. + * + * @param warnings - the list that will receive any warning we generate; can be null if we wish to ignore warnings + */ + public final Expr resolve_as_formula(Collection warnings) { + return typecheck_as_formula().resolve(Type.FORMULA, warnings).typecheck_as_formula(); + } + + /** Converts this into an "integer expression" if possible, then resolves it if ambiguous. + * + *

On success: the return value will be a well-typed unambiguous integer expression + *

On failure: the return value's "errors" list will be nonempty + * + *

If we detect any type warnings, we will add the type warnings to the "warnings" collection. + * + * @param warnings - the list that will receive any warning we generate; can be null if we wish to ignore warnings + */ + public final Expr resolve_as_int(Collection warnings) { + return typecheck_as_int().resolve(Type.smallIntType(), warnings).typecheck_as_int(); + } + + /** Converts this into a "set or relation" if possible, then resolves it if ambiguous. + * + *

On success: the return value will be a well-typed unambiguous set or relation expression + *

On failure: the return value's "errors" list will be nonempty + * + *

If we detect any type warnings, we will add the type warnings to the "warnings" collection. + * + * @param warnings - the list that will receive any warning we generate; can be null if we wish to ignore warnings + */ + public final Expr resolve_as_set(Collection warnings) { + Expr x = typecheck_as_set(); + Type t = x.type; + return x.resolve(Type.removesBoolAndInt(t), warnings).typecheck_as_set(); + } + + //================================================================================================================// + + /** Returns true if we can determine the two expressions are equivalent; may sometimes return false. */ + public boolean isSame(Expr obj) { + while(obj instanceof ExprUnary && ((ExprUnary)obj).op==ExprUnary.Op.NOOP) obj=((ExprUnary)obj).sub; + return obj==this; + } + + /** Remove the "NOP" in front of an expression (if any). */ + public final Expr deNOP() { + Expr x = this; + while(x instanceof ExprUnary && ((ExprUnary)x).op==ExprUnary.Op.NOOP) x=((ExprUnary)x).sub; + return x; + } + + /** If this is loneOf/oneOf/someOf/exactlyOf expression, return loneOf/oneOf/someOf/exactlyOf, otherwise returns setOf. */ + public final ExprUnary.Op mult() { + Expr x = this; + while(x instanceof ExprUnary) { + ExprUnary.Op op = ((ExprUnary)x).op; + if (op==ExprUnary.Op.NOOP) { x = ((ExprUnary)x).sub; continue; } + if (op==ExprUnary.Op.ONEOF || op==ExprUnary.Op.LONEOF || op==ExprUnary.Op.SOMEOF || op==ExprUnary.Op.EXACTLYOF) return op; + break; + } + return ExprUnary.Op.SETOF; + } + + /** A return visitor that determines whether the node (or a subnode) contains a predicate/function call. */ + private static final VisitQuery hasCall = new VisitQuery() { + @Override public final Object visit(ExprCall x) { return this; } + }; + + /** Returns true if the node is well-typed, unambiguous, and contains a predicate/function call. */ + final boolean hasCall() { + boolean ans = !ambiguous && errors.isEmpty(); + if (ans) { try { ans=accept(hasCall)!=null; } catch(Err ex) { ans=false; } } // This exception should not occur + return ans; + } + + /** Returns true if the node is well-typed, unambiguous, and contains the given variable. */ + public final boolean hasVar(final ExprVar goal) { + if (ambiguous || !errors.isEmpty()) return false; + VisitQuery hasVar = new VisitQuery() { + @Override public final Object visit(ExprVar x) throws Err { + if (x==goal) return this; else return null; + } + }; + boolean ans; + try { ans=accept(hasVar)!=null; } catch(Err ex) { return false; } // This exception should not occur + return ans; + } + + /** Transitively returns a set that contains all predicates/functions that this expression calls directly or indirectly. */ + public final Iterable findAllFunctions() { + final LinkedHashSet seen = new LinkedHashSet(); + final List todo = new ArrayList(); + final VisitQuery q = new VisitQuery() { + @Override public final Object visit(ExprCall x) { if (seen.add(x.fun)) todo.add(x.fun); return null; } + }; + try { + q.visitThis(this); + while(!todo.isEmpty()) { q.visitThis(todo.remove(todo.size()-1).getBody()); } + } catch(Err ex) { } // Exception should not occur + return seen; + } + + /** Returns the height of the abstract syntax tree starting from this node. */ + public abstract int getDepth(); + + //================================================================================// + // Below are convenience methods for building up expressions from subexpressions. // + //================================================================================// + + /** Returns the formula (this and x) + *

this and x must both be formulas + *

Note: as a special guarantee, if x==null, then the method will return this Expr object as-is. + */ + public final Expr and(Expr x) { return (x==null) ? this : ExprBinary.Op.AND.make(span().merge(x.span()), null, this, x); } + + /** Returns the formula (this or x) + *

this and x must both be formulas + *

Note: as a special guarantee, if x==null, then the method will return this Expr object as-is. + */ + public final Expr or(Expr x) { return (x==null) ? this : ExprBinary.Op.OR.make(span().merge(x.span()), null, this, x); } + + /** Returns the formula (this iff x) + *

this and x must both be formulas + */ + public final Expr iff(Expr x) { return ExprBinary.Op.IFF.make(span().merge(x.span()), null, this, x); } + + /** Returns the formula (this implies x) + *

this and x must both be formulas + */ + public final Expr implies(Expr x) { return ExprBinary.Op.IMPLIES.make(span().merge(x.span()), null, this, x); } + + /** Returns the expression (this.x) + *

1. this must be a set or relation + *

2. x must be a set or relation + *

3. at most one of them can be a unary set + */ + public final Expr join(Expr x) { return ExprBinary.Op.JOIN.make(span().merge(x.span()), null, this, x); } + + /** Returns the expression (this <: x) + *

this must be a unary set + *

x must be a set or relation + */ + public final Expr domain(Expr x) { return ExprBinary.Op.DOMAIN.make(span().merge(x.span()), null, this, x); } + + /** Returns the expression (this :> x) + *

this must be a set or relation + *

x must be a unary set + */ + public final Expr range(Expr x) { return ExprBinary.Op.RANGE.make(span().merge(x.span()), null, this, x); } + + /** Returns the expression (this intersects x) + *

this and x must be expressions with the same arity + */ + public final Expr intersect(Expr x) { return ExprBinary.Op.INTERSECT.make(span().merge(x.span()), null, this, x); } + + /** Returns the expression (this++x) + *

this and x must be expressions with the same arity + */ + public final Expr override(Expr x) { return ExprBinary.Op.PLUSPLUS.make(span().merge(x.span()), null, this, x); } + + /** Returns the expression (this+x) + *

this and x must be expressions with the same arity, or both be integer expressions + *

Note: as a special guarantee, if x==null, then the method will return this Expr object as-is. + */ + public final Expr plus(Expr x) { return (x==null) ? this : ExprBinary.Op.PLUS.make(span().merge(x.span()), null, this, x); } + public final Expr iplus(Expr x) { return (x==null) ? this : ExprBinary.Op.IPLUS.make(span().merge(x.span()), null, this, x); } + + /** Returns the expression (this-x) + *

this and x must be expressions with the same arity, or both be integer expressions + */ + public final Expr minus(Expr x) { return ExprBinary.Op.MINUS.make(span().merge(x.span()), null, this, x); } + public final Expr iminus(Expr x) { return ExprBinary.Op.IMINUS.make(span().merge(x.span()), null, this, x); } + + /** Returns the formula "this.mul[x]" (the result of multiplying this by x) + *

this and x must both be integer expressions + */ + public final Expr mul(Expr x) { return ExprBinary.Op.MUL.make(span().merge(x.span()), null, this, x); } + + /** Returns the formula "this.div[x]" (the quotient of dividing this by x) + *

this and x must both be integer expressions + */ + public final Expr div(Expr x) { return ExprBinary.Op.DIV.make(span().merge(x.span()), null, this, x); } + + /** Returns the formula "this.rem[x]" (the remainder of dividing this by x) + *

this and x must both be integer expressions + */ + public final Expr rem(Expr x) { return ExprBinary.Op.REM.make(span().merge(x.span()), null, this, x); } + + /** Returns the formula (this==x) + *

this and x must be expressions with the same arity, or both be integer expressions + */ + public final Expr equal(Expr x) { return ExprBinary.Op.EQUALS.make(span().merge(x.span()), null, this, x); } + + /** Returns the formula (this < x) + *

this and x must both be integer expressions + */ + public final Expr lt(Expr x) { return ExprBinary.Op.LT.make(span().merge(x.span()), null, this, x); } + + /** Returns the formula (this <= x) + *

this and x must both be integer expressions + */ + public final Expr lte(Expr x) { return ExprBinary.Op.LTE.make(span().merge(x.span()), null, this, x); } + + /** Returns the formula (this > x) + *

this and x must both be integer expressions + */ + public final Expr gt(Expr x) { return ExprBinary.Op.GT.make(span().merge(x.span()), null, this, x); } + + /** Returns the formula (this >= x) + *

this and x must both be integer expressions + */ + public final Expr gte(Expr x) { return ExprBinary.Op.GTE.make(span().merge(x.span()), null, this, x); } + + /** Returns the integer expression (this << x) + *

this and x must both be integer expressions + */ + public final Expr shl(Expr x) { return ExprBinary.Op.SHL.make(span().merge(x.span()), null, this, x); } + + /** Returns the integer expression (this >>> x) + *

this and x must both be integer expressions + */ + public final Expr shr(Expr x) { return ExprBinary.Op.SHR.make(span().merge(x.span()), null, this, x); } + + /** Returns the integer expression (this >> x) + *

this and x must both be integer expressions + */ + public final Expr sha(Expr x) { return ExprBinary.Op.SHA.make(span().merge(x.span()), null, this, x); } + + /** Returns the formula (this in x) + *

this must be a set or relation + *

x must be a set or relation or multiplicity constraint + *

this and x must have the same arity + */ + public final Expr in(Expr x) { return ExprBinary.Op.IN.make(span().merge(x.span()), null, this, x); } + + /** Returns the expression (this -> x) which can also be regarded as a multiplicity constraint (this set->set x) + *

this must be a set or relation + *

x must be a set or relation + */ + public final Expr product(Expr x) { return ExprBinary.Op.ARROW.make(span().merge(x.span()), null, this, x); } + + /** Returns the multiplicity constraint (this set->some x) + *

this must be a set or relation + *

x must be a set or relation + */ + public final Expr any_arrow_some(Expr x) { return ExprBinary.Op.ANY_ARROW_SOME.make(span().merge(x.span()), null, this, x); } + + /** Returns the multiplicity constraint (this set->one x) + *

this must be a set or relation + *

x must be a set or relation + */ + public final Expr any_arrow_one(Expr x) { return ExprBinary.Op.ANY_ARROW_ONE.make(span().merge(x.span()), null, this, x); } + + /** Returns the multiplicity constraint (this set->lone x) + *

this must be a set or relation + *

x must be a set or relation + */ + public final Expr any_arrow_lone(Expr x) { return ExprBinary.Op.ANY_ARROW_LONE.make(span().merge(x.span()), null, this, x); } + + /** Returns the multiplicity constraint (this some->set x) + *

this must be a set or relation + *

x must be a set or relation + */ + public final Expr some_arrow_any(Expr x) { return ExprBinary.Op.SOME_ARROW_ANY.make(span().merge(x.span()), null, this, x); } + + /** Returns the multiplicity constraint (this some->some x) + *

this must be a set or relation + *

x must be a set or relation + */ + public final Expr some_arrow_some(Expr x) { return ExprBinary.Op.SOME_ARROW_SOME.make(span().merge(x.span()), null, this, x); } + + /** Returns the multiplicity constraint (this some->one x) + *

this must be a set or relation + *

x must be a set or relation + */ + public final Expr some_arrow_one(Expr x) { return ExprBinary.Op.SOME_ARROW_ONE.make(span().merge(x.span()), null, this, x); } + + /** Returns the multiplicity constraint (this some->lone x) + *

this must be a set or relation + *

x must be a set or relation + */ + public final Expr some_arrow_lone(Expr x) { return ExprBinary.Op.SOME_ARROW_LONE.make(span().merge(x.span()), null, this, x); } + + /** Returns the multiplicity constraint (this one->set x) + *

this must be a set or relation + *

x must be a set or relation + */ + public final Expr one_arrow_any(Expr x) { return ExprBinary.Op.ONE_ARROW_ANY.make(span().merge(x.span()), null, this, x); } + + /** Returns the multiplicity constraint (this one->some x) + *

this must be a set or relation + *

x must be a set or relation + */ + public final Expr one_arrow_some(Expr x) { return ExprBinary.Op.ONE_ARROW_SOME.make(span().merge(x.span()), null, this, x); } + + /** Returns the multiplicity constraint (this one->one x) + *

this must be a set or relation + *

x must be a set or relation + */ + public final Expr one_arrow_one(Expr x) { return ExprBinary.Op.ONE_ARROW_ONE.make(span().merge(x.span()), null, this, x); } + + /** Returns the multiplicity constraint (this one->lone x) + *

this must be a set or relation + *

x must be a set or relation + */ + public final Expr one_arrow_lone(Expr x) { return ExprBinary.Op.ONE_ARROW_LONE.make(span().merge(x.span()), null, this, x); } + + /** Returns the multiplicity constraint (this lone->set x) + *

this must be a set or relation + *

x must be a set or relation + */ + public final Expr lone_arrow_any(Expr x) { return ExprBinary.Op.LONE_ARROW_ANY.make(span().merge(x.span()), null, this, x); } + + /** Returns the multiplicity constraint (this lone->some x) + *

this must be a set or relation + *

x must be a set or relation + */ + public final Expr lone_arrow_some(Expr x) { return ExprBinary.Op.LONE_ARROW_SOME.make(span().merge(x.span()), null, this, x); } + + /** Returns the multiplicity constraint (this lone->one x) + *

this must be a set or relation + *

x must be a set or relation + */ + public final Expr lone_arrow_one(Expr x) { return ExprBinary.Op.LONE_ARROW_ONE.make(span().merge(x.span()), null, this, x); } + + /** Returns the multiplicity constraint (this lone->lone x) + *

this must be a set or relation + *

x must be a set or relation + */ + public final Expr lone_arrow_lone(Expr x) { return ExprBinary.Op.LONE_ARROW_LONE.make(span().merge(x.span()), null, this, x); } + + /** Returns the multiplicity constraint (this isSeq->lone x) + *

this must be a set or relation + *

x must be a set or relation + */ + public final Expr isSeq_arrow_lone(Expr x) { return ExprBinary.Op.ISSEQ_ARROW_LONE.make(span().merge(x.span()), null, this, x); } + + /** Returns the expression/integer/formula (this => x else y) + *

this must be a formula + *

x and y must both be expressions of the same arity, or both be integer expressions, or both be formulas + */ + public final Expr ite(Expr x, Expr y) { return ExprITE.make(Pos.UNKNOWN, this, x, y); } + + /** Returns the formula (all...| this) + *

this must be a formula + */ + public final Expr forAll(Decl firstDecl, Decl... moreDecls) throws Err { + Pos p = firstDecl.span(); + for(Decl v: moreDecls) p=p.merge(v.span()); + return ExprQt.Op.ALL.make(p, null, Util.prepend(Util.asList(moreDecls), firstDecl), this); + } + + /** Returns the formula (no...| this) + *

this must be a formula + */ + public final Expr forNo(Decl firstDecl, Decl... moreDecls) throws Err { + Pos p = firstDecl.span(); + for(Decl v: moreDecls) p=p.merge(v.span()); + return ExprQt.Op.NO.make(p, null, Util.prepend(Util.asList(moreDecls), firstDecl), this); + } + + /** Returns the formula (lone...| this) + *

this must be a formula + */ + public final Expr forLone(Decl firstDecl, Decl... moreDecls) throws Err { + Pos p = firstDecl.span(); + for(Decl v: moreDecls) p=p.merge(v.span()); + return ExprQt.Op.LONE.make(p, null, Util.prepend(Util.asList(moreDecls), firstDecl), this); + } + + /** Returns the formula (one ...| this) + *

this must be a formula + */ + public final Expr forOne(Decl firstDecl, Decl... moreDecls) throws Err { + Pos p = firstDecl.span(); + for(Decl v: moreDecls) p=p.merge(v.span()); + return ExprQt.Op.ONE.make(p, null, Util.prepend(Util.asList(moreDecls), firstDecl), this); + } + + /** Returns the formula (some...| this) + *

this must be a formula + */ + public final Expr forSome(Decl firstDecl, Decl... moreDecls) throws Err { + Pos p = firstDecl.span(); + for(Decl v: moreDecls) p=p.merge(v.span()); + return ExprQt.Op.SOME.make(p, null, Util.prepend(Util.asList(moreDecls), firstDecl), this); + } + + /** Returns the comprehension expression {...|this} + *

this must be a formula + *

each declaration must be a "one-of" quantification over a unary set + */ + public final Expr comprehensionOver(Decl firstDecl, Decl... moreDecls) throws Err { + Pos p = firstDecl.span(); + for(Decl v: moreDecls) p=p.merge(v.span()); + return ExprQt.Op.COMPREHENSION.make(p, null, Util.prepend(Util.asList(moreDecls), firstDecl), this); + } + + /** Returns the integer (sum...| this) + *

this must be an integer expression + *

each declaration must be a "one-of" quantification over a unary set + */ + public final Expr sumOver(Decl firstDecl, Decl... moreDecls) throws Err { + Pos p = firstDecl.span(); + for(Decl v: moreDecls) p=p.merge(v.span()); + return ExprQt.Op.SUM.make(p, null, Util.prepend(Util.asList(moreDecls), firstDecl), this); + } + + /** Return the multiplicity expression "some this" + *

this must be already fully typechecked, and must be a unary set + */ + public final Expr someOf() { + return ExprUnary.Op.SOMEOF.make(span(), this); + } + + /** Return a new declaration "v: some this" + *

this must be already fully typechecked, and must be a unary set + *

the label is only used for pretty-printing, and does not have to be unique + */ + public final Decl someOf(String label) throws Err { + Expr x = ExprUnary.Op.SOMEOF.make(span(), this); + ExprVar v = ExprVar.make(x.span(), label, type); + return new Decl(null, null, null, Arrays.asList(v), x); + } + + /** Return the multiplicity expression "lone this" + *

this must be already fully typechecked, and must be a unary set + */ + public final Expr loneOf() { + return ExprUnary.Op.LONEOF.make(span(), this); + } + + /** Return a new declaration "v: lone this" + *

this must be already fully typechecked, and must be a unary set + *

the label is only used for pretty-printing, and does not have to be unique + */ + public final Decl loneOf(String label) throws Err { + Expr x = ExprUnary.Op.LONEOF.make(span(), this); + ExprVar v = ExprVar.make(x.span(), label, type); + return new Decl(null, null, null, Arrays.asList(v), x); + } + + /** Return the multiplicity expression "one this" + *

this must be already fully typechecked, and must be a unary set + */ + public final Expr oneOf() { + return ExprUnary.Op.ONEOF.make(span(), this); + } + + /** Return a new declaration "v: one this" + *

this must be already fully typechecked, and must be a unary set + *

the label is only used for pretty-printing, and does not have to be unique + */ + public final Decl oneOf(String label) throws Err { + Expr x = ExprUnary.Op.ONEOF.make(span(), this); + ExprVar v = ExprVar.make(x.span(), label, type); + return new Decl(null, null, null, Arrays.asList(v), x); + } + + /** Return the multiplicity expression "set this" + *

this must be already fully typechecked, and must be a set or relation + */ + public final Expr setOf() { + return ExprUnary.Op.SETOF.make(span(), this); + } + + /** Return a new declaration "v: set this" + *

this must be already fully typechecked, and must be a set or relation + *

the label is only used for pretty-printing, and does not have to be unique + */ + public final Decl setOf(String label) throws Err { + Expr x = ExprUnary.Op.SETOF.make(span(), this); + ExprVar v = ExprVar.make(x.span(), label, type); + return new Decl(null, null, null, Arrays.asList(v), x); + } + + /** Returns the formula (not this) + *

this must be a formula + */ + public final Expr not() { return ExprUnary.Op.NOT.make(span(), this); } + + /** Returns the formula (no this) + *

this must be a set or a relation + */ + public final Expr no() { return ExprUnary.Op.NO.make(span(), this); } + + /** Returns the formula (some this) + *

this must be a set or a relation + */ + public final Expr some() { return ExprUnary.Op.SOME.make(span(), this); } + + /** Returns the formula (lone this) + *

this must be a set or a relation + */ + public final Expr lone() { return ExprUnary.Op.LONE.make(span(), this); } + + /** Returns the formula (one this) + *

this must be a set or a relation + */ + public final Expr one() { return ExprUnary.Op.ONE.make(span(), this); } + + /** Returns the expression (~this) + *

this must be a binary relation + */ + public final Expr transpose() { return ExprUnary.Op.TRANSPOSE.make(span(), this); } + + /** Returns the expression (*this) + *

this must be a binary relation + */ + public final Expr reflexiveClosure() { return ExprUnary.Op.RCLOSURE.make(span(), this); } + + /** Returns the expression (^this) + *

this must be a binary relation + */ + public final Expr closure() { return ExprUnary.Op.CLOSURE.make(span(), this); } + + /** Returns the integer expression (#this) truncated to the current integer bitwidth. + *

this must be a set or a relation + */ + public final Expr cardinality() { return ExprUnary.Op.CARDINALITY.make(span(), this); } + + /** Returns the integer expression "int[this]" + *

this must be a unary set + */ + public final Expr cast2int() { return ExprUnary.Op.CAST2INT.make(span(), this); } + + /** Returns the singleton set "Int[this]" + *

this must be an integer expression + */ + public final Expr cast2sigint() { return ExprUnary.Op.CAST2SIGINT.make(span(), this); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprBad.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprBad.java new file mode 100644 index 00000000..670b09d5 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprBad.java @@ -0,0 +1,70 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.JoinableList; +import static edu.mit.csail.sdg.alloy4compiler.ast.Type.EMPTY; + +/** Immutable; represents an illegal node. + * + *

Invariant: this.type==EMPTY && this.errors.size()==1 + */ + +public final class ExprBad extends Expr { + + /** The original source text that caused the error. */ + private final String originalText; + + /** {@inheritDoc} */ + @Override public Pos span() { return pos; } + + /** {@inheritDoc} */ + @Override public void toString(StringBuilder out, int indent) { + if (indent<0) { + out.append(originalText); + } else { + for(int i=0; i(error)); + this.originalText = originalText; + } + + /** {@inheritDoc} */ + public int getDepth() { return 1; } + + /** {@inheritDoc} */ + @Override public Expr resolve(Type t, Collection warns) { return this; } + + /** {@inheritDoc} */ + @Override public final T accept(VisitReturn visitor) throws Err { return visitor.visit(this); } + + /** {@inheritDoc} */ + @Override public String getHTML() { return "error (parser or typechecker failed)"; } + + /** {@inheritDoc} */ + @Override public List getSubnodes() { return new ArrayList(0); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprBadCall.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprBadCall.java new file mode 100644 index 00000000..21e1e767 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprBadCall.java @@ -0,0 +1,131 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.JoinableList; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import static edu.mit.csail.sdg.alloy4compiler.ast.Type.EMPTY; + +/** Immutable; represents an illegal pred/fun call. + * + *

Invariant: this.type==EMPTY && this.errors.size()>0 + */ + +public final class ExprBadCall extends Expr { + + /** The function. */ + public final Func fun; + + /** The unmodifiable list of arguments. */ + public final ConstList args; + + /** The extra weight added to this node on top of the combined weights of the arguments. */ + public final long extraWeight; + + /** Caches the span() result. */ + private Pos span=null; + + /** {@inheritDoc} */ + @Override public Pos span() { + Pos p=span; + if (p==null) { + p=pos.merge(closingBracket); + for(Expr a:args) p=p.merge(a.span()); + span=p; + } + return p; + } + + /** {@inheritDoc} */ + @Override public void toString(StringBuilder out, int indent) { + if (indent<0) { + out.append(fun.label).append('['); + for(int i=0; i0) out.append(", "); args.get(i).toString(out,-1); } + out.append(']'); + } else { + for(int i=0; i args, JoinableList errors, long extraWeight, long weight) { + super(pos, closingBracket, ambiguous, EMPTY, 0, weight, errors); + this.fun=fun; + this.args=args; + this.extraWeight=extraWeight; + } + + /** Constructs an ExprBadCall object. */ + public static Expr make(final Pos pos, final Pos closingBracket, final Func fun, ConstList args, long extraPenalty) { + if (extraPenalty<0) extraPenalty=0; + if (args==null) args=ConstList.make(); + long weight = extraPenalty; + boolean ambiguous = false; + JoinableList errors = emptyListOfErrors; + for(Expr x: args) { + weight = weight + x.weight; + ambiguous = ambiguous || x.ambiguous; + errors = errors.make(x.errors); + } + if (errors.isEmpty()) { + StringBuilder sb=new StringBuilder("This cannot be a correct call to "); + sb.append(fun.isPred?"pred ":"fun "); + sb.append(fun.label); + sb.append(fun.count()==0 ? ".\nIt has no parameters,\n" : ".\nThe parameters are\n"); + for(ExprVar v:fun.params()) { + sb.append(" ").append(v.label).append(": ").append(v.type).append('\n'); + } + sb.append(args.size()==0 || fun.count()==0 ? "so the arguments cannot be empty.\n" : "so the arguments cannot be\n"); + int n = fun.count(); + for(Expr v: args) { + if (n==0) break; else n--; + sb.append(" "); + v.toString(sb, -1); + sb.append(" (type = ").append(v.type).append(")\n"); + } + errors = errors.make(new ErrorType(pos, sb.toString())); + } + return new ExprBadCall(pos, closingBracket, ambiguous, fun, args, errors, extraPenalty, weight); + } + + /** {@inheritDoc} */ + public int getDepth() { + int max = 1; + for(Expr x: args) { int tmp=x.getDepth(); if (max warns) { return this; } + + /** {@inheritDoc} */ + @Override public final T accept(VisitReturn visitor) throws Err { return visitor.visit(this); } + + /** {@inheritDoc} */ + @Override public String getHTML() { return "error (parser or typechecker failed)"; } + + /** {@inheritDoc} */ + @Override public List getSubnodes() { return new ArrayList(0); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprBadJoin.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprBadJoin.java new file mode 100644 index 00000000..5284b4e0 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprBadJoin.java @@ -0,0 +1,103 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.JoinableList; +import static edu.mit.csail.sdg.alloy4compiler.ast.Type.EMPTY; + +/** Immutable; represents an illegal relation join. + * + *

Invariant: this.type==EMPTY && this.errors.size()>0 + */ + +public final class ExprBadJoin extends Expr { + + /** The left-hand-side expression. */ + public final Expr left; + + /** The right-hand-side expression. */ + public final Expr right; + + /** Caches the span() result. */ + private Pos span=null; + + /** {@inheritDoc} */ + @Override public Pos span() { + Pos p=span; + if (p==null) span = (p = pos.merge(closingBracket).merge(right.span()).merge(left.span())); + return p; + } + + /** {@inheritDoc} */ + @Override public void toString(StringBuilder out, int indent) { + if (indent<0) { + left.toString(out,-1); + out.append('.'); + right.toString(out,-1); + } else { + for(int i=0; i errors) { + super(pos, closingBracket, (left.ambiguous || right.ambiguous), EMPTY, 0, 0, errors); + this.left=left; + this.right=right; + } + + /** Constructs an ExprBadJoin node. */ + public static Expr make(Pos pos, Pos closingBracket, Expr left, Expr right) { + JoinableList errors = left.errors.make(right.errors); + if (errors.isEmpty()) { + StringBuilder sb=new StringBuilder("This cannot be a legal relational join where\nleft hand side is "); + left.toString(sb,-1); + sb.append(" (type = ").append(left.type).append(")\nright hand side is "); + right.toString(sb,-1); + sb.append(" (type = ").append(right.type).append(")\n"); + errors = errors.make(new ErrorType(pos, sb.toString())); + } + return new ExprBadJoin(pos, closingBracket, left, right, errors); + } + + /** {@inheritDoc} */ + public int getDepth() { + int a=left.getDepth(), b=right.getDepth(); + if (a>=b) return 1+a; else return 1+b; + } + + /** {@inheritDoc} */ + @Override public Expr resolve(Type t, Collection warns) { return this; } + + /** {@inheritDoc} */ + @Override public final T accept(VisitReturn visitor) throws Err { return visitor.visit(this); } + + /** {@inheritDoc} */ + @Override public String getHTML() { return "error (parser or typechecker failed)"; } + + /** {@inheritDoc} */ + @Override public List getSubnodes() { return new ArrayList(0); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprBinary.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprBinary.java new file mode 100644 index 00000000..0a2ad703 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprBinary.java @@ -0,0 +1,521 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import static edu.mit.csail.sdg.alloy4compiler.ast.Type.EMPTY; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.JoinableList; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; +import edu.mit.csail.sdg.alloy4compiler.ast.Type.ProductType; + +/** Immutable; represents an expression of the form (x OP y). + * + *

Invariant: type!=EMPTY => (this.mult!=1) + *

Invariant: type!=EMPTY => (this.mult==2 => this.op is one of the 17 arrow operators) + *

Invariant: type!=EMPTY => (left.mult!=1) + *

Invariant: type!=EMPTY => (left.mult==2 => this.op is one of the 17 arrow operators) + *

Invariant: type!=EMPTY => (right.mult==1 => this.op==IN) + *

Invariant: type!=EMPTY => (right.mult==2 => (this.op==IN || this.op is one of the 17 arrow operators)) + */ + +public final class ExprBinary extends Expr { + + /** The binary operator. */ + public final Op op; + + /** The left-hand-side expression. */ + public final Expr left; + + /** The right-hand-side expression. */ + public final Expr right; + + /** Caches the span() result. */ + private Pos span = null; + + //============================================================================================================// + + /** Constructs a new ExprBinary node. */ + private ExprBinary(Pos pos, Pos closingBracket, Op op, Expr left, Expr right, Type type, JoinableList errors) { + super(pos, + closingBracket, + left.ambiguous || right.ambiguous, + type, + (op.isArrow && (left.mult==2 || right.mult==2 || op!=Op.ARROW))?2:0, + left.weight + right.weight, + errors); + this.op = op; + this.left = left; + this.right = right; + } + + //============================================================================================================// + + /** Returns true if we can determine the two expressions are equivalent; may sometimes return false. */ + @Override public boolean isSame(Expr obj) { + while(obj instanceof ExprUnary && ((ExprUnary)obj).op==ExprUnary.Op.NOOP) obj=((ExprUnary)obj).sub; + if (obj==this) return true; + if (!(obj instanceof ExprBinary)) return false; + ExprBinary x = (ExprBinary)obj; + return op==x.op && left.isSame(x.left) && right.isSame(x.right); + } + + //============================================================================================================// + + /** Convenience method that generates a type error with "msg" as the message, + * and includes the left and right bounding types in the message. + */ + private static ErrorType error(Pos pos, String msg, Expr left, Expr right) { + return new ErrorType(pos, msg+"\nLeft type = "+left.type+"\nRight type = "+right.type); + } + + //============================================================================================================// + + /** Convenience method that generates a type warning with "msg" as the message, + * and includes the left and right bounding types in the message. + */ + private ErrorWarning warn(String msg) { + return new ErrorWarning(pos, msg + +"\nLeft type = " + Type.removesBoolAndInt(left.type) + +"\nRight type = " + Type.removesBoolAndInt(right.type)); + } + + //============================================================================================================// + + /** Convenience method that generates a type warning with "msg" as the message, + * and includes the parent's relevance type, as well as the left and right bounding types in the message. + */ + private ErrorWarning warn(String msg, Type parent) { + return new ErrorWarning(pos, msg + + "\nParent's relevant type = " + Type.removesBoolAndInt(parent) + + "\nLeft type = " + Type.removesBoolAndInt(left.type) + + "\nRight type = " + Type.removesBoolAndInt(right.type)); + } + + //============================================================================================================// + + /** {@inheritDoc} */ + @Override public Pos span() { + Pos p = span; + if (p==null) span = (p = pos.merge(closingBracket).merge(right.span()).merge(left.span())); + return p; + } + + //============================================================================================================// + + /** {@inheritDoc} */ + @Override public void toString(StringBuilder out, int indent) { + if (indent<0) { + if (op==Op.ISSEQ_ARROW_LONE) out.append("seq "); else { left.toString(out,-1); out.append(' ').append(op).append(' '); } + right.toString(out,-1); + } else { + for(int i=0; i",true), + /** ->some */ ANY_ARROW_SOME("->some",true), + /** ->one */ ANY_ARROW_ONE("->one",true), + /** ->lone */ ANY_ARROW_LONE("->lone",true), + /** some-> */ SOME_ARROW_ANY("some->",true), + /** some->some */ SOME_ARROW_SOME("some->some",true), + /** some->one */ SOME_ARROW_ONE("some->one",true), + /** some->lone */ SOME_ARROW_LONE("some->lone",true), + /** one-> */ ONE_ARROW_ANY("one->",true), + /** one->some */ ONE_ARROW_SOME("one->some",true), + /** one->one */ ONE_ARROW_ONE("one->one",true), + /** one->lone */ ONE_ARROW_LONE("one->lone",true), + /** lone-> */ LONE_ARROW_ANY("lone->",true), + /** lone->some */ LONE_ARROW_SOME("lone->some",true), + /** lone->one */ LONE_ARROW_ONE("lone->one",true), + /** lone->lone */ LONE_ARROW_LONE("lone->lone",true), + /** isSeq->lone */ ISSEQ_ARROW_LONE("isSeq->lone",true), + /** . */ JOIN(".",false), + /** <: */ DOMAIN("<:",false), + /** :> */ RANGE(":>",false), + /** & */ INTERSECT("&",false), + /** ++ */ PLUSPLUS("++",false), + /** set union */ PLUS("+",false), + /** int + */ IPLUS("@+",false), + /** set diff */ MINUS("-",false), + /** int - */ IMINUS("@-",false), + /** multiply */ MUL("*",false), + /** divide */ DIV("/",false), + /** remainder */ REM("%",false), + /** = */ EQUALS("=",false), + /** != */ NOT_EQUALS("!=",false), + /** => */ IMPLIES("=>",false), + /** < */ LT("<",false), + /** =< */ LTE("<=",false), + /** > */ GT(">",false), + /** >= */ GTE(">=",false), + /** !< */ NOT_LT("!<",false), + /** !=< */ NOT_LTE("!<=",false), + /** !> */ NOT_GT("!>",false), + /** !>= */ NOT_GTE("!>=",false), + /** << */ SHL("<<",false), + /** >> */ SHA(">>",false), + /** >>> */ SHR(">>>",false), + /** in */ IN("in",false), + /** !in */ NOT_IN("!in",false), + /** && */ AND("&&",false), + /** || */ OR("||",false), + /** <=> */ IFF("<=>",false); + + /** The constructor. + * @param label - the label (for printing debugging messages) + * @param isArrow - true if this operator is one of the 17 arrow operators + */ + private Op(String label, boolean isArrow) { + this.label=label; + this.isArrow=isArrow; + } + + /** The human readable label for this operator. */ + private final String label; + + /** True if and only if this operator is the Cartesian product "->", a "seq" multiplicity, + * or is a multiplicity arrow of the form "?->?". + */ + public final boolean isArrow; + + /** Constructs a new ExprBinary node. + * @param pos - the original position in the source file (can be null if unknown) + * @param left - the left hand side expression + * @param right - the right hand side expression + */ + public final Expr make(Pos pos, Pos closingBracket, Expr left, Expr right) { + switch(this) { + case AND: return ExprList.makeAND(pos, closingBracket, left, right); + case OR: return ExprList.makeOR(pos, closingBracket, left, right); + case DOMAIN: { + // Special optimization + Expr f = right.deNOP(); + if (f instanceof Field && ((Field)f).sig==left.deNOP()) return right; + break; + } + case MUL: case DIV: case REM: case LT: case LTE: case GT: case GTE: case SHL: case SHR: case SHA: + case NOT_LT: case NOT_GT: case NOT_LTE: case NOT_GTE: { + left = left.typecheck_as_int(); + right = right.typecheck_as_int(); + break; + } + case IFF: case IMPLIES: { + left = left.typecheck_as_formula(); + right = right.typecheck_as_formula(); + break; + } + case IPLUS: case IMINUS: { + left = left.typecheck_as_int(); + right = right.typecheck_as_int(); + break; + } + case PLUS: case MINUS: case EQUALS: case NOT_EQUALS: { + //[AM]: these are always relational operators now, so no casts +// Type a=left.type, b=right.type; +// if (a.hasCommonArity(b) || (a.is_int && b.is_int)) break; +// if (Type.SIGINT2INT) { +// if (a.is_int && b.intersects(SIGINT.type)) { right=right.cast2int(); break; } +// if (b.is_int && a.intersects(SIGINT.type)) { left=left.cast2int(); break; } +// } +// if (Type.INT2SIGINT) { +// if (a.is_int && b.hasArity(1)) { left=left.cast2sigint(); break; } +// if (b.is_int && a.hasArity(1)) { right=right.cast2sigint(); break; } +// } + break; + } + default: { + left = left.typecheck_as_set(); + right = right.typecheck_as_set(); + } + } + Err e=null; + Type type=EMPTY; + JoinableList errs = left.errors.make(right.errors); + if (errs.isEmpty()) switch(this) { + case LT: case LTE: case GT: case GTE: case NOT_LT: case NOT_LTE: case NOT_GT: case NOT_GTE: + case AND: case OR: case IFF: case IMPLIES: + type = Type.FORMULA; + break; + case MUL: case DIV: case REM: case SHL: case SHR: case SHA: + type = Type.smallIntType(); + break; + case PLUSPLUS: + type = left.type.unionWithCommonArity(right.type); + if (type==EMPTY) e=error(pos, "++ can be used only between two expressions of the same arity.", left, right); + break; + case PLUS: case MINUS: case EQUALS: case NOT_EQUALS: + if (this==EQUALS || this==NOT_EQUALS) { + if (left.type.hasCommonArity(right.type) || (left.type.is_int() && right.type.is_int())) { + type=Type.FORMULA; + break; + } + } else { + type = (this==PLUS ? left.type.unionWithCommonArity(right.type) : left.type.pickCommonArity(right.type)); + if (type!=EMPTY) break; + } + e=error(pos, this+" can be used only between 2 expressions of the same arity, or between 2 integer expressions.", left, right); + break; + case IPLUS: case IMINUS: + type = Type.smallIntType(); + break; + case IN: case NOT_IN: + type=(left.type.hasCommonArity(right.type)) ? Type.FORMULA : EMPTY; + if (type==EMPTY) e=error(pos,this+" can be used only between 2 expressions of the same arity.", left, right); + break; + case JOIN: + type=left.type.join(right.type); + if (type==EMPTY) return ExprBadJoin.make(pos, closingBracket, left, right); + break; + case DOMAIN: + type=right.type.domainRestrict(left.type); + if (type==EMPTY) e=new ErrorType(left.span(), + "This must be a unary set, but instead it has the following possible type(s):\n"+left.type); + break; + case RANGE: + type=left.type.rangeRestrict(right.type); + if (type==EMPTY) e=new ErrorType(right.span(), + "This must be a unary set, but instead it has the following possible type(s):\n"+right.type); + break; + case INTERSECT: + type=left.type.intersect(right.type); + if (type==EMPTY) e=error(pos,"& can be used only between 2 expressions of the same arity.", left, right); + break; + default: + type=left.type.product(right.type); + } + if ((isArrow && left.mult==1) || (!isArrow && left.mult!=0)) + errs = errs.make(new ErrorSyntax(left.span(), "Multiplicity expression not allowed here.")); + if ((isArrow && right.mult==1) || (!isArrow && this!=Op.IN && right.mult!=0)) + errs = errs.make(new ErrorSyntax(right.span(), "Multiplicity expression not allowed here.")); + return new ExprBinary(pos, closingBracket, this, left, right, type, errs.make(e)); + } + + /** Returns the human readable label for this operator. */ + @Override public final String toString() { return label; } + + /** Returns the human readable label already encoded for HTML */ + public final String toHTML() { return "" + Util.encode(label) + ""; } + } + + //============================================================================================================// + + /** {@inheritDoc} */ + @Override public Expr resolve(Type p, Collection warns) { + if (errors.size()>0) return this; + ErrorWarning w=null; + Type a=left.type, b=right.type; + switch(op) { + case MUL: case DIV: case REM: case LT: case LTE: case GT: case GTE: case SHL: case SHR: case SHA: + case NOT_LTE: case NOT_GTE: case NOT_LT: case NOT_GT: { + a=(b=Type.smallIntType()); + break; + } + case AND: case OR: case IFF: case IMPLIES: { + a=(b=Type.FORMULA); + break; + } + case EQUALS: case NOT_EQUALS: { + p=a.intersect(b); + if (p.hasTuple()) {a=p; b=p;} else {a=a.pickCommonArity(b); b=b.pickCommonArity(a);} + //[AM] +// if (left.type.is_int() && right.type.is_int()) { +// a=Type.makeInt(a); b=Type.makeInt(b); +// } else + if (warns==null) { + break; + } else if (left.type.hasTuple() && right.type.hasTuple() && !(left.type.intersects(right.type))) { + w=warn("== is redundant, because the left and right expressions are always disjoint."); + } else if (left.isSame(right)) { + w=warn("== is redundant, because the left and right expressions always have the same value."); + } + break; + } + case IN: case NOT_IN: { + a=a.pickCommonArity(b); + b=b.intersect(a); + if (warns==null) break; + if (left.type.hasNoTuple() && right.type.hasNoTuple()) + w=warn("Subset operator is redundant, because both subexpressions are always empty."); + else if (left.type.hasNoTuple()) + w=warn("Subset operator is redundant, because the left subexpression is always empty."); + else if (right.type.hasNoTuple()) + w=warn("Subset operator is redundant, because the right subexpression is always empty."); + else if (b.hasNoTuple()) + w=warn("Subset operator is redundant, because the left and right subexpressions are always disjoint."); + else if (left.isSame(right)) + w=warn("Subset operator is redundant, because the left and right expressions always have the same value."); + break; + } + case INTERSECT: { + a=a.intersect(p); + b=b.intersect(p); + if (warns!=null && type.hasNoTuple()) w=warn("& is irrelevant because the two subexpressions are always disjoint."); + break; + } + case IPLUS: case IMINUS: { + a = Type.smallIntType(); + b = Type.smallIntType(); + break; + } + case PLUSPLUS: case PLUS: { + a=a.intersect(p); + b=b.intersect(p); + //[AM] +// if (op==Op.PLUS && p.is_int()) { a=Type.makeInt(a); b=Type.makeInt(b); } + if (warns==null) break; + if (a==EMPTY && b==EMPTY) + w=warn(this+" is irrelevant since both subexpressions are redundant.", p); + else if (a==EMPTY) + w=warn(this+" is irrelevant since the left subexpression is redundant.", p); + else if (b==EMPTY || (op==Op.PLUSPLUS && !right.type.canOverride(left.type))) + w=warn(this+" is irrelevant since the right subexpression is redundant.", p); + break; + } + case MINUS: { + a=p; + b=p.intersect(b); + //[AM] +// if (p.is_int()) { +// a=Type.makeInt(a); b=Type.makeInt(b); +// } else + if (warns!=null && (type.hasNoTuple() || b.hasNoTuple())) { + w=warn("- is irrelevant since the right expression is redundant.", p); + } + break; + } + case JOIN: { + if (warns!=null && type.hasNoTuple()) w=warn("The join operation here always yields an empty set."); + a=(b=EMPTY); + for (ProductType aa: left.type) for (ProductType bb: right.type) if (p.hasArity(aa.arity()+bb.arity()-2)) { + PrimSig j = aa.get(aa.arity()-1).intersect(bb.get(0)); + if (j != Sig.NONE) for (ProductType cc:p.intersect(aa.join(bb))) if (!cc.isEmpty()) { + List v = new ArrayList(cc.arity() + 1); + for(int i=0; ir2 in parentType} + // rightType' = {r2 | r2 in rightType and there exists r1 in leftType such that r1:>r2 in parentType} + if (warns!=null && type.hasNoTuple()) w=warn(":> is irrelevant because the result is always empty."); + Type leftType=EMPTY, rightType=EMPTY; + for(ProductType bb:b) if (bb.arity()==1) for(ProductType aa:a) if (p.hasArity(aa.arity())) + for (ProductType cc:p.intersect(aa.columnRestrict(bb.get(0), aa.arity()-1))) if (!cc.isEmpty()) { + leftType = leftType.merge(cc); + rightType = rightType.merge(cc, cc.arity()-1, cc.arity()); + } + if (leftType==EMPTY || rightType==EMPTY) { // We try to proceed the best we can + leftType = a.pickCommonArity(p); + rightType = b.extract(1); + } + a=leftType; b=rightType; break; + } + default: { + // leftType' == {r1 | r1 in leftType and there exists r2 in rightType such that r1->r2 in parentType} + // rightType' == {r2 | r2 in rightType and there exists r1 in leftType such that r1->r2 in parentType} + if (warns==null) { + // do nothing + } else if (a.hasTuple()) { + if (b.hasNoTuple()) w=warn("The left expression of -> is irrelevant because the right expression is always empty."); + } else { + if (b.hasTuple()) w=warn("The right expression of -> is irrelevant because the left expression is always empty."); + } + Type leftType=EMPTY, rightType=EMPTY; + for (ProductType aa:a) if (!aa.isEmpty()) + for (ProductType bb:b) if (!bb.isEmpty() && p.hasArity(aa.arity()+bb.arity())) + for (ProductType cc:p.intersect(aa.product(bb))) if (!cc.isEmpty()) { + leftType = leftType.merge(cc, 0, aa.arity()); + rightType = rightType.merge(cc, aa.arity(), cc.arity()); + } + // We try to proceed the best we can; we should have issued a relevance warning already. + if (leftType==EMPTY || rightType==EMPTY) { leftType=a; rightType=b; } + a=leftType; + b=rightType; + } + } + Expr left = this.left.resolve(a, warns); + Expr right = this.right.resolve(b, warns); + if (w!=null) warns.add(w); + return (left==this.left && right==this.right) ? this : op.make(pos, closingBracket, left, right); + } + + //============================================================================================================// + + /** {@inheritDoc} */ + public int getDepth() { + int a=left.getDepth(), b=right.getDepth(); + if (a>=b) return 1+a; else return 1+b; + } + + /** {@inheritDoc} */ + @Override public final T accept(VisitReturn visitor) throws Err { return visitor.visit(this); } + + /** {@inheritDoc} */ + @Override public String getHTML() { return op.toHTML() + " " + type + ""; } + + /** {@inheritDoc} */ + @Override public List getSubnodes() { return Util.asList(left, right); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprCall.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprCall.java new file mode 100644 index 00000000..e0cab7bc --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprCall.java @@ -0,0 +1,276 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import java.util.Collection; +import java.util.List; +import edu.mit.csail.sdg.alloy4.JoinableList; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Env; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.ConstList.TempList; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; +import static edu.mit.csail.sdg.alloy4compiler.ast.Type.EMPTY; + +/** Immutable; represents a call. + * + *

Invariant: type!=EMPTY => (all x:args | x.mult==0) + */ + +public final class ExprCall extends Expr { + + /** The actual function being called; never null. */ + public final Func fun; + + /** The list of arguments to the call. */ + public final ConstList args; + + /** The extra weight added to this node on top of the combined weights of the arguments. */ + public final long extraWeight; + + /** Caches the span() result. */ + private Pos span=null; + + //============================================================================================================// + + /** {@inheritDoc} */ + @Override public Pos span() { + Pos p=span; + if (p==null) { + p=pos.merge(closingBracket); + for(Expr a:args) p=p.merge(a.span()); + span=p; + } + return p; + } + + //============================================================================================================// + + /** {@inheritDoc} */ + @Override public void toString(StringBuilder out, int indent) { + if (indent<0) { + out.append(fun.label); + if (args.size()==0) return; + out.append('['); + for(int i=0; i0) out.append(", "); args.get(i).toString(out,-1); } + out.append(']'); + } else { + for(int i=0; i with type=").append(type).append('\n'); + for(Expr a:args) { a.toString(out, indent+2); } + } + } + + //============================================================================================================// + + /** This visitor assumes the input expression is already fully typechecked, and derive a tight bound on the return type. */ + private static final class DeduceType extends VisitReturn { + private final Env env = new Env(); + private DeduceType() { } + @Override public Type visit(ExprITE x) throws Err { + Type t = x.left.accept(this); + if (t.size()==0) return t; + Type t2 = x.right.accept(this); + return t.unionWithCommonArity(t2); + } + @Override public Type visit(ExprBinary x) throws Err { + switch(x.op) { + case IMPLIES: case GT: case GTE: case LT: case LTE: case IFF: case EQUALS: case IN: case OR: case AND: + case NOT_LT: case NOT_GT: case NOT_LTE: case NOT_GTE: case NOT_IN: case NOT_EQUALS: + return Type.FORMULA; + case MUL: case DIV: case REM: case SHL: case SHR: case SHA: + return Type.smallIntType(); + } + Type a = x.left.accept(this); + Type b = x.right.accept(this); + switch(x.op) { + case JOIN: return a.join(b); + case DOMAIN: return b.domainRestrict(a); + case RANGE: return a.rangeRestrict(b); + case INTERSECT: return a.intersect(b); + case PLUSPLUS: return a.unionWithCommonArity(b); + case PLUS: return a.unionWithCommonArity(b); //[AM]: return (a.is_int() && b.is_int()) ? Type.makeInt(a.unionWithCommonArity(b)) : a.unionWithCommonArity(b); + case IPLUS: case IMINUS: return Type.smallIntType(); + case MINUS: return a.pickCommonArity(b); //[AM]: return (a.is_int() && b.is_int()) ? Type.makeInt(a.pickCommonArity(b)) : a.pickCommonArity(b); + default: return a.product(b); + } + } + @Override public Type visit(ExprUnary x) throws Err { + Type t = x.sub.accept(this); + switch(x.op) { + case NOOP: case LONEOF: case ONEOF: case SETOF: case SOMEOF: case EXACTLYOF: return t; + case CARDINALITY: case CAST2INT: return Type.smallIntType(); + case CAST2SIGINT: return Sig.SIGINT.type; + case TRANSPOSE: return t.transpose(); + case CLOSURE: return t.closure(); + case RCLOSURE: return Type.make2(Sig.UNIV); + default: return Type.FORMULA; + } + } + @Override public Type visit(ExprQt x) throws Err { + if (x.op == ExprQt.Op.SUM) return Type.smallIntType(); + if (x.op != ExprQt.Op.COMPREHENSION) return Type.FORMULA; + Type ans = null; + for(Decl d: x.decls) { + Type t = d.expr.accept(this); + for(ExprHasName v: d.names) { + env.put((ExprVar)v, t); + if (ans==null) ans=t; else ans=ans.product(t); + } + } + for(Decl d: x.decls) for(ExprHasName v: d.names) env.remove((ExprVar)v); + return (ans==null) ? EMPTY : ans; + } + @Override public Type visit(ExprLet x) throws Err { + env.put(x.var, x.expr.accept(this)); + Type ans = x.sub.accept(this); + env.remove(x.var); + return ans; + } + @Override public Type visit(ExprCall x) throws Err { + throw new ErrorSyntax(x.span(), "Return type declaration cannot contain predicate/function calls."); + } + @Override public Type visit(ExprVar x) { Type t=env.get(x); return (t!=null && t!=EMPTY) ? t : x.type; } + @Override public Type visit(ExprConstant x) { return x.type; } + @Override public Type visit(Sig x) { return x.type; } + @Override public Type visit(Field x) { return x.type; } + @Override public Type visit(ExprList x) { return Type.FORMULA; } + } + + //============================================================================================================// + + /** Constructs an ExprCall node with the given function "pred/fun" and the list of arguments "args". */ + private ExprCall (Pos pos, Pos closingBracket, boolean ambiguous, Type type, + Func fun, ConstList args, long extraWeight, long weight, JoinableList errs) { + super(pos, closingBracket, ambiguous, type, 0, weight, errs); + this.fun = fun; + this.args = args; + this.extraWeight = extraWeight; + } + + //============================================================================================================// + + /** Returns true if we can determine the two expressions are equivalent; may sometimes return false. */ + @Override public boolean isSame(Expr obj) { + while(obj instanceof ExprUnary && ((ExprUnary)obj).op==ExprUnary.Op.NOOP) obj=((ExprUnary)obj).sub; + if (obj==this) return true; + if (!(obj instanceof ExprCall)) return false; + ExprCall x=(ExprCall)obj; + if (fun!=x.fun || args.size()!=x.args.size()) return false; + for(int i=0; i args, long extraPenalty) { + if (extraPenalty<0) extraPenalty = 0; + if (args==null) args = ConstList.make(); + long weight = extraPenalty; + boolean ambiguous = false; + JoinableList errs = emptyListOfErrors; + TempList newargs = new TempList(args.size()); + if (args.size() != fun.count()) { + errs = errs.make( + new ErrorSyntax(pos, ""+fun+" has "+fun.count()+" parameters but is called with "+args.size()+" arguments.")); + } + for(int i=0; i0 && x.errors.isEmpty() && !x.type.hasArity(a)) + errs = errs.make(new ErrorType(x.span(), "This should have arity "+a+" but instead its possible type(s) are "+x.type)); + newargs.add(x); + } + Type t=Type.FORMULA; + if (!fun.isPred && errs.size()==0) { + final Type tt = fun.returnDecl.type; + try { + // This provides a limited form of polymorphic function, + // by using actual arguments at each call site to derive a tighter bound on the return value. + DeduceType d = new DeduceType(); + for(int i=0; i warns) { + if (errors.size()>0) return this; + TempList args = new TempList(this.args.size()); + boolean changed = false; + for(int i=0; i T accept(VisitReturn visitor) throws Err { return visitor.visit(this); } + + /** {@inheritDoc} */ + @Override public String getHTML() { return "call " + fun.label + " " + type + ""; } + + /** {@inheritDoc} */ + @Override public List getSubnodes() { + if (args.size()==0) { + Expr b = fun.getBody(); + return Util.asList(make(b.pos(), b.span(), b.getHTML(), b.getSubnodes())); + } + Pos p = pos; + if (p == Pos.UNKNOWN) p = span(); + Browsable f = make(p, p, (fun.isPred ? "pred " : "fun ")+fun.label , fun.getSubnodes()); + Browsable a = make(span(), span(), "" + args.size() + " argument" + (args.size()==1 ? "" : "s"), args); + return Util.asList(f, a); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprChoice.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprChoice.java new file mode 100644 index 00000000..a400364c --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprChoice.java @@ -0,0 +1,207 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import static edu.mit.csail.sdg.alloy4compiler.ast.Type.EMPTY; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.Pos; + +/** Immutable; represents an unresolved node that has several possibilities. */ + +public final class ExprChoice extends Expr { + + /** The unmodifiable list of Expr(s) from that this ExprChoice can refer to. */ + public final ConstList choices; + + /** The unmodifiable list of String(s) explaining where each choice came from. */ + public final ConstList reasons; + + /** Caches the span() result. */ + private Pos span=null; + + //============================================================================================================// + + /** {@inheritDoc} */ + @Override public Pos span() { + Pos p=span; + if (p==null) { + p=pos; + for(Expr a:choices) p=p.merge(a.span()); + span=p; + } + return p; + } + + //============================================================================================================// + + /** {@inheritDoc} */ + @Override public void toString(StringBuilder out, int indent) { + if (indent<0) { + out.append("<"); + for(Expr e:choices) { e.toString(out,-1); out.append(";"); } + out.append(">"); + } else { + for(int i=0; i choices, ConstList reasons, Type type, long weight) { + super(pos, null, true, type, 0, weight, emptyListOfErrors.make(type==EMPTY ? complain(pos,choices) : null)); + this.choices = choices; + this.reasons = reasons; + } + + //============================================================================================================// + + /** Construct an ExprChoice node. */ + public static Expr make(Pos pos, ConstList choices, ConstList reasons) { + if (choices.size()==0) return new ExprBad(pos, "", new ErrorType(pos, "This expression failed to be typechecked.")); + if (choices.size()==1 && choices.get(0).errors.isEmpty()) return choices.get(0); // Shortcut + Type type=EMPTY; + boolean first=true; + long weight=0; + for(Expr x:choices) { + type=x.type.merge(type); + if (first || weight>x.weight) if (x.type!=EMPTY) { weight=x.weight; first=false; } + } + return new ExprChoice(pos, choices, reasons, type, weight); + } + + //============================================================================================================// + + /** Resolve the list of choices, or return an ExprBad object containing the list of unresolvable ambiguities. */ + private Expr resolveHelper(boolean firstPass, final Type t, List choices, List reasons, Collection warns) { + List ch = new ArrayList(choices.size()); + List re = new ArrayList(choices.size()); + // We first prefer exact matches + for(int i=0; iint +// if (ch.size()==0 && Type.SIGINT2INT && t.is_int) { +// for(int i=0; isigint +// if (ch.size()==0 && Type.INT2SIGINT && t.hasArity(1)) { +// for(int i=0; i1) { + List ch2 = new ArrayList(ch.size()); + List re2 = new ArrayList(ch.size()); + long w = 0; + for(int i=0; i0 && c.weight>w) continue; else if (ch2.size()==0 || c.weight1) { + ch2 = new ArrayList(ch.size()); + for(Expr c:ch) ch2.add(c.resolve(t, null)); + return resolveHelper(false, t, ch2, re, warns); + } + } + // If we are down to exactly 1 match, return it + if (ch.size()==1) return ch.get(0).resolve(t, warns); + // If we are faced with 2 or more choices, but they all result in emptyset-of-the-same-arity, then just return emptyset + none: + while(ch.size()>1) { + int arity = -1; + for(Expr c: ch) { + if (c.type.is_bool || c.type.is_int() || c.type.hasTuple()) break none; + int a = c.type.arity(); + if (a<1) break none; + if (arity<0) arity=a; else if (arity!=a) break none; + } + Expr ans = Sig.NONE; + while(arity>1) {ans=ans.product(Sig.NONE); arity--;} + return ExprUnary.Op.NOOP.make(span(), ans); + } + // Otherwise, complain! + String txt; + if (ch.size()>1) { + txt="\nThis name is ambiguous due to multiple matches:"; + } else { + txt="\nThis name cannot be resolved; its relevant type does not intersect with any of the following candidates:"; + re = reasons; + } + StringBuilder msg = new StringBuilder(txt); + for(String r:re) msg.append('\n').append(r); + return new ExprBad(pos, toString(), new ErrorType(pos, msg.toString())); + } + + /** {@inheritDoc} */ + @Override public Expr resolve(Type t, Collection warns) { + if (errors.size()>0) return this; else return resolveHelper(true, t, choices, reasons, warns); + } + + //============================================================================================================// + + /** {@inheritDoc} */ + public int getDepth() { + int max = 1; + for(Expr x: choices) { int tmp=x.getDepth(); if (max T accept(VisitReturn visitor) throws Err { + if (!errors.isEmpty()) throw errors.pick(); + throw new ErrorType(span(), "This expression failed to be resolved."); + } + + /** {@inheritDoc} */ + @Override public String getHTML() { return "error (parser or typechecker failed)"; } + + /** {@inheritDoc} */ + @Override public List getSubnodes() { return new ArrayList(0); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprConstant.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprConstant.java new file mode 100644 index 00000000..8b38520c --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprConstant.java @@ -0,0 +1,176 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.UNIV; + +/** Immutable; represents a constant in the AST. */ + +public final class ExprConstant extends Expr { + + /** The type of constant. */ + public final Op op; + + /** If this node is a String constant, then this field stores the String, else this field stores "". */ + public final String string; + + /** If this node is a number constant, then this field stores the number, else this field stores 0. */ + public final int num; + + /** Return the number if this node is a number constant, otherwise return 0. */ + public int num() { return num; } + + /** {@inheritDoc} */ + @Override public Pos span() { return pos; } + + /** {@inheritDoc} */ + @Override public void toString(StringBuilder out, int indent) { + if (indent<0) { + if (op==Op.NUMBER) out.append(num); else if (op==Op.STRING) out.append(string); else out.append(op); + } else { + for(int i=0; i warns) { return this; } + + /** {@inheritDoc} */ + @Override public final T accept(VisitReturn visitor) throws Err { return visitor.visit(this); } + + /** {@inheritDoc} */ + public int getDepth() { return 1; } + + /** {@inheritDoc} */ + @Override public String getHTML() { + switch(op) { + case TRUE: return "true"; + case FALSE: return "false"; + case IDEN: return "iden"; + case MAX: return "fun/max"; + case MIN: return "fun/min"; + case NEXT: return "fun/next"; + case EMPTYNESS: return "none"; + case STRING: return "\"" + string + "\""; + } + return "" + num + ""; + } + + /** {@inheritDoc} */ + @Override public List getSubnodes() { return new ArrayList(0); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprCustom.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprCustom.java new file mode 100644 index 00000000..fea6d801 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprCustom.java @@ -0,0 +1,49 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import java.util.Collection; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.JoinableList; +import static edu.mit.csail.sdg.alloy4compiler.ast.Type.EMPTY; + +/** Immutable; represents a custom node. + * + *

Invariant: this.type==EMPTY && this.errors.size()==1 + */ + +public abstract class ExprCustom extends Expr { + + /** {@inheritDoc} */ + @Override public Pos span() { return pos; } + + /** Constructs an ExprCustom object. + * @param pos - the Pos for this expression (can be Pos.UNKNOWN if unknown) + * @param error - the error to display if this node does not get desugared + */ + public ExprCustom(Pos pos, Err error) { + super(pos, null, false, EMPTY, 0, 0, new JoinableList(error)); + if (error==null) throw new NullPointerException(); + } + + /** {@inheritDoc} */ + @Override public Expr resolve(Type t, Collection warns) { return this; } + + /** {@inheritDoc} */ + @Override public final T accept(VisitReturn visitor) throws Err { throw errors.pick(); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprHasName.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprHasName.java new file mode 100644 index 00000000..714c381a --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprHasName.java @@ -0,0 +1,44 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import edu.mit.csail.sdg.alloy4.Pos; + +/** Immutable; represents a named entity (such as a Field, or a LET or QUANTIFICATION variable, or a function/predicate parameter). */ + +public abstract class ExprHasName extends Expr { + + /** The label associated with this object; it's used for pretty-printing and does not have to be unique. */ + public final String label; + + /** Constructs an ExprHasName object */ + ExprHasName(Pos pos, String label, Type type) { + super(pos, null, false, type, 0, 0, null); + this.label = (label==null ? "" : label); + } + + /** {@inheritDoc} */ + @Override public final boolean isSame(Expr obj) { + while(obj instanceof ExprUnary && ((ExprUnary)obj).op==ExprUnary.Op.NOOP) obj=((ExprUnary)obj).sub; + return this==obj; + } + + /** {@inheritDoc} */ + @Override public final Pos span() { return pos; } + + /** {@inheritDoc} */ + public final int getDepth() { return 1; } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprITE.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprITE.java new file mode 100644 index 00000000..003900a1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprITE.java @@ -0,0 +1,166 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import static edu.mit.csail.sdg.alloy4compiler.ast.Type.EMPTY; + +import java.util.Collection; +import java.util.List; + +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.JoinableList; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Util; + +/** Immutable; represents an if-then-else expression. + * + *

Invariant: type!=EMPTY => (cond.mult==0 && left.mult==0 && right.mult==0) + */ + +public final class ExprITE extends Expr { + + /** The condition formula. */ + public final Expr cond; + + /** The then-clause. */ + public final Expr left; + + /** The else-clause. */ + public final Expr right; + + /** Caches the span() result. */ + private Pos span = null; + + /** {@inheritDoc} */ + @Override public Pos span() { + Pos p = span; + if (p==null) span = (p = cond.span().merge(right.span()).merge(left.span())); + return p; + } + + /** {@inheritDoc} */ + @Override public void toString(StringBuilder out, int indent) { + if (indent<0) { + out.append('('); + cond.toString(out,-1); + out.append(" => "); + left.toString(out,-1); + out.append(" else "); + right.toString(out,-1); + out.append(')'); + } else { + for(int i=0; i warns) { + if (errors.size()>0) return this; + Type a = left.type, b = right.type; + if (p.size()>0) { + a = a.intersect(p); + b = b.intersect(p); + //if (p.is_int()) { a=Type.makeInt(a); b=Type.makeInt(b); } + if (p.is_bool) { a=Type.makeBool(a); b=Type.makeBool(b); } + if (warns!=null && left.type.hasTuple() && !a.hasTuple()) warns.add(new ErrorWarning(left.span(),"This subexpression is redundant.")); + if (warns!=null && right.type.hasTuple() && !b.hasTuple()) warns.add(new ErrorWarning(right.span(),"This subexpression is redundant.")); + } else { + a = p; + b = p; + } + Expr cond = this.cond.resolve(Type.FORMULA, warns); + Expr left = this.left.resolve(a, warns); + Expr right = this.right.resolve(b, warns); + return (cond==this.cond && left==this.left && right==this.right) ? this : make(pos,cond,left,right); + } + + /** {@inheritDoc} */ + public int getDepth() { + int a = cond.getDepth(), b = left.getDepth(), c = right.getDepth(); + if (a>=b) return 1+(a>=c ? a : c); else return 1+(b>=c ? b : c); + } + + /** {@inheritDoc} */ + @Override public final T accept(VisitReturn visitor) throws Err { return visitor.visit(this); } + + /** {@inheritDoc} */ + @Override public String getHTML() { return "if-then-else" + " " + type + ""; } + + /** {@inheritDoc} */ + @Override public List getSubnodes() { return Util.asList(cond, left, right); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprLet.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprLet.java new file mode 100644 index 00000000..5265312d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprLet.java @@ -0,0 +1,139 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import java.util.Collection; +import java.util.List; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.JoinableList; +import edu.mit.csail.sdg.alloy4.Util; + +/** Immutable; represents an expression of the form (let a=b | x). + * + *

Invariant: type!=EMPTY => (var.type.unambiguos() && sub.mult==0) + */ + +public final class ExprLet extends Expr { + + /** The LET variable. */ + public final ExprVar var; + + /** The expression bound to the LET variable. */ + public final Expr expr; + + /** The body of the LET expression. */ + public final Expr sub; + + /** Caches the span() result. */ + private Pos span = null; + + //=============================================================================================================// + + /** {@inheritDoc} */ + @Override public Pos span() { + Pos p = span; + if (p==null) span = (p = var.span().merge(expr.span()).merge(sub.span())); + return p; + } + + //=============================================================================================================// + + /** {@inheritDoc} */ + @Override public void toString(StringBuilder out, int indent) { + if (indent<0) { + out.append("(let ").append(var.label).append("= ").append(expr.toString()).append(" | "); + sub.toString(out,-1); + out.append(')'); + } else { + for(int i=0; i errs = var.errors.make(expr.errors).make(sub.errors); + if (expr.mult!=0) + errs = errs.make(new ErrorSyntax(expr.span(), "Multiplicity expression not allowed here.")); + if (sub.mult != 0) + errs = errs.make(new ErrorSyntax(sub.span(), "Multiplicity expression not allowed here.")); + if (errs.size()==0 && var.type!=expr.type) + if (/*[AM] var.type.is_int()!=expr.type.is_int()|| */ + var.type.is_bool != expr.type.is_bool || + var.type.arity() != expr.type.arity()) + errs = errs.make(new ErrorType(var.span(), "This variable has type "+var.type+" but is bound to a value of type "+expr.type)); + return new ExprLet(pos, var, expr, sub, errs); + } + + //=============================================================================================================// + + /** {@inheritDoc} */ + @Override public Expr resolve(Type p, Collection warns) { + if (errors.size()>0) return this; + // The var and expr are always already fully resolved, so we only need to resolve sub + Expr newSub = sub.resolve(p, warns); + if (warns!=null && !newSub.hasVar(var)) warns.add(new ErrorWarning(var.pos, "This variable is unused.")); + return (sub==newSub) ? this : make(pos, var, expr, newSub); + } + + //=============================================================================================================// + + /** {@inheritDoc} */ + public int getDepth() { + int a=var.getDepth(), b=sub.getDepth(), c=expr.getDepth(); + if (a T accept(VisitReturn visitor) throws Err { return visitor.visit(this); } + + /** {@inheritDoc} */ + @Override public String getHTML() { return "let " + type + ""; } + + /** {@inheritDoc} */ + @Override public List getSubnodes() { + Browsable a = make(var.pos, var.pos, "var "+var.label+" = ...", expr); + Browsable b = make(sub.span(), sub.span(), "where...", sub); + return Util.asList(a, b); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprList.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprList.java new file mode 100644 index 00000000..d95c730a --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprList.java @@ -0,0 +1,238 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.ConstList.TempList; +import edu.mit.csail.sdg.alloy4.JoinableList; +import static edu.mit.csail.sdg.alloy4compiler.ast.Type.EMPTY; + +/** Immutable; represents disjoint[] or pred/totalOrder[] or (... and ... and ..) and other similar list of arugments. + * + *

Invariant: type!=EMPTY => (all x:args | x.mult==0) + */ + +public final class ExprList extends Expr { + + /** This class contains all possible builtin predicates. */ + public static enum Op { + /** DISJOINT (meaning the argument relations are all disjoint) */ DISJOINT, + /** TOTALORDER (meaning it's a total order over the arguments) */ TOTALORDER, + /** AND (meaning the logical conjunction of all arguments) */ AND, + /** OR (meaning the logical disjunction of all arguments) */ OR + }; + + /** The builtin operator. */ + public final Op op; + + /** The unmodifiable list of arguments. */ + public final ConstList args; + + /** Caches the span() result. */ + private Pos span = null; + + //============================================================================================================// + + /** {@inheritDoc} */ + @Override public Pos span() { + Pos p=span; + if (p==null) { + p=pos.merge(closingBracket); + for(Expr a:args) p=p.merge(a.span()); + span=p; + } + return p; + } + + //============================================================================================================// + + /** {@inheritDoc} */ + @Override public void toString(StringBuilder out, int indent) { + if (indent<0) { + out.append(op).append("["); + for(int i=0; i0) out.append(", "); args.get(i).toString(out,-1); } + out.append(']'); + } else { + for(int i=0; i list = new TempList(2); + list.add(a); + list.add(b); + return make(pos, closingBracket, Op.AND, list.makeConst()); + } + + /** Generates the expression (arg1 || arg2) */ + public static ExprList makeOR(Pos pos, Pos closingBracket, Expr a, Expr b) { + TempList list = new TempList(2); + list.add(a); + list.add(b); + return make(pos, closingBracket, Op.OR, list.makeConst()); + } + + /** Generates the expression pred/totalOrder[arg1, args2, arg3...] */ + public static ExprList makeTOTALORDER(Pos pos, Pos closingBracket, List args) { return make(pos, closingBracket, Op.TOTALORDER, args); } + + /** Generates the expression disj[arg1, args2, arg3...] */ + public static ExprList makeDISJOINT(Pos pos, Pos closingBracket, List args) { return make(pos, closingBracket, Op.DISJOINT, args); } + + /** Return a new ExprList object that is the same as this one except with one additional argument. */ + public ExprList addArg(Expr x) { + List args = new ArrayList(this.args); + args.add(x); + return make(pos, closingBracket, op, args); + } + + //============================================================================================================// + + /** {@inheritDoc} */ + @Override public Expr resolve(Type p, Collection warns) { + TempList newargs = new TempList(args.size()); + boolean changed = false; + if (errors.size()>0) return this; + if (op==Op.AND || op==Op.OR) { + for(int i=0; i T accept(VisitReturn visitor) throws Err { return visitor.visit(this); } + + /** {@inheritDoc} */ + @Override public String getHTML() { return "" + op + " [ ]"; } + + /** {@inheritDoc} */ + @Override public List getSubnodes() { return args; } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprQt.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprQt.java new file mode 100644 index 00000000..b773c574 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprQt.java @@ -0,0 +1,285 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.NoSuchElementException; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.JoinableList; +import edu.mit.csail.sdg.alloy4.ConstList.TempList; +import static edu.mit.csail.sdg.alloy4compiler.ast.Type.EMPTY; + +/** Immutable; represents a quantified expression. + * + * It can have one of the following forms: + * + *
+ *
( all a,b:t | formula ) + *
( no a,b:t | formula ) + *
( lone a,b:t | formula ) + *
( one a,b:t | formula ) + *
( some a,b:t | formula ) + *
( sum a,b:t | integer expression ) + *
{ a,b:t | formula } + *
{ a,b:t } + *
+ * + *
Invariant: type!=EMPTY => sub.mult==0 + *
Invariant: type!=EMPTY => vars.size()>0 + */ + +public final class ExprQt extends Expr { + + /** The operator (ALL, NO, LONE, ONE, SOME, SUM, or COMPREHENSION) */ + public final Op op; + + /** The unmodifiable list of variables. */ + public final ConstList decls; + + /** The body of the quantified expression. */ + public final Expr sub; + + /** Caches the span() result. */ + private Pos span; + + /** Return the number of variables. */ + public int count() { + int n = 0; + for(Decl d: decls) n = n + d.names.size(); + return n; + } + + /** Return the i-th variable. */ + public ExprVar get(int i) { + if (i<0) throw new NoSuchElementException(); + for(Decl d: decls) { + if (i < d.names.size()) return (ExprVar) (d.names.get(i)); + i = i - d.names.size(); + } + throw new NoSuchElementException(); + } + + /** Return the i-th variable's bound. */ + public Expr getBound(int i) { + if (i<0) throw new NoSuchElementException(); + for(Decl d: decls) { + if (i < d.names.size()) return d.expr; + i = i - d.names.size(); + } + throw new NoSuchElementException(); + } + + //=============================================================================================================// + + /** {@inheritDoc} */ + @Override public Pos span() { + Pos p = span; + // We intentionally do NOT merge the VAR's position into the span. + // That allows us to control the highlighting of this component + // simply by deciding this.pos and this.closingBracket + if (p == null) span = (p = pos.merge(closingBracket).merge(sub.span())); + return p; + } + + //=============================================================================================================// + + /** {@inheritDoc} */ + @Override public void toString(StringBuilder out, int indent) { + if (indent<0) { + boolean first = true; + if (op!=Op.COMPREHENSION) out.append('(').append(op).append(' '); else out.append('{'); + for(Decl d: decls) for(ExprHasName v: d.names) { if (!first) out.append(','); first=false; out.append(v.label); } + if (op!=Op.COMPREHENSION || !(sub instanceof ExprConstant) || ((ExprConstant)sub).op!=ExprConstant.Op.TRUE) + {out.append(" | "); sub.toString(out,-1);} + if (op!=Op.COMPREHENSION) out.append(')'); else out.append('}'); + } else { + for(int i=0; i decls, Expr sub) { + Type t = this==SUM ? Type.smallIntType() : (this==COMPREHENSION ? Type.EMPTY : Type.FORMULA); + if (this!=SUM) sub = sub.typecheck_as_formula(); else sub = sub.typecheck_as_int(); + boolean ambiguous = sub.ambiguous; + JoinableList errs = emptyListOfErrors; + if (sub.mult!=0) errs = errs.make(new ErrorSyntax(sub.span(), "Multiplicity expression not allowed here.")); + long weight = sub.weight; + if (decls.size()==0) errs = errs.make(new ErrorSyntax(pos, "List of variables cannot be empty.")); + for(Decl d: decls) { + Expr v = d.expr; + ambiguous = ambiguous || v.ambiguous; + weight = weight + v.weight; + errs = errs.make(v.errors); + if (v.errors.size()>0) continue; + if (v.type.size()==0) { + errs = errs.make(new ErrorType(v.span(), "This must be a set or relation. Instead, its type is " + v.type)); + continue; + } + ExprUnary.Op op = v.mult(); + if (op==ExprUnary.Op.EXACTLYOF) { errs = errs.make(new ErrorType(v.span(), "This cannot be an exactly-of expression.")); continue; } + if (this!=SUM && this!=COMPREHENSION) continue; + if (!v.type.hasArity(1)) { + errs = errs.make(new ErrorType(v.span(), "This must be a unary set. Instead, its type is " + v.type)); + continue; + } + if (v.mult==1) { + if (op == ExprUnary.Op.SETOF) + errs = errs.make(new ErrorType(v.span(), "This cannot be a set-of expression.")); + else if (op == ExprUnary.Op.SOMEOF) + errs = errs.make(new ErrorType(v.span(), "This cannot be a some-of expression.")); + else if (op == ExprUnary.Op.LONEOF) + errs = errs.make(new ErrorType(v.span(), "This cannot be a lone-of expression.")); + } + if (this==COMPREHENSION) { + Type t1 = v.type.extract(1); + for(int n=d.names.size(); n>0; n--) if (t==EMPTY) t = t1; else t = t.product(t1); + } + } + if (errs.isEmpty()) errs = sub.errors; // if the vars have errors, then the subexpression's errors will be too confusing, so let's skip them + return new ExprQt(pos, closingBracket, this, t, ConstList.make(decls), sub, ambiguous, weight, errs); + } + + /** Returns the human readable label for this operator */ + @Override public final String toString() { return label; } + } + + //=============================================================================================================// + + /** {@inheritDoc} */ + @Override public Expr resolve(Type unused, Collection warns) { + if (warns!=null && op!=Op.COMPREHENSION) { + for(int i=0; i1 && d.disjoint != null); + } + if (!hasDisjoint) return this; + TempList newdecls = new TempList(decls.size()); + Expr guard = null; + for(Decl d: decls) { + if (d.names.size()<=1 || d.disjoint==null) { newdecls.add(d); continue; } + guard = ExprList.makeDISJOINT(d.disjoint, null, d.names).and(guard); + newdecls.add(new Decl(null, null, null, d.names, d.expr)); + } + if (guard==null) return this; + Expr sub; + switch(op) { + case SUM: sub = guard.ite(this.sub, ExprConstant.ZERO); break; + case ALL: sub = guard.implies(this.sub); break; + default: sub = guard.and(this.sub); + } + return op.make(pos, closingBracket, newdecls.makeConst(), sub); + } + + //=============================================================================================================// + + /** {@inheritDoc} */ + public int getDepth() { + int max = sub.getDepth(); + for(Decl d: decls) for(ExprHasName x: d.names) { int tmp = x.getDepth(); if (max T accept(VisitReturn visitor) throws Err { return visitor.visit(this); } + + /** {@inheritDoc} */ + @Override public String getHTML() { + StringBuilder sb = new StringBuilder("").append(op).append(" "); + boolean first = true; + for (Decl d: decls) for(ExprHasName v: d.names) { if (!first) sb.append(", "); sb.append(v.label); first=false; } + return sb.append("... ").append(type).append("").toString(); + } + + /** {@inheritDoc} */ + @Override public List getSubnodes() { + ArrayList ans = new ArrayList(); + for(Decl d: decls) for(ExprHasName v: d.names) { + ans.add(make(v.pos, v.pos, "var "+v.label+" "+v.type+"", d.expr)); + } + ans.add(make(sub.span(), sub.span(), "body", sub)); + return ans; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprUnary.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprUnary.java new file mode 100644 index 00000000..7099f886 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprUnary.java @@ -0,0 +1,348 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.SIGINT; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.UNIV; +import static edu.mit.csail.sdg.alloy4compiler.ast.Type.EMPTY; + +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.List; + +import edu.mit.csail.sdg.alloy4.DirectedGraph; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.JoinableList; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; +import edu.mit.csail.sdg.alloy4compiler.ast.Type.ProductType; + +/** Immutable; represents a unary expression of the form "(OP subexpression)" + * + *

Invariant: type!=EMPTY => sub.mult==0 + */ + +public final class ExprUnary extends Expr { + + /** The unary operator. */ + public final Op op; + + /** The subexpression. */ + public final Expr sub; + + /** Caches the span() result. */ + private Pos span=null; + + //============================================================================================================// + + /** {@inheritDoc} */ + @Override public Pos span() { + Pos p=span; + if (p==null) { if (op==Op.NOOP && pos!=Pos.UNKNOWN) span=(p=pos); else span=(p=pos.merge(sub.span())); } + return p; + } + + //============================================================================================================// + + /** {@inheritDoc} */ + @Override public void toString(StringBuilder out, int indent) { + if (indent<0) { + switch(op) { + case SOMEOF: out.append("some "); break; + case LONEOF: out.append("lone "); break; + case ONEOF: out.append("one "); break; + case SETOF: out.append("set "); break; + case EXACTLYOF: out.append("exactly "); break; + case CAST2INT: out.append("int["); sub.toString(out,-1); out.append(']'); return; + case CAST2SIGINT: out.append("Int["); sub.toString(out,-1); out.append(']'); return; + case NOOP: break; + default: out.append(op).append(' '); + } + sub.toString(out,-1); + } else { + for(int i=0; iint"), + /** integer-to-IntAtom */ CAST2SIGINT("int->Int"), + /** No-Operation */ NOOP("NOOP"); + + /** The constructor */ + private Op(String label) {this.label=label;} + + /** The human readable label for this operator */ + private final String label; + + /** Construct an ExprUnary node. + * @param pos - the original position of the "unary operator" in the file (can be null if unknown) + * @param sub - the subexpression + * + *

Alloy4 disallows multiplicity like this: "variable : one (X lone-> Y)", + *
that is, a some/lone/one in front of an arrow multiplicity declaration. + *
Alloy4 does allow "variable : set (X lone-> Y)", where we ignore the word "set". + *
(This desugaring is done by the ExprUnary.Op.make() method, so ExprUnary's constructor never sees it) + */ + public final Expr make(Pos pos, Expr sub) { return make(pos, sub, null, 0); } + + /** Construct an ExprUnary node. + * @param pos - the original position of the "unary operator" in the file (can be null if unknown) + * @param sub - the subexpression + * @param extraError - if nonnull, it will be appended as an extra error + * @param extraWeight - it's the amount of extra weight + * + *

Alloy4 disallows multiplicity like this: "variable : one (X lone-> Y)", + *
that is, a some/lone/one in front of an arrow multiplicity declaration. + *
Alloy4 does allow "variable : set (X lone-> Y)", where we ignore the word "set". + *
(This desugaring is done by the ExprUnary.Op.make() method, so ExprUnary's constructor never sees it) + */ + public final Expr make(Pos pos, Expr sub, Err extraError, long extraWeight) { + if (pos==null || pos==Pos.UNKNOWN) { if (this==NOOP) pos = sub.pos; else pos = sub.span(); } + JoinableList errors = sub.errors.make(extraError); + if (sub.mult!=0) { + if (this==SETOF) return sub; + if (this!=NOOP && extraError==null) + errors = errors.make(new ErrorSyntax(sub.span(), "Multiplicity expression not allowed here.")); + // When you have a multiplicity expression like (A one->one B), and you call cint() on it, + // cint() will try to compose a NOOP node around the (A one->one B) with the error message "This must be an integer!" + // So in such a case, we will have a "NOOP" in front of a "MULTIPLICITY", and we don't want + // to clutter the output window with an extra useless report of "Multiplicity expression not allowed here!" + } + extraError=null; + switch(this) { + case NOOP: break; + case NOT: sub=sub.typecheck_as_formula(); break; + case CAST2SIGINT: + if (sub instanceof ExprUnary) + if (((ExprUnary) sub).op == CAST2SIGINT) + return sub; + sub=sub.typecheck_as_int(); + break; + case CAST2INT: + if (sub instanceof ExprUnary) { + // shortcircuit + ExprUnary sub2 = (ExprUnary) sub; + if (sub2.op == CAST2INT) + return sub2; + if (sub2.op == CAST2SIGINT) + return sub2.sub; + } + sub=sub.typecheck_as_set(); + break; + default: sub=sub.typecheck_as_set(); + } + Type type=sub.type; + if (sub.errors.isEmpty()) switch(this) { + case EXACTLYOF: case SOMEOF: case LONEOF: case ONEOF: case SETOF: + if (this==SETOF || this==EXACTLYOF) type=Type.removesBoolAndInt(sub.type); else type=sub.type.extract(1); + if (type==EMPTY) extraError=new ErrorType(sub.span(), "After the some/lone/one multiplicity symbol, " + + "this expression must be a unary set.\nInstead, its possible type(s) are:\n" + sub.type); + break; + case NOT: case NO: case SOME: case LONE: case ONE: + type=Type.FORMULA; + break; + case TRANSPOSE: + type=sub.type.transpose(); + if (type==EMPTY) extraError=new ErrorType(sub.span(), "~ can be used only with a binary relation.\n" + + "Instead, its possible type(s) are:\n"+sub.type); + break; + case RCLOSURE: case CLOSURE: + type=sub.type.closure(); + if (type==EMPTY) extraError=new ErrorType(sub.span(), label+" can be used only with a binary relation.\n" + + "Instead, its possible type(s) are:\n"+sub.type); + if (this==RCLOSURE) type=Type.make2(UNIV); + break; + case CARDINALITY: + type=Type.smallIntType(); + break; + case CAST2INT: + if (!sub.type.hasArity(1)) extraError=new ErrorType(sub.span(), "int[] can be used only with a unary set.\n" + + "Instead, its possible type(s) are:\n"+sub.type); + type=Type.smallIntType(); + break; + case CAST2SIGINT: + type=SIGINT.type; + break; + } + return new ExprUnary(pos, this, sub, type, extraWeight + sub.weight, errors.make(extraError)); + } + + /** Returns the human readable label for this operator */ + @Override public final String toString() { return label; } + + /** Returns the human readable label already encoded for HTML */ + public final String toHTML() { + if (this == CAST2INT) return "Int->int"; + if (this == CAST2SIGINT) return "int->Int"; + return label; + } + } + + //============================================================================================================// + + /** {@inheritDoc} */ + @Override public Expr resolve(Type p, Collection warns) { + if (errors.size()>0) return this; + ErrorWarning w1=null, w2=null; + Type s=p; + switch(op) { + case NOT: + s=Type.FORMULA; + break; + case TRANSPOSE: case RCLOSURE: case CLOSURE: + if (warns!=null && op!=Op.TRANSPOSE && type.join(type).hasNoTuple()) + w1=new ErrorWarning(pos, this+" is redundant since its domain and range are disjoint: "+sub.type.extract(2)); + s = (op!=Op.TRANSPOSE) ? resolveClosure(p, sub.type) : sub.type.transpose().intersect(p).transpose() ; + if (warns!=null && s==EMPTY && p.hasTuple()) + w2=new ErrorWarning(sub.span(), + "The value of this expression does not contribute to the value of the parent.\nParent's relevant type = " + +p+"\nThis expression's type = "+sub.type.extract(2)); + break; + case CARDINALITY: case NO: case ONE: case SOME: case LONE: + s=Type.removesBoolAndInt(sub.type); + break; + case CAST2SIGINT: + s=Type.smallIntType(); + break; + case CAST2INT: + s=sub.type.intersect(SIGINT.type); + if (warns!=null && s.hasNoTuple()) + w1=new ErrorWarning(sub.span(), + "This expression should contain Int atoms.\nInstead, its possible type(s) are:\n"+sub.type.extract(1)); + break; + } + Expr sub = this.sub.resolve(s, warns); + if (w1!=null) warns.add(w1); + if (w2!=null) warns.add(w2); + return (sub==this.sub) ? this : op.make(pos, sub, null, weight-(this.sub.weight)); + } + + //============================================================================================================// + + /** Helper method that computes the relevant type for a closure expression. + * + *

Return Value == { c1->c2 | c1->c2 in childType, AND exists p1->p2 in parentType + * where p1..c1..c2..p2 is a path in the closure graph } + * + *

+ * We need to do this because of situations like this follow: + * Suppose e's type is "A->B + B->C". + * Therefore, ^e = A->B + B->C + A->C which makes sense. + * But as we compute the relevance type back down, we may have lost some entries, + * and possibly end up with only A->B + A->C so we need to rediscover the relevant edges. + */ + private static Type resolveClosure (Type parent, Type child) { + LinkedHashSet nodes = new LinkedHashSet(); + DirectedGraph graph = new DirectedGraph(); + // For each (v1->v2) in childType, add (v1->v2) into the graph. + for (ProductType c:child) if (c.arity()==2) { + PrimSig a=c.get(0), b=c.get(1); + nodes.add(a); + nodes.add(b); + graph.addEdge(a,b); + } + // For each distinct v1 and v2 in the graph where v1&v2!=empty, add the edges v1->v2 and v2->v1. + for (PrimSig a:nodes) for (PrimSig b:nodes) if (a!=b && a.intersects(b)) graph.addEdge(a,b); + // For each a->b in ParentType: + // 1) add a + // 2) add b + // 3) if a has subtypes/supertypes in the graph, connect between a and them. + // 4) if b has subtypes/supertypes in the graph, connect between b and them. + for (ProductType p:parent) if (p.arity()==2) { + PrimSig a=p.get(0), b=p.get(1); + // Add edges between a and all its subtypes and supertypes + if (!nodes.contains(a)) { + for (PrimSig x:nodes) if (a.intersects(x)) { graph.addEdge(a,x); graph.addEdge(x,a); } + nodes.add(a); + } + // Add edges between b and all its subtypes and supertypes + if (!nodes.contains(b)) { + for (PrimSig x:nodes) if (b.intersects(x)) { graph.addEdge(b,x); graph.addEdge(x,b); } + nodes.add(b); + } + } + // For each c1->c2 in childType, add c1->c2 into the finalType if there exists p1->p2 in parentType + // such that p1->..->c1->c2->..->p2 is a path in the graph. + Type answer=Type.EMPTY; + for (ProductType c:child) if (c.arity()==2) { + PrimSig c1=c.get(0), c2=c.get(1); + for (ProductType p:parent) if (p.arity()==2) { + PrimSig p1=p.get(0), p2=p.get(1); + if (graph.hasPath(p1,c1) && graph.hasPath(c2,p2)) { answer=answer.merge(c); break; } + } + } + return answer; + } + + //============================================================================================================// + + /** {@inheritDoc} */ + public int getDepth() { return 1 + sub.getDepth(); } + + /** {@inheritDoc} */ + @Override public final T accept(VisitReturn visitor) throws Err { return visitor.visit(this); } + + /** {@inheritDoc} */ + @Override public String getHTML() { return op==Op.NOOP ? sub.getHTML() : (op+" " + type + ""); } + + /** {@inheritDoc} */ + @Override public List getSubnodes() { return op==Op.NOOP ? sub.getSubnodes() : Util.asList(sub); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprVar.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprVar.java new file mode 100644 index 00000000..2fdc74db --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/ExprVar.java @@ -0,0 +1,75 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorWarning; + +/** Immutable; represents a LET or QUANTIFICATION variable in the AST. + * + *

Invariant: type!=EMPTY => (type==expr.type && !expr.ambiguous) + */ + +public final class ExprVar extends ExprHasName { + + /** {@inheritDoc} */ + @Override public void toString(StringBuilder out, int indent) { + if (indent<0) { + out.append(label); + } else { + for(int i=0; i with type=").append(type).append('\n'); + } + } + + /** Constructs an ExprVar object */ + private ExprVar(Pos pos, String label, Type type) { + super(pos, label, type); + } + + /** Constructs an ExprVar variable with the EMPTY type + * @param pos - the original position in the source file (can be null if unknown) + * @param label - the label for this variable (it is only used for pretty-printing and does not have to be unique) + */ + public static ExprVar make(Pos pos, String label) { + return new ExprVar(pos, label, Type.EMPTY); + } + + /** Constructs an ExprVar variable with the given type + * @param pos - the original position in the source file (can be null if unknown) + * @param label - the label for this variable (it is only used for pretty-printing and does not have to be unique) + * @param type - the type + */ + public static ExprVar make(Pos pos, String label, Type type) { + return new ExprVar(pos, label, type); + } + + /** {@inheritDoc} */ + @Override public Expr resolve(Type p, Collection warns) { return this; } + + /** {@inheritDoc} */ + @Override public T accept(VisitReturn visitor) throws Err { return visitor.visit(this); } + + /** {@inheritDoc} */ + @Override public String getHTML() { return "variable: " + label + " " + type + ""; } + + /** {@inheritDoc} */ + @Override public List getSubnodes() { return new ArrayList(0); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Func.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Func.java new file mode 100644 index 00000000..fa334ad1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Func.java @@ -0,0 +1,207 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.Util; + +/** Mutable; represents a predicate or function. + * + *

Invariant: the list of parameters do not contain duplicates + *

Invariant: none of the parameter declaration contains a predicate/function call + *

Invariant: the return type declaration does not contain a predicate/function call + */ + +public final class Func extends Browsable { + + /** The location in the original file where this predicate/function is declared; never null. */ + public final Pos pos; + + /** If nonnull, then this predicate/function is private (and this.isPrivate is the location of the "private" keyword) */ + public final Pos isPrivate; + + /** The label of this predicate/function; it does not need to be unique. */ + public final String label; + + /** True if this is a predicate; false if this is a function. */ + public final boolean isPred; + + /** The list of parameter declarations; may be an empty list if this predicate/function has no parameters. */ + public final ConstList decls; + + /** The declared return type; never null. */ + public final Expr returnDecl; + + /** Return the number of parameters. */ + public int count() { + int n = 0; + for(Decl d: decls) n = n + d.names.size(); + return n; + } + + /** Return the i-th parameter where i goes from 0 to count()-1 */ + public ExprVar get(int i) { + if (i<0) throw new NoSuchElementException(); + for(Decl d: decls) { + if (i params() { + int n = count(); + List list = new ArrayList(n); + for(Decl d: decls) for(ExprHasName name: d.names) list.add((ExprVar)name); + return list; + } + + /** Constructs a new predicate/function. + * + *

The first declaration's bound should be an expression with no free variables. + *
The second declaration's bound should be an expression with no free variables, except possibly the parameters in first declaration. + *
The third declaration's bound should be an expression with no free variables, except possibly the parameters in first two declarations. + *
etc. + *
The return declaration should have no free variables, except possibly the list of input parameters. + * + * @param pos - the original position in the file + * @param label - the label for this predicate/function (does not have to be unique) + * @param decls - the list of parameter declarations (can be null or an empty list if this predicate/function has no parameters) + * @param returnDecl - the return declaration (null if this is a predicate rather than a function) + * + * @throws ErrorType if returnType!=null and returnType cannot be unambiguously typechecked to be a set/relation + * @throws ErrorSyntax if the list of parameters contain duplicates + * @throws ErrorSyntax if at least one of the parameter declaration contains a predicate/function call + * @throws ErrorSyntax if this function's return type declaration contains a predicate/function call + */ + public Func(Pos pos, String label, List decls, Expr returnDecl, Expr body) throws Err { + this(pos, null, label, decls, returnDecl, body); + } + + /** Constructs a new predicate/function. + * + *

The first declaration's bound should be an expression with no free variables. + *
The second declaration's bound should be an expression with no free variables, except possibly the parameters in first declaration. + *
The third declaration's bound should be an expression with no free variables, except possibly the parameters in first two declarations. + *
etc. + *
The return declaration should have no free variables, except possibly the list of input parameters. + * + * @param pos - the original position in the file + * @param isPrivate - if nonnull, then the user intended this func/pred to be "private" + * @param label - the label for this predicate/function (does not have to be unique) + * @param decls - the list of parameter declarations (can be null or an empty list if this predicate/function has no parameters) + * @param returnDecl - the return declaration (null if this is a predicate rather than a function) + * + * @throws ErrorType if returnType!=null and returnType cannot be unambiguously typechecked to be a set/relation + * @throws ErrorSyntax if the list of parameters contain duplicates + * @throws ErrorSyntax if at least one of the parameter declaration contains a predicate/function call + * @throws ErrorSyntax if this function's return type declaration contains a predicate/function call + */ + public Func(Pos pos, Pos isPrivate, String label, List decls, Expr returnDecl, Expr body) throws Err { + if (pos==null) pos = Pos.UNKNOWN; + this.pos = pos; + this.isPrivate = isPrivate; + this.label = (label==null ? "" : label); + this.isPred = (returnDecl==null); + if (returnDecl==null) returnDecl = ExprConstant.FALSE; + if (returnDecl.mult==0 && returnDecl.type.arity()==1) returnDecl = ExprUnary.Op.ONEOF.make(null, returnDecl); + this.returnDecl = returnDecl; + this.body = body; + if (body.mult!=0) throw new ErrorSyntax(body.span(), "Multiplicity expression not allowed here."); + this.decls = ConstList.make(decls); + for(int n=count(), i=0; iPrecondition: The expression should have no free variables, + * except possibly the list of function parameters. + * + * @throws ErrorSyntax if newBody.mult!=0 + * @throws ErrorType if newBody cannot be unambiguously resolved + * @throws ErrorType if newBody's type is incompatible with the original declared type of this predicate/function + */ + public void setBody(Expr newBody) throws Err { + if (isPred) { + newBody = newBody.typecheck_as_formula(); + if (newBody.ambiguous) newBody = newBody.resolve_as_formula(null); + if (newBody.errors.size()>0) throw newBody.errors.pick(); + } else { + newBody = newBody.typecheck_as_set(); + if (newBody.ambiguous) newBody = newBody.resolve_as_set(null); + if (newBody.errors.size()>0) throw newBody.errors.pick(); + if (newBody.type.arity() != returnDecl.type.arity()) + throw new ErrorType(newBody.span(), + "Function return type is "+returnDecl.type+",\nso the body must be a relation with arity " + +returnDecl.type.arity()+".\nSo the body's type cannot be: "+newBody.type); + } + if (newBody.mult!=0) throw new ErrorSyntax(newBody.span(), "Multiplicity expression not allowed here."); + this.body = newBody; + } + + /** Return the body of this predicate/function. + *
If the user has not called setBody() to set the body, + *
then the default body is "false" (if this is a predicate), + *
or the empty set/relation of the appropriate arity (if this is a function). + */ + public Expr getBody() { return body; } + + /** Convenience method that calls this function with the given list of arguments. */ + public Expr call(Expr... args) { return ExprCall.make(null, null, this, Util.asList(args), 0); } + + /** Returns a human-readable description for this predicate/function */ + @Override public final String toString() { return (isPred ? "pred " : "fun ") + label; } + + /** {@inheritDoc} */ + @Override public final Pos pos() { return pos; } + + /** {@inheritDoc} */ + @Override public final Pos span() { return pos; } + + /** {@inheritDoc} */ + @Override public String getHTML() { return (isPred ? "pred " : "fun ") + label; } + + /** {@inheritDoc} */ + @Override public List getSubnodes() { + ArrayList ans = new ArrayList(); + for(Decl d: decls) for(ExprHasName v: d.names) { + ans.add(make(v.pos, v.pos, "parameter "+v.label+" "+v.type+"", d.expr)); + } + if (!isPred) ans.add(make(returnDecl.span(), returnDecl.span(), "return type " + returnDecl.type + "", returnDecl)); + ans.add(make(body.span(), body.span(), "body " + body.type + "", body)); + return ans; + } + +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Module.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Module.java new file mode 100644 index 00000000..09d364bb --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Module.java @@ -0,0 +1,77 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.List; +import javax.swing.JFrame; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.Listener; +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.alloy4.SafeList; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.Func; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; + +/** This interface represents an Alloy module. */ + +public interface Module { + + /** Returns the text of the "MODULE" line at the top of the file; "unknown" if the line has not be parsed from the file yet. */ + public String getModelName(); + + /** Return the simplest path pointing to this Module ("" if this is the main module) */ + public String path(); + + /** Return the list containing THIS MODULE and all modules reachable from this module. */ + public SafeList getAllReachableModules(); + + /** Return the list of all relative filenames included from this MODULE. */ + public List getAllReachableModulesFilenames(); + + /** Return the list containing UNIV, SIGINT, SEQIDX, STRING, NONE, and all sigs defined in this module or a reachable submodule. */ + public ConstList getAllReachableSigs(); + + /** Returns an unmodifiable list of all signatures defined inside this module. */ + public SafeList getAllSigs(); + + /** Return an unmodifiable list of all functions in this module. */ + public SafeList getAllFunc(); + + /** Return an unmodifiable list of all assertions in this module. */ + public ConstList> getAllAssertions(); + + /** Return an unmodifiable list of all facts in this module. */ + public SafeList> getAllFacts(); + + /** Return the conjunction of all facts in this module and all reachable submodules (not including field constraints, nor including sig appended constraints) */ + public Expr getAllReachableFacts(); + + /** Return an unmodifiable list of all commands in this module. */ + public ConstList getAllCommands(); + + /** Add a global expression; if the name already exists, it is removed first. */ + public void addGlobal(String name, Expr value); + + /** Display this object (and so objects) as a tree; if listener!=null, it will receive OurTree.Event.SELECT events. */ + public JFrame showAsTree(Listener listener); + + /** Parse one expression by starting fromt this module as the root module. */ + public Expr parseOneExpressionFromString(String input) throws Err, FileNotFoundException, IOException; +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Sig.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Sig.java new file mode 100644 index 00000000..d0a6cd03 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Sig.java @@ -0,0 +1,590 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.alloy4.ConstList.TempList; +import edu.mit.csail.sdg.alloy4compiler.ast.Attr.AttrType; +import edu.mit.csail.sdg.alloy4.SafeList; +import edu.mit.csail.sdg.alloy4.Util; + +/** Mutable; represents a signature. */ + +public abstract class Sig extends Expr { + + /** The built-in "univ" signature. */ + public static final PrimSig UNIV = new PrimSig("univ", null, false); + + /** The built-in "Int" signature. */ + public static final PrimSig SIGINT = new PrimSig("Int", UNIV, false); + + /** The built-in "seq/Int" signature. */ + public static final PrimSig SEQIDX = new PrimSig("seq/Int", SIGINT, true); + + /** The built-in "String" signature. */ + public static final PrimSig STRING = new PrimSig("String", UNIV, true); + + /** The built-in "none" signature. */ + public static final PrimSig NONE = new PrimSig("none", null, false); + + /** The built-in "none" signature. */ + public static final PrimSig GHOST = mkGhostSig(); + + private static final PrimSig mkGhostSig() { + try { + return new PrimSig("Univ", null, new Attr[0]); + } catch (Err e) { + return null; // never happens + } + } + + /** Returns the name for this sig; this name need not be unique. */ + @Override public final String toString() { return label; } + + /** {@inheritDoc} */ + @Override public final void toString(StringBuilder out, int indent) { + if (indent<0) { + out.append(label); + } else { + for(int i=0; i Note: at most one of "lone", "one", "some" can be nonnull for each sig. + */ + public final Pos isOne; + + /** Nonnull if this sig's multiplicity is declared to be some. + *

Note: at most one of "lone", "one", "some" can be nonnull for each sig. + */ + public final Pos isSome; + + /** Nonnull if the user wanted this sig to be private. + *

Note: this value is always null for builtin sigs. + */ + public final Pos isPrivate; + + /** Nonnull if the sig is toplevel and is an enum. + *

Note: this value is always null for builtin sigs. + */ + public final Pos isEnum; + + /** Nonnull if this sig is a meta sig. + *

Note: this value is always null for builtin sigs. + */ + public final Pos isMeta; + + /** The label for this sig; this name does not need to be unique. */ + public final String label; + + /** The declaration that quantifies over each atom in this sig. */ + public final Decl decl; + + /** The list of "per atom" fact associated with this signature; each fact is allowed to refer to this.decl.get() */ + private final SafeList facts = new SafeList(); + + /** Returns true if this sig is a toplevel sig (meaning: it is UNIV, or it is a non-subset sig with parent==UNIV) */ + public final boolean isTopLevel() { + return (this!=NONE) && (this instanceof PrimSig) && (this==UNIV || ((PrimSig)this).parent==UNIV); + } + + /** Constructs a new builtin PrimSig. */ + private Sig(String label) { + super(Pos.UNKNOWN, null); + Expr oneof = ExprUnary.Op.ONEOF.make(null, this); + ExprVar v = ExprVar.make(null, "this", oneof.type); + this.decl = new Decl(null, null, null, Util.asList(v), oneof); + this.builtin = true; + this.isAbstract = null; + this.isLone = null; + this.isOne = null; + this.isSome = null; + this.label = label; + this.isSubset = null; + this.isSubsig = Pos.UNKNOWN; + this.isPrivate = null; + this.isMeta = null; + this.isEnum = null; + this.attributes = ConstList.make(); + } + + /** Constructs a new PrimSig or SubsetSig. */ + private Sig(Type type, String label, Attr... attributes) throws Err { + super(AttrType.WHERE.find(attributes), type); + this.attributes = Util.asList(attributes); + Expr oneof = ExprUnary.Op.ONEOF.make(null, this); + ExprVar v = ExprVar.make(null, "this", oneof.type); + this.decl = new Decl(null, null, null, Util.asList(v), oneof); + Pos isAbstract=null, isLone=null, isOne=null, isSome=null, isSubsig=null, isSubset=null, isPrivate=null, isMeta=null, isEnum=null; + for(Attr a: attributes) if (a!=null) switch(a.type) { + case ABSTRACT: isAbstract = a.pos.merge(isAbstract); break; + case ENUM: isEnum = a.pos.merge(isEnum); break; + case LONE: isLone = a.pos.merge(isLone); break; + case META: isMeta = a.pos.merge(isMeta); break; + case ONE: isOne = a.pos.merge(isOne); break; + case PRIVATE: isPrivate = a.pos.merge(isPrivate); break; + case SOME: isSome = a.pos.merge(isSome); break; + case SUBSET: isSubset = a.pos.merge(isSubset); break; + case SUBSIG: isSubsig = a.pos.merge(isSubsig); break; + } + this.isPrivate = isPrivate; + this.isMeta = isMeta; + this.isEnum = isEnum; + this.isAbstract = isAbstract; + this.isLone = isLone; + this.isOne = isOne; + this.isSome = isSome; + this.isSubset = isSubset; + this.isSubsig = isSubsig; + this.label = label; + this.builtin = false; + if (isLone!=null && isOne!=null) throw new ErrorSyntax(isLone.merge(isOne), "You cannot declare a sig to be both lone and one."); + if (isLone!=null && isSome!=null) throw new ErrorSyntax(isLone.merge(isSome), "You cannot declare a sig to be both lone and some."); + if (isOne!=null && isSome!=null) throw new ErrorSyntax(isOne.merge(isSome), "You cannot declare a sig to be both one and some."); + if (isSubset!=null && isAbstract!=null) throw new ErrorSyntax(isAbstract, "Subset signature cannot be abstract."); + if (isSubset!=null && isSubsig!=null) throw new ErrorSyntax(isAbstract, "Subset signature cannot be a regular subsignature."); + } + + /** Returns true if we can determine the two expressions are equivalent; may sometimes return false. */ + @Override public boolean isSame(Expr obj) { + Sig me = this; + while(obj instanceof ExprUnary && ((ExprUnary)obj).op==ExprUnary.Op.NOOP) obj=((ExprUnary)obj).sub; + while(obj instanceof SubsetSig && ((SubsetSig)obj).exact && ((SubsetSig)obj).parents.size()==1) obj = ((SubsetSig)obj).parents.get(0); + while(me instanceof SubsetSig && ((SubsetSig)me).exact && ((SubsetSig)me).parents.size()==1) me = ((SubsetSig)me).parents.get(0); + return (me == obj); + } + + /** Returns true iff "this is equal or subtype of that" */ + public abstract boolean isSameOrDescendentOf(Sig that); + + /** {@inheritDoc} */ + public int getDepth() { return 1; } + + /** Add a new per-atom fact; this expression is allowed to refer to this.decl.get() */ + public void addFact(Expr fact) throws Err { + if (fact.ambiguous) fact = fact.resolve_as_formula(null); + if (!fact.errors.isEmpty()) throw fact.errors.pick(); + if (!fact.type.is_bool) throw new ErrorType(fact.span(), "This expression must be a formula; instead its type is "+fact.type); + facts.add(fact); + } + + /** Return the list of per-atom facts; each expression is allowed to refer to this.decl.get() */ + public SafeList getFacts() { return facts.dup(); } + + /** {@inheritDoc} */ + @Override public final String getHTML() { return "sig " + label + " " + type + ""; } + + /** {@inheritDoc} */ + @Override public final List getSubnodes() { + TempList ans = new TempList(); + if (this instanceof PrimSig) { + Sig parent = ((PrimSig)this).parent; + if (parent!=null && !parent.builtin) ans.add(make(parent.pos, parent.span(), "extends sig " + parent.label, parent.getSubnodes())); + } else { + ConstList parents = ((SubsetSig)this).parents; + for(Sig p: parents) ans.add(make(p.pos, p.span(), "in sig " + p.label, p.getSubnodes())); + } + for(Decl d: fields) for(ExprHasName v: d.names) { + ans.add(make(v.span(), v.span(), "field " + v.label + " " + v.type + "", d.expr)); + } + for(Expr f: facts) ans.add(make(f.span(), f.span(), "fact", f)); + return ans.makeConst(); + } + + //==============================================================================================================// + + /** Mutable; reresents a non-subset signature. + * + *

Note: except for "children()", the return value of every method is always valid for all time; + * for example, given sigs A and B, and you call C=A.intersect(B), then the result C will always be + * the intersection of A and B even if the caller later constructs more sigs or subsigs or subsetsigs... + */ + + public static final class PrimSig extends Sig { + + /** Stores its immediate children sigs (not including NONE) + *

Note: if this==UNIV, then this list will always be empty, since we don't keep track of UNIV's children + */ + private final SafeList children = new SafeList(); + + /** Returns its immediate children sigs (not including NONE) + *

Note: if this==UNIV, then this method will throw an exception, since we don't keep track of UNIV's children + */ + public SafeList children() throws Err { + if (this==UNIV) throw new ErrorFatal("Internal error (cannot enumerate the subsigs of UNIV)"); + return children.dup(); + } + + /** Returns its subsigs and their subsigs and their subsigs, etc. + *

Note: if this==UNIV, then this method will throw an exception, since we don't keep track of UNIV's children + */ + public Iterable descendents() throws Err { + if (this==UNIV) throw new ErrorFatal("Internal error (cannot enumerate the subsigs of UNIV)"); + Iterable answer = children.dup(); + for(PrimSig x:children) answer = Util.fastJoin(answer, x.descendents()); + return answer; + } + + /** If this is UNIV or NONE, then this field is null, else this field is the parent sig. */ + public final PrimSig parent; + + /** Constructs a builtin PrimSig. */ + private PrimSig(String label, PrimSig parent, boolean add) { + super(label); + this.parent = parent; + if (add) this.parent.children.add(this); + } + + /** Constructs a non-builtin sig. + * + * @param label - the name of this sig (it does not need to be unique) + * @param parent - the parent (must not be null, and must not be NONE) + * @param attributes - the list of optional attributes such as ABSTRACT, LONE, ONE, SOME, SUBSIG, PRIVATE, META, or ENUM + * + * @throws ErrorSyntax if the signature has two or more multiplicities + * @throws ErrorType if you attempt to extend the builtin sigs NONE, SIGINT, SEQIDX, or STRING + */ + public PrimSig (String label, PrimSig parent, Attr... attributes) throws Err { + super(((parent!=null && parent.isEnum!=null) ? parent.type : null), label, Util.append(attributes, Attr.SUBSIG)); + if (parent==SIGINT) throw new ErrorSyntax(pos, "sig "+label+" cannot extend the builtin \"Int\" signature"); + if (parent==SEQIDX) throw new ErrorSyntax(pos, "sig "+label+" cannot extend the builtin \"seq/Int\" signature"); + if (parent==STRING) throw new ErrorSyntax(pos, "sig "+label+" cannot extend the builtin \"String\" signature"); + if (parent==NONE) throw new ErrorSyntax(pos, "sig "+label+" cannot extend the builtin \"none\" signature"); + if (parent==null) parent=UNIV; else if (parent!=UNIV) parent.children.add(this); + this.parent = parent; + if (isEnum!=null && parent!=UNIV) throw new ErrorType(pos, "sig "+label+" is not a toplevel sig, so it cannot be an enum."); + for( ; parent!=null ; parent=parent.parent) if (parent.isEnum!=null) { + if (parent!=this.parent) throw new ErrorSyntax(pos, "sig "+label+" cannot extend a signature which is an atom in an enum."); + if (isOne==null) throw new ErrorSyntax(pos, "sig "+label+" is an atom in an enum, so it must have the \"one\" multiplicity."); + } + } + + /** Constructs a toplevel non-builtin sig. + * + * @param label - the name of this sig (it does not need to be unique) + * @param attributes - the list of optional attributes such as ABSTRACT, LONE, ONE, SOME, SUBSIG, PRIVATE, META, or ENUM + * + * @throws ErrorSyntax if the signature has two or more multiplicities + */ + public PrimSig(String label, Attr... attributes) throws Err { this(label, null, attributes); } + + /** {@inheritDoc} */ + @Override public boolean isSameOrDescendentOf(Sig that) { + if (this==NONE || this==that || that==UNIV) return true; + if (this==UNIV || that==NONE) return false; + for(PrimSig me=this; me!=null; me=me.parent) if (me==that) return true; + return false; + } + + /** Returns the intersection between this and that (and returns "none" if they do not intersect). */ + public PrimSig intersect(PrimSig that) { + if (this.isSameOrDescendentOf(that)) return this; + if (that.isSameOrDescendentOf(this)) return that; + return NONE; + } + + /** Returns true iff the intersection between this and that is not "none". */ + public boolean intersects(PrimSig that) { + if (this.isSameOrDescendentOf(that)) return this!=NONE; + if (that.isSameOrDescendentOf(this)) return that!=NONE; + return false; + } + + /** Returns the most-specific-sig that contains this and that. + * In particular, if this extends that, then return that. + */ + public PrimSig leastParent(PrimSig that) { + if (isSameOrDescendentOf(that)) return that; + PrimSig me=this; + while(true) { + if (that.isSameOrDescendentOf(me)) return me; + me=me.parent; + if (me==null) return UNIV; + } + } + } + + //==============================================================================================================// + + /** Mutable; reresents a subset signature. */ + + public static final class SubsetSig extends Sig { + + /** The list of Sig that it is a subset of; this list is never empty. */ + public final ConstList parents; + + /** If true, then this sig is EXACTLY equal to the union of its parents. */ + public final boolean exact; + + /** Computes the type for this sig. */ + private static Type getType(String label, Iterable parents) throws Err { + Type ans = null; + if (parents!=null) for(Sig parent: parents) { + if (parent==UNIV) return UNIV.type; + if (ans==null) ans=parent.type; else ans=ans.unionWithCommonArity(parent.type); + } + return (ans!=null) ? ans : (UNIV.type); + } + + /** Constructs a subset sig. + * + * @param label - the name of this sig (it does not need to be unique) + * @param parents - the list of parents (if this list is null or empty, we assume the caller means UNIV) + * @param attributes - the list of optional attributes such as EXACT, SUBSET, LONE, ONE, SOME, PRIVATE, or META + * + * @throws ErrorSyntax if the signature has two or more multiplicities + * @throws ErrorType if parents only contains NONE + */ + public SubsetSig(String label, Collection parents, Attr... attributes) throws Err { + super(getType(label,parents), label, Util.append(attributes, Attr.SUBSET)); + if (isEnum!=null) throw new ErrorType(pos, "Subset signature cannot be an enum."); + boolean exact = false; + for(Attr a: attributes) if (a!=null && a.type==AttrType.EXACT) exact = true; + this.exact = exact; + TempList temp = new TempList(parents==null ? 1 : parents.size()); + if (parents==null || parents.size()==0) { + temp.add(UNIV); + } else { + for(Sig parent:parents) { + if (!Version.experimental) { + if (parent==SIGINT) throw new ErrorSyntax(pos, "sig "+label+" cannot be a subset of the builtin \"Int\" signature"); + if (parent==SEQIDX) throw new ErrorSyntax(pos, "sig "+label+" cannot be a subset of the builtin \"seq/Int\" signature"); + if (parent==STRING) throw new ErrorSyntax(pos, "sig "+label+" cannot be a subset of the builtin \"String\" signature"); + } + if (parent==Sig.UNIV) {temp.clear(); temp.add(UNIV); break;} + if (parent!=Sig.NONE && !temp.contains(parent)) temp.add(parent); + } + } + if (temp.size()==0) throw new ErrorType(pos, "Sig "+label+" must have at least one non-empty parent."); + this.parents = temp.makeConst(); + } + + /** {@inheritDoc} */ + @Override public boolean isSameOrDescendentOf(Sig that) { + if (that==UNIV || that==this) return true; + if (that==NONE) return false; + for(Sig p:parents) if (p.isSameOrDescendentOf(that)) return true; + return false; + } + } + + //==============================================================================================================// + + /** Mutable; represents a field. */ + + public static final class Field extends ExprHasName { + + /** The sig that this field belongs to; never null. */ + public final Sig sig; + + /** Nonnull if the user wanted this field to be private. */ + public final Pos isPrivate; + + /** Nonnull if this field is a meta field. */ + public final Pos isMeta; + + /** True if this is a defined field. */ + public final boolean defined; + + /** The declaration that this field came from. */ + private Decl decl; + + /** Return the declaration that this field came from. */ + public Decl decl() { return decl; } + + /** Constructs a new Field object. */ + private Field(Pos pos, Pos isPrivate, Pos isMeta, Pos disjoint, Pos disjoint2, Sig sig, String label, Expr bound) throws Err { + super(pos, label, sig.type.product(bound.type)); + this.defined = bound.mult() == ExprUnary.Op.EXACTLYOF; + if (sig.builtin) throw new ErrorSyntax(pos, "Builtin sig \""+sig+"\" cannot have fields."); + if (!bound.errors.isEmpty()) throw bound.errors.pick(); + if (!this.defined && bound.hasCall()) throw new ErrorSyntax(pos, "Field \""+label+"\" declaration cannot contain a function or predicate call."); + if (bound.type.arity()>0 && bound.type.hasNoTuple()) throw new ErrorType(pos, "Cannot bind field "+label+" to the empty set or empty relation."); + this.isPrivate = (isPrivate!=null ? isPrivate : sig.isPrivate); + this.isMeta = (isMeta!=null ? isMeta : sig.isMeta); + this.sig = sig; + } + + /** Returns a human-readable description of this field's name. */ + @Override public String toString() { + if (sig.label.length()==0) return label; else return "field ("+sig+" <: "+label+")"; + } + + /** {@inheritDoc} */ + @Override public void toString(StringBuilder out, int indent) { + if (indent<0) { + out.append("(").append(sig.label).append(" <: ").append(label).append(")"); + } else { + for(int i=0; ifield " + label + " " + type + ""; } + + /** {@inheritDoc} */ + @Override public List getSubnodes() { + Expr bound = decl.expr; + Browsable s = make(sig.pos, sig.span(), "from sig "+sig.label, sig.getSubnodes()); + Browsable b = make(bound.span(), bound.span(), "bound", bound); + return Util.asList(s, b); + } + } + + //==============================================================================================================// + + /** The list of fields. */ + private final SafeList fields = new SafeList(); + + /** Return the list of fields as a unmodifiable list of declarations (where you can see which fields are declared to be disjoint) */ + public final SafeList getFieldDecls() { + return fields.dup(); + } + + /** Return the list of fields as a combined unmodifiable list (without telling you which fields are declared to be disjoint) */ + public final SafeList getFields() { + SafeList ans = new SafeList(); + for(Decl d: fields) for(ExprHasName n: d.names) ans.add((Field)n); + return ans.dup(); + } + + /** Add then return a new field, where "all x: ThisSig | x.F in bound" + *

Note: the bound must be fully-typechecked and have exactly 0 free variable, or have "x" as its sole free variable. + * + * @param label - the name of this field (it does not need to be unique) + * @param bound - the new field will be bound by "all x: one ThisSig | x.ThisField in bound" + * + * @throws ErrorSyntax if the sig is one of the builtin sig + * @throws ErrorSyntax if the bound contains a predicate/function call + * @throws ErrorType if the bound is not fully typechecked or is not a set/relation + */ + public final Field addField (String label, Expr bound) throws Err { + bound = bound.typecheck_as_set(); + if (bound.ambiguous) bound = bound.resolve_as_set(null); + if (bound.mult==0 && bound.type.arity()==1) bound = ExprUnary.Op.ONEOF.make(null, bound); // If unary, and no multiplicity symbol, we assume it's oneOf + final Field f = new Field(null, null, null, null, null, this, label, bound); + final Decl d = new Decl(null, null, null, Arrays.asList(f), bound); + f.decl = d; + fields.add(d); + return f; + } + + /** Add then return a new field, where "all x: ThisSig | x.F in bound" + *

Note: the bound must be fully-typechecked and have exactly 0 free variable, or have "x" as its sole free variable. + * + * @param pos - the position in the original file where this field was defined (can be null if unknown) + * @param isPrivate - if nonnull, that means the user intended this field to be "private" + * @param isMeta - if nonnull, that means the user intended this field to be "meta" + * @param labels - the names of the fields to be added (these names does not need to be unique) + * @param bound - the new field will be bound by "all x: one ThisSig | x.ThisField in bound" + * + * @throws ErrorSyntax if the sig is one of the builtin sig + * @throws ErrorSyntax if the bound contains a predicate/function call + * @throws ErrorType if the bound is not fully typechecked or is not a set/relation + */ + public final Field[] addTrickyField (Pos pos, Pos isPrivate, Pos isDisjoint, Pos isDisjoint2, Pos isMeta, String[] labels, Expr bound) throws Err { + bound = bound.typecheck_as_set(); + if (bound.ambiguous) bound = bound.resolve_as_set(null); + if (bound.mult==0 && bound.type.arity()==1) bound = ExprUnary.Op.ONEOF.make(null, bound); // If unary, and no multiplicity symbol, we assume it's oneOf + final Field[] f = new Field[labels.length]; + for(int i=0; i Note: the definition must be fully-typechecked and have exactly 0 free variables. + *

Note: currently the defined field must consist product and union operators over sigs. + * + * @param pos - the position in the original file where this field was defined (can be null if unknown) + * @param isPrivate - if nonnull, that means this field should be marked as private + * @param isMeta - if nonnull, that means this field should be marked as meta + * @param label - the name of this field (it does not need to be unique) + * @param bound - the new field will be defined to be exactly equal to sig.product(definition) + * + * @throws ErrorSyntax if the sig is one of the builtin sig + * @throws ErrorSyntax if the bound contains a predicate/function call + * @throws ErrorType if the bound is not fully typechecked or is not a set/relation + */ + public final Field addDefinedField(Pos pos, Pos isPrivate, Pos isMeta, String label, Expr bound) throws Err { + bound = bound.typecheck_as_set(); + if (bound.ambiguous) bound = bound.resolve_as_set(null); + if (bound.mult() != ExprUnary.Op.EXACTLYOF) bound = ExprUnary.Op.EXACTLYOF.make(null, bound); + final Field f = new Field(pos, isPrivate, isMeta, null, null, this, label, bound); + final Decl d = new Decl(null, null, null, Arrays.asList(f), bound); + f.decl = d; + fields.add(d); + return f; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Type.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Type.java new file mode 100644 index 00000000..ea992594 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/Type.java @@ -0,0 +1,899 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.NONE; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.UNIV; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.SafeList; +import edu.mit.csail.sdg.alloy4.ConstList.TempList; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; + +/** Immutable; represents the type of an expression. + * + *

Invariant: all x:entries | x.arity()>0 + * + *

Note: except for "toString()" and "fold()", the return value of every method is always valid for all time; + * for example, given types A and B, and you call C=A.intersect(B), then the result C will always be + * the intersection of A and B even if the caller later constructs more sigs or subsigs or subsetsigs... + */ + +public final class Type implements Iterable { + + //[AM] +// /** This configuration option is true if we want to automatically cast from int to Int when necessary. */ +// public static final boolean INT2SIGINT=true; +// +// /** This configuration option is true if we want to automatically cast from Int to int when necessary. */ +// public static final boolean SIGINT2INT=true; + + /** Immutable; represents a list of PrimSig objects. + * + *

Invariant: "one of the sig in the list is NONE" iff "every sig in the list is NONE". + * + *

Note: the return value of every method is always valid for all time; + * for example, given ProductType A and B, and you call C=A.intersect(B), then the result C will always be + * the intersection of A and B even if the caller later constructs more sigs or subsigs or subsetsigs... + */ + public static final class ProductType { + + /** The array of PrimSig objects. */ + private final PrimSig[] types; + + /** The ProductType with arity==0 */ + private static final ProductType zero = new ProductType(new PrimSig[0]); + + /** Constructs a new ProductType object consisting of the given array of PrimSig objects. + *

Precondition: "one of the sig in the list is NONE" iff "every sig in the list is NONE" + *

Note: it will use the array as-is, so the caller should give up its reference to the array. + *

Note: this constructor promises it won't call any method or read anything from any of the sig(s). + */ + private ProductType(PrimSig[] array) { + types = array; + } + + /** Constructs a new ProductType made of exactly 1 PrimSig; + *

Note: this constructor promises it won't call any method or read anything from the sig. + */ + private ProductType(PrimSig sig) { + types = new PrimSig[]{sig}; + } + + /** Constructs a new ProductType made of exactly n references to the same PrimSig object. + *

Note: this constructor promises it won't call any method or read anything from the sig. + */ + private ProductType(int n, PrimSig sig) { + types = new PrimSig[n]; + for(int i=0; i=0; i--) if (types[i]!=x.types[i]) return false; + return true; + } + + /** Returns true if (this[i] is equal or subtype of that[i]) for every i. + *

Precondition: this.arity == that.arity + */ + private boolean isSubtypeOf(ProductType that) { + if (this==that) return true; + for(int i=types.length-1; i>=0; i--) if (!types[i].isSameOrDescendentOf(that.types[i])) return false; + return true; + } + + /** Returns true if (this[i] is equal or subtype of that[i]) for every i. + *

Precondition: this.arity == that.arity + */ + private boolean isSubtypeOf(List that) { + for(int i=types.length-1; i>=0; i--) if (!types[i].isSameOrDescendentOf(that.get(i))) return false; + return true; + } + + /** Returns the arity of this ProductType object. */ + public int arity() { return types.length; } + + /** Returns a specific PrimSig in this ProductType + * @throws ArrayIndexOutOfBoundsException if (i < 0) or (i >= arity) + */ + public PrimSig get(int i) { return types[i]; } + + /** Returns true if this.arity==0 or this==NONE->..->NONE */ + public boolean isEmpty() { return types.length==0 || types[0]==NONE; } + + /** Returns the tranpose of this + *

Precondition: this.arity()==2 + */ + private ProductType transpose() { + if (types[0]==types[1]) return this; else return new ProductType(new PrimSig[]{types[1], types[0]}); + } + + /** Returns the cross product of this and that. + *

Note: If either or both is NONE->..->NONE, then we return NONE->..->NONE instead. + */ + ProductType product(ProductType that) { + final int n = types.length + that.types.length; + if (n<0) throw new OutOfMemoryError(); // This means the addition overflowed! + if (this.isEmpty()) return (n==this.types.length) ? this : (new ProductType(n, NONE)); + if (that.isEmpty()) return (n==that.types.length) ? that : (new ProductType(n, NONE)); + final PrimSig[] ans = new PrimSig[n]; + int j=0; + for(int i=0; i Note: if (this[i] & that[i]) is empty for at least one i, then we return "NONE->..->NONE" instead. + * + *

Precondition: this.arity == that.arity + */ + private ProductType intersect(ProductType that) { + if (isEmpty()) return this; + if (that.isEmpty()) return that; + final int n = types.length; + final PrimSig[] ans = new PrimSig[n]; + for(int i=0; i Precondition: this.arity == that.arity + */ + private boolean intersects(ProductType that) { + for(int i=types.length-1; i>=0; i--) if (!types[i].intersects(that.types[i])) return false; + return true; + } + + /** Returns the relational join of this and that. + * + *

Note: if (this.rightmost() & that.leftmost()) is empty, we return NONE->..->NONE instead. + * + *

Precondition: (this.arity > 0) && (that.arity > 0) && (this.arity!=1 || that.arity!=1) + */ + ProductType join(ProductType that) { + int left=types.length, right=that.types.length, n=left+right-2; + if (left<=1 && right<=1) return zero; // We try to do the best we can, in the face of precondition violation + if (n<0) throw new OutOfMemoryError(); // This means the addition overflowed! + final PrimSig a=types[left-1], b=that.types[0], c=a.intersect(b); + if (c==NONE) return new ProductType(n, c); + final PrimSig[] types = new PrimSig[n]; + int j=0; + for(int i=0; ithis[1]->this[2]->this[3]..->this[n-1] + * except the i-th entry is replaced by (this[i] & that). + * + *

Otherwise, this method returns NONE->..->NONE + */ + ProductType columnRestrict(PrimSig that, int i) { + if (i<0 || i>=types.length || isEmpty()) return this; + that = types[i].intersect(that); + if (that==types[i]) return this; + if (that==NONE) return new ProductType(types.length, that); + final PrimSig[] newlist = new PrimSig[types.length]; + for(int j=0; j"); + ans.append(types[i]); + } + return ans.toString(); + } + } + + /** Constant value with is_int==false, is_bool==false, and entries.size()==0. */ + public static final Type EMPTY = new Type(false, null, 0); + + //[AM] + /* Can't be final because it relies on a static Sig.SIGINT being initialized */ + private static Type SMALL_INT = null; + + /** Constant value with is_int==false, is_bool==true, and entries.size()==0. */ + public static final Type FORMULA = new Type(true, null, 0); + + /** Constant value with is_int==true, is_bool==true, and entries.size()==0. */ + public static final Type INTANDFORMULA = new Type(true, null, 0); + + /** True if primitive integer value is a possible value in this type. */ +// private final boolean is_int; + private boolean is_small_int; + + /** True if primitive boolean value is a possible value in this type. */ + public final boolean is_bool; + + /** Contains a summary of the arities in this type. + * + *
The (1<<0) bitmask is nonzero iff arity X exists for some X>30 + *
The (1<<1) bitmask is nonzero iff arity 1 exists + *
The (1<<2) bitmask is nonzero iff arity 2 exists + *
The (1<<3) bitmask is nonzero iff arity 3 exists + *
... + *
The (1<<30) bitmask is nonzero iff arity 30 exists + */ + private final int arities; + + /** Contains the list of ProductType entries in this type. */ + private final ConstList entries; + + public boolean is_int() { return checkIntType(); } + public boolean is_small_int() { return is_int() && is_small_int; } + + private boolean checkIntType() { + if (entries == null) + return false; + for (ProductType e : entries) { + if (e.arity() == 1 && e.get(0) == Sig.SIGINT) + return true; + } + return false; + } + + public static Type smallIntType() { + if (SMALL_INT == null) { + SMALL_INT = make(Sig.SIGINT); + SMALL_INT.is_small_int = true; + } + return SMALL_INT; + } + + /** Returns an iterator that iterates over the ProductType entries in this type. + *

This iterator will reject all modification requests. + */ + public Iterator iterator() { return entries.iterator(); } + + /** Merge "x" into the set of entries, then return the new arity bitmask. + *
Precondition: entries and arities are consistent + */ + private static int add(TempList entries, int arities, ProductType x) { + if (x==null || x.types.length==0) return arities; + final int arity=x.types.length; + // If x is subsumed by a ProductType in this, return. Likewise, remove all entries in this that are subsumed by x. + for(int n=entries.size(), i=n-1; i>=0; i--) { + ProductType y=entries.get(i); + if (y.types.length != arity) continue; + if (x.isSubtypeOf(y)) return arities; + if (y.isSubtypeOf(x)) { n--; entries.set(i, entries.get(n)).remove(n); } + } + if (arity>30) arities = arities | 1; else arities = arities | (1 << arity); + entries.add(x); + return arities; + } + + /** Create a new type consisting of the given set of entries, set of arities, and the given is_int/is_bool values; + *

Precondition: entries and arities must be consistent + */ + private Type(boolean is_bool, ConstList entries, int arities) { + this.is_bool = is_bool; + if (entries==null || entries.size()==0 || arities==0) { + this.entries = ConstList.make(); + this.arities = 0; + } else { + this.entries = entries; + this.arities = arities; + } + } + + /** Create a new type consisting of the given set of entries, set of arities, and the given is_int/is_bool values; + *

Precondition: entries and arities must be consistent + */ + private static Type make(boolean is_bool, ConstList entries, int arities) { + if (entries==null || entries.size()==0 || arities==0) { + return is_bool?FORMULA:EMPTY; + } + return new Type(is_bool, entries, arities); + } + + /** Create the type consisting of the given ProductType entry. + */ + static Type make(ProductType productType) { + int ar=productType.types.length; + if (ar==0) return EMPTY; + return make(false, ConstList.make(1,productType), (ar>30) ? 1 : (1<list[start+1]->..->list[end-1] + * (If start<0, end<0, end>list.size(), or start>=end, this method will return EMPTY) + */ + static Type make(List list, int start, int end) { + if (start<0 || end<0 || start>=end || end>list.size()) return EMPTY; + PrimSig[] newlist = new PrimSig[end-start]; + for(int i=start, j=0; isig". */ + static Type make2(PrimSig sig) { + return make(new ProductType(2,sig)); + } + + /** Create a new type that is the same as "old", except the "is_int" flag is set to true. */ +// static Type makeInt(Type old) { +// if (old.is_int()) return old; else return make(true, old.is_bool, old.entries, old.arities); +// } + + /** Create a new type that is the same as "old", except the "is_bool" flag is set to true. */ + static Type makeBool(Type old) { + if (old.is_bool) return old; else return make(true, old.entries, old.arities); + } + + /** Create a new type that is the same as "old", except the "is_bool" and "is_int" flags are both set to false. */ + public static Type removesBoolAndInt(Type old) { + if (!old.is_bool && !old.is_int()) return old; else return make(false, old.entries, old.arities); + } + + /** Returns true iff ((this subsumes that) and (that subsumes this)) */ + @Override public boolean equals(Object that) { + if (this==that) return true; + if (!(that instanceof Type)) return false; + Type x = (Type)that; + if (arities != x.arities || /*[AM] is_int() != x.is_int() || */is_bool != x.is_bool) return false; + again1: + for(ProductType aa:entries) { + for(ProductType bb:x.entries) if (aa.types.length==bb.types.length && aa.isSubtypeOf(bb)) continue again1; + return false; + } + again2: + for(ProductType bb:x.entries) { + for(ProductType aa:entries) if (aa.types.length==bb.types.length && bb.isSubtypeOf(aa)) continue again2; + return false; + } + return true; + } + + /** Returns a hash code consistent with equals() */ + @Override public int hashCode() { return arities * /*[AM] (is_int()?1732051:1) **/ (is_bool?314157:1); } + + /** Returns true if this.size()==0 or every entry consists only of NONE. */ + public boolean hasNoTuple() { + for(int i=entries.size()-1; i>=0; i--) if (!entries.get(i).isEmpty()) return false; + return true; + } + + /** Returns true if this.size()>0 and at least one entry consists of something other than NONE. */ + public boolean hasTuple() { + for(int i=entries.size()-1; i>=0; i--) if (!entries.get(i).isEmpty()) return true; + return false; + } + + /** Returns the number of ProductType entries in this type. */ + public int size() { return entries.size(); } + + /** Returns true iff this contains an entry of the given arity. */ + public boolean hasArity(int arity) { + if (arity<=30) return arity>0 && ((arities & (1<=0; i--) if (entries.get(i).types.length==arity) return true; + return false; + } + + /** If every entry has the same arity, that arity is returned; + *
else if some entries have different arities, we return -1; + *
else we return 0 (which only happens when there are no entries at all). + */ + public int arity() { + if (arities==0) return 0; + int ans=0; + if ((arities & 1)==0) { + for(int i=1; i<=30; i++) if ((arities & (1<=0; j--) { + int i=entries.get(j).types.length; + if (ans==0) ans=i; else if (ans!=i) return -1; + } + } + return ans; + } + + /** Returns true if exists some A in this, some B in that, where (A[0]&B[0]!=empty) + *

This method ignores the "is_int" and "is_bool" flags. + */ + public boolean firstColumnOverlaps(Type that) { + if ((arities | that.arities)!=0) + for (ProductType a:this) + for (ProductType b:that) + if (a.types[0].intersects(b.types[0])) + return true; + return false; + } + + /** Returns true if exists some A in this, some B in that, where (A.arity==B.arity, and A[0]&B[0]!=empty) + *

This method ignores the "is_int" and "is_bool" flags. + */ + public boolean canOverride(Type that) { + if ((arities & that.arities)!=0) + for (ProductType a:this) + for (ProductType b:that) + if (a.types.length==b.types.length && a.types[0].intersects(b.types[0])) + return true; + return false; + } + + /** Returns true iff exists some A in this, some B in that, where A.arity==B.arity */ + public boolean hasCommonArity(Type that) { + if ((arities & 1)!=0 && (that.arities & 1)!=0) { + if (((arities-1) & (that.arities-1))!=0) return true; + for (ProductType a:this) for (ProductType b:that) if (a.types.length==b.types.length) return true; + return false; + } + return (arities & that.arities)!=0; + } + + /** Returns a new type { A->B | A is in this, and B is in that } + * + *

ReturnValue.is_int == false + *
ReturnValue.is_bool == false + * + *

If this.size()==0, or that.size()==0, then result.size()==0 + */ + public Type product(Type that) { + if ((arities | that.arities)==0) return EMPTY; + TempList ee=new TempList(); + int aa=0; + for (ProductType a:this) for (ProductType b:that) aa=add(ee, aa, a.product(b)); + return make(false, ee.makeConst(), aa); + } + + /** Returns true iff { A&B | A is in this, and B is in that } can have tuples. + */ + public boolean intersects(Type that) { + if ((arities & that.arities)!=0) + for (ProductType a:this) if (!a.isEmpty()) + for (ProductType b:that) if (a.types.length==b.types.length && !b.isEmpty() && a.intersects(b)) + return true; + return false; + } + + /** Returns a new type { A&B | A is in this, and B is in that } + * + *

ReturnValue.is_int == false + *
ReturnValue.is_bool == false + * + *

If this.size()==0, or that.size()==0, or they do not have entries with same arity, then result.size()==0 + */ + public Type intersect(Type that) { + if ((arities & that.arities)==0) return EMPTY; + TempList ee=new TempList(); + int aa=0; + for (ProductType a:this) + for (ProductType b:that) + if (a.types.length==b.types.length) + aa=add(ee, aa, a.intersect(b)); + return make(false, ee.makeConst(), aa); + } + + /** Returns a new type { A&that | A is in this } + * + *

ReturnValue.is_int == false + *
ReturnValue.is_bool == false + * + *

If (this.size()==0), or (that.arity is not in this), then result.size()==0 + */ + public Type intersect(ProductType that) { + if (!hasArity(that.types.length)) return EMPTY; + TempList ee=new TempList(); + int aa=0; + for (ProductType a:this) if (a.types.length==that.types.length) aa=add(ee, aa, a.intersect(that)); + return make(false, ee.makeConst(), aa); + } + + /** Returns a new type { A | A is in this, or A is in that } + * + *

ReturnValue.is_int == this.is_int || that.is_int + *
ReturnValue.is_bool == this.is_bool || that.is_bool + * + *

If this.size()==0 and that.size()==0, then result.size()==0 + * + *

As a special guarantee: if that==null, then the merge() method just returns the current object + */ + public Type merge(Type that) { + if (that==null) return this; + if (is_bool==that.is_bool) { + if (this.size()==0) return that; + if (that.size()==0) return this; + } + TempList ee=new TempList(entries); + int aa=arities; + for(ProductType x:that) aa=add(ee,aa,x); + return make(is_bool||that.is_bool, ee.makeConst(), aa); + } + + /** Returns a new type { A | A is in this, or A == that } + * + *

ReturnValue.is_int == this.is_int + *
ReturnValue.is_bool == this.is_bool + */ + public Type merge(ProductType that) { + TempList ee=new TempList(entries); + int aa=add(ee, arities, that); + return make(is_bool, ee.makeConst(), aa); + } + + /** Returns a new type { A | A is in this, or A == that.subList(begin,end) } + * + *

ReturnValue.is_int == this.is_int + *
ReturnValue.is_bool == this.is_bool + */ + public Type merge(ProductType that, int begin, int end) { + if (!(0<=begin && begin ee=new TempList(entries); + int aa=add(ee, arities, new ProductType(array)); + return make(is_bool, ee.makeConst(), aa); + } + + /** Returns a new type { A | A is in this, or A == that } + * + *

ReturnValue.is_int == this.is_int + *
ReturnValue.is_bool == this.is_bool + */ + public Type merge(List that) { + if (that.size() == 0) return this; + PrimSig[] array=new PrimSig[that.size()]; + for(int i=0; i < array.length; i++) { + array[i] = that.get(i); + if (array[i]==NONE) { + if (hasArity(array.length)) return this; + for(i=0; i ee=new TempList(entries); + int aa=add(ee, arities, new ProductType(array)); + return make(is_bool, ee.makeConst(), aa); + } + + /** Returns a new type { A | (A is in this && A.arity in that) or (A is in that && A.arity in this) } + * + *

ReturnValue.is_int == false + *
ReturnValue.is_bool == false + * + *

If this.size()==0 or that.size()==0, then result.size()==0 + * + *

Special promise: if the result would be identical to this, then we will return "this" as-is, without constructing a new object + */ + public Type unionWithCommonArity(Type that) { + if ((arities & that.arities)==0) return EMPTY; + TempList ee=new TempList(); + int aa=0; + if (this.size()>0 && that.size()>0) { + // add() ensures that if x doesn't need to change "ee", then "ee" will stay unchanged + for(ProductType x:this) if (that.hasArity(x.types.length)) aa=add(ee,aa,x); + for(ProductType x:that) if (this.hasArity(x.types.length)) aa=add(ee,aa,x); + } + // So now, if nothing changed, we want to return "this" as-is + if (!is_int() && !is_bool && aa==this.arities && ee.size()==this.entries.size()) { + for(int i=ee.size()-1; ; i--) { + if (i<0) return this; + if (ee.get(i) != this.entries.get(i)) break; + } + } + return make(false, ee.makeConst(), aa); + } + + /** Returns a new type { A | (A is in this && A.arity in that) } + * + *

ReturnValue.is_int == false + *
ReturnValue.is_bool == false + * + *

If this.size()==0 or that.size()==0, then result.size()==0 + */ + public Type pickCommonArity(Type that) { + if (!is_int() && !is_bool && (arities & 1)==0 && (arities & that.arities)==arities) return this; + TempList ee=new TempList(); + int aa=0; + if ((arities & 1)==0) { + for(ProductType x:entries) { + int xa = 1 << x.types.length; + if ((that.arities & xa) != 0) { aa = (aa|xa); ee.add(x); } + } + } else { + for(ProductType x:entries) if (that.hasArity(x.types.length)) aa=add(ee,aa,x); + } + return make(false, ee.makeConst(), aa); + } + + /** Returns a new type { A in this | A.artiy==1 } + * + *

ReturnValue.is_int == false + *
ReturnValue.is_bool == false + * + *

If this.size()==0, or does not contain any ProductType entries of the given arity, then result.size()==0 + */ + public Type pickUnary() { + if ((arities & (1<<1))==0) return EMPTY; + if (!is_int() && !is_bool && arities==(1<<1)) return this; + TempList ee=new TempList(); + for(ProductType x: entries) if (x.types.length == 1) ee.add(x); + return make(false, ee.makeConst(), (1<<1)); + } + + /** Returns a new type { A in this | A.artiy==2 } + * + *

ReturnValue.is_int == false + *
ReturnValue.is_bool == false + * + *

If this.size()==0, or does not contain any ProductType entries of the given arity, then result.size()==0 + */ + public Type pickBinary() { + if ((arities & (1<<2))==0) return EMPTY; + if (!is_int() && !is_bool && arities==(1<<2)) return this; + TempList ee=new TempList(); + for(ProductType x: entries) if (x.types.length == 2) ee.add(x); + return make(false, ee.makeConst(), (1<<2)); + } + + /** Returns a new type { A | A is binary and ~A is in this } + * + *

ReturnValue.is_int == false + *
ReturnValue.is_bool == false + * + *

If this.size()==0, or does not contain any binary ProductType entries, then result.size()==0 + */ + public Type transpose() { + if ((arities & (1<<2))==0) return EMPTY; + TempList ee=new TempList(); + int aa=0; + for(ProductType a:this) if (a.types.length==2) aa=add(ee, aa, a.transpose()); + return make(false, ee.makeConst(), aa); + } + + /** Returns true if for all A in this, there exists B in that, where A is equal or subset of B. + *

Note: if this.is_int && !that.is_int, we return false immediately. + *

Note: if this.is_bool && !that.is_bool, we return false immediately. + *

Note: if this nothing above is violated, and this type has no relational entry in it, we return true. + */ + public boolean isSubtypeOf(Type that) { + if (this==that) return true; + if (is_int() && !that.is_int()) return false; + if (is_bool && !that.is_bool) return false; + List> those = that.fold(); + again: + for(ProductType a: this) { + for(List b: those) if (a.arity()==b.size() && a.isSubtypeOf(b)) continue again; + return false; + } + return true; + } + + /** Returns a new type { A.B | exists A in this, exists B in that, where A.arity+B.arity>2 } + *

If this.size()==0, or that.size()==0, or none of the entries have the right arity, then result.size()==0. + * + *

ReturnValue.is_int == false + *
ReturnValue.is_bool == false + */ + public Type join(Type that) { + if (size()==0 || that.size()==0) return EMPTY; + TempList ee=new TempList(); + int aa=0; + for (ProductType a:this) for (ProductType b:that) if (a.types.length>1 || b.types.length>1) aa=add(ee, aa, a.join(b)); + return make(false, ee.makeConst(), aa); + } + + /** Returns a new type { R[0]->..->R[n-1] | + * exists n-ary A in this, exists unary B in that, such that R[i]==A[i] except R[0]==(A[0] & B) + * + *

ReturnValue.is_int == false + *
ReturnValue.is_bool == false + * + *

If this.size()==0, or that does not contain any unary entry, then result.size()==0 + */ + public Type domainRestrict(Type that) { + if (size()==0 || (that.arities & (1<<1))==0) return EMPTY; + TempList ee=new TempList(); + int aa=0; + for (ProductType b:that) + if (b.types.length==1) + for (ProductType a:this) + aa = add(ee, aa, a.columnRestrict(b.types[0], 0)); + return make(false, ee.makeConst(), aa); + } + + /** Returns a new type { R[0]->..->R[n-1] | + * exists n-ary A in this, exists unary B in that, such that R[i]==A[i] except R[n-1]==(A[n-1] & B) + * + *

ReturnValue.is_int == false + *
ReturnValue.is_bool == false + * + *

If this.size()==0, or that does not contain any unary entry, then result.size()==0 + */ + public Type rangeRestrict(Type that) { + if (size()==0 || (that.arities & (1<<1))==0) return EMPTY; + TempList ee=new TempList(); + int aa=0; + for (ProductType b:that) + if (b.types.length==1) + for (ProductType a:this) + aa = add(ee, aa, a.columnRestrict(b.types[0], a.types.length-1)); + return make(false, ee.makeConst(), aa); + } + + /** Returns a new type { A | (A in this) and (A.arity == arity) } + * + *

ReturnValue.is_int == false + *
ReturnValue.is_bool == false + * + *

If it does not contain any entry with the given arity, then result.size()==0 + */ + public Type extract(int arity) { + final int aa = (arity>30 ? 1 : (1< ee=new TempList(); + for(ProductType x: entries) if (x.types.length == arity) ee.add(x); + return make(false, ee.makeConst(), aa); + } + + /** Returns a new type u + u.u + u.u.u + ... (where u == the set of binary entries in this type) + * + *

ReturnValue.is_int == false + *
ReturnValue.is_bool == false + * + *

If it does not contain any binary entries, then result.size()==0 + */ + public Type closure() { + Type ans=extract(2), u=ans, uu=u.join(u); + while(uu.hasTuple()) { + Type oldans=ans, olduu=uu; + ans=ans.unionWithCommonArity(uu); + uu=uu.join(u); + if (oldans==ans && olduu.equals(uu)) break; + // The special guarantee of unionWithCommonArity() allows us to use the cheaper "oldans==ans" here + // instead of doing the more expensive "oldans.equals(ans)" + } + return ans; + } + + /** Convert this type into a UNION of PRODUCT of sigs. + * @throws ErrorType if it does not contain exactly one arity + * @throws ErrorType if is_int is true + * @throws ErrorType if is_bool is true + */ + public Expr toExpr() throws Err { + int arity = arity(); + if (is_bool || arity<1) + throw new ErrorType("Cannot convert this type into a bounding expression."); + Expr ans = null; + for(ProductType pt:this) { + Expr pro = null; + for(int i=0; i If {a}+this.entries contain a set of entries X1..Xn, such that + *
(1) For each X: X[j]==a[j] for i!=j, and X[i].super==a[i].super + *
(2) X1[i]..Xn[i] exhaust all the direct subsignatures of an abstract parent sig + *
THEN: + *
we remove X1..Xn, then return the merged result of X1..Xn + *
ELSE + *
we change nothing, and simply return null + * + *

Precondition: a[i] is not NONE, and a[i].parent is abstract, and a[i].parent!=UNIV + */ + private static List fold(ArrayList> entries, List a, int i) { + PrimSig parent = a.get(i).parent; + SafeList children; + try { children=parent.children(); } catch(Err ex) { return null; } // Exception only occurs if a[i].parent==UNIV + List subs = children.makeCopy(); + ArrayList> toDelete = new ArrayList>(); + for(int bi=entries.size()-1; bi>=0; bi--) { + List b=entries.get(bi); + if (b.size() == a.size()) { + for(int j=0; ;j++) { + if (j>=b.size()) {toDelete.add(b); subs.remove(b.get(i)); break;} + PrimSig bt1=a.get(j), bt2=b.get(j); + if (i==j && bt2.parent!=parent) break; + if (i!=j && bt2!=bt1) break; + } + } + } + subs.remove(a.get(i)); + if (subs.size()!=0) return null; + entries.removeAll(toDelete); + entries.remove(a); + a=new ArrayList(a); + a.set(i, parent); + return a; + } + + /** Return the result of folding this Type (that is, whenever a subset of relations are identical + * except for 1 position, where together they comprise of all direct subsigs of an abstract sig, + * then we merge them) + * + *

Note: the result is only current with respect to the current existing sig objects + */ + public List> fold() { + ArrayList> e = new ArrayList>(); + for(ProductType xx: entries) { + List x = Arrays.asList(xx.types); + while(true) { + int n = x.size(); + boolean changed = false; + for(int i=0; i folded = fold(e, x, i); + if (folded!=null) {x=folded; changed=true; i--;} + } + } + if (changed==false) break; + } + e.add(x); + } + return e; + } + + /** Returns a human-readable description of this type. */ + @Override public String toString() { + boolean first=true; + StringBuilder ans=new StringBuilder("{"); + //[AM] if (is_int()) { first=false; ans.append("PrimitiveInteger"); } + if (is_bool) { if (!first) ans.append(", "); first=false; ans.append("PrimitiveBoolean"); } + for(List r:fold()) { + if (!first) ans.append(", "); + first=false; + for(int i=0; i"); ans.append(r.get(i)); } + } + return ans.append('}').toString(); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/VisitQuery.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/VisitQuery.java new file mode 100644 index 00000000..555ca6df --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/VisitQuery.java @@ -0,0 +1,101 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; + +/** This abstract class implements a Query visitor that walks over an Expr and its subnodes. + *
As soon as one of the node returns a nonnull value,the nonnull value will be propagated to be the output of this visitor. + * + *

This default implementation will return null on all the leaf Expr nodes and thus the final answer will be null. + *
To implement a particular query, you need to extend this class. + */ + +public abstract class VisitQuery extends VisitReturn { + + /** Constructs a VisitQuery object. */ + public VisitQuery() { } + + /** Visits an ExprBinary node (A OP B) by calling accept() on A then B. */ + @Override public T visit(ExprBinary x) throws Err { + T ans=x.left.accept(this); + if (ans==null) ans=x.right.accept(this); + return ans; + } + + /** Visits an ExprList node F[X1,X2,X3..] by calling accept() on X1, X2, X3... */ + @Override public T visit(ExprList x) throws Err { + for(Expr y:x.args) { T ans=y.accept(this); if (ans!=null) return ans; } + return null; + } + + /** Visits an ExprCall node F[X1,X2,X3..] by calling accept() on X1, X2, X3... */ + @Override public T visit(ExprCall x) throws Err { + for(Expr y:x.args) { T ans=y.accept(this); if (ans!=null) return ans; } + return null; + } + + /** Visits an ExprConstant node (this default implementation simply returns null) */ + @Override public T visit(ExprConstant x) throws Err { + return null; + } + + /** Visits an ExprITE node (C => X else Y) by calling accept() on C, X, then Y. */ + @Override public T visit(ExprITE x) throws Err { + T ans = x.cond.accept(this); + if (ans==null) ans = x.left.accept(this); + if (ans==null) ans = x.right.accept(this); + return ans; + } + + /** Visits an ExprLet node (let a=x | y) by calling accept() on "a", "x", then "y". */ + @Override public T visit(ExprLet x) throws Err { + T ans = x.var.accept(this); + if (ans==null) ans = x.expr.accept(this); + if (ans==null) ans = x.sub.accept(this); + return ans; + } + + /** Visits an ExprQt node (all a,b,c:X1, d,e,f:X2... | F) by calling accept() on a,b,c,X1,d,e,f,X2... then on F. */ + @Override public T visit(ExprQt x) throws Err { + for(Decl d: x.decls) { + for(ExprHasName v: d.names) { T ans = v.accept(this); if (ans!=null) return ans; } + T ans = d.expr.accept(this); if (ans!=null) return ans; + } + return x.sub.accept(this); + } + + /** Visits an ExprUnary node (OP X) by calling accept() on X. */ + @Override public T visit(ExprUnary x) throws Err { + return x.sub.accept(this); + } + + /** Visits a ExprVar node (this default implementation simply returns null) */ + @Override public T visit(ExprVar x) throws Err { + return null; + } + + /** Visits a Sig node (this default implementation simply returns null) */ + @Override public T visit(Sig x) throws Err { + return null; + } + + /** Visits a Field node (this default implementation simply returns null) */ + @Override public T visit(Field x) throws Err { + return null; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/VisitReturn.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/VisitReturn.java new file mode 100644 index 00000000..8192484e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/ast/VisitReturn.java @@ -0,0 +1,72 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.ast; + +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; + +/** This abstract class defines what a Return Visitor's interface needs to be. */ + +public abstract class VisitReturn { + + /** Constructs a VisitReturn object. */ + public VisitReturn() { } + + /** This is the start method that begins a traversal over the given expression. */ + public final T visitThis(Expr x) throws Err { return x.accept(this); } + + /** Visits a ExprBad node */ + public T visit(ExprBad x) throws Err { throw x.errors.pick(); } + + /** Visits a ExprBadCall node */ + public T visit(ExprBadCall x) throws Err { throw x.errors.pick(); } + + /** Visits a ExprBadJoin node */ + public T visit(ExprBadJoin x) throws Err { throw x.errors.pick(); } + + /** Visits an ExprBinary node. */ + public abstract T visit(ExprBinary x) throws Err; + + /** Visits an ExprList node. */ + public abstract T visit(ExprList x) throws Err; + + /** Visits an ExprCall node. */ + public abstract T visit(ExprCall x) throws Err; + + /** Visits an ExprConstant node. */ + public abstract T visit(ExprConstant x) throws Err; + + /** Visits an ExprITE node. */ + public abstract T visit(ExprITE x) throws Err; + + /** Visits an ExprLet node. */ + public abstract T visit(ExprLet x) throws Err; + + /** Visits an ExprQt node. */ + public abstract T visit(ExprQt x) throws Err; + + /** Visits an ExprUnary node. */ + public abstract T visit(ExprUnary x) throws Err; + + /** Visits an ExprVar node. */ + public abstract T visit(ExprVar x) throws Err; + + /** Visits a Sig node. */ + public abstract T visit(Sig x) throws Err; + + /** Visits a Field node. */ + public abstract T visit(Field x) throws Err; +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/Alloy.cup b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/Alloy.cup new file mode 100644 index 00000000..1796efb0 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/Alloy.cup @@ -0,0 +1,1038 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2008, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Warning: this file alone is not enough to correctly parse Alloy4 since the actual + * language is not LALR(1); instead, we have to pre-process the token stream + * using CompFilter.java to rearrange/transform the token stream, and then we can + * parse the transformed token stream using this LALR(1) grammar. For more information, + * please refer to CompFilter.java + */ + +import java.util.Stack; +import java.util.List; +import java.util.ArrayList; +import java.util.TreeSet; +import java.util.Map; +import java.util.LinkedHashMap; +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.Reader; +import java.io.IOException; +import java.io.StringReader; +import java_cup.runtime.*; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.alloy4compiler.ast.Attr.AttrType; +import edu.mit.csail.sdg.alloy4compiler.ast.CommandScope; +import edu.mit.csail.sdg.alloy4compiler.ast.Decl; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprBadJoin; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprITE; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprLet; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprBinary; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprList; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprConstant; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprQt; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprUnary; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; + +//===========================================================================// + +parser code {: + + public CompModule alloymodule=null; + + @Override public Symbol parse() throws java.lang.Exception { + int act; // current action code + Symbol lhs_sym = null; // the Symbol/stack element returned by a reduce + short handle_size, lhs_sym_num; // information about production being reduced with + boolean logging = "yes".equals(System.getProperty("debug")); + production_tab = production_table(); + action_tab = action_table(); + reduce_tab = reduce_table(); + init_actions(); + user_init(); + // start + cur_token = scan(); + stack.removeAllElements(); + stack.push(getSymbolFactory().startSymbol("START", 0, start_state())); + tos = 0; + for (_done_parsing = false; !_done_parsing; ) { + act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym); + if (act > 0) { // "shift"; thus, we shift to the encoded state by pushing it on the stack + if (logging) System.out.println("shift " + cur_token.sym); + cur_token.parse_state = act-1; + stack.push(cur_token); + tos++; + cur_token = scan(); + } else if (act<0) { // "reduce" + if (logging) System.out.println("reduce " + ((-act)-1)); + lhs_sym = do_action((-act)-1, this, stack, tos); + lhs_sym_num = production_tab[(-act)-1][0]; + handle_size = production_tab[(-act)-1][1]; + for (int i = 0; i < handle_size; i++) { stack.pop(); tos--; } + act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num); + lhs_sym.parse_state = act; + stack.push(lhs_sym); + tos++; + } else { // "error" + if (logging) System.out.println("error"); + syntax_error(cur_token); + done_parsing(); + } + } + return lhs_sym; + } + + public void syntax_error(Symbol x) throws Err { + Map ch = new LinkedHashMap(); + ch.put(CompSym.ARROW, "->"); + ch.put(CompSym.ANY_ARROW_SOME, "->"); + ch.put(CompSym.ANY_ARROW_ONE, "->"); + ch.put(CompSym.ANY_ARROW_LONE, "->"); + ch.put(CompSym.SOME_ARROW_ANY, "some"); + ch.put(CompSym.SOME_ARROW_SOME, "some"); + ch.put(CompSym.SOME_ARROW_ONE, "some"); + ch.put(CompSym.SOME_ARROW_LONE, "some"); + ch.put(CompSym.ONE_ARROW_ANY, "one"); + ch.put(CompSym.ONE_ARROW_SOME, "one"); + ch.put(CompSym.ONE_ARROW_ONE, "one"); + ch.put(CompSym.ONE_ARROW_LONE, "one"); + ch.put(CompSym.LONE_ARROW_ANY, "lone"); + ch.put(CompSym.LONE_ARROW_SOME, "lone"); + ch.put(CompSym.LONE_ARROW_ONE, "lone"); + ch.put(CompSym.LONE_ARROW_LONE, "lone"); + ch.put(CompSym.INTADD, "fun"); + ch.put(CompSym.INTSUB, "fun"); + ch.put(CompSym.INTMUL, "fun"); + ch.put(CompSym.INTDIV, "fun"); + ch.put(CompSym.INTREM, "fun"); + ch.put(CompSym.INTMIN, "fun"); + ch.put(CompSym.INTMAX, "fun"); + ch.put(CompSym.INTNEXT, "fun"); + ch.put(CompSym.TOTALORDER, "pred"); + ch.put(CompSym.ABSTRACT, "abstract"); + ch.put(CompSym.ALL, "all"); + ch.put(CompSym.ALL2, "all"); + ch.put(CompSym.AMPERSAND, "&"); + ch.put(CompSym.AND, "&&"); + ch.put(CompSym.AS, "as"); + ch.put(CompSym.ASSERT, "assert"); + ch.put(CompSym.AT, "@"); + ch.put(CompSym.BAR, "|"); + ch.put(CompSym.BUT, "but"); + ch.put(CompSym.CARET, "^"); + ch.put(CompSym.CHECK, "check"); + ch.put(CompSym.COLON, ":"); + ch.put(CompSym.COMMA, ", "); + ch.put(CompSym.DISJ, "disj"); + ch.put(CompSym.DOMAIN, "<:"); + ch.put(CompSym.DOT, "."); + ch.put(CompSym.ELSE, "else"); + ch.put(CompSym.ENUM, "enum"); + ch.put(CompSym.EQUALS, "="); + ch.put(CompSym.EXACTLY, "exactly"); + ch.put(CompSym.EXH, "exh"); + ch.put(CompSym.EXPECT, "expect"); + ch.put(CompSym.EXTENDS, "extends"); + ch.put(CompSym.FACT, "fact"); + ch.put(CompSym.FOR, "for"); + ch.put(CompSym.FUN, "fun"); + ch.put(CompSym.GT, ">"); + ch.put(CompSym.GTE, ">="); + ch.put(CompSym.HASH, "#"); + ch.put(CompSym.IDEN, "iden"); + ch.put(CompSym.IFF, "iff"); + ch.put(CompSym.IMPLIES, "=>"); + ch.put(CompSym.IN, "in"); + ch.put(CompSym.INT, "int"); + ch.put(CompSym.LBRACE, "{"); + ch.put(CompSym.LBRACKET, "["); + ch.put(CompSym.LET, "let"); + ch.put(CompSym.LONE2, "lone"); + ch.put(CompSym.LONE, "lone"); + ch.put(CompSym.LPAREN, "("); + ch.put(CompSym.LT, "<"); + ch.put(CompSym.LTE, "<="); + ch.put(CompSym.MINUS, "-"); + ch.put(CompSym.MODULE, "module"); + ch.put(CompSym.NO2, "no"); + ch.put(CompSym.NO, "no"); + ch.put(CompSym.NONE, "none"); + ch.put(CompSym.NOT, "!"); + ch.put(CompSym.NOTEQUALS, "!"); + ch.put(CompSym.NOTGT, "!"); + ch.put(CompSym.NOTGTE, "!"); + ch.put(CompSym.NOTIN, "!"); + ch.put(CompSym.NOTLT, "!"); + ch.put(CompSym.NOTLTE, "!"); + ch.put(CompSym.ONE2, "one"); + ch.put(CompSym.ONE, "one"); + ch.put(CompSym.OPEN, "open"); + ch.put(CompSym.OR, "||"); + ch.put(CompSym.PART, "part"); + ch.put(CompSym.PLUS, "+"); + ch.put(CompSym.PLUSPLUS, "++"); + ch.put(CompSym.PRED, "pred"); + ch.put(CompSym.PRIVATE, "private"); + ch.put(CompSym.RANGE, ":>"); + ch.put(CompSym.RBRACE, "}"); + ch.put(CompSym.RBRACKET, "]"); + ch.put(CompSym.RPAREN, ")"); + ch.put(CompSym.RUN, "run"); + ch.put(CompSym.SEQ, "seq"); + ch.put(CompSym.SET, "set"); + ch.put(CompSym.SHL, "<<"); + ch.put(CompSym.SHR, ">>>"); + ch.put(CompSym.SHA, ">>"); + ch.put(CompSym.SIG, "sig"); + ch.put(CompSym.SIGINT, "Int"); + ch.put(CompSym.SLASH, "/"); + ch.put(CompSym.SOME2, "some"); + ch.put(CompSym.SOME, "some"); + ch.put(CompSym.STAR, "*"); + ch.put(CompSym.STRING, "String"); + ch.put(CompSym.SUM2, "sum"); + ch.put(CompSym.SUM, "sum"); + ch.put(CompSym.THIS, "this"); + ch.put(CompSym.TILDE, "~"); + ch.put(CompSym.UNIV, "univ"); + ch.put(CompSym.ID, "NAME"); + ch.put(CompSym.NUMBER, "NUMBER"); + ch.put(CompSym.STR, "STRING"); + TreeSet list = new TreeSet(); + Pos p=Pos.UNKNOWN; + if (x!=null && x.value instanceof Pos) p=(Pos)(x.value); + else if (x!=null && x.value instanceof Expr) p=((Expr)(x.value)).pos; + else if (x!=null) p=x.pos; + if (!stack.empty()) for(Map.Entry e:ch.entrySet()) { + int key=e.getKey(), act=get_action(((Symbol)stack.peek()).parse_state, key); + if (act==0) continue; + try { + if (act>0 || alloy_confirm(key)) list.add(e.getValue()); + } catch(Throwable ex) { + // If the parser is really really confused, alloy_confirm() could fail with array out-of-bound exception, etc. + } + } + String result="There are "+list.size()+" possible tokens that can appear here:\n"; + for(String item:list) result=result+item+" "; + throw new ErrorSyntax(p, (list.size()!=0)?result:""); + } + + private boolean alloy_confirm(int key) { + int state = ((Symbol)stack.peek()).parse_state; + Stack newstack=new Stack(); for(Object x:stack) newstack.push(x); + while(true) { + int act = get_action(state, key); + if (act>0) return true; + if (act==0) return false; + int lhs_sym_num = production_tab[(-act)-1][0]; + int handle_size = production_tab[(-act)-1][1]; + for (int i = 0; i < handle_size; i++) { if (newstack.empty()) return false; newstack.pop(); } + if (newstack.empty()) return false; + if (newstack.peek() instanceof Symbol) state=((Symbol)newstack.peek()).parse_state; + state=get_reduce(state, lhs_sym_num); + newstack.push(null); + } + } + + static CompModule alloy_parseStream (List seenDollar, + Map loaded, Map fc, CompModule root, + int lineOffset, String filename, String prefix, int initialResolutionMode) throws Err, FileNotFoundException, IOException { + Reader isr=null; + try { + if (root==null && prefix.length()!=0) throw new ErrorFatal("Internal error (parse subfile with root==null)"); + if (root!=null && prefix.length()==0) throw new ErrorFatal("Internal error (parse topfile with root!=null)"); + CompModule u = new CompModule(root, filename, prefix); + if (root == null) + u.addOpen(null, null, ExprVar.make(null, "util/integer"), null, ExprVar.make(null, "integer")); + u.resolution = initialResolutionMode; + String content = fc!=null ? fc.get(filename) : null; + if (content==null && loaded!=null) content = loaded.get(filename); + if (content==null) content = Util.readAll(filename); + if (loaded!=null) loaded.put(filename,content); + content = Util.convertLineBreak(content); + isr = new StringReader(content); + CompFilter s = new CompFilter(u, seenDollar, filename, lineOffset, new BufferedReader(isr)); + CompParser p = new CompParser(s); + p.alloymodule=u; + try {p.parse();} catch(Throwable ex) {if (ex instanceof Err) throw (Err)ex; throw new ErrorFatal("Parser Exception", ex);} + // if no sigs are defined by the user, add one + if (root == null && u.getAllSigs().isEmpty()) { + u.addGhostSig(); + } + return u; + } finally { + Util.close(isr); + } + } + +:}; + +action code {: + /** This function is needed to handle a difficult parsing ambiguity. + * + *

+ * "some EXPR", "one EXPR", and "lone EXPR" + * can be either formulas (saying the EXPR has at least 1, exactly 1, or at most 1 tuple), + * or multiplicity constraints (saying something else has this multiplicity). + * + *

+ * So we let the parser generate the former by default. + * And whenever we construct a Decl "x: y" object, + * or an binary expression "x in y", or a function return type, + * we call this method on y to convert it into a multiplicity constraint. + * + *

+ * This is safe, because in all 3 cases, a formula would be illegal. + * So the first form is always wrong. + * + *

+ * And this is sufficient, because those are the only 3 places + * where a mulitplicity constraint is allowed to appear. + * + * @return a newly formed multiplciity constraint (if this.op==SOME or LONE or ONE), + * otherwise it just returns the original node. + */ + private Expr mult(Expr x) throws Err { + if (x instanceof ExprUnary) { + ExprUnary y=(ExprUnary)x; + if (y.op==ExprUnary.Op.SOME) return ExprUnary.Op.SOMEOF.make(y.pos, y.sub); + if (y.op==ExprUnary.Op.LONE) return ExprUnary.Op.LONEOF.make(y.pos, y.sub); + if (y.op==ExprUnary.Op.ONE) return ExprUnary.Op.ONEOF.make(y.pos, y.sub); + } + return x; + } + private void nod(ExprVar name) throws Err { + if (name.label.indexOf('$')>=0) throw new ErrorSyntax(name.pos, "The name cannot contain the '$' symbol."); + } + private void nod(List names) throws Err { + if (names!=null) for(ExprVar n:names) if (n!=null && n.label.indexOf('$')>=0) throw new ErrorSyntax(n.pos, "The name cannot contain the '$' symbol."); + } + private void c(boolean follow, ExprVar o, ExprVar x, ExprVar n, Expr e, List s, ExprConstant c) throws Err { + if (n!=null) nod(n); + int bitwidth=(-1), maxseq=(-1), overall=(-1), expects=(c==null ? -1 : c.num); + Pos p = o.pos.merge(n!=null ? n.span() : e.span()); + for(int i=s.size()-1; i>=0; i--) { + Sig j=s.get(i).sig; int k=s.get(i).startingScope; + p=p.merge(j.pos); + if (j.label.equals("univ")) { overall=k; s.remove(i); continue; } + if (j.label.equals("int")) { if (bitwidth>=0) throw new ErrorSyntax(j.pos, "The bitwidth cannot be specified more than once."); bitwidth=k; s.remove(i); continue; } + if (j.label.equals("seq")) { if (maxseq>=0) throw new ErrorSyntax(j.pos, "The maximum sequence length cannot be specified more than once."); maxseq=k; s.remove(i); continue; } + } + if (n!=null) + parser.alloymodule.addCommand(follow, p, n.label, o.label.equals("c"), overall, bitwidth, maxseq, expects, s, x); + else + parser.alloymodule.addCommand(follow, p, e, o.label.equals("c"), overall, bitwidth, maxseq, expects, s, x); + } + private Expr t(Pos pos, Pos oldClosing, Expr left, Expr right, Pos close) throws Err { + if (right instanceof ExprVar) { + String n = ((ExprVar)right).label; + if (n.equals("int")) return ExprUnary.Op.CAST2INT.make(pos, left); + if (n.equals("disj")) return ExprList.makeDISJOINT(pos, close, Util.asList(left)); + if (n.equals("pred/totalOrder")) return ExprList.makeTOTALORDER(pos, close, Util.asList(left)); + } + else if (right instanceof ExprList) { + return ((ExprList)right).addArg(left); + } + return ExprBadJoin.make(pos, oldClosing, left, right); + } +:}; + +//===========================================================================// + +terminal Pos ARROW; // -> +terminal Pos ANY_ARROW_SOME; // ->some // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos ANY_ARROW_ONE; // ->one // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos ANY_ARROW_LONE; // ->lone // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos SOME_ARROW_ANY; // some-> // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos SOME_ARROW_SOME; // some->some // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos SOME_ARROW_ONE; // some->one // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos SOME_ARROW_LONE; // some->lone // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos ONE_ARROW_ANY; // one-> // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos ONE_ARROW_SOME; // one->some // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos ONE_ARROW_ONE; // one->one // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos ONE_ARROW_LONE; // one->lone // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos LONE_ARROW_ANY; // lone->any // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos LONE_ARROW_SOME; // lone->some // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos LONE_ARROW_ONE; // lone->one // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos LONE_ARROW_LONE; // lone->lone // The filter allows whitespace/comment in these 15 "*->*" tokens + +terminal Pos INTADD; +terminal Pos INTSUB; +terminal Pos INTMUL; +terminal Pos INTDIV; +terminal Pos INTREM; +terminal Pos INTMIN; +terminal Pos INTMAX; +terminal Pos INTNEXT; +terminal Pos TOTALORDER; + +terminal Pos ABSTRACT; // abstract +terminal Pos ALL; // all // The filter enables us to disambiguate +terminal Pos ALL2; // all // The filter enables us to disambiguate +terminal Pos AMPERSAND; // & +terminal Pos AND; // && and +terminal Pos AS; // as +terminal Pos ASSERT; // assert +terminal Pos AT; // @ +terminal Pos BAR; // | +terminal Pos BUT; // but +terminal Pos CARET; // ^ +terminal Pos CHECK; // check +terminal Pos COLON; // : +terminal Pos COMMA; // , +terminal Pos DISJ; // disj disjoint +terminal Pos DOMAIN; // <: +terminal Pos DOT; // . +terminal Pos ELSE; // else +terminal Pos ENUM; // enum +terminal Pos EQUALS; // = == +terminal Pos EXACTLY; // exactly +terminal Pos EXH; // exh exhaustive +terminal Pos EXPECT; // expect +terminal Pos EXTENDS; // extends +terminal Pos FACT; // fact +terminal Pos FOR; // for +terminal Pos FUN; // fun +terminal Pos GT; // > +terminal Pos GTE; // >= +terminal Pos HASH; // # +terminal Pos IDEN; // iden +terminal Pos IFF; // <=> iff +terminal Pos IMPLIES; // => implies +terminal Pos IN; // in +terminal Pos INT; // int +terminal Pos LBRACE; // { +terminal Pos LBRACKET; // [ +terminal Pos LET; // let +terminal Pos LONE2; // lone // The filter enables us to disambiguate +terminal Pos LONE; // lone // The filter enables us to disambiguate +terminal Pos LPAREN; // ( +terminal Pos LT; // < +terminal Pos LTE; // <= =< +terminal Pos MINUS; // - +terminal Pos MODULE; // module +terminal Pos NO2; // no // The filter enables us to disambiguate +terminal Pos NO; // no // The filter enables us to disambiguate +terminal Pos NONE; // none +terminal Pos NOT; // ! not +terminal Pos NOTEQUALS; // != not= // The filter allows whitespace/comment in between +terminal Pos NOTGT; // !> not> // The filter allows whitespace/comment in between +terminal Pos NOTGTE; // !>= not>= // The filter allows whitespace/comment in between +terminal Pos NOTIN; // !in notin // The filter allows whitespace/comment in between +terminal Pos NOTLT; // !< not< // The filter allows whitespace/comment in between +terminal Pos NOTLTE; // !=< not=< // The filter allows whitespace/comment in between +terminal Pos ONE2; // one // The filter enables us to disambiguate +terminal Pos ONE; // one // The filter enables us to disambiguate +terminal Pos OPEN; // open +terminal Pos OR; // || or +terminal Pos PART; // part partition +terminal Pos PLUS; // + +terminal Pos PLUSPLUS; // ++ +terminal Pos PRED; // pred +terminal Pos PRIVATE; // private +terminal Pos RANGE; // :> +terminal Pos RBRACE; // } +terminal Pos RBRACKET; // ] +terminal Pos RPAREN; // ) +terminal Pos RUN; // run +terminal Pos SEQ; // seq +terminal Pos SET; // set +terminal Pos SHL; // << +terminal Pos SHR; // >>> +terminal Pos SHA; // >> +terminal Pos SIG; // sig +terminal Pos SIGINT; // Int +terminal Pos SLASH; // / +terminal Pos SOME2; // some // The filter enables us to disambiguate +terminal Pos SOME; // some // The filter enables us to disambiguate +terminal Pos STAR; // * +terminal Pos STRING; // String +terminal Pos SUM2; // sum // The filter enables us to disambiguate +terminal Pos SUM; // sum // The filter enables us to disambiguate +terminal Pos THIS; // this +terminal Pos TILDE; // ~ +terminal Pos UNIV; // univ + +terminal ExprVar ID; + +terminal ExprConstant NUMBER, STR; + +//===========================================================================// + +nonterminal Expr AndExprA; +nonterminal Expr AndExprB; +nonterminal Expr BaseExpr; +nonterminal Expr Bind; +nonterminal Expr BracketExprA; +nonterminal Expr BracketExprB; +nonterminal Expr CompareExprA; +nonterminal Expr CompareExprB; +nonterminal Command; +nonterminal ExprVar CommandPrefix; +nonterminal Decl Decla; +nonterminal Decl Declb; +nonterminal List Declp; +nonterminal List Decls; +nonterminal List Declz; +nonterminal Expr DomainExprA; +nonterminal Expr DomainExprB; +nonterminal Expr DotExprA; +nonterminal Expr DotExprB; +nonterminal Expr EquivExprA; +nonterminal Expr EquivExprB; +nonterminal ExprConstant Expects; +nonterminal Expr Expr; +nonterminal Expr Super; +nonterminal Expr SuperOpt; +nonterminal Expr SuperP; +nonterminal Expr SuperOrBar; +nonterminal List Exprs; +nonterminal List Exprp; +nonterminal Function; +nonterminal Expr ImpliesExprA; +nonterminal Expr ImpliesExprB; +nonterminal Expr ImpliesExprCloseA; +nonterminal Expr ImpliesExprCloseB; +nonterminal Expr ImpliesExprOpenA; +nonterminal Expr ImpliesExprOpenB; +nonterminal Expr IntersectExprA; +nonterminal Expr IntersectExprB; +nonterminal Expr Let; +nonterminal Macro; +nonterminal Expr MacroBody; +nonterminal ExprVar Name; +nonterminal ExprVar NameHelper; +nonterminal List Names; +nonterminal List Namex; +nonterminal Expr NegExprA; +nonterminal Expr NegExprB; +nonterminal Expr NumUnopExprA; +nonterminal Expr NumUnopExprB; +nonterminal Expr OrExprA; +nonterminal Expr OrExprB; +nonterminal Expr OverrideExprA; +nonterminal Expr OverrideExprB; +nonterminal Predicate; +nonterminal Expr RangeExprA; +nonterminal Expr RangeExprB; +nonterminal Pair RelOp; +nonterminal Expr RelationExprA; +nonterminal Expr RelationExprB; +nonterminal List Scope; +nonterminal Sig; +nonterminal List SigIn; +nonterminal List SigQual; +nonterminal List SigQuals; +nonterminal ExprVar SigRef; +nonterminal List SigRefp; +nonterminal List SigRefs; +nonterminal List SigRefu; +nonterminal File; +nonterminal Spec; +nonterminal CommandScope TypeNumber; +nonterminal CommandScope Typescope; +nonterminal List Typescopes; +nonterminal Expr ShiftExprA; +nonterminal Expr ShiftExprB; +nonterminal Expr MulExprA; +nonterminal Expr MulExprB; +nonterminal Expr UnionDiffExprA; +nonterminal Expr UnionDiffExprB; +nonterminal Expr UnopExprA; +nonterminal Expr UnopExprB; +nonterminal Pos Vis; + +//===========================================================================// + +File ::= Spec {: parser.alloymodule.doneParsing(); :}; + +Spec ::= Spec MODULE:o Name:n {: nod(n); parser.alloymodule.addModelName(o.merge(n.pos) , n.label , new ArrayList()); :}; +Spec ::= Spec MODULE:o Name:n LBRACKET Namex:b RBRACKET:r {: nod(n); nod(b); parser.alloymodule.addModelName(o.merge(r) , n.label , b ); :}; +Spec ::= Spec Vis:p OPEN:o Name:a {: nod(a); parser.alloymodule.addOpen(o.merge(a.pos), p, a, null, null); :}; +Spec ::= Spec Vis:p OPEN:o Name:a AS Name:c {: nod(a); nod(c); parser.alloymodule.addOpen(o.merge(c.pos), p, a, null, c); :}; +Spec ::= Spec Vis:p OPEN:o Name:a LBRACKET SigRefs:b RBRACKET:c {: nod(a); parser.alloymodule.addOpen(o.merge(c), p, a, b, null); :}; +Spec ::= Spec Vis:p OPEN:o Name:a LBRACKET SigRefs:b RBRACKET AS Name:c {: nod(a); nod(c); parser.alloymodule.addOpen(o.merge(c.pos), p, a, b, c); :}; +Spec ::= Spec Vis:p ENUM:o Name:a LBRACE Names:n RBRACE:c {: nod(a); parser.alloymodule.addEnum(o.merge(c), p, a, n, c); :}; +Spec ::= Spec Vis:p ENUM:o Name:a LBRACE RBRACE:c {: nod(a); parser.alloymodule.addEnum(o.merge(c), p, a, null, c); :}; +Spec ::= Spec FACT:o Super:e {: parser.alloymodule.addFact (o , "" , e); :}; +Spec ::= Spec FACT:o Name:n Super:e {: nod(n); parser.alloymodule.addFact (o , n.label , e); :}; +Spec ::= Spec FACT:o STR:n Super:e {: parser.alloymodule.addFact (o , n.string , e); :}; +Spec ::= Spec ASSERT:o Super:e {: parser.alloymodule.addAssertion (o , "" , e); :}; +Spec ::= Spec ASSERT:o Name:n Super:e {: nod(n); parser.alloymodule.addAssertion (o , n.label , e); :}; +Spec ::= Spec ASSERT:o STR:n Super:e {: parser.alloymodule.addAssertion (o , n.string , e); :}; +Spec ::= Spec Sig ; +Spec ::= Spec Function ; +Spec ::= Spec Predicate ; +Spec ::= Spec Macro ; +Spec ::= Spec Command ; +Spec ::= ; + +CommandPrefix ::= CHECK:c {: RESULT = ExprVar.make(c, "c"); :}; +CommandPrefix ::= RUN:r {: RESULT = ExprVar.make(r, "r"); :}; + +Command ::= CommandPrefix:o Name:x Super:e Scope:s Expects:c {: c(false,o,x ,null,e ,s,c); :}; +Command ::= CommandPrefix:o Super:e Scope:s Expects:c {: c(false,o,null,null,e ,s,c); :}; +Command ::= Command IMPLIES CommandPrefix:o Name:x Super:e Scope:s Expects:c {: c(true ,o,x ,null,e ,s,c); :}; +Command ::= Command IMPLIES CommandPrefix:o Super:e Scope:s Expects:c {: c(true ,o,null,null,e ,s,c); :}; +Command ::= CommandPrefix:o Name:x Name:n Scope:s Expects:c {: c(false,o,x ,n ,null,s,c); :}; +Command ::= CommandPrefix:o Name:n Scope:s Expects:c {: c(false,o,null,n ,null,s,c); :}; +Command ::= Command IMPLIES CommandPrefix:o Name:x Name:n Scope:s Expects:c {: c(true ,o,x ,n ,null,s,c); :}; +Command ::= Command IMPLIES CommandPrefix:o Name:n Scope:s Expects:c {: c(true ,o,null,n ,null,s,c); :}; + +Expects ::= {: RESULT=null; :}; +Expects ::= EXPECT NUMBER:a {: RESULT=a; :}; + +Scope ::= FOR NUMBER:a {: RESULT=new ArrayList(); RESULT.add(new CommandScope(a.pos, new PrimSig("univ", AttrType.WHERE.make(a.pos)), true, a.num, a.num, 1)); :}; +Scope ::= FOR NUMBER:a BUT Typescopes:b {: RESULT=b; b.add(new CommandScope(a.pos, new PrimSig("univ", AttrType.WHERE.make(a.pos)), true, a.num, a.num, 1)); :}; +Scope ::= FOR Typescopes:b {: RESULT=b; :}; +Scope ::= {: RESULT=new ArrayList(); :}; + +Typescopes ::= Typescope:a {: RESULT=new ArrayList(); RESULT.add(a); :}; +Typescopes ::= Typescopes:a COMMA Typescope:b {: RESULT=a; a.add(b); :}; + +Typescope ::= TypeNumber:a Name:b {: + nod(b); + RESULT = new CommandScope(a.pos.merge(b.pos), new PrimSig(b.label, AttrType.WHERE.make(a.pos.merge(b.pos))), a.isExact, a.startingScope, a.endingScope, a.increment); +:}; + +//[AM]: INT -> SIGINT +Typescope ::= TypeNumber:a SIGINT:b {: + Pos p = a.pos.merge(b); + if (a.endingScope>a.startingScope) throw new ErrorSyntax(p, "Cannot specify a growing scope for \"Int\""); + if (a.isExact) throw new ErrorSyntax(p, "The exactly keyword is redundant here since the integer bitwidth must be exact."); + RESULT = new CommandScope(p, new PrimSig("int", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.startingScope, 1); +:}; + +Typescope ::= TypeNumber:a INT:b {: + Pos p = a.pos.merge(b); + if (a.endingScope>a.startingScope) throw new ErrorSyntax(p, "Cannot specify a growing scope for \"Int\""); + if (a.isExact) throw new ErrorSyntax(p, "The exactly keyword is redundant here since the integer bitwidth must be exact."); + RESULT = new CommandScope(p, new PrimSig("int", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.startingScope, 1); +:}; + +Typescope ::= TypeNumber:a SEQ:b {: + Pos p = a.pos.merge(b); + if (a.endingScope>a.startingScope) throw new ErrorSyntax(p, "Cannot specify a growing scope for \"seq\""); + if (a.isExact) throw new ErrorSyntax(p, "The exactly keyword is redundant here since the number of sequence index has to be exact."); + RESULT = new CommandScope(p, new PrimSig("seq", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.startingScope, 1); +:}; + +Typescope ::= TypeNumber:e UNIV:f {: if (1==1) throw new ErrorSyntax(e.pos.merge(f), "You cannot set a scope on univ."); :}; + +Typescope ::= TypeNumber:a STRING:b {: RESULT = new CommandScope(a.pos.merge(b), new PrimSig("String", AttrType.WHERE.make(a.pos.merge(b))), a.isExact, a.startingScope, a.endingScope, a.increment); :}; + +//[AM] Typescope ::= TypeNumber:e SIGINT:f {: if (1==1) throw new ErrorSyntax(e.pos.merge(f), "You can no longer set a scope on Int; the number of Int atoms is always exactly equal to 2^(integer bitwidth).\n"); :}; + +Typescope ::= TypeNumber:e NONE:f {: if (1==1) throw new ErrorSyntax(e.pos.merge(f), "You cannot set a scope on none."); :}; + +TypeNumber ::= EXACTLY:e NUMBER:a {: RESULT = new CommandScope( e.merge(a.pos), Sig.NONE, true, a.num, a.num, 1 ); :}; +TypeNumber ::= EXACTLY:e NUMBER:a DOT DOT NUMBER:b {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e.merge(b.pos), Sig.NONE, true, a.num, b.num, 1 ); :}; +TypeNumber ::= EXACTLY:e NUMBER:a DOT DOT NUMBER:b COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e.merge(i.pos), Sig.NONE, true, a.num, b.num, i.num); :}; +TypeNumber ::= EXACTLY:e NUMBER:a COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e.merge(i.pos), Sig.NONE, true, a.num, Integer.MAX_VALUE, i.num); :}; +TypeNumber ::= NUMBER:a {: RESULT = new CommandScope(a.pos , Sig.NONE, false, a.num, a.num, 1 ); :}; +TypeNumber ::= NUMBER:a DOT DOT NUMBER:b {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos.merge(b.pos), Sig.NONE, false, a.num, b.num, 1 ); :}; +TypeNumber ::= NUMBER:a DOT DOT NUMBER:b COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos.merge(i.pos), Sig.NONE, false, a.num, b.num, i.num); :}; +TypeNumber ::= NUMBER:a COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos.merge(i.pos), Sig.NONE, false, a.num, Integer.MAX_VALUE, i.num); :}; + +Macro ::= Vis:p LET:o Name:n LPAREN Names:d RPAREN MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, d , v); :}; +Macro ::= Vis:p LET:o Name:n LPAREN RPAREN MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, null , v); :}; +Macro ::= Vis:p LET:o Name:n LBRACKET Names:d RBRACKET MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, d , v); :}; +Macro ::= Vis:p LET:o Name:n LBRACKET RBRACKET MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, null , v); :}; +Macro ::= Vis:p LET:o Name:n MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, null , v); :}; + +MacroBody ::= Super:a {: RESULT=a; :}; +MacroBody ::= EQUALS Expr:a {: RESULT=a; :}; + +Function ::= Vis:p FUN:o Name:n LPAREN Decls:d RPAREN COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, d , mult(r), v); :}; +Function ::= Vis:p FUN:o Name:n LBRACKET Decls:d RBRACKET COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, d , mult(r), v); :}; +Function ::= Vis:p FUN:o Name:n COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, null , mult(r), v); :}; +Function ::= Vis:p FUN:o SigRef:f DOT Name:n LPAREN Decls:d RPAREN COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , d , mult(r), v); :}; +Function ::= Vis:p FUN:o SigRef:f DOT Name:n LBRACKET Decls:d RBRACKET COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , d , mult(r), v); :}; +Function ::= Vis:p FUN:o SigRef:f DOT Name:n COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , null , mult(r), v); :}; + +Predicate ::= Vis:p PRED:o Name:n LPAREN Decls:d RPAREN Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, d , null, v); :}; +Predicate ::= Vis:p PRED:o Name:n LBRACKET Decls:d RBRACKET Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, d , null, v); :}; +Predicate ::= Vis:p PRED:o Name:n Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, null , null, v); :}; +Predicate ::= Vis:p PRED:o SigRef:f DOT Name:n LPAREN Decls:d RPAREN Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , d , null, v); :}; +Predicate ::= Vis:p PRED:o SigRef:f DOT Name:n LBRACKET Decls:d RBRACKET Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , d , null, v); :}; +Predicate ::= Vis:p PRED:o SigRef:f DOT Name:n Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , null , null, v); :}; + +Vis ::= {: RESULT=null; :}; +Vis ::= PRIVATE:p {: RESULT=p; :}; + +Sig ::= SigQuals:a Names:b SigIn:c LBRACE Decls:d RBRACE:o SuperOpt:e + {: + if (e==null) e = ExprConstant.Op.TRUE.make(o, 0); + ExprVar cc = (c!=null && c.size()>0) ? c.remove(c.size()-1) : null; + for(ExprVar bb:b) { + parser.alloymodule.addSig(bb.label, cc, c, d, e, + AttrType.WHERE .makenull(bb.pos.merge(e==null ? o : e.span())), + AttrType.ABSTRACT.makenull(a.get(0)), + AttrType.LONE .makenull(a.get(1)), + AttrType.ONE .makenull(a.get(2)), + AttrType.SOME .makenull(a.get(3)), + AttrType.PRIVATE .makenull(a.get(4))); + } + :}; + +SigQual ::= ABSTRACT:x {: RESULT=new ArrayList(5); RESULT.add(x); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); :}; +SigQual ::= LONE:x {: RESULT=new ArrayList(5); RESULT.add(null); RESULT.add(x); RESULT.add(null); RESULT.add(null); RESULT.add(null); :}; +SigQual ::= ONE:x {: RESULT=new ArrayList(5); RESULT.add(null); RESULT.add(null); RESULT.add(x); RESULT.add(null); RESULT.add(null); :}; +SigQual ::= SOME:x {: RESULT=new ArrayList(5); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(x); RESULT.add(null); :}; +SigQual ::= PRIVATE:x {: RESULT=new ArrayList(5); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(x); :}; + +SigQuals ::= SIG {: RESULT=new ArrayList(5); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); :}; +SigQuals ::= SigQual:a SigQuals:b {: RESULT=a; for(int i=0;i<5;i++) if (a.get(i)==null) a.set(i,b.get(i)); else if (b.get(i)!=null) throw new ErrorSyntax(b.get(i), "The same qualifer cannot be specified more than once for the same sig."); :}; + +SigIn ::= EXTENDS:a SigRef:x {: RESULT=new ArrayList(2); RESULT.add(x); RESULT.add(ExprVar.make(a, "extends")); :}; +SigIn ::= IN:a SigRefu:x {: RESULT=x; x.add(ExprVar.make(a,"in")); :}; +SigIn ::= EQUALS:a SigRefu:x {: RESULT=x; x.add(ExprVar.make(a,"=")); :}; +SigIn ::= {: RESULT=null; :}; + +SigRef ::= Name:x {: RESULT=x; :}; +SigRef ::= UNIV:x {: RESULT=ExprVar.make(x, "univ"); :}; +SigRef ::= STRING:x {: RESULT=ExprVar.make(x, "String"); :}; +SigRef ::= SIGINT:x {: RESULT=ExprVar.make(x, "Int"); :}; +SigRef ::= SEQ:a SLASH SIGINT:b {: RESULT=ExprVar.make(a.merge(b), "seq/Int"); :}; +SigRef ::= NONE:x {: RESULT=ExprVar.make(x, "none"); :}; + +SigRefs ::= {: RESULT=new ArrayList(); :}; +SigRefs ::= SigRefp:x {: RESULT=x; :}; + +SigRefp ::= SigRef:x {: RESULT=new ArrayList(); RESULT.add(x); :}; +SigRefp ::= SigRefp:a COMMA SigRef:b {: a.add(b); RESULT=a; :}; + +SigRefu ::= SigRef:x {: RESULT=new ArrayList(); RESULT.add(x); :}; +SigRefu ::= SigRefu:a PLUS SigRef:b {: a.add(b); RESULT=a; :}; + +Name ::= NameHelper:x {: RESULT=x; :}; +Name ::= THIS:a SLASH NameHelper:b {: RESULT=ExprVar.make(a.merge(b.pos), "this/"+b.label); :}; +Name ::= SEQ:a SLASH NameHelper:b {: RESULT=ExprVar.make(a.merge(b.pos), "seq/"+b.label); :}; + +NameHelper ::= ID:x {: RESULT=x; :}; +NameHelper ::= NameHelper:a SLASH ID:b {: RESULT=ExprVar.make(a.pos.merge(b.pos), a.label+"/"+b.label); :}; + +Names ::= Name:x {: nod(x); RESULT=new ArrayList(); RESULT.add(x); :}; +Names ::= Names:a COMMA Name:b {: nod(b); a.add(b); RESULT=a; :}; + +Namex ::= Name:x {: nod(x); RESULT=new ArrayList(); RESULT.add(x); :}; +Namex ::= EXACTLY Name:x {: nod(x); RESULT=new ArrayList(); RESULT.add(null); RESULT.add(x); :}; +Namex ::= Namex:a COMMA Name:b {: nod(b); a.add(b); RESULT=a; :}; +Namex ::= Namex:a COMMA EXACTLY Name:b {: nod(b); a.add(null); a.add(b); RESULT=a; :}; + +Decla ::= PART:k Names COLON Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; +Decla ::= EXH:k Names COLON Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; +Decla ::= DISJ:k Names:a COLON Expr:b {: RESULT=new Decl(null, k, null, a, mult(b)); :}; +Decla ::= PRIVATE:p DISJ:k Names:a COLON Expr:b {: RESULT=new Decl(p, k, null, a, mult(b)); :}; +Decla ::= PRIVATE:p Names:a COLON Expr:b {: RESULT=new Decl(p, null, null, a, mult(b)); :}; +Decla ::= Names:a COLON Expr:b {: RESULT=new Decl(null, null, null, a, mult(b)); :}; + +Decla ::= PART:k Names COLON DISJ Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; +Decla ::= EXH:k Names COLON DISJ Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; +Decla ::= DISJ:k Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(null, k, d, a, mult(b)); :}; +Decla ::= PRIVATE:p DISJ:k Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(p, k, d, a, mult(b)); :}; +Decla ::= PRIVATE:p Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(p, null, d, a, mult(b)); :}; +Decla ::= Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(null, null, d, a, mult(b)); :}; + +Declb ::= Decla:x {: RESULT=x; :}; + +Declb ::= PART:k Names EQUALS Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; +Declb ::= EXH:k Names EQUALS Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; +Declb ::= DISJ:d Names EQUALS Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; +Declb ::= PRIVATE DISJ:d Names EQUALS Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; +Declb ::= PRIVATE:p Names:a EQUALS Expr:b {: RESULT=new Decl(p, null, null, a, ExprUnary.Op.EXACTLYOF.make(null, b)); :}; +Declb ::= Names:a EQUALS Expr:b {: RESULT=new Decl(null, null, null, a, ExprUnary.Op.EXACTLYOF.make(null, b)); :}; + +Declb ::= PART:k Names EQUALS DISJ Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; +Declb ::= EXH:k Names EQUALS DISJ Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; +Declb ::= DISJ Names EQUALS DISJ:d Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; +Declb ::= PRIVATE DISJ Names EQUALS DISJ:d Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; +Declb ::= PRIVATE Names EQUALS DISJ:d Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; +Declb ::= Names EQUALS DISJ:d Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; + +Declz ::= Declz:x COMMA Decla:y {: RESULT=x; RESULT.add(y); :}; +Declz ::= Decla:y {: RESULT=new ArrayList(); RESULT.add(y); :}; + +Declp ::= Declp:x COMMA Declb:y {: RESULT=x; RESULT.add(y); :}; +Declp ::= Declb:y {: RESULT=new ArrayList(); RESULT.add(y); :}; + +Decls ::= {: RESULT=new ArrayList(); :}; +Decls ::= Declb:x {: RESULT=new ArrayList(); RESULT.add(x); :}; +Decls ::= Declb:x COMMA Decls:y {: RESULT=y; RESULT.add(0,x); :}; +Decls ::= COMMA Decls:y {: RESULT=y; :}; + +Let ::= Name:a EQUALS:o Expr:b SuperOrBar:x {: + nod(a); + if (a.label.indexOf('/')>=0) throw new ErrorSyntax(a.pos, "Let variable name cannot contain \'/\'"); + if (a.label.indexOf('@')>=0) throw new ErrorSyntax(a.pos, "Let variable name cannot contain \'@\'"); + RESULT = ExprLet.make(o, ExprVar.make(a.pos, a.label), b, x); +:}; + +Let ::= Name:a EQUALS:o Expr:b COMMA Let:x {: + nod(a); + if (a.label.indexOf('/')>=0) throw new ErrorSyntax(a.pos, "Let variable name cannot contain \'/\'"); + if (a.label.indexOf('@')>=0) throw new ErrorSyntax(a.pos, "Let variable name cannot contain \'@\'"); + RESULT = ExprLet.make(o, ExprVar.make(a.pos, a.label), b, x); +:}; + +SuperOpt ::= {: RESULT=null; :}; +SuperOpt ::= Super:x {: RESULT=x; :}; +Super ::= LBRACE:a SuperP:x RBRACE:b {: RESULT=ExprUnary.Op.NOOP.make(a.merge(b), x); :}; +Super ::= LBRACE:a RBRACE:b {: RESULT=ExprConstant.Op.TRUE.make(a.merge(b), 0); :}; +SuperP ::= Expr:a {: RESULT=a; :}; +SuperP ::= SuperP:a Expr:b {: RESULT=ExprBinary.Op.AND.make(null, null, a, b); :}; + +SuperOrBar ::= BAR Expr:x {: RESULT=x; :}; +SuperOrBar ::= Super:x {: RESULT=x; :}; + +Exprs ::= {: RESULT=new ArrayList(); :}; +Exprs ::= Exprp:x {: RESULT=x; :}; +Exprp ::= Expr:x {: RESULT=new ArrayList(); RESULT.add(x); :}; +Exprp ::= Exprp:a COMMA Expr:b {: a.add(b); RESULT=a; :}; + +//============================================================================= + +Expr ::= OrExprA:x {: RESULT = x; :}; +Expr ::= OrExprB:x {: RESULT = x; :}; +Expr ::= Bind:x {: RESULT = x; :}; +Bind ::= LET Let:x {: RESULT = x; :}; +Bind ::= ALL2:o Declp:a SuperOrBar:b {: RESULT = ExprQt.Op.ALL .make(o, null, a, b); :}; +Bind ::= NO2:o Declp:a SuperOrBar:b {: RESULT = ExprQt.Op.NO .make(o, null, a, b); :}; +Bind ::= SOME2:o Declp:a SuperOrBar:b {: RESULT = ExprQt.Op.SOME.make(o, null, a, b); :}; +Bind ::= LONE2:o Declp:a SuperOrBar:b {: RESULT = ExprQt.Op.LONE.make(o, null, a, b); :}; +Bind ::= ONE2:o Declp:a SuperOrBar:b {: RESULT = ExprQt.Op.ONE .make(o, null, a, b); :}; +Bind ::= SUM2:o Declp:a SuperOrBar:b {: RESULT = ExprQt.Op.SUM .make(o, null, a, b); :}; + +OrExprA ::= EquivExprA:a {: RESULT=a; :}; +OrExprA ::= OrExprB:a OR:o Bind:b {: RESULT=ExprBinary.Op.OR.make(o, null, a, b); :}; +OrExprB ::= EquivExprB:b {: RESULT=b; :}; +OrExprB ::= OrExprB:a OR:o EquivExprB:b {: RESULT=ExprBinary.Op.OR.make(o, null, a, b); :}; + +EquivExprA ::= ImpliesExprA:b {: RESULT=b; :}; +EquivExprA ::= EquivExprB:a IFF:o Bind:b {: RESULT=ExprBinary.Op.IFF.make(o, null, a, b); :}; +EquivExprB ::= ImpliesExprB:b {: RESULT=b; :}; +EquivExprB ::= EquivExprB:a IFF:o ImpliesExprB:b {: RESULT=ExprBinary.Op.IFF.make(o, null, a, b); :}; + +ImpliesExprA ::= ImpliesExprCloseA:a {: RESULT=a; :}; +ImpliesExprA ::= ImpliesExprOpenA:a {: RESULT=a; :}; +ImpliesExprCloseA ::= AndExprA:a {: RESULT=a; :}; +ImpliesExprCloseA ::= AndExprB:a IMPLIES:o ImpliesExprCloseB:b ELSE ImpliesExprCloseA:c {: RESULT = ExprITE.make(o,a,b,c); :}; +ImpliesExprOpenA ::= AndExprB:a IMPLIES:o ImpliesExprCloseB:b ELSE ImpliesExprOpenA:c {: RESULT = ExprITE.make(o,a,b,c); :}; +ImpliesExprOpenA ::= AndExprB:a IMPLIES:o ImpliesExprA:b {: RESULT = ExprBinary.Op.IMPLIES.make(o, null, a, b); :}; + +ImpliesExprCloseA ::= AndExprB:a IMPLIES:o ImpliesExprCloseB:b ELSE Bind:c {: RESULT = ExprITE.make(o,a,b,c); :}; +ImpliesExprOpenA ::= AndExprB:a IMPLIES:o Bind:b {: RESULT = ExprBinary.Op.IMPLIES.make(o, null, a, b); :}; + +ImpliesExprB ::= ImpliesExprCloseB:a {: RESULT=a; :}; +ImpliesExprB ::= ImpliesExprOpenB:a {: RESULT=a; :}; +ImpliesExprCloseB ::= AndExprB:a {: RESULT=a; :}; +ImpliesExprCloseB ::= AndExprB:a IMPLIES:o ImpliesExprCloseB:b ELSE ImpliesExprCloseB:c {: RESULT = ExprITE.make(o,a,b,c); :}; +ImpliesExprOpenB ::= AndExprB:a IMPLIES:o ImpliesExprCloseB:b ELSE ImpliesExprOpenB:c {: RESULT = ExprITE.make(o,a,b,c); :}; +ImpliesExprOpenB ::= AndExprB:a IMPLIES:o ImpliesExprB:b {: RESULT = ExprBinary.Op.IMPLIES.make(o, null, a, b); :}; + +AndExprA ::= NegExprA:a {: RESULT=a; :}; +AndExprA ::= AndExprB:a AND:o Bind:b {: RESULT=ExprBinary.Op.AND.make(o, null, a, b); :}; +AndExprB ::= NegExprB:b {: RESULT=b; :}; +AndExprB ::= AndExprB:a AND:o NegExprB:b {: RESULT=ExprBinary.Op.AND.make(o, null, a, b); :}; + +NegExprA ::= CompareExprA:b {: RESULT=b; :}; +NegExprA ::= NOT:o Bind:b {: RESULT=ExprUnary.Op.NOT.make(o, b); :}; +NegExprA ::= NOT:o NegExprA:b {: RESULT=ExprUnary.Op.NOT.make(o, b); :}; +NegExprB ::= CompareExprB:b {: RESULT=b; :}; +NegExprB ::= NOT:o NegExprB:b {: RESULT=ExprUnary.Op.NOT.make(o, b); :}; + +CompareExprA ::= CompareExprB:a IN:o ShiftExprA:b {: RESULT=ExprBinary.Op.IN .make(o, null, a, mult(b)); :}; +CompareExprA ::= CompareExprB:a EQUALS:o ShiftExprA:b {: RESULT=ExprBinary.Op.EQUALS .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a LT:o ShiftExprA:b {: RESULT=ExprBinary.Op.LT .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a GT:o ShiftExprA:b {: RESULT=ExprBinary.Op.GT .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a LTE:o ShiftExprA:b {: RESULT=ExprBinary.Op.LTE .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a GTE:o ShiftExprA:b {: RESULT=ExprBinary.Op.GTE .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a NOTIN:o ShiftExprA:b {: RESULT=ExprBinary.Op.NOT_IN .make(o, null, a, mult(b)); :}; +CompareExprA ::= CompareExprB:a NOTEQUALS:o ShiftExprA:b {: RESULT=ExprBinary.Op.NOT_EQUALS.make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a NOTLT:o ShiftExprA:b {: RESULT=ExprBinary.Op.NOT_LT .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a NOTGT:o ShiftExprA:b {: RESULT=ExprBinary.Op.NOT_GT .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a NOTLTE:o ShiftExprA:b {: RESULT=ExprBinary.Op.NOT_LTE .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a NOTGTE:o ShiftExprA:b {: RESULT=ExprBinary.Op.NOT_GTE .make(o, null, a, b); :}; +CompareExprA ::= ALL:o ShiftExprA {: if (1==1) throw new ErrorSyntax(o,"The \"all x\" construct is no longer supported. If you know the range of possible values of x, consider rewriting it as \"x == set_of_all_possible_values\"."); :}; +CompareExprA ::= NO:o ShiftExprA:b {: RESULT=ExprUnary.Op.NO .make(o, b); :}; +CompareExprA ::= SOME:o ShiftExprA:b {: RESULT=ExprUnary.Op.SOME .make(o, b); :}; +CompareExprA ::= LONE:o ShiftExprA:b {: RESULT=ExprUnary.Op.LONE .make(o, b); :}; +CompareExprA ::= ONE:o ShiftExprA:b {: RESULT=ExprUnary.Op.ONE .make(o, b); :}; +CompareExprA ::= SET:o ShiftExprA:b {: RESULT=ExprUnary.Op.SETOF.make(o, b); :}; +CompareExprA ::= SEQ:o ShiftExprA:b {: RESULT=ExprBinary.Op.ISSEQ_ARROW_LONE.make(o, null, ExprVar.make(o, "seq/Int"), b); parser.alloymodule.addSeq(o); :}; +CompareExprA ::= ShiftExprA:b {: RESULT=b; :}; + +CompareExprB ::= CompareExprB:a IN:o ShiftExprB:b {: RESULT=ExprBinary.Op.IN .make(o, null, a, mult(b)); :}; +CompareExprB ::= CompareExprB:a EQUALS:o ShiftExprB:b {: RESULT=ExprBinary.Op.EQUALS .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a LT:o ShiftExprB:b {: RESULT=ExprBinary.Op.LT .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a GT:o ShiftExprB:b {: RESULT=ExprBinary.Op.GT .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a LTE:o ShiftExprB:b {: RESULT=ExprBinary.Op.LTE .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a GTE:o ShiftExprB:b {: RESULT=ExprBinary.Op.GTE .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a NOTIN:o ShiftExprB:b {: RESULT=ExprBinary.Op.NOT_IN .make(o, null, a, mult(b)); :}; +CompareExprB ::= CompareExprB:a NOTEQUALS:o ShiftExprB:b {: RESULT=ExprBinary.Op.NOT_EQUALS.make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a NOTLT:o ShiftExprB:b {: RESULT=ExprBinary.Op.NOT_LT .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a NOTGT:o ShiftExprB:b {: RESULT=ExprBinary.Op.NOT_GT .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a NOTLTE:o ShiftExprB:b {: RESULT=ExprBinary.Op.NOT_LTE .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a NOTGTE:o ShiftExprB:b {: RESULT=ExprBinary.Op.NOT_GTE .make(o, null, a, b); :}; +CompareExprB ::= ALL:o ShiftExprB {: if (1==1) throw new ErrorSyntax(o,"The \"all x\" construct is no longer supported. If you know the range of possible values of x, consider rewriting it as \"x == set_of_all_possible_values\"."); :}; +CompareExprB ::= NO:o ShiftExprB:b {: RESULT=ExprUnary.Op.NO .make(o, b); :}; +CompareExprB ::= SOME:o ShiftExprB:b {: RESULT=ExprUnary.Op.SOME .make(o, b); :}; +CompareExprB ::= LONE:o ShiftExprB:b {: RESULT=ExprUnary.Op.LONE .make(o, b); :}; +CompareExprB ::= ONE:o ShiftExprB:b {: RESULT=ExprUnary.Op.ONE .make(o, b); :}; +CompareExprB ::= SET:o ShiftExprB:b {: RESULT=ExprUnary.Op.SETOF.make(o, b); :}; +CompareExprB ::= SEQ:o ShiftExprB:b {: RESULT=ExprBinary.Op.ISSEQ_ARROW_LONE.make(o, null, ExprVar.make(o,"seq/Int"), b); parser.alloymodule.addSeq(o); :}; +CompareExprB ::= ShiftExprB:b {: RESULT=b; :}; + +ShiftExprA ::= UnionDiffExprA:b {: RESULT=b; :}; +ShiftExprA ::= ShiftExprB:a SHL:o Bind:b {: RESULT=ExprBinary.Op.SHL.make(o, null, a, b); :}; +ShiftExprA ::= ShiftExprB:a SHR:o Bind:b {: RESULT=ExprBinary.Op.SHR.make(o, null, a, b); :}; +ShiftExprA ::= ShiftExprB:a SHA:o Bind:b {: RESULT=ExprBinary.Op.SHA.make(o, null, a, b); :}; +ShiftExprB ::= UnionDiffExprB:b {: RESULT=b; :}; +ShiftExprB ::= ShiftExprB:a SHL:o UnionDiffExprB:b {: RESULT=ExprBinary.Op.SHL.make(o, null, a, b); :}; +ShiftExprB ::= ShiftExprB:a SHR:o UnionDiffExprB:b {: RESULT=ExprBinary.Op.SHR.make(o, null, a, b); :}; +ShiftExprB ::= ShiftExprB:a SHA:o UnionDiffExprB:b {: RESULT=ExprBinary.Op.SHA.make(o, null, a, b); :}; + +UnionDiffExprA ::= MulExprA:b {: RESULT=b; :}; +UnionDiffExprA ::= UnionDiffExprB:a PLUS:o Bind:b {: RESULT=ExprBinary.Op.PLUS .make(o, null, a, b); :}; +UnionDiffExprA ::= UnionDiffExprB:a MINUS:o Bind:b {: RESULT=ExprBinary.Op.MINUS.make(o, null, a, b); :}; +UnionDiffExprA ::= UnionDiffExprB:a INTADD:o Bind:b {: RESULT=ExprBinary.Op.IPLUS.make(o, null, a, b); :}; +UnionDiffExprA ::= UnionDiffExprB:a INTSUB:o Bind:b {: RESULT=ExprBinary.Op.IMINUS.make(o, null, a, b); :}; +UnionDiffExprB ::= MulExprB:b {: RESULT=b; :}; +UnionDiffExprB ::= UnionDiffExprB:a PLUS:o MulExprB:b {: RESULT=ExprBinary.Op.PLUS .make(o, null, a, b); :}; +UnionDiffExprB ::= UnionDiffExprB:a MINUS:o MulExprB:b {: RESULT=ExprBinary.Op.MINUS.make(o, null, a, b); :}; +UnionDiffExprB ::= UnionDiffExprB:a INTADD:o MulExprB:b {: RESULT=ExprBinary.Op.IPLUS.make(o, null, a, b); :}; +UnionDiffExprB ::= UnionDiffExprB:a INTSUB:o MulExprB:b {: RESULT=ExprBinary.Op.IMINUS.make(o, null, a, b); :}; + +MulExprA ::= NumUnopExprA:b {: RESULT=b; :}; +MulExprA ::= MulExprB:a INTMUL:o Bind:b {: RESULT=ExprBinary.Op.MUL .make(o, null, a, b); :}; +MulExprA ::= MulExprB:a INTDIV:o Bind:b {: RESULT=ExprBinary.Op.DIV .make(o, null, a, b); :}; +MulExprA ::= MulExprB:a INTREM:o Bind:b {: RESULT=ExprBinary.Op.REM .make(o, null, a, b); :}; +MulExprB ::= NumUnopExprB:b {: RESULT=b; :}; +MulExprB ::= MulExprB:a INTMUL:o NumUnopExprB:b {: RESULT=ExprBinary.Op.MUL .make(o, null, a, b); :}; +MulExprB ::= MulExprB:a INTDIV:o NumUnopExprB:b {: RESULT=ExprBinary.Op.DIV .make(o, null, a, b); :}; +MulExprB ::= MulExprB:a INTREM:o NumUnopExprB:b {: RESULT=ExprBinary.Op.REM .make(o, null, a, b); :}; + +NumUnopExprA ::= OverrideExprA:b {: RESULT=b; :}; +NumUnopExprA ::= HASH:o Bind:b {: RESULT=ExprUnary.Op.CARDINALITY.make(o, b); :}; +NumUnopExprA ::= SUM:o Bind:b {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); :}; +//[AM]: INT->SIGINT +NumUnopExprA ::= INT:o Bind:b {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); :}; +NumUnopExprA ::= HASH:o NumUnopExprA:b {: RESULT=ExprUnary.Op.CARDINALITY.make(o, b); :}; +NumUnopExprA ::= SUM:o NumUnopExprA:b {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); :}; +//[AM]: INT->SIGINT +NumUnopExprA ::= INT:o NumUnopExprA:b {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); :}; +NumUnopExprB ::= OverrideExprB:b {: RESULT=b; :}; +NumUnopExprB ::= HASH:o NumUnopExprB:b {: RESULT=ExprUnary.Op.CARDINALITY.make(o, b); :}; +NumUnopExprB ::= SUM:o NumUnopExprB:b {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); :}; +//[AM]: INT->SIGINT +NumUnopExprB ::= INT:o NumUnopExprB:b {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); :}; + +OverrideExprA ::= IntersectExprA:b {: RESULT=b; :}; +OverrideExprA ::= OverrideExprB:a PLUSPLUS:o Bind:b {: RESULT=ExprBinary.Op.PLUSPLUS.make(o, null, a, b); :}; +OverrideExprB ::= IntersectExprB:b {: RESULT=b; :}; +OverrideExprB ::= OverrideExprB:a PLUSPLUS:o IntersectExprB:b {: RESULT=ExprBinary.Op.PLUSPLUS.make(o, null, a, b); :}; + +IntersectExprA ::= RelationExprA:b {: RESULT=b; :}; +IntersectExprA ::= IntersectExprB:a AMPERSAND:o Bind:b {: RESULT=ExprBinary.Op.INTERSECT.make(o, null, a, b); :}; +IntersectExprB ::= RelationExprB:b {: RESULT=b; :}; +IntersectExprB ::= IntersectExprB:a AMPERSAND:o RelationExprB:b {: RESULT=ExprBinary.Op.INTERSECT.make(o, null, a, b); :}; + +RelOp ::= ARROW:o {: RESULT=new Pair(o, ExprBinary.Op.ARROW ); :}; +RelOp ::= ANY_ARROW_SOME:o {: RESULT=new Pair(o, ExprBinary.Op.ANY_ARROW_SOME ); :}; +RelOp ::= ANY_ARROW_ONE:o {: RESULT=new Pair(o, ExprBinary.Op.ANY_ARROW_ONE ); :}; +RelOp ::= ANY_ARROW_LONE:o {: RESULT=new Pair(o, ExprBinary.Op.ANY_ARROW_LONE ); :}; +RelOp ::= SOME_ARROW_ANY:o {: RESULT=new Pair(o, ExprBinary.Op.SOME_ARROW_ANY ); :}; +RelOp ::= SOME_ARROW_SOME:o {: RESULT=new Pair(o, ExprBinary.Op.SOME_ARROW_SOME); :}; +RelOp ::= SOME_ARROW_ONE:o {: RESULT=new Pair(o, ExprBinary.Op.SOME_ARROW_ONE ); :}; +RelOp ::= SOME_ARROW_LONE:o {: RESULT=new Pair(o, ExprBinary.Op.SOME_ARROW_LONE); :}; +RelOp ::= ONE_ARROW_ANY:o {: RESULT=new Pair(o, ExprBinary.Op.ONE_ARROW_ANY ); :}; +RelOp ::= ONE_ARROW_SOME:o {: RESULT=new Pair(o, ExprBinary.Op.ONE_ARROW_SOME ); :}; +RelOp ::= ONE_ARROW_ONE:o {: RESULT=new Pair(o, ExprBinary.Op.ONE_ARROW_ONE ); :}; +RelOp ::= ONE_ARROW_LONE:o {: RESULT=new Pair(o, ExprBinary.Op.ONE_ARROW_LONE ); :}; +RelOp ::= LONE_ARROW_ANY:o {: RESULT=new Pair(o, ExprBinary.Op.LONE_ARROW_ANY ); :}; +RelOp ::= LONE_ARROW_SOME:o {: RESULT=new Pair(o, ExprBinary.Op.LONE_ARROW_SOME); :}; +RelOp ::= LONE_ARROW_ONE:o {: RESULT=new Pair(o, ExprBinary.Op.LONE_ARROW_ONE ); :}; +RelOp ::= LONE_ARROW_LONE:o {: RESULT=new Pair(o, ExprBinary.Op.LONE_ARROW_LONE); :}; + +RelationExprA ::= DomainExprA:a {: RESULT=a; :}; +RelationExprA ::= DomainExprB:a RelOp:o Bind:b {: RESULT=o.b.make(o.a, null, a, b); :}; +RelationExprB ::= DomainExprB:a {: RESULT=a; :}; +RelationExprB ::= DomainExprB:a RelOp:o RelationExprB:b {: RESULT=o.b.make(o.a, null, a, b); :}; + +DomainExprA ::= RangeExprA:b {: RESULT=b; :}; +DomainExprA ::= DomainExprB:a DOMAIN:o Bind:b {: RESULT=ExprBinary.Op.DOMAIN.make(o, null, a, b); :}; +DomainExprB ::= RangeExprB:b {: RESULT=b; :}; +DomainExprB ::= DomainExprB:a DOMAIN:o RangeExprB:b {: RESULT=ExprBinary.Op.DOMAIN.make(o, null, a, b); :}; + +RangeExprA ::= BracketExprA:b {: RESULT=b; :}; +RangeExprA ::= RangeExprB:a RANGE:o Bind:b {: RESULT=ExprBinary.Op.RANGE.make(o, null, a, b); :}; +RangeExprB ::= BracketExprB:b {: RESULT=b; :}; +RangeExprB ::= RangeExprB:a RANGE:o BracketExprB:b {: RESULT=ExprBinary.Op.RANGE.make(o, null, a, b); :}; + +BracketExprA ::= DotExprA:b {: RESULT=b; :}; +BracketExprB ::= DotExprB:b {: RESULT=b; :}; +BracketExprB ::= BracketExprB:a LBRACKET Exprs:b RBRACKET:c {: Expr aa=a; for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=aa; :}; +BracketExprB ::= DISJ:a LBRACKET Exprs:b RBRACKET:c {: Expr aa=ExprVar.make(a, "disj"); for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=aa; :}; +BracketExprB ::= TOTALORDER:a LBRACKET Exprs:b RBRACKET:c {: Expr aa=ExprVar.make(a, "pred/totalOrder"); for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=aa; :}; +//[AM]: INT->SIGINT +BracketExprB ::= INT:a LBRACKET Exprs:b RBRACKET:c {: Expr aa=ExprVar.make(a, "int"); for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=ExprUnary.Op.CAST2SIGINT.make(a, aa); :}; +BracketExprB ::= SUM:a LBRACKET Exprs:b RBRACKET:c {: Expr aa=ExprVar.make(a, "int"); for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=ExprUnary.Op.CAST2SIGINT.make(a, aa); :}; + +DotExprA ::= UnopExprA:b {: RESULT=b; :}; +DotExprA ::= BracketExprB:a DOT:o Bind:b {: RESULT=t(o, null, a, b, null); :}; +DotExprB ::= UnopExprB:b {: RESULT=b; :}; +DotExprB ::= BracketExprB:a DOT:o UnopExprB:b {: RESULT=t(o, null, a, b, null); :}; +DotExprB ::= BracketExprB:a DOT:o DISJ:b {: RESULT=t(o, null, a, ExprVar.make(b, "disj"), null); :}; +DotExprB ::= BracketExprB:a DOT:o TOTALORDER:b {: RESULT=t(o, null, a, ExprVar.make(b, "pred/totalOrder"), null); :}; +//[AM]: INT->SIGINT +DotExprB ::= BracketExprB:a DOT:o INT {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, a)); :}; +DotExprB ::= BracketExprB:a DOT:o SUM {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, a)); :}; + +UnopExprA ::= TILDE:o Bind:b {: RESULT=ExprUnary.Op.TRANSPOSE.make(o,b); :}; +UnopExprA ::= STAR:o Bind:b {: RESULT=ExprUnary.Op.RCLOSURE .make(o,b); :}; +UnopExprA ::= CARET:o Bind:b {: RESULT=ExprUnary.Op.CLOSURE .make(o,b); :}; +UnopExprA ::= TILDE:o UnopExprA:b {: RESULT=ExprUnary.Op.TRANSPOSE.make(o,b); :}; +UnopExprA ::= STAR:o UnopExprA:b {: RESULT=ExprUnary.Op.RCLOSURE .make(o,b); :}; +UnopExprA ::= CARET:o UnopExprA:b {: RESULT=ExprUnary.Op.CLOSURE .make(o,b); :}; +UnopExprB ::= BaseExpr:b {: RESULT=b; :}; +UnopExprB ::= TILDE:o UnopExprB:b {: RESULT=ExprUnary.Op.TRANSPOSE.make(o,b); :}; +UnopExprB ::= STAR:o UnopExprB:b {: RESULT=ExprUnary.Op.RCLOSURE .make(o,b); :}; +UnopExprB ::= CARET:o UnopExprB:b {: RESULT=ExprUnary.Op.CLOSURE .make(o,b); :}; + +BaseExpr ::= NUMBER:x {: RESULT = x; :}; +BaseExpr ::= STR:x {: RESULT = x; :}; +BaseExpr ::= IDEN:o {: RESULT = ExprVar.make(o, "iden"); :}; +BaseExpr ::= THIS:o {: RESULT = ExprVar.make(o, "this"); :}; +BaseExpr ::= INTMIN:o {: RESULT = ExprConstant.Op.MIN.make(o, 0); :}; +BaseExpr ::= INTMAX:o {: RESULT = ExprConstant.Op.MAX.make(o, 0); :}; +BaseExpr ::= INTNEXT:o {: RESULT = ExprConstant.Op.NEXT.make(o, 0); :}; +BaseExpr ::= LPAREN Expr:x RPAREN {: RESULT = x; :}; +BaseExpr ::= SigRef:x {: RESULT = x; :}; +BaseExpr ::= AT:o Name:x {: nod(x); RESULT = ExprVar.make(o.merge(x.pos), "@"+x.label); :}; +BaseExpr ::= Super:x {: RESULT = x; :}; +BaseExpr ::= LBRACE:o Declz:a SuperOrBar:b RBRACE:c {: RESULT = ExprQt.Op.COMPREHENSION.make(o, c, a, b); :}; +BaseExpr ::= LBRACE:o Declz:a RBRACE:c {: RESULT = ExprQt.Op.COMPREHENSION.make(o, c, a, ExprConstant.TRUE); :}; + +//============================================================================= diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/Alloy.lex b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/Alloy.lex new file mode 100644 index 00000000..b6f2af29 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/Alloy.lex @@ -0,0 +1,218 @@ +// Alloy Analyzer 4 -- Copyright (c) 2006-2008, Felix Chang +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files +// (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, +// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +package edu.mit.csail.sdg.alloy4compiler.parser; + +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprConstant; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import java.util.List; +import java_cup.runtime.*; + +/** Autogenerated by JFlex 1.4.1 */ + +%% + +// There are 3 sets of "special tokens" that the lexer will not output. +// But the Parser expects them. +// So a special Filter class is written that sits between Lexer and Parser. +// The Filter class observes the stream of tokens, and intelligently +// merges or changes some primitive tokens into special tokens. +// For more details, refer to the main documentation. +// +// But, very briefly, here are the 3 groups: +// +// (1) The lexer will generate only ALL, NO, LONE, ONE, SUM, SOME. +// It will not output ALL2, NO2, LONE2, ONE2, SUM2, SOME2. +// (The Filter class will change some ONE into ONE2, etc) +// +// (2) The lexer won't output NOTEQUALS, NOTIN, NOTLT, NOTLTE, NOTGT, NOTGTE. +// Instead it outputs them as separate tokens (eg. "NOT" "EQUALS"). +// (The Filter class is used to merge them into a single "NOTEQUALS" token) +// +// (3) The lexer willn't output the 15 special arrows (eg. ONE_ARROW_ONE) +// Instead it outputs them as separate tokens (eg. "ONE", "ARROW", "ONE") +// (The Filter class is used to merge them into a single "ONE_ARROW_ONE" token) + +%class CompLexer // The ordering of these directives is important +%cupsym CompSym +%cup +%eofval{ + return new Symbol(CompSym.EOF, alloy_here(" "), alloy_here(" ")); +%eofval} +%public +%final +%unicode +%line +%column +%pack + +%{ + public String alloy_filename=""; + public int alloy_lineoffset=0; // If not zero, it is added to the current LINE NUMBER + public List alloy_seenDollar; + public CompModule alloy_module; + private final Pos alloy_here(String txt) { + return new Pos(alloy_filename,yycolumn+1,yyline+1+alloy_lineoffset,yycolumn+txt.length(),yyline+1); + } + private final Symbol alloy_sym(String txt, int type) { + Pos p = alloy_here(txt); return new Symbol(type, p, p); + } + private final Symbol alloy_string(String txt) throws Err { + Pos p = alloy_here(txt); + if (!Version.experimental) throw new ErrorSyntax(p, "String literal is not currently supported."); + StringBuilder sb = new StringBuilder(txt.length()); + for(int i=0; i=txt.length()) throw new ErrorSyntax(p, "String literal cannot end with a single \\"); + c = txt.charAt(i); + if (c=='n') c='\n'; else if (c!='\'' && c!='\"' && c!='\\') throw new ErrorSyntax(p, "String literal currenty only supports\nfour escape sequences: \\\\, \\n, \\\', and \\\""); + } + sb.append(c); + } + txt = sb.toString(); + if (txt.length()==2) throw new ErrorSyntax(p, "Empty string is not allowed; try rewriting your model to use an empty set instead."); + return new Symbol(CompSym.STR, p, ExprConstant.Op.STRING.make(p, txt)); + } + private final Symbol alloy_id(String txt) throws Err { + Pos p=alloy_here(txt); + if (alloy_seenDollar.size()==0 && txt.indexOf('$')>=0) alloy_seenDollar.add(null); + return new Symbol(CompSym.ID, p, ExprVar.make(p,txt)); + } + private final Symbol alloy_num(String txt) throws Err { + Pos p=alloy_here(txt); + int n=0; + try { + n=Integer.parseInt(txt); + } catch(NumberFormatException ex) { + throw new ErrorSyntax(p, "The number "+txt+" is too large to be stored in a Java integer"); + } + return new Symbol(CompSym.NUMBER, p, ExprConstant.Op.NUMBER.make(p, n)); + } +%} + +%% + +"!" { return alloy_sym(yytext(), CompSym.NOT );} +"#" { return alloy_sym(yytext(), CompSym.HASH );} +"&&" { return alloy_sym(yytext(), CompSym.AND );} +"&" { return alloy_sym(yytext(), CompSym.AMPERSAND );} +"(" { return alloy_sym(yytext(), CompSym.LPAREN );} +")" { return alloy_sym(yytext(), CompSym.RPAREN );} +"*" { return alloy_sym(yytext(), CompSym.STAR );} +"++" { return alloy_sym(yytext(), CompSym.PLUSPLUS );} +"+" { return alloy_sym(yytext(), CompSym.PLUS );} +"," { return alloy_sym(yytext(), CompSym.COMMA );} +"->" { return alloy_sym(yytext(), CompSym.ARROW );} +"-" { return alloy_sym(yytext(), CompSym.MINUS );} +"." { return alloy_sym(yytext(), CompSym.DOT );} +"/" { return alloy_sym(yytext(), CompSym.SLASH );} +"::" { return alloy_sym(yytext(), CompSym.DOT );} +":>" { return alloy_sym(yytext(), CompSym.RANGE );} +":" { return alloy_sym(yytext(), CompSym.COLON );} +"<=>" { return alloy_sym(yytext(), CompSym.IFF );} +"<=" { return alloy_sym(yytext(), CompSym.LTE );} +"<:" { return alloy_sym(yytext(), CompSym.DOMAIN );} +"<<" { return alloy_sym(yytext(), CompSym.SHL );} +"<" { return alloy_sym(yytext(), CompSym.LT );} +"=<" { return alloy_sym(yytext(), CompSym.LTE );} +"=>" { return alloy_sym(yytext(), CompSym.IMPLIES );} +"=" { return alloy_sym(yytext(), CompSym.EQUALS );} +">>>" { return alloy_sym(yytext(), CompSym.SHR );} +">>" { return alloy_sym(yytext(), CompSym.SHA );} +">=" { return alloy_sym(yytext(), CompSym.GTE );} +">" { return alloy_sym(yytext(), CompSym.GT );} +"@" { return alloy_sym(yytext(), CompSym.AT );} +"[" { return alloy_sym(yytext(), CompSym.LBRACKET );} +"]" { return alloy_sym(yytext(), CompSym.RBRACKET );} +"^" { return alloy_sym(yytext(), CompSym.CARET );} +"{" { return alloy_sym(yytext(), CompSym.LBRACE );} +"||" { return alloy_sym(yytext(), CompSym.OR );} +"|" { return alloy_sym(yytext(), CompSym.BAR );} +"}" { return alloy_sym(yytext(), CompSym.RBRACE );} +"~" { return alloy_sym(yytext(), CompSym.TILDE );} +"abstract" { return alloy_sym(yytext(), CompSym.ABSTRACT );} +"all" { return alloy_sym(yytext(), CompSym.ALL );} +"and" { return alloy_sym(yytext(), CompSym.AND );} +"assert" { return alloy_sym(yytext(), CompSym.ASSERT );} +"as" { return alloy_sym(yytext(), CompSym.AS );} +"but" { return alloy_sym(yytext(), CompSym.BUT );} +"check" { return alloy_sym(yytext(), CompSym.CHECK );} +"disjoint" { return alloy_sym(yytext(), CompSym.DISJ );} +"disj" { return alloy_sym(yytext(), CompSym.DISJ );} +"else" { return alloy_sym(yytext(), CompSym.ELSE );} +"enum" { return alloy_sym(yytext(), CompSym.ENUM );} +"exactly" { return alloy_sym(yytext(), CompSym.EXACTLY );} +"exhaustive" { return alloy_sym(yytext(), CompSym.EXH );} +"exh" { return alloy_sym(yytext(), CompSym.EXH );} +"expect" { return alloy_sym(yytext(), CompSym.EXPECT );} +"extends" { return alloy_sym(yytext(), CompSym.EXTENDS );} +"fact" { return alloy_sym(yytext(), CompSym.FACT );} +"for" { return alloy_sym(yytext(), CompSym.FOR );} +"fun" { return alloy_sym(yytext(), CompSym.FUN );} +"iden" { return alloy_sym(yytext(), CompSym.IDEN );} +"iff" { return alloy_sym(yytext(), CompSym.IFF );} +"implies" { return alloy_sym(yytext(), CompSym.IMPLIES );} +"Int" { return alloy_sym(yytext(), CompSym.SIGINT );} +"int" { return alloy_sym(yytext(), CompSym.INT );} +"in" { return alloy_sym(yytext(), CompSym.IN );} +"let" { return alloy_sym(yytext(), CompSym.LET );} +"lone" { return alloy_sym(yytext(), CompSym.LONE );} +"module" { return alloy_sym(yytext(), CompSym.MODULE );} +"none" { return alloy_sym(yytext(), CompSym.NONE );} +"not" { return alloy_sym(yytext(), CompSym.NOT );} +"no" { return alloy_sym(yytext(), CompSym.NO );} +"one" { return alloy_sym(yytext(), CompSym.ONE );} +"open" { return alloy_sym(yytext(), CompSym.OPEN );} +"or" { return alloy_sym(yytext(), CompSym.OR );} +"partition" { return alloy_sym(yytext(), CompSym.PART );} +"part" { return alloy_sym(yytext(), CompSym.PART );} +"pred" { return alloy_sym(yytext(), CompSym.PRED );} +"private" { return alloy_sym(yytext(), CompSym.PRIVATE );} +"run" { return alloy_sym(yytext(), CompSym.RUN );} +"seq" { return alloy_sym(yytext(), CompSym.SEQ );} +"set" { return alloy_sym(yytext(), CompSym.SET );} +"sig" { return alloy_sym(yytext(), CompSym.SIG );} +"some" { return alloy_sym(yytext(), CompSym.SOME );} +"String" { return alloy_sym(yytext(), CompSym.STRING );} +"sum" { return alloy_sym(yytext(), CompSym.SUM );} +"this" { return alloy_sym(yytext(), CompSym.THIS );} +"univ" { return alloy_sym(yytext(), CompSym.UNIV );} + +[\"] ([^\\\"] | ("\\" .))* [\"] [\$0-9a-zA-Z_\'\"] [\$0-9a-zA-Z_\'\"]* { throw new ErrorSyntax(alloy_here(yytext()),"String literal cannot be followed by a legal identifier character."); } +[\"] ([^\\\"] | ("\\" .))* [\"] { return alloy_string(yytext()); } +[\"] ([^\\\"] | ("\\" .))* { throw new ErrorSyntax(alloy_here(yytext()),"String literal is missing its closing \" character"); } +[0-9][0-9]*[\$a-zA-Z_\'\"][\$0-9a-zA-Z_\'\"]* { throw new ErrorSyntax(alloy_here(yytext()),"Name cannot start with a number."); } +[0-9][0-9]* { return alloy_num (yytext()); } +[:jletter:][[:jletterdigit:]\'\"]* { return alloy_id (yytext()); } +//[\$a-zA-Z][\$0-9a-zA-Z_\'\"]* { return alloy_id (yytext()); } + +"/**" ~"*/" { } + +"/*" ~"*/" { } + +("//"|"--") [^\r\n]* [\r\n] { } + +("//"|"--") [^\r\n]* { } // This rule is shorter than the previous rule, + // so it will only apply if the final line of a file is missing the \n or \r character. + +[ \t\f\r\n] { } + +. { throw new ErrorSyntax(alloy_here(" "), "Syntax error at the "+yytext()+" character."); } diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/CompFilter.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/CompFilter.java new file mode 100644 index 00000000..a7fd672b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/CompFilter.java @@ -0,0 +1,241 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.parser; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.io.Reader; +import java_cup.runtime.Scanner; +import java_cup.runtime.Symbol; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprConstant; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import static edu.mit.csail.sdg.alloy4compiler.parser.CompSym.*; + +/** This class sits between the lexer and the parser. + * + *

+ * Reason: there are 3 sets of "special tokens" that the lexer will not output. + * But the Parser expects them. So this filter class observes the stream of + * tokens, and intelligently merges or changes some primitive tokens into special tokens. + * + *

+ * For more details, refer to the main documentation. + * But, very briefly, here are the 3 groups: + * + *

+ * (1) The lexer will generate only ALL, NO, LONE, ONE, SUM, SOME. + * It will not output ALL2, NO2, LONE2, ONE2, SUM2, SOME2. + * (The Filter class will change ONE into ONE2 when appropriate) + * + *

+ * (2) The lexer won't output NOTEQUALS, NOTIN, NOTLT, NOTLTE, NOTGT, NOTGTE. + * Instead it outputs them as separate tokens (eg. "NOT" "EQUALS"). + * (The Filter class is used to merge them into a single "NOTEQUALS" token) + * + *

+ * (3) The lexer won't output the 15 special arrows (eg. ONE_ARROW_ONE) + * Instead it outputs them as separate tokens (eg. "ONE", "ARROW", "ONE") + * (The Filter class is used to merge them into a single "ONE_ARROW_ONE" token) + */ + +final class CompFilter implements Scanner { + + //===================== PHASE 1 ================================================================================== + + /** The underlying lexer. */ + private final Scanner r; + + /** A list of tokens that we prefetched from the underlying lexer. */ + private final LinkedList undo = new LinkedList(); + + /** Stores the latest token passed from phase 1 to phase 2. */ + private Symbol last = null; + + /** Reads a token from the underlying lexer; if the undo list is not empty, we take it from there instead. */ + private Symbol myread() throws Err { + if (!undo.isEmpty()) return undo.removeFirst(); + try { + return r.next_token(); + } catch(Exception ex) { + if (ex instanceof Err) throw (Err)ex; else throw new ErrorFatal("IO error: "+ex.getMessage(), ex); + } + } + + /** Reads one or more tokens from the underlying lexer, transform them if necessarly. */ + public Symbol next_token() throws Err { + Symbol a = myread(), b; + int c; + if (last==null || (last.sym!=COLON && last.sym!=DISJ)) { + if (a.sym==NO) c=NO2; + else if (a.sym==ALL) c=ALL2; + else if (a.sym==SUM) c=SUM2; + else if (a.sym==LONE) c=LONE2; + else if (a.sym==ONE) c=ONE2; + else if (a.sym==SOME) c=SOME2; + else return last=a; + final ArrayList temp = new ArrayList(); + temp.add(b = myread()); + if (b.sym==PRIVATE) temp.add(b = myread()); + if (b.sym==DISJ || b.sym==PART || b.sym==EXH) temp.add(b = myread()); + while(b.sym==ID) { + temp.add(b = myread()); + if (b.sym==COMMA) temp.add(b = myread()); else if (b.sym==COLON) { a.sym=c; break; } else { break; } + } + for(int i=temp.size()-1; i>=0; i--) undo.add(0, temp.get(i)); + } + return last=a; + } + + /** Change a.pos to be the merger of a.pos and b.pos, then change a.sym to be sym, then return a. */ + private static Symbol merge(Symbol a, Symbol b, int sym) { + a.pos = a.pos.merge(b.pos); + a.sym = sym; + return a; + } + + /** Construct a filter for the tokens from the given file. */ + public CompFilter(CompModule module, List seenDollar, String filename, int lineOffset, Reader i) throws Err { + final CompLexer L = new CompLexer(i); + L.alloy_module = module; + L.alloy_filename = filename; + L.alloy_lineoffset = lineOffset; + L.alloy_seenDollar = seenDollar; + // Replace "ID : RUN/CHECK ID" with "RUN/CHECK ID ID" + // Replace "ID : RUN/CHECK {" WITH "RUN/CHECK ID {" + final Scanner A = new Scanner() { + private Symbol a, b, c, d; + public final Symbol next_token() throws Exception { + if (a==null) a=L.next_token(); if (a.sym==EOF) { b=a; c=a; d=a; } + if (b==null) b=L.next_token(); if (b.sym==EOF) { c=b; d=b; } + if (c==null) c=L.next_token(); if (c.sym==EOF) { d=c; } + if (d==null) d=L.next_token(); + if (a.sym==ID && b.sym==COLON && (c.sym==RUN || c.sym==CHECK) && (d.sym==ID || d.sym==LBRACE)) { + Symbol x=c; b=d; c=null; d=null; return x; + } + Symbol x=a; a=b; b=c; c=d; d=null; return x; + } + }; + // Merges "pred" "/" "xxx" into the actual symbol + // Merges "fun" "/" "xxx" into the actual symbol + // Merges ! { in = < <= > >= } into a single symbol + // Merges {..}=>{..} into a single symbol + final Scanner B = new Scanner() { + private Symbol undo; + public final Symbol next_token() throws Exception { + Symbol x = undo; + undo = null; + if (x==null) x = A.next_token(); + if (x.sym==NOT) { + Symbol y = A.next_token(); + if (y.sym==IN) return merge(x, y, NOTIN); + if (y.sym==EQUALS) return merge(x, y, NOTEQUALS); + if (y.sym==LT) return merge(x, y, NOTLT); + if (y.sym==LTE) return merge(x, y, NOTLTE); + if (y.sym==GT) return merge(x, y, NOTGT); + if (y.sym==GTE) return merge(x, y, NOTGTE); + undo = y; + } else if (x.sym==PRED) { + Symbol y = A.next_token(); + if (y.sym!=SLASH) { undo=y; return x; } + Symbol z = A.next_token(); + if (z.sym==ID && ((ExprVar)(z.value)).label.equals("totalOrder")) return merge(x, z, TOTALORDER); + undo = z; + } else if (x.sym==FUN) { + Symbol y = A.next_token(); + if (y.sym!=SLASH) { undo=y; return x; } + Symbol z = A.next_token(); + if (z.sym==ID && ((ExprVar)(z.value)).label.equals("add")) return merge(x, z, INTADD); + if (z.sym==ID && ((ExprVar)(z.value)).label.equals("sub")) return merge(x, z, INTSUB); + if (z.sym==ID && ((ExprVar)(z.value)).label.equals("mul")) return merge(x, z, INTMUL); + if (z.sym==ID && ((ExprVar)(z.value)).label.equals("div")) return merge(x, z, INTDIV); + if (z.sym==ID && ((ExprVar)(z.value)).label.equals("rem")) return merge(x, z, INTREM); + if (z.sym==ID && ((ExprVar)(z.value)).label.equals("min")) return merge(x, z, INTMIN); + if (z.sym==ID && ((ExprVar)(z.value)).label.equals("max")) return merge(x, z, INTMAX); + if (z.sym==ID && ((ExprVar)(z.value)).label.equals("next")) return merge(x, z, INTNEXT); + } else if (x.sym==ONE) { + Symbol y = A.next_token(); + if (y.sym!=ARROW) { undo=y; return x; } + Symbol z = A.next_token(); + if (z.sym==ONE) return merge(x, z, ONE_ARROW_ONE); + if (z.sym==LONE) return merge(x, z, ONE_ARROW_LONE); + if (z.sym==SOME) return merge(x, z, ONE_ARROW_SOME); + if (z.sym==SET) return merge(x, z, ONE_ARROW_ANY); else { undo=z; return merge(x, y, ONE_ARROW_ANY); } + } else if (x.sym==LONE) { + Symbol y = A.next_token(); + if (y.sym!=ARROW) { undo=y; return x; } + Symbol z = A.next_token(); + if (z.sym==ONE) return merge(x, z, LONE_ARROW_ONE); + if (z.sym==LONE) return merge(x, z, LONE_ARROW_LONE); + if (z.sym==SOME) return merge(x, z, LONE_ARROW_SOME); + if (z.sym==SET) return merge(x, z, LONE_ARROW_ANY); else { undo=z; return merge(x, y, LONE_ARROW_ANY); } + } else if (x.sym==SOME) { + Symbol y = A.next_token(); + if (y.sym!=ARROW) { undo=y; return x; } + Symbol z = A.next_token(); + if (z.sym==ONE) return merge(x, z, SOME_ARROW_ONE); + if (z.sym==LONE) return merge(x, z, SOME_ARROW_LONE); + if (z.sym==SOME) return merge(x, z, SOME_ARROW_SOME); + if (z.sym==SET) return merge(x, z, SOME_ARROW_ANY); else { undo=z; return merge(x, y, SOME_ARROW_ANY); } + } else if (x.sym==SET) { + Symbol y = A.next_token(); + if (y.sym!=ARROW) { undo=y; return x; } + Symbol z = A.next_token(); + if (z.sym==ONE) return merge(x, z, ANY_ARROW_ONE); + if (z.sym==LONE) return merge(x, z, ANY_ARROW_LONE); + if (z.sym==SOME) return merge(x, z, ANY_ARROW_SOME); + if (z.sym==SET) return merge(x, z, ARROW); else { undo=z; return merge(x, y, ARROW); } + } else if (x.sym==ARROW) { + Symbol z = A.next_token(); + if (z.sym==ONE) return merge(x, z, ANY_ARROW_ONE); + if (z.sym==LONE) return merge(x, z, ANY_ARROW_LONE); + if (z.sym==SOME) return merge(x, z, ANY_ARROW_SOME); + if (z.sym==SET) return merge(x, z, ARROW); else { undo=z; } + } + return x; + } + }; + // Merge "- number" into "-number" whenever it is not immediately following ")" "]" "}" DISJ TOTALORDER INT SUM ID NUMBER STR IDEN THIS INTMIN INTMAX INTNEXT UNIV SIGINT NONE + final Scanner C = new Scanner() { + private Symbol last, undo; + public final Symbol next_token() throws Exception { + Symbol x = undo; + undo = null; + if (x==null) x = B.next_token(); + if (last!=null) { + if (last.sym==RPAREN || last.sym==RBRACKET || last.sym==RBRACE || last.sym==DISJ || last.sym==TOTALORDER || last.sym==INT) return last = x; + if (last.sym==SUM || last.sym==ID || last.sym==NUMBER || last.sym==STR || last.sym==IDEN || last.sym==THIS) return last = x; + if (last.sym==INTMIN || last.sym==INTMAX || last.sym==INTNEXT || last.sym==UNIV || last.sym==SIGINT || last.sym==NONE) return last = x; + } + if (x.sym==MINUS) { + Symbol y = B.next_token(); + if (y.sym==NUMBER) { + ExprConstant num = (ExprConstant)(y.value); + y.pos = x.pos.merge(y.pos); + y.value = ExprConstant.Op.NUMBER.make(y.pos, 0 - num.num); + return last = y; + } + undo = y; + return last = x; + } + return last = x; + } + }; + this.r = C; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/CompLexer.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/CompLexer.java new file mode 100644 index 00000000..b3da5ca2 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/CompLexer.java @@ -0,0 +1,1213 @@ +/* The following code was generated by JFlex 1.4.1 on 8/16/11 10:01 PM */ + +// Alloy Analyzer 4 -- Copyright (c) 2006-2008, Felix Chang +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files +// (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, +// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +package edu.mit.csail.sdg.alloy4compiler.parser; + +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprConstant; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import java.util.List; +import java_cup.runtime.*; + +/** Autogenerated by JFlex 1.4.1 */ + + +public final class CompLexer implements java_cup.runtime.Scanner { + + /** This character denotes the end of file */ + public static final int YYEOF = -1; + + /** initial size of the lookahead buffer */ + private static final int ZZ_BUFFERSIZE = 16384; + + /** lexical states */ + public static final int YYINITIAL = 0; + + /** + * Translates characters to character classes + */ + private static final String ZZ_CMAP_PACKED = + "\11\71\1\73\1\64\1\0\1\73\1\72\16\71\4\0\1\73\1\1"+ + "\1\62\1\2\1\70\1\0\1\3\1\65\1\4\1\5\1\6\1\7"+ + "\1\10\1\11\1\13\1\14\12\66\1\15\1\0\1\16\1\17\1\12"+ + "\1\0\1\20\10\70\1\56\11\70\1\61\7\70\1\21\1\63\1\22"+ + "\1\23\1\70\1\0\1\30\1\31\1\35\1\40\1\41\1\55\1\60"+ + "\1\43\1\45\1\46\1\44\1\36\1\50\1\37\1\47\1\54\1\57"+ + "\1\34\1\32\1\33\1\42\1\53\1\70\1\51\1\52\1\70\1\24"+ + "\1\25\1\26\1\27\41\71\2\0\4\67\4\0\1\67\2\0\1\71"+ + "\7\0\1\67\4\0\1\67\5\0\27\67\1\0\37\67\1\0\u013f\67"+ + "\31\0\162\67\4\0\14\67\16\0\5\67\11\0\1\67\21\0\130\71"+ + "\5\0\23\71\12\0\1\67\13\0\1\67\1\0\3\67\1\0\1\67"+ + "\1\0\24\67\1\0\54\67\1\0\46\67\1\0\5\67\4\0\202\67"+ + "\1\0\4\71\3\0\105\67\1\0\46\67\2\0\2\67\6\0\20\67"+ + "\41\0\46\67\2\0\1\67\7\0\47\67\11\0\21\71\1\0\27\71"+ + "\1\0\3\71\1\0\1\71\1\0\2\71\1\0\1\71\13\0\33\67"+ + "\5\0\3\67\15\0\4\71\14\0\6\71\13\0\32\67\5\0\13\67"+ + "\16\71\7\0\12\71\4\0\2\67\1\71\143\67\1\0\1\67\10\71"+ + "\1\0\6\71\2\67\2\71\1\0\4\71\2\67\12\71\3\67\2\0"+ + "\1\67\17\0\1\71\1\67\1\71\36\67\33\71\2\0\3\67\60\0"+ + "\46\67\13\71\1\67\u014f\0\3\71\66\67\2\0\1\71\1\67\20\71"+ + "\2\0\1\67\4\71\3\0\12\67\2\71\2\0\12\71\21\0\3\71"+ + "\1\0\10\67\2\0\2\67\2\0\26\67\1\0\7\67\1\0\1\67"+ + "\3\0\4\67\2\0\1\71\1\67\7\71\2\0\2\71\2\0\3\71"+ + "\11\0\1\71\4\0\2\67\1\0\3\67\2\71\2\0\12\71\4\67"+ + "\15\0\3\71\1\0\6\67\4\0\2\67\2\0\26\67\1\0\7\67"+ + "\1\0\2\67\1\0\2\67\1\0\2\67\2\0\1\71\1\0\5\71"+ + "\4\0\2\71\2\0\3\71\13\0\4\67\1\0\1\67\7\0\14\71"+ + "\3\67\14\0\3\71\1\0\11\67\1\0\3\67\1\0\26\67\1\0"+ + "\7\67\1\0\2\67\1\0\5\67\2\0\1\71\1\67\10\71\1\0"+ + "\3\71\1\0\3\71\2\0\1\67\17\0\2\67\2\71\2\0\12\71"+ + "\1\0\1\67\17\0\3\71\1\0\10\67\2\0\2\67\2\0\26\67"+ + "\1\0\7\67\1\0\2\67\1\0\5\67\2\0\1\71\1\67\6\71"+ + "\3\0\2\71\2\0\3\71\10\0\2\71\4\0\2\67\1\0\3\67"+ + "\4\0\12\71\1\0\1\67\20\0\1\71\1\67\1\0\6\67\3\0"+ + "\3\67\1\0\4\67\3\0\2\67\1\0\1\67\1\0\2\67\3\0"+ + "\2\67\3\0\3\67\3\0\10\67\1\0\3\67\4\0\5\71\3\0"+ + "\3\71\1\0\4\71\11\0\1\71\17\0\11\71\11\0\1\67\7\0"+ + "\3\71\1\0\10\67\1\0\3\67\1\0\27\67\1\0\12\67\1\0"+ + "\5\67\4\0\7\71\1\0\3\71\1\0\4\71\7\0\2\71\11\0"+ + "\2\67\4\0\12\71\22\0\2\71\1\0\10\67\1\0\3\67\1\0"+ + "\27\67\1\0\12\67\1\0\5\67\2\0\1\71\1\67\7\71\1\0"+ + "\3\71\1\0\4\71\7\0\2\71\7\0\1\67\1\0\2\67\4\0"+ + "\12\71\22\0\2\71\1\0\10\67\1\0\3\67\1\0\27\67\1\0"+ + "\20\67\4\0\6\71\2\0\3\71\1\0\4\71\11\0\1\71\10\0"+ + "\2\67\4\0\12\71\22\0\2\71\1\0\22\67\3\0\30\67\1\0"+ + "\11\67\1\0\1\67\2\0\7\67\3\0\1\71\4\0\6\71\1\0"+ + "\1\71\1\0\10\71\22\0\2\71\15\0\60\67\1\71\2\67\7\71"+ + "\4\0\10\67\10\71\1\0\12\71\47\0\2\67\1\0\1\67\2\0"+ + "\2\67\1\0\1\67\2\0\1\67\6\0\4\67\1\0\7\67\1\0"+ + "\3\67\1\0\1\67\1\0\1\67\2\0\2\67\1\0\4\67\1\71"+ + "\2\67\6\71\1\0\2\71\1\67\2\0\5\67\1\0\1\67\1\0"+ + "\6\71\2\0\12\71\2\0\2\67\42\0\1\67\27\0\2\71\6\0"+ + "\12\71\13\0\1\71\1\0\1\71\1\0\1\71\4\0\2\71\10\67"+ + "\1\0\42\67\6\0\24\71\1\0\2\71\4\67\4\0\10\71\1\0"+ + "\44\71\11\0\1\71\71\0\42\67\1\0\5\67\1\0\2\67\1\0"+ + "\7\71\3\0\4\71\6\0\12\71\6\0\6\67\4\71\106\0\46\67"+ + "\12\0\51\67\7\0\132\67\5\0\104\67\5\0\122\67\6\0\7\67"+ + "\1\0\77\67\1\0\1\67\1\0\4\67\2\0\7\67\1\0\1\67"+ + "\1\0\4\67\2\0\47\67\1\0\1\67\1\0\4\67\2\0\37\67"+ + "\1\0\1\67\1\0\4\67\2\0\7\67\1\0\1\67\1\0\4\67"+ + "\2\0\7\67\1\0\7\67\1\0\27\67\1\0\37\67\1\0\1\67"+ + "\1\0\4\67\2\0\7\67\1\0\47\67\1\0\23\67\16\0\11\71"+ + "\56\0\125\67\14\0\u026c\67\2\0\10\67\12\0\32\67\5\0\113\67"+ + "\3\0\3\67\17\0\15\67\1\0\4\67\3\71\13\0\22\67\3\71"+ + "\13\0\22\67\2\71\14\0\15\67\1\0\3\67\1\0\2\71\14\0"+ + "\64\67\40\71\3\0\1\67\3\0\2\67\1\71\2\0\12\71\41\0"+ + "\3\71\2\0\12\71\6\0\130\67\10\0\51\67\1\71\126\0\35\67"+ + "\3\0\14\71\4\0\14\71\12\0\12\71\36\67\2\0\5\67\u038b\0"+ + "\154\67\224\0\234\67\4\0\132\67\6\0\26\67\2\0\6\67\2\0"+ + "\46\67\2\0\6\67\2\0\10\67\1\0\1\67\1\0\1\67\1\0"+ + "\1\67\1\0\37\67\2\0\65\67\1\0\7\67\1\0\1\67\3\0"+ + "\3\67\1\0\7\67\3\0\4\67\2\0\6\67\4\0\15\67\5\0"+ + "\3\67\1\0\7\67\17\0\4\71\32\0\5\71\20\0\2\67\23\0"+ + "\1\67\13\0\4\71\6\0\6\71\1\0\1\67\15\0\1\67\40\0"+ + "\22\67\36\0\15\71\4\0\1\71\3\0\6\71\27\0\1\67\4\0"+ + "\1\67\2\0\12\67\1\0\1\67\3\0\5\67\6\0\1\67\1\0"+ + "\1\67\1\0\1\67\1\0\4\67\1\0\3\67\1\0\7\67\3\0"+ + "\3\67\5\0\5\67\26\0\44\67\u0e81\0\3\67\31\0\11\67\6\71"+ + "\1\0\5\67\2\0\5\67\4\0\126\67\2\0\2\71\2\0\3\67"+ + "\1\0\137\67\5\0\50\67\4\0\136\67\21\0\30\67\70\0\20\67"+ + "\u0200\0\u19b6\67\112\0\u51a6\67\132\0\u048d\67\u0773\0\u2ba4\67\u215c\0\u012e\67"+ + "\2\0\73\67\225\0\7\67\14\0\5\67\5\0\1\67\1\71\12\67"+ + "\1\0\15\67\1\0\5\67\1\0\1\67\1\0\2\67\1\0\2\67"+ + "\1\0\154\67\41\0\u016b\67\22\0\100\67\2\0\66\67\50\0\15\67"+ + "\3\0\20\71\20\0\4\71\17\0\2\67\30\0\3\67\31\0\1\67"+ + "\6\0\5\67\1\0\207\67\2\0\1\71\4\0\1\67\13\0\12\71"+ + "\7\0\32\67\4\0\1\67\1\0\32\67\12\0\132\67\3\0\6\67"+ + "\2\0\6\67\2\0\6\67\2\0\3\67\3\0\2\67\3\0\2\67"+ + "\22\0\3\71\4\0"; + + /** + * Translates characters to character classes + */ + private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); + + /** + * Translates DFA states to action switch labels. + */ + private static final int [] ZZ_ACTION = zzUnpackAction(); + + private static final String ZZ_ACTION_PACKED_0 = + "\1\0\1\1\1\2\1\3\1\4\1\5\1\6\1\7"+ + "\1\10\1\11\1\12\1\13\1\14\1\15\1\16\1\17"+ + "\1\20\1\21\1\22\1\23\1\24\1\25\1\26\1\27"+ + "\1\30\23\31\1\32\1\33\1\34\1\35\1\36\1\33"+ + "\1\37\1\40\1\41\1\0\1\42\1\43\1\44\1\45"+ + "\1\46\1\45\1\47\1\31\1\50\14\31\1\51\5\31"+ + "\1\52\3\31\1\47\12\31\1\53\1\0\1\54\1\55"+ + "\2\0\1\56\2\31\1\57\1\35\1\60\1\61\1\62"+ + "\1\63\1\64\2\31\1\65\1\31\1\66\1\31\1\2"+ + "\6\31\1\67\2\31\1\70\2\31\1\56\1\71\6\31"+ + "\1\72\1\73\1\74\1\31\1\75\1\0\1\33\2\31"+ + "\1\76\1\77\1\31\1\100\1\101\1\102\1\103\1\104"+ + "\4\31\1\105\1\106\1\31\1\107\1\31\1\110\1\111"+ + "\1\31\1\112\3\31\1\113\13\31\1\114\4\31\1\115"+ + "\1\31\1\116\2\31\1\117\2\31\1\120\1\121\1\31"+ + "\1\46\1\31\1\122\1\123\1\102\3\31\1\110\1\67"; + + private static int [] zzUnpackAction() { + int [] result = new int[210]; + int offset = 0; + offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAction(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + + /** + * Translates a state to a row index in the transition table + */ + private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); + + private static final String ZZ_ROWMAP_PACKED_0 = + "\0\0\0\74\0\74\0\74\0\170\0\74\0\74\0\74"+ + "\0\264\0\74\0\360\0\u012c\0\74\0\u0168\0\u01a4\0\u01e0"+ + "\0\u021c\0\74\0\74\0\74\0\74\0\74\0\u0258\0\74"+ + "\0\74\0\u0294\0\u02d0\0\u030c\0\u0348\0\u0384\0\u03c0\0\u03fc"+ + "\0\u0438\0\u0474\0\u04b0\0\u04ec\0\u0528\0\u0564\0\u05a0\0\u05dc"+ + "\0\u0618\0\u0654\0\u0690\0\u06cc\0\u0708\0\74\0\u0744\0\74"+ + "\0\74\0\u0780\0\74\0\u07bc\0\74\0\u07f8\0\74\0\74"+ + "\0\74\0\u0834\0\74\0\74\0\74\0\u0870\0\u08ac\0\u08e8"+ + "\0\u0924\0\u0960\0\u099c\0\u09d8\0\u0a14\0\u0a50\0\u0a8c\0\u0ac8"+ + "\0\u0b04\0\u0b40\0\u0b7c\0\u0bb8\0\u0bf4\0\u0c30\0\u0c6c\0\u0ca8"+ + "\0\u0ce4\0\u0d20\0\u0d5c\0\u0d98\0\u0dd4\0\u0528\0\u0e10\0\u0e4c"+ + "\0\u0e88\0\u0ec4\0\u0f00\0\u0f3c\0\u0f78\0\u0fb4\0\u0ff0\0\u102c"+ + "\0\u1068\0\u10a4\0\u10e0\0\74\0\u111c\0\u1158\0\74\0\u1194"+ + "\0\u11d0\0\u0528\0\u0528\0\u0528\0\u0528\0\u0528\0\u0528\0\u0528"+ + "\0\u120c\0\u1248\0\u0528\0\u1284\0\u0528\0\u12c0\0\u0528\0\u12fc"+ + "\0\u1338\0\u1374\0\u13b0\0\u13ec\0\u1428\0\u1464\0\u14a0\0\u14dc"+ + "\0\u0528\0\u1518\0\u1554\0\u0528\0\u0528\0\u1590\0\u15cc\0\u1608"+ + "\0\u1644\0\u1680\0\u16bc\0\u0528\0\u0528\0\u0528\0\u16f8\0\u1068"+ + "\0\u1734\0\u111c\0\u1770\0\u17ac\0\u0528\0\u0528\0\u17e8\0\u0528"+ + "\0\u0528\0\u1824\0\u0528\0\u0528\0\u1860\0\u189c\0\u18d8\0\u1914"+ + "\0\u0528\0\u0528\0\u1950\0\u0528\0\u198c\0\u19c8\0\u0528\0\u1a04"+ + "\0\u0528\0\u1a40\0\u1a7c\0\u1ab8\0\u0528\0\u1af4\0\u1b30\0\u1b6c"+ + "\0\u1ba8\0\u1be4\0\u1c20\0\u1c5c\0\u1c98\0\u1cd4\0\u1d10\0\u1d4c"+ + "\0\u0528\0\u1d88\0\u1dc4\0\u1e00\0\u1e3c\0\u0528\0\u1e78\0\u0528"+ + "\0\u1eb4\0\u1ef0\0\u0528\0\u1f2c\0\u1f68\0\u0528\0\u0528\0\u1fa4"+ + "\0\u0528\0\u1fe0\0\u0528\0\u0528\0\u0528\0\u201c\0\u2058\0\u2094"+ + "\0\u0528\0\u0528"; + + private static int [] zzUnpackRowMap() { + int [] result = new int[210]; + int offset = 0; + offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackRowMap(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int high = packed.charAt(i++) << 16; + result[j++] = high | packed.charAt(i++); + } + return j; + } + + /** + * The transition table of the DFA + */ + private static final int [] ZZ_TRANS = zzUnpackTrans(); + + private static final String ZZ_TRANS_PACKED_0 = + "\1\2\1\3\1\4\1\5\1\6\1\7\1\10\1\11"+ + "\1\12\1\13\1\14\1\15\1\16\1\17\1\20\1\21"+ + "\1\22\1\23\1\24\1\25\1\26\1\27\1\30\1\31"+ + "\1\32\1\33\1\34\1\35\1\36\1\37\1\40\1\41"+ + "\1\42\1\43\1\44\2\45\1\46\1\45\1\47\1\50"+ + "\3\45\1\51\1\52\1\53\2\45\1\54\1\55\1\2"+ + "\1\56\1\2\1\57\2\45\1\2\2\56\77\0\1\60"+ + "\77\0\1\61\75\0\1\62\1\63\73\0\1\64\4\0"+ + "\1\65\62\0\1\66\5\0\1\62\71\0\1\67\2\0"+ + "\1\15\73\0\1\70\1\71\1\72\66\0\1\73\3\0"+ + "\1\74\102\0\1\75\76\0\1\45\1\76\1\77\3\45"+ + "\1\100\1\101\23\45\2\0\5\45\32\0\12\45\1\102"+ + "\20\45\2\0\5\45\32\0\11\45\1\103\1\104\2\45"+ + "\1\105\1\45\1\106\13\45\2\0\5\45\32\0\13\45"+ + "\1\107\17\45\2\0\5\45\32\0\12\45\1\110\20\45"+ + "\2\0\5\45\32\0\13\45\1\111\17\45\2\0\5\45"+ + "\32\0\11\45\1\112\5\45\1\113\13\45\2\0\5\45"+ + "\32\0\17\45\1\114\13\45\2\0\5\45\32\0\15\45"+ + "\1\115\15\45\2\0\5\45\32\0\6\45\1\116\1\117"+ + "\11\45\1\120\11\45\2\0\5\45\32\0\7\45\1\121"+ + "\23\45\2\0\5\45\32\0\33\45\2\0\5\45\32\0"+ + "\7\45\1\122\1\123\7\45\1\124\4\45\1\125\5\45"+ + "\2\0\5\45\32\0\4\45\1\126\2\45\1\127\14\45"+ + "\1\130\6\45\2\0\5\45\32\0\17\45\1\131\13\45"+ + "\2\0\5\45\32\0\1\132\3\45\1\133\26\45\2\0"+ + "\5\45\32\0\1\134\11\45\1\135\4\45\1\136\13\45"+ + "\2\0\5\45\32\0\7\45\1\137\23\45\2\0\5\45"+ + "\32\0\3\45\1\140\27\45\2\0\5\45\2\0\62\55"+ + "\1\141\1\142\10\55\30\0\33\143\2\0\1\143\1\57"+ + "\1\0\1\143\3\0\64\62\1\56\5\62\1\56\1\62"+ + "\12\0\1\144\61\0\6\145\1\146\65\145\12\0\1\147"+ + "\111\0\2\45\1\150\30\45\2\0\5\45\32\0\2\45"+ + "\1\151\30\45\2\0\5\45\32\0\6\45\1\152\24\45"+ + "\2\0\5\45\32\0\10\45\1\153\22\45\2\0\5\45"+ + "\32\0\3\45\1\154\27\45\2\0\5\45\32\0\3\45"+ + "\1\155\23\45\1\156\3\45\2\0\5\45\32\0\20\45"+ + "\1\157\12\45\2\0\5\45\32\0\30\45\1\160\2\45"+ + "\2\0\5\45\32\0\20\45\1\161\12\45\2\0\5\45"+ + "\32\0\15\45\1\162\15\45\2\0\5\45\32\0\7\45"+ + "\1\163\23\45\2\0\5\45\32\0\11\45\1\164\21\45"+ + "\2\0\5\45\32\0\3\45\1\165\27\45\2\0\5\45"+ + "\32\0\7\45\1\166\23\45\2\0\5\45\32\0\3\45"+ + "\1\167\3\45\1\170\23\45\2\0\5\45\32\0\2\45"+ + "\1\171\30\45\2\0\5\45\32\0\2\45\1\172\30\45"+ + "\2\0\5\45\32\0\12\45\1\173\20\45\2\0\5\45"+ + "\32\0\1\174\2\45\1\175\7\45\1\176\10\45\1\177"+ + "\6\45\2\0\5\45\32\0\15\45\1\200\15\45\2\0"+ + "\5\45\32\0\3\45\1\201\27\45\2\0\5\45\32\0"+ + "\11\45\1\202\21\45\2\0\5\45\32\0\24\45\1\203"+ + "\6\45\2\0\5\45\32\0\25\45\1\204\5\45\2\0"+ + "\5\45\32\0\11\45\1\205\21\45\2\0\5\45\32\0"+ + "\11\45\1\206\21\45\2\0\5\45\32\0\10\45\1\207"+ + "\22\45\2\0\5\45\32\0\4\45\1\210\26\45\2\0"+ + "\5\45\32\0\11\45\1\211\3\45\1\212\15\45\2\0"+ + "\5\45\32\0\5\45\1\213\25\45\2\0\5\45\32\0"+ + "\7\45\1\214\23\45\2\0\5\45\32\0\4\45\1\215"+ + "\26\45\2\0\5\45\32\0\3\45\1\216\27\45\2\0"+ + "\5\45\32\0\4\45\1\217\26\45\2\0\5\45\32\0"+ + "\33\220\2\0\2\220\1\0\1\220\3\0\64\55\1\0"+ + "\7\55\30\0\33\143\2\0\2\143\1\0\1\143\3\0"+ + "\6\145\1\221\73\145\1\221\5\145\1\222\57\145\30\0"+ + "\3\45\1\223\27\45\2\0\5\45\32\0\11\45\1\224"+ + "\21\45\2\0\5\45\32\0\11\45\1\225\21\45\2\0"+ + "\5\45\32\0\2\45\1\226\30\45\2\0\5\45\32\0"+ + "\5\45\1\227\25\45\2\0\5\45\32\0\11\45\1\230"+ + "\21\45\2\0\5\45\32\0\11\45\1\231\21\45\2\0"+ + "\5\45\32\0\16\45\1\232\14\45\2\0\5\45\32\0"+ + "\11\45\1\233\21\45\2\0\5\45\32\0\20\45\1\234"+ + "\12\45\2\0\5\45\32\0\5\45\1\235\25\45\2\0"+ + "\5\45\32\0\11\45\1\236\21\45\2\0\5\45\32\0"+ + "\1\237\32\45\2\0\5\45\32\0\11\45\1\240\21\45"+ + "\2\0\5\45\32\0\23\45\1\241\7\45\2\0\5\45"+ + "\32\0\7\45\1\242\23\45\2\0\5\45\32\0\6\45"+ + "\1\243\24\45\2\0\5\45\32\0\7\45\1\244\23\45"+ + "\2\0\5\45\32\0\12\45\1\245\20\45\2\0\5\45"+ + "\32\0\3\45\1\246\27\45\2\0\5\45\32\0\10\45"+ + "\1\247\22\45\2\0\5\45\32\0\23\45\1\250\7\45"+ + "\2\0\5\45\32\0\3\45\1\251\27\45\2\0\5\45"+ + "\32\0\15\45\1\252\15\45\2\0\5\45\2\0\6\145"+ + "\1\221\5\145\1\56\57\145\30\0\4\45\1\253\26\45"+ + "\2\0\5\45\32\0\4\45\1\254\26\45\2\0\5\45"+ + "\32\0\14\45\1\255\16\45\2\0\5\45\32\0\17\45"+ + "\1\256\13\45\2\0\5\45\32\0\3\45\1\257\27\45"+ + "\2\0\5\45\32\0\7\45\1\260\23\45\2\0\5\45"+ + "\32\0\12\45\1\261\20\45\2\0\5\45\32\0\5\45"+ + "\1\262\25\45\2\0\5\45\32\0\15\45\1\263\15\45"+ + "\2\0\5\45\32\0\6\45\1\264\24\45\2\0\5\45"+ + "\32\0\15\45\1\265\15\45\2\0\5\45\32\0\1\266"+ + "\32\45\2\0\5\45\32\0\7\45\1\267\23\45\2\0"+ + "\5\45\32\0\1\270\32\45\2\0\5\45\32\0\3\45"+ + "\1\271\27\45\2\0\5\45\32\0\15\45\1\272\15\45"+ + "\2\0\5\45\32\0\6\45\1\273\24\45\2\0\5\45"+ + "\32\0\10\45\1\274\22\45\2\0\5\45\32\0\2\45"+ + "\1\275\30\45\2\0\5\45\32\0\3\45\1\276\27\45"+ + "\2\0\5\45\32\0\11\45\1\277\21\45\2\0\5\45"+ + "\32\0\11\45\1\300\21\45\2\0\5\45\32\0\3\45"+ + "\1\301\27\45\2\0\5\45\32\0\3\45\1\302\27\45"+ + "\2\0\5\45\32\0\30\45\1\303\2\45\2\0\5\45"+ + "\32\0\5\45\1\304\25\45\2\0\5\45\32\0\7\45"+ + "\1\305\23\45\2\0\5\45\32\0\22\45\1\306\10\45"+ + "\2\0\5\45\32\0\2\45\1\307\30\45\2\0\5\45"+ + "\32\0\3\45\1\310\27\45\2\0\5\45\32\0\2\45"+ + "\1\311\30\45\2\0\5\45\32\0\15\45\1\312\15\45"+ + "\2\0\5\45\32\0\11\45\1\313\21\45\2\0\5\45"+ + "\32\0\3\45\1\314\27\45\2\0\5\45\32\0\3\45"+ + "\1\315\27\45\2\0\5\45\32\0\15\45\1\316\15\45"+ + "\2\0\5\45\32\0\17\45\1\317\13\45\2\0\5\45"+ + "\32\0\23\45\1\320\7\45\2\0\5\45\32\0\7\45"+ + "\1\321\23\45\2\0\5\45\32\0\11\45\1\322\21\45"+ + "\2\0\5\45\2\0"; + + private static int [] zzUnpackTrans() { + int [] result = new int[8400]; + int offset = 0; + offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackTrans(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + value--; + do result[j++] = value; while (--count > 0); + } + return j; + } + + + /* error codes */ + private static final int ZZ_UNKNOWN_ERROR = 0; + private static final int ZZ_NO_MATCH = 1; + private static final int ZZ_PUSHBACK_2BIG = 2; + + /* error messages for the codes above */ + private static final String ZZ_ERROR_MSG[] = { + "Unkown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" + }; + + /** + * ZZ_ATTRIBUTE[aState] contains the attributes of state aState + */ + private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); + + private static final String ZZ_ATTRIBUTE_PACKED_0 = + "\1\0\3\11\1\1\3\11\1\1\1\11\2\1\1\11"+ + "\4\1\5\11\1\1\2\11\24\1\1\11\1\1\2\11"+ + "\1\1\1\11\1\1\1\11\1\0\3\11\1\1\3\11"+ + "\44\1\1\0\1\1\1\11\2\0\1\11\51\1\1\0"+ + "\101\1"; + + private static int [] zzUnpackAttribute() { + int [] result = new int[210]; + int offset = 0; + offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAttribute(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + /** the input device */ + private java.io.Reader zzReader; + + /** the current state of the DFA */ + private int zzState; + + /** the current lexical state */ + private int zzLexicalState = YYINITIAL; + + /** this buffer contains the current text to be matched and is + the source of the yytext() string */ + private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; + + /** the textposition at the last accepting state */ + private int zzMarkedPos; + + /** the textposition at the last state to be included in yytext */ + private int zzPushbackPos; + + /** the current text position in the buffer */ + private int zzCurrentPos; + + /** startRead marks the beginning of the yytext() string in the buffer */ + private int zzStartRead; + + /** endRead marks the last character in the buffer, that has been read + from input */ + private int zzEndRead; + + /** number of newlines encountered up to the start of the matched text */ + private int yyline; + + /** the number of characters up to the start of the matched text */ + private int yychar; + + /** + * the number of characters from the last newline up to the start of the + * matched text + */ + private int yycolumn; + + /** + * zzAtBOL == true <=> the scanner is currently at the beginning of a line + */ + private boolean zzAtBOL = true; + + /** zzAtEOF == true <=> the scanner is at the EOF */ + private boolean zzAtEOF; + + /** denotes if the user-EOF-code has already been executed */ + private boolean zzEOFDone; + + /* user code: */ + public String alloy_filename=""; + public int alloy_lineoffset=0; // If not zero, it is added to the current LINE NUMBER + public List alloy_seenDollar; + public CompModule alloy_module; + private final Pos alloy_here(String txt) { + return new Pos(alloy_filename,yycolumn+1,yyline+1+alloy_lineoffset,yycolumn+txt.length(),yyline+1); + } + private final Symbol alloy_sym(String txt, int type) { + Pos p = alloy_here(txt); return new Symbol(type, p, p); + } + private final Symbol alloy_string(String txt) throws Err { + Pos p = alloy_here(txt); + if (!Version.experimental) throw new ErrorSyntax(p, "String literal is not currently supported."); + StringBuilder sb = new StringBuilder(txt.length()); + for(int i=0; i=txt.length()) throw new ErrorSyntax(p, "String literal cannot end with a single \\"); + c = txt.charAt(i); + if (c=='n') c='\n'; else if (c!='\'' && c!='\"' && c!='\\') throw new ErrorSyntax(p, "String literal currenty only supports\nfour escape sequences: \\\\, \\n, \\\', and \\\""); + } + sb.append(c); + } + txt = sb.toString(); + if (txt.length()==2) throw new ErrorSyntax(p, "Empty string is not allowed; try rewriting your model to use an empty set instead."); + return new Symbol(CompSym.STR, p, ExprConstant.Op.STRING.make(p, txt)); + } + private final Symbol alloy_id(String txt) throws Err { + Pos p=alloy_here(txt); + if (alloy_seenDollar.size()==0 && txt.indexOf('$')>=0) alloy_seenDollar.add(null); + return new Symbol(CompSym.ID, p, ExprVar.make(p,txt)); + } + private final Symbol alloy_num(String txt) throws Err { + Pos p=alloy_here(txt); + int n=0; + try { + n=Integer.parseInt(txt); + } catch(NumberFormatException ex) { + throw new ErrorSyntax(p, "The number "+txt+" is too large to be stored in a Java integer"); + } + return new Symbol(CompSym.NUMBER, p, ExprConstant.Op.NUMBER.make(p, n)); + } + + + /** + * Creates a new scanner + * There is also a java.io.InputStream version of this constructor. + * + * @param in the java.io.Reader to read input from. + */ + public CompLexer(java.io.Reader in) { + this.zzReader = in; + } + + /** + * Creates a new scanner. + * There is also java.io.Reader version of this constructor. + * + * @param in the java.io.Inputstream to read input from. + */ + public CompLexer(java.io.InputStream in) { + this(new java.io.InputStreamReader(in)); + } + + /** + * Unpacks the compressed character translation table. + * + * @param packed the packed character translation table + * @return the unpacked character translation table + */ + private static char [] zzUnpackCMap(String packed) { + char [] map = new char[0x10000]; + int i = 0; /* index in packed string */ + int j = 0; /* index in unpacked array */ + while (i < 1766) { + int count = packed.charAt(i++); + char value = packed.charAt(i++); + do map[j++] = value; while (--count > 0); + } + return map; + } + + + /** + * Refills the input buffer. + * + * @return false, iff there was new input. + * + * @exception java.io.IOException if any I/O-Error occurs + */ + private boolean zzRefill() throws java.io.IOException { + + /* first: make room (if you can) */ + if (zzStartRead > 0) { + System.arraycopy(zzBuffer, zzStartRead, + zzBuffer, 0, + zzEndRead-zzStartRead); + + /* translate stored positions */ + zzEndRead-= zzStartRead; + zzCurrentPos-= zzStartRead; + zzMarkedPos-= zzStartRead; + zzPushbackPos-= zzStartRead; + zzStartRead = 0; + } + + /* is the buffer big enough? */ + if (zzCurrentPos >= zzBuffer.length) { + /* if not: blow it up */ + char newBuffer[] = new char[zzCurrentPos*2]; + System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); + zzBuffer = newBuffer; + } + + /* finally: fill the buffer with new input */ + int numRead = zzReader.read(zzBuffer, zzEndRead, + zzBuffer.length-zzEndRead); + + if (numRead < 0) { + return true; + } + else { + zzEndRead+= numRead; + return false; + } + } + + + /** + * Closes the input stream. + */ + public final void yyclose() throws java.io.IOException { + zzAtEOF = true; /* indicate end of file */ + zzEndRead = zzStartRead; /* invalidate buffer */ + + if (zzReader != null) + zzReader.close(); + } + + + /** + * Resets the scanner to read from a new input stream. + * Does not close the old reader. + * + * All internal variables are reset, the old input stream + * cannot be reused (internal buffer is discarded and lost). + * Lexical state is set to ZZ_INITIAL. + * + * @param reader the new input stream + */ + public final void yyreset(java.io.Reader reader) { + zzReader = reader; + zzAtBOL = true; + zzAtEOF = false; + zzEndRead = zzStartRead = 0; + zzCurrentPos = zzMarkedPos = zzPushbackPos = 0; + yyline = yychar = yycolumn = 0; + zzLexicalState = YYINITIAL; + } + + + /** + * Returns the current lexical state. + */ + public final int yystate() { + return zzLexicalState; + } + + + /** + * Enters a new lexical state + * + * @param newState the new lexical state + */ + public final void yybegin(int newState) { + zzLexicalState = newState; + } + + + /** + * Returns the text matched by the current regular expression. + */ + public final String yytext() { + return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead ); + } + + + /** + * Returns the character at position pos from the + * matched text. + * + * It is equivalent to yytext().charAt(pos), but faster + * + * @param pos the position of the character to fetch. + * A value from 0 to yylength()-1. + * + * @return the character at position pos + */ + public final char yycharat(int pos) { + return zzBuffer[zzStartRead+pos]; + } + + + /** + * Returns the length of the matched text region. + */ + public final int yylength() { + return zzMarkedPos-zzStartRead; + } + + + /** + * Reports an error that occured while scanning. + * + * In a wellformed scanner (no or only correct usage of + * yypushback(int) and a match-all fallback rule) this method + * will only be called with things that "Can't Possibly Happen". + * If this method is called, something is seriously wrong + * (e.g. a JFlex bug producing a faulty scanner etc.). + * + * Usual syntax/scanner level error handling should be done + * in error fallback rules. + * + * @param errorCode the code of the errormessage to display + */ + private void zzScanError(int errorCode) { + String message; + try { + message = ZZ_ERROR_MSG[errorCode]; + } + catch (ArrayIndexOutOfBoundsException e) { + message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; + } + + throw new Error(message); + } + + + /** + * Pushes the specified amount of characters back into the input stream. + * + * They will be read again by then next call of the scanning method + * + * @param number the number of characters to be read again. + * This number must not be greater than yylength()! + */ + public void yypushback(int number) { + if ( number > yylength() ) + zzScanError(ZZ_PUSHBACK_2BIG); + + zzMarkedPos -= number; + } + + + /** + * Contains user EOF-code, which will be executed exactly once, + * when the end of file is reached + */ + private void zzDoEOF() throws java.io.IOException { + if (!zzEOFDone) { + zzEOFDone = true; + yyclose(); + } + } + + + /** + * Resumes scanning until the next regular expression is matched, + * the end of input is encountered or an I/O-Error occurs. + * + * @return the next token + * @exception java.io.IOException if any I/O-Error occurs + */ + public java_cup.runtime.Symbol next_token() throws java.io.IOException, Err { + int zzInput; + int zzAction; + + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + char [] zzBufferL = zzBuffer; + char [] zzCMapL = ZZ_CMAP; + + int [] zzTransL = ZZ_TRANS; + int [] zzRowMapL = ZZ_ROWMAP; + int [] zzAttrL = ZZ_ATTRIBUTE; + + while (true) { + zzMarkedPosL = zzMarkedPos; + + boolean zzR = false; + for (zzCurrentPosL = zzStartRead; zzCurrentPosL < zzMarkedPosL; + zzCurrentPosL++) { + switch (zzBufferL[zzCurrentPosL]) { + case '\u000B': + case '\u000C': + case '\u0085': + case '\u2028': + case '\u2029': + yyline++; + yycolumn = 0; + zzR = false; + break; + case '\r': + yyline++; + yycolumn = 0; + zzR = true; + break; + case '\n': + if (zzR) + zzR = false; + else { + yyline++; + yycolumn = 0; + } + break; + default: + zzR = false; + yycolumn++; + } + } + + if (zzR) { + // peek one character ahead if it is \n (if we have counted one line too much) + boolean zzPeek; + if (zzMarkedPosL < zzEndReadL) + zzPeek = zzBufferL[zzMarkedPosL] == '\n'; + else if (zzAtEOF) + zzPeek = false; + else { + boolean eof = zzRefill(); + zzEndReadL = zzEndRead; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + if (eof) + zzPeek = false; + else + zzPeek = zzBufferL[zzMarkedPosL] == '\n'; + } + if (zzPeek) yyline--; + } + zzAction = -1; + + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + zzState = zzLexicalState; + + + zzForAction: { + while (true) { + + if (zzCurrentPosL < zzEndReadL) + zzInput = zzBufferL[zzCurrentPosL++]; + else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } + else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; + } + else { + zzInput = zzBufferL[zzCurrentPosL++]; + } + } + int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; + if (zzNext == -1) break zzForAction; + zzState = zzNext; + + int zzAttributes = zzAttrL[zzState]; + if ( (zzAttributes & 1) == 1 ) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ( (zzAttributes & 8) == 8 ) break zzForAction; + } + + } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 4: + { return alloy_sym(yytext(), CompSym.AMPERSAND ); + } + case 84: break; + case 50: + { return alloy_sym(yytext(), CompSym.SEQ ); + } + case 85: break; + case 38: + { return alloy_sym(yytext(), CompSym.IMPLIES ); + } + case 86: break; + case 23: + { return alloy_sym(yytext(), CompSym.RBRACE ); + } + case 87: break; + case 80: + { return alloy_sym(yytext(), CompSym.EXACTLY ); + } + case 88: break; + case 53: + { return alloy_sym(yytext(), CompSym.RUN ); + } + case 89: break; + case 36: + { return alloy_sym(yytext(), CompSym.SHL ); + } + case 90: break; + case 35: + { return alloy_sym(yytext(), CompSym.DOMAIN ); + } + case 91: break; + case 60: + { return alloy_sym(yytext(), CompSym.SIGINT ); + } + case 92: break; + case 24: + { return alloy_sym(yytext(), CompSym.TILDE ); + } + case 93: break; + case 21: + { return alloy_sym(yytext(), CompSym.LBRACE ); + } + case 94: break; + case 7: + { return alloy_sym(yytext(), CompSym.STAR ); + } + case 95: break; + case 30: + { return alloy_sym(yytext(), CompSym.PLUSPLUS ); + } + case 96: break; + case 58: + { return alloy_sym(yytext(), CompSym.FUN ); + } + case 97: break; + case 79: + { return alloy_sym(yytext(), CompSym.STRING ); + } + case 98: break; + case 55: + { return alloy_sym(yytext(), CompSym.EXH ); + } + case 99: break; + case 56: + { return alloy_sym(yytext(), CompSym.INT ); + } + case 100: break; + case 52: + { return alloy_sym(yytext(), CompSym.SIG ); + } + case 101: break; + case 73: + { return alloy_sym(yytext(), CompSym.PRED ); + } + case 102: break; + case 25: + { return alloy_id (yytext()); + } + case 103: break; + case 64: + { return alloy_sym(yytext(), CompSym.LONE ); + } + case 104: break; + case 41: + { return alloy_sym(yytext(), CompSym.NO ); + } + case 105: break; + case 9: + { return alloy_sym(yytext(), CompSym.COMMA ); + } + case 106: break; + case 40: + { return alloy_sym(yytext(), CompSym.AS ); + } + case 107: break; + case 63: + { return alloy_sym(yytext(), CompSym.THIS ); + } + case 108: break; + case 13: + { return alloy_sym(yytext(), CompSym.SLASH ); + } + case 109: break; + case 48: + { return alloy_sym(yytext(), CompSym.BUT ); + } + case 110: break; + case 43: + { return alloy_string(yytext()); + } + case 111: break; + case 66: + { return alloy_sym(yytext(), CompSym.DISJ ); + } + case 112: break; + case 32: + { return alloy_sym(yytext(), CompSym.SHA ); + } + case 113: break; + case 39: + { return alloy_sym(yytext(), CompSym.OR ); + } + case 114: break; + case 45: + { return alloy_sym(yytext(), CompSym.SHR ); + } + case 115: break; + case 82: + { return alloy_sym(yytext(), CompSym.PRIVATE ); + } + case 116: break; + case 31: + { return alloy_sym(yytext(), CompSym.ARROW ); + } + case 117: break; + case 33: + { return alloy_sym(yytext(), CompSym.GTE ); + } + case 118: break; + case 20: + { return alloy_sym(yytext(), CompSym.CARET ); + } + case 119: break; + case 46: + { return alloy_sym(yytext(), CompSym.IFF ); + } + case 120: break; + case 67: + { return alloy_sym(yytext(), CompSym.ELSE ); + } + case 121: break; + case 3: + { return alloy_sym(yytext(), CompSym.HASH ); + } + case 122: break; + case 12: + { return alloy_sym(yytext(), CompSym.DOT ); + } + case 123: break; + case 22: + { return alloy_sym(yytext(), CompSym.BAR ); + } + case 124: break; + case 77: + { return alloy_sym(yytext(), CompSym.EXPECT ); + } + case 125: break; + case 8: + { return alloy_sym(yytext(), CompSym.PLUS ); + } + case 126: break; + case 37: + { return alloy_sym(yytext(), CompSym.LTE ); + } + case 127: break; + case 57: + { return alloy_sym(yytext(), CompSym.ONE ); + } + case 128: break; + case 71: + { return alloy_sym(yytext(), CompSym.OPEN ); + } + case 129: break; + case 11: + { return alloy_sym(yytext(), CompSym.GT ); + } + case 130: break; + case 78: + { return alloy_sym(yytext(), CompSym.MODULE ); + } + case 131: break; + case 14: + { return alloy_sym(yytext(), CompSym.COLON ); + } + case 132: break; + case 51: + { return alloy_sym(yytext(), CompSym.SUM ); + } + case 133: break; + case 72: + { return alloy_sym(yytext(), CompSym.PART ); + } + case 134: break; + case 16: + { return alloy_sym(yytext(), CompSym.EQUALS ); + } + case 135: break; + case 81: + { return alloy_sym(yytext(), CompSym.EXTENDS ); + } + case 136: break; + case 1: + { throw new ErrorSyntax(alloy_here(" "), "Syntax error at the "+yytext()+" character."); + } + case 137: break; + case 26: + { throw new ErrorSyntax(alloy_here(yytext()),"String literal is missing its closing \" character"); + } + case 138: break; + case 59: + { return alloy_sym(yytext(), CompSym.FOR ); + } + case 139: break; + case 28: + { return alloy_num (yytext()); + } + case 140: break; + case 70: + { return alloy_sym(yytext(), CompSym.IDEN ); + } + case 141: break; + case 15: + { return alloy_sym(yytext(), CompSym.LT ); + } + case 142: break; + case 17: + { return alloy_sym(yytext(), CompSym.AT ); + } + case 143: break; + case 34: + { return alloy_sym(yytext(), CompSym.RANGE ); + } + case 144: break; + case 69: + { return alloy_sym(yytext(), CompSym.UNIV ); + } + case 145: break; + case 2: + { return alloy_sym(yytext(), CompSym.NOT ); + } + case 146: break; + case 49: + { return alloy_sym(yytext(), CompSym.SET ); + } + case 147: break; + case 6: + { return alloy_sym(yytext(), CompSym.RPAREN ); + } + case 148: break; + case 42: + { return alloy_sym(yytext(), CompSym.IN ); + } + case 149: break; + case 75: + { return alloy_sym(yytext(), CompSym.CHECK ); + } + case 150: break; + case 29: + { return alloy_sym(yytext(), CompSym.AND ); + } + case 151: break; + case 62: + { return alloy_sym(yytext(), CompSym.SOME ); + } + case 152: break; + case 74: + { return alloy_sym(yytext(), CompSym.FACT ); + } + case 153: break; + case 10: + { return alloy_sym(yytext(), CompSym.MINUS ); + } + case 154: break; + case 5: + { return alloy_sym(yytext(), CompSym.LPAREN ); + } + case 155: break; + case 65: + { return alloy_sym(yytext(), CompSym.NONE ); + } + case 156: break; + case 18: + { return alloy_sym(yytext(), CompSym.LBRACKET ); + } + case 157: break; + case 19: + { return alloy_sym(yytext(), CompSym.RBRACKET ); + } + case 158: break; + case 68: + { return alloy_sym(yytext(), CompSym.ENUM ); + } + case 159: break; + case 47: + { return alloy_sym(yytext(), CompSym.ALL ); + } + case 160: break; + case 83: + { return alloy_sym(yytext(), CompSym.ABSTRACT ); + } + case 161: break; + case 76: + { return alloy_sym(yytext(), CompSym.ASSERT ); + } + case 162: break; + case 61: + { throw new ErrorSyntax(alloy_here(yytext()),"String literal cannot be followed by a legal identifier character."); + } + case 163: break; + case 54: + { return alloy_sym(yytext(), CompSym.LET ); + } + case 164: break; + case 27: + { + } + case 165: break; + case 44: + { throw new ErrorSyntax(alloy_here(yytext()),"Name cannot start with a number."); + } + case 166: break; + default: + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + zzDoEOF(); + { return new Symbol(CompSym.EOF, alloy_here(" "), alloy_here(" ")); + } + } + else { + zzScanError(ZZ_NO_MATCH); + } + } + } + } + + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/CompModule.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/CompModule.java new file mode 100644 index 00000000..8af0984f --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/CompModule.java @@ -0,0 +1,1598 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.parser; + +import static edu.mit.csail.sdg.alloy4.Util.asList; +import static edu.mit.csail.sdg.alloy4compiler.ast.Attr.AttrType.ABSTRACT; +import static edu.mit.csail.sdg.alloy4compiler.ast.Attr.AttrType.ONE; +import static edu.mit.csail.sdg.alloy4compiler.ast.Attr.AttrType.PRIVATE; +import static edu.mit.csail.sdg.alloy4compiler.ast.Attr.AttrType.SUBSET; +import static edu.mit.csail.sdg.alloy4compiler.ast.Attr.AttrType.SUBSIG; +import static edu.mit.csail.sdg.alloy4compiler.ast.Attr.AttrType.WHERE; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.NONE; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.SEQIDX; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.SIGINT; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.STRING; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.UNIV; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Env; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.JoinableList; +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.SafeList; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.alloy4.ConstList.TempList; +import edu.mit.csail.sdg.alloy4compiler.ast.Attr; +import edu.mit.csail.sdg.alloy4compiler.ast.Browsable; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.CommandScope; +import edu.mit.csail.sdg.alloy4compiler.ast.Decl; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprBad; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprBadCall; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprBadJoin; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprBinary; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprCall; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprChoice; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprConstant; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprHasName; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprITE; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprLet; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprList; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprQt; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprUnary; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import edu.mit.csail.sdg.alloy4compiler.ast.Func; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Type; +import edu.mit.csail.sdg.alloy4compiler.ast.VisitReturn; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.SubsetSig; + +/** Mutable; this class represents an Alloy module; equals() uses object identity. */ + +public final class CompModule extends Browsable implements Module { + + // These fields are shared by all Modules that point to each other + + /** Maps each actual Sig to the original parser-generated Sig that it came from. */ + private final LinkedHashMap new2old; + + /** Maps each parser-generated Sig to its original list of field declarations. */ + private final LinkedHashMap> old2fields; + + /** Maps each parser-generated Sig to its original appended facts. */ + private final LinkedHashMap old2appendedfacts; + + /** Maps each Sig to the CompModule it belongs to. */ + private final HashMap sig2module; + + /** The list of CompModules. */ + private final List allModules; + + /** The list of sigs in the entire world whose scope shall be deemed "exact" */ + private final Set exactSigs; + + /** This stores a set of global values; given a unresolved name, we query this map first before all else. */ + private final Map globals; + + /** This stores the meta signature "sig$" */ + private final PrimSig metaSig; + + /** This stores the meta signature "field$" */ + private final PrimSig metaField; + + //============================================================================================================================// + + /** This field is used during a depth-first search of the dag-of-module(s) to mark which modules have been visited. */ + private Object visitedBy = null; + + /** The world that this CompModule belongs to. */ + private final CompModule world; + + /** The simplest path pointing to this Module ("" if this is the main module) */ + public final String path; + + /** Return the simplest path pointing to this Module ("" if this is the main module) */ + public String path() { return path; } + + /** 1: has seen the "module" line + * 3: has seen the "sig/pred/fun/fact/assert/check/run" commands + */ + private int status = 0; + + /** The position of the "MODULE" line at the top of the file; Pos.UNKNOWN if the line has not been parsed from the file yet. */ + private Pos modulePos = Pos.UNKNOWN; + + /** The text of the "MODULE" line at the top of the file; "unknown" if the line has not be parsed from the file yet. */ + private String moduleName = "unknown"; + + /** Whether we have seen a name containing a dollar sign or not. */ + boolean seenDollar = false; + + /** Each param is mapped to its corresponding Sig (or null if we have not resolved it). */ + private final Map params = new LinkedHashMap(); // Must be LinkedHashMap since the order matters + + /** Each alias is mapped to its corresponding "open" statement. */ + private final Map opens = new LinkedHashMap(); + + /** Each sig name is mapped to its corresponding SigAST. */ + private final Map sigs = new LinkedHashMap(); + + /** The list of params in this module whose scope shall be deemed "exact" */ + private final List exactParams = new ArrayList(); + + /** The current name resolution mode (0=pure) (1=Alloy 4.1.3 and older) (2=new) */ + int resolution = 1; + + /** Each func name is mapped to a nonempty list of FunAST objects. */ + private final Map> funcs = new LinkedHashMap>(); + + /** Each macro name is mapped to a MacroAST object. */ + private final Map macros = new LinkedHashMap(); + + /** Each assertion name is mapped to its Expr. */ + private final Map asserts = new LinkedHashMap(); + + /** The list of facts; each fact is either an untypechecked Exp or a typechecked Expr. */ + private final List> facts = new ArrayList>(); + + /** The list of (CommandName,Command,Expr) triples; NOTE: duplicate command names are allowed. */ + private final List commands = new ArrayList(); + + //============================================================================================================================// + + /** Mutable; this class represents the current typechecking context. */ + static final class Context extends VisitReturn { + + /** The place where warnings should go; can be null if we don't care about storing the warnings. */ + private List warns; + + /** The module that the current context is in. */ + final CompModule rootmodule; + + /** Nonnull if we are typechecking a field declaration or a sig appended facts. */ + Sig rootsig = null; + + /** Nonnull if we are typechecking a field declaration. */ + private Decl rootfield = null; + + /** True if we are typechecking a function's parameter declarations or return declaration. */ + private boolean rootfunparam = false; + + /** Nonnull if we are typechecking a function's body. */ + private Func rootfunbody = null; + + /** This maps local names (eg. let/quantification variables and function parameters) to the objects they refer to. */ + private final Env env = new Env(); + + /** The level of macro substitution recursion. */ + public final int unrolls; + + /** Associates the given name with the given expression in the current lexical scope. */ + final void put(String name, Expr value) { + env.put(name,value); + } + + /** Removes the latest binding for the given name from the current lexical scope. */ + final void remove(String name) { + env.remove(name); + } + + /** Construct a new Context with an empty lexical scope. */ + Context(CompModule rootModule, List warns) { + this(rootModule, warns, 20); // 20 is a reasonable threshold; deeper than this would likely be too big to solve anyway + } + + /** Construct a new Context with an empty lexical scope. */ + Context(CompModule rootModule, List warns, int unrolls) { + this.rootmodule = rootModule; + this.unrolls = unrolls; + this.warns = warns; + } + + /** Resolve the given name to get a collection of Expr and Func objects. */ + public Expr resolve(final Pos pos, final String name) { + if (name.indexOf('/') >= 0) { + String n = name.startsWith("this/") ? name.substring(5) : name; + CompModule mod = rootmodule; + while(true) { + int i = n.indexOf('/'); + if (i<0) { + Macro m = mod.macros.get(n); + if (m==null || (m.isPrivate!=null && mod!=rootmodule)) break; else return m.changePos(pos); + } + String alias = n.substring(0,i); + Open uu = mod.opens.get(alias); + if (uu==null || uu.realModule==null || uu.isPrivate) break; + n = n.substring(i+1); + mod = uu.realModule; + } + } + Expr match = env.get(name); + if (match==null) { + boolean ambiguous = false; + StringBuilder sb = new StringBuilder(); + for(CompModule m: rootmodule.getAllNameableModules()) { + Macro mac = m.macros.get(name); + if (mac==null) continue; + if (match!=null) ambiguous=true; else match=mac; + sb.append("\n").append(m.path.length()==0 ? "this" : m.path).append("/").append(name); + } + if (ambiguous) return new ExprBad(pos, name, new ErrorType(pos, "There are multiple macros with the same name:"+sb)); + } + if (match==null) match = rootmodule.globals.get(name); + if (match!=null) { + if (match instanceof Macro) return ((Macro)match).changePos(pos); + match = ExprUnary.Op.NOOP.make(pos, match); + return ExprChoice.make(pos, asList(match), asList(name)); + } + Expr th = env.get("this"); + if (th!=null) th = ExprUnary.Op.NOOP.make(pos, th); + TempList ch = new TempList(); + TempList re = new TempList(); + Expr ans = rootmodule.populate(ch, re, rootfield, rootsig, rootfunparam, rootfunbody, pos, name, th); + if (ans!=null) return ans; + if (ch.size()==0) return new ExprBad(pos, name, hint(pos, name)); else return ExprChoice.make(pos, ch.makeConst(), re.makeConst()); + } + + Expr check(Expr x) throws Err { + return visitThis(x); + } + + /** Returns true if the function's parameters have reasonable intersection with the list of arguments. + *
If args.length() > f.params.size(), the extra arguments are ignored by this check + */ + private static boolean applicable(Func f, List args) { + if (f.count() > args.size()) return false; + int i=0; + for(ExprVar d: f.params()) { + Type param=d.type(), arg=args.get(i).type(); + i++; + // The reason we don't directly compare "arg.arity()" with "param.arity()" + // is because the arguments may not be fully resolved yet. + if (!arg.hasCommonArity(param)) return false; + if (arg.hasTuple() && param.hasTuple() && !arg.intersects(param)) return false; + } + return true; + } + + private Expr process(Pos pos, Pos closingBracket, Pos rightPos, List choices, List oldReasons, Expr arg) { + TempList list = new TempList(choices.size()); + TempList reasons = new TempList(choices.size()); + for(int i=0; i newargs = Util.append(bc.args, arg); + if (applicable(bc.fun, newargs)) + y=ExprCall.make(bc.pos, bc.closingBracket, bc.fun, newargs, bc.extraWeight); + else + y=ExprBadCall.make(bc.pos, bc.closingBracket, bc.fun, newargs, bc.extraWeight); + } else { + y=ExprBinary.Op.JOIN.make(pos, closingBracket, arg, y); + } + } else { + y=ExprBinary.Op.JOIN.make(pos, closingBracket, arg, x); + } + list.add(y); + reasons.add(oldReasons.get(i)); + } + return ExprChoice.make(rightPos, list.makeConst(), reasons.makeConst()); + } + + /** {@inheritDoc} */ + @Override public Expr visit(ExprList x) throws Err { + TempList temp = new TempList(x.args.size()); + for(int i=0; i decls = new TempList(x.decls.size()); + boolean isMetaSig=false, isMetaField=false; + for(Decl d: x.decls) { + Expr exp = visitThis(d.expr).resolve_as_set(warns); + if (exp.mult==0 && exp.type().arity()==1) exp = ExprUnary.Op.ONEOF.make(null, exp); + if (exp.errors.isEmpty()) { + if (exp.type().isSubtypeOf(rootmodule.metaSig().plus(rootmodule.metaField()).type())) { + isMetaSig = exp.type().intersects(rootmodule.metaSig().type()); + isMetaField = exp.type().intersects(rootmodule.metaField().type()); + } + } + // Below is a special case to allow more fine-grained typechecking when we see "all x:field$" or "some x:field$" + boolean some = (x.op==ExprQt.Op.SOME), compre = (x.op==ExprQt.Op.COMPREHENSION); + if (x.decls.size()==1 && d.names.size()==1 && isOneOf(exp) && (x.op==ExprQt.Op.ALL || some || compre) && (isMetaSig || isMetaField)) { + ExprVar v = (ExprVar)(d.names.get(0)); + // Prevent warnings + List saved = warns; + warns = null; + // Now duplicate the body for each possible Meta Atom binding + Expr answer = null; + if (isMetaSig) for(PrimSig child: rootmodule.metaSig().children()) if (child.type().intersects(exp.type())) { + put(v.label, child); + Expr sub = visitThis(x.sub); + remove(v.label); + if (compre) answer = child.in(exp).and(sub).ite(child, Sig.NONE).plus(answer); + else if (some) answer = child.in(exp).and(sub).or(answer); + else answer = child.in(exp).implies(sub).and(answer); + } + if (isMetaField) for(PrimSig child: rootmodule.metaField().children()) if (child.type().intersects(exp.type())) { + put(v.label, child); + Expr sub = visitThis(x.sub); + remove(v.label); + if (compre) answer = child.in(exp).and(sub).ite(child, Sig.NONE).plus(answer); + else if (some) answer = child.in(exp).and(sub).or(answer); + else answer = child.in(exp).implies(sub).and(answer); + } + if (answer==null) answer = (compre ? Sig.NONE : (some ? ExprConstant.FALSE : ExprConstant.TRUE)); else answer = answer.resolve(answer.type(), null); + // Now, wrap the body in an ExprLet expression to prevent any more warnings by outer code + ExprVar combinedAnswer = ExprVar.make(Pos.UNKNOWN, "", answer.type()); + Expr returnValue = ExprLet.make(Pos.UNKNOWN, combinedAnswer, answer, combinedAnswer); + // Restore the "warns" array, then return the answer + warns = saved; + return returnValue; + } + // Above is a special case to allow more fine-grained typechecking when we see "all x:field$" or "some x:field$" + TempList n = new TempList(d.names.size()); + for(ExprHasName v: d.names) n.add(ExprVar.make(v.pos, v.label, exp.type())); + Decl dd = new Decl(d.isPrivate, d.disjoint, d.disjoint2, n.makeConst(), exp); + for(ExprHasName newname: dd.names) put(newname.label, newname); + decls.add(dd); + } + Expr sub = visitThis(x.sub); + if (x.op==ExprQt.Op.SUM) sub=sub.resolve_as_int(warns); else sub=sub.resolve_as_formula(warns); + for(Decl d: decls.makeConst()) for(ExprHasName v: d.names) remove(v.label); + return x.op.make(x.pos, x.closingBracket, decls.makeConst(), sub); + } + + /** {@inheritDoc} */ + @Override public Expr visit(ExprVar x) throws Err { + Expr obj = resolve(x.pos, x.label); + if (obj instanceof Macro) return ((Macro)obj).instantiate(this, warns); else return obj; + } + + /** {@inheritDoc} */ + @Override public Expr visit(ExprUnary x) throws Err { + return x.op.make(x.pos, visitThis(x.sub)); + } + + /** {@inheritDoc} */ + @Override public Expr visit(ExprCall x) { return x; } + + /** {@inheritDoc} */ + @Override public Expr visit(ExprConstant x) { return x; } + + /** {@inheritDoc} */ + @Override public Expr visit(Sig x) { return x; } + + /** {@inheritDoc} */ + @Override public Expr visit(Field x) { return x; } + + } + + //============================================================================================================================// + + /** Mutable; this class represents an untypechecked Alloy module import statement; equals() uses object identity. */ + public static final class Open { + + /** The position in the original model where this "open" statement was declared; never null. */ + public final Pos pos; + + /** The alias for this open declaration; always a nonempty string. */ + public final String alias; + + /** The unmodifiable list of instantiating arguments. */ + public final ConstList args; + + /** The relative filename for the file being imported, without the final ".als" part; always a nonempty string. */ + public final String filename; + + /** Whether this is a private open or not. */ + final boolean isPrivate; + + /** The actual Module object that it points to; null until we resolve it. */ + private CompModule realModule = null; + + /** Returns the actual Module object that it points to; null if we have not resolved it. */ + public CompModule getRealModule() { return realModule; } + + /** Constructs an Open object. */ + private Open(Pos pos, boolean isPrivate, String alias, ConstList args, String filename) { + this.pos=pos; this.isPrivate=isPrivate; this.alias=alias; this.args=args; this.filename=filename; + } + + /** Connect this OPEN statement to a module that it points to. */ + void connect(CompModule realModule) throws Err { + if (this.realModule!=null && this.realModule!=realModule) throw new ErrorFatal("Internal error (import mismatch)"); + this.realModule=realModule; + } + } + + //============================================================================================================================// + + /** Constructs a new CompModule object + * @param world - the world that this CompModule belongs to (null if this is the beginning of a new World) + * @param filename - the filename corresponding to this module + * @param path - one of the path pointing to this module + */ + CompModule(CompModule world, String filename, String path) throws Err { + if (world==null) { + if (path.length()>0) throw new ErrorFatal("Root module misparsed by parser."); + this.world = this; + new2old = new LinkedHashMap(); + old2fields = new LinkedHashMap>(); + old2appendedfacts = new LinkedHashMap(); + sig2module = new HashMap(); + allModules = new ArrayList(); + exactSigs = new LinkedHashSet(); + globals = new LinkedHashMap(); + metaSig = new PrimSig("this/sig$", Attr.ABSTRACT, Attr.META); + metaField = new PrimSig("this/field$", Attr.ABSTRACT, Attr.META); + } else { + this.world = world; + new2old = world.new2old; + old2fields = world.old2fields; + old2appendedfacts = world.old2appendedfacts; + sig2module = world.sig2module; + allModules = world.allModules; + exactSigs = world.exactSigs; + globals = world.globals; + metaSig = world.metaSig; + metaField = world.metaField; + } + this.path = path; + if (filename!=null && filename.length()>0) this.modulePos=new Pos(filename,1,1); + } + + /** {@inheritDoc} */ + @Override public final Pos pos() { return modulePos; } + + /** {@inheritDoc} */ + @Override public final Pos span() { return modulePos; } + + /** {@inheritDoc} */ + @Override public String getHTML() { + StringBuilder sb = new StringBuilder("module ").append(path).append(" "); + Util.encodeXML(sb, modulePos.filename); + return sb.append("").toString(); + } + + /** {@inheritDoc} */ + @Override public List getSubnodes() { + ArrayList ans = new ArrayList(); + ArrayList x; + if (opens.size()>0) { + x = new ArrayList(opens.size()); + for(Open e: opens.values()) if (!x.contains(e.realModule)) x.add(e.realModule); + ans.add(make(""+x.size()+(x.size()>1?" opens":" open"), x)); + } + if (sigs.size()>0) { + x = new ArrayList(sigs.values()); + ans.add(make(""+x.size()+(x.size()>1?" sigs":" sig"), x)); + } + if (funcs.size()>0) { + ArrayList x2 = new ArrayList(funcs.size()); + x = new ArrayList(funcs.size()); + for(ArrayList e: funcs.values()) for(Func f: e) if (f.isPred) x.add(f); else x2.add(f); + if (x.size()>0) ans.add(make(""+x.size()+(x.size()>1?" preds":" pred"), x)); + if (x2.size()>0) ans.add(make(""+x2.size()+(x2.size()>1?" funs":" fun"), x2)); + } + if (commands.size()>0) { + ArrayList x2 = new ArrayList(commands.size()); + x = new ArrayList(commands.size()); + for(Command e: commands) if (e.check) x.add(e); else x2.add(e); + if (x.size()>0) ans.add(make(""+x.size()+(x.size()>1?" checks":" check"), x)); + if (x2.size()>0) ans.add(make(""+x2.size()+(x2.size()>1?" runs":" run"), x2)); + } + if (facts.size()>0) { + x = new ArrayList(facts.size()); + for(Pair e: facts) x.add(make(e.b.span(), e.b.span(), "fact " + e.a + "", e.b)); + ans.add(make(""+x.size()+(x.size()>1?" facts":" fact"), x)); + } + if (asserts.size()>0) { + x = new ArrayList(asserts.size()); + for(Map.Entry e: asserts.entrySet()) { + Pos sp = e.getValue().span(); + x.add(make(sp, sp, "assert "+e.getKey(), e.getValue())); + } + ans.add(make(""+x.size()+(x.size()>1?" asserts":" assert"), x)); + } + return ans; + } + + /** Returns the meta signature "sig$" (or null if such a sig does not exist) */ + public PrimSig metaSig() { return world.metaSig; } + + /** Returns the meta signature "field$" (or null if such a sig does not exist) */ + public PrimSig metaField() { return world.metaField; } + + private static String base(String string) { + int i = string.lastIndexOf('/'); + return i<0 ? string : string.substring(i+1); + } + + private static String base(Sig sig) { return base(sig.label); } + + /** Generate an error message saying the given keyword is no longer supported. */ + static ErrorSyntax hint (Pos pos, String name) { + String msg="The name \""+name+"\" cannot be found."; + if ("exh".equals(name) || "exhaustive".equals(name) || "part".equals(name) || "partition".equals(name)) + msg=msg+" If you are migrating from Alloy 3, please see Help->QuickGuide on how to translate models that use the \"" + +name+"\" keyword."; + return new ErrorSyntax(pos, msg); + } + + /** Parse one expression by starting fromt this module as the root module. */ + public Expr parseOneExpressionFromString(String input) throws Err, FileNotFoundException, IOException { + Map fc = new LinkedHashMap(); + fc.put("", "run {\n"+input+"}"); // We prepend the line "run{" + CompModule m = CompParser.alloy_parseStream(new ArrayList(), null, fc, null, -1, "", "", 1); + if (m.funcs.size()==0) throw new ErrorSyntax("The input does not correspond to an Alloy expression."); + Expr body = m.funcs.values().iterator().next().get(0).getBody(); + Context cx = new Context(this, null); + body = cx.check(body); + body = body.resolve(body.type(), null); + if (body.errors.size()>0) throw body.errors.pick(); else return body; + } + + /** Throw an exception if the name is already used, or has @ or /, or is univ/Int/none. */ + private void dup(Pos pos, String name, boolean checkSig) throws Err { + if (name.length()==0) throw new ErrorSyntax(pos, "Name cannot be empty"); + if (name.indexOf('@')>=0) throw new ErrorSyntax(pos, "Name cannot contain the \'@\' character"); + if (name.indexOf('/')>=0) throw new ErrorSyntax(pos, "Name cannot contain the \'/\' character"); + if (name.equals("univ")) throw new ErrorSyntax(pos, "\'univ\' is a reserved keyword."); + if (name.equals("Int")) throw new ErrorSyntax(pos, "\'Int\' is a reserved keyword."); + if (name.equals("none")) throw new ErrorSyntax(pos, "\'none\' is a reserved keyword."); + if (checkSig && (params.containsKey(name) || sigs.containsKey(name))) + throw new ErrorSyntax(pos, "\""+name+"\" is already the name of a sig/parameter in this module."); + } + + /** Throw an exception if there are more than 1 match; return nonnull if only one match; return null if no match. */ + private Object unique (Pos pos, String name, List objs) throws Err { + if (objs.size()==0) return null; + if (objs.size()==1) return objs.get(0); + StringBuilder msg = new StringBuilder("The name \"").append(name); + msg.append("\" is ambiguous.\n" + "There are ").append(objs.size()).append(" choices:"); + for(int i=0; i ans, Object key) { + if (visitedBy==key) return; + visitedBy=key; + ans.add(this); + for(Open i: opens.values()) if (!(level>0 && i.isPrivate)) { + CompModule m = i.realModule; + if (m!=null) m.getHelper(level<0 ? (-1) : (level+1), ans, key); + } + } + + /** Return the list containing THIS MODULE and all modules reachable from this module. */ + public SafeList getAllReachableModules() { + SafeList ans=new SafeList(); + getHelper(-1, ans, new Object()); // The object must be new, since we need it to be a unique key + return ans.dup(); + } + + /** Return the list of all relative filenames included from this MODULE. */ + public List getAllReachableModulesFilenames() { + Set set = new LinkedHashSet(); + for(Open o: opens.values()) set.add(o.filename); + return new ArrayList(set); + } + + /** Return the list containing THIS MODULE and all modules nameable from this module. */ + private SafeList getAllNameableModules() { + SafeList ans=new SafeList(); + getHelper(0, ans, new Object()); // The object must be new, since we need it to be a unique key + return ans.dup(); + } + + /** Return the list containing UNIV, SIGINT, SEQIDX, STRING, NONE, and all sigs defined in this module or a reachable submodule. */ + public ConstList getAllReachableSigs() { + TempList x = new TempList(); + x.add(UNIV); + x.add(SIGINT); + x.add(SEQIDX); + x.add(STRING); + x.add(NONE); + for(CompModule m:getAllReachableModules()) x.addAll(m.sigs.values()); + return x.makeConst(); + } + + /** Lookup non-fully-qualified Sig/Func/Assertion from the current module; it skips PARAMs. */ + private List getRawNQS (CompModule start, final int r, String name) { + // (r&1)!=0 => Sig, (r&2) != 0 => assertion, (r&4)!=0 => Func + List ans=new ArrayList(); + for(CompModule m:getAllNameableModules()) { + if ((r&1)!=0) { Sig x=m.sigs.get(name); if (x!=null) if (m==start || x.isPrivate==null) ans.add(x); } + if ((r&2)!=0) { Expr x=m.asserts.get(name); if (x!=null) ans.add(x); } + if ((r&4)!=0) { ArrayList x=m.funcs.get(name); if (x!=null) for(Func y:x) if (m==start || y.isPrivate==null) ans.add(y); } + } + return ans; + } + + /** Lookup a fully-qualified Sig/Func/Assertion from the current module; it skips PARAMs. */ + private List getRawQS (final int r, String name) { + // (r&1)!=0 => Sig, (r&2) != 0 => assertion, (r&4)!=0 => Func + List ans=new ArrayList(); + CompModule u=this; + if (name.startsWith("this/")) name=name.substring(5); + for(int level=0; ;level++) { + int i=name.indexOf('/'); + if (i<0) { + if ((r&1)!=0) { Sig x=u.sigs.get(name); if (x!=null) if (level==0 || x.isPrivate==null) ans.add(x); } + if ((r&2)!=0) { Expr x=u.asserts.get(name); if (x!=null) ans.add(x); } + if ((r&4)!=0) { ArrayList x=u.funcs.get(name); if (x!=null) for(Func y:x) if (level==0 || y.isPrivate==null) ans.add(y); } + if (ans.size()==0) return u.getRawNQS(this,r,name); // If nothing at this module, then do a non-qualified search from this module + return ans; + } + String alias=name.substring(0,i); + Open uu=u.opens.get(alias); + if (uu==null || uu.realModule==null) return ans; // may happen during the initial "module" + if (level>0 && uu.isPrivate) return ans; // that means the module is imported privately + u=uu.realModule; + name=name.substring(i+1); + } + } + + /** Lookup a Sig from the current module (and it will also search this.params) */ + private Sig getRawSIG (Pos pos, String name) throws Err { + List s; + Sig s2=null; + if (name.equals("sig$") || name.equals("field$")) if (world!=null) { + s2 = world.sigs.get(name); + if (s2!=null) return s2; + } + if (name.equals("univ")) return UNIV; + if (name.equals("Int")) return SIGINT; + if (name.equals("seq/Int")) return SEQIDX; + if (name.equals("String")) return STRING; + if (name.equals("none")) return NONE; + if (name.indexOf('/')<0) { + s=getRawNQS(this, 1, name); + s2=params.get(name); + } else { + if (name.startsWith("this/")) { name=name.substring(5); s2=params.get(name); } + s=getRawQS(1, name); + } + if (s2!=null && !s.contains(s2)) s.add(s2); + return (Sig) (unique(pos, name, s)); + } + + /** Returns a short description for this module. */ + @Override public String toString() { return "module{"+path+"}"; } + + //============================================================================================================================// + + /** Returns a pointer to the root module in this world. */ + public CompModule getRootModule() { return world; } + + /** Returns the text of the "MODULE" line at the top of the file; "unknown" if the line has not be parsed from the file yet. */ + public String getModelName() { return moduleName; } + + /** Returns an unmodifiable copy of the current list of OPEN statements. */ + public ConstList getOpens() { return ConstList.make(opens.values()); } + + /** Add the "MODULE" declaration. */ + void addModelName(Pos pos, String moduleName, List list) throws Err { + if (status>0) throw new ErrorSyntax(pos, + "The \"module\" declaration must occur at the top,\n" + "and can occur at most once."); + this.moduleName = moduleName; + this.modulePos = pos; + boolean nextIsExact = false; + if (list!=null) for(ExprVar expr: list) { + if (expr==null) { nextIsExact=true; continue; } + String name = expr.label; + dup(expr.span(), name, true); + if (path.length()==0) { + Sig newSig = addSig(name, null, null, null, null, WHERE.make(expr.span())); + if (nextIsExact) exactSigs.add(newSig); + } else { + params.put(name, null); + if (nextIsExact) exactParams.add(name); + } + nextIsExact=false; + } + this.status=1; // This line must be at the end, since "addSig" will otherwise bump the status value to 3 + } + + /** Add util/sequniv to the list of declarations. */ + void addSeq(Pos pos) throws Err { + int oldStatus = status; + status = 0; + try { + addOpen(pos, null, ExprVar.make(pos, "util/sequniv"), null, ExprVar.make(pos, "seq")); + } finally { + status = oldStatus; + } + } + + /** Add an OPEN declaration. */ + void addOpen(Pos pos, Pos isPrivate, ExprVar name, List args, ExprVar alias) throws Err { + if (status>2) throw new ErrorSyntax(pos, "The \"open\" declaration must occur before any\n" + "sig/pred/fun/fact/assert/check/run command."); + String as = (alias==null ? "" : alias.label); + if (name.label.length()==0) throw new ErrorSyntax(name.span(), "The filename cannot be empty."); + if (as.indexOf('$')>=0) throw new ErrorSyntax(alias==null ? null : alias.span(), "Alias must not contain the \'$\' character"); + if (as.indexOf('@')>=0) throw new ErrorSyntax(alias==null ? null : alias.span(), "Alias must not contain the \'@\' character"); + if (as.indexOf('/')>=0) throw new ErrorSyntax(alias==null ? null : alias.span(), "Alias must not contain the \'/\' character"); + if (as.length()==0) { + as="open$"+(1+opens.size()); + if (args==null || args.size()==0) { + for(int i=0; ; i++) { + if (i>=name.label.length()) { as=name.label; break; } + char c=name.label.charAt(i); + if ((c>='a' && c<='z') || (c>='A' && c<='Z')) continue; + if (i==0) break; + if (!(c>='0' && c<='9') && c!='_' && c!='\'' && c!='\"') break; + } + } + } + final TempList newlist = new TempList(args==null ? 0 : args.size()); + if (args!=null) for(int i=0; i=0) throw new ErrorSyntax(arg.span(), "Argument cannot contain the \'@\' chracter."); + newlist.add(arg.label); + } + Open x = opens.get(as); + if (x!=null) { + // we allow this, especially because of util/sequniv + if (x.args.equals(newlist.makeConst()) && x.filename.equals(name.label)) return; + throw new ErrorSyntax(pos, "You cannot import two different modules\n" + "using the same alias."); + } + x = new Open(pos, isPrivate!=null, as, newlist.makeConst(), name.label); + opens.put(as, x); + } + + /** Do any post-parsing processig. */ + void doneParsing() { + status = 3; + LinkedHashMap copy = new LinkedHashMap(opens); + opens.clear(); + for(Map.Entry e: copy.entrySet()) { + String a = e.getKey(); + Open m = e.getValue(); + if (a.indexOf('$')>=0) { + String base = m.filename; + int i = base.lastIndexOf('/'); + if (i>=0) base = base.substring(i+1); + if (!copy.containsKey(base) && !opens.containsKey(base)) { + for(i=0; i='a' && c<='z') || (c>='A' && c<='Z')) continue; + if (i!=0 && ((c>='0' && c<='9') || c=='_' || c=='\'' || c=='\"')) continue; + break; + } + if (i>=base.length()) a = base; + } + } + opens.put(a, new Open(m.pos, m.isPrivate, a, m.args, m.filename)); + } + } + + /** Every param in every module will now point to a nonnull Sig. */ + private static void resolveParams(A4Reporter rep, List modules) throws Err { + while(true) { + boolean chg=false; + Open missing=null; + String missingName=""; + for(CompModule mod: modules) for(Open open: mod.opens.values()) { + CompModule sub = open.realModule; + if (open.args.size()!=sub.params.size()) + throw new ErrorSyntax(open.pos, + "You supplied "+open.args.size()+" arguments to the open statement, but the imported module requires " + +sub.params.size()+" arguments."); + int i=0; + for(Map.Entry p: sub.params.entrySet()) { + Sig old = p.getValue(); + String kn = p.getKey(), vn = open.args.get(i); + i++; + Sig vv=mod.getRawSIG(open.pos, vn); + if (vv==null) {if (old==null) {missing=open; missingName=vn;} continue;} + if (old==vv) continue; + if (old!=null) throw new ErrorFatal(open.pos, "Internal error (module re-instantiated with different arguments)"); + if (vv==NONE) throw new ErrorSyntax(open.pos, "You cannot use \"none\" as an instantiating argument."); + chg=true; + p.setValue(vv); + rep.parse("RESOLVE: "+(sub.path.length()==0?"this/":sub.path)+"/"+kn+" := "+vv+"\n"); + } + } + if (!chg && missing==null) return; + if (!chg) throw new ErrorSyntax(missing.pos, "The signature name \""+missingName+"\" cannot be found."); + } + } + + /** Modules with same filename and instantiating arguments will be merged. */ + private static void resolveModules(A4Reporter rep, List modules) { + // Before merging, the only pointers that go between Module objects are + // (1) a module's "params" may point to a sig in another module + // (2) a module's "imports" may point to another module + // So when we find that two modules A and B should be merged, + // we go through every module and replace "pointers into B" with equivalent "pointers into A". + while(true) { + boolean chg=false; + for(int i=0; i=0)) if ((aa>=0 && bb<0) || Util.slashComparator.compare(a.path, b.path)>0) { + a=b; b=modules.get(i); modules.set(i,a); + } + modules.remove(j); + j--; + for(CompModule c:modules) { + for(Map.Entry p:c.params.entrySet()) + if (isin(p.getValue(), b.sigs)) p.setValue(a.sigs.get(base(p.getValue()))); + for(Open p: c.opens.values()) + if (p.realModule==b) p.realModule=a; + } + } + } + if (!chg) break; + } + } + + //============================================================================================================================// + + /** Add a sig declaration. */ + void addGhostSig() throws Err { + sigs.put(Sig.GHOST.label, Sig.GHOST); + } + + Sig addSig(String name, ExprVar par, List parents, List fields, Expr fact, Attr... attributes) throws Err { + Sig obj; + Pos pos = Pos.UNKNOWN.merge(WHERE.find(attributes)); + status = 3; + dup(pos, name, true); + String full = (path.length()==0) ? "this/"+name : path+"/"+name; + Pos subset=null, subsig=null; + boolean exact = false; + if (par!=null) { + if (par.label.equals("extends")) { subsig=par.span().merge(parents.get(0).span()); } + else { exact=!par.label.equals("in"); subset=par.span(); for(ExprVar p:parents) subset=p.span().merge(subset); } + } + attributes = Util.append(attributes, exact ? Attr.EXACT : null); + if (subset!=null) { + attributes = Util.append(attributes, SUBSET.makenull(subset)); + List newParents = new ArrayList(parents==null ? 0 : parents.size()); + if (parents!=null) for(ExprVar p: parents) newParents.add(new PrimSig(p.label, WHERE.make(p.pos))); + obj = new SubsetSig(full, newParents, attributes); + } else { + attributes = Util.append(attributes, SUBSIG.makenull(subsig)); + PrimSig newParent = (parents!=null && parents.size()>0) ? (new PrimSig(parents.get(0).label, WHERE.make(parents.get(0).pos))) : UNIV; + obj = new PrimSig(full, newParent, attributes); + } + sigs.put(name, obj); + old2fields.put(obj, fields); + old2appendedfacts.put(obj, fact); + return obj; + } + + /** Add an enumeration. */ + void addEnum(Pos pos, Pos priv, ExprVar name, List atoms, Pos closingBracket) throws Err { + ExprVar EXTENDS = ExprVar.make(null, "extends"); + ExprVar THIS = ExprVar.make(null, "this/"+name); + List THESE = Arrays.asList(THIS); + if (atoms==null || atoms.size()==0) throw new ErrorSyntax(pos, "Enumeration must contain at least one name."); + addSig(name.label, null, null, null, null, WHERE.make(name.pos), ABSTRACT.make(name.pos), PRIVATE.makenull(priv), Attr.ENUM); + for(ExprVar a:atoms) addSig(a.label, EXTENDS, THESE, null, null, WHERE.make(a.pos), ONE.make(a.pos), PRIVATE.makenull(priv)); + int oldStatus = status; + status = 0; + try { + addOpen(null, null, ExprVar.make(pos, "util/ordering"), Arrays.asList(THIS), null); + } finally { + status = oldStatus; + } + } + + /** The given Sig will now point to a nonnull Sig. */ + private static Sig resolveSig(CompModule res, Set topo, Sig oldS) throws Err { + if (res.new2old.containsKey(oldS)) return oldS; + Sig realSig; + final Pos pos = oldS.pos; + final CompModule u = res.sig2module.get(oldS); + final String name = base(oldS); + final String fullname = (u.path.length()==0) ? ("this/"+name) : (u.path+"/"+name); + if (!topo.add(oldS)) throw new ErrorType(pos, "Sig "+oldS+" is involved in a cyclic inheritance."); + if (oldS instanceof SubsetSig) { + List parents = new ArrayList(); + for(Sig n: ((SubsetSig)oldS).parents) { + Sig parentAST = u.getRawSIG(n.pos, n.label); + if (parentAST==null) throw new ErrorSyntax(n.pos, "The sig \""+n.label+"\" cannot be found."); + parents.add(resolveSig(res, topo, parentAST)); + } + realSig = new SubsetSig(fullname, parents, oldS.attributes.toArray(new Attr[0])); + } else { + Sig sup = ((PrimSig)oldS).parent; + Sig parentAST = u.getRawSIG(sup.pos, sup.label); + if (parentAST==null) throw new ErrorSyntax(sup.pos, "The sig \""+sup.label+"\" cannot be found."); + Sig parent = resolveSig(res, topo, parentAST); + if (!(parent instanceof PrimSig)) throw new ErrorSyntax(sup.pos, "Cannot extend the subset signature \"" + parent + + "\".\n" + "A signature can only extend a toplevel signature or a subsignature."); + PrimSig p = (PrimSig)parent; + realSig = new PrimSig(fullname, p, oldS.attributes.toArray(new Attr[0])); + } + res.new2old.put(realSig, oldS); + res.sig2module.put(realSig, u); + for(CompModule m: res.allModules) { + for(Map.Entry e: m.sigs.entrySet()) if (e.getValue()==oldS) e.setValue(realSig); + for(Map.Entry e: m.params.entrySet()) if (e.getValue()==oldS) e.setValue(realSig); + } + if (res.exactSigs.remove(oldS)) res.exactSigs.add(realSig); + return realSig; + } + + /** Returns an unmodifiable list of all signatures defined inside this module. */ + public SafeList getAllSigs() { + SafeList x = new SafeList(sigs.values()); + return x.dup(); + } + + //============================================================================================================================// + + /** Add a MACRO declaration. */ + void addMacro(Pos p, Pos isPrivate, String n, List decls, Expr v) throws Err { + if (!Version.experimental) throw new ErrorSyntax(p, "LET declaration is allowed only inside a toplevel paragraph."); + ConstList ds = ConstList.make(decls); + status=3; + dup(p, n, false); + for(int i=0; i decls, Expr t, Expr v) throws Err { + if (decls==null) decls=new ArrayList(); else decls=new ArrayList(decls); + if (f!=null) decls.add(0, new Decl(null, null, null, Util.asList(ExprVar.make(f.span(), "this")), f)); + for(Decl d:decls) { + if (d.isPrivate!=null) { + ExprHasName name = d.names.get(0); + throw new ErrorSyntax(d.isPrivate.merge(name.pos), "Function parameter \""+name.label+"\" is always private already."); + } + if (d.disjoint2!=null) { + ExprHasName name = d.names.get(d.names.size()-1); + throw new ErrorSyntax(d.disjoint2.merge(name.pos), "Function parameter \""+name.label+"\" cannot be bound to a 'disjoint' expression."); + } + } + status=3; + dup(p, n, false); + ExprHasName dup = Decl.findDuplicateName(decls); + if (dup!=null) throw new ErrorSyntax(dup.span(), "The parameter name \""+dup.label+"\" cannot appear more than once."); + Func ans = new Func(p, isPrivate, n, decls, t, v); + ArrayList list = funcs.get(n); + if (list==null) { list = new ArrayList(); funcs.put(n, list); } + list.add(ans); + } + + /** Each FunAST will now point to a bodyless Func object. */ + private JoinableList resolveFuncDecls(A4Reporter rep, JoinableList errors, List warns) throws Err { + for(ArrayList list: funcs.values()) { + for(int listi=0; listi tmpdecls = new TempList(); + boolean err = false; + for(Decl d: f.decls) { + TempList tmpvars = new TempList(); + Expr val = cx.check(d.expr).resolve_as_set(warns); + if (!val.errors.isEmpty()) { err = true; errors = errors.make(val.errors); } + for(ExprHasName n: d.names) { + ExprVar v = ExprVar.make(n.span(), n.label, val.type()); + cx.put(n.label, v); + tmpvars.add(v); + rep.typecheck((f.isPred?"pred ":"fun ")+fullname+", Param "+n.label+": "+v.type()+"\n"); + } + tmpdecls.add(new Decl(d.isPrivate, d.disjoint, d.disjoint2, tmpvars.makeConst(), val)); + } + Expr ret = null; + if (!f.isPred) { + ret = cx.check(f.returnDecl).resolve_as_set(warns); + if (!ret.errors.isEmpty()) { err = true; errors = errors.make(ret.errors); } + } + if (err) continue; + try { + f = new Func(f.pos, f.isPrivate, fullname, tmpdecls.makeConst(), ret, f.getBody()); + list.set(listi, f); + rep.typecheck("" + f + ", RETURN: " + f.returnDecl.type() + "\n"); + } catch(Err ex) { errors = errors.make(ex); } + } + } + return errors; + } + + /** Each Func's body will now be typechecked Expr object. */ + private JoinableList resolveFuncBody(A4Reporter rep, JoinableList errors, List warns) throws Err { + for(ArrayList entry: funcs.values()) for(Func ff: entry) { + Context cx = new Context(this, warns); + cx.rootfunbody = ff; + for(Decl d: ff.decls) for(ExprHasName n: d.names) cx.put(n.label, n); + Expr newBody = cx.check(ff.getBody()); + if (ff.isPred) + newBody = newBody.resolve_as_formula(warns); + else + newBody = newBody.resolve_as_set(warns); + errors = errors.make(newBody.errors); + if (!newBody.errors.isEmpty()) continue; + try { ff.setBody(newBody); } catch(Err er) {errors = errors.make(er); continue;} + if (warns!=null && ff.returnDecl.type().hasTuple() && newBody.type().hasTuple() && !newBody.type().intersects(ff.returnDecl.type())) + warns.add(new ErrorWarning(newBody.span(), + "Function return value is disjoint from its return type.\n" + +"Function body has type "+newBody.type() + "\n" + "but the return type is "+ff.returnDecl.type())); + //else if (warns!=null && Version.experimental && !newBody.type.isSubtypeOf(ff.returnDecl.type)) + // warns.add(new ErrorWarning(newBody.span(), + // "Function may return a tuple not in its declared return type.\n" + // +"The Alloy Analyzer's analysis may be unsound\n" + // +"if it returns a tuple outside its declared return type.\n" + // +"Function body has type "+newBody.type+"\nbut the return type is "+ff.returnDecl.type)); + rep.typecheck(ff.toString()+", BODY:"+newBody.type()+"\n"); + } + return errors; + } + + /** Return an unmodifiable list of all functions in this module. */ + public SafeList getAllFunc() { + SafeList ans = new SafeList(); + for(ArrayList e: funcs.values()) ans.addAll(e); + return ans.dup(); + } + + //============================================================================================================================// + + /** Add an ASSERT declaration. */ + String addAssertion(Pos pos, String name, Expr value) throws Err { + status=3; + if (name==null || name.length()==0) name="assert$"+(1+asserts.size()); + dup(pos, name, false); + Expr old = asserts.put(name, ExprUnary.Op.NOOP.make(value.span().merge(pos), value)); + if (old!=null) { + asserts.put(name, old); + throw new ErrorSyntax(pos, "\""+name+"\" is already the name of an assertion in this module."); + } + return name; + } + + /** Each assertion name now points to a typechecked Expr rather than an untypechecked Exp. */ + private JoinableList resolveAssertions(A4Reporter rep, JoinableList errors, List warns) throws Err { + Context cx = new Context(this, warns); + for(Map.Entry e: asserts.entrySet()) { + Expr expr = e.getValue(); + expr = cx.check(expr).resolve_as_formula(warns); + if (expr.errors.isEmpty()) { + e.setValue(expr); + rep.typecheck("Assertion " + e.getKey() + ": " + expr.type()+"\n"); + } else errors = errors.make(expr.errors); + } + return errors; + } + + /** Return an unmodifiable list of all assertions in this module. */ + public ConstList> getAllAssertions() { + TempList> ans = new TempList>(asserts.size()); + for(Map.Entry e: asserts.entrySet()) { + ans.add(new Pair(e.getKey(), e.getValue())); + } + return ans.makeConst(); + } + + //============================================================================================================================// + + /** Add a FACT declaration. */ + void addFact(Pos pos, String name, Expr value) throws Err { + status=3; + if (name==null || name.length()==0) name="fact$"+(1+facts.size()); + facts.add(new Pair(name, ExprUnary.Op.NOOP.make(value.span().merge(pos), value))); + } + + /** Each fact name now points to a typechecked Expr rather than an untypechecked Exp; we'll also add the sig appended facts. */ + private JoinableList resolveFacts(CompModule res, A4Reporter rep, JoinableList errors, List warns) throws Err { + Context cx = new Context(this, warns); + for(int i=0; i(name, expr)); + rep.typecheck("Fact " + name + ": " + expr.type()+"\n"); + } else errors = errors.make(expr.errors); + } + for(Sig s: sigs.values()) { + Expr f = res.old2appendedfacts.get(res.new2old.get(s)); + if (f == null) continue; + if (f instanceof ExprConstant && ((ExprConstant)f).op==ExprConstant.Op.TRUE) continue; + Expr formula; + cx.rootsig = s; + if (s.isOne==null) { + cx.put("this", s.decl.get()); + formula = cx.check(f).resolve_as_formula(warns); + } else { + cx.put("this", s); + formula = cx.check(f).resolve_as_formula(warns); + } + cx.remove("this"); + if (formula.errors.size()>0) errors = errors.make(formula.errors); else { s.addFact(formula); rep.typecheck("Fact "+s+"$fact: " + formula.type()+"\n"); } + } + return errors; + } + + /** Return an unmodifiable list of all facts in this module. */ + public SafeList> getAllFacts() { + return (new SafeList>(facts)).dup(); + } + + /** Return the conjunction of all facts in this module and all reachable submodules (not including field constraints, nor including sig appended constraints) */ + public Expr getAllReachableFacts() { + ArrayList facts = new ArrayList(); + for(CompModule m: world.getAllReachableModules()) for(Pair f: m.facts) facts.add(f.b); + if (facts.size()==0) return ExprConstant.TRUE; else return ExprList.make(null, null, ExprList.Op.AND, facts); + } + + //============================================================================================================================// + + /** Add a COMMAND declaration. */ + void addCommand(boolean followUp, Pos p, String n, boolean c, int o, int b, int seq, int exp, List s, ExprVar label) throws Err { + if (followUp && !Version.experimental) throw new ErrorSyntax(p, "Syntax error encountering => symbol."); + if (label!=null) p=Pos.UNKNOWN.merge(p).merge(label.pos); + status=3; + if (n.length()==0) throw new ErrorSyntax(p, "Predicate/assertion name cannot be empty."); + if (n.indexOf('@')>=0) throw new ErrorSyntax(p, "Predicate/assertion name cannot contain \'@\'"); + String labelName = (label==null || label.label.length()==0) ? n : label.label; + Command parent = followUp ? commands.get(commands.size()-1) : null; + Command newcommand = new Command(p, labelName, c, o, b, seq, exp, s, null, ExprVar.make(null, n), parent); + if (parent!=null) commands.set(commands.size()-1, newcommand); else commands.add(newcommand); + } + + /** Add a COMMAND declaration. */ + void addCommand(boolean followUp, Pos p, Expr e, boolean c, int o, int b, int seq, int exp, List s, ExprVar label) throws Err { + if (followUp && !Version.experimental) throw new ErrorSyntax(p, "Syntax error encountering => symbol."); + if (label!=null) p=Pos.UNKNOWN.merge(p).merge(label.pos); + status=3; + String n; + if (c) n=addAssertion(p,"check$"+(1+commands.size()),e); + else addFunc(e.span().merge(p), Pos.UNKNOWN, n="run$"+(1+commands.size()), null, new ArrayList(), null, e); + String labelName = (label==null || label.label.length()==0) ? n : label.label; + Command parent = followUp ? commands.get(commands.size()-1) : null; + Command newcommand = new Command(e.span().merge(p), labelName, c, o, b, seq, exp, s, null, ExprVar.make(null, n), parent); + if (parent!=null) commands.set(commands.size()-1, newcommand); else commands.add(newcommand); + } + + /** Resolve a particular command. */ + private Command resolveCommand(Command cmd, ConstList exactSigs, Expr globalFacts) throws Err { + Command parent = cmd.parent==null ? null : resolveCommand(cmd.parent, exactSigs, globalFacts); + String cname = ((ExprVar)(cmd.formula)).label; + Expr e; + if (cmd.check) { + List m = getRawQS(2, cname); // We prefer assertion in the topmost module + if (m.size()==0 && cname.indexOf('/')<0) m=getRawNQS(this, 2, cname); + if (m.size()>1) unique(cmd.pos, cname, m); + if (m.size()<1) throw new ErrorSyntax(cmd.pos, "The assertion \""+cname+"\" cannot be found."); + e = ((Expr)(m.get(0))).not(); + } else { + List m = getRawQS(4, cname); // We prefer fun/pred in the topmost module + if (m.size()==0 && cname.indexOf('/')<0) m=getRawNQS(this, 4, cname); + if (m.size()>1) unique(cmd.pos, cname, m); + if (m.size()<1) throw new ErrorSyntax(cmd.pos, "The predicate/function \""+cname+"\" cannot be found."); + Func f = (Func) (m.get(0)); + e = f.getBody(); + if (!f.isPred) e = e.in(f.returnDecl); + if (f.decls.size()>0) e = ExprQt.Op.SOME.make(null, null, f.decls, e); + } + if (e==null) e = ExprConstant.TRUE; + TempList sc=new TempList(cmd.scope.size()); + for(CommandScope et: cmd.scope) { + Sig s = getRawSIG(et.sig.pos, et.sig.label); + if (s==null) throw new ErrorSyntax(et.sig.pos, "The sig \""+et.sig.label+"\" cannot be found."); + sc.add(new CommandScope(null, s, et.isExact, et.startingScope, et.endingScope, et.increment)); + } + return new Command(cmd.pos, cmd.label, cmd.check, cmd.overall, cmd.bitwidth, cmd.maxseq, cmd.expects, sc.makeConst(), exactSigs, globalFacts.and(e), parent); + } + + /** Each command now points to a typechecked Expr. */ + private void resolveCommands(Expr globalFacts) throws Err { + ConstList exactSigs = ConstList.make(world.exactSigs); + for(int i=0; i getAllCommands() { return ConstList.make(commands); } + + //============================================================================================================================// + + /** Returns true if exists some entry (a,b) in the map, such that b==value (using object identity as the comparison) */ + private static boolean isin(V value, Map map) { + for(V v: map.values()) if (v==value) return true; + return false; + } + + //============================================================================================================================// + + private static void resolveFieldDecl(CompModule res, final A4Reporter rep, final Sig s, final List warns, boolean defined) throws Err { + // When typechecking each field: + // * it is allowed to refer to earlier fields in the same SIG or in any visible ancestor sig + // * it is allowed to refer to visible sigs + // * it is NOT allowed to refer to any predicate or function + // For example, if A.als opens B.als, and B/SIGX extends A/SIGY, + // then B/SIGX's fields cannot refer to A/SIGY, nor any fields in A/SIGY) + final List oldDecls = res.old2fields.get(res.new2old.get(s)); + if (oldDecls==null) return; + final CompModule m = res.sig2module.get(s); + final Context cx = new Context(m, warns); + final ExprHasName dup = Decl.findDuplicateName(oldDecls); + if (dup!=null) throw new ErrorSyntax(dup.span(), "sig \""+s+"\" cannot have 2 fields named \""+dup.label+"\""); + for(final Decl d: oldDecls) { + if (d.expr.mult()!=ExprUnary.Op.EXACTLYOF) {if (defined) continue;} else {if (!defined) continue;} + // The name "this" does matter, since the parser and the typechecker both refer to it as "this" + cx.rootfield = d; + cx.rootsig = s; + cx.put("this", s.decl.get()); + Expr bound = cx.check(d.expr).resolve_as_set(warns); + cx.remove("this"); + String[] names = new String[d.names.size()]; for(int i=0; i modules) throws Err { + // The Alloy language forbids two overlapping sigs from having fields with the same name. + // In other words: if 2 fields have the same name, then their type's first column must not intersect. + final Map> fieldname2fields=new LinkedHashMap>(); + for(CompModule m: modules) { + for(Sig sig: m.sigs.values()) { + for(Field field: sig.getFields()) { + List peers=fieldname2fields.get(field.label); + if (peers==null) { peers=new ArrayList(); fieldname2fields.put(field.label, peers); } + for(Field field2: peers) + if (field.type().firstColumnOverlaps(field2.type())) + throw new ErrorType(field.pos, + "Two overlapping signatures cannot have\n" + "two fields with the same name \""+field.label + +"\":\n\n1) one is in sig \""+field.sig+"\"\n"+field.pos + +"\n\n2) the other is in sig \""+field2.sig+"\"\n"+field2.pos); + peers.add(field); + } + } + } + } + + //============================================================================================================================// + + private static void resolveMeta(final CompModule root) throws Err { + // Now, add the meta sigs and fields if needed + Map sig2meta = new LinkedHashMap(); + Map field2meta = new LinkedHashMap(); + boolean hasMetaSig = false, hasMetaField = false; + root.new2old.put(root.metaSig, root.metaSig); root.sigs.put(base(root.metaSig), root.metaSig); + root.new2old.put(root.metaField, root.metaField); root.sigs.put(base(root.metaField), root.metaField); + for(CompModule m: root.allModules) for(Sig s: new ArrayList(m.sigs.values())) if (m!=root || (s!=root.metaSig && s!=root.metaField)) { + PrimSig ka = new PrimSig(s.label+"$", root.metaSig, Attr.ONE, PRIVATE.makenull(s.isPrivate), Attr.META); + sig2meta.put(s, ka); + ka.addDefinedField(Pos.UNKNOWN, null, Pos.UNKNOWN, "value", s); + m.new2old.put(ka, ka); + m.sigs.put(base(ka), ka); + hasMetaSig = true; + Expr allfields = ExprConstant.EMPTYNESS; + for(Field field: s.getFields()) { + Pos priv = field.isPrivate; if (priv==null) priv = s.isPrivate; + PrimSig kb = new PrimSig(s.label+"$"+field.label, root.metaField, Attr.ONE, PRIVATE.makenull(priv), Attr.META); + field2meta.put(field, kb); + m.new2old.put(kb, kb); + m.sigs.put(base(kb), kb); + hasMetaField = true; + kb.addDefinedField(Pos.UNKNOWN, null, Pos.UNKNOWN, "value", field); + if (allfields==ExprConstant.EMPTYNESS) allfields = kb; else allfields = allfields.plus(kb); + } + ka.addDefinedField(Pos.UNKNOWN, null, Pos.UNKNOWN, "fields", allfields); + } + for(Map.Entry e: sig2meta.entrySet()) { + Expr expr = null; + if ((e.getKey()) instanceof PrimSig) { + PrimSig a = (PrimSig)(e.getKey()); + if (a.parent!=null && a.parent!=UNIV) expr = sig2meta.get(a.parent); + } + e.getValue().addDefinedField(Pos.UNKNOWN, null, Pos.UNKNOWN, "parent", (expr==null ? ExprConstant.EMPTYNESS : expr)); + } + for(Map.Entry e: sig2meta.entrySet()) { + Sig s = e.getKey(); + PrimSig s2 = e.getValue(); + Expr allfields = ExprConstant.EMPTYNESS; + for(Field f: s.getFields()) { + PrimSig metaF = field2meta.get(f); + if (allfields==ExprConstant.EMPTYNESS) allfields = metaF; else allfields = allfields.plus(metaF); + } + if (s instanceof PrimSig) for(Sig c: (((PrimSig)s).descendents())) for(Field f: c.getFields()) { + PrimSig metaF = field2meta.get(f); + if (allfields==ExprConstant.EMPTYNESS) allfields = metaF; else allfields = allfields.plus(metaF); + } + s2.addDefinedField(Pos.UNKNOWN, null, Pos.UNKNOWN, "subfields", allfields); + } + if (hasMetaSig==false) root.facts.add(new Pair("sig$fact", root.metaSig.no().and(root.metaField.no()))); + else if (hasMetaField==false) root.facts.add(new Pair("sig$fact", root.metaField.no())); + } + + //============================================================================================================================// + + /** This method resolves the entire world; NOTE: if it throws an exception, it may leave the world in an inconsistent state! */ + static CompModule resolveAll(final A4Reporter rep, final CompModule root) throws Err { + final List warns = new ArrayList(); + for(CompModule m: root.getAllReachableModules()) root.allModules.add(m); + resolveParams(rep, root.allModules); + resolveModules(rep, root.allModules); + for(CompModule m: root.allModules) for(Sig s: m.sigs.values()) root.sig2module.put(s, m); + // Resolves SigAST -> Sig, and topologically sort the sigs into the "sorted" array + root.new2old.put(UNIV,UNIV); + root.new2old.put(SIGINT,SIGINT); + root.new2old.put(SEQIDX,SEQIDX); + root.new2old.put(STRING,STRING); + root.new2old.put(NONE,NONE); + HashSet topo = new HashSet(); + for(CompModule m: root.allModules) for(Sig s: m.sigs.values()) resolveSig(root, topo, s); + // Add the non-defined fields to the sigs in topologically sorted order (since fields in subsigs are allowed to refer to parent's fields) + for(Sig oldS: root.new2old.keySet()) resolveFieldDecl(root, rep, oldS, warns, false); + // Typecheck the function declarations + JoinableList errors = new JoinableList(); + for(CompModule x: root.allModules) errors = x.resolveFuncDecls(rep, errors, warns); + if (!errors.isEmpty()) throw errors.pick(); + // Typecheck the defined fields + for(Sig oldS: root.new2old.keySet()) resolveFieldDecl(root, rep, oldS, warns, true); + if (Version.experimental && root.seenDollar) resolveMeta(root); + // Reject name clash + rejectNameClash(root.allModules); + // Typecheck the function bodies, assertions, and facts (which can refer to function declarations) + for(CompModule x: root.allModules) { + errors = x.resolveFuncBody(rep, errors, warns); + errors = x.resolveAssertions(rep, errors, warns); + errors = x.resolveFacts(root, rep, errors, warns); + // also, we can collect up all the exact sigs and add them to the root module's list of exact sigs + for(String n: x.exactParams) { Sig sig = x.params.get(n); if (sig!=null) root.exactSigs.add(sig); } + } + if (!errors.isEmpty()) throw errors.pick(); + // Typecheck the run/check commands (which can refer to function bodies and assertions) + root.resolveCommands(root.getAllReachableFacts()); + if (!errors.isEmpty()) throw errors.pick(); + for(ErrorWarning w:warns) rep.warning(w); + for(Sig s: root.exactSigs) rep.debug("Forced to be exact: "+s+"\n"); + return root; + } + + //============================================================================================================================// + + /** Add a global expression; if the name already exists, it is removed first. */ + public void addGlobal(String name, Expr value) { + globals.put(name, value); + } + + /** Resolve the name based on the current context and this module. */ + private Expr populate(TempList ch, TempList re, Decl rootfield, Sig rootsig, boolean rootfunparam, Func rootfunbody, Pos pos, String fullname, Expr THIS) { + // Return object can be Func(with > 0 arguments) or Expr + final String name = (fullname.charAt(0)=='@') ? fullname.substring(1) : fullname; + boolean fun = (rootsig!=null && (rootfield==null || rootfield.expr.mult()==ExprUnary.Op.EXACTLYOF)) + || (rootsig==null && !rootfunparam); + if (name.equals("univ")) return ExprUnary.Op.NOOP.make(pos, UNIV); + if (name.equals("Int")) return ExprUnary.Op.NOOP.make(pos, SIGINT); + if (name.equals("seq/Int")) return ExprUnary.Op.NOOP.make(pos, SEQIDX); + if (name.equals("String")) return ExprUnary.Op.NOOP.make(pos, STRING); + if (name.equals("none")) return ExprUnary.Op.NOOP.make(pos, NONE); + if (name.equals("iden")) return ExprConstant.Op.IDEN.make(pos, 0); + if (name.equals("sig$") || name.equals("field$")) if (world!=null) { + Sig s = world.sigs.get(name); + if (s!=null) return ExprUnary.Op.NOOP.make(pos, s); + } + final List ans = name.indexOf('/')>=0 ? getRawQS(fun?5:1, name) : getRawNQS(this, fun?5:1, name); + final Sig param = params.get(name); if (param!=null && !ans.contains(param)) ans.add(param); + for(Object x: ans) { + if (x instanceof Sig) { + Sig y = (Sig)x; + ch.add(ExprUnary.Op.NOOP.make(pos, y, null, 0)); + re.add("sig "+y.label); + } + else if (x instanceof Func) { + Func f = (Func)x; + int fn = f.count(); + int penalty = 0; + if (resolution==1 && fn>0 && rootsig!=null && THIS!=null && THIS.type().hasArity(1) && f.get(0).type().intersects(THIS.type())) { + // If we're inside a sig, and there is a unary variable bound to "this", + // we should consider it as a possible FIRST ARGUMENT of a fun/pred call + ConstList t = Util.asList(THIS); + ch.add(fn==1 ? ExprCall.make(pos, null, f, t, 1+penalty) : ExprBadCall.make(pos, null, f, t, 1+penalty)); // penalty of 1 + re.add((f.isPred?"pred this.":"fun this.")+f.label); + } + if (resolution==1) { + ch.add(fn==0 ? ExprCall.make(pos, null, f, null, penalty) : ExprBadCall.make(pos, null, f, null, penalty)); + re.add((f.isPred?"pred ":"fun ")+f.label); + } + if (resolution==2 && f!=rootfunbody && THIS!=null && fullname.charAt(0)!='@' && fn>0 && f.get(0).type().intersects(THIS.type())) { + // If there is some value bound to "this", we should consider it as a possible FIRST ARGUMENT of a fun/pred call + ConstList t = Util.asList(THIS); + ch.add(fn==1 ? ExprCall.make(pos, null, f, t, 0) : ExprBadCall.make(pos, null, f, t, 0)); + re.add((f.isPred?"pred this.":"fun this.")+f.label); + } + if (resolution!=1) { + ch.add(fn==0 ? ExprCall.make(pos, null, f, null, 0) : ExprBadCall.make(pos, null, f, null, 0)); + re.add((f.isPred?"pred ":"fun ")+f.label); + } + } + } + // Within a field decl + // (1) Can refer to any visible sig/param (but you cannot call any function or predicates) + // (2) Can refer to field in this sig (defined earlier than you), and fields in any visible ancestor sig + // Within an appended facts + // (1) Can refer to any visible sig/param/func/predicate + // (2) Can refer to any visible field + // Within a function paramDecl/returnDecl + // (1) Cannot call + // (2) But can refer to anything else visible. + // All else: we can call, and can refer to anything visible. + for(CompModule m: getAllNameableModules()) + for(Sig s: m.sigs.values()) if (m==this || s.isPrivate==null) + for(Field f: s.getFields()) if (f.isMeta==null && (m==this || f.isPrivate==null) && f.label.equals(name)) + if (resolution==1) { + Expr x=null; + if (rootsig==null) + { x=ExprUnary.Op.NOOP.make(pos, f, null, 0); } + else if (rootsig.isSameOrDescendentOf(f.sig)) + { x=ExprUnary.Op.NOOP.make(pos, f, null, 0); if (fullname.charAt(0)!='@') x=THIS.join(x); } + else if (rootfield==null || rootfield.expr.mult()==ExprUnary.Op.EXACTLYOF) + { x=ExprUnary.Op.NOOP.make(pos, f, null, 1); } // penalty of 1 + if (x!=null) { ch.add(x); re.add("field "+f.sig.label+" <: "+f.label); } + } else if (rootfield==null || rootsig.isSameOrDescendentOf(f.sig)) { + Expr x0 = ExprUnary.Op.NOOP.make(pos, f, null, 0); + if (resolution==2 && THIS!=null && fullname.charAt(0)!='@' && f.type().firstColumnOverlaps(THIS.type())) { + ch.add(THIS.join(x0)); + re.add("field "+f.sig.label+" <: this."+f.label); + if (rootsig!=null) continue; + } + ch.add(x0); + re.add("field "+f.sig.label+" <: "+f.label); + } + if (metaSig()!=null && (rootsig==null || rootfield==null)) { + SafeList children = null; + try { children=metaSig().children(); } catch(Err err) { return null; } // exception NOT possible + for(PrimSig s:children) for(Field f:s.getFields()) if (f.label.equals(name)) { + Expr x=ExprUnary.Op.NOOP.make(pos, f, null, 0); ch.add(x); re.add("field "+f.sig.label+" <: "+f.label); + } + } + if (metaField()!=null && (rootsig==null || rootfield==null)) { + SafeList children = null; + try { children=metaField().children(); } catch(Err err) { return null; } // exception NOT possible + for(PrimSig s:children) for(Field f:s.getFields()) if (f.label.equals(name)) { + Expr x=ExprUnary.Op.NOOP.make(pos, f, null, 0); ch.add(x); re.add("field "+f.sig.label+" <: "+f.label); + } + } + return null; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/CompParser.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/CompParser.java new file mode 100644 index 00000000..0ecc13ce --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/CompParser.java @@ -0,0 +1,7836 @@ + +//---------------------------------------------------- +// The following code was generated by CUP v0.11a beta 20060608 +// Tue Nov 08 16:09:13 EST 2011 +//---------------------------------------------------- + +package edu.mit.csail.sdg.alloy4compiler.parser; + +import java.util.Stack; +import java.util.List; +import java.util.ArrayList; +import java.util.TreeSet; +import java.util.Map; +import java.util.LinkedHashMap; +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.Reader; +import java.io.IOException; +import java.io.StringReader; +import java_cup.runtime.*; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.alloy4compiler.ast.Attr.AttrType; +import edu.mit.csail.sdg.alloy4compiler.ast.CommandScope; +import edu.mit.csail.sdg.alloy4compiler.ast.Decl; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprBadJoin; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprITE; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprLet; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprBinary; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprList; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprConstant; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprQt; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprUnary; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; + +/** CUP v0.11a beta 20060608 generated parser. + * @version Tue Nov 08 16:09:13 EST 2011 + */ +public class CompParser extends java_cup.runtime.lr_parser { + + /** Default constructor. */ + public CompParser() {super();} + + /** Constructor which sets the default scanner. */ + public CompParser(java_cup.runtime.Scanner s) {super(s);} + + /** Constructor which sets the default scanner. */ + public CompParser(java_cup.runtime.Scanner s, java_cup.runtime.SymbolFactory sf) {super(s,sf);} + + /** Production table. */ + protected static final short _production_table[][] = + unpackFromStrings(new String[] { + "\000\u015e\000\002\106\003\000\002\002\004\000\002\107" + + "\005\000\002\107\010\000\002\107\006\000\002\107\010" + + "\000\002\107\011\000\002\107\013\000\002\107\011\000" + + "\002\107\010\000\002\107\005\000\002\107\006\000\002" + + "\107\006\000\002\107\005\000\002\107\006\000\002\107" + + "\006\000\002\107\004\000\002\107\004\000\002\107\004" + + "\000\002\107\004\000\002\107\004\000\002\107\002\000" + + "\002\013\003\000\002\013\003\000\002\012\007\000\002" + + "\012\006\000\002\012\011\000\002\012\010\000\002\012" + + "\007\000\002\012\006\000\002\012\011\000\002\012\010" + + "\000\002\027\002\000\002\027\004\000\002\075\004\000" + + "\002\075\006\000\002\075\004\000\002\075\002\000\002" + + "\112\003\000\002\112\005\000\002\111\004\000\002\111" + + "\004\000\002\111\004\000\002\111\004\000\002\111\004" + + "\000\002\111\004\000\002\111\004\000\002\110\004\000" + + "\002\110\007\000\002\110\011\000\002\110\006\000\002" + + "\110\003\000\002\110\006\000\002\110\010\000\002\110" + + "\005\000\002\051\011\000\002\051\010\000\002\051\011" + + "\000\002\051\010\000\002\051\006\000\002\052\003\000" + + "\002\052\004\000\002\037\013\000\002\037\013\000\002" + + "\037\010\000\002\037\015\000\002\037\015\000\002\037" + + "\012\000\002\067\011\000\002\067\011\000\002\067\006" + + "\000\002\067\013\000\002\067\013\000\002\067\010\000" + + "\002\123\002\000\002\123\003\000\002\076\011\000\002" + + "\100\003\000\002\100\003\000\002\100\003\000\002\100" + + "\003\000\002\100\003\000\002\101\003\000\002\101\004" + + "\000\002\077\004\000\002\077\004\000\002\077\004\000" + + "\002\077\002\000\002\102\003\000\002\102\003\000\002" + + "\102\003\000\002\102\003\000\002\102\005\000\002\102" + + "\003\000\002\104\002\000\002\104\003\000\002\103\003" + + "\000\002\103\005\000\002\105\003\000\002\105\005\000" + + "\002\053\003\000\002\053\005\000\002\053\005\000\002" + + "\054\003\000\002\054\005\000\002\055\003\000\002\055" + + "\005\000\002\056\003\000\002\056\004\000\002\056\005" + + "\000\002\056\006\000\002\014\006\000\002\014\006\000" + + "\002\014\006\000\002\014\007\000\002\014\006\000\002" + + "\014\005\000\002\014\007\000\002\014\007\000\002\014" + + "\007\000\002\014\010\000\002\014\007\000\002\014\006" + + "\000\002\015\003\000\002\015\006\000\002\015\006\000" + + "\002\015\006\000\002\015\007\000\002\015\006\000\002" + + "\015\005\000\002\015\007\000\002\015\007\000\002\015" + + "\007\000\002\015\010\000\002\015\007\000\002\015\006" + + "\000\002\020\005\000\002\020\003\000\002\016\005\000" + + "\002\016\003\000\002\017\002\000\002\017\003\000\002" + + "\017\005\000\002\017\004\000\002\050\006\000\002\050" + + "\007\000\002\032\002\000\002\032\003\000\002\031\005" + + "\000\002\031\004\000\002\033\003\000\002\033\004\000" + + "\002\034\004\000\002\034\003\000\002\035\002\000\002" + + "\035\003\000\002\036\003\000\002\036\005\000\002\030" + + "\003\000\002\030\003\000\002\030\003\000\002\005\004" + + "\000\002\005\005\000\002\005\005\000\002\005\005\000" + + "\002\005\005\000\002\005\005\000\002\005\005\000\002" + + "\063\003\000\002\063\005\000\002\064\003\000\002\064" + + "\005\000\002\025\003\000\002\025\005\000\002\026\003" + + "\000\002\026\005\000\002\040\003\000\002\040\003\000" + + "\002\042\003\000\002\042\007\000\002\044\007\000\002" + + "\044\005\000\002\042\007\000\002\044\005\000\002\041" + + "\003\000\002\041\003\000\002\043\003\000\002\043\007" + + "\000\002\045\007\000\002\045\005\000\002\002\003\000" + + "\002\002\005\000\002\003\003\000\002\003\005\000\002" + + "\057\003\000\002\057\004\000\002\057\004\000\002\060" + + "\003\000\002\060\004\000\002\010\005\000\002\010\005" + + "\000\002\010\005\000\002\010\005\000\002\010\005\000" + + "\002\010\005\000\002\010\005\000\002\010\005\000\002" + + "\010\005\000\002\010\005\000\002\010\005\000\002\010" + + "\005\000\002\010\004\000\002\010\004\000\002\010\004" + + "\000\002\010\004\000\002\010\004\000\002\010\004\000" + + "\002\010\004\000\002\010\003\000\002\011\005\000\002" + + "\011\005\000\002\011\005\000\002\011\005\000\002\011" + + "\005\000\002\011\005\000\002\011\005\000\002\011\005" + + "\000\002\011\005\000\002\011\005\000\002\011\005\000" + + "\002\011\005\000\002\011\004\000\002\011\004\000\002" + + "\011\004\000\002\011\004\000\002\011\004\000\002\011" + + "\004\000\002\011\004\000\002\011\003\000\002\113\003" + + "\000\002\113\005\000\002\113\005\000\002\113\005\000" + + "\002\114\003\000\002\114\005\000\002\114\005\000\002" + + "\114\005\000\002\117\003\000\002\117\005\000\002\117" + + "\005\000\002\117\005\000\002\117\005\000\002\120\003" + + "\000\002\120\005\000\002\120\005\000\002\120\005\000" + + "\002\120\005\000\002\115\003\000\002\115\005\000\002" + + "\115\005\000\002\115\005\000\002\116\003\000\002\116" + + "\005\000\002\116\005\000\002\116\005\000\002\061\003" + + "\000\002\061\004\000\002\061\004\000\002\061\004\000" + + "\002\061\004\000\002\061\004\000\002\061\004\000\002" + + "\062\003\000\002\062\004\000\002\062\004\000\002\062" + + "\004\000\002\065\003\000\002\065\005\000\002\066\003" + + "\000\002\066\005\000\002\046\003\000\002\046\005\000" + + "\002\047\003\000\002\047\005\000\002\072\003\000\002" + + "\072\003\000\002\072\003\000\002\072\003\000\002\072" + + "\003\000\002\072\003\000\002\072\003\000\002\072\003" + + "\000\002\072\003\000\002\072\003\000\002\072\003\000" + + "\002\072\003\000\002\072\003\000\002\072\003\000\002" + + "\072\003\000\002\072\003\000\002\073\003\000\002\073" + + "\005\000\002\074\003\000\002\074\005\000\002\021\003" + + "\000\002\021\005\000\002\022\003\000\002\022\005\000" + + "\002\070\003\000\002\070\005\000\002\071\003\000\002" + + "\071\005\000\002\006\003\000\002\007\003\000\002\007" + + "\006\000\002\007\006\000\002\007\006\000\002\007\006" + + "\000\002\007\006\000\002\023\003\000\002\023\005\000" + + "\002\024\003\000\002\024\005\000\002\024\005\000\002" + + "\024\005\000\002\024\005\000\002\024\005\000\002\121" + + "\004\000\002\121\004\000\002\121\004\000\002\121\004" + + "\000\002\121\004\000\002\121\004\000\002\122\003\000" + + "\002\122\004\000\002\122\004\000\002\122\004\000\002" + + "\004\003\000\002\004\003\000\002\004\003\000\002\004" + + "\003\000\002\004\003\000\002\004\003\000\002\004\003" + + "\000\002\004\005\000\002\004\003\000\002\004\004\000" + + "\002\004\003\000\002\004\006\000\002\004\005" }); + + /** Access to production table. */ + public short[][] production_table() {return _production_table;} + + /** Parse-action table. */ + protected static final short[][] _action_table = + unpackFromStrings(new String[] { + "\000\u02b4\000\002\001\uffec\000\004\002\u02b6\001\002\000" + + "\032\002\001\035\026\043\010\050\017\065\016\104\006" + + "\111\021\125\027\134\012\141\024\147\013\153\030\001" + + "\uffb7\000\002\001\uffb3\000\002\001\uffef\000\014\100\242" + + "\142\053\160\046\163\044\165\u02b2\001\002\000\002\001" + + "\uffee\000\014\057\uffb6\067\uffb6\102\uffb6\126\uffb6\133\uffb6" + + "\001\uffb0\000\002\001\uffaf\000\012\100\242\142\053\160" + + "\046\163\044\001\002\000\002\001\ufff0\000\014\100\242" + + "\142\053\160\046\163\044\165\u02a1\001\002\000\002\001" + + "\uffeb\000\002\001\ufff1\000\010\142\053\160\046\163\044" + + "\001\002\000\016\035\026\104\006\125\027\134\u0294\147" + + "\013\153\030\001\002\000\010\142\053\160\046\163\044" + + "\001\002\000\002\001\uffea\000\004\075\u0252\001\uffed\000" + + "\002\001\uffb4\000\002\001\uffb2\000\002\001\uffb1\000\014" + + "\057\032\067\036\102\033\126\035\133\034\001\002\000" + + "\010\142\053\160\046\163\044\001\002\000\010\142\053" + + "\160\046\163\044\001\002\000\020\114\045\142\041\150" + + "\047\155\040\160\046\162\043\163\044\001\002\000\010" + + "\142\053\160\046\163\044\001\002\000\020\114\045\142" + + "\041\150\047\155\040\160\046\162\043\163\044\001\002" + + "\000\010\051\u020b\101\u020d\105\u020c\001\uffa9\000\002\001" + + "\uffa7\000\004\151\u0112\001\002\000\004\151\056\001\uff9d" + + "\000\002\001\uffa8\000\002\001\uff9a\000\002\001\uffa4\000" + + "\004\151\u011e\001\002\000\002\001\uffa6\000\004\055\051" + + "\001\002\000\010\142\053\160\046\163\044\001\002\000" + + "\010\051\060\101\062\105\061\001\002\000\004\151\054" + + "\001\002\000\004\163\044\001\002\000\004\151\056\001" + + "\uff9b\000\004\163\057\001\002\000\002\001\uff99\000\116" + + "\031\120\032\144\033\150\034\151\036\124\037\174\044" + + "\102\047\210\053\223\072\220\073\116\077\165\100\125" + + "\102\215\103\204\104\153\105\127\112\152\113\212\114" + + "\045\115\134\124\113\125\154\142\200\143\177\150\047" + + "\152\161\153\205\154\162\155\040\156\176\157\121\160" + + "\171\161\135\162\043\163\044\164\147\165\137\001\002" + + "\000\022\052\072\053\063\062\065\130\064\134\074\142" + + "\053\160\046\163\044\001\uff75\000\022\052\072\053\063" + + "\062\065\130\064\134\074\142\053\160\046\163\044\001" + + "\uff75\000\010\142\053\160\046\163\044\001\002\000\010" + + "\142\053\160\046\163\044\001\002\000\010\142\053\160" + + "\046\163\044\001\002\000\004\052\u01f3\001\uff74\000\002" + + "\001\uff98\000\010\051\u01bc\052\077\060\u01ef\001\002\000" + + "\002\001\uff86\000\022\052\072\053\063\062\065\130\064" + + "\134\074\142\053\160\046\163\044\001\uff75\000\004\137" + + "\u01ea\001\002\000\012\053\075\142\053\160\046\163\044" + + "\001\002\000\010\142\053\160\046\163\044\001\002\000" + + "\010\051\101\052\077\060\100\001\002\000\010\142\053" + + "\160\046\163\044\001\002\000\116\031\120\032\144\033" + + "\150\034\151\036\124\037\174\044\102\047\210\053\u01e2" + + "\072\220\073\116\077\165\100\125\102\215\103\204\104" + + "\153\105\127\112\152\113\212\114\045\115\134\124\113" + + "\125\154\142\200\143\177\150\047\152\161\153\205\154" + + "\162\155\040\156\176\157\121\160\171\161\135\162\043" + + "\163\044\164\147\165\137\001\002\000\116\031\120\032" + + "\144\033\150\034\151\036\124\037\174\044\102\047\210" + + "\053\167\072\220\073\116\077\165\100\125\102\215\103" + + "\204\104\153\105\127\112\152\113\212\114\045\115\134" + + "\124\113\125\154\142\200\143\177\150\047\152\161\153" + + "\205\154\162\155\040\156\176\157\121\160\171\161\135" + + "\162\043\163\044\164\147\165\137\001\002\000\010\142" + + "\053\160\046\163\044\001\002\000\002\001\uff53\000\002" + + "\001\uff55\000\002\001\uff61\000\006\041\u01d7\075\u01d6\001" + + "\uff47\000\002\001\uff4f\000\044\004\350\005\335\006\351" + + "\007\343\010\344\011\353\012\346\013\340\014\354\015" + + "\342\016\337\017\345\020\336\021\347\022\341\023\355" + + "\054\u01d2\001\ufed3\000\002\001\ufed5\000\002\001\ufefc\000" + + "\020\053\063\062\065\130\064\134\074\142\053\160\046" + + "\163\044\001\002\000\002\001\uff00\000\004\132\u01ce\001" + + "\ufef1\000\002\001\ufeae\000\002\001\ufef8\000\002\001\ufeac" + + "\000\102\031\120\032\144\033\150\034\151\037\174\044" + + "\102\047\210\053\223\072\220\073\116\077\165\100\125" + + "\101\312\102\215\103\204\105\127\112\152\114\045\124" + + "\113\142\041\150\047\152\161\154\162\155\040\156\176" + + "\157\121\160\171\161\135\162\043\163\044\164\147\165" + + "\137\001\002\000\002\001\uff41\000\002\001\uff43\000\062" + + "\031\120\032\144\033\150\034\151\044\102\047\210\053" + + "\223\072\220\073\116\077\165\100\125\105\127\114\045" + + "\142\041\150\047\154\162\155\040\157\121\160\171\161" + + "\135\162\043\163\044\164\147\165\137\001\002\000\126" + + "\031\120\032\144\033\150\034\151\036\124\037\174\044" + + "\102\047\210\053\u01a6\062\u01a2\072\220\073\116\077\165" + + "\100\125\102\215\103\204\104\153\105\127\112\152\113" + + "\212\114\045\115\134\124\113\125\154\130\u01a3\134\u01a9" + + "\136\246\142\200\143\177\150\047\152\161\153\205\154" + + "\162\155\040\156\176\157\121\160\171\161\135\162\043" + + "\163\044\164\147\165\137\001\002\000\002\001\uff8e\000" + + "\116\031\120\032\144\033\150\034\151\036\124\037\174" + + "\044\102\047\210\053\223\072\220\073\116\077\165\100" + + "\125\102\215\103\204\104\153\105\127\112\152\113\212" + + "\114\045\115\134\124\113\125\154\142\200\143\177\150" + + "\047\152\161\153\205\154\162\155\040\156\176\157\121" + + "\160\171\161\135\162\043\163\044\164\147\165\137\001" + + "\002\000\004\135\u019e\001\ufecf\000\002\001\ufed1\000\006" + + "\055\u019c\101\301\001\ufecb\000\002\001\ufecd\000\116\031" + + "\120\032\144\033\150\034\151\036\124\037\174\044\102" + + "\047\210\053\223\072\220\073\116\077\165\100\125\102" + + "\215\103\204\104\153\105\127\112\152\113\212\114\045" + + "\115\134\124\113\125\154\142\200\143\177\150\047\152" + + "\161\153\205\154\162\155\040\156\176\157\121\160\171" + + "\161\135\162\043\163\044\164\147\165\137\001\002\000" + + "\066\031\120\032\144\033\150\037\174\044\102\047\210" + + "\073\116\100\125\102\215\103\204\105\127\112\152\114" + + "\045\124\113\142\041\150\047\152\161\154\162\155\040" + + "\156\176\160\171\161\135\162\043\163\044\164\147\165" + + "\137\001\002\000\002\001\ufea8\000\002\001\ufeaf\000\010" + + "\144\375\145\373\146\374\001\uff13\000\002\001\uff27\000" + + "\032\060\u017e\070\u017c\071\u0177\076\u0176\106\u017f\107\u0178" + + "\116\u0175\117\u017a\120\u0179\121\u0174\122\u017d\123\u017b\001" + + "\uff3c\000\002\001\uff3f\000\002\001\ufeab\000\004\127\u0170" + + "\001\uff62\000\002\001\uff63\000\002\001\ufeb0\000\002\001" + + "\ufeaa\000\004\101\u016d\001\002\000\020\053\063\062\065" + + "\130\064\134\074\142\053\160\046\163\044\001\002\000" + + "\062\031\120\032\144\033\150\034\151\044\102\047\210" + + "\053\223\072\220\073\116\077\165\100\125\105\127\114" + + "\045\142\041\150\047\154\162\155\040\157\121\160\171" + + "\161\135\162\043\163\044\164\147\165\137\001\002\000" + + "\062\031\120\032\144\033\150\034\151\044\102\047\210" + + "\053\223\072\220\073\116\077\165\100\125\105\127\114" + + "\045\142\041\150\047\154\162\155\040\157\121\160\171" + + "\161\135\162\043\163\044\164\147\165\137\001\002\000" + + "\004\074\u012d\001\uff57\000\002\001\uff59\000\002\001\ufee7" + + "\000\002\001\ufee9\000\020\053\063\062\065\130\064\134" + + "\074\142\053\160\046\163\044\001\002\000\066\031\120" + + "\032\144\033\150\037\174\044\102\047\210\073\116\100" + + "\125\102\215\103\204\105\127\112\152\114\045\124\113" + + "\142\041\150\047\152\161\154\162\155\040\156\176\160" + + "\171\161\135\162\043\163\044\164\147\165\137\001\002" + + "\000\002\001\ufec0\000\002\001\ufec2\000\102\031\120\032" + + "\144\033\150\034\151\037\174\044\102\047\210\053\223" + + "\072\220\073\116\077\165\100\125\101\315\102\215\103" + + "\204\105\127\112\152\114\045\124\113\142\041\150\047" + + "\152\161\154\162\155\040\156\176\157\121\160\171\161" + + "\135\162\043\163\044\164\147\165\137\001\002\000\002" + + "\001\ufeb4\000\120\031\120\032\144\033\150\034\151\036" + + "\124\037\174\044\102\047\210\053\223\072\220\073\116" + + "\077\165\100\125\101\225\102\215\103\204\104\153\105" + + "\127\112\152\113\212\114\045\115\134\124\113\125\154" + + "\142\200\143\177\150\047\152\161\153\205\154\162\155" + + "\040\156\176\157\121\160\171\161\135\162\043\163\044" + + "\164\147\165\137\001\002\000\010\026\u0120\027\u0122\030" + + "\u0121\001\uff05\000\004\151\u011e\001\ufead\000\002\001\uff0a" + + "\000\004\040\u011c\001\ufeeb\000\020\053\063\062\065\130" + + "\064\134\074\142\053\160\046\163\044\001\002\000\002" + + "\001\ufeed\000\020\053\063\062\065\130\064\134\074\142" + + "\053\160\046\163\044\001\002\000\062\031\120\032\144" + + "\033\150\034\151\044\102\047\210\053\223\072\220\073" + + "\116\077\165\100\125\105\127\114\045\142\041\150\047" + + "\154\162\155\040\157\121\160\171\161\135\162\043\163" + + "\044\164\147\165\137\001\002\000\064\031\120\032\144" + + "\033\150\034\151\044\102\047\210\053\223\072\220\073" + + "\116\077\165\100\125\105\127\114\045\142\041\150\047" + + "\151\u0112\154\162\155\040\157\121\160\171\161\135\162" + + "\043\163\044\164\147\165\137\001\002\000\002\001\uffa9" + + "\000\002\001\ufec8\000\002\001\ufec9\000\020\053\063\062" + + "\065\130\064\134\074\142\053\160\046\163\044\001\002" + + "\000\062\031\120\032\144\033\150\034\151\044\102\047" + + "\210\053\223\072\220\073\116\077\165\100\125\105\127" + + "\114\045\142\041\150\047\154\162\155\040\157\121\160" + + "\171\161\135\162\043\163\044\164\147\165\137\001\002" + + "\000\002\001\uff49\000\002\001\uff51\000\066\031\120\032" + + "\144\033\150\037\174\044\102\047\210\073\116\100\125" + + "\102\215\103\204\105\127\112\152\114\045\124\113\142" + + "\041\150\047\152\161\154\162\155\040\156\176\160\171" + + "\161\135\162\043\163\044\164\147\165\137\001\002\000" + + "\002\001\ufea6\000\062\031\120\032\144\033\150\034\151" + + "\044\102\047\210\053\223\072\220\073\116\077\165\100" + + "\125\105\127\114\045\142\041\150\047\154\162\155\040" + + "\157\121\160\171\161\135\162\043\163\044\164\147\165" + + "\137\001\002\000\012\024\257\025\255\110\256\131\254" + + "\001\uff0e\000\002\001\uff12\000\010\142\053\160\046\163" + + "\044\001\002\000\002\001\uff48\000\002\001\uff50\000\100" + + "\031\120\032\144\033\150\034\151\037\174\044\102\047" + + "\210\053\223\072\220\073\116\077\165\100\125\102\215" + + "\103\204\105\127\112\152\114\045\124\113\142\041\150" + + "\047\152\161\154\162\155\040\156\176\157\121\160\171" + + "\161\135\162\043\163\044\164\147\165\137\001\002\000" + + "\002\001\ufef0\000\002\001\ufef4\000\004\101\225\001\002" + + "\000\002\001\ufef7\000\116\031\120\032\144\033\150\034" + + "\151\036\124\037\174\044\102\047\210\053\223\072\220" + + "\073\116\077\165\100\125\102\215\103\204\104\153\105" + + "\127\112\152\113\212\114\045\115\134\124\113\125\154" + + "\142\200\143\177\150\047\152\161\153\205\154\162\155" + + "\040\156\176\157\121\160\171\161\135\162\043\163\044" + + "\164\147\165\137\001\uff67\000\002\001\uff65\000\004\137" + + "\233\001\002\000\004\052\231\001\uff66\000\116\031\120" + + "\032\144\033\150\034\151\036\124\037\174\044\102\047" + + "\210\053\223\072\220\073\116\077\165\100\125\102\215" + + "\103\204\104\153\105\127\112\152\113\212\114\045\115" + + "\134\124\113\125\154\142\200\143\177\150\047\152\161" + + "\153\205\154\162\155\040\156\176\157\121\160\171\161" + + "\135\162\043\163\044\164\147\165\137\001\002\000\002" + + "\001\uff64\000\002\001\ufec6\000\004\060\236\001\002\000" + + "\002\001\uff60\000\116\031\120\032\144\033\150\034\151" + + "\036\124\037\174\044\102\047\210\053\223\072\220\073" + + "\116\077\165\100\125\102\215\103\204\104\153\105\127" + + "\112\152\113\212\114\045\115\134\124\113\125\154\142" + + "\200\143\177\150\047\152\161\153\205\154\162\155\040" + + "\156\176\157\121\160\171\161\135\162\043\163\044\164" + + "\147\165\137\001\002\000\010\045\243\052\240\100\242" + + "\001\002\000\010\142\053\160\046\163\044\001\002\000" + + "\002\001\uff71\000\120\031\120\032\144\033\150\034\151" + + "\036\124\037\174\044\102\047\210\053\223\072\220\073" + + "\116\077\165\100\125\102\215\103\204\104\153\105\127" + + "\112\152\113\212\114\045\115\134\124\113\125\154\136" + + "\246\142\200\143\177\150\047\152\161\153\205\154\162" + + "\155\040\156\176\157\121\160\171\161\135\162\043\163" + + "\044\164\147\165\137\001\002\000\116\031\120\032\144" + + "\033\150\034\151\036\124\037\174\044\102\047\210\053" + + "\223\072\220\073\116\077\165\100\125\102\215\103\204" + + "\104\153\105\127\112\152\113\212\114\045\115\134\124" + + "\113\125\154\142\200\143\177\150\047\152\161\153\205" + + "\154\162\155\040\156\176\157\121\160\171\161\135\162" + + "\043\163\044\164\147\165\137\001\002\000\002\001\uff68" + + "\000\002\001\uff69\000\002\001\uff6c\000\002\001\uff6b\000" + + "\120\031\120\032\144\033\150\034\151\036\124\037\174" + + "\044\102\047\210\053\223\072\220\073\116\077\165\100" + + "\125\102\215\103\204\104\153\105\127\112\152\113\212" + + "\114\045\115\134\124\113\125\154\136\251\142\200\143" + + "\177\150\047\152\161\153\205\154\162\155\040\156\176" + + "\157\121\160\171\161\135\162\043\163\044\164\147\165" + + "\137\001\002\000\002\001\uff6d\000\002\001\uff6a\000\002" + + "\001\uff70\000\100\031\120\032\144\033\150\034\151\037" + + "\174\044\102\047\267\053\223\072\261\073\116\077\262" + + "\100\125\102\215\103\204\105\127\112\152\114\045\124" + + "\113\142\041\150\047\152\161\154\264\155\040\156\176" + + "\157\272\160\171\161\263\162\043\163\044\164\147\165" + + "\137\001\002\000\100\031\120\032\144\033\150\034\151" + + "\037\174\044\102\047\267\053\223\072\261\073\116\077" + + "\262\100\125\102\215\103\204\105\127\112\152\114\045" + + "\124\113\142\041\150\047\152\161\154\264\155\040\156" + + "\176\157\272\160\171\161\263\162\043\163\044\164\147" + + "\165\137\001\002\000\100\031\120\032\144\033\150\034" + + "\151\037\174\044\102\047\267\053\223\072\261\073\116" + + "\077\262\100\125\102\215\103\204\105\127\112\152\114" + + "\045\124\113\142\041\150\047\152\161\154\264\155\040" + + "\156\176\157\272\160\171\161\263\162\043\163\044\164" + + "\147\165\137\001\002\000\100\031\120\032\144\033\150" + + "\034\151\037\174\044\102\047\267\053\223\072\261\073" + + "\116\077\262\100\125\102\215\103\204\105\127\112\152" + + "\114\045\124\113\142\041\150\047\152\161\154\264\155" + + "\040\156\176\157\272\160\171\161\263\162\043\163\044" + + "\164\147\165\137\001\002\000\004\040\332\001\ufeeb\000" + + "\062\031\120\032\144\033\150\034\151\044\102\047\267" + + "\053\223\072\261\073\116\077\262\100\125\105\127\114" + + "\045\142\041\150\047\154\264\155\040\157\272\160\171" + + "\161\263\162\043\163\044\164\147\165\137\001\002\000" + + "\064\031\120\032\144\033\150\034\151\044\102\047\267" + + "\053\223\072\261\073\116\077\262\100\125\101\315\105" + + "\127\114\045\142\041\150\047\154\264\155\040\157\272" + + "\160\171\161\263\162\043\163\044\164\147\165\137\001" + + "\002\000\050\031\120\032\144\033\150\044\102\047\267" + + "\073\116\100\125\105\127\114\045\142\041\150\047\154" + + "\264\155\040\160\171\161\263\162\043\163\044\164\147" + + "\165\137\001\002\000\050\031\120\032\144\033\150\044" + + "\102\047\267\073\116\100\125\105\127\114\045\142\041" + + "\150\047\154\264\155\040\160\171\161\263\162\043\163" + + "\044\164\147\165\137\001\002\000\044\004\350\005\335" + + "\006\351\007\343\010\344\011\353\012\346\013\340\014" + + "\354\015\342\016\337\017\345\020\336\021\347\022\341" + + "\023\355\054\334\001\ufed3\000\004\132\330\001\ufef1\000" + + "\050\031\120\032\144\033\150\044\102\047\267\073\116" + + "\100\125\105\127\114\045\142\041\150\047\154\264\155" + + "\040\160\171\161\263\162\043\163\044\164\147\165\137" + + "\001\002\000\010\026\321\027\323\030\322\001\uff02\000" + + "\006\055\302\101\301\001\ufecb\000\064\031\120\032\144" + + "\033\150\034\151\044\102\047\267\053\223\072\261\073" + + "\116\077\262\100\125\101\312\105\127\114\045\142\041" + + "\150\047\154\264\155\040\157\272\160\171\161\263\162" + + "\043\163\044\164\147\165\137\001\002\000\004\135\275" + + "\001\ufecf\000\002\001\uff07\000\060\031\120\032\144\033" + + "\150\034\151\044\102\047\267\053\223\073\116\077\276" + + "\100\125\105\127\114\045\142\041\150\047\154\264\155" + + "\040\157\277\160\171\161\263\162\043\163\044\164\147" + + "\165\137\001\002\000\004\101\315\001\002\000\004\101" + + "\312\001\002\000\006\055\302\101\301\001\ufeca\000\116" + + "\031\120\032\144\033\150\034\151\036\124\037\174\044" + + "\102\047\210\053\223\072\220\073\116\077\165\100\125" + + "\102\215\103\204\104\153\105\127\112\152\113\212\114" + + "\045\115\134\124\113\125\154\142\200\143\177\150\047" + + "\152\161\153\205\154\162\155\040\156\176\157\121\160" + + "\171\161\135\162\043\163\044\164\147\165\137\001\uff67" + + "\000\060\031\120\032\144\033\150\034\303\044\102\047" + + "\267\053\305\073\116\077\304\100\125\105\127\114\045" + + "\142\041\150\047\154\264\155\040\157\306\160\171\161" + + "\263\162\043\163\044\164\147\165\137\001\002\000\002" + + "\001\ufebd\000\002\001\ufebc\000\002\001\ufebe\000\002\001" + + "\ufebb\000\002\001\ufebf\000\004\137\311\001\002\000\002" + + "\001\ufec7\000\116\031\120\032\144\033\150\034\151\036" + + "\124\037\174\044\102\047\210\053\223\072\220\073\116" + + "\077\165\100\125\102\215\103\204\104\153\105\127\112" + + "\152\113\212\114\045\115\134\124\113\125\154\142\200" + + "\143\177\150\047\152\161\153\205\154\162\155\040\156" + + "\176\157\121\160\171\161\135\162\043\163\044\164\147" + + "\165\137\001\uff67\000\004\137\314\001\002\000\002\001" + + "\ufec3\000\116\031\120\032\144\033\150\034\151\036\124" + + "\037\174\044\102\047\210\053\223\072\220\073\116\077" + + "\165\100\125\102\215\103\204\104\153\105\127\112\152" + + "\113\212\114\045\115\134\124\113\125\154\142\200\143" + + "\177\150\047\152\161\153\205\154\162\155\040\156\176" + + "\157\121\160\171\161\135\162\043\163\044\164\147\165" + + "\137\001\uff67\000\004\137\317\001\002\000\002\001\ufec4" + + "\000\002\001\ufeef\000\062\031\120\032\144\033\150\034" + + "\151\044\102\047\267\053\223\072\261\073\116\077\262" + + "\100\125\105\127\114\045\142\041\150\047\154\264\155" + + "\040\157\272\160\171\161\263\162\043\163\044\164\147" + + "\165\137\001\002\000\062\031\120\032\144\033\150\034" + + "\151\044\102\047\267\053\223\072\261\073\116\077\262" + + "\100\125\105\127\114\045\142\041\150\047\154\264\155" + + "\040\157\272\160\171\161\263\162\043\163\044\164\147" + + "\165\137\001\002\000\062\031\120\032\144\033\150\034" + + "\151\044\102\047\267\053\223\072\261\073\116\077\262" + + "\100\125\105\127\114\045\142\041\150\047\154\264\155" + + "\040\157\272\160\171\161\263\162\043\163\044\164\147" + + "\165\137\001\002\000\002\001\ufefa\000\002\001\ufef9\000" + + "\002\001\ufefb\000\002\001\ufeb1\000\060\031\120\032\144" + + "\033\150\034\151\044\102\047\267\053\223\073\116\077" + + "\276\100\125\105\127\114\045\142\041\150\047\154\264" + + "\155\040\157\277\160\171\161\263\162\043\163\044\164" + + "\147\165\137\001\002\000\004\040\332\001\ufeea\000\060" + + "\031\120\032\144\033\150\034\151\044\102\047\267\053" + + "\223\073\116\077\276\100\125\105\127\114\045\142\041" + + "\150\047\154\264\155\040\157\277\160\171\161\263\162" + + "\043\163\044\164\147\165\137\001\002\000\002\001\ufee6" + + "\000\060\031\120\032\144\033\150\034\151\044\102\047" + + "\267\053\223\073\116\077\276\100\125\105\127\114\045" + + "\142\041\150\047\154\264\155\040\157\277\160\171\161" + + "\263\162\043\163\044\164\147\165\137\001\002\000\002" + + "\001\ufee4\000\002\001\ufed9\000\002\001\ufedb\000\002\001" + + "\ufede\000\002\001\ufed7\000\002\001\ufedc\000\002\001\ufee2" + + "\000\002\001\ufee1\000\002\001\ufeda\000\002\001\ufedf\000" + + "\002\001\ufed8\000\002\001\ufee5\000\002\001\ufee3\000\060" + + "\031\120\032\144\033\150\034\151\044\102\047\267\053" + + "\223\073\116\077\276\100\125\105\127\114\045\142\041" + + "\150\047\154\264\155\040\157\277\160\171\161\263\162" + + "\043\163\044\164\147\165\137\001\002\000\002\001\ufee0" + + "\000\002\001\ufedd\000\002\001\ufed6\000\002\001\ufed2\000" + + "\004\135\275\001\ufece\000\002\001\ufeb2\000\002\001\ufeb3" + + "\000\002\001\ufeee\000\010\026\321\027\323\030\322\001" + + "\uff03\000\002\001\uff08\000\010\026\321\027\323\030\322" + + "\001\uff01\000\002\001\uff06\000\010\026\321\027\323\030" + + "\322\001\uff04\000\002\001\uff09\000\010\144\375\145\373" + + "\146\374\001\uff19\000\002\001\uff2d\000\100\031\120\032" + + "\144\033\150\034\151\037\174\044\102\047\267\053\223" + + "\072\261\073\116\077\262\100\125\102\215\103\204\105" + + "\127\112\152\114\045\124\113\142\041\150\047\152\161" + + "\154\264\155\040\156\176\157\272\160\171\161\263\162" + + "\043\163\044\164\147\165\137\001\002\000\100\031\120" + + "\032\144\033\150\034\151\037\174\044\102\047\267\053" + + "\223\072\261\073\116\077\262\100\125\102\215\103\204" + + "\105\127\112\152\114\045\124\113\142\041\150\047\152" + + "\161\154\264\155\040\156\176\157\272\160\171\161\263" + + "\162\043\163\044\164\147\165\137\001\002\000\100\031" + + "\120\032\144\033\150\034\151\037\174\044\102\047\267" + + "\053\223\072\261\073\116\077\262\100\125\102\215\103" + + "\204\105\127\112\152\114\045\124\113\142\041\150\047" + + "\152\161\154\264\155\040\156\176\157\272\160\171\161" + + "\263\162\043\163\044\164\147\165\137\001\002\000\010" + + "\026\321\027\323\030\322\001\uff05\000\012\024\u0104\025" + + "\u0102\110\u0103\131\u0101\001\uff0d\000\002\001\uff11\000\062" + + "\031\120\032\144\033\150\034\151\044\102\047\267\053" + + "\223\072\261\073\116\077\262\100\125\105\127\114\045" + + "\142\041\150\047\154\264\155\040\157\272\160\171\161" + + "\263\162\043\163\044\164\147\165\137\001\002\000\062" + + "\031\120\032\144\033\150\034\151\044\102\047\267\053" + + "\223\072\261\073\116\077\262\100\125\105\127\114\045" + + "\142\041\150\047\154\264\155\040\157\272\160\171\161" + + "\263\162\043\163\044\164\147\165\137\001\002\000\062" + + "\031\120\032\144\033\150\034\151\044\102\047\267\053" + + "\223\072\261\073\116\077\262\100\125\105\127\114\045" + + "\142\041\150\047\154\264\155\040\157\272\160\171\161" + + "\263\162\043\163\044\164\147\165\137\001\002\000\062" + + "\031\120\032\144\033\150\034\151\044\102\047\267\053" + + "\223\072\261\073\116\077\262\100\125\105\127\114\045" + + "\142\041\150\047\154\264\155\040\157\272\160\171\161" + + "\263\162\043\163\044\164\147\165\137\001\002\000\012" + + "\024\u0104\025\u0102\110\u0103\131\u0101\001\uff0b\000\002\001" + + "\uff0f\000\012\024\u0104\025\u0102\110\u0103\131\u0101\001\uff0c" + + "\000\002\001\uff10\000\002\001\ufeb8\000\002\001\ufeb5\000" + + "\010\144\375\145\373\146\374\001\uff18\000\002\001\uff2c" + + "\000\002\001\uff76\000\010\045\243\052\u010f\100\242\001" + + "\002\000\020\053\063\062\065\130\064\134\074\142\053" + + "\160\046\163\044\001\002\000\002\001\uff5c\000\002\001" + + "\uff77\000\006\150\u0115\163\044\001\002\000\010\144\375" + + "\145\373\146\374\001\uff14\000\002\001\uff28\000\002\001" + + "\uffa5\000\010\144\375\145\373\146\374\001\uff15\000\002" + + "\001\uff29\000\010\045\243\052\u010f\100\242\001\002\000" + + "\002\001\uff5a\000\010\045\243\052\u010f\100\242\001\002" + + "\000\002\001\uff5f\000\076\031\120\032\144\033\150\034" + + "\151\037\174\044\102\047\267\053\223\073\116\077\276" + + "\100\125\102\215\103\204\105\127\112\152\114\045\124" + + "\113\142\041\150\047\152\161\154\264\155\040\156\176" + + "\157\277\160\171\161\263\162\043\163\044\164\147\165" + + "\137\001\002\000\002\001\ufee8\000\004\163\044\001\002" + + "\000\004\151\056\001\uff9c\000\100\031\120\032\144\033" + + "\150\034\151\037\174\044\102\047\267\053\223\072\261" + + "\073\116\077\262\100\125\102\215\103\204\105\127\112" + + "\152\114\045\124\113\142\041\150\047\152\161\154\264" + + "\155\040\156\176\157\272\160\171\161\263\162\043\163" + + "\044\164\147\165\137\001\002\000\100\031\120\032\144" + + "\033\150\034\151\037\174\044\102\047\267\053\223\072" + + "\261\073\116\077\262\100\125\102\215\103\204\105\127" + + "\112\152\114\045\124\113\142\041\150\047\152\161\154" + + "\264\155\040\156\176\157\272\160\171\161\263\162\043" + + "\163\044\164\147\165\137\001\002\000\100\031\120\032" + + "\144\033\150\034\151\037\174\044\102\047\267\053\223" + + "\072\261\073\116\077\262\100\125\102\215\103\204\105" + + "\127\112\152\114\045\124\113\142\041\150\047\152\161" + + "\154\264\155\040\156\176\157\272\160\171\161\263\162" + + "\043\163\044\164\147\165\137\001\002\000\002\001\ufefe" + + "\000\002\001\ufefd\000\002\001\ufeff\000\002\001\uff88\000" + + "\002\001\ufef2\000\002\001\ufef5\000\002\001\ufeb9\000\002" + + "\001\ufeb6\000\010\045\243\052\u010f\100\242\001\002\000" + + "\002\001\uff5d\000\116\031\120\032\144\033\150\034\151" + + "\036\u0139\037\174\044\102\047\267\053\223\072\261\073" + + "\116\077\262\100\125\102\215\103\204\104\u0138\105\127" + + "\112\152\113\u0137\114\045\115\u0130\124\113\125\u0136\142" + + "\u012e\143\u013b\150\047\152\161\153\u012f\154\264\155\040" + + "\156\176\157\272\160\171\161\263\162\043\163\044\164" + + "\147\165\137\001\002\000\064\031\120\032\144\033\150" + + "\034\151\044\102\047\267\053\223\072\261\073\116\077" + + "\262\100\125\105\127\114\045\142\041\150\047\151\u0112" + + "\154\264\155\040\157\272\160\171\161\263\162\043\163" + + "\044\164\147\165\137\001\002\000\062\031\120\032\144" + + "\033\150\034\151\044\102\047\267\053\223\072\261\073" + + "\116\077\262\100\125\105\127\114\045\142\041\150\047" + + "\154\264\155\040\157\272\160\171\161\263\162\043\163" + + "\044\164\147\165\137\001\002\000\100\031\120\032\144" + + "\033\150\034\151\036\u0139\044\102\047\267\053\223\072" + + "\261\073\116\077\262\100\125\104\u0138\105\127\113\u0137" + + "\114\045\115\u0130\125\u0136\142\u012e\143\u013b\150\047\153" + + "\u012f\154\264\155\040\157\272\160\171\161\263\162\043" + + "\163\044\164\147\165\137\001\002\000\010\144\u013f\145" + + "\u013d\146\u013e\001\uff13\000\032\060\u0156\070\u0154\071\u014f" + + "\076\u014d\106\u0157\107\u0150\116\u014e\117\u0152\120\u0151\121" + + "\u014c\122\u0155\123\u0153\001\uff3c\000\006\041\u0145\075\u0144" + + "\001\uff47\000\002\001\uff52\000\012\024\u0104\025\u0102\110" + + "\u0103\131\u0101\001\uff0e\000\062\031\120\032\144\033\150" + + "\034\151\044\102\047\267\053\223\072\261\073\116\077" + + "\262\100\125\105\127\114\045\142\041\150\047\154\264" + + "\155\040\157\272\160\171\161\263\162\043\163\044\164" + + "\147\165\137\001\002\000\062\031\120\032\144\033\150" + + "\034\151\044\102\047\267\053\223\072\261\073\116\077" + + "\262\100\125\105\127\114\045\142\041\150\047\154\264" + + "\155\040\157\272\160\171\161\263\162\043\163\044\164" + + "\147\165\137\001\002\000\062\031\120\032\144\033\150" + + "\034\151\044\102\047\267\053\223\072\261\073\116\077" + + "\262\100\125\105\127\114\045\142\041\150\047\154\264" + + "\155\040\157\272\160\171\161\263\162\043\163\044\164" + + "\147\165\137\001\002\000\062\031\120\032\144\033\150" + + "\034\151\044\102\047\267\053\223\072\261\073\116\077" + + "\262\100\125\105\127\114\045\142\041\150\047\154\264" + + "\155\040\157\272\160\171\161\263\162\043\163\044\164" + + "\147\165\137\001\002\000\002\001\uff54\000\062\031\120" + + "\032\144\033\150\034\151\044\102\047\267\053\223\072" + + "\261\073\116\077\262\100\125\105\127\114\045\142\041" + + "\150\047\154\264\155\040\157\272\160\171\161\263\162" + + "\043\163\044\164\147\165\137\001\002\000\010\144\u013f" + + "\145\u013d\146\u013e\001\uff15\000\062\031\120\032\144\033" + + "\150\034\151\044\102\047\267\053\223\072\261\073\116" + + "\077\262\100\125\105\127\114\045\142\041\150\047\154" + + "\264\155\040\157\272\160\171\161\263\162\043\163\044" + + "\164\147\165\137\001\002\000\062\031\120\032\144\033" + + "\150\034\151\044\102\047\267\053\223\072\261\073\116" + + "\077\262\100\125\105\127\114\045\142\041\150\047\154" + + "\264\155\040\157\272\160\171\161\263\162\043\163\044" + + "\164\147\165\137\001\002\000\062\031\120\032\144\033" + + "\150\034\151\044\102\047\267\053\223\072\261\073\116" + + "\077\262\100\125\105\127\114\045\142\041\150\047\154" + + "\264\155\040\157\272\160\171\161\263\162\043\163\044" + + "\164\147\165\137\001\002\000\010\144\u013f\145\u013d\146" + + "\u013e\001\uff1a\000\010\144\u013f\145\u013d\146\u013e\001\uff17" + + "\000\010\144\u013f\145\u013d\146\u013e\001\uff19\000\010\144" + + "\u013f\145\u013d\146\u013e\001\uff16\000\100\031\120\032\144" + + "\033\150\034\151\036\u0139\044\102\047\267\053\223\072" + + "\261\073\116\077\262\100\125\104\u0138\105\127\113\u0137" + + "\114\045\115\u0130\125\u0136\142\u012e\143\u013b\150\047\153" + + "\u012f\154\264\155\040\157\272\160\171\161\263\162\043" + + "\163\044\164\147\165\137\001\002\000\100\031\120\032" + + "\144\033\150\034\151\036\u0139\044\102\047\267\053\223" + + "\072\261\073\116\077\262\100\125\104\u0138\105\127\113" + + "\u0137\114\045\115\u0130\125\u0136\142\u012e\143\u013b\150\047" + + "\153\u012f\154\264\155\040\157\272\160\171\161\263\162" + + "\043\163\044\164\147\165\137\001\002\000\002\001\uff40" + + "\000\002\001\uff44\000\004\056\u0149\001\uff49\000\100\031" + + "\120\032\144\033\150\034\151\036\u0139\044\102\047\267" + + "\053\223\072\261\073\116\077\262\100\125\104\u0138\105" + + "\127\113\u0137\114\045\115\u0130\125\u0136\142\u012e\143\u013b" + + "\150\047\153\u012f\154\264\155\040\157\272\160\171\161" + + "\263\162\043\163\044\164\147\165\137\001\002\000\002" + + "\001\uff45\000\002\001\uff46\000\062\031\120\032\144\033" + + "\150\034\151\044\102\047\267\053\223\072\261\073\116" + + "\077\262\100\125\105\127\114\045\142\041\150\047\154" + + "\264\155\040\157\272\160\171\161\263\162\043\163\044" + + "\164\147\165\137\001\002\000\062\031\120\032\144\033" + + "\150\034\151\044\102\047\267\053\223\072\261\073\116" + + "\077\262\100\125\105\127\114\045\142\041\150\047\154" + + "\264\155\040\157\272\160\171\161\263\162\043\163\044" + + "\164\147\165\137\001\002\000\062\031\120\032\144\033" + + "\150\034\151\044\102\047\267\053\223\072\261\073\116" + + "\077\262\100\125\105\127\114\045\142\041\150\047\154" + + "\264\155\040\157\272\160\171\161\263\162\043\163\044" + + "\164\147\165\137\001\002\000\062\031\120\032\144\033" + + "\150\034\151\044\102\047\267\053\223\072\261\073\116" + + "\077\262\100\125\105\127\114\045\142\041\150\047\154" + + "\264\155\040\157\272\160\171\161\263\162\043\163\044" + + "\164\147\165\137\001\002\000\062\031\120\032\144\033" + + "\150\034\151\044\102\047\267\053\223\072\261\073\116" + + "\077\262\100\125\105\127\114\045\142\041\150\047\154" + + "\264\155\040\157\272\160\171\161\263\162\043\163\044" + + "\164\147\165\137\001\002\000\062\031\120\032\144\033" + + "\150\034\151\044\102\047\267\053\223\072\261\073\116" + + "\077\262\100\125\105\127\114\045\142\041\150\047\154" + + "\264\155\040\157\272\160\171\161\263\162\043\163\044" + + "\164\147\165\137\001\002\000\062\031\120\032\144\033" + + "\150\034\151\044\102\047\267\053\223\072\261\073\116" + + "\077\262\100\125\105\127\114\045\142\041\150\047\154" + + "\264\155\040\157\272\160\171\161\263\162\043\163\044" + + "\164\147\165\137\001\002\000\062\031\120\032\144\033" + + "\150\034\151\044\102\047\267\053\223\072\261\073\116" + + "\077\262\100\125\105\127\114\045\142\041\150\047\154" + + "\264\155\040\157\272\160\171\161\263\162\043\163\044" + + "\164\147\165\137\001\002\000\062\031\120\032\144\033" + + "\150\034\151\044\102\047\267\053\223\072\261\073\116" + + "\077\262\100\125\105\127\114\045\142\041\150\047\154" + + "\264\155\040\157\272\160\171\161\263\162\043\163\044" + + "\164\147\165\137\001\002\000\062\031\120\032\144\033" + + "\150\034\151\044\102\047\267\053\223\072\261\073\116" + + "\077\262\100\125\105\127\114\045\142\041\150\047\154" + + "\264\155\040\157\272\160\171\161\263\162\043\163\044" + + "\164\147\165\137\001\002\000\062\031\120\032\144\033" + + "\150\034\151\044\102\047\267\053\223\072\261\073\116" + + "\077\262\100\125\105\127\114\045\142\041\150\047\154" + + "\264\155\040\157\272\160\171\161\263\162\043\163\044" + + "\164\147\165\137\001\002\000\062\031\120\032\144\033" + + "\150\034\151\044\102\047\267\053\223\072\261\073\116" + + "\077\262\100\125\105\127\114\045\142\041\150\047\154" + + "\264\155\040\157\272\160\171\161\263\162\043\163\044" + + "\164\147\165\137\001\002\000\010\144\u013f\145\u013d\146" + + "\u013e\001\uff24\000\010\144\u013f\145\u013d\146\u013e\001\uff25" + + "\000\010\144\u013f\145\u013d\146\u013e\001\uff1e\000\010\144" + + "\u013f\145\u013d\146\u013e\001\uff23\000\010\144\u013f\145\u013d" + + "\146\u013e\001\uff1c\000\010\144\u013f\145\u013d\146\u013e\001" + + "\uff1d\000\010\144\u013f\145\u013d\146\u013e\001\uff1b\000\010" + + "\144\u013f\145\u013d\146\u013e\001\uff22\000\010\144\u013f\145" + + "\u013d\146\u013e\001\uff21\000\010\144\u013f\145\u013d\146\u013e" + + "\001\uff1f\000\010\144\u013f\145\u013d\146\u013e\001\uff26\000" + + "\010\144\u013f\145\u013d\146\u013e\001\uff20\000\002\001\uff3b" + + "\000\010\144\u013f\145\u013d\146\u013e\001\uff18\000\010\144" + + "\u013f\145\u013d\146\u013e\001\uff14\000\010\144\375\145\373" + + "\146\374\001\uff16\000\002\001\uff2a\000\010\144\375\145" + + "\373\146\374\001\uff17\000\002\001\uff2b\000\010\045\243" + + "\052\u010f\100\242\001\002\000\002\001\uff5e\000\116\031" + + "\120\032\144\033\150\034\151\036\124\037\174\044\102" + + "\047\210\053\223\072\220\073\116\077\165\100\125\102" + + "\215\103\204\104\153\105\127\112\152\113\212\114\045" + + "\115\134\124\113\125\154\142\200\143\177\150\047\152" + + "\161\153\205\154\162\155\040\156\176\157\121\160\171" + + "\161\135\162\043\163\044\164\147\165\137\001\uff67\000" + + "\004\137\u016f\001\002\000\002\001\ufec5\000\116\031\120" + + "\032\144\033\150\034\151\036\u0139\037\174\044\102\047" + + "\267\053\223\072\261\073\116\077\262\100\125\102\215" + + "\103\204\104\u0138\105\127\112\152\113\u0137\114\045\115" + + "\u0130\124\113\125\u0136\142\u012e\143\u013b\150\047\152\161" + + "\153\u012f\154\264\155\040\156\176\157\272\160\171\161" + + "\263\162\043\163\044\164\147\165\137\001\002\000\004" + + "\074\u0173\001\uff56\000\002\001\uff58\000\100\031\120\032" + + "\144\033\150\034\151\036\u0139\044\102\047\267\053\223" + + "\072\261\073\116\077\262\100\125\104\u0138\105\127\113" + + "\u0137\114\045\115\u0130\125\u0136\142\u012e\143\u013b\150\047" + + "\153\u012f\154\264\155\040\157\272\160\171\161\263\162" + + "\043\163\044\164\147\165\137\001\002\000\062\031\120" + + "\032\144\033\150\034\151\044\102\047\210\053\223\072" + + "\220\073\116\077\165\100\125\105\127\114\045\142\041" + + "\150\047\154\162\155\040\157\121\160\171\161\135\162" + + "\043\163\044\164\147\165\137\001\002\000\062\031\120" + + "\032\144\033\150\034\151\044\102\047\210\053\223\072" + + "\220\073\116\077\165\100\125\105\127\114\045\142\041" + + "\150\047\154\162\155\040\157\121\160\171\161\135\162" + + "\043\163\044\164\147\165\137\001\002\000\062\031\120" + + "\032\144\033\150\034\151\044\102\047\210\053\223\072" + + "\220\073\116\077\165\100\125\105\127\114\045\142\041" + + "\150\047\154\162\155\040\157\121\160\171\161\135\162" + + "\043\163\044\164\147\165\137\001\002\000\062\031\120" + + "\032\144\033\150\034\151\044\102\047\210\053\223\072" + + "\220\073\116\077\165\100\125\105\127\114\045\142\041" + + "\150\047\154\162\155\040\157\121\160\171\161\135\162" + + "\043\163\044\164\147\165\137\001\002\000\062\031\120" + + "\032\144\033\150\034\151\044\102\047\210\053\223\072" + + "\220\073\116\077\165\100\125\105\127\114\045\142\041" + + "\150\047\154\162\155\040\157\121\160\171\161\135\162" + + "\043\163\044\164\147\165\137\001\002\000\062\031\120" + + "\032\144\033\150\034\151\044\102\047\210\053\223\072" + + "\220\073\116\077\165\100\125\105\127\114\045\142\041" + + "\150\047\154\162\155\040\157\121\160\171\161\135\162" + + "\043\163\044\164\147\165\137\001\002\000\062\031\120" + + "\032\144\033\150\034\151\044\102\047\210\053\223\072" + + "\220\073\116\077\165\100\125\105\127\114\045\142\041" + + "\150\047\154\162\155\040\157\121\160\171\161\135\162" + + "\043\163\044\164\147\165\137\001\002\000\062\031\120" + + "\032\144\033\150\034\151\044\102\047\210\053\223\072" + + "\220\073\116\077\165\100\125\105\127\114\045\142\041" + + "\150\047\154\162\155\040\157\121\160\171\161\135\162" + + "\043\163\044\164\147\165\137\001\002\000\062\031\120" + + "\032\144\033\150\034\151\044\102\047\210\053\223\072" + + "\220\073\116\077\165\100\125\105\127\114\045\142\041" + + "\150\047\154\162\155\040\157\121\160\171\161\135\162" + + "\043\163\044\164\147\165\137\001\002\000\062\031\120" + + "\032\144\033\150\034\151\044\102\047\210\053\223\072" + + "\220\073\116\077\165\100\125\105\127\114\045\142\041" + + "\150\047\154\162\155\040\157\121\160\171\161\135\162" + + "\043\163\044\164\147\165\137\001\002\000\062\031\120" + + "\032\144\033\150\034\151\044\102\047\210\053\223\072" + + "\220\073\116\077\165\100\125\105\127\114\045\142\041" + + "\150\047\154\162\155\040\157\121\160\171\161\135\162" + + "\043\163\044\164\147\165\137\001\002\000\062\031\120" + + "\032\144\033\150\034\151\044\102\047\210\053\223\072" + + "\220\073\116\077\165\100\125\105\127\114\045\142\041" + + "\150\047\154\162\155\040\157\121\160\171\161\135\162" + + "\043\163\044\164\147\165\137\001\002\000\010\144\375" + + "\145\373\146\374\001\uff24\000\002\001\uff38\000\010\144" + + "\375\145\373\146\374\001\uff25\000\002\001\uff39\000\010" + + "\144\375\145\373\146\374\001\uff1e\000\002\001\uff32\000" + + "\010\144\375\145\373\146\374\001\uff23\000\002\001\uff37" + + "\000\010\144\375\145\373\146\374\001\uff1c\000\002\001" + + "\uff30\000\010\144\375\145\373\146\374\001\uff1d\000\002" + + "\001\uff31\000\010\144\375\145\373\146\374\001\uff1b\000" + + "\002\001\uff2f\000\010\144\375\145\373\146\374\001\uff22" + + "\000\002\001\uff36\000\010\144\375\145\373\146\374\001" + + "\uff21\000\002\001\uff35\000\010\144\375\145\373\146\374" + + "\001\uff26\000\002\001\uff3a\000\010\144\375\145\373\146" + + "\374\001\uff1f\000\002\001\uff33\000\010\144\375\145\373" + + "\146\374\001\uff20\000\002\001\uff34\000\002\001\ufeba\000" + + "\002\001\ufeb7\000\002\001\uff3e\000\002\001\uff3d\000\076" + + "\031\120\032\144\033\150\034\303\037\174\044\102\047" + + "\267\053\305\073\116\077\304\100\125\102\215\103\204" + + "\105\127\112\152\114\045\124\113\142\041\150\047\152" + + "\161\154\264\155\040\156\176\157\306\160\171\161\263" + + "\162\043\163\044\164\147\165\137\001\002\000\002\001" + + "\ufec1\000\076\031\120\032\144\033\150\034\151\037\174" + + "\044\102\047\267\053\223\073\116\077\276\100\125\102" + + "\215\103\204\105\127\112\152\114\045\124\113\142\041" + + "\150\047\152\161\154\264\155\040\156\176\157\277\160" + + "\171\161\263\162\043\163\044\164\147\165\137\001\002" + + "\000\002\001\ufecc\000\004\140\u01a1\001\002\000\002\001" + + "\ufea9\000\010\142\053\160\046\163\044\001\002\000\010" + + "\142\053\160\046\163\044\001\002\000\006\051\u01bc\052" + + "\077\001\002\000\012\045\243\052\u01b6\100\242\136\u01b8" + + "\001\002\000\012\101\225\142\053\160\046\163\044\001" + + "\002\000\002\001\uff78\000\006\051\uff98\052\uff98\001\uffa9" + + "\000\012\053\u01aa\142\053\160\046\163\044\001\002\000" + + "\010\142\053\160\046\163\044\001\002\000\006\051\101" + + "\052\077\001\002\000\006\051\u01ad\052\077\001\002\000" + + "\116\031\120\032\144\033\150\034\151\036\124\037\174" + + "\044\102\047\210\053\u01af\072\220\073\116\077\165\100" + + "\125\102\215\103\204\104\153\105\127\112\152\113\212" + + "\114\045\115\134\124\113\125\154\142\200\143\177\150" + + "\047\152\161\153\205\154\162\155\040\156\176\157\121" + + "\160\171\161\135\162\043\163\044\164\147\165\137\001" + + "\002\000\002\001\uff8f\000\120\031\120\032\144\033\150" + + "\034\151\036\124\037\174\044\102\047\210\053\223\072" + + "\220\073\116\077\165\100\125\101\225\102\215\103\204" + + "\104\153\105\127\112\152\113\212\114\045\115\134\124" + + "\113\125\154\142\200\143\177\150\047\152\161\153\205" + + "\154\162\155\040\156\176\157\121\160\171\161\135\162" + + "\043\163\044\164\147\165\137\001\002\000\002\001\uff89" + + "\000\006\051\u01b2\052\077\001\002\000\116\031\120\032" + + "\144\033\150\034\151\036\124\037\174\044\102\047\210" + + "\053\u01b4\072\220\073\116\077\165\100\125\102\215\103" + + "\204\104\153\105\127\112\152\113\212\114\045\115\134" + + "\124\113\125\154\142\200\143\177\150\047\152\161\153" + + "\205\154\162\155\040\156\176\157\121\160\171\161\135" + + "\162\043\163\044\164\147\165\137\001\002\000\002\001" + + "\uff90\000\120\031\120\032\144\033\150\034\151\036\124" + + "\037\174\044\102\047\210\053\223\072\220\073\116\077" + + "\165\100\125\101\225\102\215\103\204\104\153\105\127" + + "\112\152\113\212\114\045\115\134\124\113\125\154\142" + + "\200\143\177\150\047\152\161\153\205\154\162\155\040" + + "\156\176\157\121\160\171\161\135\162\043\163\044\164" + + "\147\165\137\001\002\000\002\001\uff8a\000\020\053\u01ba" + + "\062\u01a2\130\u01a3\134\u01a9\142\053\160\046\163\044\001" + + "\002\000\004\136\u01b9\001\002\000\002\001\ufea4\000\002" + + "\001\ufea5\000\010\142\053\160\046\163\044\001\002\000" + + "\002\001\uff79\000\116\031\120\032\144\033\150\034\151" + + "\036\124\037\174\044\102\047\210\053\u01be\072\220\073" + + "\116\077\165\100\125\102\215\103\204\104\153\105\127" + + "\112\152\113\212\114\045\115\134\124\113\125\154\142" + + "\200\143\177\150\047\152\161\153\205\154\162\155\040" + + "\156\176\157\121\160\171\161\135\162\043\163\044\164" + + "\147\165\137\001\002\000\002\001\uff8d\000\120\031\120" + + "\032\144\033\150\034\151\036\124\037\174\044\102\047" + + "\210\053\223\072\220\073\116\077\165\100\125\101\225" + + "\102\215\103\204\104\153\105\127\112\152\113\212\114" + + "\045\115\134\124\113\125\154\142\200\143\177\150\047" + + "\152\161\153\205\154\162\155\040\156\176\157\121\160" + + "\171\161\135\162\043\163\044\164\147\165\137\001\002" + + "\000\002\001\uff87\000\006\051\u01c1\052\077\001\002\000" + + "\116\031\120\032\144\033\150\034\151\036\124\037\174" + + "\044\102\047\210\053\u01c3\072\220\073\116\077\165\100" + + "\125\102\215\103\204\104\153\105\127\112\152\113\212" + + "\114\045\115\134\124\113\125\154\142\200\143\177\150" + + "\047\152\161\153\205\154\162\155\040\156\176\157\121" + + "\160\171\161\135\162\043\163\044\164\147\165\137\001" + + "\002\000\002\001\uff92\000\120\031\120\032\144\033\150" + + "\034\151\036\124\037\174\044\102\047\210\053\223\072" + + "\220\073\116\077\165\100\125\101\225\102\215\103\204" + + "\104\153\105\127\112\152\113\212\114\045\115\134\124" + + "\113\125\154\142\200\143\177\150\047\152\161\153\205" + + "\154\162\155\040\156\176\157\121\160\171\161\135\162" + + "\043\163\044\164\147\165\137\001\002\000\002\001\uff8c" + + "\000\006\051\u01c6\052\077\001\002\000\116\031\120\032" + + "\144\033\150\034\151\036\124\037\174\044\102\047\210" + + "\053\u01c8\072\220\073\116\077\165\100\125\102\215\103" + + "\204\104\153\105\127\112\152\113\212\114\045\115\134" + + "\124\113\125\154\142\200\143\177\150\047\152\161\153" + + "\205\154\162\155\040\156\176\157\121\160\171\161\135" + + "\162\043\163\044\164\147\165\137\001\002\000\002\001" + + "\uff91\000\120\031\120\032\144\033\150\034\151\036\124" + + "\037\174\044\102\047\210\053\223\072\220\073\116\077" + + "\165\100\125\101\225\102\215\103\204\104\153\105\127" + + "\112\152\113\212\114\045\115\134\124\113\125\154\142" + + "\200\143\177\150\047\152\161\153\205\154\162\155\040" + + "\156\176\157\121\160\171\161\135\162\043\163\044\164" + + "\147\165\137\001\002\000\002\001\uff8b\000\010\144\375" + + "\145\373\146\374\001\uff1a\000\002\001\uff2e\000\002\001" + + "\ufef3\000\002\001\ufef6\000\076\031\120\032\144\033\150" + + "\034\151\037\174\044\102\047\267\053\223\073\116\077" + + "\276\100\125\102\215\103\204\105\127\112\152\114\045" + + "\124\113\142\041\150\047\152\161\154\264\155\040\156" + + "\176\157\277\160\171\161\263\162\043\163\044\164\147" + + "\165\137\001\002\000\002\001\ufeec\000\010\045\243\052" + + "\u010f\100\242\001\002\000\002\001\uff5b\000\076\031\120" + + "\032\144\033\150\034\151\037\174\044\102\047\267\053" + + "\223\073\116\077\276\100\125\102\215\103\204\105\127" + + "\112\152\114\045\124\113\142\041\150\047\152\161\154" + + "\264\155\040\156\176\157\277\160\171\161\263\162\043" + + "\163\044\164\147\165\137\001\002\000\076\031\120\032" + + "\144\033\150\034\151\037\174\044\102\047\267\053\223" + + "\073\116\077\276\100\125\102\215\103\204\105\127\112" + + "\152\114\045\124\113\142\041\150\047\152\161\154\264" + + "\155\040\156\176\157\277\160\171\161\263\162\043\163" + + "\044\164\147\165\137\001\002\000\002\001\ufed4\000\002" + + "\001\ufed0\000\116\031\120\032\144\033\150\034\151\036" + + "\124\037\174\044\102\047\210\053\223\072\220\073\116" + + "\077\165\100\125\102\215\103\204\104\153\105\127\112" + + "\152\113\212\114\045\115\134\124\113\125\154\142\200" + + "\143\177\150\047\152\161\153\205\154\162\155\040\156" + + "\176\157\121\160\171\161\135\162\043\163\044\164\147" + + "\165\137\001\002\000\116\031\120\032\144\033\150\034" + + "\151\036\u0139\037\174\044\102\047\267\053\223\072\261" + + "\073\116\077\262\100\125\102\215\103\204\104\u0138\105" + + "\127\112\152\113\u0137\114\045\115\u0130\124\113\125\u0136" + + "\142\u012e\143\u013b\150\047\152\161\153\u012f\154\264\155" + + "\040\156\176\157\272\160\171\161\263\162\043\163\044" + + "\164\147\165\137\001\002\000\002\001\uff42\000\002\001" + + "\uff4c\000\002\001\uff4a\000\004\056\u01dc\001\uff49\000\116" + + "\031\120\032\144\033\150\034\151\036\124\037\174\044" + + "\102\047\210\053\223\072\220\073\116\077\165\100\125" + + "\102\215\103\204\104\153\105\127\112\152\113\212\114" + + "\045\115\134\124\113\125\154\142\200\143\177\150\047" + + "\152\161\153\205\154\162\155\040\156\176\157\121\160" + + "\171\161\135\162\043\163\044\164\147\165\137\001\002" + + "\000\002\001\uff4b\000\002\001\uff4e\000\002\001\uff4d\000" + + "\002\001\ufea7\000\002\001\uff81\000\120\031\120\032\144" + + "\033\150\034\151\036\124\037\174\044\102\047\210\053" + + "\223\072\220\073\116\077\165\100\125\101\225\102\215" + + "\103\204\104\153\105\127\112\152\113\212\114\045\115" + + "\134\124\113\125\154\142\200\143\177\150\047\152\161" + + "\153\205\154\162\155\040\156\176\157\121\160\171\161" + + "\135\162\043\163\044\164\147\165\137\001\002\000\002" + + "\001\uff7b\000\002\001\uff97\000\010\051\u01ad\052\077\060" + + "\u01e6\001\002\000\116\031\120\032\144\033\150\034\151" + + "\036\124\037\174\044\102\047\210\053\u01e8\072\220\073" + + "\116\077\165\100\125\102\215\103\204\104\153\105\127" + + "\112\152\113\212\114\045\115\134\124\113\125\154\142" + + "\200\143\177\150\047\152\161\153\205\154\162\155\040" + + "\156\176\157\121\160\171\161\135\162\043\163\044\164" + + "\147\165\137\001\002\000\002\001\uff82\000\120\031\120" + + "\032\144\033\150\034\151\036\124\037\174\044\102\047" + + "\210\053\223\072\220\073\116\077\165\100\125\101\225" + + "\102\215\103\204\104\153\105\127\112\152\113\212\114" + + "\045\115\134\124\113\125\154\142\200\143\177\150\047" + + "\152\161\153\205\154\162\155\040\156\176\157\121\160" + + "\171\161\135\162\043\163\044\164\147\165\137\001\002" + + "\000\002\001\uff7c\000\004\051\u01eb\001\002\000\116\031" + + "\120\032\144\033\150\034\151\036\124\037\174\044\102" + + "\047\210\053\223\072\220\073\116\077\165\100\125\102" + + "\215\103\204\104\153\105\127\112\152\113\212\114\045" + + "\115\134\124\113\125\154\142\200\143\177\150\047\152" + + "\161\153\205\154\162\155\040\156\176\157\121\160\171" + + "\161\135\162\043\163\044\164\147\165\137\001\002\000" + + "\004\100\242\001\002\000\002\001\uffbf\000\002\001\uff72" + + "\000\116\031\120\032\144\033\150\034\151\036\124\037" + + "\174\044\102\047\210\053\u01f1\072\220\073\116\077\165" + + "\100\125\102\215\103\204\104\153\105\127\112\152\113" + + "\212\114\045\115\134\124\113\125\154\142\200\143\177" + + "\150\047\152\161\153\205\154\162\155\040\156\176\157" + + "\121\160\171\161\135\162\043\163\044\164\147\165\137" + + "\001\002\000\002\001\uff80\000\120\031\120\032\144\033" + + "\150\034\151\036\124\037\174\044\102\047\210\053\223" + + "\072\220\073\116\077\165\100\125\101\225\102\215\103" + + "\204\104\153\105\127\112\152\113\212\114\045\115\134" + + "\124\113\125\154\142\200\143\177\150\047\152\161\153" + + "\205\154\162\155\040\156\176\157\121\160\171\161\135" + + "\162\043\163\044\164\147\165\137\001\002\000\002\001" + + "\uff7a\000\022\052\072\053\063\062\065\130\064\134\074" + + "\142\053\160\046\163\044\001\uff75\000\002\001\uff73\000" + + "\010\051\u01c6\052\077\060\u01f6\001\002\000\116\031\120" + + "\032\144\033\150\034\151\036\124\037\174\044\102\047" + + "\210\053\u01f8\072\220\073\116\077\165\100\125\102\215" + + "\103\204\104\153\105\127\112\152\113\212\114\045\115" + + "\134\124\113\125\154\142\200\143\177\150\047\152\161" + + "\153\205\154\162\155\040\156\176\157\121\160\171\161" + + "\135\162\043\163\044\164\147\165\137\001\002\000\002" + + "\001\uff84\000\120\031\120\032\144\033\150\034\151\036" + + "\124\037\174\044\102\047\210\053\223\072\220\073\116" + + "\077\165\100\125\101\225\102\215\103\204\104\153\105" + + "\127\112\152\113\212\114\045\115\134\124\113\125\154" + + "\142\200\143\177\150\047\152\161\153\205\154\162\155" + + "\040\156\176\157\121\160\171\161\135\162\043\163\044" + + "\164\147\165\137\001\002\000\002\001\uff7e\000\010\051" + + "\u01c1\052\077\060\u01fb\001\002\000\116\031\120\032\144" + + "\033\150\034\151\036\124\037\174\044\102\047\210\053" + + "\u01fd\072\220\073\116\077\165\100\125\102\215\103\204" + + "\104\153\105\127\112\152\113\212\114\045\115\134\124" + + "\113\125\154\142\200\143\177\150\047\152\161\153\205" + + "\154\162\155\040\156\176\157\121\160\171\161\135\162" + + "\043\163\044\164\147\165\137\001\002\000\002\001\uff85" + + "\000\120\031\120\032\144\033\150\034\151\036\124\037" + + "\174\044\102\047\210\053\223\072\220\073\116\077\165" + + "\100\125\101\225\102\215\103\204\104\153\105\127\112" + + "\152\113\212\114\045\115\134\124\113\125\154\142\200" + + "\143\177\150\047\152\161\153\205\154\162\155\040\156" + + "\176\157\121\160\171\161\135\162\043\163\044\164\147" + + "\165\137\001\002\000\002\001\uff7f\000\010\051\u01b2\052" + + "\077\060\u0200\001\002\000\116\031\120\032\144\033\150" + + "\034\151\036\124\037\174\044\102\047\210\053\u0202\072" + + "\220\073\116\077\165\100\125\102\215\103\204\104\153" + + "\105\127\112\152\113\212\114\045\115\134\124\113\125" + + "\154\142\200\143\177\150\047\152\161\153\205\154\162" + + "\155\040\156\176\157\121\160\171\161\135\162\043\163" + + "\044\164\147\165\137\001\002\000\002\001\uff83\000\120" + + "\031\120\032\144\033\150\034\151\036\124\037\174\044" + + "\102\047\210\053\223\072\220\073\116\077\165\100\125" + + "\101\225\102\215\103\204\104\153\105\127\112\152\113" + + "\212\114\045\115\134\124\113\125\154\142\200\143\177" + + "\150\047\152\161\153\205\154\162\155\040\156\176\157" + + "\121\160\171\161\135\162\043\163\044\164\147\165\137" + + "\001\002\000\002\001\uff7d\000\004\140\u0205\001\002\000" + + "\004\051\u0206\001\002\000\116\031\120\032\144\033\150" + + "\034\151\036\124\037\174\044\102\047\210\053\223\072" + + "\220\073\116\077\165\100\125\102\215\103\204\104\153" + + "\105\127\112\152\113\212\114\045\115\134\124\113\125" + + "\154\142\200\143\177\150\047\152\161\153\205\154\162" + + "\155\040\156\176\157\121\160\171\161\135\162\043\163" + + "\044\164\147\165\137\001\002\000\004\100\242\001\002" + + "\000\002\001\uffc0\000\004\100\242\001\002\000\002\001" + + "\uffbe\000\116\031\120\032\144\033\150\034\151\036\124" + + "\037\174\044\102\047\210\053\223\072\220\073\116\077" + + "\165\100\125\102\215\103\204\104\153\105\127\112\152" + + "\113\212\114\045\115\134\124\113\125\154\142\200\143" + + "\177\150\047\152\161\153\205\154\162\155\040\156\176" + + "\157\121\160\171\161\135\162\043\163\044\164\147\165" + + "\137\001\002\000\022\052\072\053\063\062\065\130\064" + + "\134\074\142\053\160\046\163\044\001\uff75\000\022\052" + + "\072\053\063\062\065\130\064\134\074\142\053\160\046" + + "\163\044\001\uff75\000\004\137\u020f\001\002\000\004\051" + + "\u0210\001\002\000\116\031\120\032\144\033\150\034\151" + + "\036\124\037\174\044\102\047\210\053\223\072\220\073" + + "\116\077\165\100\125\102\215\103\204\104\153\105\127" + + "\112\152\113\212\114\045\115\134\124\113\125\154\142" + + "\200\143\177\150\047\152\161\153\205\154\162\155\040" + + "\156\176\157\121\160\171\161\135\162\043\163\044\164" + + "\147\165\137\001\002\000\004\100\242\001\002\000\002" + + "\001\uffc2\000\004\140\u0214\001\002\000\004\051\u0215\001" + + "\002\000\116\031\120\032\144\033\150\034\151\036\124" + + "\037\174\044\102\047\210\053\223\072\220\073\116\077" + + "\165\100\125\102\215\103\204\104\153\105\127\112\152" + + "\113\212\114\045\115\134\124\113\125\154\142\200\143" + + "\177\150\047\152\161\153\205\154\162\155\040\156\176" + + "\157\121\160\171\161\135\162\043\163\044\164\147\165" + + "\137\001\002\000\004\100\242\001\002\000\002\001\uffc3" + + "\000\004\100\242\001\002\000\002\001\uffc1\000\006\042" + + "\u021b\101\u021c\001\ufffd\000\010\142\053\160\046\163\044" + + "\001\002\000\020\114\045\142\041\150\047\155\040\160" + + "\046\162\043\163\044\001\uffa3\000\004\137\u0222\001\002" + + "\000\004\052\u0220\001\uffa2\000\002\001\uffa1\000\020\114" + + "\045\142\041\150\047\155\040\160\046\162\043\163\044" + + "\001\002\000\002\001\uffa0\000\004\042\u0223\001\ufffb\000" + + "\010\142\053\160\046\163\044\001\002\000\002\001\ufffa" + + "\000\002\001\ufffc\000\010\100\242\101\u0235\105\u0234\001" + + "\uffa9\000\004\055\u0228\001\002\000\010\142\053\160\046" + + "\163\044\001\002\000\010\100\242\101\u022c\105\u022b\001" + + "\002\000\002\001\uffb8\000\022\052\072\053\063\062\065" + + "\130\064\134\074\142\053\160\046\163\044\001\uff75\000" + + "\022\052\072\053\063\062\065\130\064\134\074\142\053" + + "\160\046\163\044\001\uff75\000\004\137\u022e\001\002\000" + + "\004\100\242\001\002\000\002\001\uffb9\000\004\140\u0231" + + "\001\002\000\004\100\242\001\002\000\002\001\uffba\000" + + "\002\001\uffbb\000\022\052\072\053\063\062\065\130\064" + + "\134\074\142\053\160\046\163\044\001\uff75\000\022\052" + + "\072\053\063\062\065\130\064\134\074\142\053\160\046" + + "\163\044\001\uff75\000\004\137\u0237\001\002\000\004\100" + + "\242\001\002\000\002\001\uffbc\000\004\140\u023a\001\002" + + "\000\004\100\242\001\002\000\002\001\uffbd\000\012\060" + + "\u023d\100\242\101\u0241\105\u0240\001\002\000\116\031\120" + + "\032\144\033\150\034\151\036\124\037\174\044\102\047" + + "\210\053\223\072\220\073\116\077\165\100\125\102\215" + + "\103\204\104\153\105\127\112\152\113\212\114\045\115" + + "\134\124\113\125\154\142\200\143\177\150\047\152\161" + + "\153\205\154\162\155\040\156\176\157\121\160\171\161" + + "\135\162\043\163\044\164\147\165\137\001\002\000\002" + + "\001\uffc6\000\002\001\uffc5\000\012\140\u0247\142\053\160" + + "\046\163\044\001\002\000\012\137\u0243\142\053\160\046" + + "\163\044\001\002\000\006\052\077\137\u0245\001\002\000" + + "\006\060\u023d\100\242\001\002\000\002\001\uffc7\000\006" + + "\060\u023d\100\242\001\002\000\002\001\uffc8\000\006\060" + + "\u023d\100\242\001\002\000\006\052\077\140\u0249\001\002" + + "\000\006\060\u023d\100\242\001\002\000\002\001\uffca\000" + + "\002\001\uffc9\000\002\001\uffc4\000\004\100\u024e\001\002" + + "\000\012\136\u0250\142\053\160\046\163\044\001\002\000" + + "\006\052\077\136\u0251\001\002\000\002\001\ufff8\000\002" + + "\001\ufff9\000\006\050\017\141\024\001\002\000\012\100" + + "\242\142\053\160\046\163\044\001\002\000\014\066\u0257" + + "\100\242\142\053\160\046\163\044\001\uffdc\000\004\066" + + "\u0257\001\uffdc\000\004\063\u0279\001\uffe1\000\006\061\u0258" + + "\164\u025b\001\002\000\004\164\u0270\001\002\000\022\077" + + "\u0269\114\u026e\142\u026c\150\u026f\155\u026b\160\046\162\u026d" + + "\163\044\001\002\000\004\052\u0266\001\uffdd\000\030\046" + + "\u025e\051\u025d\055\u025f\077\uffce\114\uffce\142\uffce\150\uffce" + + "\155\uffce\160\uffce\162\uffce\163\uffce\001\uffdf\000\002\001" + + "\uffdb\000\004\164\u0268\001\002\000\006\061\u0258\164\u0265" + + "\001\002\000\004\055\u0260\001\002\000\004\164\u0261\001" + + "\002\000\004\051\u0262\001\uffcd\000\004\164\u0263\001\002" + + "\000\002\001\uffcc\000\004\052\u0266\001\uffde\000\006\051" + + "\u025d\055\u025f\001\uffce\000\006\061\u0258\164\u0265\001\002" + + "\000\002\001\uffda\000\002\001\uffcb\000\002\001\uffd7\000" + + "\002\001\uffd9\000\002\001\uffd4\000\004\151\054\001\uffd6" + + "\000\002\001\uffd5\000\002\001\uffd3\000\002\001\uffd8\000" + + "\006\051\u0271\055\u0272\001\uffd2\000\004\164\u0277\001\002" + + "\000\004\055\u0273\001\002\000\004\164\u0274\001\002\000" + + "\004\051\u0275\001\uffd1\000\004\164\u0276\001\002\000\002" + + "\001\uffd0\000\002\001\uffcf\000\002\001\uffe6\000\004\164" + + "\u027a\001\002\000\002\001\uffe0\000\004\066\u0257\001\uffdc" + + "\000\004\066\u0257\001\uffdc\000\004\063\u0279\001\uffe1\000" + + "\002\001\uffe2\000\004\063\u0279\001\uffe1\000\002\001\uffe7" + + "\000\004\063\u0279\001\uffe1\000\002\001\uffe3\000\012\052" + + "\077\060\u0286\064\u0285\076\u0284\001\uffaa\000\020\114\045" + + "\142\041\150\047\155\040\160\046\162\043\163\044\001" + + "\002\000\020\114\045\142\041\150\047\155\040\160\046" + + "\162\043\163\044\001\002\000\020\114\045\142\041\150" + + "\047\155\040\160\046\162\043\163\044\001\002\000\004" + + "\100\u0288\001\002\000\022\052\072\053\063\062\065\130" + + "\064\134\074\142\053\160\046\163\044\001\uff75\000\004" + + "\136\u028a\001\002\000\004\100\242\001\uff6f\000\002\001" + + "\uffb5\000\002\001\uff6e\000\004\131\u028f\001\uffab\000\002" + + "\001\uff9f\000\020\114\045\142\041\150\047\155\040\160" + + "\046\162\043\163\044\001\002\000\002\001\uff9e\000\002" + + "\001\uffad\000\004\131\u028f\001\uffac\000\002\001\uffae\000" + + "\002\001\uffb0\000\004\101\u0296\001\uffff\000\012\061\u0298" + + "\142\053\160\046\163\044\001\002\000\002\001\uff96\000" + + "\010\142\053\160\046\163\044\001\002\000\006\052\u029a" + + "\137\u029b\001\002\000\012\061\u029d\142\053\160\046\163" + + "\044\001\002\000\002\001\ufffe\000\002\001\uff94\000\010" + + "\142\053\160\046\163\044\001\002\000\002\001\uff93\000" + + "\002\001\uff95\000\004\100\242\001\002\000\004\100\242" + + "\001\002\000\002\001\ufff7\000\002\001\ufff5\000\002\001" + + "\ufff6\000\014\066\u0257\100\242\142\053\160\046\163\044" + + "\001\uffdc\000\004\066\u0257\001\uffdc\000\004\063\u0279\001" + + "\uffe1\000\002\001\uffe8\000\004\066\u0257\001\uffdc\000\004" + + "\066\u0257\001\uffdc\000\004\063\u0279\001\uffe1\000\002\001" + + "\uffe4\000\004\063\u0279\001\uffe1\000\002\001\uffe9\000\004" + + "\063\u0279\001\uffe1\000\002\001\uffe5\000\004\100\242\001" + + "\002\000\004\100\242\001\002\000\002\001\ufff4\000\002" + + "\001\ufff2\000\002\001\ufff3\000\002\001\000" }); + + /** Access to parse-action table. */ + public short[][] action_table() {return _action_table;} + + /** reduce_goto table. */ + protected static final short[][] _reduce_table = + unpackFromStrings(new String[] { + "\000\u02b4\000\006\106\003\107\004\001\001\000\002\001" + + "\001\000\024\012\024\013\013\037\014\051\010\067\006" + + "\076\017\100\021\101\022\123\030\001\001\000\002\001" + + "\001\000\002\001\001\000\010\031\u02b2\053\u02b0\054\041" + + "\001\001\000\002\001\001\000\002\001\001\000\002\001" + + "\001\000\010\031\u02a5\053\u02a4\054\041\001\001\000\002" + + "\001\001\000\010\031\u02a1\053\u029f\054\041\001\001\000" + + "\002\001\001\000\002\001\001\000\006\053\u0294\054\041" + + "\001\001\000\006\100\021\101\u0292\001\001\000\010\053" + + "\066\054\041\055\u0282\001\001\000\002\001\001\000\002" + + "\001\001\000\002\001\001\000\002\001\001\000\002\001" + + "\001\000\002\001\001\000\006\053\u024c\054\041\001\001" + + "\000\006\053\u023b\054\041\001\001\000\010\053\u0225\054" + + "\041\102\u0226\001\001\000\006\053\u0219\054\041\001\001" + + "\000\010\053\036\054\041\102\047\001\001\000\002\001" + + "\001\000\002\001\001\000\002\001\001\000\002\001\001" + + "\000\002\001\001\000\002\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\002\001\001\000\006" + + "\053\051\054\041\001\001\000\002\001\001\000\002\001" + + "\001\000\004\054\054\001\001\000\002\001\001\000\002" + + "\001\001\000\002\001\001\000\140\002\106\003\105\004" + + "\165\005\104\006\132\007\131\010\142\011\141\021\110" + + "\022\107\023\202\024\201\025\155\026\154\030\u0208\031" + + "\210\040\103\041\102\042\206\043\205\044\216\045\215" + + "\046\174\047\172\053\200\054\041\057\122\060\121\061" + + "\113\062\111\063\145\064\144\065\116\066\114\070\130" + + "\071\127\073\157\074\156\102\135\113\140\114\137\115" + + "\171\116\167\117\213\120\212\121\163\122\162\001\001" + + "\000\016\014\070\015\065\017\u0203\053\066\054\041\055" + + "\067\001\001\000\016\014\070\015\065\017\072\053\066" + + "\054\041\055\067\001\001\000\010\053\066\054\041\055" + + "\u01fe\001\001\000\010\053\066\054\041\055\u01f9\001\001" + + "\000\010\053\066\054\041\055\u01f4\001\001\000\002\001" + + "\001\000\002\001\001\000\002\001\001\000\002\001\001" + + "\000\016\014\070\015\065\017\u01ed\053\066\054\041\055" + + "\067\001\001\000\002\001\001\000\010\053\066\054\041" + + "\055\075\001\001\000\010\053\066\054\041\055\u01e4\001" + + "\001\000\002\001\001\000\006\053\u01e3\054\041\001\001" + + "\000\140\002\106\003\105\004\165\005\104\006\132\007" + + "\131\010\142\011\141\021\110\022\107\023\202\024\201" + + "\025\155\026\154\030\u01e0\031\210\040\103\041\102\042" + + "\206\043\205\044\216\045\215\046\174\047\172\053\200" + + "\054\041\057\122\060\121\061\113\062\111\063\145\064" + + "\144\065\116\066\114\070\130\071\127\073\157\074\156" + + "\102\135\113\140\114\137\115\171\116\167\117\213\120" + + "\212\121\163\122\162\001\001\000\140\002\106\003\105" + + "\004\165\005\104\006\132\007\131\010\142\011\141\021" + + "\110\022\107\023\202\024\201\025\155\026\154\030\125" + + "\031\210\040\103\041\102\042\206\043\205\044\216\045" + + "\215\046\174\047\172\053\200\054\041\057\122\060\121" + + "\061\113\062\111\063\145\064\144\065\116\066\114\070" + + "\130\071\127\073\157\074\156\102\135\113\140\114\137" + + "\115\171\116\167\117\213\120\212\121\163\122\162\001" + + "\001\000\006\053\u01df\054\041\001\001\000\002\001\001" + + "\000\002\001\001\000\002\001\001\000\002\001\001\000" + + "\002\001\001\000\004\072\u01d2\001\001\000\002\001\001" + + "\000\002\001\001\000\016\014\070\015\u010c\016\u01cf\053" + + "\066\054\041\055\067\001\001\000\002\001\001\000\002" + + "\001\001\000\002\001\001\000\002\001\001\000\002\001" + + "\001\000\062\004\165\005\u01cc\006\132\007\131\021\110" + + "\022\107\023\202\024\201\031\210\046\174\047\172\053" + + "\200\054\041\061\u01cb\062\317\065\116\066\114\070\130" + + "\071\127\073\157\074\156\102\135\121\163\122\162\001" + + "\001\000\002\001\001\000\002\001\001\000\074\004\165" + + "\006\132\007\131\021\110\022\107\023\202\024\201\031" + + "\210\046\174\047\172\053\200\054\041\061\113\062\111" + + "\065\116\066\114\070\130\071\127\073\157\074\156\102" + + "\135\113\u01ca\114\u01c9\115\171\116\167\117\213\120\212" + + "\121\163\122\162\001\001\000\150\002\106\003\105\004" + + "\165\005\104\006\132\007\131\010\142\011\141\014\u01a6" + + "\020\u01a4\021\110\022\107\023\202\024\201\025\155\026" + + "\154\030\246\031\210\033\247\040\103\041\102\042\206" + + "\043\205\044\216\045\215\046\174\047\172\053\u01a7\054" + + "\041\055\u01a3\057\122\060\121\061\113\062\111\063\145" + + "\064\144\065\116\066\114\070\130\071\127\073\157\074" + + "\156\102\135\113\140\114\137\115\171\116\167\117\213" + + "\120\212\121\163\122\162\001\001\000\002\001\001\000" + + "\140\002\106\003\105\004\165\005\104\006\132\007\131" + + "\010\142\011\141\021\110\022\107\023\202\024\201\025" + + "\155\026\154\030\u019f\031\210\040\103\041\102\042\206" + + "\043\205\044\216\045\215\046\174\047\172\053\200\054" + + "\041\057\122\060\121\061\113\062\111\063\145\064\144" + + "\065\116\066\114\070\130\071\127\073\157\074\156\102" + + "\135\113\140\114\137\115\171\116\167\117\213\120\212" + + "\121\163\122\162\001\001\000\002\001\001\000\002\001" + + "\001\000\002\001\001\000\002\001\001\000\106\004\165" + + "\005\u0199\006\132\007\131\010\142\011\141\021\110\022" + + "\107\023\202\024\201\031\210\046\174\047\172\053\200" + + "\054\041\057\u019a\060\u0163\061\113\062\111\065\116\066" + + "\114\070\130\071\127\073\157\074\156\102\135\113\140" + + "\114\137\115\171\116\167\117\213\120\212\121\163\122" + + "\162\001\001\000\022\004\165\005\u0197\031\210\053\200" + + "\054\041\102\135\121\u0198\122\360\001\001\000\002\001" + + "\001\000\002\001\001\000\002\001\001\000\002\001\001" + + "\000\002\001\001\000\002\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\002\001\001\000\002" + + "\001\001\000\002\001\001\000\016\014\070\015\u010c\016" + + "\u016a\053\066\054\041\055\067\001\001\000\074\004\165" + + "\006\132\007\131\021\110\022\107\023\202\024\201\031" + + "\210\046\174\047\172\053\200\054\041\061\113\062\111" + + "\065\116\066\114\070\130\071\127\073\157\074\156\102" + + "\135\113\u0169\114\u0168\115\171\116\167\117\213\120\212" + + "\121\163\122\162\001\001\000\074\004\165\006\132\007" + + "\131\021\110\022\107\023\202\024\201\031\210\046\174" + + "\047\172\053\200\054\041\061\113\062\111\065\116\066" + + "\114\070\130\071\127\073\157\074\156\102\135\113\u0167" + + "\114\u0166\115\171\116\167\117\213\120\212\121\163\122" + + "\162\001\001\000\002\001\001\000\002\001\001\000\002" + + "\001\001\000\002\001\001\000\016\014\070\015\u010c\016" + + "\u012a\053\066\054\041\055\067\001\001\000\022\004\165" + + "\005\u0128\031\210\053\200\054\041\102\135\121\u0129\122" + + "\357\001\001\000\002\001\001\000\002\001\001\000\062" + + "\004\165\005\u0127\006\132\007\131\021\110\022\107\023" + + "\202\024\201\031\210\046\174\047\172\053\200\054\041" + + "\061\u0126\062\361\065\116\066\114\070\130\071\127\073" + + "\157\074\156\102\135\121\163\122\162\001\001\000\002" + + "\001\001\000\140\002\106\003\105\004\165\005\104\006" + + "\132\007\131\010\142\011\141\021\110\022\107\023\202" + + "\024\201\025\155\026\154\030\u0125\031\210\040\103\041" + + "\102\042\206\043\205\044\216\045\215\046\174\047\172" + + "\053\200\054\041\057\122\060\121\061\113\062\111\063" + + "\145\064\144\065\116\066\114\070\130\071\127\073\157" + + "\074\156\102\135\113\140\114\137\115\171\116\167\117" + + "\213\120\212\121\163\122\162\001\001\000\002\001\001" + + "\000\002\001\001\000\002\001\001\000\002\001\001\000" + + "\016\014\070\015\u010c\016\u0119\053\066\054\041\055\067" + + "\001\001\000\002\001\001\000\016\014\070\015\u010c\016" + + "\u0117\053\066\054\041\055\067\001\001\000\074\004\165" + + "\006\132\007\131\021\110\022\107\023\202\024\201\031" + + "\210\046\174\047\172\053\200\054\041\061\113\062\111" + + "\065\116\066\114\070\130\071\127\073\157\074\156\102" + + "\135\113\u0116\114\u0115\115\171\116\167\117\213\120\212" + + "\121\163\122\162\001\001\000\074\004\165\006\132\007" + + "\131\021\110\022\107\023\202\024\201\031\210\046\174" + + "\047\172\053\200\054\041\061\113\062\111\065\116\066" + + "\114\070\130\071\127\073\157\074\156\102\135\113\u0113" + + "\114\u0112\115\171\116\167\117\213\120\212\121\163\122" + + "\162\001\001\000\002\001\001\000\002\001\001\000\002" + + "\001\001\000\016\014\070\015\u010c\016\u010d\053\066\054" + + "\041\055\067\001\001\000\074\004\165\006\132\007\131" + + "\021\110\022\107\023\202\024\201\031\210\046\174\047" + + "\172\053\200\054\041\061\113\062\111\065\116\066\114" + + "\070\130\071\127\073\157\074\156\102\135\113\u010b\114" + + "\u010a\115\171\116\167\117\213\120\212\121\163\122\162" + + "\001\001\000\002\001\001\000\002\001\001\000\022\004" + + "\165\005\u0108\031\210\053\200\054\041\102\135\121\u0109" + + "\122\326\001\001\000\002\001\001\000\074\004\165\006" + + "\132\007\131\021\110\022\107\023\202\024\201\031\210" + + "\046\174\047\172\053\200\054\041\061\113\062\111\065" + + "\116\066\114\070\130\071\127\073\157\074\156\102\135" + + "\113\371\114\370\115\171\116\167\117\213\120\212\121" + + "\163\122\162\001\001\000\002\001\001\000\002\001\001" + + "\000\010\050\234\053\233\054\041\001\001\000\002\001" + + "\001\000\002\001\001\000\062\004\165\005\223\006\132" + + "\007\131\021\110\022\107\023\202\024\201\031\210\046" + + "\174\047\172\053\200\054\041\061\221\062\220\065\116" + + "\066\114\070\130\071\127\073\157\074\156\102\135\121" + + "\163\122\162\001\001\000\002\001\001\000\002\001\001" + + "\000\002\001\001\000\002\001\001\000\144\002\106\003" + + "\105\004\165\005\104\006\132\007\131\010\142\011\141" + + "\021\110\022\107\023\202\024\201\025\155\026\154\030" + + "\225\031\210\035\226\036\227\040\103\041\102\042\206" + + "\043\205\044\216\045\215\046\174\047\172\053\200\054" + + "\041\057\122\060\121\061\113\062\111\063\145\064\144" + + "\065\116\066\114\070\130\071\127\073\157\074\156\102" + + "\135\113\140\114\137\115\171\116\167\117\213\120\212" + + "\121\163\122\162\001\001\000\002\001\001\000\002\001" + + "\001\000\002\001\001\000\140\002\106\003\105\004\165" + + "\005\104\006\132\007\131\010\142\011\141\021\110\022" + + "\107\023\202\024\201\025\155\026\154\030\231\031\210" + + "\040\103\041\102\042\206\043\205\044\216\045\215\046" + + "\174\047\172\053\200\054\041\057\122\060\121\061\113" + + "\062\111\063\145\064\144\065\116\066\114\070\130\071" + + "\127\073\157\074\156\102\135\113\140\114\137\115\171" + + "\116\167\117\213\120\212\121\163\122\162\001\001\000" + + "\002\001\001\000\002\001\001\000\002\001\001\000\002" + + "\001\001\000\140\002\106\003\105\004\165\005\104\006" + + "\132\007\131\010\142\011\141\021\110\022\107\023\202" + + "\024\201\025\155\026\154\030\236\031\210\040\103\041" + + "\102\042\206\043\205\044\216\045\215\046\174\047\172" + + "\053\200\054\041\057\122\060\121\061\113\062\111\063" + + "\145\064\144\065\116\066\114\070\130\071\127\073\157" + + "\074\156\102\135\113\140\114\137\115\171\116\167\117" + + "\213\120\212\121\163\122\162\001\001\000\006\031\243" + + "\034\240\001\001\000\010\050\252\053\233\054\041\001" + + "\001\000\002\001\001\000\142\002\106\003\105\004\165" + + "\005\104\006\132\007\131\010\142\011\141\021\110\022" + + "\107\023\202\024\201\025\155\026\154\030\246\031\210" + + "\033\247\040\103\041\102\042\206\043\205\044\216\045" + + "\215\046\174\047\172\053\200\054\041\057\122\060\121" + + "\061\113\062\111\063\145\064\144\065\116\066\114\070" + + "\130\071\127\073\157\074\156\102\135\113\140\114\137" + + "\115\171\116\167\117\213\120\212\121\163\122\162\001" + + "\001\000\140\002\106\003\105\004\165\005\104\006\132" + + "\007\131\010\142\011\141\021\110\022\107\023\202\024" + + "\201\025\155\026\154\030\244\031\210\040\103\041\102" + + "\042\206\043\205\044\216\045\215\046\174\047\172\053" + + "\200\054\041\057\122\060\121\061\113\062\111\063\145" + + "\064\144\065\116\066\114\070\130\071\127\073\157\074" + + "\156\102\135\113\140\114\137\115\171\116\167\117\213" + + "\120\212\121\163\122\162\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\002\001\001\000\140" + + "\002\106\003\105\004\165\005\104\006\132\007\131\010" + + "\142\011\141\021\110\022\107\023\202\024\201\025\155" + + "\026\154\030\251\031\210\040\103\041\102\042\206\043" + + "\205\044\216\045\215\046\174\047\172\053\200\054\041" + + "\057\122\060\121\061\113\062\111\063\145\064\144\065" + + "\116\066\114\070\130\071\127\073\157\074\156\102\135" + + "\113\140\114\137\115\171\116\167\117\213\120\212\121" + + "\163\122\162\001\001\000\002\001\001\000\002\001\001" + + "\000\002\001\001\000\042\004\165\005\367\007\270\022" + + "\264\024\201\031\210\047\257\053\200\054\041\062\111" + + "\066\265\071\272\074\156\102\135\116\366\122\162\001" + + "\001\000\042\004\165\005\365\007\270\022\264\024\201" + + "\031\210\047\257\053\200\054\041\062\111\066\265\071" + + "\272\074\156\102\135\116\364\122\162\001\001\000\042" + + "\004\165\005\363\007\270\022\264\024\201\031\210\047" + + "\257\053\200\054\041\062\111\066\265\071\272\074\156" + + "\102\135\116\362\122\162\001\001\000\042\004\165\005" + + "\273\007\270\022\264\024\201\031\210\047\257\053\200" + + "\054\041\062\111\066\265\071\272\074\156\102\135\116" + + "\267\122\162\001\001\000\002\001\001\000\036\004\165" + + "\007\270\022\264\024\201\031\210\047\257\053\200\054" + + "\041\062\220\066\265\071\272\074\156\102\135\122\162" + + "\001\001\000\036\004\165\007\270\022\264\024\201\031" + + "\210\047\257\053\200\054\041\062\361\066\265\071\272" + + "\074\156\102\135\122\162\001\001\000\016\004\165\031" + + "\210\053\200\054\041\102\135\122\360\001\001\000\016" + + "\004\165\031\210\053\200\054\041\102\135\122\357\001" + + "\001\000\004\072\351\001\001\000\002\001\001\000\016" + + "\004\165\031\210\053\200\054\041\102\135\122\326\001" + + "\001\000\002\001\001\000\002\001\001\000\036\004\165" + + "\007\270\022\264\024\201\031\210\047\257\053\200\054" + + "\041\062\317\066\265\071\272\074\156\102\135\122\162" + + "\001\001\000\002\001\001\000\002\001\001\000\022\004" + + "\165\007\277\024\201\031\210\053\200\054\041\102\135" + + "\122\162\001\001\000\002\001\001\000\002\001\001\000" + + "\002\001\001\000\144\002\106\003\105\004\165\005\104" + + "\006\132\007\131\010\142\011\141\021\110\022\107\023" + + "\202\024\201\025\155\026\154\030\225\031\210\035\307" + + "\036\227\040\103\041\102\042\206\043\205\044\216\045" + + "\215\046\174\047\172\053\200\054\041\057\122\060\121" + + "\061\113\062\111\063\145\064\144\065\116\066\114\070" + + "\130\071\127\073\157\074\156\102\135\113\140\114\137" + + "\115\171\116\167\117\213\120\212\121\163\122\162\001" + + "\001\000\016\004\165\031\210\053\200\054\041\102\135" + + "\122\306\001\001\000\002\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\002\001\001\000\002" + + "\001\001\000\002\001\001\000\144\002\106\003\105\004" + + "\165\005\104\006\132\007\131\010\142\011\141\021\110" + + "\022\107\023\202\024\201\025\155\026\154\030\225\031" + + "\210\035\312\036\227\040\103\041\102\042\206\043\205" + + "\044\216\045\215\046\174\047\172\053\200\054\041\057" + + "\122\060\121\061\113\062\111\063\145\064\144\065\116" + + "\066\114\070\130\071\127\073\157\074\156\102\135\113" + + "\140\114\137\115\171\116\167\117\213\120\212\121\163" + + "\122\162\001\001\000\002\001\001\000\002\001\001\000" + + "\144\002\106\003\105\004\165\005\104\006\132\007\131" + + "\010\142\011\141\021\110\022\107\023\202\024\201\025" + + "\155\026\154\030\225\031\210\035\315\036\227\040\103" + + "\041\102\042\206\043\205\044\216\045\215\046\174\047" + + "\172\053\200\054\041\057\122\060\121\061\113\062\111" + + "\063\145\064\144\065\116\066\114\070\130\071\127\073" + + "\157\074\156\102\135\113\140\114\137\115\171\116\167" + + "\117\213\120\212\121\163\122\162\001\001\000\002\001" + + "\001\000\002\001\001\000\002\001\001\000\036\004\165" + + "\007\270\022\264\024\201\031\210\047\257\053\200\054" + + "\041\062\325\066\265\071\272\074\156\102\135\122\162" + + "\001\001\000\036\004\165\007\270\022\264\024\201\031" + + "\210\047\257\053\200\054\041\062\324\066\265\071\272" + + "\074\156\102\135\122\162\001\001\000\036\004\165\007" + + "\270\022\264\024\201\031\210\047\257\053\200\054\041" + + "\062\323\066\265\071\272\074\156\102\135\122\162\001" + + "\001\000\002\001\001\000\002\001\001\000\002\001\001" + + "\000\002\001\001\000\032\004\165\007\270\022\264\024" + + "\201\031\210\047\330\053\200\054\041\071\272\074\156" + + "\102\135\122\162\001\001\000\002\001\001\000\030\004" + + "\165\007\270\022\264\024\201\031\210\053\200\054\041" + + "\071\272\074\332\102\135\122\162\001\001\000\002\001" + + "\001\000\024\004\165\007\270\024\201\031\210\053\200" + + "\054\041\071\356\102\135\122\162\001\001\000\002\001" + + "\001\000\002\001\001\000\002\001\001\000\002\001\001" + + "\000\002\001\001\000\002\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\002\001\001\000\002" + + "\001\001\000\002\001\001\000\002\001\001\000\030\004" + + "\165\007\270\022\264\024\201\031\210\053\200\054\041" + + "\071\272\074\355\102\135\122\162\001\001\000\002\001" + + "\001\000\002\001\001\000\002\001\001\000\002\001\001" + + "\000\002\001\001\000\002\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\002\001\001\000\002" + + "\001\001\000\002\001\001\000\002\001\001\000\002\001" + + "\001\000\002\001\001\000\002\001\001\000\044\004\165" + + "\005\u0107\007\270\022\264\024\201\031\210\047\257\053" + + "\200\054\041\062\111\066\265\071\272\074\156\102\135" + + "\116\375\120\u0106\122\162\001\001\000\044\004\165\005" + + "\u0105\007\270\022\264\024\201\031\210\047\257\053\200" + + "\054\041\062\111\066\265\071\272\074\156\102\135\116" + + "\375\120\u0104\122\162\001\001\000\044\004\165\005\377" + + "\007\270\022\264\024\201\031\210\047\257\053\200\054" + + "\041\062\111\066\265\071\272\074\156\102\135\116\375" + + "\120\376\122\162\001\001\000\002\001\001\000\002\001" + + "\001\000\002\001\001\000\040\004\165\007\270\022\264" + + "\024\201\031\210\047\257\053\200\054\041\062\111\066" + + "\265\071\272\074\156\102\135\116\366\122\162\001\001" + + "\000\040\004\165\007\270\022\264\024\201\031\210\047" + + "\257\053\200\054\041\062\111\066\265\071\272\074\156" + + "\102\135\116\364\122\162\001\001\000\040\004\165\007" + + "\270\022\264\024\201\031\210\047\257\053\200\054\041" + + "\062\111\066\265\071\272\074\156\102\135\116\362\122" + + "\162\001\001\000\040\004\165\007\270\022\264\024\201" + + "\031\210\047\257\053\200\054\041\062\111\066\265\071" + + "\272\074\156\102\135\116\267\122\162\001\001\000\002" + + "\001\001\000\002\001\001\000\002\001\001\000\002\001" + + "\001\000\002\001\001\000\002\001\001\000\002\001\001" + + "\000\002\001\001\000\002\001\001\000\006\031\243\034" + + "\u010f\001\001\000\014\014\070\015\u0110\053\066\054\041" + + "\055\067\001\001\000\002\001\001\000\002\001\001\000" + + "\004\054\054\001\001\000\002\001\001\000\002\001\001" + + "\000\002\001\001\000\002\001\001\000\002\001\001\000" + + "\006\031\243\034\u0118\001\001\000\002\001\001\000\006" + + "\031\243\034\u011a\001\001\000\002\001\001\000\032\004" + + "\165\005\u011c\007\270\022\264\024\201\031\210\053\200" + + "\054\041\071\272\074\332\102\135\122\162\001\001\000" + + "\002\001\001\000\004\054\u011e\001\001\000\002\001\001" + + "\000\040\004\165\005\u0124\007\270\022\264\024\201\031" + + "\210\047\257\053\200\054\041\062\325\066\265\071\272" + + "\074\156\102\135\122\162\001\001\000\040\004\165\005" + + "\u0123\007\270\022\264\024\201\031\210\047\257\053\200" + + "\054\041\062\324\066\265\071\272\074\156\102\135\122" + + "\162\001\001\000\040\004\165\005\u0122\007\270\022\264" + + "\024\201\031\210\047\257\053\200\054\041\062\323\066" + + "\265\071\272\074\156\102\135\122\162\001\001\000\002" + + "\001\001\000\002\001\001\000\002\001\001\000\002\001" + + "\001\000\002\001\001\000\002\001\001\000\002\001\001" + + "\000\002\001\001\000\006\031\243\034\u012b\001\001\000" + + "\002\001\001\000\062\003\u0132\004\165\005\u0139\007\270" + + "\011\u0131\022\264\024\201\031\210\041\u0133\043\205\045" + + "\215\047\257\053\200\054\041\060\121\062\111\066\265" + + "\071\272\074\156\102\135\114\u0130\116\375\120\u0134\122" + + "\162\001\001\000\044\004\165\007\270\022\264\024\201" + + "\031\210\047\257\053\200\054\041\062\111\066\265\071" + + "\272\074\156\102\135\114\u0165\116\375\120\u0134\122\162" + + "\001\001\000\044\004\165\007\270\022\264\024\201\031" + + "\210\047\257\053\200\054\041\062\111\066\265\071\272" + + "\074\156\102\135\114\u0164\116\375\120\u0134\122\162\001" + + "\001\000\050\004\165\007\270\011\u0131\022\264\024\201" + + "\031\210\047\257\053\200\054\041\060\u0163\062\111\066" + + "\265\071\272\074\156\102\135\114\u0130\116\375\120\u0134" + + "\122\162\001\001\000\002\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\002\001\001\000\044" + + "\004\165\007\270\022\264\024\201\031\210\047\257\053" + + "\200\054\041\062\111\066\265\071\272\074\156\102\135" + + "\114\u0142\116\375\120\u0134\122\162\001\001\000\044\004" + + "\165\007\270\022\264\024\201\031\210\047\257\053\200" + + "\054\041\062\111\066\265\071\272\074\156\102\135\114" + + "\u0141\116\375\120\u0134\122\162\001\001\000\044\004\165" + + "\007\270\022\264\024\201\031\210\047\257\053\200\054" + + "\041\062\111\066\265\071\272\074\156\102\135\114\u0140" + + "\116\375\120\u0134\122\162\001\001\000\044\004\165\007" + + "\270\022\264\024\201\031\210\047\257\053\200\054\041" + + "\062\111\066\265\071\272\074\156\102\135\114\u013f\116" + + "\375\120\u0134\122\162\001\001\000\002\001\001\000\044" + + "\004\165\007\270\022\264\024\201\031\210\047\257\053" + + "\200\054\041\062\111\066\265\071\272\074\156\102\135" + + "\114\u013b\116\375\120\u0134\122\162\001\001\000\002\001" + + "\001\000\042\004\165\007\270\022\264\024\201\031\210" + + "\047\257\053\200\054\041\062\111\066\265\071\272\074" + + "\156\102\135\116\375\120\u0106\122\162\001\001\000\042" + + "\004\165\007\270\022\264\024\201\031\210\047\257\053" + + "\200\054\041\062\111\066\265\071\272\074\156\102\135" + + "\116\375\120\u0104\122\162\001\001\000\042\004\165\007" + + "\270\022\264\024\201\031\210\047\257\053\200\054\041" + + "\062\111\066\265\071\272\074\156\102\135\116\375\120" + + "\376\122\162\001\001\000\002\001\001\000\002\001\001" + + "\000\002\001\001\000\002\001\001\000\060\003\u0132\004" + + "\165\007\270\011\u0131\022\264\024\201\031\210\041\u0146" + + "\043\u0147\045\215\047\257\053\200\054\041\060\121\062" + + "\111\066\265\071\272\074\156\102\135\114\u0130\116\375" + + "\120\u0134\122\162\001\001\000\050\004\165\007\270\011" + + "\u0131\022\264\024\201\031\210\047\257\053\200\054\041" + + "\060\u0145\062\111\066\265\071\272\074\156\102\135\114" + + "\u0130\116\375\120\u0134\122\162\001\001\000\002\001\001" + + "\000\002\001\001\000\002\001\001\000\056\003\u0132\004" + + "\165\007\270\011\u0131\022\264\024\201\031\210\043\u014a" + + "\045\u0149\047\257\053\200\054\041\060\121\062\111\066" + + "\265\071\272\074\156\102\135\114\u0130\116\375\120\u0134" + + "\122\162\001\001\000\002\001\001\000\002\001\001\000" + + "\044\004\165\007\270\022\264\024\201\031\210\047\257" + + "\053\200\054\041\062\111\066\265\071\272\074\156\102" + + "\135\114\u0162\116\375\120\u0134\122\162\001\001\000\044" + + "\004\165\007\270\022\264\024\201\031\210\047\257\053" + + "\200\054\041\062\111\066\265\071\272\074\156\102\135" + + "\114\u0161\116\375\120\u0134\122\162\001\001\000\044\004" + + "\165\007\270\022\264\024\201\031\210\047\257\053\200" + + "\054\041\062\111\066\265\071\272\074\156\102\135\114" + + "\u0160\116\375\120\u0134\122\162\001\001\000\044\004\165" + + "\007\270\022\264\024\201\031\210\047\257\053\200\054" + + "\041\062\111\066\265\071\272\074\156\102\135\114\u015f" + + "\116\375\120\u0134\122\162\001\001\000\044\004\165\007" + + "\270\022\264\024\201\031\210\047\257\053\200\054\041" + + "\062\111\066\265\071\272\074\156\102\135\114\u015e\116" + + "\375\120\u0134\122\162\001\001\000\044\004\165\007\270" + + "\022\264\024\201\031\210\047\257\053\200\054\041\062" + + "\111\066\265\071\272\074\156\102\135\114\u015d\116\375" + + "\120\u0134\122\162\001\001\000\044\004\165\007\270\022" + + "\264\024\201\031\210\047\257\053\200\054\041\062\111" + + "\066\265\071\272\074\156\102\135\114\u015c\116\375\120" + + "\u0134\122\162\001\001\000\044\004\165\007\270\022\264" + + "\024\201\031\210\047\257\053\200\054\041\062\111\066" + + "\265\071\272\074\156\102\135\114\u015b\116\375\120\u0134" + + "\122\162\001\001\000\044\004\165\007\270\022\264\024" + + "\201\031\210\047\257\053\200\054\041\062\111\066\265" + + "\071\272\074\156\102\135\114\u015a\116\375\120\u0134\122" + + "\162\001\001\000\044\004\165\007\270\022\264\024\201" + + "\031\210\047\257\053\200\054\041\062\111\066\265\071" + + "\272\074\156\102\135\114\u0159\116\375\120\u0134\122\162" + + "\001\001\000\044\004\165\007\270\022\264\024\201\031" + + "\210\047\257\053\200\054\041\062\111\066\265\071\272" + + "\074\156\102\135\114\u0158\116\375\120\u0134\122\162\001" + + "\001\000\044\004\165\007\270\022\264\024\201\031\210" + + "\047\257\053\200\054\041\062\111\066\265\071\272\074" + + "\156\102\135\114\u0157\116\375\120\u0134\122\162\001\001" + + "\000\002\001\001\000\002\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\002\001\001\000\002" + + "\001\001\000\002\001\001\000\002\001\001\000\002\001" + + "\001\000\002\001\001\000\002\001\001\000\002\001\001" + + "\000\002\001\001\000\002\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\002\001\001\000\006" + + "\031\243\034\u016b\001\001\000\002\001\001\000\144\002" + + "\106\003\105\004\165\005\104\006\132\007\131\010\142" + + "\011\141\021\110\022\107\023\202\024\201\025\155\026" + + "\154\030\225\031\210\035\u016d\036\227\040\103\041\102" + + "\042\206\043\205\044\216\045\215\046\174\047\172\053" + + "\200\054\041\057\122\060\121\061\113\062\111\063\145" + + "\064\144\065\116\066\114\070\130\071\127\073\157\074" + + "\156\102\135\113\140\114\137\115\171\116\167\117\213" + + "\120\212\121\163\122\162\001\001\000\002\001\001\000" + + "\002\001\001\000\064\003\u0132\004\165\005\u0171\007\270" + + "\011\u0131\022\264\024\201\026\u0170\031\210\041\102\043" + + "\205\045\215\047\257\053\200\054\041\060\121\062\111" + + "\066\265\071\272\074\156\102\135\114\u0130\116\375\120" + + "\u0134\122\162\001\001\000\002\001\001\000\002\001\001" + + "\000\060\003\u0132\004\165\007\270\011\u0131\022\264\024" + + "\201\031\210\041\u0133\043\205\045\215\047\257\053\200" + + "\054\041\060\121\062\111\066\265\071\272\074\156\102" + + "\135\114\u0130\116\375\120\u0134\122\162\001\001\000\074" + + "\004\165\006\132\007\131\021\110\022\107\023\202\024" + + "\201\031\210\046\174\047\172\053\200\054\041\061\113" + + "\062\111\065\116\066\114\070\130\071\127\073\157\074" + + "\156\102\135\113\u0196\114\u0195\115\171\116\167\117\213" + + "\120\212\121\163\122\162\001\001\000\074\004\165\006" + + "\132\007\131\021\110\022\107\023\202\024\201\031\210" + + "\046\174\047\172\053\200\054\041\061\113\062\111\065" + + "\116\066\114\070\130\071\127\073\157\074\156\102\135" + + "\113\u0194\114\u0193\115\171\116\167\117\213\120\212\121" + + "\163\122\162\001\001\000\074\004\165\006\132\007\131" + + "\021\110\022\107\023\202\024\201\031\210\046\174\047" + + "\172\053\200\054\041\061\113\062\111\065\116\066\114" + + "\070\130\071\127\073\157\074\156\102\135\113\u0192\114" + + "\u0191\115\171\116\167\117\213\120\212\121\163\122\162" + + "\001\001\000\074\004\165\006\132\007\131\021\110\022" + + "\107\023\202\024\201\031\210\046\174\047\172\053\200" + + "\054\041\061\113\062\111\065\116\066\114\070\130\071" + + "\127\073\157\074\156\102\135\113\u0190\114\u018f\115\171" + + "\116\167\117\213\120\212\121\163\122\162\001\001\000" + + "\074\004\165\006\132\007\131\021\110\022\107\023\202" + + "\024\201\031\210\046\174\047\172\053\200\054\041\061" + + "\113\062\111\065\116\066\114\070\130\071\127\073\157" + + "\074\156\102\135\113\u018e\114\u018d\115\171\116\167\117" + + "\213\120\212\121\163\122\162\001\001\000\074\004\165" + + "\006\132\007\131\021\110\022\107\023\202\024\201\031" + + "\210\046\174\047\172\053\200\054\041\061\113\062\111" + + "\065\116\066\114\070\130\071\127\073\157\074\156\102" + + "\135\113\u018c\114\u018b\115\171\116\167\117\213\120\212" + + "\121\163\122\162\001\001\000\074\004\165\006\132\007" + + "\131\021\110\022\107\023\202\024\201\031\210\046\174" + + "\047\172\053\200\054\041\061\113\062\111\065\116\066" + + "\114\070\130\071\127\073\157\074\156\102\135\113\u018a" + + "\114\u0189\115\171\116\167\117\213\120\212\121\163\122" + + "\162\001\001\000\074\004\165\006\132\007\131\021\110" + + "\022\107\023\202\024\201\031\210\046\174\047\172\053" + + "\200\054\041\061\113\062\111\065\116\066\114\070\130" + + "\071\127\073\157\074\156\102\135\113\u0188\114\u0187\115" + + "\171\116\167\117\213\120\212\121\163\122\162\001\001" + + "\000\074\004\165\006\132\007\131\021\110\022\107\023" + + "\202\024\201\031\210\046\174\047\172\053\200\054\041" + + "\061\113\062\111\065\116\066\114\070\130\071\127\073" + + "\157\074\156\102\135\113\u0186\114\u0185\115\171\116\167" + + "\117\213\120\212\121\163\122\162\001\001\000\074\004" + + "\165\006\132\007\131\021\110\022\107\023\202\024\201" + + "\031\210\046\174\047\172\053\200\054\041\061\113\062" + + "\111\065\116\066\114\070\130\071\127\073\157\074\156" + + "\102\135\113\u0184\114\u0183\115\171\116\167\117\213\120" + + "\212\121\163\122\162\001\001\000\074\004\165\006\132" + + "\007\131\021\110\022\107\023\202\024\201\031\210\046" + + "\174\047\172\053\200\054\041\061\113\062\111\065\116" + + "\066\114\070\130\071\127\073\157\074\156\102\135\113" + + "\u0182\114\u0181\115\171\116\167\117\213\120\212\121\163" + + "\122\162\001\001\000\074\004\165\006\132\007\131\021" + + "\110\022\107\023\202\024\201\031\210\046\174\047\172" + + "\053\200\054\041\061\113\062\111\065\116\066\114\070" + + "\130\071\127\073\157\074\156\102\135\113\u0180\114\u017f" + + "\115\171\116\167\117\213\120\212\121\163\122\162\001" + + "\001\000\002\001\001\000\002\001\001\000\002\001\001" + + "\000\002\001\001\000\002\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\002\001\001\000\002" + + "\001\001\000\002\001\001\000\002\001\001\000\002\001" + + "\001\000\002\001\001\000\002\001\001\000\002\001\001" + + "\000\002\001\001\000\002\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\002\001\001\000\002" + + "\001\001\000\002\001\001\000\002\001\001\000\002\001" + + "\001\000\002\001\001\000\002\001\001\000\020\004\165" + + "\005\u019c\031\210\053\200\054\041\102\135\122\306\001" + + "\001\000\002\001\001\000\024\004\165\005\u019e\007\277" + + "\024\201\031\210\053\200\054\041\102\135\122\162\001" + + "\001\000\002\001\001\000\002\001\001\000\002\001\001" + + "\000\010\053\066\054\041\055\u01c4\001\001\000\010\053" + + "\066\054\041\055\u01bf\001\001\000\002\001\001\000\006" + + "\031\243\034\u01b6\001\001\000\010\053\066\054\041\055" + + "\u01b0\001\001\000\002\001\001\000\002\001\001\000\010" + + "\053\066\054\041\055\u01aa\001\001\000\010\053\066\054" + + "\041\055\u01ab\001\001\000\002\001\001\000\002\001\001" + + "\000\140\002\106\003\105\004\165\005\104\006\132\007" + + "\131\010\142\011\141\021\110\022\107\023\202\024\201" + + "\025\155\026\154\030\u01ad\031\210\040\103\041\102\042" + + "\206\043\205\044\216\045\215\046\174\047\172\053\200" + + "\054\041\057\122\060\121\061\113\062\111\063\145\064" + + "\144\065\116\066\114\070\130\071\127\073\157\074\156" + + "\102\135\113\140\114\137\115\171\116\167\117\213\120" + + "\212\121\163\122\162\001\001\000\002\001\001\000\140" + + "\002\106\003\105\004\165\005\104\006\132\007\131\010" + + "\142\011\141\021\110\022\107\023\202\024\201\025\155" + + "\026\154\030\u01af\031\210\040\103\041\102\042\206\043" + + "\205\044\216\045\215\046\174\047\172\053\200\054\041" + + "\057\122\060\121\061\113\062\111\063\145\064\144\065" + + "\116\066\114\070\130\071\127\073\157\074\156\102\135" + + "\113\140\114\137\115\171\116\167\117\213\120\212\121" + + "\163\122\162\001\001\000\002\001\001\000\002\001\001" + + "\000\140\002\106\003\105\004\165\005\104\006\132\007" + + "\131\010\142\011\141\021\110\022\107\023\202\024\201" + + "\025\155\026\154\030\u01b2\031\210\040\103\041\102\042" + + "\206\043\205\044\216\045\215\046\174\047\172\053\200" + + "\054\041\057\122\060\121\061\113\062\111\063\145\064" + + "\144\065\116\066\114\070\130\071\127\073\157\074\156" + + "\102\135\113\140\114\137\115\171\116\167\117\213\120" + + "\212\121\163\122\162\001\001\000\002\001\001\000\140" + + "\002\106\003\105\004\165\005\104\006\132\007\131\010" + + "\142\011\141\021\110\022\107\023\202\024\201\025\155" + + "\026\154\030\u01b4\031\210\040\103\041\102\042\206\043" + + "\205\044\216\045\215\046\174\047\172\053\200\054\041" + + "\057\122\060\121\061\113\062\111\063\145\064\144\065" + + "\116\066\114\070\130\071\127\073\157\074\156\102\135" + + "\113\140\114\137\115\171\116\167\117\213\120\212\121" + + "\163\122\162\001\001\000\002\001\001\000\012\014\u01ba" + + "\053\066\054\041\055\u01a3\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\010\053\066\054\041" + + "\055\u01b0\001\001\000\002\001\001\000\140\002\106\003" + + "\105\004\165\005\104\006\132\007\131\010\142\011\141" + + "\021\110\022\107\023\202\024\201\025\155\026\154\030" + + "\u01bc\031\210\040\103\041\102\042\206\043\205\044\216" + + "\045\215\046\174\047\172\053\200\054\041\057\122\060" + + "\121\061\113\062\111\063\145\064\144\065\116\066\114" + + "\070\130\071\127\073\157\074\156\102\135\113\140\114" + + "\137\115\171\116\167\117\213\120\212\121\163\122\162" + + "\001\001\000\002\001\001\000\140\002\106\003\105\004" + + "\165\005\104\006\132\007\131\010\142\011\141\021\110" + + "\022\107\023\202\024\201\025\155\026\154\030\u01be\031" + + "\210\040\103\041\102\042\206\043\205\044\216\045\215" + + "\046\174\047\172\053\200\054\041\057\122\060\121\061" + + "\113\062\111\063\145\064\144\065\116\066\114\070\130" + + "\071\127\073\157\074\156\102\135\113\140\114\137\115" + + "\171\116\167\117\213\120\212\121\163\122\162\001\001" + + "\000\002\001\001\000\002\001\001\000\140\002\106\003" + + "\105\004\165\005\104\006\132\007\131\010\142\011\141" + + "\021\110\022\107\023\202\024\201\025\155\026\154\030" + + "\u01c1\031\210\040\103\041\102\042\206\043\205\044\216" + + "\045\215\046\174\047\172\053\200\054\041\057\122\060" + + "\121\061\113\062\111\063\145\064\144\065\116\066\114" + + "\070\130\071\127\073\157\074\156\102\135\113\140\114" + + "\137\115\171\116\167\117\213\120\212\121\163\122\162" + + "\001\001\000\002\001\001\000\140\002\106\003\105\004" + + "\165\005\104\006\132\007\131\010\142\011\141\021\110" + + "\022\107\023\202\024\201\025\155\026\154\030\u01c3\031" + + "\210\040\103\041\102\042\206\043\205\044\216\045\215" + + "\046\174\047\172\053\200\054\041\057\122\060\121\061" + + "\113\062\111\063\145\064\144\065\116\066\114\070\130" + + "\071\127\073\157\074\156\102\135\113\140\114\137\115" + + "\171\116\167\117\213\120\212\121\163\122\162\001\001" + + "\000\002\001\001\000\002\001\001\000\140\002\106\003" + + "\105\004\165\005\104\006\132\007\131\010\142\011\141" + + "\021\110\022\107\023\202\024\201\025\155\026\154\030" + + "\u01c6\031\210\040\103\041\102\042\206\043\205\044\216" + + "\045\215\046\174\047\172\053\200\054\041\057\122\060" + + "\121\061\113\062\111\063\145\064\144\065\116\066\114" + + "\070\130\071\127\073\157\074\156\102\135\113\140\114" + + "\137\115\171\116\167\117\213\120\212\121\163\122\162" + + "\001\001\000\002\001\001\000\140\002\106\003\105\004" + + "\165\005\104\006\132\007\131\010\142\011\141\021\110" + + "\022\107\023\202\024\201\025\155\026\154\030\u01c8\031" + + "\210\040\103\041\102\042\206\043\205\044\216\045\215" + + "\046\174\047\172\053\200\054\041\057\122\060\121\061" + + "\113\062\111\063\145\064\144\065\116\066\114\070\130" + + "\071\127\073\157\074\156\102\135\113\140\114\137\115" + + "\171\116\167\117\213\120\212\121\163\122\162\001\001" + + "\000\002\001\001\000\002\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\034\004\165\005\u01ce" + + "\007\270\022\264\024\201\031\210\047\330\053\200\054" + + "\041\071\272\074\156\102\135\122\162\001\001\000\002" + + "\001\001\000\006\031\243\034\u01d0\001\001\000\002\001" + + "\001\000\026\004\165\005\u01d4\007\270\024\201\031\210" + + "\053\200\054\041\071\356\102\135\122\162\001\001\000" + + "\032\004\165\005\u01d3\007\270\022\264\024\201\031\210" + + "\053\200\054\041\071\272\074\355\102\135\122\162\001" + + "\001\000\002\001\001\000\002\001\001\000\126\002\106" + + "\003\105\004\165\005\u01d9\006\132\007\131\010\142\011" + + "\141\021\110\022\107\023\202\024\201\031\210\040\u01d8" + + "\041\u0146\042\206\043\u01da\044\216\045\215\046\174\047" + + "\172\053\200\054\041\057\122\060\121\061\113\062\111" + + "\065\116\066\114\070\130\071\127\073\157\074\156\102" + + "\135\113\140\114\137\115\171\116\167\117\213\120\212" + + "\121\163\122\162\001\001\000\052\004\165\005\u01d7\007" + + "\270\011\u0131\022\264\024\201\031\210\047\257\053\200" + + "\054\041\060\u0145\062\111\066\265\071\272\074\156\102" + + "\135\114\u0130\116\375\120\u0134\122\162\001\001\000\002" + + "\001\001\000\002\001\001\000\002\001\001\000\002\001" + + "\001\000\122\002\106\003\105\004\165\005\u01dc\006\132" + + "\007\131\010\142\011\141\021\110\022\107\023\202\024" + + "\201\031\210\042\u01dd\043\u014a\044\u01de\045\u0149\046\174" + + "\047\172\053\200\054\041\057\122\060\121\061\113\062" + + "\111\065\116\066\114\070\130\071\127\073\157\074\156" + + "\102\135\113\140\114\137\115\171\116\167\117\213\120" + + "\212\121\163\122\162\001\001\000\002\001\001\000\002" + + "\001\001\000\002\001\001\000\002\001\001\000\002\001" + + "\001\000\140\002\106\003\105\004\165\005\104\006\132" + + "\007\131\010\142\011\141\021\110\022\107\023\202\024" + + "\201\025\155\026\154\030\u01e2\031\210\040\103\041\102" + + "\042\206\043\205\044\216\045\215\046\174\047\172\053" + + "\200\054\041\057\122\060\121\061\113\062\111\063\145" + + "\064\144\065\116\066\114\070\130\071\127\073\157\074" + + "\156\102\135\113\140\114\137\115\171\116\167\117\213" + + "\120\212\121\163\122\162\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\140\002\106\003\105" + + "\004\165\005\104\006\132\007\131\010\142\011\141\021" + + "\110\022\107\023\202\024\201\025\155\026\154\030\u01e6" + + "\031\210\040\103\041\102\042\206\043\205\044\216\045" + + "\215\046\174\047\172\053\200\054\041\057\122\060\121" + + "\061\113\062\111\063\145\064\144\065\116\066\114\070" + + "\130\071\127\073\157\074\156\102\135\113\140\114\137" + + "\115\171\116\167\117\213\120\212\121\163\122\162\001" + + "\001\000\002\001\001\000\140\002\106\003\105\004\165" + + "\005\104\006\132\007\131\010\142\011\141\021\110\022" + + "\107\023\202\024\201\025\155\026\154\030\u01e8\031\210" + + "\040\103\041\102\042\206\043\205\044\216\045\215\046" + + "\174\047\172\053\200\054\041\057\122\060\121\061\113" + + "\062\111\063\145\064\144\065\116\066\114\070\130\071" + + "\127\073\157\074\156\102\135\113\140\114\137\115\171" + + "\116\167\117\213\120\212\121\163\122\162\001\001\000" + + "\002\001\001\000\002\001\001\000\140\002\106\003\105" + + "\004\165\005\104\006\132\007\131\010\142\011\141\021" + + "\110\022\107\023\202\024\201\025\155\026\154\030\u01eb" + + "\031\210\040\103\041\102\042\206\043\205\044\216\045" + + "\215\046\174\047\172\053\200\054\041\057\122\060\121" + + "\061\113\062\111\063\145\064\144\065\116\066\114\070" + + "\130\071\127\073\157\074\156\102\135\113\140\114\137" + + "\115\171\116\167\117\213\120\212\121\163\122\162\001" + + "\001\000\004\031\u01ec\001\001\000\002\001\001\000\002" + + "\001\001\000\140\002\106\003\105\004\165\005\104\006" + + "\132\007\131\010\142\011\141\021\110\022\107\023\202" + + "\024\201\025\155\026\154\030\u01ef\031\210\040\103\041" + + "\102\042\206\043\205\044\216\045\215\046\174\047\172" + + "\053\200\054\041\057\122\060\121\061\113\062\111\063" + + "\145\064\144\065\116\066\114\070\130\071\127\073\157" + + "\074\156\102\135\113\140\114\137\115\171\116\167\117" + + "\213\120\212\121\163\122\162\001\001\000\002\001\001" + + "\000\140\002\106\003\105\004\165\005\104\006\132\007" + + "\131\010\142\011\141\021\110\022\107\023\202\024\201" + + "\025\155\026\154\030\u01f1\031\210\040\103\041\102\042" + + "\206\043\205\044\216\045\215\046\174\047\172\053\200" + + "\054\041\057\122\060\121\061\113\062\111\063\145\064" + + "\144\065\116\066\114\070\130\071\127\073\157\074\156" + + "\102\135\113\140\114\137\115\171\116\167\117\213\120" + + "\212\121\163\122\162\001\001\000\002\001\001\000\016" + + "\014\070\015\065\017\u01f3\053\066\054\041\055\067\001" + + "\001\000\002\001\001\000\002\001\001\000\140\002\106" + + "\003\105\004\165\005\104\006\132\007\131\010\142\011" + + "\141\021\110\022\107\023\202\024\201\025\155\026\154" + + "\030\u01f6\031\210\040\103\041\102\042\206\043\205\044" + + "\216\045\215\046\174\047\172\053\200\054\041\057\122" + + "\060\121\061\113\062\111\063\145\064\144\065\116\066" + + "\114\070\130\071\127\073\157\074\156\102\135\113\140" + + "\114\137\115\171\116\167\117\213\120\212\121\163\122" + + "\162\001\001\000\002\001\001\000\140\002\106\003\105" + + "\004\165\005\104\006\132\007\131\010\142\011\141\021" + + "\110\022\107\023\202\024\201\025\155\026\154\030\u01f8" + + "\031\210\040\103\041\102\042\206\043\205\044\216\045" + + "\215\046\174\047\172\053\200\054\041\057\122\060\121" + + "\061\113\062\111\063\145\064\144\065\116\066\114\070" + + "\130\071\127\073\157\074\156\102\135\113\140\114\137" + + "\115\171\116\167\117\213\120\212\121\163\122\162\001" + + "\001\000\002\001\001\000\002\001\001\000\140\002\106" + + "\003\105\004\165\005\104\006\132\007\131\010\142\011" + + "\141\021\110\022\107\023\202\024\201\025\155\026\154" + + "\030\u01fb\031\210\040\103\041\102\042\206\043\205\044" + + "\216\045\215\046\174\047\172\053\200\054\041\057\122" + + "\060\121\061\113\062\111\063\145\064\144\065\116\066" + + "\114\070\130\071\127\073\157\074\156\102\135\113\140" + + "\114\137\115\171\116\167\117\213\120\212\121\163\122" + + "\162\001\001\000\002\001\001\000\140\002\106\003\105" + + "\004\165\005\104\006\132\007\131\010\142\011\141\021" + + "\110\022\107\023\202\024\201\025\155\026\154\030\u01fd" + + "\031\210\040\103\041\102\042\206\043\205\044\216\045" + + "\215\046\174\047\172\053\200\054\041\057\122\060\121" + + "\061\113\062\111\063\145\064\144\065\116\066\114\070" + + "\130\071\127\073\157\074\156\102\135\113\140\114\137" + + "\115\171\116\167\117\213\120\212\121\163\122\162\001" + + "\001\000\002\001\001\000\002\001\001\000\140\002\106" + + "\003\105\004\165\005\104\006\132\007\131\010\142\011" + + "\141\021\110\022\107\023\202\024\201\025\155\026\154" + + "\030\u0200\031\210\040\103\041\102\042\206\043\205\044" + + "\216\045\215\046\174\047\172\053\200\054\041\057\122" + + "\060\121\061\113\062\111\063\145\064\144\065\116\066" + + "\114\070\130\071\127\073\157\074\156\102\135\113\140" + + "\114\137\115\171\116\167\117\213\120\212\121\163\122" + + "\162\001\001\000\002\001\001\000\140\002\106\003\105" + + "\004\165\005\104\006\132\007\131\010\142\011\141\021" + + "\110\022\107\023\202\024\201\025\155\026\154\030\u0202" + + "\031\210\040\103\041\102\042\206\043\205\044\216\045" + + "\215\046\174\047\172\053\200\054\041\057\122\060\121" + + "\061\113\062\111\063\145\064\144\065\116\066\114\070" + + "\130\071\127\073\157\074\156\102\135\113\140\114\137" + + "\115\171\116\167\117\213\120\212\121\163\122\162\001" + + "\001\000\002\001\001\000\002\001\001\000\002\001\001" + + "\000\140\002\106\003\105\004\165\005\104\006\132\007" + + "\131\010\142\011\141\021\110\022\107\023\202\024\201" + + "\025\155\026\154\030\u0206\031\210\040\103\041\102\042" + + "\206\043\205\044\216\045\215\046\174\047\172\053\200" + + "\054\041\057\122\060\121\061\113\062\111\063\145\064" + + "\144\065\116\066\114\070\130\071\127\073\157\074\156" + + "\102\135\113\140\114\137\115\171\116\167\117\213\120" + + "\212\121\163\122\162\001\001\000\004\031\u0207\001\001" + + "\000\002\001\001\000\004\031\u0209\001\001\000\002\001" + + "\001\000\140\002\106\003\105\004\165\005\104\006\132" + + "\007\131\010\142\011\141\021\110\022\107\023\202\024" + + "\201\025\155\026\154\030\u0217\031\210\040\103\041\102" + + "\042\206\043\205\044\216\045\215\046\174\047\172\053" + + "\200\054\041\057\122\060\121\061\113\062\111\063\145" + + "\064\144\065\116\066\114\070\130\071\127\073\157\074" + + "\156\102\135\113\140\114\137\115\171\116\167\117\213" + + "\120\212\121\163\122\162\001\001\000\016\014\070\015" + + "\065\017\u0212\053\066\054\041\055\067\001\001\000\016" + + "\014\070\015\065\017\u020d\053\066\054\041\055\067\001" + + "\001\000\002\001\001\000\002\001\001\000\140\002\106" + + "\003\105\004\165\005\104\006\132\007\131\010\142\011" + + "\141\021\110\022\107\023\202\024\201\025\155\026\154" + + "\030\u0210\031\210\040\103\041\102\042\206\043\205\044" + + "\216\045\215\046\174\047\172\053\200\054\041\057\122" + + "\060\121\061\113\062\111\063\145\064\144\065\116\066" + + "\114\070\130\071\127\073\157\074\156\102\135\113\140" + + "\114\137\115\171\116\167\117\213\120\212\121\163\122" + + "\162\001\001\000\004\031\u0211\001\001\000\002\001\001" + + "\000\002\001\001\000\002\001\001\000\140\002\106\003" + + "\105\004\165\005\104\006\132\007\131\010\142\011\141" + + "\021\110\022\107\023\202\024\201\025\155\026\154\030" + + "\u0215\031\210\040\103\041\102\042\206\043\205\044\216" + + "\045\215\046\174\047\172\053\200\054\041\057\122\060" + + "\121\061\113\062\111\063\145\064\144\065\116\066\114" + + "\070\130\071\127\073\157\074\156\102\135\113\140\114" + + "\137\115\171\116\167\117\213\120\212\121\163\122\162" + + "\001\001\000\004\031\u0216\001\001\000\002\001\001\000" + + "\004\031\u0218\001\001\000\002\001\001\000\002\001\001" + + "\000\006\053\u0224\054\041\001\001\000\014\053\200\054" + + "\041\102\u021e\103\u021d\104\u021c\001\001\000\002\001\001" + + "\000\002\001\001\000\002\001\001\000\010\053\200\054" + + "\041\102\u0220\001\001\000\002\001\001\000\002\001\001" + + "\000\006\053\u0223\054\041\001\001\000\002\001\001\000" + + "\002\001\001\000\004\031\u0232\001\001\000\002\001\001" + + "\000\006\053\u0228\054\041\001\001\000\004\031\u0229\001" + + "\001\000\002\001\001\000\016\014\070\015\065\017\u022f" + + "\053\066\054\041\055\067\001\001\000\016\014\070\015" + + "\065\017\u022c\053\066\054\041\055\067\001\001\000\002" + + "\001\001\000\004\031\u022e\001\001\000\002\001\001\000" + + "\002\001\001\000\004\031\u0231\001\001\000\002\001\001" + + "\000\002\001\001\000\016\014\070\015\065\017\u0238\053" + + "\066\054\041\055\067\001\001\000\016\014\070\015\065" + + "\017\u0235\053\066\054\041\055\067\001\001\000\002\001" + + "\001\000\004\031\u0237\001\001\000\002\001\001\000\002" + + "\001\001\000\004\031\u023a\001\001\000\002\001\001\000" + + "\006\031\u023e\052\u023d\001\001\000\140\002\106\003\105" + + "\004\165\005\104\006\132\007\131\010\142\011\141\021" + + "\110\022\107\023\202\024\201\025\155\026\154\030\u024b" + + "\031\210\040\103\041\102\042\206\043\205\044\216\045" + + "\215\046\174\047\172\053\200\054\041\057\122\060\121" + + "\061\113\062\111\063\145\064\144\065\116\066\114\070" + + "\130\071\127\073\157\074\156\102\135\113\140\114\137" + + "\115\171\116\167\117\213\120\212\121\163\122\162\001" + + "\001\000\002\001\001\000\002\001\001\000\010\053\066" + + "\054\041\055\u0247\001\001\000\010\053\066\054\041\055" + + "\u0241\001\001\000\002\001\001\000\006\031\u023e\052\u0243" + + "\001\001\000\002\001\001\000\006\031\u023e\052\u0245\001" + + "\001\000\002\001\001\000\006\031\u023e\052\u024a\001\001" + + "\000\002\001\001\000\006\031\u023e\052\u0249\001\001\000" + + "\002\001\001\000\002\001\001\000\002\001\001\000\002" + + "\001\001\000\010\053\066\054\041\055\u024e\001\001\000" + + "\002\001\001\000\002\001\001\000\002\001\001\000\004" + + "\013\u0252\001\001\000\010\031\u0254\053\u0253\054\041\001" + + "\001\000\012\031\u027b\053\u027a\054\041\075\u027c\001\001" + + "\000\004\075\u0255\001\001\000\004\027\u0277\001\001\000" + + "\010\110\u0258\111\u025b\112\u0259\001\001\000\002\001\001" + + "\000\006\053\u0269\054\041\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\002\001\001\000\010" + + "\110\u0258\111\u025b\112\u0263\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\002\001\001\000\002" + + "\001\001\000\002\001\001\000\002\001\001\000\006\110" + + "\u0258\111\u0266\001\001\000\002\001\001\000\002\001\001" + + "\000\002\001\001\000\002\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\002\001\001\000\002" + + "\001\001\000\002\001\001\000\002\001\001\000\002\001" + + "\001\000\002\001\001\000\002\001\001\000\002\001\001" + + "\000\002\001\001\000\002\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\004\075\u0280\001\001" + + "\000\004\075\u027e\001\001\000\004\027\u027d\001\001\000" + + "\002\001\001\000\004\027\u027f\001\001\000\002\001\001" + + "\000\004\027\u0281\001\001\000\002\001\001\000\004\077" + + "\u0286\001\001\000\012\053\200\054\041\102\u028d\105\u0291" + + "\001\001\000\010\053\200\054\041\102\u0290\001\001\000" + + "\012\053\200\054\041\102\u028d\105\u028c\001\001\000\002" + + "\001\001\000\016\014\070\015\065\017\u0288\053\066\054" + + "\041\055\067\001\001\000\002\001\001\000\006\031\u028b" + + "\032\u028a\001\001\000\002\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\010\053\200\054\041" + + "\102\u028f\001\001\000\002\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001\000\002\001\001\000\002" + + "\001\001\000\010\053\u0296\054\041\056\u0298\001\001\000" + + "\002\001\001\000\006\053\u029e\054\041\001\001\000\002" + + "\001\001\000\006\053\u029b\054\041\001\001\000\002\001" + + "\001\000\002\001\001\000\006\053\u029d\054\041\001\001" + + "\000\002\001\001\000\002\001\001\000\004\031\u02a3\001" + + "\001\000\004\031\u02a2\001\001\000\002\001\001\000\002" + + "\001\001\000\002\001\001\000\012\031\u02a9\053\u02a8\054" + + "\041\075\u02aa\001\001\000\004\075\u02a6\001\001\000\004" + + "\027\u02a7\001\001\000\002\001\001\000\004\075\u02ae\001" + + "\001\000\004\075\u02ac\001\001\000\004\027\u02ab\001\001" + + "\000\002\001\001\000\004\027\u02ad\001\001\000\002\001" + + "\001\000\004\027\u02af\001\001\000\002\001\001\000\004" + + "\031\u02b4\001\001\000\004\031\u02b3\001\001\000\002\001" + + "\001\000\002\001\001\000\002\001\001\000\002\001\001" + + "" }); + + /** Access to reduce_goto table. */ + public short[][] reduce_table() {return _reduce_table;} + + /** Instance of action encapsulation class. */ + protected CUP$CompParser$actions action_obj; + + /** Action encapsulation object initializer. */ + protected void init_actions() + { + action_obj = new CUP$CompParser$actions(this); + } + + /** Invoke a user supplied parse action. */ + public java_cup.runtime.Symbol do_action( + int act_num, + java_cup.runtime.lr_parser parser, + java.util.Stack stack, + int top) + throws java.lang.Exception + { + /* call code in generated class */ + return action_obj.CUP$CompParser$do_action(act_num, parser, stack, top); + } + + /** Indicates start state. */ + public int start_state() {return 0;} + /** Indicates start production. */ + public int start_production() {return 1;} + + /** EOF Symbol index. */ + public int EOF_sym() {return 0;} + + /** error Symbol index. */ + public int error_sym() {return 1;} + + + + + public CompModule alloymodule=null; + + @Override public Symbol parse() throws java.lang.Exception { + int act; // current action code + Symbol lhs_sym = null; // the Symbol/stack element returned by a reduce + short handle_size, lhs_sym_num; // information about production being reduced with + boolean logging = "yes".equals(System.getProperty("debug")); + production_tab = production_table(); + action_tab = action_table(); + reduce_tab = reduce_table(); + init_actions(); + user_init(); + // start + cur_token = scan(); + stack.removeAllElements(); + stack.push(getSymbolFactory().startSymbol("START", 0, start_state())); + tos = 0; + for (_done_parsing = false; !_done_parsing; ) { + act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym); + if (act > 0) { // "shift"; thus, we shift to the encoded state by pushing it on the stack + if (logging) System.out.println("shift " + cur_token.sym); + cur_token.parse_state = act-1; + stack.push(cur_token); + tos++; + cur_token = scan(); + } else if (act<0) { // "reduce" + if (logging) System.out.println("reduce " + ((-act)-1)); + lhs_sym = do_action((-act)-1, this, stack, tos); + lhs_sym_num = production_tab[(-act)-1][0]; + handle_size = production_tab[(-act)-1][1]; + for (int i = 0; i < handle_size; i++) { stack.pop(); tos--; } + act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num); + lhs_sym.parse_state = act; + stack.push(lhs_sym); + tos++; + } else { // "error" + if (logging) System.out.println("error"); + syntax_error(cur_token); + done_parsing(); + } + } + return lhs_sym; + } + + public void syntax_error(Symbol x) throws Err { + Map ch = new LinkedHashMap(); + ch.put(CompSym.ARROW, "->"); + ch.put(CompSym.ANY_ARROW_SOME, "->"); + ch.put(CompSym.ANY_ARROW_ONE, "->"); + ch.put(CompSym.ANY_ARROW_LONE, "->"); + ch.put(CompSym.SOME_ARROW_ANY, "some"); + ch.put(CompSym.SOME_ARROW_SOME, "some"); + ch.put(CompSym.SOME_ARROW_ONE, "some"); + ch.put(CompSym.SOME_ARROW_LONE, "some"); + ch.put(CompSym.ONE_ARROW_ANY, "one"); + ch.put(CompSym.ONE_ARROW_SOME, "one"); + ch.put(CompSym.ONE_ARROW_ONE, "one"); + ch.put(CompSym.ONE_ARROW_LONE, "one"); + ch.put(CompSym.LONE_ARROW_ANY, "lone"); + ch.put(CompSym.LONE_ARROW_SOME, "lone"); + ch.put(CompSym.LONE_ARROW_ONE, "lone"); + ch.put(CompSym.LONE_ARROW_LONE, "lone"); + ch.put(CompSym.INTADD, "fun"); + ch.put(CompSym.INTSUB, "fun"); + ch.put(CompSym.INTMUL, "fun"); + ch.put(CompSym.INTDIV, "fun"); + ch.put(CompSym.INTREM, "fun"); + ch.put(CompSym.INTMIN, "fun"); + ch.put(CompSym.INTMAX, "fun"); + ch.put(CompSym.INTNEXT, "fun"); + ch.put(CompSym.TOTALORDER, "pred"); + ch.put(CompSym.ABSTRACT, "abstract"); + ch.put(CompSym.ALL, "all"); + ch.put(CompSym.ALL2, "all"); + ch.put(CompSym.AMPERSAND, "&"); + ch.put(CompSym.AND, "&&"); + ch.put(CompSym.AS, "as"); + ch.put(CompSym.ASSERT, "assert"); + ch.put(CompSym.AT, "@"); + ch.put(CompSym.BAR, "|"); + ch.put(CompSym.BUT, "but"); + ch.put(CompSym.CARET, "^"); + ch.put(CompSym.CHECK, "check"); + ch.put(CompSym.COLON, ":"); + ch.put(CompSym.COMMA, ", "); + ch.put(CompSym.DISJ, "disj"); + ch.put(CompSym.DOMAIN, "<:"); + ch.put(CompSym.DOT, "."); + ch.put(CompSym.ELSE, "else"); + ch.put(CompSym.ENUM, "enum"); + ch.put(CompSym.EQUALS, "="); + ch.put(CompSym.EXACTLY, "exactly"); + ch.put(CompSym.EXH, "exh"); + ch.put(CompSym.EXPECT, "expect"); + ch.put(CompSym.EXTENDS, "extends"); + ch.put(CompSym.FACT, "fact"); + ch.put(CompSym.FOR, "for"); + ch.put(CompSym.FUN, "fun"); + ch.put(CompSym.GT, ">"); + ch.put(CompSym.GTE, ">="); + ch.put(CompSym.HASH, "#"); + ch.put(CompSym.IDEN, "iden"); + ch.put(CompSym.IFF, "iff"); + ch.put(CompSym.IMPLIES, "=>"); + ch.put(CompSym.IN, "in"); + ch.put(CompSym.INT, "int"); + ch.put(CompSym.LBRACE, "{"); + ch.put(CompSym.LBRACKET, "["); + ch.put(CompSym.LET, "let"); + ch.put(CompSym.LONE2, "lone"); + ch.put(CompSym.LONE, "lone"); + ch.put(CompSym.LPAREN, "("); + ch.put(CompSym.LT, "<"); + ch.put(CompSym.LTE, "<="); + ch.put(CompSym.MINUS, "-"); + ch.put(CompSym.MODULE, "module"); + ch.put(CompSym.NO2, "no"); + ch.put(CompSym.NO, "no"); + ch.put(CompSym.NONE, "none"); + ch.put(CompSym.NOT, "!"); + ch.put(CompSym.NOTEQUALS, "!"); + ch.put(CompSym.NOTGT, "!"); + ch.put(CompSym.NOTGTE, "!"); + ch.put(CompSym.NOTIN, "!"); + ch.put(CompSym.NOTLT, "!"); + ch.put(CompSym.NOTLTE, "!"); + ch.put(CompSym.ONE2, "one"); + ch.put(CompSym.ONE, "one"); + ch.put(CompSym.OPEN, "open"); + ch.put(CompSym.OR, "||"); + ch.put(CompSym.PART, "part"); + ch.put(CompSym.PLUS, "+"); + ch.put(CompSym.PLUSPLUS, "++"); + ch.put(CompSym.PRED, "pred"); + ch.put(CompSym.PRIVATE, "private"); + ch.put(CompSym.RANGE, ":>"); + ch.put(CompSym.RBRACE, "}"); + ch.put(CompSym.RBRACKET, "]"); + ch.put(CompSym.RPAREN, ")"); + ch.put(CompSym.RUN, "run"); + ch.put(CompSym.SEQ, "seq"); + ch.put(CompSym.SET, "set"); + ch.put(CompSym.SHL, "<<"); + ch.put(CompSym.SHR, ">>>"); + ch.put(CompSym.SHA, ">>"); + ch.put(CompSym.SIG, "sig"); + ch.put(CompSym.SIGINT, "Int"); + ch.put(CompSym.SLASH, "/"); + ch.put(CompSym.SOME2, "some"); + ch.put(CompSym.SOME, "some"); + ch.put(CompSym.STAR, "*"); + ch.put(CompSym.STRING, "String"); + ch.put(CompSym.SUM2, "sum"); + ch.put(CompSym.SUM, "sum"); + ch.put(CompSym.THIS, "this"); + ch.put(CompSym.TILDE, "~"); + ch.put(CompSym.UNIV, "univ"); + ch.put(CompSym.ID, "NAME"); + ch.put(CompSym.NUMBER, "NUMBER"); + ch.put(CompSym.STR, "STRING"); + TreeSet list = new TreeSet(); + Pos p=Pos.UNKNOWN; + if (x!=null && x.value instanceof Pos) p=(Pos)(x.value); + else if (x!=null && x.value instanceof Expr) p=((Expr)(x.value)).pos; + else if (x!=null) p=x.pos; + if (!stack.empty()) for(Map.Entry e:ch.entrySet()) { + int key=e.getKey(), act=get_action(((Symbol)stack.peek()).parse_state, key); + if (act==0) continue; + try { + if (act>0 || alloy_confirm(key)) list.add(e.getValue()); + } catch(Throwable ex) { + // If the parser is really really confused, alloy_confirm() could fail with array out-of-bound exception, etc. + } + } + String result="There are "+list.size()+" possible tokens that can appear here:\n"; + for(String item:list) result=result+item+" "; + throw new ErrorSyntax(p, (list.size()!=0)?result:""); + } + + private boolean alloy_confirm(int key) { + int state = ((Symbol)stack.peek()).parse_state; + Stack newstack=new Stack(); for(Object x:stack) newstack.push(x); + while(true) { + int act = get_action(state, key); + if (act>0) return true; + if (act==0) return false; + int lhs_sym_num = production_tab[(-act)-1][0]; + int handle_size = production_tab[(-act)-1][1]; + for (int i = 0; i < handle_size; i++) { if (newstack.empty()) return false; newstack.pop(); } + if (newstack.empty()) return false; + if (newstack.peek() instanceof Symbol) state=((Symbol)newstack.peek()).parse_state; + state=get_reduce(state, lhs_sym_num); + newstack.push(null); + } + } + + static CompModule alloy_parseStream (List seenDollar, + Map loaded, Map fc, CompModule root, + int lineOffset, String filename, String prefix, int initialResolutionMode) throws Err, FileNotFoundException, IOException { + Reader isr=null; + try { + if (root==null && prefix.length()!=0) throw new ErrorFatal("Internal error (parse subfile with root==null)"); + if (root!=null && prefix.length()==0) throw new ErrorFatal("Internal error (parse topfile with root!=null)"); + CompModule u = new CompModule(root, filename, prefix); + if (root == null) + u.addOpen(null, null, ExprVar.make(null, "util/integer"), null, ExprVar.make(null, "integer")); + u.resolution = initialResolutionMode; + String content = fc!=null ? fc.get(filename) : null; + if (content==null && loaded!=null) content = loaded.get(filename); + if (content==null) content = Util.readAll(filename); + if (loaded!=null) loaded.put(filename,content); + content = Util.convertLineBreak(content); + isr = new StringReader(content); + CompFilter s = new CompFilter(u, seenDollar, filename, lineOffset, new BufferedReader(isr)); + CompParser p = new CompParser(s); + p.alloymodule=u; + try {p.parse();} catch(Throwable ex) {if (ex instanceof Err) throw (Err)ex; throw new ErrorFatal("Parser Exception", ex);} + // if no sigs are defined by the user, add one + if (root == null && u.getAllSigs().isEmpty()) { + u.addGhostSig(); + } + return u; + } finally { + Util.close(isr); + } + } + + +} + +/** Cup generated class to encapsulate user supplied action code.*/ +class CUP$CompParser$actions { + + + /** This function is needed to handle a difficult parsing ambiguity. + * + *

+ * "some EXPR", "one EXPR", and "lone EXPR" + * can be either formulas (saying the EXPR has at least 1, exactly 1, or at most 1 tuple), + * or multiplicity constraints (saying something else has this multiplicity). + * + *

+ * So we let the parser generate the former by default. + * And whenever we construct a Decl "x: y" object, + * or an binary expression "x in y", or a function return type, + * we call this method on y to convert it into a multiplicity constraint. + * + *

+ * This is safe, because in all 3 cases, a formula would be illegal. + * So the first form is always wrong. + * + *

+ * And this is sufficient, because those are the only 3 places + * where a mulitplicity constraint is allowed to appear. + * + * @return a newly formed multiplciity constraint (if this.op==SOME or LONE or ONE), + * otherwise it just returns the original node. + */ + private Expr mult(Expr x) throws Err { + if (x instanceof ExprUnary) { + ExprUnary y=(ExprUnary)x; + if (y.op==ExprUnary.Op.SOME) return ExprUnary.Op.SOMEOF.make(y.pos, y.sub); + if (y.op==ExprUnary.Op.LONE) return ExprUnary.Op.LONEOF.make(y.pos, y.sub); + if (y.op==ExprUnary.Op.ONE) return ExprUnary.Op.ONEOF.make(y.pos, y.sub); + } + return x; + } + private void nod(ExprVar name) throws Err { + if (name.label.indexOf('$')>=0) throw new ErrorSyntax(name.pos, "The name cannot contain the '$' symbol."); + } + private void nod(List names) throws Err { + if (names!=null) for(ExprVar n:names) if (n!=null && n.label.indexOf('$')>=0) throw new ErrorSyntax(n.pos, "The name cannot contain the '$' symbol."); + } + private void c(boolean follow, ExprVar o, ExprVar x, ExprVar n, Expr e, List s, ExprConstant c) throws Err { + if (n!=null) nod(n); + int bitwidth=(-1), maxseq=(-1), overall=(-1), expects=(c==null ? -1 : c.num); + Pos p = o.pos.merge(n!=null ? n.span() : e.span()); + for(int i=s.size()-1; i>=0; i--) { + Sig j=s.get(i).sig; int k=s.get(i).startingScope; + p=p.merge(j.pos); + if (j.label.equals("univ")) { overall=k; s.remove(i); continue; } + if (j.label.equals("int")) { if (bitwidth>=0) throw new ErrorSyntax(j.pos, "The bitwidth cannot be specified more than once."); bitwidth=k; s.remove(i); continue; } + if (j.label.equals("seq")) { if (maxseq>=0) throw new ErrorSyntax(j.pos, "The maximum sequence length cannot be specified more than once."); maxseq=k; s.remove(i); continue; } + } + if (n!=null) + parser.alloymodule.addCommand(follow, p, n.label, o.label.equals("c"), overall, bitwidth, maxseq, expects, s, x); + else + parser.alloymodule.addCommand(follow, p, e, o.label.equals("c"), overall, bitwidth, maxseq, expects, s, x); + } + private Expr t(Pos pos, Pos oldClosing, Expr left, Expr right, Pos close) throws Err { + if (right instanceof ExprVar) { + String n = ((ExprVar)right).label; + if (n.equals("int")) return ExprUnary.Op.CAST2INT.make(pos, left); + if (n.equals("disj")) return ExprList.makeDISJOINT(pos, close, Util.asList(left)); + if (n.equals("pred/totalOrder")) return ExprList.makeTOTALORDER(pos, close, Util.asList(left)); + } + else if (right instanceof ExprList) { + return ((ExprList)right).addArg(left); + } + return ExprBadJoin.make(pos, oldClosing, left, right); + } + + private final CompParser parser; + + /** Constructor */ + CUP$CompParser$actions(CompParser parser) { + this.parser = parser; + } + + /** Method with the actual generated action code. */ + public final java_cup.runtime.Symbol CUP$CompParser$do_action( + int CUP$CompParser$act_num, + java_cup.runtime.lr_parser CUP$CompParser$parser, + java.util.Stack CUP$CompParser$stack, + int CUP$CompParser$top) + throws java.lang.Exception + { + /* Symbol object for return from actions */ + java_cup.runtime.Symbol CUP$CompParser$result; + + /* select the action based on the action number */ + switch (CUP$CompParser$act_num) + { + /*. . . . . . . . . . . . . . . . . . . .*/ + case 349: // BaseExpr ::= LBRACE Declz RBRACE + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos c = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprQt.Op.COMPREHENSION.make(o, c, a, ExprConstant.TRUE); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BaseExpr",2, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 348: // BaseExpr ::= LBRACE Declz SuperOrBar RBRACE + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos c = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprQt.Op.COMPREHENSION.make(o, c, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BaseExpr",2, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 347: // BaseExpr ::= Super + { + Expr RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr x = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = x; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BaseExpr",2, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 346: // BaseExpr ::= AT Name + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar x = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(x); RESULT = ExprVar.make(o.merge(x.pos), "@"+x.label); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BaseExpr",2, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 345: // BaseExpr ::= SigRef + { + Expr RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar x = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = x; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BaseExpr",2, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 344: // BaseExpr ::= LPAREN Expr RPAREN + { + Expr RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Expr x = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + RESULT = x; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BaseExpr",2, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 343: // BaseExpr ::= INTNEXT + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprConstant.Op.NEXT.make(o, 0); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BaseExpr",2, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 342: // BaseExpr ::= INTMAX + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprConstant.Op.MAX.make(o, 0); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BaseExpr",2, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 341: // BaseExpr ::= INTMIN + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprConstant.Op.MIN.make(o, 0); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BaseExpr",2, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 340: // BaseExpr ::= THIS + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprVar.make(o, "this"); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BaseExpr",2, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 339: // BaseExpr ::= IDEN + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprVar.make(o, "iden"); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BaseExpr",2, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 338: // BaseExpr ::= STR + { + Expr RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant x = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = x; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BaseExpr",2, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 337: // BaseExpr ::= NUMBER + { + Expr RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant x = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = x; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BaseExpr",2, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 336: // UnopExprB ::= CARET UnopExprB + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.CLOSURE .make(o,b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnopExprB",80, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 335: // UnopExprB ::= STAR UnopExprB + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.RCLOSURE .make(o,b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnopExprB",80, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 334: // UnopExprB ::= TILDE UnopExprB + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.TRANSPOSE.make(o,b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnopExprB",80, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 333: // UnopExprB ::= BaseExpr + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnopExprB",80, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 332: // UnopExprA ::= CARET UnopExprA + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.CLOSURE .make(o,b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnopExprA",79, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 331: // UnopExprA ::= STAR UnopExprA + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.RCLOSURE .make(o,b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnopExprA",79, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 330: // UnopExprA ::= TILDE UnopExprA + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.TRANSPOSE.make(o,b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnopExprA",79, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 329: // UnopExprA ::= CARET Bind + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.CLOSURE .make(o,b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnopExprA",79, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 328: // UnopExprA ::= STAR Bind + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.RCLOSURE .make(o,b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnopExprA",79, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 327: // UnopExprA ::= TILDE Bind + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.TRANSPOSE.make(o,b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnopExprA",79, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 326: // DotExprB ::= BracketExprB DOT SUM + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, a)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("DotExprB",18, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 325: // DotExprB ::= BracketExprB DOT INT + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, a)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("DotExprB",18, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 324: // DotExprB ::= BracketExprB DOT TOTALORDER + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos b = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=t(o, null, a, ExprVar.make(b, "pred/totalOrder"), null); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("DotExprB",18, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 323: // DotExprB ::= BracketExprB DOT DISJ + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos b = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=t(o, null, a, ExprVar.make(b, "disj"), null); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("DotExprB",18, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 322: // DotExprB ::= BracketExprB DOT UnopExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=t(o, null, a, b, null); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("DotExprB",18, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 321: // DotExprB ::= UnopExprB + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("DotExprB",18, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 320: // DotExprA ::= BracketExprB DOT Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=t(o, null, a, b, null); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("DotExprA",17, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 319: // DotExprA ::= UnopExprA + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("DotExprA",17, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 318: // BracketExprB ::= SUM LBRACKET Exprs RBRACKET + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos a = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List b = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos c = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + Expr aa=ExprVar.make(a, "int"); for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=ExprUnary.Op.CAST2SIGINT.make(a, aa); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BracketExprB",5, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 317: // BracketExprB ::= INT LBRACKET Exprs RBRACKET + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos a = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List b = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos c = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + Expr aa=ExprVar.make(a, "int"); for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=ExprUnary.Op.CAST2SIGINT.make(a, aa); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BracketExprB",5, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 316: // BracketExprB ::= TOTALORDER LBRACKET Exprs RBRACKET + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos a = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List b = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos c = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + Expr aa=ExprVar.make(a, "pred/totalOrder"); for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=aa; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BracketExprB",5, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 315: // BracketExprB ::= DISJ LBRACKET Exprs RBRACKET + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos a = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List b = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos c = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + Expr aa=ExprVar.make(a, "disj"); for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=aa; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BracketExprB",5, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 314: // BracketExprB ::= BracketExprB LBRACKET Exprs RBRACKET + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List b = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos c = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + Expr aa=a; for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=aa; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BracketExprB",5, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 313: // BracketExprB ::= DotExprB + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BracketExprB",5, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 312: // BracketExprA ::= DotExprA + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("BracketExprA",4, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 311: // RangeExprB ::= RangeExprB RANGE BracketExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.RANGE.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RangeExprB",55, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 310: // RangeExprB ::= BracketExprB + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RangeExprB",55, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 309: // RangeExprA ::= RangeExprB RANGE Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.RANGE.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RangeExprA",54, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 308: // RangeExprA ::= BracketExprA + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RangeExprA",54, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 307: // DomainExprB ::= DomainExprB DOMAIN RangeExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.DOMAIN.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("DomainExprB",16, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 306: // DomainExprB ::= RangeExprB + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("DomainExprB",16, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 305: // DomainExprA ::= DomainExprB DOMAIN Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.DOMAIN.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("DomainExprA",15, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 304: // DomainExprA ::= RangeExprA + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("DomainExprA",15, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 303: // RelationExprB ::= DomainExprB RelOp RelationExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pair o = (Pair)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=o.b.make(o.a, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelationExprB",58, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 302: // RelationExprB ::= DomainExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelationExprB",58, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 301: // RelationExprA ::= DomainExprB RelOp Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pair o = (Pair)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=o.b.make(o.a, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelationExprA",57, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 300: // RelationExprA ::= DomainExprA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelationExprA",57, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 299: // RelOp ::= LONE_ARROW_LONE + { + Pair RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Pair(o, ExprBinary.Op.LONE_ARROW_LONE); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelOp",56, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 298: // RelOp ::= LONE_ARROW_ONE + { + Pair RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Pair(o, ExprBinary.Op.LONE_ARROW_ONE ); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelOp",56, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 297: // RelOp ::= LONE_ARROW_SOME + { + Pair RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Pair(o, ExprBinary.Op.LONE_ARROW_SOME); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelOp",56, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 296: // RelOp ::= LONE_ARROW_ANY + { + Pair RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Pair(o, ExprBinary.Op.LONE_ARROW_ANY ); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelOp",56, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 295: // RelOp ::= ONE_ARROW_LONE + { + Pair RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Pair(o, ExprBinary.Op.ONE_ARROW_LONE ); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelOp",56, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 294: // RelOp ::= ONE_ARROW_ONE + { + Pair RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Pair(o, ExprBinary.Op.ONE_ARROW_ONE ); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelOp",56, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 293: // RelOp ::= ONE_ARROW_SOME + { + Pair RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Pair(o, ExprBinary.Op.ONE_ARROW_SOME ); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelOp",56, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 292: // RelOp ::= ONE_ARROW_ANY + { + Pair RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Pair(o, ExprBinary.Op.ONE_ARROW_ANY ); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelOp",56, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 291: // RelOp ::= SOME_ARROW_LONE + { + Pair RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Pair(o, ExprBinary.Op.SOME_ARROW_LONE); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelOp",56, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 290: // RelOp ::= SOME_ARROW_ONE + { + Pair RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Pair(o, ExprBinary.Op.SOME_ARROW_ONE ); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelOp",56, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 289: // RelOp ::= SOME_ARROW_SOME + { + Pair RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Pair(o, ExprBinary.Op.SOME_ARROW_SOME); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelOp",56, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 288: // RelOp ::= SOME_ARROW_ANY + { + Pair RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Pair(o, ExprBinary.Op.SOME_ARROW_ANY ); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelOp",56, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 287: // RelOp ::= ANY_ARROW_LONE + { + Pair RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Pair(o, ExprBinary.Op.ANY_ARROW_LONE ); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelOp",56, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 286: // RelOp ::= ANY_ARROW_ONE + { + Pair RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Pair(o, ExprBinary.Op.ANY_ARROW_ONE ); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelOp",56, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 285: // RelOp ::= ANY_ARROW_SOME + { + Pair RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Pair(o, ExprBinary.Op.ANY_ARROW_SOME ); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelOp",56, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 284: // RelOp ::= ARROW + { + Pair RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Pair(o, ExprBinary.Op.ARROW ); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("RelOp",56, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 283: // IntersectExprB ::= IntersectExprB AMPERSAND RelationExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.INTERSECT.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("IntersectExprB",37, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 282: // IntersectExprB ::= RelationExprB + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("IntersectExprB",37, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 281: // IntersectExprA ::= IntersectExprB AMPERSAND Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.INTERSECT.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("IntersectExprA",36, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 280: // IntersectExprA ::= RelationExprA + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("IntersectExprA",36, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 279: // OverrideExprB ::= OverrideExprB PLUSPLUS IntersectExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.PLUSPLUS.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("OverrideExprB",52, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 278: // OverrideExprB ::= IntersectExprB + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("OverrideExprB",52, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 277: // OverrideExprA ::= OverrideExprB PLUSPLUS Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.PLUSPLUS.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("OverrideExprA",51, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 276: // OverrideExprA ::= IntersectExprA + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("OverrideExprA",51, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 275: // NumUnopExprB ::= INT NumUnopExprB + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("NumUnopExprB",48, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 274: // NumUnopExprB ::= SUM NumUnopExprB + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("NumUnopExprB",48, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 273: // NumUnopExprB ::= HASH NumUnopExprB + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.CARDINALITY.make(o, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("NumUnopExprB",48, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 272: // NumUnopExprB ::= OverrideExprB + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("NumUnopExprB",48, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 271: // NumUnopExprA ::= INT NumUnopExprA + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("NumUnopExprA",47, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 270: // NumUnopExprA ::= SUM NumUnopExprA + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("NumUnopExprA",47, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 269: // NumUnopExprA ::= HASH NumUnopExprA + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.CARDINALITY.make(o, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("NumUnopExprA",47, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 268: // NumUnopExprA ::= INT Bind + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("NumUnopExprA",47, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 267: // NumUnopExprA ::= SUM Bind + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("NumUnopExprA",47, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 266: // NumUnopExprA ::= HASH Bind + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.CARDINALITY.make(o, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("NumUnopExprA",47, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 265: // NumUnopExprA ::= OverrideExprA + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("NumUnopExprA",47, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 264: // MulExprB ::= MulExprB INTREM NumUnopExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.REM .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("MulExprB",76, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 263: // MulExprB ::= MulExprB INTDIV NumUnopExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.DIV .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("MulExprB",76, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 262: // MulExprB ::= MulExprB INTMUL NumUnopExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.MUL .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("MulExprB",76, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 261: // MulExprB ::= NumUnopExprB + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("MulExprB",76, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 260: // MulExprA ::= MulExprB INTREM Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.REM .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("MulExprA",75, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 259: // MulExprA ::= MulExprB INTDIV Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.DIV .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("MulExprA",75, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 258: // MulExprA ::= MulExprB INTMUL Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.MUL .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("MulExprA",75, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 257: // MulExprA ::= NumUnopExprA + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("MulExprA",75, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 256: // UnionDiffExprB ::= UnionDiffExprB INTSUB MulExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.IMINUS.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnionDiffExprB",78, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 255: // UnionDiffExprB ::= UnionDiffExprB INTADD MulExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.IPLUS.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnionDiffExprB",78, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 254: // UnionDiffExprB ::= UnionDiffExprB MINUS MulExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.MINUS.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnionDiffExprB",78, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 253: // UnionDiffExprB ::= UnionDiffExprB PLUS MulExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.PLUS .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnionDiffExprB",78, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 252: // UnionDiffExprB ::= MulExprB + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnionDiffExprB",78, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 251: // UnionDiffExprA ::= UnionDiffExprB INTSUB Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.IMINUS.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnionDiffExprA",77, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 250: // UnionDiffExprA ::= UnionDiffExprB INTADD Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.IPLUS.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnionDiffExprA",77, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 249: // UnionDiffExprA ::= UnionDiffExprB MINUS Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.MINUS.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnionDiffExprA",77, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 248: // UnionDiffExprA ::= UnionDiffExprB PLUS Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.PLUS .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnionDiffExprA",77, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 247: // UnionDiffExprA ::= MulExprA + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("UnionDiffExprA",77, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 246: // ShiftExprB ::= ShiftExprB SHA UnionDiffExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.SHA.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ShiftExprB",74, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 245: // ShiftExprB ::= ShiftExprB SHR UnionDiffExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.SHR.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ShiftExprB",74, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 244: // ShiftExprB ::= ShiftExprB SHL UnionDiffExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.SHL.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ShiftExprB",74, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 243: // ShiftExprB ::= UnionDiffExprB + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ShiftExprB",74, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 242: // ShiftExprA ::= ShiftExprB SHA Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.SHA.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ShiftExprA",73, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 241: // ShiftExprA ::= ShiftExprB SHR Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.SHR.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ShiftExprA",73, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 240: // ShiftExprA ::= ShiftExprB SHL Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.SHL.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ShiftExprA",73, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 239: // ShiftExprA ::= UnionDiffExprA + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ShiftExprA",73, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 238: // CompareExprB ::= ShiftExprB + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 237: // CompareExprB ::= SEQ ShiftExprB + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.ISSEQ_ARROW_LONE.make(o, null, ExprVar.make(o,"seq/Int"), b); parser.alloymodule.addSeq(o); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 236: // CompareExprB ::= SET ShiftExprB + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.SETOF.make(o, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 235: // CompareExprB ::= ONE ShiftExprB + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.ONE .make(o, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 234: // CompareExprB ::= LONE ShiftExprB + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.LONE .make(o, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 233: // CompareExprB ::= SOME ShiftExprB + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.SOME .make(o, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 232: // CompareExprB ::= NO ShiftExprB + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.NO .make(o, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 231: // CompareExprB ::= ALL ShiftExprB + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + if (1==1) throw new ErrorSyntax(o,"The \"all x\" construct is no longer supported. If you know the range of possible values of x, consider rewriting it as \"x == set_of_all_possible_values\"."); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 230: // CompareExprB ::= CompareExprB NOTGTE ShiftExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.NOT_GTE .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 229: // CompareExprB ::= CompareExprB NOTLTE ShiftExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.NOT_LTE .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 228: // CompareExprB ::= CompareExprB NOTGT ShiftExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.NOT_GT .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 227: // CompareExprB ::= CompareExprB NOTLT ShiftExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.NOT_LT .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 226: // CompareExprB ::= CompareExprB NOTEQUALS ShiftExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.NOT_EQUALS.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 225: // CompareExprB ::= CompareExprB NOTIN ShiftExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.NOT_IN .make(o, null, a, mult(b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 224: // CompareExprB ::= CompareExprB GTE ShiftExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.GTE .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 223: // CompareExprB ::= CompareExprB LTE ShiftExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.LTE .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 222: // CompareExprB ::= CompareExprB GT ShiftExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.GT .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 221: // CompareExprB ::= CompareExprB LT ShiftExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.LT .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 220: // CompareExprB ::= CompareExprB EQUALS ShiftExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.EQUALS .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 219: // CompareExprB ::= CompareExprB IN ShiftExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.IN .make(o, null, a, mult(b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprB",7, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 218: // CompareExprA ::= ShiftExprA + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 217: // CompareExprA ::= SEQ ShiftExprA + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.ISSEQ_ARROW_LONE.make(o, null, ExprVar.make(o, "seq/Int"), b); parser.alloymodule.addSeq(o); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 216: // CompareExprA ::= SET ShiftExprA + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.SETOF.make(o, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 215: // CompareExprA ::= ONE ShiftExprA + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.ONE .make(o, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 214: // CompareExprA ::= LONE ShiftExprA + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.LONE .make(o, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 213: // CompareExprA ::= SOME ShiftExprA + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.SOME .make(o, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 212: // CompareExprA ::= NO ShiftExprA + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.NO .make(o, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 211: // CompareExprA ::= ALL ShiftExprA + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + if (1==1) throw new ErrorSyntax(o,"The \"all x\" construct is no longer supported. If you know the range of possible values of x, consider rewriting it as \"x == set_of_all_possible_values\"."); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 210: // CompareExprA ::= CompareExprB NOTGTE ShiftExprA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.NOT_GTE .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 209: // CompareExprA ::= CompareExprB NOTLTE ShiftExprA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.NOT_LTE .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 208: // CompareExprA ::= CompareExprB NOTGT ShiftExprA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.NOT_GT .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 207: // CompareExprA ::= CompareExprB NOTLT ShiftExprA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.NOT_LT .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 206: // CompareExprA ::= CompareExprB NOTEQUALS ShiftExprA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.NOT_EQUALS.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 205: // CompareExprA ::= CompareExprB NOTIN ShiftExprA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.NOT_IN .make(o, null, a, mult(b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 204: // CompareExprA ::= CompareExprB GTE ShiftExprA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.GTE .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 203: // CompareExprA ::= CompareExprB LTE ShiftExprA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.LTE .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 202: // CompareExprA ::= CompareExprB GT ShiftExprA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.GT .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 201: // CompareExprA ::= CompareExprB LT ShiftExprA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.LT .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 200: // CompareExprA ::= CompareExprB EQUALS ShiftExprA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.EQUALS .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 199: // CompareExprA ::= CompareExprB IN ShiftExprA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.IN .make(o, null, a, mult(b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CompareExprA",6, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 198: // NegExprB ::= NOT NegExprB + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.NOT.make(o, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("NegExprB",46, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 197: // NegExprB ::= CompareExprB + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("NegExprB",46, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 196: // NegExprA ::= NOT NegExprA + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.NOT.make(o, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("NegExprA",45, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 195: // NegExprA ::= NOT Bind + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.NOT.make(o, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("NegExprA",45, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 194: // NegExprA ::= CompareExprA + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("NegExprA",45, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 193: // AndExprB ::= AndExprB AND NegExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.AND.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("AndExprB",1, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 192: // AndExprB ::= NegExprB + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("AndExprB",1, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 191: // AndExprA ::= AndExprB AND Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.AND.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("AndExprA",0, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 190: // AndExprA ::= NegExprA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("AndExprA",0, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 189: // ImpliesExprOpenB ::= AndExprB IMPLIES ImpliesExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprBinary.Op.IMPLIES.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ImpliesExprOpenB",35, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 188: // ImpliesExprOpenB ::= AndExprB IMPLIES ImpliesExprCloseB ELSE ImpliesExprOpenB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr c = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprITE.make(o,a,b,c); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ImpliesExprOpenB",35, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 187: // ImpliesExprCloseB ::= AndExprB IMPLIES ImpliesExprCloseB ELSE ImpliesExprCloseB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr c = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprITE.make(o,a,b,c); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ImpliesExprCloseB",33, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 186: // ImpliesExprCloseB ::= AndExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ImpliesExprCloseB",33, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 185: // ImpliesExprB ::= ImpliesExprOpenB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ImpliesExprB",31, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 184: // ImpliesExprB ::= ImpliesExprCloseB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ImpliesExprB",31, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 183: // ImpliesExprOpenA ::= AndExprB IMPLIES Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprBinary.Op.IMPLIES.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ImpliesExprOpenA",34, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 182: // ImpliesExprCloseA ::= AndExprB IMPLIES ImpliesExprCloseB ELSE Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr c = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprITE.make(o,a,b,c); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ImpliesExprCloseA",32, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 181: // ImpliesExprOpenA ::= AndExprB IMPLIES ImpliesExprA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprBinary.Op.IMPLIES.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ImpliesExprOpenA",34, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 180: // ImpliesExprOpenA ::= AndExprB IMPLIES ImpliesExprCloseB ELSE ImpliesExprOpenA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr c = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprITE.make(o,a,b,c); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ImpliesExprOpenA",34, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 179: // ImpliesExprCloseA ::= AndExprB IMPLIES ImpliesExprCloseB ELSE ImpliesExprCloseA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr c = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprITE.make(o,a,b,c); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ImpliesExprCloseA",32, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 178: // ImpliesExprCloseA ::= AndExprA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ImpliesExprCloseA",32, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 177: // ImpliesExprA ::= ImpliesExprOpenA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ImpliesExprA",30, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 176: // ImpliesExprA ::= ImpliesExprCloseA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("ImpliesExprA",30, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 175: // EquivExprB ::= EquivExprB IFF ImpliesExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.IFF.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("EquivExprB",20, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 174: // EquivExprB ::= ImpliesExprB + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("EquivExprB",20, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 173: // EquivExprA ::= EquivExprB IFF Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.IFF.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("EquivExprA",19, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 172: // EquivExprA ::= ImpliesExprA + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("EquivExprA",19, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 171: // OrExprB ::= OrExprB OR EquivExprB + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.OR.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("OrExprB",50, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 170: // OrExprB ::= EquivExprB + { + Expr RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("OrExprB",50, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 169: // OrExprA ::= OrExprB OR Bind + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.OR.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("OrExprA",49, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 168: // OrExprA ::= EquivExprA + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("OrExprA",49, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 167: // Bind ::= SUM2 Declp SuperOrBar + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprQt.Op.SUM .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Bind",3, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 166: // Bind ::= ONE2 Declp SuperOrBar + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprQt.Op.ONE .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Bind",3, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 165: // Bind ::= LONE2 Declp SuperOrBar + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprQt.Op.LONE.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Bind",3, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 164: // Bind ::= SOME2 Declp SuperOrBar + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprQt.Op.SOME.make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Bind",3, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 163: // Bind ::= NO2 Declp SuperOrBar + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprQt.Op.NO .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Bind",3, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 162: // Bind ::= ALL2 Declp SuperOrBar + { + Expr RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprQt.Op.ALL .make(o, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Bind",3, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 161: // Bind ::= LET Let + { + Expr RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr x = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = x; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Bind",3, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 160: // Expr ::= Bind + { + Expr RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr x = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = x; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Expr",22, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 159: // Expr ::= OrExprB + { + Expr RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr x = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = x; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Expr",22, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 158: // Expr ::= OrExprA + { + Expr RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr x = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = x; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Expr",22, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 157: // Exprp ::= Exprp COMMA Expr + { + List RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + a.add(b); RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Exprp",28, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 156: // Exprp ::= Expr + { + List RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr x = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new ArrayList(); RESULT.add(x); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Exprp",28, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 155: // Exprs ::= Exprp + { + List RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + List x = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=x; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Exprs",27, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 154: // Exprs ::= + { + List RESULT =null; + RESULT=new ArrayList(); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Exprs",27, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 153: // SuperOrBar ::= Super + { + Expr RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr x = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=x; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SuperOrBar",26, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 152: // SuperOrBar ::= BAR Expr + { + Expr RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr x = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=x; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SuperOrBar",26, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 151: // SuperP ::= SuperP Expr + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprBinary.Op.AND.make(null, null, a, b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SuperP",25, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 150: // SuperP ::= Expr + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SuperP",25, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 149: // Super ::= LBRACE RBRACE + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos a = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos b = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprConstant.Op.TRUE.make(a.merge(b), 0); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Super",23, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 148: // Super ::= LBRACE SuperP RBRACE + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Pos a = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Expr x = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos b = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprUnary.Op.NOOP.make(a.merge(b), x); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Super",23, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 147: // SuperOpt ::= Super + { + Expr RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr x = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=x; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SuperOpt",24, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 146: // SuperOpt ::= + { + Expr RESULT =null; + RESULT=null; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SuperOpt",24, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 145: // Let ::= Name EQUALS Expr COMMA Let + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + ExprVar a = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr x = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + + nod(a); + if (a.label.indexOf('/')>=0) throw new ErrorSyntax(a.pos, "Let variable name cannot contain \'/\'"); + if (a.label.indexOf('@')>=0) throw new ErrorSyntax(a.pos, "Let variable name cannot contain \'@\'"); + RESULT = ExprLet.make(o, ExprVar.make(a.pos, a.label), b, x); + + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Let",38, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 144: // Let ::= Name EQUALS Expr SuperOrBar + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + ExprVar a = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr x = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + + nod(a); + if (a.label.indexOf('/')>=0) throw new ErrorSyntax(a.pos, "Let variable name cannot contain \'/\'"); + if (a.label.indexOf('@')>=0) throw new ErrorSyntax(a.pos, "Let variable name cannot contain \'@\'"); + RESULT = ExprLet.make(o, ExprVar.make(a.pos, a.label), b, x); + + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Let",38, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 143: // Decls ::= COMMA Decls + { + List RESULT =null; + int yleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int yright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + List y = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=y; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Decls",13, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 142: // Decls ::= Declb COMMA Decls + { + List RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Decl x = (Decl)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int yleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int yright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + List y = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=y; RESULT.add(0,x); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Decls",13, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 141: // Decls ::= Declb + { + List RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Decl x = (Decl)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new ArrayList(); RESULT.add(x); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Decls",13, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 140: // Decls ::= + { + List RESULT =null; + RESULT=new ArrayList(); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Decls",13, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 139: // Declp ::= Declb + { + List RESULT =null; + int yleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int yright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Decl y = (Decl)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new ArrayList(); RESULT.add(y); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Declp",12, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 138: // Declp ::= Declp COMMA Declb + { + List RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List x = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int yleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int yright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Decl y = (Decl)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=x; RESULT.add(y); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Declp",12, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 137: // Declz ::= Decla + { + List RESULT =null; + int yleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int yright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Decl y = (Decl)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new ArrayList(); RESULT.add(y); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Declz",14, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 136: // Declz ::= Declz COMMA Decla + { + List RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List x = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int yleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int yright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Decl y = (Decl)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=x; RESULT.add(y); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Declz",14, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 135: // Declb ::= Names EQUALS DISJ Expr + { + Decl RESULT =null; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos d = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Declb",11, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 134: // Declb ::= PRIVATE Names EQUALS DISJ Expr + { + Decl RESULT =null; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos d = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Declb",11, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 133: // Declb ::= PRIVATE DISJ Names EQUALS DISJ Expr + { + Decl RESULT =null; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos d = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Declb",11, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 132: // Declb ::= DISJ Names EQUALS DISJ Expr + { + Decl RESULT =null; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos d = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Declb",11, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 131: // Declb ::= EXH Names EQUALS DISJ Expr + { + Decl RESULT =null; + int kleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int kright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Pos k = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + if (1==1) throw CompModule.hint(k, "exh"); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Declb",11, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 130: // Declb ::= PART Names EQUALS DISJ Expr + { + Decl RESULT =null; + int kleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int kright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Pos k = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + if (1==1) throw CompModule.hint(k, "part"); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Declb",11, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 129: // Declb ::= Names EQUALS Expr + { + Decl RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Decl(null, null, null, a, ExprUnary.Op.EXACTLYOF.make(null, b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Declb",11, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 128: // Declb ::= PRIVATE Names EQUALS Expr + { + Decl RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Decl(p, null, null, a, ExprUnary.Op.EXACTLYOF.make(null, b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Declb",11, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 127: // Declb ::= PRIVATE DISJ Names EQUALS Expr + { + Decl RESULT =null; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos d = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Declb",11, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 126: // Declb ::= DISJ Names EQUALS Expr + { + Decl RESULT =null; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos d = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Declb",11, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 125: // Declb ::= EXH Names EQUALS Expr + { + Decl RESULT =null; + int kleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int kright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos k = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + if (1==1) throw CompModule.hint(k, "exh"); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Declb",11, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 124: // Declb ::= PART Names EQUALS Expr + { + Decl RESULT =null; + int kleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int kright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos k = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + if (1==1) throw CompModule.hint(k, "part"); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Declb",11, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 123: // Declb ::= Decla + { + Decl RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Decl x = (Decl)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=x; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Declb",11, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 122: // Decla ::= Names COLON DISJ Expr + { + Decl RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos d = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Decl(null, null, d, a, mult(b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Decla",10, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 121: // Decla ::= PRIVATE Names COLON DISJ Expr + { + Decl RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos d = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Decl(p, null, d, a, mult(b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Decla",10, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 120: // Decla ::= PRIVATE DISJ Names COLON DISJ Expr + { + Decl RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).value; + int kleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int kright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Pos k = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos d = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Decl(p, k, d, a, mult(b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Decla",10, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 119: // Decla ::= DISJ Names COLON DISJ Expr + { + Decl RESULT =null; + int kleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int kright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Pos k = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos d = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Decl(null, k, d, a, mult(b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Decla",10, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 118: // Decla ::= EXH Names COLON DISJ Expr + { + Decl RESULT =null; + int kleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int kright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Pos k = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + if (1==1) throw CompModule.hint(k, "exh"); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Decla",10, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 117: // Decla ::= PART Names COLON DISJ Expr + { + Decl RESULT =null; + int kleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int kright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Pos k = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + if (1==1) throw CompModule.hint(k, "part"); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Decla",10, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 116: // Decla ::= Names COLON Expr + { + Decl RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Decl(null, null, null, a, mult(b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Decla",10, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 115: // Decla ::= PRIVATE Names COLON Expr + { + Decl RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Decl(p, null, null, a, mult(b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Decla",10, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 114: // Decla ::= PRIVATE DISJ Names COLON Expr + { + Decl RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int kleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int kright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos k = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Decl(p, k, null, a, mult(b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Decla",10, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 113: // Decla ::= DISJ Names COLON Expr + { + Decl RESULT =null; + int kleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int kright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos k = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr b = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new Decl(null, k, null, a, mult(b)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Decla",10, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 112: // Decla ::= EXH Names COLON Expr + { + Decl RESULT =null; + int kleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int kright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos k = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + if (1==1) throw CompModule.hint(k, "exh"); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Decla",10, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 111: // Decla ::= PART Names COLON Expr + { + Decl RESULT =null; + int kleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int kright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos k = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + if (1==1) throw CompModule.hint(k, "part"); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Decla",10, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 110: // Namex ::= Namex COMMA EXACTLY Name + { + List RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar b = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(b); a.add(null); a.add(b); RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Namex",44, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 109: // Namex ::= Namex COMMA Name + { + List RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar b = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(b); a.add(b); RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Namex",44, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 108: // Namex ::= EXACTLY Name + { + List RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar x = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(x); RESULT=new ArrayList(); RESULT.add(null); RESULT.add(x); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Namex",44, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 107: // Namex ::= Name + { + List RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar x = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(x); RESULT=new ArrayList(); RESULT.add(x); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Namex",44, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 106: // Names ::= Names COMMA Name + { + List RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar b = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(b); a.add(b); RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Names",43, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 105: // Names ::= Name + { + List RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar x = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(x); RESULT=new ArrayList(); RESULT.add(x); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Names",43, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 104: // NameHelper ::= NameHelper SLASH ID + { + ExprVar RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + ExprVar a = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar b = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprVar.make(a.pos.merge(b.pos), a.label+"/"+b.label); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("NameHelper",42, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 103: // NameHelper ::= ID + { + ExprVar RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar x = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=x; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("NameHelper",42, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 102: // Name ::= SEQ SLASH NameHelper + { + ExprVar RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Pos a = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar b = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprVar.make(a.merge(b.pos), "seq/"+b.label); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Name",41, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 101: // Name ::= THIS SLASH NameHelper + { + ExprVar RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Pos a = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar b = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprVar.make(a.merge(b.pos), "this/"+b.label); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Name",41, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 100: // Name ::= NameHelper + { + ExprVar RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar x = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=x; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Name",41, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 99: // SigRefu ::= SigRefu PLUS SigRef + { + List RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar b = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + a.add(b); RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigRefu",67, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 98: // SigRefu ::= SigRef + { + List RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar x = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new ArrayList(); RESULT.add(x); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigRefu",67, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 97: // SigRefp ::= SigRefp COMMA SigRef + { + List RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar b = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + a.add(b); RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigRefp",65, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 96: // SigRefp ::= SigRef + { + List RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar x = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new ArrayList(); RESULT.add(x); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigRefp",65, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 95: // SigRefs ::= SigRefp + { + List RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + List x = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=x; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigRefs",66, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 94: // SigRefs ::= + { + List RESULT =null; + RESULT=new ArrayList(); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigRefs",66, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 93: // SigRef ::= NONE + { + ExprVar RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos x = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprVar.make(x, "none"); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigRef",64, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 92: // SigRef ::= SEQ SLASH SIGINT + { + ExprVar RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Pos a = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos b = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprVar.make(a.merge(b), "seq/Int"); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigRef",64, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 91: // SigRef ::= SIGINT + { + ExprVar RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos x = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprVar.make(x, "Int"); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigRef",64, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 90: // SigRef ::= STRING + { + ExprVar RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos x = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprVar.make(x, "String"); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigRef",64, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 89: // SigRef ::= UNIV + { + ExprVar RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos x = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=ExprVar.make(x, "univ"); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigRef",64, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 88: // SigRef ::= Name + { + ExprVar RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar x = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=x; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigRef",64, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 87: // SigIn ::= + { + List RESULT =null; + RESULT=null; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigIn",61, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 86: // SigIn ::= EQUALS SigRefu + { + List RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos a = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + List x = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=x; x.add(ExprVar.make(a,"=")); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigIn",61, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 85: // SigIn ::= IN SigRefu + { + List RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos a = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + List x = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=x; x.add(ExprVar.make(a,"in")); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigIn",61, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 84: // SigIn ::= EXTENDS SigRef + { + List RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos a = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar x = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new ArrayList(2); RESULT.add(x); RESULT.add(ExprVar.make(a, "extends")); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigIn",61, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 83: // SigQuals ::= SigQual SigQuals + { + List RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + List b = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=a; for(int i=0;i<5;i++) if (a.get(i)==null) a.set(i,b.get(i)); else if (b.get(i)!=null) throw new ErrorSyntax(b.get(i), "The same qualifer cannot be specified more than once for the same sig."); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigQuals",63, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 82: // SigQuals ::= SIG + { + List RESULT =null; + RESULT=new ArrayList(5); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigQuals",63, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 81: // SigQual ::= PRIVATE + { + List RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos x = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new ArrayList(5); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(x); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigQual",62, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 80: // SigQual ::= SOME + { + List RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos x = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new ArrayList(5); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(x); RESULT.add(null); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigQual",62, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 79: // SigQual ::= ONE + { + List RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos x = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new ArrayList(5); RESULT.add(null); RESULT.add(null); RESULT.add(x); RESULT.add(null); RESULT.add(null); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigQual",62, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 78: // SigQual ::= LONE + { + List RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos x = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new ArrayList(5); RESULT.add(null); RESULT.add(x); RESULT.add(null); RESULT.add(null); RESULT.add(null); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigQual",62, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 77: // SigQual ::= ABSTRACT + { + List RESULT =null; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos x = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new ArrayList(5); RESULT.add(x); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("SigQual",62, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 76: // Sig ::= SigQuals Names SigIn LBRACE Decls RBRACE SuperOpt + { + Object RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).right; + List b = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + List c = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List d = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int eleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int eright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr e = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + + if (e==null) e = ExprConstant.Op.TRUE.make(o, 0); + ExprVar cc = (c!=null && c.size()>0) ? c.remove(c.size()-1) : null; + for(ExprVar bb:b) { + parser.alloymodule.addSig(bb.label, cc, c, d, e, + AttrType.WHERE .makenull(bb.pos.merge(e==null ? o : e.span())), + AttrType.ABSTRACT.makenull(a.get(0)), + AttrType.LONE .makenull(a.get(1)), + AttrType.ONE .makenull(a.get(2)), + AttrType.SOME .makenull(a.get(3)), + AttrType.PRIVATE .makenull(a.get(4))); + } + + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Sig",60, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 75: // Vis ::= PRIVATE + { + Pos RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=p; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Vis",81, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 74: // Vis ::= + { + Pos RESULT =null; + RESULT=null; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Vis",81, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 73: // Predicate ::= Vis PRED SigRef DOT Name Super + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int fleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int fright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + ExprVar f = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int vleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int vright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr v = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , null , null, v); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Predicate",53, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 72: // Predicate ::= Vis PRED SigRef DOT Name LBRACKET Decls RBRACKET Super + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-7)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-7)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-7)).value; + int fleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).left; + int fright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).right; + ExprVar f = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List d = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int vleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int vright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr v = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , d , null, v); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Predicate",53, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 71: // Predicate ::= Vis PRED SigRef DOT Name LPAREN Decls RPAREN Super + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-7)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-7)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-7)).value; + int fleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).left; + int fright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).right; + ExprVar f = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List d = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int vleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int vright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr v = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , d , null, v); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Predicate",53, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 70: // Predicate ::= Vis PRED Name Super + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int vleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int vright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr v = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, null , null, v); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Predicate",53, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 69: // Predicate ::= Vis PRED Name LBRACKET Decls RBRACKET Super + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List d = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int vleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int vright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr v = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, d , null, v); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Predicate",53, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 68: // Predicate ::= Vis PRED Name LPAREN Decls RPAREN Super + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List d = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int vleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int vright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr v = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, d , null, v); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Predicate",53, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 67: // Function ::= Vis FUN SigRef DOT Name COLON Expr Super + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-7)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-7)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-7)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).value; + int fleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).left; + int fright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).right; + ExprVar f = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int rleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int rright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Expr r = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int vleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int vright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr v = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , null , mult(r), v); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Function",29, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-7)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 66: // Function ::= Vis FUN SigRef DOT Name LBRACKET Decls RBRACKET COLON Expr Super + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-10)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-10)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-10)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-9)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-9)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-9)).value; + int fleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)).left; + int fright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)).right; + ExprVar f = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).value; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + List d = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int rleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int rright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Expr r = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int vleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int vright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr v = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , d , mult(r), v); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Function",29, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-10)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 65: // Function ::= Vis FUN SigRef DOT Name LPAREN Decls RPAREN COLON Expr Super + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-10)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-10)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-10)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-9)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-9)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-9)).value; + int fleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)).left; + int fright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)).right; + ExprVar f = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).value; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + List d = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int rleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int rright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Expr r = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int vleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int vright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr v = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , d , mult(r), v); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Function",29, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-10)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 64: // Function ::= Vis FUN Name COLON Expr Super + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int rleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int rright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Expr r = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int vleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int vright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr v = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, null , mult(r), v); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Function",29, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 63: // Function ::= Vis FUN Name LBRACKET Decls RBRACKET COLON Expr Super + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-7)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-7)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-7)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).value; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + List d = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int rleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int rright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Expr r = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int vleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int vright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr v = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, d , mult(r), v); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Function",29, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 62: // Function ::= Vis FUN Name LPAREN Decls RPAREN COLON Expr Super + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-7)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-7)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-7)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).value; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + List d = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int rleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int rright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Expr r = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int vleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int vright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr v = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, d , mult(r), v); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Function",29, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 61: // MacroBody ::= EQUALS Expr + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("MacroBody",40, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 60: // MacroBody ::= Super + { + Expr RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr a = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("MacroBody",40, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 59: // Macro ::= Vis LET Name MacroBody + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int vleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int vright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr v = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, null , v); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Macro",39, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 58: // Macro ::= Vis LET Name LBRACKET RBRACKET MacroBody + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int vleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int vright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr v = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, null , v); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Macro",39, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 57: // Macro ::= Vis LET Name LBRACKET Names RBRACKET MacroBody + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List d = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int vleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int vright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr v = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, d , v); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Macro",39, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 56: // Macro ::= Vis LET Name LPAREN RPAREN MacroBody + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int vleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int vright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr v = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, null , v); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Macro",39, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 55: // Macro ::= Vis LET Name LPAREN Names RPAREN MacroBody + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int dleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int dright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List d = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int vleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int vright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr v = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, d , v); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Macro",39, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 54: // TypeNumber ::= NUMBER COLON NUMBER + { + CommandScope RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + ExprConstant a = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int ileft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int iright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant i = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos.merge(i.pos), Sig.NONE, false, a.num, Integer.MAX_VALUE, i.num); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("TypeNumber",70, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 53: // TypeNumber ::= NUMBER DOT DOT NUMBER COLON NUMBER + { + CommandScope RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).right; + ExprConstant a = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + ExprConstant b = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int ileft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int iright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant i = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos.merge(i.pos), Sig.NONE, false, a.num, b.num, i.num); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("TypeNumber",70, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 52: // TypeNumber ::= NUMBER DOT DOT NUMBER + { + CommandScope RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + ExprConstant a = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant b = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos.merge(b.pos), Sig.NONE, false, a.num, b.num, 1 ); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("TypeNumber",70, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 51: // TypeNumber ::= NUMBER + { + CommandScope RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant a = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = new CommandScope(a.pos , Sig.NONE, false, a.num, a.num, 1 ); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("TypeNumber",70, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 50: // TypeNumber ::= EXACTLY NUMBER COLON NUMBER + { + CommandScope RESULT =null; + int eleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int eright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos e = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + ExprConstant a = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int ileft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int iright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant i = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e.merge(i.pos), Sig.NONE, true, a.num, Integer.MAX_VALUE, i.num); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("TypeNumber",70, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 49: // TypeNumber ::= EXACTLY NUMBER DOT DOT NUMBER COLON NUMBER + { + CommandScope RESULT =null; + int eleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).left; + int eright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).right; + Pos e = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).right; + ExprConstant a = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + ExprConstant b = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int ileft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int iright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant i = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e.merge(i.pos), Sig.NONE, true, a.num, b.num, i.num); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("TypeNumber",70, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 48: // TypeNumber ::= EXACTLY NUMBER DOT DOT NUMBER + { + CommandScope RESULT =null; + int eleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int eright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Pos e = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + ExprConstant a = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant b = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e.merge(b.pos), Sig.NONE, true, a.num, b.num, 1 ); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("TypeNumber",70, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 47: // TypeNumber ::= EXACTLY NUMBER + { + CommandScope RESULT =null; + int eleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int eright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos e = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant a = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = new CommandScope( e.merge(a.pos), Sig.NONE, true, a.num, a.num, 1 ); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("TypeNumber",70, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 46: // Typescope ::= TypeNumber NONE + { + CommandScope RESULT =null; + int eleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int eright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + CommandScope e = (CommandScope)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int fleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int fright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos f = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + if (1==1) throw new ErrorSyntax(e.pos.merge(f), "You cannot set a scope on none."); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Typescope",71, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 45: // Typescope ::= TypeNumber STRING + { + CommandScope RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + CommandScope a = (CommandScope)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos b = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = new CommandScope(a.pos.merge(b), new PrimSig("String", AttrType.WHERE.make(a.pos.merge(b))), a.isExact, a.startingScope, a.endingScope, a.increment); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Typescope",71, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 44: // Typescope ::= TypeNumber UNIV + { + CommandScope RESULT =null; + int eleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int eright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + CommandScope e = (CommandScope)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int fleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int fright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos f = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + if (1==1) throw new ErrorSyntax(e.pos.merge(f), "You cannot set a scope on univ."); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Typescope",71, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 43: // Typescope ::= TypeNumber SEQ + { + CommandScope RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + CommandScope a = (CommandScope)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos b = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + + Pos p = a.pos.merge(b); + if (a.endingScope>a.startingScope) throw new ErrorSyntax(p, "Cannot specify a growing scope for \"seq\""); + if (a.isExact) throw new ErrorSyntax(p, "The exactly keyword is redundant here since the number of sequence index has to be exact."); + RESULT = new CommandScope(p, new PrimSig("seq", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.startingScope, 1); + + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Typescope",71, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 42: // Typescope ::= TypeNumber INT + { + CommandScope RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + CommandScope a = (CommandScope)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos b = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + + Pos p = a.pos.merge(b); + if (a.endingScope>a.startingScope) throw new ErrorSyntax(p, "Cannot specify a growing scope for \"Int\""); + if (a.isExact) throw new ErrorSyntax(p, "The exactly keyword is redundant here since the integer bitwidth must be exact."); + RESULT = new CommandScope(p, new PrimSig("int", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.startingScope, 1); + + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Typescope",71, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 41: // Typescope ::= TypeNumber SIGINT + { + CommandScope RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + CommandScope a = (CommandScope)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos b = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + + Pos p = a.pos.merge(b); + if (a.endingScope>a.startingScope) throw new ErrorSyntax(p, "Cannot specify a growing scope for \"Int\""); + if (a.isExact) throw new ErrorSyntax(p, "The exactly keyword is redundant here since the integer bitwidth must be exact."); + RESULT = new CommandScope(p, new PrimSig("int", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.startingScope, 1); + + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Typescope",71, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 40: // Typescope ::= TypeNumber Name + { + CommandScope RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + CommandScope a = (CommandScope)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar b = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + + nod(b); + RESULT = new CommandScope(a.pos.merge(b.pos), new PrimSig(b.label, AttrType.WHERE.make(a.pos.merge(b.pos))), a.isExact, a.startingScope, a.endingScope, a.increment); + + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Typescope",71, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 39: // Typescopes ::= Typescopes COMMA Typescope + { + List RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + List a = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + CommandScope b = (CommandScope)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=a; a.add(b); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Typescopes",72, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 38: // Typescopes ::= Typescope + { + List RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + CommandScope a = (CommandScope)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new ArrayList(); RESULT.add(a); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Typescopes",72, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 37: // Scope ::= + { + List RESULT =null; + RESULT=new ArrayList(); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Scope",59, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 36: // Scope ::= FOR Typescopes + { + List RESULT =null; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + List b = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Scope",59, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 35: // Scope ::= FOR NUMBER BUT Typescopes + { + List RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + ExprConstant a = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + List b = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=b; b.add(new CommandScope(a.pos, new PrimSig("univ", AttrType.WHERE.make(a.pos)), true, a.num, a.num, 1)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Scope",59, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 34: // Scope ::= FOR NUMBER + { + List RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant a = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=new ArrayList(); RESULT.add(new CommandScope(a.pos, new PrimSig("univ", AttrType.WHERE.make(a.pos)), true, a.num, a.num, 1)); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Scope",59, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 33: // Expects ::= EXPECT NUMBER + { + ExprConstant RESULT =null; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant a = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT=a; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Expects",21, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 32: // Expects ::= + { + ExprConstant RESULT =null; + RESULT=null; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Expects",21, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 31: // Command ::= Command IMPLIES CommandPrefix Name Scope Expects + { + Object RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + ExprVar o = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int sleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int sright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List s = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant c = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + c(true ,o,null,n ,null,s,c); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Command",8, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 30: // Command ::= Command IMPLIES CommandPrefix Name Name Scope Expects + { + Object RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + ExprVar o = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + ExprVar x = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int sleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int sright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List s = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant c = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + c(true ,o,x ,n ,null,s,c); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Command",8, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 29: // Command ::= CommandPrefix Name Scope Expects + { + Object RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + ExprVar o = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int sleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int sright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List s = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant c = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + c(false,o,null,n ,null,s,c); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Command",8, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 28: // Command ::= CommandPrefix Name Name Scope Expects + { + Object RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + ExprVar o = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + ExprVar x = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int sleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int sright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List s = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant c = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + c(false,o,x ,n ,null,s,c); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Command",8, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 27: // Command ::= Command IMPLIES CommandPrefix Super Scope Expects + { + Object RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + ExprVar o = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int eleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int eright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr e = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int sleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int sright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List s = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant c = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + c(true ,o,null,null,e ,s,c); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Command",8, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 26: // Command ::= Command IMPLIES CommandPrefix Name Super Scope Expects + { + Object RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + ExprVar o = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + ExprVar x = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int eleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int eright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr e = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int sleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int sright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List s = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant c = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + c(true ,o,x ,null,e ,s,c); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Command",8, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 25: // Command ::= CommandPrefix Super Scope Expects + { + Object RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + ExprVar o = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int eleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int eright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr e = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int sleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int sright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List s = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant c = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + c(false,o,null,null,e ,s,c); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Command",8, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 24: // Command ::= CommandPrefix Name Super Scope Expects + { + Object RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + ExprVar o = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int xleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int xright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + ExprVar x = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int eleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int eright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Expr e = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int sleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int sright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List s = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprConstant c = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + c(false,o,x ,null,e ,s,c); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Command",8, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 23: // CommandPrefix ::= RUN + { + ExprVar RESULT =null; + int rleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int rright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos r = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprVar.make(r, "r"); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CommandPrefix",9, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 22: // CommandPrefix ::= CHECK + { + ExprVar RESULT =null; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos c = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + RESULT = ExprVar.make(c, "c"); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("CommandPrefix",9, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 21: // Spec ::= + { + Object RESULT =null; + + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 20: // Spec ::= Spec Command + { + Object RESULT =null; + + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 19: // Spec ::= Spec Macro + { + Object RESULT =null; + + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 18: // Spec ::= Spec Predicate + { + Object RESULT =null; + + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 17: // Spec ::= Spec Function + { + Object RESULT =null; + + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 16: // Spec ::= Spec Sig + { + Object RESULT =null; + + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 15: // Spec ::= Spec ASSERT STR Super + { + Object RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + ExprConstant n = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int eleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int eright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr e = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + parser.alloymodule.addAssertion (o , n.string , e); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 14: // Spec ::= Spec ASSERT Name Super + { + Object RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int eleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int eright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr e = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addAssertion (o , n.label , e); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 13: // Spec ::= Spec ASSERT Super + { + Object RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int eleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int eright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr e = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + parser.alloymodule.addAssertion (o , "" , e); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 12: // Spec ::= Spec FACT STR Super + { + Object RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + ExprConstant n = (ExprConstant)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int eleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int eright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr e = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + parser.alloymodule.addFact (o , n.string , e); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 11: // Spec ::= Spec FACT Name Super + { + Object RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int eleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int eright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr e = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addFact (o , n.label , e); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 10: // Spec ::= Spec FACT Super + { + Object RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int eleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int eright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Expr e = (Expr)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + parser.alloymodule.addFact (o , "" , e); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 9: // Spec ::= Spec Vis ENUM Name LBRACE RBRACE + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + ExprVar a = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos c = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(a); parser.alloymodule.addEnum(o.merge(c), p, a, null, c); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 8: // Spec ::= Spec Vis ENUM Name LBRACE Names RBRACE + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + ExprVar a = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List n = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos c = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(a); parser.alloymodule.addEnum(o.merge(c), p, a, n, c); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 7: // Spec ::= Spec Vis OPEN Name LBRACKET SigRefs RBRACKET AS Name + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-7)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-7)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-7)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).right; + ExprVar a = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + List b = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar c = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(a); nod(c); parser.alloymodule.addOpen(o.merge(c.pos), p, a, b, c); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-8)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 6: // Spec ::= Spec Vis OPEN Name LBRACKET SigRefs RBRACKET + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + ExprVar a = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List b = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos c = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(a); parser.alloymodule.addOpen(o.merge(c), p, a, b, null); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-6)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 5: // Spec ::= Spec Vis OPEN Name AS Name + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + ExprVar a = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int cleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int cright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar c = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(a); nod(c); parser.alloymodule.addOpen(o.merge(c.pos), p, a, null, c); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 4: // Spec ::= Spec Vis OPEN Name + { + Object RESULT =null; + int pleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).left; + int pright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).right; + Pos p = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)).value; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int aleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int aright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar a = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(a); parser.alloymodule.addOpen(o.merge(a.pos), p, a, null, null); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 3: // Spec ::= Spec MODULE Name LBRACKET Namex RBRACKET + { + Object RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-4)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-3)).value; + int bleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int bright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + List b = (List)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int rleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int rright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + Pos r = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); nod(b); parser.alloymodule.addModelName(o.merge(r) , n.label , b ); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-5)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 2: // Spec ::= Spec MODULE Name + { + Object RESULT =null; + int oleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int oright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Pos o = (Pos)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + int nleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).left; + int nright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()).right; + ExprVar n = (ExprVar)((java_cup.runtime.Symbol) CUP$CompParser$stack.peek()).value; + nod(n); parser.alloymodule.addModelName(o.merge(n.pos) , n.label , new ArrayList()); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("Spec",69, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-2)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 1: // $START ::= File EOF + { + Object RESULT =null; + int start_valleft = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).left; + int start_valright = ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).right; + Object start_val = (Object)((java_cup.runtime.Symbol) CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)).value; + RESULT = start_val; + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("$START",0, ((java_cup.runtime.Symbol)CUP$CompParser$stack.elementAt(CUP$CompParser$top-1)), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + /* ACCEPT */ + CUP$CompParser$parser.done_parsing(); + return CUP$CompParser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 0: // File ::= Spec + { + Object RESULT =null; + parser.alloymodule.doneParsing(); + CUP$CompParser$result = parser.getSymbolFactory().newSymbol("File",68, ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), ((java_cup.runtime.Symbol)CUP$CompParser$stack.peek()), RESULT); + } + return CUP$CompParser$result; + + /* . . . . . .*/ + default: + throw new Exception( + "Invalid action number found in internal parse table"); + + } + } +} + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/CompSym.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/CompSym.java new file mode 100644 index 00000000..243199db --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/CompSym.java @@ -0,0 +1,129 @@ + +//---------------------------------------------------- +// The following code was generated by CUP v0.11a beta 20060608 +// Tue Nov 08 16:09:13 EST 2011 +//---------------------------------------------------- + +package edu.mit.csail.sdg.alloy4compiler.parser; + +/** CUP generated class containing symbol constants. */ +public class CompSym { + /* terminals */ + public static final int AT = 34; + public static final int AS = 32; + public static final int ANY_ARROW_SOME = 3; + public static final int GT = 54; + public static final int ARROW = 2; + public static final int NOTLTE = 81; + public static final int INTSUB = 19; + public static final int ONE_ARROW_ANY = 10; + public static final int ONE2 = 82; + public static final int ENUM = 45; + public static final int IDEN = 57; + public static final int SIG = 101; + public static final int EXH = 48; + public static final int INTMIN = 23; + public static final int COMMA = 40; + public static final int SUM = 109; + public static final int RBRACE = 92; + public static final int RPAREN = 94; + public static final int LONE_ARROW_LONE = 17; + public static final int RUN = 95; + public static final int NOTGTE = 78; + public static final int ALL = 28; + public static final int LT = 68; + public static final int INTMUL = 20; + public static final int LBRACE = 62; + public static final int SOME_ARROW_ANY = 6; + public static final int LPAREN = 67; + public static final int SHR = 99; + public static final int NOT = 75; + public static final int TILDE = 111; + public static final int PART = 86; + public static final int SHL = 98; + public static final int NOTEQUALS = 76; + public static final int STR = 115; + public static final int SHA = 100; + public static final int LONE_ARROW_ONE = 16; + public static final int SOME_ARROW_LONE = 9; + public static final int INTADD = 18; + public static final int INTDIV = 21; + public static final int INTMAX = 24; + public static final int NUMBER = 114; + public static final int ABSTRACT = 27; + public static final int INTNEXT = 25; + public static final int SLASH = 103; + public static final int NO2 = 72; + public static final int TOTALORDER = 26; + public static final int ONE_ARROW_LONE = 13; + public static final int NOTIN = 79; + public static final int UNIV = 112; + public static final int PLUS = 87; + public static final int FACT = 51; + public static final int LONE = 66; + public static final int ONE = 83; + public static final int MODULE = 71; + public static final int EXTENDS = 50; + public static final int DOMAIN = 42; + public static final int EXACTLY = 47; + public static final int NONE = 74; + public static final int SOME2 = 104; + public static final int FOR = 52; + public static final int STAR = 106; + public static final int LONE_ARROW_SOME = 15; + public static final int ELSE = 44; + public static final int FUN = 53; + public static final int DOT = 43; + public static final int AMPERSAND = 30; + public static final int INT = 61; + public static final int LTE = 69; + public static final int SIGINT = 102; + public static final int DISJ = 41; + public static final int EOF = 0; + public static final int THIS = 110; + public static final int INTREM = 22; + public static final int ANY_ARROW_LONE = 5; + public static final int BUT = 36; + public static final int LONE_ARROW_ANY = 14; + public static final int ALL2 = 29; + public static final int MINUS = 70; + public static final int SOME_ARROW_SOME = 7; + public static final int SUM2 = 108; + public static final int IN = 60; + public static final int OR = 85; + public static final int SET = 97; + public static final int error = 1; + public static final int NOTGT = 77; + public static final int SEQ = 96; + public static final int GTE = 55; + public static final int ID = 113; + public static final int ONE_ARROW_SOME = 11; + public static final int ONE_ARROW_ONE = 12; + public static final int COLON = 39; + public static final int CHECK = 38; + public static final int ASSERT = 33; + public static final int SOME = 105; + public static final int LONE2 = 65; + public static final int RBRACKET = 93; + public static final int CARET = 37; + public static final int EXPECT = 49; + public static final int PLUSPLUS = 88; + public static final int STRING = 107; + public static final int RANGE = 91; + public static final int NO = 73; + public static final int SOME_ARROW_ONE = 8; + public static final int AND = 31; + public static final int ANY_ARROW_ONE = 4; + public static final int PRIVATE = 90; + public static final int OPEN = 84; + public static final int BAR = 35; + public static final int NOTLT = 80; + public static final int IMPLIES = 59; + public static final int LBRACKET = 63; + public static final int PRED = 89; + public static final int LET = 64; + public static final int IFF = 58; + public static final int EQUALS = 46; + public static final int HASH = 56; +} + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/CompUtil.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/CompUtil.java new file mode 100644 index 00000000..6dd5d5a8 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/CompUtil.java @@ -0,0 +1,263 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.parser; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; +import edu.mit.csail.sdg.alloy4compiler.parser.CompModule.Open; + +/** This class provides convenience methods for calling the parser and the compiler. */ + +public final class CompUtil { + + /** Constructor is private, since this class never needs to be instantiated. */ + private CompUtil() { } + + //=============================================================================================================// + + /** Go up the directory hierachy 0 or more times. + *
For example, on a UNIX machine, goUp("/home/abc/def",1) will return "/home/abc" + *
For example, on a UNIX machine, goUp("/home/abc/def",2) will return "/home" + * @param filepath - this must be an absolute path + * @param numberOfSteps - the number of steps to go up + */ + private static String up(String filepath, int numberOfSteps) { + while(numberOfSteps > 0) { + numberOfSteps--; + int i=filepath.lastIndexOf(File.separatorChar); + if (i<=0) return ""; + filepath=filepath.substring(0,i); + } + return filepath; + } + + //=============================================================================================================// + + /** Given the name of a module, and the filename for that module, compute the filename for another module + * @param moduleA - must be a legal Alloy modulepath (eg. name) (eg. name/name/name) (must not start or end in '/') + * @param fileA - the filename corresponding to moduleA + * @param moduleB - must be a legal Alloy modulepath (eg. name) (eg. name/name/name) (must not start or end in '/') + * @return the filename corresponding to moduleB + */ + private static String computeModulePath(String moduleA, String fileA, String moduleB) { + fileA=Util.canon(fileA); // Make sure it's a canonical absolute path + if (moduleA.length()==0) moduleA="anything"; // Harmonizes the boundary case + while(moduleA.length()>0 && moduleB.length()>0) { + int a=moduleA.indexOf('/'), b=moduleB.indexOf('/'); + String headOfA = (a>=0) ? moduleA.substring(0,a) : moduleA; + String headOfB = (b>=0) ? moduleB.substring(0,b) : moduleB; + if (!headOfA.equals(headOfB) || a<0 || b<0) { + // eg. util/boolean==/home/models/util/boolean.als, then test=>/home/models/test.als" + // eg. util/boolean==/home/models/util/boolean.als, then sub/test=>/home/models/sub/test.als + // eg. main==/home/models/main.als, then test=>/home/models/test.als + // eg. main==/home/models/main.als, then sub/test=>/home/models/sub/test.als" + int numberOfSlash=0; + for(int i=0; i seenDollar, Map loaded, Map fc, Pos pos, String filename, CompModule root, String prefix, Set thispath, int initialResolution) + throws Err, FileNotFoundException, IOException { + // Add the filename into a ArrayList, so that we can detect cycles in the module import graph + // How? I'll argue that (filename appears > 1 time along a chain) <=> (infinite loop in the import graph) + // => As you descend down the chain via OPEN, if you see the same FILE twice, then + // you will go into an infinite loop (since, regardless of the instantiating parameter, + // that file will attempt to OPEN the exact same set of files. leading back to itself, etc. etc.) + // <= If there is an infinite loop, that means there is at least 1 infinite chain of OPEN (from root). + // Since the number of files is finite, at least 1 filename will be repeated. + if (thispath.contains(filename)) + throw new ErrorSyntax(pos, + "Circular dependency in module import. The file \""+(new File(filename)).getName()+"\" is imported infinitely often."); + thispath.add(filename); + // No cycle detected so far. So now we parse the file. + CompModule u = CompParser.alloy_parseStream(seenDollar, loaded, fc, root, 0, filename, prefix, initialResolution); + if (prefix.length()==0) root = u; + + // Here, we recursively open the included files + for(Open x: u.getOpens()) { + String cp=Util.canon(computeModulePath(u.getModelName(), filename, x.filename)), content=fc.get(cp); + try { + if (content==null) { content=loaded.get(cp); } + if (content==null) { content=fc.get(x.filename); if (content!=null) cp=x.filename; } + if (content==null) { content=loaded.get(x.filename); if (content!=null) cp=x.filename; } + if (content==null) { content=Util.readAll(cp); } + } catch(IOException ex1) { + try { + String newCp = (Util.jarPrefix()+"models/"+x.filename+".als").replace('/', File.separatorChar); + content = Util.readAll(newCp); + cp = newCp; + } catch(IOException ex) { + throw new ErrorSyntax(x.pos, + "This module cannot be found.\nIt is not a built-in library module, and it cannot be found at \""+cp+"\".\n"); + } + } + loaded.put(cp, content); + CompModule y = parseRecursively(seenDollar, loaded, fc, x.pos, cp, root, (prefix.length()==0 ? x.alias : prefix+"/"+x.alias), thispath, initialResolution); + x.connect(y); + } + thispath.remove(filename); // Remove this file from the CYCLE DETECTION LIST. + return u; + } + + //=============================================================================================================// + + /** Parses 1 module from the input string (without loading any subfiles) + * @return an array of 0 or more Command if no error occurred + */ + public static ConstList parseOneModule_fromString(String content) throws Err { + CompModule u = parseOneModule(content); + return ConstList.make(u.getAllCommands()); + } + + public static CompModule parseOneModule(String content) throws Err { + try { + Map fc = new LinkedHashMap(); + fc.put("", content); + return CompParser.alloy_parseStream(new ArrayList(), null, fc, null, 0, "", "", 1); + } catch(IOException ex) { + throw new ErrorFatal("IOException occurred: "+ex.getMessage(), ex); + } catch(Throwable ex) { + if (ex instanceof Err) throw (Err)ex; else throw new ErrorFatal("Unknown exception occurred: "+ex, ex); + } + } + + //=============================================================================================================// + + /** Parses 1 module from the file (without loading any subfiles) + * @return an array of 0 or more Command if no error occurred + */ + public static ConstList parseOneModule_fromFile(String filename) throws Err { + try { + CompModule u = CompParser.alloy_parseStream(new ArrayList(), null, null, null, 0, filename, "", 1); + return ConstList.make(u.getAllCommands()); + } catch(IOException ex) { + throw new ErrorFatal("IOException occurred: "+ex.getMessage(), ex); + } catch(Throwable ex) { + if (ex instanceof Err) throw (Err)ex; else throw new ErrorFatal("Unknown exception occurred: "+ex, ex); + } + } + + //=============================================================================================================// + + /** Parses then typecheck the given input String as an Alloy expression from that world + * @return the fully-typechecked expression if no error occurred + * @throws Err if world==null or if any other error occurred + */ + public static Expr parseOneExpression_fromString (Module world, String input) throws Err { + try { + if (world==null) throw new ErrorFatal("Cannot parse an expression with null world."); + return world.parseOneExpressionFromString(input); + } catch(IOException ex) { + throw new ErrorFatal("IOException occurred: "+ex.getMessage(), ex); + } catch(Throwable ex) { + if (ex instanceof Err) throw (Err)ex; else throw new ErrorFatal("Unknown exception occurred: "+ex, ex); + } + } + + //=============================================================================================================// + + /** Read everything from "file" and parse it; if it mentions submodules, open them and parse them too. + * @param rep - if nonnull, we will report compilation progress messages to it + * @param loaded - a cache of files that have been pre-fetched (can be null if there were no prefetching) + * @param filename - the main module we are parsing + * @return the root Module which contains pointers to all submodules + * @throws Err if an error occurred + *

And if loaded!=null, it will contain all the files needed for this parse, and furthermore, other entries will be deleted. + */ + public static CompModule parseEverything_fromFile (A4Reporter rep, Map loaded, String filename) throws Err { + try { + filename = Util.canon(filename); + Set thispath = new LinkedHashSet(); + if (loaded==null) loaded = new LinkedHashMap(); + Map fc = new LinkedHashMap(loaded); + loaded.clear(); + List seenDollar = new ArrayList(); + CompModule root = parseRecursively(seenDollar, loaded, fc, new Pos(filename,1,1), filename, null, "", thispath, 1); + root.seenDollar = seenDollar.size()>0; + return CompModule.resolveAll(rep==null ? A4Reporter.NOP : rep, root); + } catch(FileNotFoundException ex) { + throw new ErrorSyntax("File cannot be found.\n"+ex.getMessage(), ex); + } catch(IOException ex) { + throw new ErrorFatal("IOException occurred: "+ex.getMessage(), ex); + } catch(Throwable ex) { + if (ex instanceof Err) throw (Err)ex; else throw new ErrorFatal("Unknown exception occurred: "+ex, ex); + } + } + + /** Read everything from "file" and parse it; if it mentions submodules, open them and parse them too. + * @param rep - if nonnull, we will report compilation progress messages to it + * @param loaded - a cache of files that have been pre-fetched (can be null if there were no prefetching) + * @param filename - the main module we are parsing + * @param initialResolutionMode - use 1 for the historical behavior, and 2 for Alloy 4.2's new "universal implicit this" name resolution behavior + * @return the root CompModule which contains pointers to all submodules + * @throws Err if an error occurred + *

And if loaded!=null, it will contain all the files needed for this parse, and furthermore, other entries will be deleted. + */ + public static CompModule parseEverything_fromFile (A4Reporter rep, Map loaded, String filename, int initialResolutionMode) throws Err { + try { + filename = Util.canon(filename); + Set thispath = new LinkedHashSet(); + if (loaded==null) loaded = new LinkedHashMap(); + Map fc = new LinkedHashMap(loaded); + loaded.clear(); + List seenDollar = new ArrayList(); + CompModule root = parseRecursively(seenDollar, loaded, fc, new Pos(filename,1,1), filename, null, "", thispath, initialResolutionMode); + root.seenDollar = seenDollar.size()>0; + return CompModule.resolveAll(rep==null ? A4Reporter.NOP : rep, root); + } catch(FileNotFoundException ex) { + throw new ErrorSyntax("File cannot be found.\n"+ex.getMessage(), ex); + } catch(IOException ex) { + throw new ErrorFatal("IOException occurred: "+ex.getMessage(), ex); + } catch(Throwable ex) { + if (ex instanceof Err) throw (Err)ex; else throw new ErrorFatal("Unknown exception occurred: "+ex, ex); + } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/Macro.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/Macro.java new file mode 100644 index 00000000..e2e78b8f --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/Macro.java @@ -0,0 +1,126 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.parser; + +import java.util.ArrayList; +import java.util.List; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4compiler.ast.Browsable; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprBad; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprCustom; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import edu.mit.csail.sdg.alloy4compiler.parser.CompModule.Context; + +/** Immutable; this class represents a macro. */ + +final class Macro extends ExprCustom { + + /** If nonnull, this is a private macro. */ + final Pos isPrivate; + + /** The module that defined this. */ + private final CompModule realModule; + + /** The name of the macro. */ + private final String name; + + /** The list of parameters (can be an empty list) */ + private final ConstList params; + + /** The list of arguments (can be an empty list) (must be equal or shorter than this.params) */ + private final ConstList args; + + /** The macro body. */ + private final Expr body; + + /** Construct a new Macro object. */ + private Macro(Pos pos, Pos isPrivate, CompModule realModule, String name, List params, List args, Expr body) { + super(pos, new ErrorFatal(pos, "Incomplete call on the macro \""+name+"\"")); + this.realModule = realModule; + this.isPrivate = isPrivate; + this.name = name; + this.params = ConstList.make(params); + this.args = ConstList.make(args); + this.body = body; + } + + /** Construct a new Macro object. */ + Macro(Pos pos, Pos isPrivate, CompModule realModule, String name, List params, Expr body) { + this(pos, isPrivate, realModule, name, params, null, body); + } + + Macro addArg(Expr arg) { + return new Macro(pos, isPrivate, realModule, name, params, Util.append(args,arg), body); + } + + Expr changePos(Pos pos) { + return new Macro(pos, isPrivate, realModule, name, params, args, body); + } + + /** Instantiate it. + * + * @param warnings - the list that will receive any warning we generate; can be null if we wish to ignore warnings + */ + Expr instantiate(Context cx, List warnings) throws Err { + if (cx.unrolls<=0) { + Pos p = span(); + return new ExprBad(p, toString(), new ErrorType(p, "Macro substitution too deep; possibly indicating an infinite recursion.")); + } + if (params.size() != args.size()) return this; + Context cx2 = new Context(realModule, warnings, cx.unrolls-1); + for(int n=params.size(), i=0; ierror (parser or typechecker failed)"; } + + /** {@inheritDoc} */ + @Override public List getSubnodes() { return new ArrayList(0); } + + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/generate-lexer.sh b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/generate-lexer.sh new file mode 100644 index 00000000..de50c662 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/generate-lexer.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +java -cp $LIB_SDG/jars-external/JFlex.jar JFlex.Main --nobak -d . Alloy.lex + +sed -i 's/public java_cup.runtime.Symbol next_token() throws java.io.IOException/public java_cup.runtime.Symbol next_token() throws java.io.IOException, Err/' CompLexer.java + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/generate-parser.sh b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/generate-parser.sh new file mode 100644 index 00000000..f27fddeb --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/generate-parser.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +java -cp $LIB_SDG/jars-external/java-cup-11a.jar java_cup.Main \ + -package edu.mit.csail.sdg.alloy4compiler.parser \ + -parser CompParser \ + -progress -time -compact_red \ + -symbols CompSym < Alloy.cup \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/generate-parsing-trace-from-log.sh b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/generate-parsing-trace-from-log.sh new file mode 100644 index 00000000..4c640e8d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/parser/generate-parsing-trace-from-log.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +## ---------------------------------------------------------------------- +## +## This script takes a parsing log and from it generates a human readable +## parsing trace, i.g. a sequence of shifts and reduces that took place. +## +## To get the parsing log just set the "debug" environment variable to +## "yes" before runngin Alloy (or add "-Ddebug=yes" to the list of JVM +## arguments) +## +## This script must be invoked from exactly the folder where it resides +## because it needs to find the CompParser.java and CompSym.java files +## in the same folder. +## +## ---------------------------------------------------------------------- + +logFile=$1 + +if [[ -z $logFile ]] +then + echo "usage: $0 " + exit +fi + +if [[ ! -f $logFile ]] +then + echo "file $logFile doesn't exist" + exit +fi + +while read line +do + if [[ ! -z $(echo $line | grep "^reduce ") ]] + then + act=$(echo $line | sed 's/reduce //') + echo "reduce" + grep "case $act:" CompParser.java + elif [[ ! -z $(echo $line | grep "^shift ") ]] + then + sym=$(echo $line | sed 's/shift //') + sgn=$(grep " = $sym;" CompSym.java | sed 's/ public static final int //' | sed 's/ = '$sym';//') + echo "shift" + echo " $sgn" + else + echo $line + fi +done < $logFile \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/sim/SimAtom.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/sim/SimAtom.java new file mode 100644 index 00000000..23781016 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/sim/SimAtom.java @@ -0,0 +1,146 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.sim; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.util.WeakHashMap; + +/** Immutable; represents an atom. + * + *

Outside of this class, we guarantee for any SimAtom x and y, then "x.equals(y) iff x==y". + *
Even though that means "equals()" and "==" are equivalent, + *
the equals() method is much slower than "==" for SimAtom, + *
so you should always try to use "==" on SimAtom. + * + *

Thread Safety: Safe. + */ + +public final class SimAtom { + + /** This map is used to canonicalize the atoms. */ + private static final WeakHashMap> map = new WeakHashMap>(); + + /** The String label for the atom; all distinct atoms have distinct labels. */ + private String string; + + /** Construct a SimAtom; this constructor must only be called by make() since we want to canonicalize all SimAtom instances out there. */ + private SimAtom(String x) { this.string = x; } + + /** Construct a SimAtom for the given label, or if an existing SimAtom hasn't been garbage collected yet then return that instead. */ + public static SimAtom make(String label) { + synchronized(map) { + SimAtom x = new SimAtom(label); + WeakReference ans = map.get(x); + if (ans != null) { SimAtom y = ans.get(); if (y!=null) return y; } + map.put(x, new WeakReference(x)); + return x; + } + } + + /** Construct a SimAtom for the given integer, or if an existing SimAtom hasn't been garbage collected yet then return that instead. */ + public static SimAtom make(int i) { return make(String.valueOf(i)); } + + /** Construct a SimAtom for the given integer, or if an existing SimAtom hasn't been garbage collected yet then return that instead. */ + public static SimAtom make(long i) { return make(String.valueOf(i)); } + + /** Preconstructed atom representing emptystring. */ + public static final SimAtom EMPTYSTRING = make(""); + + /** Preconstructed atom representing 0. */ + public static final SimAtom ZERO = make("0"); + + /** Preconstructed atom representing 1. */ + public static final SimAtom ONE = make("1"); + + /** Write this atom as "..". */ + void write(BufferedOutputStream out) throws IOException { + byte array[] = string.getBytes("UTF-8"); + out.write('\"'); + for(int n=array.length, i=0; i0 && b<=' ') out.write(' '); + else out.write(b); + } + out.write('\"'); + } + + /** Read a "..." atom assuming the leading " has already been consumed. */ + static SimAtom read(BufferedInputStream in) throws IOException { + byte temp[] = new byte[64]; // to ensure proper detection of out-of-memory error, this number must be 2^n for some n>=0 + int n = 0; + while(true) { + int c = in.read(); + if (c<0) throw new IOException("Unexpected EOF"); + if (c=='\"') break; + if (c=='\\') { + c=in.read(); + if (c<0) throw new IOException("Unexpected EOF"); + if (c=='n') c='\n'; + } + while (n >= temp.length) { + byte temp2[] = new byte[temp.length * 2]; + System.arraycopy(temp, 0, temp2, 0, temp.length); + temp = temp2; + } + temp[n]=(byte)c; + n++; + } + return make(new String(temp, 0, n, "UTF-8")); + } + + /** If the atom starts with "-" or "0-9" then convert it into a 32-bit int (here we assume that it came from a 32-bit int) + *

+ * If the atom does not start with "-" or "0-9", then return defaultValue. + */ + public Integer toInt(Integer defaultValue) throws NumberFormatException { + int ans=0, i=0, n=string.length(); + if (n==0) return defaultValue; + // Due to Java's 2's complement arithmetic, this will successfully + // convert all integers ranging from Integer.MIN to Integer.MAX + if (string.charAt(0)=='-') i++; + if (string.charAt(i)<'0' || string.charAt(i)>'9') return defaultValue; + for(;i arguments) throws Exception; +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/sim/SimInstance.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/sim/SimInstance.java new file mode 100644 index 00000000..9a1614dd --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/sim/SimInstance.java @@ -0,0 +1,883 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.sim; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import edu.mit.csail.sdg.alloy4.Env; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorAPI; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.ConstList.TempList; +import edu.mit.csail.sdg.alloy4compiler.ast.Decl; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprBinary; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprCall; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprConstant; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprHasName; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprITE; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprLet; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprList; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprQt; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprUnary; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import edu.mit.csail.sdg.alloy4compiler.ast.Func; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.VisitReturn; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.SubsetSig; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; + +/** Mutable; represents an instance. */ + +public final class SimInstance extends VisitReturn { + + /** The root module associated with this instance. */ + public final Module root; + + /** This maps the current local variables (LET, QUANT, Function Param) to the actual SimTupleset/Integer/Boolean */ + private Env env = new Env(); + + /** This stores the "call backs" where you can supply Java code to efficiently handle certain functions/predicates. */ + private final Map callbacks; + + /** The exact values of each sig, field, and skolem (Note: it must not cache the value of any "defined" field, nor any builtin sig) */ + private final Map sfs = new LinkedHashMap(); + + /** If nonnull, it caches the current value of STRING (this value must be cleared or updated when you change the value of sigs/fields/vars) */ + private SimTupleset cacheSTRING = null; + + /** If nonnull, it caches the current value of UNIV (this value must be cleared or updated when you change the value of sigs) */ + private SimTupleset cacheUNIV = null; + + /** Caches parameter-less functions to a Boolean, Integer, or SimTupleset. */ + private final Map cacheForConstants = new IdentityHashMap(); + + /** This is used to detect "function recursion" (which we currently do not allow). */ + private final List current_function = new ArrayList(); + + /** The chosen bitwidth */ + private final int bitwidth; + + /** The chosen maxseq length. */ + private final int maxseq; + + /** The shiftmask based on the chosen bitwidth. */ + private final int shiftmask; + + /** The minimum allowed integer based on the chosen bitwidth. */ + private final int min; + + /** The maximum allowed integer based on the chosen bitwidth. */ + private final int max; + + /** Whether the was overflow the last time "trunc" was called */ + private boolean wasOverflow; + public boolean wasOverflow() { return wasOverflow; } + + /** Helper method that encodes the given string using UTF-8 and write to the output stream. */ + private static void write(BufferedOutputStream out, String string) throws IOException { + out.write(string.getBytes("UTF-8")); + } + + /** Write the bitwidth, maxseq, set of all atoms, and map of all sig/field/var into the given file. */ + public void write(String filename) throws IOException { + FileOutputStream fos = null; + BufferedOutputStream bos = null; + try { + fos = new FileOutputStream(filename); + bos = new BufferedOutputStream(fos); + write(bos); + bos.flush(); + bos.close(); + bos = null; + fos.close(); + fos = null; + } finally { + Util.close(bos); + Util.close(fos); + } + } + + /** Write the bitwidth, maxseq, set of all atoms, and map of all sig/field/var into the given file. */ + private void write(BufferedOutputStream out) throws IOException { + write(out, "maxseq = " + maxseq + ("\n" + "bitwidth = ") + bitwidth + "\n"); + for(Map.Entry entry: sfs.entrySet()) { + Expr e = entry.getKey(); + if (e instanceof Sig) write(out, "sig " + ((Sig)e).label + " = "); + else if (e instanceof Field) write(out, "field " + ((Field)e).sig.label + " " + ((Field)e).label + " = "); + else if (e instanceof ExprVar) write(out, "var " + ((ExprVar)e).label + " = "); + else continue; + entry.getValue().write(out); + out.write('\n'); + } + } + + /** Temporary buffer used by the parser; access to this buffer must be synchronized on SimInstance's class. */ + private static byte[] readcache = null; + + /** Helper method that read a non-negative integer followed by a line break. */ + private static int readNonNegativeIntThenLinebreak(BufferedInputStream bis) throws IOException { + int n = 0; + while(true) { + int c = bis.read(); + if (c<0) throw new IOException("Unexpected EOF"); + if (c=='\n') return n; + if (c>0 && c<=' ') continue; // skip white space + if (!(c>='0' && c<='9')) throw new IOException("Expects a DIGIT or a white space!"); + n = n*10 + (c-'0'); + } + } + + /** Helper method that read "key =" then return the key part (with leading and trailing spaces removed). + * This method can only be called after you've synchronized on SimInstance's class. + */ + private static String readkey(BufferedInputStream bis) throws IOException { + int n = 0; + while(true) { + int c = bis.read(); + if (c<0) return ""; + if (c=='=') break; + if (readcache==null) readcache = new byte[64]; // to ensure proper detection of out-of-memory error, this number must be 2^n for some n>=0 + while(n >= readcache.length) { + byte[] readcache2 = new byte[readcache.length * 2]; + System.arraycopy(readcache, 0, readcache2, 0, readcache.length); + readcache = readcache2; + } + readcache[n] = (byte)c; + n++; + } + while(n>0 && readcache[n-1]>0 && readcache[n-1]<=' ') n--; // skip trailing spaces + int i = 0; + while(i0 && readcache[i]<=' ') i++; // skip leading space + return new String(readcache, i, n-i, "UTF-8"); + } + + /** Construct a new simulation context by reading the given file. */ + public static synchronized SimInstance read(Module root, String filename, List vars) throws Err, IOException { + FileInputStream fis = null; + BufferedInputStream bis = null; + try { + fis = new FileInputStream(filename); + bis = new BufferedInputStream(fis); + // read maxseq + if (!readkey(bis).equals("maxseq")) throw new IOException("Expecting maxseq = ..."); + int maxseq = readNonNegativeIntThenLinebreak(bis); + // read bitwidth + if (!readkey(bis).equals("bitwidth")) throw new IOException("Expecting bitwidth = ..."); + int bitwidth = readNonNegativeIntThenLinebreak(bis); + // construct the SimInstance object with no atoms and no relations + SimInstance ans = new SimInstance(root, bitwidth, maxseq); + // parse all the relations + Map sfs = new HashMap(); + while(true) { + String key = readkey(bis); + if (key.length() == 0) break; // we don't expect any more data after this + sfs.put(key, SimTupleset.read(bis)); + } + // now for each user-supplied sig, if we saw its value earlier, then assign its value in the new SimInstance's sfs map + for(final Sig s: root.getAllReachableSigs()) if (!s.builtin) { + SimTupleset ts = sfs.get("sig " + s.label); + if (ts!=null) ans.sfs.put(s, ts); + for(final Field f: s.getFields()) if (!f.defined) { + ts = sfs.get("field " + s.label + " " + f.label); + if (ts!=null) ans.sfs.put(f, ts); + } + } + // now for each user-supplied var, if we saw its value earlier, then assign its value in the new SimInstance's sfs map + if (vars!=null) for(ExprVar v: vars) { + SimTupleset ts = sfs.get("var " + v.label); + if (ts!=null) ans.sfs.put(v, ts); + } + // close the files then return the answer + bis.close(); + bis = null; + fis.close(); + fis = null; + return ans; + } finally { + // free the temporary array + readcache = null; + // if an exception occurred, we'll try to close to files anyway, since open file descriptors is a scarce resource + Util.close(bis); + Util.close(fis); + } + } + + /** Construct a new simulation context with the given bitwidth and the given maximum sequence length. */ + public SimInstance(Module root, int bitwidth, int maxseq) throws Err { + if (bitwidth<0 || bitwidth>32) throw new ErrorType("Bitwidth must be between 0 and 32."); + this.root = root; + this.bitwidth = bitwidth; + this.maxseq = maxseq; + this.callbacks = new HashMap(); + if (bitwidth==32) { max=Integer.MAX_VALUE; min=Integer.MIN_VALUE; } else { max=Util.max(bitwidth); min=(0-max)-1; } + if (maxseq < 0) throw new ErrorSyntax("The maximum sequence length cannot be negative."); + if (maxseq > 0 && maxseq > max) throw new ErrorSyntax("With integer bitwidth of "+bitwidth+", you cannot have sequence length longer than "+max); + shiftmask = Util.shiftmask(bitwidth); + } + + /** Construct a deep copy of this instance (except that it shares the same root Module object as the old instance) */ + public SimInstance(SimInstance old) throws Err { + root = old.root; + bitwidth = old.bitwidth; + maxseq = old.maxseq; + min = old.min; + max = old.max; + shiftmask = old.shiftmask; + env = old.env.dup(); + cacheUNIV = old.cacheUNIV; + cacheSTRING = old.cacheSTRING; + callbacks = new HashMap(old.callbacks); + for(Map.Entry e: old.sfs.entrySet()) sfs.put(e.getKey(), e.getValue()); + } + + /** Register a callback. */ + public void addCallback(Func predicateOrFunction, SimCallback callback) { + callbacks.put(predicateOrFunction, callback); + } + + /** Returns true if the given atom is an Int atom, or String atom, or is in at least one of the sig. */ + public boolean hasAtom(SimAtom atom) { + if (atom.toString().length()>0) { + char c = atom.toString().charAt(0); + if (c=='-' || (c>='0' && c<='9') || c=='\"') return true; + } + for(Map.Entry e: sfs.entrySet()) { + if (e.getKey() instanceof PrimSig && ((PrimSig)(e.getKey())).isTopLevel() && e.getValue().has(atom)) return true; + } + return false; + } + + /** Create a fresh atom for the given sig, then return the newly created atom. + * @throws ErrorAPI if attempting to add an atom to an abstract sig with children, or a builtin sig, or a subset sig. + */ + public SimAtom makeAtom(Sig sig) throws Err { + if (sig.builtin) throw new ErrorAPI("Cannot add an atom to a builtin sig."); + if (!(sig instanceof PrimSig)) throw new ErrorAPI("Cannot add an atom to a subset sig."); + PrimSig s = (PrimSig)sig; + if (s.isAbstract!=null && !s.children().isEmpty()) throw new ErrorAPI("Cannot add an atom to an abstract parent sig."); + String label = sig.label + "$"; + if (label.startsWith("this/")) label=label.substring(5); + for(int i=0; ;i++) { + SimAtom atom = SimAtom.make(label + i); + if (hasAtom(atom)) continue; + SimTupleset add = SimTupleset.make(SimTuple.make(atom)); + if (cacheUNIV!=null) cacheUNIV = cacheUNIV.union(add); + for(; s!=null; s=s.parent) if (!s.builtin) { + SimTupleset old = sfs.get(s); + if (old==null || old.empty()) sfs.put(s, add); else if (!add.in(old)) sfs.put(s, old.union(add)); else break; + } + return atom; + } + } + + /** Delete an atom from all sigs/fields/skolem... + *

The resulting instance may or may not satisfy all facts, and should be checked for consistency. + *

Returns true if at least one sig/field/var changed its value as a result of this deletion. + * @throws ErrorAPI if attempting to delete from "Int". + */ + public boolean deleteAtom(SimAtom atom) throws Err { + if (atom.toString().length()>0) { + char c = atom.toString().charAt(0); + if (c=='-' || (c>='0' && c<='9') || c=='\"') return false; + } + boolean changed = false; + for(Map.Entry x: sfs.entrySet()) { + SimTupleset oldvalue = x.getValue(); + SimTupleset newvalue = oldvalue.removeAll(atom); + if (oldvalue.longsize() != newvalue.longsize()) { changed=true; x.setValue(newvalue); } + } + if (changed) { cacheUNIV=null; return true; } else { return false; } + } + + /** Initializes the given sig to be associated with the given unary value; should only be called at the beginning. + *

The resulting instance may or may not satisfy all facts, and should be checked for consistency. + */ + public void init(Sig sig, SimTupleset value) throws Err { + if (value==null) { sfs.remove(sig); return; } + if (value.arity()>1) throw new ErrorType("Evaluator encountered an error: sig "+sig.label+" arity must not be " + value.arity()); + if (sig.builtin) throw new ErrorAPI("Evaluator cannot prebind the builtin sig \"" + sig.label + "\""); + sfs.put(sig, value); + cacheUNIV = null; + cacheSTRING = null; + cacheForConstants.clear(); + } + + /** Initializes the given field to be associated with the given unary value; should only be called at the beginning. + *

The resulting instance may or may not satisfy all facts, and should be checked for consistency. + */ + public void init(Field field, SimTupleset value) throws Err { + if (value==null) { sfs.remove(field); return; } + if (!value.empty() && value.arity()!=field.type().arity()) throw new ErrorType("Evaluator encountered an error: field "+field.label+" arity must not be " + value.arity()); + if (field.defined) throw new ErrorAPI("Evaluator cannot prebind the value of a defined field."); + sfs.put(field, value); + cacheUNIV = null; + cacheSTRING = null; + cacheForConstants.clear(); + } + + /** Initializes the given var to be associated with the given unary value; should only be called at the beginning. + *

The resulting instance may or may not satisfy all facts, and should be checked for consistency. + */ + public void init(ExprVar var, SimTupleset value) throws Err { + if (value==null) { sfs.remove(var); return; } + if (!value.empty() && value.arity()!=var.type().arity()) throw new ErrorType("Evaluator encountered an error: skolem "+var.label+" arity must not be " + value.arity()); + sfs.put(var, value); + cacheUNIV = null; + cacheSTRING = null; + cacheForConstants.clear(); + } + + /** Truncate the given integer based on the current chosen bitwidth (as string) plus + * a flag to indicate overflow */ + private int trunc(int i) { + int ret = (i<<(32-bitwidth)) >> (32-bitwidth); + wasOverflow = ret != i; + return ret; + } + + /** Convenience method that evalutes x and casts the result to be a boolean. + * @return the boolean - if x evaluates to a boolean + * @throws ErrorFatal - if x does not evaluate to a boolean + */ + public boolean cform(Expr x) throws Err { + if (!x.errors.isEmpty()) throw x.errors.pick(); + Object y = visitThis(x); + if (y instanceof Boolean) return Boolean.TRUE.equals(y); + throw new ErrorFatal(x.span(), "This should have been a formula.\nInstead it is "+y); + } + + /** Convenience method that evalutes x and cast the result to be a int. + * @return the int - if x evaluates to an int + * @throws ErrorFatal - if x does not evaluate to an int + */ + public int cint(Expr x) throws Err { + if (!x.errors.isEmpty()) throw x.errors.pick(); + Object y = visitThis(x); + if (y instanceof Integer) return (Integer)y; + if (y instanceof SimTupleset) return ((SimTupleset) y).sum(); + throw new ErrorFatal(x.span(), "This should have been an integer expression.\nInstead it is "+y); + } + + /** Convenience method that evalutes x and cast the result to be a tupleset + * @return the tupleset - if x evaluates to a tupleset + * @throws ErrorFatal - if x does not evaluate to a tupleset + */ + public SimTupleset cset(Expr x) throws Err { + if (!x.errors.isEmpty()) throw x.errors.pick(); + Object y = visitThis(x); + if (y instanceof SimTupleset) return (SimTupleset)y; + if (y instanceof Integer) return SimTupleset.make(SimTuple.make(SimAtom.make(((Integer) y).intValue()))); + throw new ErrorFatal(x.span(), "This should have been a set or a relation.\nInstead it is "+y); + } + + /** {@inheritDoc} */ + @Override public Object visit(ExprBinary x) throws Err { + Expr a=x.left, b=x.right; + switch(x.op) { + case ARROW: case ANY_ARROW_LONE: case ANY_ARROW_ONE: case ANY_ARROW_SOME: + case LONE_ARROW_ANY: case LONE_ARROW_LONE: case LONE_ARROW_ONE: case LONE_ARROW_SOME: + case ONE_ARROW_ANY: case ONE_ARROW_LONE: case ONE_ARROW_ONE: case ONE_ARROW_SOME: + case SOME_ARROW_ANY: case SOME_ARROW_LONE: case SOME_ARROW_ONE: case SOME_ARROW_SOME: + case ISSEQ_ARROW_LONE: + return cset(x.left).product(cset(x.right)); + case JOIN: + if (x.left.isSame(Sig.UNIV)) { + SimTupleset tp = cset(x.right); + return tp.tail(tp.arity()-1); + } + if (x.right.isSame(Sig.UNIV)) { + SimTupleset tp = cset(x.left); + return tp.head(tp.arity()-1); + } + return cset(x.left).join(cset(x.right)); + case IMPLIES: return !cform(x.left) || cform(x.right); + case AND: return cform(x.left) && cform(x.right); + case OR: return cform(x.left) || cform(x.right); + case IFF: return cform(x.left) == cform(x.right); + case SHA: return trunc(cint(x.left) >> (shiftmask & cint(x.right))); + case SHR: return trunc(cint(x.left) >>> (shiftmask & cint(x.right))); + case SHL: return trunc(cint(x.left) << (shiftmask & cint(x.right))); + case INTERSECT: return cset(x.left).intersect(cset(x.right)); + case GT: return cint(x.left) > cint(x.right); + case GTE: return cint(x.left) >= cint(x.right); + case LT: return cint(x.left) < cint(x.right); + case LTE: return cint(x.left) <= cint(x.right); + case NOT_GT: return !(cint(x.left) > cint(x.right)); + case NOT_GTE: return !(cint(x.left) >= cint(x.right)); + case NOT_LT: return !(cint(x.left) < cint(x.right)); + case NOT_LTE: return !(cint(x.left) <= cint(x.right)); + case DOMAIN: return cset(x.left).domain(cset(x.right)); + case RANGE: return cset(x.left).range(cset(x.right)); + case EQUALS: return equal(x.left, x.right); + case NOT_EQUALS: return !equal(x.left, x.right); + case IN: return isIn(x.left, x.right); + case NOT_IN: return !isIn(x.left, x.right); + case MINUS: + // Special exception to allow "0-8" to not throw an exception, where 7 is the maximum allowed integer (when bitwidth==4) + // (likewise, when bitwidth==5, then +15 is the maximum allowed integer, and we want to allow 0-16 without throwing an exception) + if (a instanceof ExprConstant && ((ExprConstant)a).op==ExprConstant.Op.NUMBER && ((ExprConstant)a).num()==0) + if (b instanceof ExprConstant && ((ExprConstant)b).op==ExprConstant.Op.NUMBER && ((ExprConstant)b).num()==max+1) + return min; + //[AM] +// if (x.left.type().is_int()) return trunc(cint(x.left)-cint(x.right)); else return cset(x.left).difference(cset(x.right)); + return cset(x.left).difference(cset(x.right)); + case IMINUS: + return trunc(cint(x.left)-cint(x.right)); + case PLUS: + return cset(x.left).union(cset(x.right)); + //[AM] +// if (x.left.type().is_int()) return trunc(cint(x.left)+cint(x.right)); else return cset(x.left).union(cset(x.right)); + case IPLUS: + return trunc(cint(x.left)+cint(x.right)); + case PLUSPLUS: + return cset(x.left).override(cset(x.right)); + case MUL: + return trunc(cint(x.left) * cint(x.right)); + case DIV: + { int p=cint(x.left), q=cint(x.right), r=(p==0 ? 0 : (q==0 ? (p<0 ? 1 : -1) : (p/q))); return trunc(r); } + case REM: + { int p=cint(x.left), q=cint(x.right), r=(p==0 ? 0 : (q==0 ? (p<0 ? 1 : -1) : (p/q))); return trunc(p-r*q); } + } + throw new ErrorFatal(x.pos, "Unsupported operator ("+x.op+") encountered during ExprBinary.accept()"); + } + + /** {@inheritDoc} */ + @Override public Object visit(ExprList x) throws Err { + if (x.op==ExprList.Op.AND) { + for(Expr e:x.args) if (!cform(e)) return false; + return true; + } + if (x.op==ExprList.Op.OR) { + for(Expr e:x.args) if (cform(e)) return true; + return false; + } + if (x.op==ExprList.Op.TOTALORDER) { + SimTupleset elem = cset(x.args.get(0)), first = cset(x.args.get(1)), next = cset(x.args.get(2)); + return next.totalOrder(elem, first); + } + SimTupleset[] ans = new SimTupleset[x.args.size()]; + for(int i=1; i newenv = new Env(); + List list = new ArrayList(x.args.size()); + for(int i=0; i oldenv = env; + env = newenv; + current_function.add(f); + Object ans = visitThis(body); + env = oldenv; + current_function.remove(current_function.size()-1); + if (f.count()==0) cacheForConstants.put(f, ans); + return ans; + } + + /** {@inheritDoc} */ + @Override public Object visit(ExprConstant x) throws Err { + switch(x.op) { + case NUMBER: + int n = x.num(); + //[am] const +// if (nmax) throw new ErrorType(x.pos, "Current bitwidth is set to "+bitwidth+", thus this integer constant "+n+" is bigger than the maximum integer "+max); + return n; + case FALSE: return Boolean.FALSE; + case TRUE: return Boolean.TRUE; + case MIN: return min; + case MAX: return max; + case EMPTYNESS: return SimTupleset.EMPTY; + case STRING: return SimTupleset.make(x.string); + case NEXT: return SimTupleset.makenext(min, max); + case IDEN: return cset(Sig.UNIV).iden(); + } + throw new ErrorFatal(x.pos, "Unsupported operator ("+x.op+") encountered during ExprConstant.accept()"); + } + + /** {@inheritDoc} */ + @Override public Object visit(ExprITE x) throws Err { + if (cform(x.cond)) return visitThis(x.left); else return visitThis(x.right); + } + + /** {@inheritDoc} */ + @Override public Object visit(ExprLet x) throws Err { + env.put(x.var, visitThis(x.expr)); + Object ans = visitThis(x.sub); + env.remove(x.var); + return ans; + } + + /** {@inheritDoc} */ + @Override public Object visit(ExprUnary x) throws Err { + switch(x.op) { + case EXACTLYOF: + case LONEOF: + case ONEOF: + case SETOF: + case SOMEOF: return cset(x.sub); + case NOOP: return visitThis(x.sub); + case CARDINALITY: return trunc(cset(x.sub).size()); + case NO: return cset(x.sub).empty(); + case LONE: return cset(x.sub).longsize()<=1; + case ONE: return cset(x.sub).longsize()==1; + case SOME: return cset(x.sub).longsize()>=1; + case NOT: return cform(x.sub) ? Boolean.FALSE : Boolean.TRUE; + case CAST2SIGINT: return SimTupleset.make(SimTuple.make(SimAtom.make(cint(x.sub)))); + case CAST2INT: return trunc(cset(x.sub).sum()); + case CLOSURE: return cset(x.sub).closure(); + case RCLOSURE: return cset(x.sub).closure().union(cset(ExprConstant.IDEN)); + case TRANSPOSE: return cset(x.sub).transpose(); + } + throw new ErrorFatal(x.pos, "Unsupported operator ("+x.op+") encountered during ExprUnary.accept()"); + } + + /** {@inheritDoc} */ + @Override public Object visit(ExprVar x) throws Err { + Object ans = env.get(x); + if (ans==null) ans = sfs.get(x); + if (ans==null) { + SimAtom a = SimAtom.make(x.label); + if (!hasAtom(a)) throw new ErrorFatal(x.pos, "Variable \""+x+"\" is not bound to a legal value during translation.\n"); + ans = SimTupleset.make(SimTuple.make(a)); + } + return ans; + } + + /** {@inheritDoc} */ + @Override public SimTupleset visit(Sig x) throws Err { + if (x.isSame(Sig.NONE)) return SimTupleset.EMPTY; + if (x.isSame(Sig.SEQIDX)) return SimTupleset.make(0, maxseq-1); + if (x.isSame(Sig.SIGINT)) return SimTupleset.make(min, max); + if (x.isSame(Sig.STRING)) { + if (cacheSTRING == null) { + cacheSTRING = SimTupleset.EMPTY; + for(Map.Entry e: sfs.entrySet()) if (e.getKey() instanceof Field || e.getKey() instanceof ExprVar) { + for(SimTuple t: e.getValue()) for(int i=t.arity()-1; i>=0; i--) { + String a = t.get(i).toString(); + if (a.length()>0 && a.charAt(0)=='"') cacheSTRING = cacheSTRING.union(SimTuple.make(t.get(i))); + } + } + } + return cacheSTRING; + } + if (x==Sig.UNIV) { + if (cacheUNIV == null) { + cacheUNIV = SimTupleset.make(min, max); + for(Map.Entry e: sfs.entrySet()) + if (e.getKey() instanceof PrimSig && ((PrimSig)(e.getKey())).isTopLevel()) + cacheUNIV = cacheUNIV.union(e.getValue()); + cacheUNIV = cacheUNIV.union(visit(Sig.STRING)); + } + return cacheUNIV; + } + Object ans = sfs.get(x); + if (ans instanceof SimTupleset) return (SimTupleset)ans; else throw new ErrorFatal("Unknown sig "+x+" encountered during evaluation."); + } + + /** {@inheritDoc} */ + @Override public SimTupleset visit(Field x) throws Err { + if (x.defined) { + final ExprVar v = (ExprVar)(x.sig.decl.get()); + final Expr b = x.decl().expr; + final Env oldenv = env; + env = new Env(); + if (!b.hasVar(v)) { SimTupleset ans=cset(x.sig).product(cset(b)); env=oldenv; return ans; } + SimTupleset ans = SimTupleset.EMPTY; + for(SimTuple a: visit(x.sig)) { + SimTupleset left = SimTupleset.make(a); + env.put(v, left); + SimTupleset right = cset(b); + env.remove(v); + ans = left.product(right).union(ans); + } + env = oldenv; + return ans; + } + Object ans = sfs.get(x); + if (ans instanceof SimTupleset) return (SimTupleset)ans; else throw new ErrorFatal("Unknown field "+x+" encountered during evaluation."); + } + + /** Helper method for enumerating all possibilties for a quantification-expression. */ + private int enumerate(final TempList store, int sum, final ExprQt x, final Expr body, final int i) throws Err { // if op is ALL NO SOME ONE LONE then it always returns 0 1 2 + final int n = x.count(); + final ExprVar v = x.get(i); + final Expr bound = x.getBound(i); + final SimTupleset e = cset(bound); + final Iterator it; + switch(bound.mult()) { + case LONEOF: it = e.loneOf(); break; + case ONEOF: it = e.oneOf(); break; + case SOMEOF: it = e.someOf(); break; + default: it = e.setOf(); + } + while(it.hasNext()) { + final SimTupleset binding = it.next(); + if (bound.mult==2 && !isIn(binding, bound)) continue; + env.put(v, binding); + if (i=2 && x.op!=ExprQt.Op.COMPREHENSION && x.op!=ExprQt.Op.SUM) return 2; // no need to enumerate further + } + return sum; + } + + /** {@inheritDoc} */ + @Override public Object visit(ExprQt x) throws Err { + Expr xx = x.desugar(); + if (xx instanceof ExprQt) x = (ExprQt)xx; else return visitThis(xx); + if (x.op == ExprQt.Op.COMPREHENSION) { + TempList ans = new TempList(); + enumerate(ans, 0, x, x.sub, 0); + return SimTupleset.make(ans.makeConst()); + } + if (x.op == ExprQt.Op.ALL) return enumerate(null, 0, x, x.sub.not(), 0) == 0; + if (x.op == ExprQt.Op.NO) return enumerate(null, 0, x, x.sub, 0) == 0; + if (x.op == ExprQt.Op.SOME) return enumerate(null, 0, x, x.sub, 0) >= 1; + if (x.op == ExprQt.Op.LONE) return enumerate(null, 0, x, x.sub, 0) <= 1; + if (x.op == ExprQt.Op.ONE) return enumerate(null, 0, x, x.sub, 0) == 1; + if (x.op == ExprQt.Op.SUM) return trunc(enumerate(null, 0, x, x.sub, 0)); + throw new ErrorFatal(x.pos, "Unsupported operator ("+x.op+") encountered during ExprQt.accept()"); + } + + /** Helper method that evaluates the formula "a in b" where b.mult==0 */ + public boolean isIn(SimTuple a, Expr b) throws Err { + b = b.deNOP(); + if (b instanceof PrimSig && ((PrimSig)b).builtin) { + if (a.arity()!=1) return false; + if (b.isSame(Sig.UNIV)) return true; + if (b.isSame(Sig.NONE)) return false; + if (b.isSame(Sig.SEQIDX)) { Integer i = a.get(0).toInt(null); return i!=null && i>=0 && i0 && (at.charAt(0)=='\"'); } + } + if (b instanceof ExprBinary && ((ExprBinary)b).op==ExprBinary.Op.ARROW) { + Expr left = ((ExprBinary)b).left, right = ((ExprBinary)b).right; + int ll = left.type().arity(), rr = right.type().arity(); + if (ll <= rr) return isIn(a.head(ll), left) && isIn(a.tail(rr), right); + return isIn(a.tail(rr), right) && isIn(a.head(ll), left); + } + if (b instanceof ExprBinary && ((ExprBinary)b).op==ExprBinary.Op.PLUS) { + return isIn(a, ((ExprBinary)b).left) || isIn(a, ((ExprBinary)b).right); + } + if (b instanceof ExprBinary && ((ExprBinary)b).op==ExprBinary.Op.MINUS) { + return isIn(a, ((ExprBinary)b).left) && !isIn(a, ((ExprBinary)b).right); + } + return cset(b).has(a); + } + + /** Helper method that evaluates the formula "a = b" */ + public boolean equal(Expr a, Expr b) throws Err { + if (a.type().is_bool) return cform(a)==cform(b); + //[AM] if (a.type().is_int()) return cint(a)==cint(b); + if (a.type().arity()<=0 || a.type().arity()!=b.type().arity()) return false; // type mismatch + if (a.isSame(b)) return true; else return cset(a).equals(cset(b)); + } + + /** Helper method that evaluates the formula "a in b" */ + public boolean isIn(Expr a, Expr b) throws Err { + if (a.type().arity()<=0 || a.type().arity()!=b.type().arity()) return false; // type mismatch + if (b.isSame(Sig.UNIV)) return true; // everything is a subset of UNIV + if (a.isSame(b)) return true; // if a==b then a is a subset of b + return isIn(cset(a), b); + } + + /** Helper method that evaluates the formula "a in b" */ + private boolean isIn(SimTupleset a, Expr b) throws Err { + b = b.deNOP(); + if (b instanceof ExprBinary && b.mult!=0 && ((ExprBinary)b).op.isArrow) { + // Handles possible "binary" or higher-arity multiplicity + return isInBinary(a, (ExprBinary)b); + } + if (b instanceof ExprUnary) { + // Handles possible "unary" multiplicity + ExprUnary y = (ExprUnary)b; + if (y.op==ExprUnary.Op.EXACTLYOF) { b = y.sub.deNOP(); return a.equals(cset(b)); } + else if (y.op==ExprUnary.Op.ONEOF) { b = y.sub.deNOP(); if (!(a.longsize()==1)) return false; } + else if (y.op==ExprUnary.Op.LONEOF) { b = y.sub.deNOP(); if (!(a.longsize()<=1)) return false; } + else if (y.op==ExprUnary.Op.SOMEOF) { b = y.sub.deNOP(); if (!(a.longsize()>=1)) return false; } + else if (y.op!=ExprUnary.Op.SETOF) { b = y.sub.deNOP(); } + } + for(SimTuple t:a) if (!isIn(t, b)) return false; + return true; + } + + /** Helper method that evaluates the formula "r in (a ?->? b)" */ + private boolean isInBinary(SimTupleset R, ExprBinary ab) throws Err { + // Special check for ISSEQ_ARROW_LONE + if (ab.op == ExprBinary.Op.ISSEQ_ARROW_LONE) { + List list = R.getAllAtoms(0); + int next = 0; + SimAtom nextStr = SimAtom.make("0"); + while (list.size() > 0) { + for (int n=list.size(), i=0; ; i++) if (i>=n) return false; else if (nextStr==list.get(i)) { list.set(i, list.get(n-1)); list.remove(n-1); next++; break; } + if (list.size()==0) break; + if (next<0 || next>=maxseq) return false; // list.size()>0 and yet we've exhausted 0..maxseq-1, so indeed there are illegal atoms + nextStr = SimAtom.make(next); + } + } + // "R in A ->op B" means for each tuple a in A, there are "op" tuples in r that begins with a. + for(SimTuple left: cset(ab.left)) { + SimTupleset ans = R.beginWith(left); + switch(ab.op) { + case ISSEQ_ARROW_LONE: + case ANY_ARROW_LONE: case SOME_ARROW_LONE: case ONE_ARROW_LONE: case LONE_ARROW_LONE: if (!(ans.longsize()<=1)) return false; else break; + case ANY_ARROW_ONE: case SOME_ARROW_ONE: case ONE_ARROW_ONE: case LONE_ARROW_ONE: if (!(ans.longsize()==1)) return false; else break; + case ANY_ARROW_SOME: case SOME_ARROW_SOME: case ONE_ARROW_SOME: case LONE_ARROW_SOME: if (!(ans.longsize()>=1)) return false; else break; + } + if (!isIn(ans, ab.right)) return false; + } + // "R in A op-> B" means for each tuple b in B, there are "op" tuples in r that end with b. + for(SimTuple right: cset(ab.right)) { + SimTupleset ans = R.endWith(right); + switch(ab.op) { + case LONE_ARROW_ANY: case LONE_ARROW_SOME: case LONE_ARROW_ONE: case LONE_ARROW_LONE: if (!(ans.longsize()<=1)) return false; else break; + case ONE_ARROW_ANY: case ONE_ARROW_SOME: case ONE_ARROW_ONE: case ONE_ARROW_LONE: if (!(ans.longsize()==1)) return false; else break; + case SOME_ARROW_ANY: case SOME_ARROW_SOME: case SOME_ARROW_ONE: case SOME_ARROW_LONE: if (!(ans.longsize()>=1)) return false; else break; + } + if (!isIn(ans, ab.left)) return false; + } + return true; + } + + /** Checks whether this instance satisfies every fact defined in the given model. + * @param world - this must be the root of the Alloy model + * @return an empty String if yes, nonempty String if no + */ + public String validate(Module world) { + try { + for(Sig s: world.getAllReachableSigs()) if (!s.builtin) { + if (s.isLone!=null && !(visit(s).longsize()<=1)) return "There can be at most one "+s; + if (s.isOne !=null && !(visit(s).longsize()==1)) return "There must be exactly one "+s; + if (s.isSome!=null && !(visit(s).longsize()>=1)) return "There must be at least one "+s; + if (s instanceof SubsetSig) { + SubsetSig p = (SubsetSig)s; + Expr sum = null; + for(Sig par: p.parents) sum = par.plus(sum); + if (p.exact) { + if (!equal(s, sum)) return "Sig "+s+" must be equal to the union of its parents "+p.parents; + } else { + if (!isIn(s, sum)) return "Sig "+s+" must be equal or subset of its parents "+p.parents; + } + } else if (s != Sig.UNIV && s != Sig.NONE) { + PrimSig p = (PrimSig)s; + if (!isIn(s, p.parent)) return "Sig "+s+" must be equal or subset of its parent "+p.parent; + } + if (s.isAbstract!=null) { + Expr sum = null; + for(Sig x: ((PrimSig)s).children()) sum = x.plus(sum); + if (sum!=null && !equal(s, sum)) return "Abstract sig "+s+" must be equal to the union of its subsigs"; + } + for(Decl d: s.getFieldDecls()) for(ExprHasName f: d.names) if (!((Field)f).defined) { + if (!cform(s.decl.get().join(f).in(d.expr).forAll(s.decl))) { + return "Field "+f+" violated its bound: " + visit((Field)f) + "\n" + d.expr; + } + SimTupleset setS = visit(s); + SimTupleset setF = visit((Field)f); + for(SimAtom x:setF.getAllAtoms(0)) if (!setS.has(x)) return "Field "+f+" first column has extra atom: "+setF+" not in "+setS; + } + for(Decl d: s.getFieldDecls()) { + if (d.disjoint!=null && d.names.size()>0) { + if (!cform(ExprList.makeDISJOINT(null, null, d.names))) return "Fields must be disjoint."; + } + if (d.disjoint2!=null) for(ExprHasName f: d.names) { + Decl that = s.oneOf("that"); + Expr formula = s.decl.get().equal(that.get()).not().implies(s.decl.get().join(f).intersect(that.get().join(f)).no()); + if (!cform(formula.forAll(that).forAll(s.decl))) return "Fields must be disjoint."; + } + } + for(Expr f: s.getFacts()) { + if (!cform(f.forAll(s.decl))) { + f = f.deNOP(); if (f instanceof ExprUnary) { + ExprUnary u = (ExprUnary)f; + f = u.sub.deNOP(); + if (f instanceof ExprBinary) { + ExprBinary b = (ExprBinary)f; + if (b.op == ExprBinary.Op.JOIN && b.left.isSame(s.decl.get()) && b.right.deNOP() instanceof Field) { + String n = ((Field)(b.right.deNOP())).label; + if (u.op == ExprUnary.Op.SOME) return "The "+n+" cannot be empty."; + if (u.op == ExprUnary.Op.LONE) return "The "+n+" cannot have more than one value."; + if (u.op == ExprUnary.Op.ONE) return "The "+n+" must have exactly one value."; + if (u.op == ExprUnary.Op.NO) return "The "+n+" must be empty."; + } + } + } + return "Cannot violate a consistency constraint"; + } + } + } + for(Module m: world.getAllReachableModules()) for(Pair f: m.getAllFacts()) if (!cform(f.b)) { + String err = f.a; + if (err.matches("^fact\\$[0-9][0-9]*")) err = f.b.toString(); + if (err.length()>=2 && err.startsWith("\"") && err.endsWith("\"")) err = err.substring(1, err.length()-1); + return "Violation: " + err; + } + return ""; + } catch(Err ex) { + return "An internal error has occured:\n" + ex.dump(); + } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/sim/SimTuple.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/sim/SimTuple.java new file mode 100644 index 00000000..5e071096 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/sim/SimTuple.java @@ -0,0 +1,242 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.sim; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; + +/** Immutable; represents a tuple. + * + *

Thread Safety: Safe. + */ + +public final class SimTuple implements Iterable { + + /** Stores the tuple. */ + private SimAtom[] array; + + /** If nonzero, it caches the hash code. */ + private int hashCode = 0; + + /** Construct a tuple backed by the given array as-is; thus the caller must not modify it any more. */ + private SimTuple(SimAtom[] array) { + if (array.length==0) throw new IllegalArgumentException(); + this.array=array; + } + + /** Construct the n-ary tuple; throws an exception if the given list is empty. */ + public static SimTuple make(List list) { + if (list.size()==0) throw new IllegalArgumentException(); + SimAtom[] array = new SimAtom[list.size()]; + for(int i=0, n=list.size(); i0) out.write(' '); + array[i].write(out); + } + out.write(')'); + } + + /** Read a (".." ".." "..") tuple assuming the leading "(" has already been consumed. */ + static SimTuple read(BufferedInputStream in) throws IOException { + List list = new ArrayList(); + while(true) { + int c = in.read(); + if (c<0) throw new IOException("Unexpected EOF"); + if (c>0 && c<=' ') continue; // skip whitespace + if (c==')') break; + if (c!='\"') throw new IOException("Expecting start of atom"); + list.add(SimAtom.read(in)); + c = in.read(); + if (c<0) throw new IOException("Unexpected EOF"); + if (c==')') break; + if (!(c<=' ')) throw new IOException("Expecting \')\' or white space after an atom."); + } + if (list.size()==0) throw new IOException("Tuple arity cannot be 0."); + return make(list); + } + + /** Returns the arity of this tuple. */ + public int arity() { return array.length; } + + /** Return the i-th atom from this tuple. */ + public SimAtom get(int i) { return array[i]; } + + /** Returns true if this tuple contains at least one occurrence of the given atom. */ + public boolean has(SimAtom atom) { + for(int i=array.length-1; i>=0; i--) if (array[i]==atom) return true; + return false; + } + + /** Replace the i-th atom, and return the resulting SimTuple. */ + public SimTuple replace(int i, SimAtom newAtom) { + if (array[i] == newAtom) return this; + SimAtom ar[] = new SimAtom[array.length]; + for(int j=0; jSimAtom map; any atom not in the map will stay unchanged. */ + public SimTuple replace(Map map) { + SimAtom[] newarray = new SimAtom[array.length]; + for(int i=array.length-1; i>=0; i--) { + SimAtom oldX = array[i]; + SimAtom newX = map.get(oldX); + newarray[i] = (newX==null ? oldX : newX); + } + return new SimTuple(newarray); + } + + /** Prepend the given atom to the front of this tuple, then return the resulting new Tuple. */ + public SimTuple prepend(SimAtom atom) { + SimAtom[] newarray = new SimAtom[array.length+1]; + newarray[0] = atom; + for(int i=0; i=0; i--) ans = ans*31 + System.identityHashCode(array[i]); + if (ans==0) ans++; // so that we don't end up re-computing this SimTuple's hashcode over and over again + hashCode = ans; + } + return ans; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object that) { + if (this==that) return true; else if (!(that instanceof SimTuple)) return false; + SimAtom[] other = ((SimTuple)that).array; + if (array==other) return true; else if (array.length != other.length) return false; + if (hashCode() != that.hashCode()) return false; + for(int i=array.length-1; i>=0; i--) if (array[i]!=other[i]) return false; + array=other; + // Change it so we share the same array; this is thread safe since these array contents are never mutated, + // so it doesn't matter if some thread sees the old array and some sees the new array. + // JLS 3rd Edition 17.7 guarantees that writes and reads of references are atomic though not necessarily visible, + // so another thread will either see the old array or the new array. + return true; + } + + /** Returns the first atom of this tuple. */ + public SimAtom head() { return array[0]; } + + /** Returns the last atom of this tuple. */ + public SimAtom tail() { return array[array.length-1]; } + + /** Returns the subtuple containing the first n atoms (n must be between 1 and arity) */ + public SimTuple head(int n) { + if (n<=0 || n>array.length) throw new IllegalArgumentException(); else if (n==array.length) return this; + SimAtom newtuple[] = new SimAtom[n]; + for(int c=0; carray.length) throw new IllegalArgumentException(); else if (n==array.length) return this; + SimAtom newtuple[] = new SimAtom[n]; + for(int a=array.length-n, c=0; c0) sb.append("->"); + sb.append(array[i]); + } + } + + /** {@inheritDoc} */ + @Override public String toString() { + StringBuilder sb = new StringBuilder(); + toString(sb); + return sb.toString(); + } + + /** {@inheritDoc} */ + public Iterator iterator() { + return new Iterator() { + private int i = 0; // the next index to read out + public boolean hasNext() { return i < array.length; } + public SimAtom next() { if (i < array.length) {i++; return array[i-1];} else throw new NoSuchElementException(); } + public void remove() { throw new UnsupportedOperationException(); } + }; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/sim/SimTupleset.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/sim/SimTupleset.java new file mode 100644 index 00000000..6a792ab3 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/sim/SimTupleset.java @@ -0,0 +1,615 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.sim; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.NoSuchElementException; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.ErrorAPI; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.ConstList.TempList; + +/** Immutable; represents a tupleset. */ + +public final class SimTupleset implements Iterable { + + // if (min Invariant: If nonempty, it must contain only same-arity tuples. + *
Invariant: It must not contain duplicate tuples. + */ + private final ConstList tuples; + private final int min; + private final int max; + private final boolean next; + + /** Construct a tupleset with the given 4 values (Note: caller MUST make sure there are no duplicates, even between (min,max) and tuples, and that all tuples are of same arity!) */ + private SimTupleset(Collection tuples, int min, int max, boolean next) { + this.tuples = ConstList.make(tuples); + this.min = min; + this.max = max; + this.next = next; + } + + /** Construct a tupleset containing the given list of tuples (Note: caller MUST make sure there are no duplicates, and all tuples are of same arity!) */ + private SimTupleset(Collection tuples) { + this.tuples = ConstList.make(tuples); + this.min = 0; + this.max = 0; + this.next = false; + } + + /** The tupleset containing no tuples. */ + public static final SimTupleset EMPTY = new SimTupleset(new TempList(0).makeConst()); + + /** Construct the set containing integers between min and max (inclusively). */ + public static SimTupleset make(int min, int max) { + if (min>max) return EMPTY; + if (min==max) return new SimTupleset(Util.asList(SimTuple.make(SimAtom.make(min))), 0, 0, false); + return new SimTupleset(EMPTY.tuples, min, max, false); + } + + /** Construct the set containing (min,min+1)...(max-1,max) */ + public static SimTupleset makenext(int min, int max) { + return min>=max ? EMPTY : (new SimTupleset(EMPTY.tuples, min, max, true)); + } + + /** Construct a tupleset containing the given tuple. */ + public static SimTupleset make(SimTuple tuple) { + return new SimTupleset(Util.asList(tuple)); + } + + /** Make a tupleset containing the given atom. */ + public static SimTupleset make(String atom) { + return make(SimTuple.make(atom)); + } + + /** Make a tupleset containing a deep copy of the given list of tuples (Note: caller MUST make sure there are no duplicates, and all tuples are of same arity!) */ + public static SimTupleset make(Collection tuples) { + return tuples.size()==0 ? EMPTY : new SimTupleset(tuples); + } + + /** If this tupleset is empty, then return 0, else return the arity of every tuple in this tupleset. */ + public int arity() { + return min=max && tuples.size()==0; + } + + /** Returns the number of tuples in this tupleset (this answer may be truncated if it cannot fit in a 32-bit integer) */ + public int size() { + return (int)longsize(); + } + + /** Returns the number of tuples in this tupleset (this answer will never overflow) */ + public long longsize() { + long ans = (min=0; i--) if (tuples.get(i).get(0)==that) return true; + return false; + } + + /** Returns an arbitrary atom from an arbitrary tuple. + * @throws - ErrorAPI if this tupleset is empty + */ + public SimAtom getAtom() throws ErrorAPI { + if (tuples.size()>0) return tuples.get(0).get(0); + if (min>=max) throw new ErrorAPI("This tupleset is empty"); + return SimAtom.make(min); + } + + /** Returns an arbitrary tuple. + * @throws - ErrorAPI if this tupleset is empty + */ + public SimTuple getTuple() throws ErrorAPI { + if (tuples.size()>0) return tuples.get(0); + if (min>=max) throw new ErrorAPI("This tupleset is empty"); + SimAtom a = SimAtom.make(min); + if (next) return SimTuple.make(a, SimAtom.make(min+1)); else return SimTuple.make(a); + } + + /** Return the union of this and that; (if this tupleset and that tupleset does not have compatible arity, then we return this tupleset as is). + *
Note: the tuples in the result will be ordered as follows: + * first comes the tuples in "this" in original order, + * then the tuples that are in "that" but not in "this". + */ + public SimTupleset union(SimTupleset that) { + if (this.empty() || this==that) return that; + if (that.empty() || arity()!=that.arity()) return this; + TempList ans = null; // when null, it means we haven't found any new tuple to add yet + for(SimTuple x: that) if (!has(x)) { + if (ans == null) ans = new TempList(tuples); + ans.add(x); + } + return ans==null ? this : new SimTupleset(ans.makeConst(), min, max, next); + } + + /** Return the union of this and that; (if this tupleset and that tuple does not have compatible arity, then we return this tupleset as is). + *
Note: if this operation is a no-op, we guarantee we'll return this SimTupleset as is. + */ + public SimTupleset union(SimTuple that) { + if (empty()) return make(that); + if (arity()!=that.arity() || has(that)) return this; + TempList ans = new TempList(tuples.size()+1); + ans.addAll(tuples).add(that); + return new SimTupleset(ans.makeConst(), min, max, next); + } + + //================================================================================================================// + + /** Return the tupleset where each tuple is truncated to the first N atoms; if n is zero or negative, we return the emptyset; if n >= this.arity, we return this as is. */ + public SimTupleset head(int n) { + if (n<=0 || empty()) return EMPTY; else if (arity() <= n) return this; + if (min ans = new TempList(tuples.size()); + for(SimTuple x: tuples) { + Integer a = x.head().toInt(null); + if (a!=null && a>=min && a ans = new TempList(tuples.size()); + for(SimTuple x: this) { SimTuple y = x.head(n); if (!ans.contains(y)) ans.add(y); } + return new SimTupleset(ans.makeConst()); + } + + /** Return the tupleset where each tuple is truncated to the last N atoms; if n is zero or negative, we return the emptyset; if n >= this.arity, we return this as is. */ + public SimTupleset tail(int n) { + if (n<=0 || empty()) return EMPTY; else if (arity() <= n) return this; + if (min ans = new TempList(tuples.size()); + for(SimTuple x: tuples) { + Integer a = x.tail().toInt(null); + if (a!=null && a>min && a<=max) continue; + SimTuple y = SimTuple.make(x.tail()); + if (!ans.contains(y)) ans.add(y); + } + return new SimTupleset(ans.makeConst(), min+1, max, false); + } + TempList ans = new TempList(tuples.size()); + for(SimTuple x: this) { SimTuple y = x.tail(n); if (!ans.contains(y)) ans.add(y); } + return new SimTupleset(ans.makeConst()); + } + + /** Returns a read-only iterator over the tuples. */ + public Iterator iterator() { + return new Iterator() { + private long n = longsize(); + private long i = 0; + public SimTuple next() { if (i>=n) throw new NoSuchElementException(); else {i++; return get(i-1);} } + public boolean hasNext() { return i0 && c<=' ') continue; // skip whitespace + if (c=='{') break; else throw new IOException("Expecting start of tupleset"); + } + LinkedHashSet list = new LinkedHashSet(); + while(true) { + int c = in.read(); + if (c<0) throw new IOException("Unexpected EOF"); + if (c>0 && c<=' ') continue; // skip whitespace + if (c=='}') break; + if (c!='(') throw new IOException("Expecting start of tuple"); + list.add(SimTuple.read(in)); + c = in.read(); + if (c<0) throw new IOException("Unexpected EOF"); + if (c=='}') break; + if (!(c<=' ')) throw new IOException("Expecting \')\' or white space after a tuple."); + } + return make(list); + } + + /** Returns the index position if the list of tuples contains the tuple (a,b) (or return -1 if not found). */ + private static int find(TempList tuples, SimAtom a, SimAtom b) { + if (tuples.size() == 0 || tuples.get(0).arity() != 2) return -1; + for(int i=tuples.size()-1; i >= 0; i--) { + SimTuple x = tuples.get(i); + if (x.head()==a && x.tail()==b) return i; + } + return -1; + } + + /** {@inheritDoc} */ + @Override public String toString() { + StringBuilder sb = null; + for(SimTuple x: this) { + if (sb==null) sb = new StringBuilder("{"); else sb.append(", "); + x.toString(sb); + } + return sb==null ? "{}" : (sb.append("}").toString()); + } + + /** Returns a hashcode consistent with the equals() method. */ + @Override public int hashCode() { + int ans = 0; + for(SimTuple t: this) ans = ans + t.hashCode(); + return ans; + } + + /** Returns true if this contains the same tuples as that. */ + @Override public boolean equals(Object that) { + return this==that || (that instanceof SimTupleset && equals((SimTupleset)that)); + } + + /** Returns true if this contains the same tuples as that. */ + public boolean equals(SimTupleset that) { + // since SimTupleset must not contain duplicates, and this.size()==that.size(), comparing one way is sufficient + return this==that || (that!=null && longsize()==that.longsize() && in(that)); + } + + /** Returns true if this is a subset of that. */ + public boolean in(SimTupleset that) { + if (empty() || this==that) return true; + if (longsize()>that.longsize() || arity()!=that.arity()) return false; + for(SimTuple t: this) if (!that.has(t)) return false; + return true; + } + + /** Sum up all the integer atoms in this tupleset; (if this tupleset's arity is not 1, then we return 0) */ + public int sum() { + if (arity() != 1) return 0; + Integer zero = 0; + int ans = 0; + for(SimTuple t: this) ans = ans + t.get(0).toInt(zero); + return ans; + } + + /** Return the identity over this tupleset; (if this tupleset's arity is not 1, then we return an emptyset) + *
Note: the result's tuple order is the same as this tupleset's tuple order. + */ + public SimTupleset iden() { + if (arity() != 1) return EMPTY; + TempList ans = new TempList(size()); + for(SimTuple x: this) ans.add(SimTuple.make(x.head(), x.head())); // since "this" has no duplicate tuples, "ans" will not have duplicate tuples either + return new SimTupleset(ans.makeConst()); + } + + /** Return the relational override of this and that; (if this tupleset and that tuple does not have compatible arity, then we return this tupleset as is). + *
Note: in general, the tuples may be ordered arbitrarily in the result. + *
Note: if this operation is a no-op, we guarantee we'll return this SimTupleset as is. + */ + public SimTupleset override(final SimTuple that) { + if (arity()==1) return union(that); + if (empty()) return SimTupleset.make(that); + if (arity()!=that.arity()) return this; + boolean added = false, same = false; + TempList ans = new TempList(size()); + SimAtom head = that.get(0); + for(SimTuple x: this) { + if (x.get(0)!=head) { ans.add(x); continue; } + if (x.equals(that)) same = true; + if (!added) { ans.add(that); added=true; } + } + if (!added) ans.add(that); else if (same && longsize()==ans.size()) return this; + return new SimTupleset(ans.makeConst()); + } + + /** Return the relational override of this and that; (if this tupleset and that tupleset does not have compatible arity, then we return this tupleset as is). + *
Note: in general, the tuples may be ordered arbitrarily in the result. + */ + public SimTupleset override(SimTupleset that) throws ErrorAPI { + if (arity()==1) return union(that); + if (this.empty() || this==that) return that; + if (that.empty() || this.arity()!=that.arity()) return this; + if (that.longsize()==1) return override(that.getTuple()); // very common case, so let's optimize it + TempList ans = new TempList(size()); + for(SimTuple x: this) if (!that.has(x)) ans.add(x); + ans.addAll(that); + return new SimTupleset(ans.makeConst()); + } + + /** Return this minus that; (if this tupleset and that tupleset does not have compatible arity, then we return this tupleset as is). + *
Note: The resulting tuples will keep their original order. + */ + public SimTupleset difference(SimTupleset that) { + if (this.empty() || this==that) return EMPTY; + if (that.empty() || arity()!=that.arity()) return this; + TempList ans = new TempList(size()-1); + for(SimTuple x: this) if (!that.has(x)) ans.add(x); + return ans.size()==longsize() ? this : (ans.size()==0 ? EMPTY : new SimTupleset(ans.makeConst())); + } + + /** Return this minus that; (if this tupleset and that tuple does not have compatible arity, then we return this tupleset as is). + *
Note: The resulting tuples will keep their original order. + *
Note: if this operation is a no-op, we guarantee we'll return this SimTupleset as is. + */ + public SimTupleset difference(SimTuple that) { + if (empty() || arity()!=that.arity()) return this; + TempList ans = new TempList(size()-1); + for(SimTuple x: this) { + if (that==null || !x.equals(that)) ans.add(x); else that=null; + } + return that!=null ? this : (ans.size()==0 ? EMPTY : new SimTupleset(ans.makeConst())); + } + + /** Return this minus any tuple that contains the given atom. + *
Note: The resulting tuples will keep their original order. + */ + public SimTupleset removeAll(SimAtom that) { + if (empty()) return EMPTY; + TempList ans = new TempList(size()-1); + again: + for(SimTuple x: this) { + for(int i=x.arity()-1; i>=0; i--) if (x.get(i)==that) continue again; + ans.add(x); + } + return ans.size()==longsize() ? this : (ans.size()==0 ? EMPTY : new SimTupleset(ans.makeConst())); + } + + /** Return the transpose of this tupleset; (if this tupleset's arity is not 2, we'll return an empty set instead) */ + public SimTupleset transpose() { + if (empty() || arity()!=2) return EMPTY; + TempList ans = new TempList(size()); + for(SimTuple x: this) ans.add(SimTuple.make(x.tail(), x.head())); // since "this" has no duplicate tuples, "ans" will not have duplicate tuples either + return new SimTupleset(ans.makeConst()); + } + + /** Return the cartesian product of this and that. */ + public SimTupleset product(SimTupleset that) { + if (empty() || that.empty()) return EMPTY; + TempList ans = new TempList(size() * that.size()); + for(SimTuple a: this) for(SimTuple b: that) { + ans.add(a.product(b)); // We don't have to check for duplicates, because we assume every tuple in "this" has same arity, and every tuple in "that" has same arity + } + return new SimTupleset(ans.makeConst()); + } + + /** Return the relational join between this and that (throws ErrorType if this.arity==1 and that.arity==1) */ + public SimTupleset join(SimTupleset that) throws ErrorType { + if (empty() || that.empty()) return EMPTY; + if (arity()==1 && that.arity()==1) throw new ErrorType("Cannot join two unary relations."); + TempList ans = new TempList(); + for(SimTuple a: this) for(SimTuple b: that) if (a.tail()==b.head()) { + SimTuple c = a.join(b); + if (!ans.contains(c)) ans.add(c); + } + return ans.size()==0 ? EMPTY : new SimTupleset(ans.makeConst()); + } + + /** Return the intersection of this and that. */ + public SimTupleset intersect(SimTupleset that) { + if (this==that) return this; else if (empty() || that.empty()) return EMPTY; + TempList ans = new TempList(size() < that.size() ? size() : that.size()); + for(SimTuple x: that) if (has(x)) ans.add(x); + if (ans.size()==0) return EMPTY; + if (ans.size()==this.longsize()) return this; + if (ans.size()==that.longsize()) return that; else return new SimTupleset(ans.makeConst()); + } + + /** Return true if the intersection of this and that is nonempty. */ + public boolean intersects(SimTupleset that) { + if (empty()) return false; + if (this==that) return true; + for(SimTuple x: that) if (has(x)) return true; + return false; + } + + /** Returns this<:that (NOTE: if this.arity!=1, then we return the empty set) */ + public SimTupleset domain(SimTupleset that) { + if (arity()!=1 || that.empty()) return EMPTY; + TempList ans = new TempList(that.size()); + for(SimTuple x: that) if (has(x.head())) ans.add(x); + return ans.size()==that.longsize() ? that : (ans.size()==0 ? EMPTY : new SimTupleset(ans.makeConst())); + } + + /** Returns this:>that (NOTE: if that.arity!=1, then we return the empty set) */ + public SimTupleset range(SimTupleset that) { + if (that.arity()!=1 || this.empty()) return EMPTY; + TempList ans = new TempList(this.size()); + for(SimTuple x: this) if (that.has(x.head())) ans.add(x); + return ans.size()==this.longsize() ? this : (ans.size()==0 ? EMPTY : new SimTupleset(ans.makeConst())); + } + + /** Returns the closure of this tupleset (NOTE: if this.arity!=2, we will return an empty set) */ + public SimTupleset closure() { + if (arity()!=2) return EMPTY; + TempList ar = new TempList(size()); + ar.addAll(this); + while(true) { + int n = ar.size(); + for(int i=0; i ans = new TempList(); + again: + for(SimTuple r: this) { + for(int i=0; i ans = new TempList(); + again: + for(SimTuple r: this) { + for(int i=0; i getAllAtoms(int column) throws ErrorAPI { + if (empty()) return new ArrayList(0); + if (column<0 || column>=arity()) throw new ErrorAPI("This tupleset does not have an \""+column+"th\" column."); + IdentityHashMap ans = new IdentityHashMap(); + for(SimTuple x: this) ans.put(x.get(column), Boolean.TRUE); + return new ArrayList(ans.keySet()); + } + + /** Return true if this is a total ordering over "elem", with "first" being the first element of the total order. */ + public boolean totalOrder(SimTupleset elem, SimTupleset first) throws ErrorAPI { + if (elem.empty()) return false; + if (elem.longsize()==1) return elem.arity()==1 && first.equals(elem) && empty(); + if (first.longsize()!=1 || first.arity()!=1 || elem.arity()!=1 || arity()!=2 || longsize()!=elem.longsize()-1) return false; + SimAtom e = first.getAtom(); + List elems = elem.getAllAtoms(0); + if (longsize() > Integer.MAX_VALUE) throw new OutOfMemoryError(); + List next = new ArrayList(size()); + for(SimTuple x: this) next.add(x); + while(true) { + // "e" must be in elems; remove it from elems + for(int n=elems.size(), i=0; ; i++) + if (i>=n) return false; + else if (elems.get(i)==e) { elems.set(i, elems.get(n-1)); elems.remove(n-1); break; } + // if "e" was the last element, then "next" must be empty as well + if (elems.size()==0) return next.size()==0; + // remove (e,e') from next and let e' be the new e + // (if there was a cycle, we would eventually detect that since the repeated element would no longer be in "elems") + for(int n=next.size(), i=0; ; i++) + if (i>=n) return false; + else if (e==next.get(i).head()) { e=next.get(i).tail(); next.set(i, next.get(n-1)); next.remove(n-1); break; } + } + } + + /** Return an iterator over all subset x of this where x.size<=1 */ + public Iterator loneOf() { + return new Iterator() { + private long i = (-1); // -1 if we haven't started yet; otherwise it is the next element to return + public SimTupleset next() { + if (i<0) {i++; return EMPTY;} else if (i>=longsize()) throw new NoSuchElementException(); + SimTupleset ans = make(get(i)); + i++; + return ans; + } + public boolean hasNext() { return i < longsize(); } + public void remove() { throw new UnsupportedOperationException(); } + }; + } + + /** Return an iterator over all subset x of this where x.size==1 */ + public Iterator oneOf() { + Iterator ans = loneOf(); + ans.next(); // here, we depend on our knowledge that loneOf() will always return the emptyset first, so we can skip it up front + return ans; + } + + /** Return an iterator over all subset x of this */ + public Iterator setOf() { + if (longsize() > Integer.MAX_VALUE) throw new OutOfMemoryError(); + return new Iterator() { + private boolean in[] = new boolean[size()]; // indicates whether each tuple should appear in the upcoming tupleset; if null, it means no more results + public SimTupleset next() { + if (in==null) throw new NoSuchElementException(); + TempList ans = new TempList(); + for(int i=0; i=1 */ + public Iterator someOf() { + Iterator ans = setOf(); + ans.next(); // here, we depend on our knowledge that setOf() will always return the emptyset first, so we can skip it up front + return ans; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/A4Options.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/A4Options.java new file mode 100644 index 00000000..8fe00e6d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/A4Options.java @@ -0,0 +1,198 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.translator; + +import java.io.Serializable; +import java.util.prefs.Preferences; +import edu.mit.csail.sdg.alloy4.ErrorAPI; +import edu.mit.csail.sdg.alloy4.SafeList; +import edu.mit.csail.sdg.alloy4.Util; + +/** Mutable; this class encapsulates the customizable options of the Alloy-to-Kodkod translator. */ + +public final class A4Options implements Serializable { + + /** This enum defines the set of possible SAT solvers. */ + public static final class SatSolver implements Serializable { + /** This ensures the class can be serialized reliably. */ + private static final long serialVersionUID = 0; + /** List of all existing SatSolver values. */ + private static final SafeList values = new SafeList(); + /** This is a unique String for this value; it should be kept consistent in future versions. */ + private final String id; + /** This is the label that the toString() method will return. */ + private final String toString; + /** If not null, this is the external command-line solver to use. */ + private final String external; + /** If not null, this is the set of options to use with the command-line solver. */ + private final String[] options; + /** Constructs a new SatSolver value. */ + private SatSolver(String id, String toString, String external, String[] options, boolean add) { + this.id=id; + this.toString=toString; + this.external=external; + this.options=new String[options!=null ? options.length : 0]; + for(int i=0; i values() { + SafeList ans; + synchronized(SatSolver.class) { ans=values.dup(); } + return ans; + } + /** Returns the human-readable label for this enum value. */ + @Override public String toString() { return toString; } + /** Ensures we can use == to do comparison. */ + private Object readResolve() { + synchronized(SatSolver.class) { + for(SatSolver x:values) if (x.id.equals(id)) return x; + values.add(this); + } + return this; + } + /** Given an id, return the enum value corresponding to it (if there's no match, then return SAT4J). */ + public static SatSolver parse(String id) { + synchronized(SatSolver.class) { for(SatSolver x:values) if (x.id.equals(id)) return x; } + return SAT4J; + } + /** Saves this value into the Java preference object. */ + public void set() { Preferences.userNodeForPackage(Util.class).put("SatSolver2",id); } + /** Reads the current value of the Java preference object (if it's not set, then return SAT4J). */ + public static SatSolver get() { return parse(Preferences.userNodeForPackage(Util.class).get("SatSolver2","")); } + /** BerkMin via pipe */ + public static final SatSolver BerkMinPIPE = new SatSolver("berkmin", "BerkMin", "berkmin", null, true); + /** Spear via pipe */ + public static final SatSolver SpearPIPE = new SatSolver("spear", "Spear", "spear", new String[]{"--model", "--dimacs"}, true); + /** MiniSat1 via JNI */ + public static final SatSolver MiniSatJNI = new SatSolver("minisat(jni)", "MiniSat", null, null, true); + /** MiniSatProver1 via JNI */ + public static final SatSolver MiniSatProverJNI = new SatSolver("minisatprover(jni)", "MiniSat with Unsat Core", null, null, true); + /** ZChaff via JNI */ + public static final SatSolver ZChaffJNI = new SatSolver("zchaff(jni)", "ZChaff", null, null, true); + /** SAT4J using native Java */ + public static final SatSolver SAT4J = new SatSolver("sat4j", "SAT4J", null, null, true); + /** Outputs the raw CNF file only */ + public static final SatSolver CNF = new SatSolver("cnf", "Output CNF to file", null, null, true); + /** Outputs the raw Kodkod file only */ + public static final SatSolver KK = new SatSolver("kodkod", "Output Kodkod to file", null, null, true); + } + + /** This ensures the class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** Constructs an A4Options object with default values for everything. */ + public A4Options() { } + + /** This option specifies the amount of symmetry breaking to do (when symmetry breaking isn't explicitly disabled). + * + *

If a formula is unsatisfiable, then in general, the higher this value, + * the faster you finish the solving. But if this value is too high, it will instead slow down the solving. + * + *

If a formula is satisfiable, then in general, the lower this value, the faster you finish the solving. + * Setting this value to 0 usually gives the fastest solve. + * + *

Default value is 20. + */ + public int symmetry = 20; + + /** This option specifies the maximum skolem-function depth. + *

Default value is 0, which means it will only generate skolem constants, and will not generate skolem functions. + */ + public int skolemDepth = 0; + + /** This option specifies the unsat core minimization strategy (0=GuaranteedLocalMinimum 1=FasterButLessAccurate 2=EvenFaster...) + *

Default value is set to the fastest current strategy. + */ + public int coreMinimization = 2; + + /** Unsat core granularity, default is 0 (only top-level conjuncts are considered), 3 expands all quantifiers */ + public int coreGranularity = 0; + + /** This option specifies the SAT solver to use (SAT4J, MiniSatJNI, MiniSatProverJNI, ZChaffJNI...) + *

Default value is SAT4J. + */ + public SatSolver solver = SatSolver.SAT4J; + + /** When this.solver is external, and the solver filename is a relative filename, then this option specifies + * the directory that the solver filename is relative to. + */ + public String solverDirectory = ""; + + /** This specifies the directory where we may write temporary files to. */ + public String tempDirectory = System.getProperty("java.io.tmpdir"); + + /** This option tells the compiler the "original filename" that these AST nodes came from; + * it is only used for generating comments and other diagnostic messages. + *

Default value is "". + */ + public String originalFilename = ""; + + /** This option specifies whether the compiler should record + * the original Kodkod formula being generated and the resulting Kodkod instances. + *

Default value is false. + */ + public boolean recordKodkod = false; + + /** This option specifies whether the solver should report only solutions + * that don't cause any overflows. */ + public boolean noOverflow = false; + + /** This option constrols how deep we unroll loops and unroll recursive predicate/function/macros (negative means it's disallowed) */ + public int unrolls = (-1); + + /** This method makes a copy of this Options object. */ + public A4Options dup() { + A4Options x = new A4Options(); + x.unrolls = unrolls; + x.symmetry = symmetry; + x.skolemDepth = skolemDepth; + x.coreMinimization = coreMinimization; + x.solver = solver; + x.solverDirectory = solverDirectory; + x.tempDirectory = tempDirectory; + x.originalFilename = originalFilename; + x.recordKodkod = recordKodkod; + x.noOverflow = noOverflow; + x.coreGranularity = coreGranularity; + return x; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/A4Solution.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/A4Solution.java new file mode 100644 index 00000000..be6dab64 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/A4Solution.java @@ -0,0 +1,1134 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.translator; + +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.UNIV; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.SIGINT; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.SEQIDX; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.STRING; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.NONE; +import static kodkod.engine.Solution.Outcome.UNSATISFIABLE; +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import kodkod.ast.BinaryExpression; +import kodkod.ast.BinaryFormula; +import kodkod.ast.Decl; +import kodkod.ast.Expression; +import kodkod.ast.Formula; +import kodkod.ast.IntExpression; +import kodkod.ast.Node; +import kodkod.ast.Relation; +import kodkod.ast.Variable; +import kodkod.ast.operator.ExprOperator; +import kodkod.ast.operator.FormulaOperator; +import kodkod.engine.CapacityExceededException; +import kodkod.engine.Evaluator; +import kodkod.engine.Proof; +import kodkod.engine.Solution; +import kodkod.engine.Solver; +import kodkod.engine.config.AbstractReporter; +import kodkod.engine.config.Options; +import kodkod.engine.config.Reporter; +import kodkod.engine.fol2sat.TranslationRecord; +import kodkod.engine.fol2sat.Translator; +import kodkod.engine.satlab.SATFactory; +import kodkod.engine.ucore.HybridStrategy; +import kodkod.engine.ucore.RCEStrategy; +import kodkod.instance.Bounds; +import kodkod.instance.Instance; +import kodkod.instance.Tuple; +import kodkod.instance.TupleFactory; +import kodkod.instance.TupleSet; +import kodkod.instance.Universe; +import kodkod.util.ints.IndexedEntry; +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.ConstMap; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorAPI; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.SafeList; +import edu.mit.csail.sdg.alloy4.UniqueNameGenerator; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprBinary; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprConstant; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprUnary; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import edu.mit.csail.sdg.alloy4compiler.ast.Func; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Type; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Options.SatSolver; + +/** This class stores a SATISFIABLE or UNSATISFIABLE solution. + * It is also used as a staging area for the solver before generating the solution. + * Once solve() has been called, then this object becomes immutable after that. + */ + +public final class A4Solution { + + //====== static immutable fields ====================================================================// + + /** The constant unary relation representing the smallest Int atom. */ + static final Relation KK_MIN = Relation.unary("Int/min"); + + /** The constant unary relation representing the Int atom "0". */ + static final Relation KK_ZERO = Relation.unary("Int/zero"); + + /** The constant unary relation representing the largest Int atom. */ + static final Relation KK_MAX = Relation.unary("Int/max"); + + /** The constant binary relation representing the "next" relation from each Int atom to its successor. */ + static final Relation KK_NEXT = Relation.binary("Int/next"); + + /** The constant unary relation representing the set of all seq/Int atoms. */ + static final Relation KK_SEQIDX = Relation.unary("seq/Int"); + + /** The constant unary relation representing the set of all String atoms. */ + static final Relation KK_STRING = Relation.unary("String"); + + //====== immutable fields ===========================================================================// + + /** The original Alloy options that generated this solution. */ + private final A4Options originalOptions; + + /** The original Alloy command that generated this solution; can be "" if unknown. */ + private final String originalCommand; + + /** The bitwidth; always between 1 and 30. */ + private final int bitwidth; + + /** The maximum allowed sequence length; always between 0 and 2^(bitwidth-1)-1. */ + private final int maxseq; + + /** The maximum allowed number of loop unrolling and recursion level. */ + private final int unrolls; + + /** The list of all atoms. */ + private final ConstList kAtoms; + + /** The Kodkod TupleFactory object. */ + private final TupleFactory factory; + + /** The set of all Int atoms; immutable. */ + private final TupleSet sigintBounds; + + /** The set of all seq/Int atoms; immutable. */ + private final TupleSet seqidxBounds; + + /** The set of all String atoms; immutable. */ + private final TupleSet stringBounds; + + /** The Kodkod Solver object. */ + private final Solver solver; + + //====== mutable fields (immutable after solve() has been called) ===================================// + + /** True iff the problem is solved. */ + private boolean solved = false; + + /** The Kodkod Bounds object. */ + private Bounds bounds; + + /** The list of Kodkod formulas; can be empty if unknown; once a solution is solved we must not modify this anymore */ + private ArrayList formulas = new ArrayList(); + + /** The list of known Alloy4 sigs. */ + private SafeList sigs; + + /** If solved==true and is satisfiable, then this is the list of known skolems. */ + private SafeList skolems = new SafeList(); + + /** If solved==true and is satisfiable, then this is the list of actually used atoms. */ + private SafeList atoms = new SafeList(); + + /** If solved==true and is satisfiable, then this maps each Kodkod atom to a short name. */ + private Map atom2name = new LinkedHashMap(); + + /** If solved==true and is satisfiable, then this maps each Kodkod atom to its most specific sig. */ + private Map atom2sig = new LinkedHashMap(); + + /** If solved==true and is satisfiable, then this is the Kodkod evaluator. */ + private Evaluator eval = null; + + /** If not null, you can ask it to get another solution. */ + private Iterator kEnumerator = null; + + /** The map from each Sig/Field/Skolem/Atom to its corresponding Kodkod expression. */ + private Map a2k; + + /** The map from each String literal to its corresponding Kodkod expression. */ + private final ConstMap s2k; + + /** The map from each kodkod Formula to Alloy Expr or Alloy Pos (can be empty if unknown) */ + private Map k2pos; + + /** The map from each Kodkod Relation to Alloy Type (can be empty or incomplete if unknown) */ + private Map rel2type; + + /** The map from each Kodkod Variable to an Alloy Type and Alloy Pos. */ + private Map> decl2type; + + //===================================================================================================// + + /** Construct a blank A4Solution containing just UNIV, SIGINT, SEQIDX, STRING, and NONE as its only known sigs. + * @param originalCommand - the original Alloy command that generated this solution; can be "" if unknown + * @param bitwidth - the bitwidth; must be between 1 and 30 + * @param maxseq - the maximum allowed sequence length; must be between 0 and (2^(bitwidth-1))-1 + * @param atoms - the set of atoms + * @param rep - the reporter that will receive diagnostic and progress messages + * @param opt - the Alloy options that will affect the solution and the solver + * @param expected - whether the user expected an instance or not (1 means yes, 0 means no, -1 means the user did not express an expectation) + */ + A4Solution(String originalCommand, int bitwidth, int maxseq, Set stringAtoms, Collection atoms, final A4Reporter rep, A4Options opt, int expected) throws Err { + opt = opt.dup(); + this.unrolls = opt.unrolls; + this.sigs = new SafeList(Arrays.asList(UNIV, SIGINT, SEQIDX, STRING, NONE)); + this.a2k = Util.asMap(new Expr[]{UNIV, SIGINT, SEQIDX, STRING, NONE}, Relation.INTS.union(KK_STRING), Relation.INTS, KK_SEQIDX, KK_STRING, Relation.NONE); + this.k2pos = new LinkedHashMap(); + this.rel2type = new LinkedHashMap(); + this.decl2type = new LinkedHashMap>(); + this.originalOptions = opt; + this.originalCommand = (originalCommand==null ? "" : originalCommand); + this.bitwidth = bitwidth; + this.maxseq = maxseq; + if (bitwidth < 0) throw new ErrorSyntax("Cannot specify a bitwidth less than 0"); + if (bitwidth > 30) throw new ErrorSyntax("Cannot specify a bitwidth greater than 30"); + if (maxseq < 0) throw new ErrorSyntax("The maximum sequence length cannot be negative."); + if (maxseq > 0 && maxseq > max()) throw new ErrorSyntax("With integer bitwidth of "+bitwidth+", you cannot have sequence length longer than "+max()); + if (atoms.isEmpty()) { + atoms = new ArrayList(1); + atoms.add(""); + } + kAtoms = ConstList.make(atoms); + bounds = new Bounds(new Universe(kAtoms)); + factory = bounds.universe().factory(); + TupleSet sigintBounds = factory.noneOf(1); + TupleSet seqidxBounds = factory.noneOf(1); + TupleSet stringBounds = factory.noneOf(1); + final TupleSet next = factory.noneOf(2); + int min=min(), max=max(); + if (max >= min) for(int i=min; i<=max; i++) { // Safe since we know 1 <= bitwidth <= 30 + Tuple ii = factory.tuple(""+i); + TupleSet is = factory.range(ii, ii); + bounds.boundExactly(i, is); + sigintBounds.add(ii); + if (i>=0 && i s2k = new HashMap(); + for(String e: stringAtoms) { + Relation r = Relation.unary(""); + Tuple t = factory.tuple(e); + s2k.put(e, r); + bounds.boundExactly(r, factory.range(t, t)); + stringBounds.add(t); + } + this.s2k = ConstMap.make(s2k); + this.stringBounds = stringBounds.unmodifiableView(); + bounds.boundExactly(KK_STRING, this.stringBounds); + int sym = (expected==1 ? 0 : opt.symmetry); + solver = new Solver(); + solver.options().setNoOverflow(opt.noOverflow); + solver.options().setFlatten(false); // added for now, since multiplication and division circuit takes forever to flatten + if (opt.solver.external()!=null) { + String ext = opt.solver.external(); + if (opt.solverDirectory.length()>0 && ext.indexOf(File.separatorChar)<0) ext=opt.solverDirectory+File.separatorChar+ext; + try { + File tmp = File.createTempFile("tmp", ".cnf", new File(opt.tempDirectory)); + tmp.deleteOnExit(); + solver.options().setSolver(SATFactory.externalFactory(ext, tmp.getAbsolutePath(), "", opt.solver.options())); + //solver.options().setSolver(SATFactory.externalFactory(ext, tmp.getAbsolutePath(), opt.solver.options())); + } catch(IOException ex) { throw new ErrorFatal("Cannot create temporary directory.", ex); } + } else if (opt.solver.equals(A4Options.SatSolver.ZChaffJNI)) { + solver.options().setSolver(SATFactory.ZChaff); + } else if (opt.solver.equals(A4Options.SatSolver.MiniSatJNI)) { + solver.options().setSolver(SATFactory.MiniSat); + } else if (opt.solver.equals(A4Options.SatSolver.MiniSatProverJNI)) { + sym=20; + solver.options().setSolver(SATFactory.MiniSatProver); + solver.options().setLogTranslation(2); + solver.options().setCoreGranularity(opt.coreGranularity); + } else { + solver.options().setSolver(SATFactory.DefaultSAT4J); // Even for "KK" and "CNF", we choose SAT4J here; later, just before solving, we'll change it to a Write2CNF solver + } + solver.options().setSymmetryBreaking(sym); + solver.options().setSkolemDepth(opt.skolemDepth); + solver.options().setBitwidth(bitwidth > 0 ? bitwidth : (int) Math.ceil(Math.log(atoms.size())) + 1); + solver.options().setIntEncoding(Options.IntEncoding.TWOSCOMPLEMENT); + } + + /** Construct a new A4Solution that is the continuation of the old one, but with the "next" instance. */ + private A4Solution(A4Solution old) throws Err { + if (!old.solved) throw new ErrorAPI("This solution is not yet solved, so next() is not allowed."); + if (old.kEnumerator==null) throw new ErrorAPI("This solution was not generated by an incremental SAT solver.\n" + "Solution enumeration is currently only implemented for MiniSat and SAT4J."); + if (old.eval==null) throw new ErrorAPI("This solution is already unsatisfiable, so you cannot call next() to get the next solution."); + Instance inst = old.kEnumerator.next().instance(); + unrolls = old.unrolls; + originalOptions = old.originalOptions; + originalCommand = old.originalCommand; + bitwidth = old.bitwidth; + maxseq = old.maxseq; + kAtoms = old.kAtoms; + factory = old.factory; + sigintBounds = old.sigintBounds; + seqidxBounds = old.seqidxBounds; + stringBounds = old.stringBounds; + solver = old.solver; + bounds = old.bounds; + formulas = old.formulas; + sigs = old.sigs; + kEnumerator = old.kEnumerator; + k2pos = old.k2pos; + rel2type = old.rel2type; + decl2type = old.decl2type; + if (inst!=null) { + eval = new Evaluator(inst, old.solver.options()); + a2k = new LinkedHashMap(); + for(Map.Entry e: old.a2k.entrySet()) + if (e.getKey() instanceof Sig || e.getKey() instanceof Field) + a2k.put(e.getKey(), e.getValue()); + UniqueNameGenerator un = new UniqueNameGenerator(); + rename(this, null, null, un); + a2k = ConstMap.make(a2k); + } else { + skolems = old.skolems; + eval = null; + a2k = old.a2k; + } + s2k = old.s2k; + atoms = atoms.dup(); + atom2name = ConstMap.make(atom2name); + atom2sig = ConstMap.make(atom2sig); + solved = true; + } + + /** Turn the solved flag to be true, and make all remaining fields immutable. */ + private void solved() { + if (solved) return; // already solved + bounds = bounds.clone().unmodifiableView(); + sigs = sigs.dup(); + skolems = skolems.dup(); + atoms = atoms.dup(); + atom2name = ConstMap.make(atom2name); + atom2sig = ConstMap.make(atom2sig); + a2k = ConstMap.make(a2k); + k2pos = ConstMap.make(k2pos); + rel2type = ConstMap.make(rel2type); + decl2type = ConstMap.make(decl2type); + solved = true; + } + + //===================================================================================================// + + /** Returns the bitwidth; always between 1 and 30. */ + public int getBitwidth() { return bitwidth; } + + /** Returns the maximum allowed sequence length; always between 0 and 2^(bitwidth-1)-1. */ + public int getMaxSeq() { return maxseq; } + + /** Returns the largest allowed integer, or -1 if no integers are allowed. */ + public int max() { return Util.max(bitwidth); } + + /** Returns the smallest allowed integer, or 0 if no integers are allowed */ + public int min() { return Util.min(bitwidth); } + + /** Returns the maximum number of allowed loop unrolling or recursion level. */ + public int unrolls() { return unrolls; } + + //===================================================================================================// + + /** Returns the original Alloy file name that generated this solution; can be "" if unknown. */ + public String getOriginalFilename() { return originalOptions.originalFilename; } + + /** Returns the original command that generated this solution; can be "" if unknown. */ + public String getOriginalCommand() { return originalCommand; } + + //===================================================================================================// + + /** Returns the Kodkod input used to generate this solution; returns "" if unknown. */ + public String debugExtractKInput() { + if (solved) + return TranslateKodkodToJava.convert(Formula.and(formulas), bitwidth, kAtoms, bounds, atom2name); + else + return TranslateKodkodToJava.convert(Formula.and(formulas), bitwidth, kAtoms, bounds.unmodifiableView(), null); + } + + //===================================================================================================// + + /** Returns the Kodkod TupleFactory object. */ + TupleFactory getFactory() { return factory; } + + /** Returns a modifiable copy of the Kodkod Bounds object. */ + Bounds getBounds() { return bounds.clone(); } + + /** Add a new relation with the given label and the given lower and upper bound. + * @param label - the label for the new relation; need not be unique + * @param lower - the lowerbound; can be null if you want it to be the empty set + * @param upper - the upperbound; cannot be null; must contain everything in lowerbound + */ + Relation addRel(String label, TupleSet lower, TupleSet upper) throws ErrorFatal { + if (solved) throw new ErrorFatal("Cannot add a Kodkod relation since solve() has completed."); + Relation rel = Relation.nary(label, upper.arity()); + if (lower == upper) { + bounds.boundExactly(rel, upper); + } else if (lower == null) { + bounds.bound(rel, upper); + } else { + if (lower.arity() != upper.arity()) throw new ErrorFatal("Relation "+label+" must have same arity for lowerbound and upperbound."); + bounds.bound(rel, lower, upper); + } + return rel; + } + + /** Add a new sig to this solution and associate it with the given expression (and if s.isTopLevel then add this expression into Sig.UNIV). + *
The expression must contain only constant Relations or Relations that are already bound in this solution. + *
(If the sig was already added by a previous call to addSig(), then this call will return immediately without altering what it is associated with) + */ + void addSig(Sig s, Expression expr) throws ErrorFatal { + if (solved) throw new ErrorFatal("Cannot add an additional sig since solve() has completed."); + if (expr.arity()!=1) throw new ErrorFatal("Sig "+s+" must be associated with a unary relational value."); + if (a2k.containsKey(s)) return; + a2k.put(s, expr); + sigs.add(s); + if (s.isTopLevel()) a2k.put(UNIV, a2k.get(UNIV).union(expr)); + } + + /** Add a new field to this solution and associate it with the given expression. + *
The expression must contain only constant Relations or Relations that are already bound in this solution. + *
(If the field was already added by a previous call to addField(), then this call will return immediately without altering what it is associated with) + */ + void addField(Field f, Expression expr) throws ErrorFatal { + if (solved) throw new ErrorFatal("Cannot add an additional field since solve() has completed."); + if (expr.arity()!=f.type().arity()) throw new ErrorFatal("Field "+f+" must be associated with an "+f.type().arity()+"-ary relational value."); + if (a2k.containsKey(f)) return; + a2k.put(f, expr); + } + + /** Add a new skolem to this solution and associate it with the given expression. + *
The expression must contain only constant Relations or Relations that are already bound in this solution. + */ + private ExprVar addSkolem(String label, Type type, Expression expr) throws Err { + if (solved) throw new ErrorFatal("Cannot add an additional skolem since solve() has completed."); + int a = type.arity(); + if (a<1) throw new ErrorFatal("Skolem "+label+" must be associated with a relational value."); + if (a!=expr.arity()) throw new ErrorFatal("Skolem "+label+" must be associated with an "+a+"-ary relational value."); + ExprVar v = ExprVar.make(Pos.UNKNOWN, label, type); + a2k.put(v, expr); + skolems.add(v); + return v; + } + + /** Returns an unmodifiable copy of the map from each Sig/Field/Skolem/Atom to its corresponding Kodkod expression. */ + ConstMap a2k() { return ConstMap.make(a2k); } + + /** Returns an unmodifiable copy of the map from each String literal to its corresponding Kodkod expression. */ + ConstMap s2k() { return s2k; } + + /** Returns the corresponding Kodkod expression for the given Sig, or null if it is not associated with anything. */ + Expression a2k(Sig sig) { return a2k.get(sig); } + + /** Returns the corresponding Kodkod expression for the given Field, or null if it is not associated with anything. */ + Expression a2k(Field field) { return a2k.get(field); } + + /** Returns the corresponding Kodkod expression for the given Atom/Skolem, or null if it is not associated with anything. */ + Expression a2k(ExprVar var) { return a2k.get(var); } + + /** Returns the corresponding Kodkod expression for the given String constant, or null if it is not associated with anything. */ + Expression a2k(String stringConstant) { return s2k.get(stringConstant); } + + /** Returns the corresponding Kodkod expression for the given expression, or null if it is not associated with anything. */ + Expression a2k(Expr expr) throws ErrorFatal { + while(expr instanceof ExprUnary) { + if (((ExprUnary)expr).op==ExprUnary.Op.NOOP) { expr = ((ExprUnary)expr).sub; continue; } + if (((ExprUnary)expr).op==ExprUnary.Op.EXACTLYOF) { expr = ((ExprUnary)expr).sub; continue; } + break; + } + if (expr instanceof ExprConstant && ((ExprConstant)expr).op==ExprConstant.Op.EMPTYNESS) return Expression.NONE; + if (expr instanceof ExprConstant && ((ExprConstant)expr).op==ExprConstant.Op.STRING) return s2k.get(((ExprConstant)expr).string); + if (expr instanceof Sig || expr instanceof Field || expr instanceof ExprVar) return a2k.get(expr); + if (expr instanceof ExprBinary) { + Expr a=((ExprBinary)expr).left, b=((ExprBinary)expr).right; + switch(((ExprBinary)expr).op) { + case ARROW: return a2k(a).product(a2k(b)); + case PLUS: return a2k(a).union(a2k(b)); + case MINUS: return a2k(a).difference(a2k(b)); + //TODO: IPLUS, IMINUS??? + } + } + return null; // Current only UNION, PRODUCT, and DIFFERENCE of Sigs and Fields and ExprConstant.EMPTYNESS are allowed in a defined field's definition. + } + + /** Return a modifiable TupleSet representing a sound overapproximation of the given expression. */ + TupleSet approximate(Expression expression) { + return factory.setOf(expression.arity(), Translator.approximate(expression, bounds, solver.options()).denseIndices()); + } + + /** Query the Bounds object to find the lower/upper bound; throws ErrorFatal if expr is not Relation, nor a {union, product} of Relations. */ + TupleSet query(boolean findUpper, Expression expr, boolean makeMutable) throws ErrorFatal { + if (expr==Relation.NONE) return factory.noneOf(1); + if (expr==Relation.INTS) return makeMutable ? sigintBounds.clone() : sigintBounds; + if (expr==KK_SEQIDX) return makeMutable ? seqidxBounds.clone() : seqidxBounds; + if (expr==KK_STRING) return makeMutable ? stringBounds.clone() : stringBounds; + if (expr instanceof Relation) { + TupleSet ans = findUpper ? bounds.upperBound((Relation)expr) : bounds.lowerBound((Relation)expr); + if (ans!=null) return makeMutable ? ans.clone() : ans; + } + else if (expr instanceof BinaryExpression) { + BinaryExpression b = (BinaryExpression)expr; + if (b.op() == ExprOperator.UNION) { + TupleSet left = query(findUpper, b.left(), true); + TupleSet right = query(findUpper, b.right(), false); + left.addAll(right); + return left; + } else if (b.op() == ExprOperator.PRODUCT) { + TupleSet left = query(findUpper, b.left(), true); + TupleSet right = query(findUpper, b.right(), false); + return left.product(right); + } + } + throw new ErrorFatal("Unknown expression encountered during bounds computation: "+expr); + } + + /** Shrink the bounds for the given relation; throws an exception if the new bounds is not sameAs/subsetOf the old bounds. */ + void shrink(Relation relation, TupleSet lowerBound, TupleSet upperBound) throws Err { + if (solved) throw new ErrorFatal("Cannot shrink a Kodkod relation since solve() has completed."); + TupleSet oldL = bounds.lowerBound(relation); + TupleSet oldU = bounds.upperBound(relation); + if (oldU.containsAll(upperBound) && upperBound.containsAll(lowerBound) && lowerBound.containsAll(oldL)) { + bounds.bound(relation, lowerBound, upperBound); + } else { + throw new ErrorAPI("Inconsistent bounds shrinking on relation: "+relation); + } + } + + //===================================================================================================// + + /** Returns true iff the problem has been solved and the result is satisfiable. */ + public boolean satisfiable() { return eval!=null; } + + /** Returns an unmodifiable copy of the list of all sigs in this solution's model; always contains UNIV+SIGINT+SEQIDX+STRING+NONE and has no duplicates. */ + public SafeList getAllReachableSigs() { return sigs.dup(); } + + /** Returns an unmodifiable copy of the list of all skolems if the problem is solved and is satisfiable; else returns an empty list. */ + public Iterable getAllSkolems() { return skolems.dup(); } + + /** Returns an unmodifiable copy of the list of all atoms if the problem is solved and is satisfiable; else returns an empty list. */ + public Iterable getAllAtoms() { return atoms.dup(); } + + /** Returns the short unique name corresponding to the given atom if the problem is solved and is satisfiable; else returns atom.toString(). */ + String atom2name(Object atom) { String ans=atom2name.get(atom); return ans==null ? atom.toString() : ans; } + + /** Returns the most specific sig corresponding to the given atom if the problem is solved and is satisfiable; else returns UNIV. */ + PrimSig atom2sig(Object atom) { PrimSig sig=atom2sig.get(atom); return sig==null ? UNIV : sig; } + + /** Caches eval(Sig) and eval(Field) results. */ + private Map evalCache = new LinkedHashMap(); + + /** Return the A4TupleSet for the given sig (if solution not yet solved, or unsatisfiable, or sig not found, then return an empty tupleset) */ + public A4TupleSet eval(Sig sig) { + try { + if (!solved || eval==null) return new A4TupleSet(factory.noneOf(1), this); + A4TupleSet ans = evalCache.get(sig); + if (ans!=null) return ans; + TupleSet ts = eval.evaluate((Expression) TranslateAlloyToKodkod.alloy2kodkod(this, sig)); + ans = new A4TupleSet(ts, this); + evalCache.put(sig, ans); + return ans; + } catch(Err er) { + return new A4TupleSet(factory.noneOf(1), this); + } + } + + /** Return the A4TupleSet for the given field (if solution not yet solved, or unsatisfiable, or field not found, then return an empty tupleset) */ + public A4TupleSet eval(Field field) { + try { + if (!solved || eval==null) return new A4TupleSet(factory.noneOf(field.type().arity()), this); + A4TupleSet ans = evalCache.get(field); + if (ans!=null) return ans; + TupleSet ts = eval.evaluate((Expression) TranslateAlloyToKodkod.alloy2kodkod(this, field)); + ans = new A4TupleSet(ts, this); + evalCache.put(field, ans); + return ans; + } catch(Err er) { + return new A4TupleSet(factory.noneOf(field.type().arity()), this); + } + } + + /** If this solution is solved and satisfiable, evaluates the given expression and returns an A4TupleSet, a java Integer, or a java Boolean. */ + public Object eval(Expr expr) throws Err { + try { + if (expr instanceof Sig) return eval((Sig)expr); + if (expr instanceof Field) return eval((Field)expr); + if (!solved) throw new ErrorAPI("This solution is not yet solved, so eval() is not allowed."); + if (eval==null) throw new ErrorAPI("This solution is unsatisfiable, so eval() is not allowed."); + if (expr.ambiguous && !expr.errors.isEmpty()) expr = expr.resolve(expr.type(), null); + if (!expr.errors.isEmpty()) throw expr.errors.pick(); + Object result = TranslateAlloyToKodkod.alloy2kodkod(this, expr); + if (result instanceof IntExpression) return eval.evaluate((IntExpression)result) + (eval.wasOverflow() ? " (OF)" : ""); + if (result instanceof Formula) return eval.evaluate((Formula)result); + if (result instanceof Expression) return new A4TupleSet(eval.evaluate((Expression)result), this); + throw new ErrorFatal("Unknown internal error encountered in the evaluator."); + } catch(CapacityExceededException ex) { + throw TranslateAlloyToKodkod.rethrow(ex); + } + } + + /** Returns the Kodkod instance represented by this solution; throws an exception if the problem is not yet solved or if it is unsatisfiable. */ + public Instance debugExtractKInstance() throws Err { + if (!solved) throw new ErrorAPI("This solution is not yet solved, so instance() is not allowed."); + if (eval==null) throw new ErrorAPI("This solution is unsatisfiable, so instance() is not allowed."); + return eval.instance().unmodifiableView(); + } + + //===================================================================================================// + + /** Maps a Kodkod formula to an Alloy Expr or Alloy Pos (or null if no such mapping) */ + Object k2pos(Node formula) { return k2pos.get(formula); } + + /** Associates the Kodkod formula to a particular Alloy Expr (if the Kodkod formula is not already associated with an Alloy Expr or Alloy Pos) */ + Formula k2pos(Formula formula, Expr expr) throws Err { + if (solved) throw new ErrorFatal("Cannot alter the k->pos mapping since solve() has completed."); + if (formula==null || expr==null || k2pos.containsKey(formula)) return formula; + k2pos.put(formula, expr); + if (formula instanceof BinaryFormula) { + BinaryFormula b = (BinaryFormula)formula; + if (b.op() == FormulaOperator.AND) { k2pos(b.left(), expr); k2pos(b.right(), expr); } + } + return formula; + } + + /** Associates the Kodkod formula to a particular Alloy Pos (if the Kodkod formula is not already associated with an Alloy Expr or Alloy Pos) */ + Formula k2pos(Formula formula, Pos pos) throws Err { + if (solved) throw new ErrorFatal("Cannot alter the k->pos mapping since solve() has completed."); + if (formula==null || pos==null || pos==Pos.UNKNOWN || k2pos.containsKey(formula)) return formula; + k2pos.put(formula, pos); + if (formula instanceof BinaryFormula) { + BinaryFormula b = (BinaryFormula)formula; + if (b.op() == FormulaOperator.AND) { k2pos(b.left(), pos); k2pos(b.right(), pos); } + } + return formula; + } + + //===================================================================================================// + + /** Associates the Kodkod relation to a particular Alloy Type (if it is not already associated with something) */ + void kr2type(Relation relation, Type newType) throws Err { + if (solved) throw new ErrorFatal("Cannot alter the k->type mapping since solve() has completed."); + if (!rel2type.containsKey(relation)) rel2type.put(relation, newType); + } + + /** Remove all mapping from Kodkod relation to Alloy Type. */ + void kr2typeCLEAR() throws Err { + if (solved) throw new ErrorFatal("Cannot clear the k->type mapping since solve() has completed."); + rel2type.clear(); + } + + //===================================================================================================// + + /** Caches a constant pair of Type.EMPTY and Pos.UNKNOWN */ + private Pair cachedPAIR = null; + + /** Maps a Kodkod variable to an Alloy Type and Alloy Pos (if no association exists, it will return (Type.EMPTY , Pos.UNKNOWN) */ + Pair kv2typepos(Variable var) { + Pair ans=decl2type.get(var); + if (ans!=null) return ans; + if (cachedPAIR==null) cachedPAIR=new Pair(Type.EMPTY, Pos.UNKNOWN); + return cachedPAIR; + } + + /** Associates the Kodkod variable to a particular Alloy Type and Alloy Pos (if it is not already associated with something) */ + void kv2typepos(Variable var, Type type, Pos pos) throws Err { + if (solved) throw new ErrorFatal("Cannot alter the k->type mapping since solve() has completed."); + if (type==null) type=Type.EMPTY; + if (pos==null) pos=Pos.UNKNOWN; + if (!decl2type.containsKey(var)) decl2type.put(var, new Pair(type, pos)); + } + + //===================================================================================================// + + /** Add the given formula to the list of Kodkod formulas, and associate it with the given Pos object (pos can be null if unknown). */ + void addFormula(Formula newFormula, Pos pos) throws Err { + if (solved) throw new ErrorFatal("Cannot add an additional formula since solve() has completed."); + if (formulas.size()>0 && formulas.get(0)==Formula.FALSE) return; // If one formula is false, we don't need the others + if (newFormula==Formula.FALSE) formulas.clear(); // If one formula is false, we don't need the others + formulas.add(newFormula); + if (pos!=null && pos!=Pos.UNKNOWN) k2pos(newFormula, pos); + } + + /** Add the given formula to the list of Kodkod formulas, and associate it with the given Expr object (expr can be null if unknown) */ + void addFormula(Formula newFormula, Expr expr) throws Err { + if (solved) throw new ErrorFatal("Cannot add an additional formula since solve() has completed."); + if (formulas.size()>0 && formulas.get(0)==Formula.FALSE) return; // If one formula is false, we don't need the others + if (newFormula==Formula.FALSE) formulas.clear(); // If one formula is false, we don't need the others + formulas.add(newFormula); + if (expr!=null) k2pos(newFormula, expr); + } + + //===================================================================================================// + + /** Helper class that wraps an iterator up where it will pre-fetch the first element (note: it will not prefetch subsequent elements). */ + private static final class Peeker implements Iterator { + /** The encapsulated iterator. */ + private Iterator iterator; + /** True iff we have captured the first element. */ + private boolean hasFirst; + /** If hasFirst is true, then this is the captured first element. */ + private T first; + /** Constructrs a Peeker object. */ + private Peeker(Iterator it) { + iterator = it; + if (it.hasNext()) { hasFirst=true; first=it.next(); } + } + /** {@inheritDoc} */ + public boolean hasNext() { + return hasFirst || iterator.hasNext(); + } + /** {@inheritDoc} */ + public T next() { + if (hasFirst) { hasFirst=false; T ans=first; first=null; return ans; } else return iterator.next(); + } + /** {@inheritDoc} */ + public void remove() { throw new UnsupportedOperationException(); } + } + + //===================================================================================================// + + /** Helper method to determine if a given binary relation is a total order over a given unary relation. */ + private static List isOrder(TupleSet b, TupleSet u) { + // Size check + final int n = u.size(); + final List list = new ArrayList(n); + if (b.size() == 0 && n <= 1) return list; + if (b.size() != n-1) return null; + // Find the starting element + Tuple head = null; + TupleSet right = b.project(1); + for(Tuple x: u) if (!right.contains(x)) {head = x; break;} + if (head==null) return null; + final TupleFactory f = head.universe().factory(); + // Form the list + list.add(head); + while(true) { + // Find head.next + Tuple headnext = null; + for(Tuple x: b) if (x.atom(0)==head.atom(0)) { headnext = f.tuple(x.atom(1)); break; } + // If we've reached the end of the chain, and indeed we've formed exactly n elements (and all are in u), we're done + if (headnext==null) return list.size()==n ? list : null; + // If we've accumulated more than n elements, or if we reached an element not in u, then we declare failure + if (list.size()==n || !u.contains(headnext)) return null; + // Move on to the next step + head = headnext; + list.add(head); + } + } + + /** Helper method that chooses a name for each atom based on its most specific sig; (external caller should call this method with s==null and nexts==null) */ + private static void rename (A4Solution frame, PrimSig s, Map> nexts, UniqueNameGenerator un) throws Err { + if (s==null) { + for(ExprVar sk:frame.skolems) un.seen(sk.label); + // Store up the skolems + List skolems = new ArrayList(); + for(Map.Entry e: frame.rel2type.entrySet()) { + Relation r = e.getKey(); if (!frame.eval.instance().contains(r)) continue; + Type t = e.getValue(); if (t.arity() > r.arity()) continue; // Something is wrong; let's skip it + while (t.arity() < r.arity()) t = UNIV.type().product(t); + String n = Util.tail(r.name()); + while(n.length()>0 && n.charAt(0)=='$') n = n.substring(1); + skolems.add(n); + skolems.add(t); + skolems.add(r); + } + // Find all suitable "next" or "prev" relations + nexts = new LinkedHashMap>(); + for(Sig sig:frame.sigs) for(Field f: sig.getFields()) if (f.label.compareToIgnoreCase("next")==0) { + List> fold = f.type().fold(); + if (fold.size()==1) { + List t = fold.get(0); + if (t.size()==3 && t.get(0).isOne!=null && t.get(1)==t.get(2) && !nexts.containsKey(t.get(1))) { + TupleSet set = frame.eval.evaluate(frame.a2k(t.get(1))); + if (set.size()<=1) continue; + TupleSet next = frame.eval.evaluate(frame.a2k(t.get(0)).join(frame.a2k(f))); + List test = isOrder(next, set); + if (test!=null) nexts.put(t.get(1), test); + } else if (t.size()==2 && t.get(0)==t.get(1) && !nexts.containsKey(t.get(0))) { + TupleSet set = frame.eval.evaluate(frame.a2k(t.get(0))); + if (set.size()<=1) continue; + TupleSet next = frame.eval.evaluate(frame.a2k(f)); + List test = isOrder(next, set); + if (test!=null) nexts.put(t.get(1), test); + } + } + } + for(Sig sig:frame.sigs) for(Field f: sig.getFields()) if (f.label.compareToIgnoreCase("prev")==0) { + List> fold = f.type().fold(); + if (fold.size()==1) { + List t = fold.get(0); + if (t.size()==3 && t.get(0).isOne!=null && t.get(1)==t.get(2) && !nexts.containsKey(t.get(1))) { + TupleSet set = frame.eval.evaluate(frame.a2k(t.get(1))); + if (set.size()<=1) continue; + TupleSet next = frame.eval.evaluate(frame.a2k(t.get(0)).join(frame.a2k(f)).transpose()); + List test = isOrder(next, set); + if (test!=null) nexts.put(t.get(1), test); + } else if (t.size()==2 && t.get(0)==t.get(1) && !nexts.containsKey(t.get(0))) { + TupleSet set = frame.eval.evaluate(frame.a2k(t.get(0))); + if (set.size()<=1) continue; + TupleSet next = frame.eval.evaluate(frame.a2k(f).transpose()); + List test = isOrder(next, set); + if (test!=null) nexts.put(t.get(1), test); + } + } + } + // Assign atom->name and atom->MostSignificantSig + for(Tuple t:frame.eval.evaluate(Relation.INTS)) { frame.atom2sig.put(t.atom(0), SIGINT); } + for(Tuple t:frame.eval.evaluate(KK_SEQIDX)) { frame.atom2sig.put(t.atom(0), SEQIDX); } + for(Tuple t:frame.eval.evaluate(KK_STRING)) { frame.atom2sig.put(t.atom(0), STRING); } + for(Sig sig:frame.sigs) if (sig instanceof PrimSig && !sig.builtin && ((PrimSig)sig).isTopLevel()) rename(frame, (PrimSig)sig, nexts, un); + // These are redundant atoms that were not chosen to be in the final instance + int unused=0; + for(Tuple tuple:frame.eval.evaluate(Relation.UNIV)) { + Object atom = tuple.atom(0); + if (!frame.atom2sig.containsKey(atom)) { frame.atom2name.put(atom, "unused"+unused); unused++; } + } + // Add the skolems + for(int num=skolems.size(), i=0; i0 && n.charAt(0)=='$') n=n.substring(1); + Type t = (Type) skolems.get(i+1); + Relation r = (Relation) skolems.get(i+2); + frame.addSkolem(un.make("$"+n), t, r); + } + return; + } + for(PrimSig c: s.children()) rename(frame, c, nexts, un); + String signame = un.make(s.label.startsWith("this/") ? s.label.substring(5) : s.label); + List list = new ArrayList(); + for(Tuple t: frame.eval.evaluate(frame.a2k(s))) list.add(t); + List order = nexts.get(s); + if (order!=null && order.size()==list.size() && order.containsAll(list)) { list=order; } + int i = 0; + for(Tuple t: list) { + if (frame.atom2sig.containsKey(t.atom(0))) continue; // This means one of the subsig has already claimed this atom. + String x = signame + "$" + i; + i++; + frame.atom2sig.put(t.atom(0), s); + frame.atom2name.put(t.atom(0), x); + ExprVar v = ExprVar.make(null, x, s.type()); + TupleSet ts = t.universe().factory().range(t, t); + Relation r = Relation.unary(x); + frame.eval.instance().add(r, ts); + frame.a2k.put(v, r); + frame.atoms.add(v); + } + } + + //===================================================================================================// + + /** Solve for the solution if not solved already; if cmd==null, we will simply use the lowerbound of each relation as its value. */ + A4Solution solve(final A4Reporter rep, Command cmd, Simplifier simp, boolean tryBookExamples) throws Err, IOException { + // If already solved, then return this object as is + if (solved) return this; + // If cmd==null, then all four arguments are ignored, and we simply use the lower bound of each relation + if (cmd==null) { + Instance inst = new Instance(bounds.universe()); + for(int max=max(), i=min(); i<=max; i++) { + Tuple it = factory.tuple(""+i); + inst.add(i, factory.range(it, it)); + } + for(Relation r: bounds.relations()) inst.add(r, bounds.lowerBound(r)); + eval = new Evaluator(inst, solver.options()); + rename(this, null, null, new UniqueNameGenerator()); + solved(); + return this; + } + // Otherwise, prepare to do the solve... + final A4Options opt = originalOptions; + long time = System.currentTimeMillis(); + rep.debug("Simplifying the bounds...\n"); + if (simp!=null && formulas.size()>0 && !simp.simplify(rep, this, formulas)) addFormula(Formula.FALSE, Pos.UNKNOWN); + rep.translate(opt.solver.id(), bitwidth, maxseq, solver.options().skolemDepth(), solver.options().symmetryBreaking()); + Formula fgoal = Formula.and(formulas); + rep.debug("Generating the solution...\n"); + kEnumerator = null; + Solution sol = null; + final Reporter oldReporter = solver.options().reporter(); + final boolean solved[] = new boolean[]{true}; + solver.options().setReporter(new AbstractReporter() { // Set up a reporter to catch the type+pos of skolems + @Override public void skolemizing(Decl decl, Relation skolem, List predecl) { + try { + Type t=kv2typepos(decl.variable()).a; + if (t==Type.EMPTY) return; + for(int i=(predecl==null ? -1 : predecl.size()-1); i>=0; i--) { + Type pp=kv2typepos(predecl.get(i).variable()).a; + if (pp==Type.EMPTY) return; + t=pp.product(t); + } + kr2type(skolem, t); + } catch(Throwable ex) { } // Exception here is not fatal + } + @Override public void solvingCNF(int primaryVars, int vars, int clauses) { + if (solved[0]) return; else solved[0]=true; // initially solved[0] is true, so we won't report the # of vars/clauses + if (rep!=null) rep.solve(primaryVars, vars, clauses); + } + }); + if (!opt.solver.equals(SatSolver.CNF) && !opt.solver.equals(SatSolver.KK) && tryBookExamples) { // try book examples + A4Reporter r = "yes".equals(System.getProperty("debug")) ? rep : null; + try { sol = BookExamples.trial(r, this, fgoal, solver, cmd.check); } catch(Throwable ex) { sol = null; } + } + solved[0] = false; // this allows the reporter to report the # of vars/clauses + for(Relation r: bounds.relations()) { formulas.add(r.eq(r)); } // Without this, kodkod refuses to grow unmentioned relations + fgoal = Formula.and(formulas); + // Now pick the solver and solve it! + if (opt.solver.equals(SatSolver.KK)) { + File tmpCNF = File.createTempFile("tmp", ".java", new File(opt.tempDirectory)); + String out = tmpCNF.getAbsolutePath(); + Util.writeAll(out, debugExtractKInput()); + rep.resultCNF(out); + return null; + } + if (opt.solver.equals(SatSolver.CNF)) { + File tmpCNF = File.createTempFile("tmp", ".cnf", new File(opt.tempDirectory)); + String out = tmpCNF.getAbsolutePath(); + solver.options().setSolver(WriteCNF.factory(out)); + try { sol = solver.solve(fgoal, bounds); } catch(WriteCNF.WriteCNFCompleted ex) { rep.resultCNF(out); return null; } + // The formula is trivial (otherwise, it would have thrown an exception) + // Since the user wants it in CNF format, we manually generate a trivially satisfiable (or unsatisfiable) CNF file. + Util.writeAll(out, sol.instance()!=null ? "p cnf 1 1\n1 0\n" : "p cnf 1 2\n1 0\n-1 0\n"); + rep.resultCNF(out); + return null; + } + if (solver.options().solver()==SATFactory.ZChaffMincost || !solver.options().solver().incremental()) { + if (sol==null) sol = solver.solve(fgoal, bounds); + } else { + kEnumerator = new Peeker(solver.solveAll(fgoal, bounds)); + if (sol==null) sol = kEnumerator.next(); + } + if (!solved[0]) rep.solve(0, 0, 0); + final Instance inst = sol.instance(); + // To ensure no more output during SolutionEnumeration + solver.options().setReporter(oldReporter); + // If unsatisfiable, then retreive the unsat core if desired + if (inst==null && solver.options().solver()==SATFactory.MiniSatProver) { + try { + lCore = new LinkedHashSet(); + Proof p = sol.proof(); + if (sol.outcome()==UNSATISFIABLE) { + // only perform the minimization if it was UNSATISFIABLE, rather than TRIVIALLY_UNSATISFIABLE + int i = p.highLevelCore().size(); + rep.minimizing(cmd, i); + if (opt.coreMinimization==0) try { p.minimize(new RCEStrategy(p.log())); } catch(Throwable ex) {} + if (opt.coreMinimization==1) try { p.minimize(new HybridStrategy(p.log())); } catch(Throwable ex) {} + rep.minimized(cmd, i, p.highLevelCore().size()); + } + for(Iterator it=p.core(); it.hasNext();) { + Object n=it.next().node(); + if (n instanceof Formula) lCore.add((Formula)n); + } + Map map = p.highLevelCore(); + hCore = new LinkedHashSet(map.keySet()); + hCore.addAll(map.values()); + } catch(Throwable ex) { + lCore = hCore = null; + } + } + // If satisfiable, then add/rename the atoms and skolems + if (inst!=null) { + eval = new Evaluator(inst, solver.options()); + rename(this, null, null, new UniqueNameGenerator()); + } + // report the result + solved(); + time = System.currentTimeMillis() - time; + if (inst!=null) rep.resultSAT(cmd, time, this); else rep.resultUNSAT(cmd, time, this); + return this; + } + + //===================================================================================================// + + /** This caches the toString() output. */ + private String toStringCache = null; + + /** Dumps the Kodkod solution into String. */ + @Override public String toString() { + if (!solved) return "---OUTCOME---\nUnknown.\n"; + if (eval == null) return "---OUTCOME---\nUnsatisfiable.\n"; + String answer = toStringCache; + if (answer != null) return answer; + Instance sol = eval.instance(); + StringBuilder sb = new StringBuilder(); + sb.append("---INSTANCE---\n" + "integers={"); + boolean firstTuple = true; + for(IndexedEntry e:sol.intTuples()) { + if (firstTuple) firstTuple=false; else sb.append(", "); + // No need to print e.index() since we've ensured the Int atom's String representation is always equal to ""+e.index() + Object atom = e.value().iterator().next().atom(0); + sb.append(atom2name(atom)); + } + sb.append("}\n"); + try { + for(Sig s:sigs) { + sb.append(s.label).append("=").append(eval(s)).append("\n"); + for(Field f:s.getFields()) sb.append(s.label).append("<:").append(f.label).append("=").append(eval(f)).append("\n"); + } + for(ExprVar v:skolems) { + sb.append("skolem ").append(v.label).append("=").append(eval(v)).append("\n"); + } + return toStringCache = sb.toString(); + } catch(Err er) { + return toStringCache = (""); + } + } + + //===================================================================================================// + + /** If nonnull, it caches the result of calling "next()". */ + private A4Solution nextCache = null; + + /** If this solution is UNSAT, return itself; else return the next solution (which could be SAT or UNSAT). + * @throws ErrorAPI if the solver was not an incremental solver + */ + public A4Solution next() throws Err { + if (!solved) throw new ErrorAPI("This solution is not yet solved, so next() is not allowed."); + if (eval==null) return this; + if (nextCache==null) nextCache=new A4Solution(this); + return nextCache; + } + + /** Returns true if this solution was generated by an incremental SAT solver. */ + public boolean isIncremental() { return kEnumerator!=null; } + + //===================================================================================================// + + /** The low-level unsat core; null if it is not available. */ + private LinkedHashSet lCore = null; + + /** This caches the result of lowLevelCore(). */ + private Set lCoreCache = null; + + /** If this solution is unsatisfiable and its unsat core is available, then return the core; else return an empty set. */ + public Set lowLevelCore() { + if (lCoreCache!=null) return lCoreCache; + Set ans1 = new LinkedHashSet(); + if (lCore!=null) for(Node f: lCore) { + Object y = k2pos(f); + if (y instanceof Pos) ans1.add( (Pos)y ); else if (y instanceof Expr) ans1.add( ((Expr)y).span() ); + } + return lCoreCache = Collections.unmodifiableSet(ans1); + } + + //===================================================================================================// + + /** The high-level unsat core; null if it is not available. */ + private LinkedHashSet hCore = null; + + /** This caches the result of highLevelCore(). */ + private Pair,Set> hCoreCache = null; + + /** If this solution is unsatisfiable and its unsat core is available, then return the core; else return an empty set. */ + public Pair,Set> highLevelCore() { + if (hCoreCache!=null) return hCoreCache; + Set ans1 = new LinkedHashSet(), ans2 = new LinkedHashSet(); + if (hCore!=null) for(Node f: hCore) { + Object x = k2pos(f); + if (x instanceof Pos) { + // System.out.println("F: "+f+" at "+x+"\n"); System.out.flush(); + ans1.add((Pos)x); + } else if (x instanceof Expr) { + Expr expr = (Expr)x; + Pos p = ((Expr)x).span(); + ans1.add(p); + // System.out.println("F: "+f+" by "+p.x+","+p.y+"->"+p.x2+","+p.y2+" for "+x+"\n\n"); System.out.flush(); + for(Func func: expr.findAllFunctions()) ans2.add(func.getBody().span()); + } + } + return hCoreCache = new Pair,Set>(Collections.unmodifiableSet(ans1), Collections.unmodifiableSet(ans2)); + } + + //===================================================================================================// + + /** Helper method to write out a full XML file. */ + public void writeXML(String filename) throws Err { + writeXML(filename, null, null); + } + + /** Helper method to write out a full XML file. */ + public void writeXML(String filename, Iterable macros) throws Err { + writeXML(filename, macros, null); + } + + /** Helper method to write out a full XML file. */ + public void writeXML(String filename, Iterable macros, Map sourceFiles) throws Err { + PrintWriter out=null; + try { + out=new PrintWriter(filename,"UTF-8"); + writeXML(out, macros, sourceFiles); + if (!Util.close(out)) throw new ErrorFatal("Error writing the solution XML file."); + } catch(IOException ex) { + Util.close(out); + throw new ErrorFatal("Error writing the solution XML file.", ex); + } + } + + /** Helper method to write out a full XML file. */ + public void writeXML(A4Reporter rep, String filename, Iterable macros, Map sourceFiles) throws Err { + PrintWriter out=null; + try { + out=new PrintWriter(filename,"UTF-8"); + writeXML(rep, out, macros, sourceFiles); + if (!Util.close(out)) throw new ErrorFatal("Error writing the solution XML file."); + } catch(IOException ex) { + Util.close(out); + throw new ErrorFatal("Error writing the solution XML file.", ex); + } + } + + /** Helper method to write out a full XML file. */ + public void writeXML(PrintWriter writer, Iterable macros, Map sourceFiles) throws Err { + A4SolutionWriter.writeInstance(null, this, writer, macros, sourceFiles); + if (writer.checkError()) throw new ErrorFatal("Error writing the solution XML file."); + } + + /** Helper method to write out a full XML file. */ + public void writeXML(A4Reporter rep, PrintWriter writer, Iterable macros, Map sourceFiles) throws Err { + A4SolutionWriter.writeInstance(rep, this, writer, macros, sourceFiles); + if (writer.checkError()) throw new ErrorFatal("Error writing the solution XML file."); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/A4SolutionReader.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/A4SolutionReader.java new file mode 100644 index 00000000..83a998a8 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/A4SolutionReader.java @@ -0,0 +1,314 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.translator; + +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.UNIV; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.SIGINT; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.SEQIDX; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.STRING; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.NONE; +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import kodkod.ast.Relation; +import kodkod.instance.Tuple; +import kodkod.instance.TupleFactory; +import kodkod.instance.TupleSet; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.OurUtil; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.XMLNode; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4compiler.ast.Attr; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.SubsetSig; + +/** This helper class contains helper routines for reading an A4Solution object from an XML file. */ + +public final class A4SolutionReader { + + /** The resulting A4Solution object. */ + private final A4Solution sol; + + /** The provided choices of existing Sig and Field. */ + private final LinkedHashSet choices = new LinkedHashSet(); + + /** Stores the set of atoms. */ + private final TreeSet atoms = new TreeSet(); + + /** Stores the set of STRING atoms. */ + private final TreeSet strings = new TreeSet(); + + /** Maps each Sig/Field/Skolem id to an XMLNode. */ + private final Map nmap = new LinkedHashMap(); + + /** Maps each Sig id to a Sig. */ + private final Map id2sig = new LinkedHashMap(); + + /** Stores the set of all sigs. */ + private final Set allsigs = Util.asSet((Sig)UNIV, SIGINT, SEQIDX, STRING, NONE); + + /** Mapes each expression we've seen to its TupleSet. */ + private final Map expr2ts = new LinkedHashMap(); + + /** The Kodkod tupleset factory. */ + private final TupleFactory factory; + + /** Helper method that returns true if the given attribute value in the given XML node is equal to "yes" */ + private static boolean yes(XMLNode node, String attr) { return node.getAttribute(attr).equals("yes"); } + + /** Helper method that returns an XML node's "label" attribute. */ + private static String label(XMLNode node) { return node.getAttribute("label"); } + + /** Helper method that returns true if the two iterables contain the same elements (though possibly in different order) */ + private static boolean sameset(Iterable a, Iterable b) { + ArrayList tmp=new ArrayList(); + for(Sig x:b) tmp.add(x); + for(Sig x:a) if (tmp.contains(x)) tmp.remove(x); else return false; + return tmp.isEmpty(); + } + + /** Parse tuple. */ + private Tuple parseTuple(XMLNode tuple, int arity) throws Err { + Tuple ans = null; + try { + for(XMLNode sub:tuple) if (sub.is("atom")) { + Tuple x = factory.tuple(sub.getAttribute("label")); + if (ans==null) ans=x; else ans=ans.product(x); + } + if (ans==null) throw new ErrorFatal("Expecting: .. "); + if (ans.arity()!=arity) throw new ErrorFatal("Expecting: tuple of arity "+arity+" but got tuple of arity "+ans.arity()); + return ans; + } catch(Throwable ex) { + throw new ErrorFatal("Expecting: .. ", ex); + } + } + + /** Parse tuples. */ + private TupleSet parseTuples(XMLNode tuples, int arity) throws Err { + TupleSet ans = factory.noneOf(arity); + for(XMLNode sub:tuples) if (sub.is("tuple")) ans.add(parseTuple(sub, arity)); + return ans; + } + + /** Parse sig/set. */ + private Sig parseSig(String id, int depth) throws IOException, Err { + Sig ans = id2sig.get(id); + if (ans!=null) return ans; + XMLNode node = nmap.get(id); + if (node==null) throw new IOException("Unknown SigID "+id+" encountered."); + if (!node.is("sig")) throw new IOException("ID "+id+" is not a sig."); + String label = label(node); + Attr isAbstract = yes(node,"abstract") ? Attr.ABSTRACT : null; + Attr isOne = yes(node,"one") ? Attr.ONE : null; + Attr isLone = yes(node,"lone") ? Attr.LONE : null; + Attr isSome = yes(node,"some") ? Attr.SOME : null; + Attr isPrivate = yes(node,"private") ? Attr.PRIVATE : null; + Attr isMeta = yes(node,"meta") ? Attr.META : null; + Attr isEnum = yes(node,"enum") ? Attr.ENUM : null; + Attr isExact = yes(node,"exact") ? Attr.EXACT : null; + if (yes(node,"builtin")) { + if (label.equals(UNIV.label)) { id2sig.put(id, UNIV); return UNIV; } + if (label.equals(SIGINT.label)) { id2sig.put(id, SIGINT); return SIGINT; } + if (label.equals(SEQIDX.label)) { id2sig.put(id, SEQIDX); return SEQIDX; } + if (label.equals(STRING.label)) { id2sig.put(id, STRING); return STRING; } + throw new IOException("Unknown builtin sig: "+label+" (id="+id+")"); + } + if (depth > nmap.size()) throw new IOException("Sig "+label+" (id="+id+") is in a cyclic inheritance relationship."); + List parents = null; + TupleSet ts = factory.noneOf(1); + for(XMLNode sub:node) { + if (sub.is("atom")) { ts.add(factory.tuple(sub.getAttribute("label"))); continue; } + if (!sub.is("type")) continue; + Sig parent = parseSig(sub.getAttribute("ID"), depth+1); + if (parents==null) parents = new ArrayList(); + parents.add(parent); + } + if (parents==null) { + String parentID = node.getAttribute("parentID"); + Sig parent = parseSig(parentID, depth+1); + if (!(parent instanceof PrimSig)) throw new IOException("Parent of sig "+label+" (id="+id+") must not be a subset sig."); + for(Expr choice: choices) + if (choice instanceof PrimSig && parent==((PrimSig)choice).parent && ((Sig)choice).label.equals(label)) + { ans=(Sig)choice; choices.remove(choice); break; } + if (ans==null) { + ans = new PrimSig(label, (PrimSig)parent, isAbstract, isLone, isOne, isSome, isPrivate, isMeta, isEnum); + allsigs.add(ans); + } + } else { + for(Expr choice:choices) + if (choice instanceof SubsetSig && ((Sig)choice).label.equals(label) && sameset(parents, ((SubsetSig)choice).parents)) + { ans=(Sig)choice; choices.remove(choice); break; } + if (ans==null) { + ans = new SubsetSig(label, parents, isExact, isLone, isOne, isSome, isPrivate, isMeta); + allsigs.add(ans); + } + } + id2sig.put(id, ans); + expr2ts.put(ans, ts); + if (ans instanceof PrimSig) { + // Add the atoms in this SIG into all parent sigs + for(PrimSig ans2 = ((PrimSig)ans).parent; ans2!=null && !ans2.builtin; ans2 = ans2.parent) { + TupleSet ts2 = expr2ts.get(ans2); + if (ts2==null) ts2 = ts.clone(); else { ts2 = ts2.clone(); ts2.addAll(ts); } + expr2ts.put(ans2, ts2); + } + } + return ans; + } + + /** Parse type. */ + private Expr parseType(XMLNode node) throws IOException, Err { + Expr expr = null; + if (!node.is("types")) throw new IOException("... expected"); + for(XMLNode n:node) if (n.is("type")) { + Sig sig=parseSig(n.getAttribute("ID"), 0); + if (expr==null) expr=sig; else expr=expr.product(sig); + } + if (expr==null) throw new IOException(" expected"); + return expr; + } + + /** Parse field. */ + private Field parseField(String id) throws IOException, Err { + final XMLNode node = nmap.get(id); + if (node==null) throw new IOException("Unknown FieldID "+id+" encountered."); + if (!node.is("field")) throw new IOException("ID "+id+" is not a field."); + String label = label(node); + Pos isPrivate = yes(node,"private") ? Pos.UNKNOWN : null; + Pos isMeta = yes(node,"meta") ? Pos.UNKNOWN : null; + Expr type = null; + for(XMLNode sub:node) if (sub.is("types")) { Expr t=parseType(sub); if (type==null) type=t; else type=type.plus(t); } + int arity; + if (type==null || (arity=type.type().arity())<2) throw new IOException("Field "+label+" is maltyped."); + String parentID = node.getAttribute("parentID"); + Sig parent = id2sig.get(parentID); + if (parent==null) throw new IOException("ID "+parentID+" is not a sig."); + Field field = null; + for(Field f: parent.getFields()) + if (f.label.equals(label) && f.type().arity()==arity && choices.contains(f)) + { field=f; choices.remove(f); break; } + if (field==null) field = parent.addTrickyField(Pos.UNKNOWN, isPrivate, null, null, isMeta, new String[] {label}, UNIV.join(type)) [0]; + TupleSet ts = parseTuples(node, arity); + expr2ts.put(field, ts); + return field; + } + + /** Parse skolem. */ + private ExprVar parseSkolem(String id) throws IOException, Err { + final XMLNode node = nmap.get(id); + if (node==null) throw new IOException("Unknown ID "+id+" encountered."); + if (!node.is("skolem")) throw new IOException("ID "+id+" is not a skolem."); + String label = label(node); + Expr type = null; + for(XMLNode sub:node) if (sub.is("types")) { Expr t=parseType(sub); if (type==null) type=t; else type=type.plus(t); } + int arity; + if (type==null || (arity=type.type().arity())<1) throw new IOException("Skolem "+label+" is maltyped."); + ExprVar var = ExprVar.make(Pos.UNKNOWN, label, type.type()); + TupleSet ts = parseTuples(node, arity); + expr2ts.put(var, ts); + return var; + } + + /** Parse everything. */ + private A4SolutionReader(Iterable sigs, XMLNode xml) throws IOException, Err { + for(Sig s:sigs) if (!s.builtin) { + allsigs.add(s); + choices.add(s); + for(Field f:s.getFields()) choices.add(f); + } + // find .. + if (!xml.is("alloy")) throw new ErrorSyntax("The XML file's root node must be or ."); + XMLNode inst = null; + for(XMLNode sub: xml) if (sub.is("instance")) { inst=sub; break; } + if (inst==null) throw new ErrorSyntax("The XML file must contain an element."); + // set up the basic values of the A4Solution object + final int bitwidth = Integer.parseInt(inst.getAttribute("bitwidth")); + final int maxseq = Integer.parseInt(inst.getAttribute("maxseq")); + final int max = Util.max(bitwidth), min = Util.min(bitwidth); + if (bitwidth>=1 && bitwidth<=30) for(int i=min; i<=max; i++) { atoms.add(Integer.toString(i)); } + for(XMLNode x:inst) { + String id=x.getAttribute("ID"); + if (id.length()>0 && (x.is("field") || x.is("skolem") || x.is("sig"))) { + if (nmap.put(id, x)!=null) throw new IOException("ID "+id+" is repeated."); + if (x.is("sig")) { + boolean isString = STRING.label.equals(label(x)) && yes(x, "builtin"); + for(XMLNode y:x) if (y.is("atom")) { + String attr = y.getAttribute("label"); + atoms.add(attr); + if (isString) strings.add(attr); + } + } + } + } + // create the A4Solution object + A4Options opt = new A4Options(); + opt.originalFilename = inst.getAttribute("filename"); + sol = new A4Solution(inst.getAttribute("command"), bitwidth, maxseq, strings, atoms, null, opt, 1); + factory = sol.getFactory(); + // parse all the sigs, fields, and skolems + for(Map.Entry e:nmap.entrySet()) if (e.getValue().is("sig")) parseSig(e.getKey(), 0); + for(Map.Entry e:nmap.entrySet()) if (e.getValue().is("field")) parseField(e.getKey()); + for(Map.Entry e:nmap.entrySet()) if (e.getValue().is("skolem")) parseSkolem(e.getKey()); + for(Sig s:allsigs) if (!s.builtin) { + TupleSet ts = expr2ts.remove(s); + if (ts==null) ts = factory.noneOf(1); // If the sig was NOT mentioned in the XML file... + Relation r = sol.addRel(s.label, ts, ts); + sol.addSig(s, r); + for(Field f: s.getFields()) { + ts = expr2ts.remove(f); + if (ts==null) ts=factory.noneOf(f.type().arity()); // If the field was NOT mentioned in the XML file... + r = sol.addRel(s.label+"."+f.label, ts, ts); + sol.addField(f, r); + } + } + for(Map.Entry e:expr2ts.entrySet()) { + ExprVar v = (ExprVar)(e.getKey()); + TupleSet ts = e.getValue(); + Relation r = sol.addRel(v.label, ts, ts); + sol.kr2type(r, v.type()); + } + // Done! + sol.solve(null, null, null, false); + } + + /** Parse the XML element into an AlloyInstance. + * + *

The list of sigs, if not null, will be used as the sigs (and their fields) that we expect to exist; + *
if there's a sig or field X in the list but not in the XML, then X's tupleset will be regarded as empty; + *
if there's a sig or field X in the XML but not in the list, then X (and its value in XML file) is added to the solution. + */ + public static A4Solution read(Iterable sigs, XMLNode xml) throws Err { + try { + if (sigs == null) sigs = new ArrayList(); + A4SolutionReader x = new A4SolutionReader(sigs, xml); + return x.sol; + } catch(Throwable ex) { + if (ex instanceof Err) throw ((Err)ex); else throw new ErrorFatal("Fatal error occured: "+ex, ex); + } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/A4SolutionWriter.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/A4SolutionWriter.java new file mode 100644 index 00000000..28ab378d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/A4SolutionWriter.java @@ -0,0 +1,233 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.translator; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorAPI; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import edu.mit.csail.sdg.alloy4compiler.ast.Func; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Type; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.SubsetSig; + +/** This helper class contains helper routines for writing an A4Solution object out as an XML file. */ + +public final class A4SolutionWriter { + + /** Maps each Sig, Field, and Skolem to a unique id. */ + private final IdentityHashMap map = new IdentityHashMap(); + + /** This is the solution we're writing out. */ + private final A4Solution sol; + + /** This is the A4Reporter that we're sending diagnostic messages to; can be null if none. */ + private final A4Reporter rep; + + /** This is the list of toplevel sigs. */ + private final List toplevels = new ArrayList(); + + /** This is the output file. */ + private final PrintWriter out; + + /** Helper method that returns a unique id for the given Sig, Field, or Skolem. */ + private String map(Expr obj) { + String id = map.get(obj); + if (id==null) { id=Integer.toString(map.size()); map.put(obj, id); } + return id; + } + + /** Helper method that returns the list of direct subsignatures. */ + private Iterable children(PrimSig x) throws Err { + if (x==Sig.NONE) return new ArrayList(); + if (x!=Sig.UNIV) return x.children(); else return toplevels; + } + + /** Write the given Expr and its Type. */ + private boolean writeExpr(String prefix, Expr expr) throws Err { + Type type = expr.type(); + if (!type.hasTuple()) return false; + if (sol!=null) { + // Check to see if the tupleset is *really* fully contained inside "type". + // If not, then grow "type" until the tupleset is fully contained inside "type" + Expr sum = type.toExpr(); + int lastSize = (-1); + while(true) { + A4TupleSet ts = (A4TupleSet)(sol.eval(expr.minus(sum))); + int n = ts.size(); + if (n<=0) break; + if (lastSize>0 && lastSize<=n) throw new ErrorFatal("An internal error occurred in the evaluator."); + lastSize=n; + Type extra = ts.iterator().next().type(); + type = type.merge(extra); + sum = sum.plus(extra.toExpr()); + } + // Now, write out the tupleset + A4TupleSet ts = (A4TupleSet)(sol.eval(expr)); + for(A4Tuple t: ts) { + if (prefix.length()>0) { out.print(prefix); prefix=""; } + out.print(" "); + for(int i=0; i"); + out.print(" \n"); + } + } + // Now, write out the type + if (prefix.length()>0) return false; + for(List ps: type.fold()) { + out.print(" "); + for(PrimSig sig: ps) Util.encodeXMLs(out, " "); + out.print(" \n"); + } + return true; + } + + /** Write the given Sig. */ + private A4TupleSet writesig(final Sig x) throws Err { + A4TupleSet ts = null, ts2 = null; + if (x==Sig.NONE) return null; // should not happen, but we test for it anyway + if (sol==null && x.isMeta!=null) return null; // When writing the metamodel, skip the metamodel sigs! + if (x instanceof PrimSig) for(final PrimSig sub:children((PrimSig)x)) { + A4TupleSet ts3 = writesig(sub); + if (ts2==null) ts2 = ts3; else ts2 = ts2.plus(ts3); + } + if (rep!=null) rep.write(x); + Util.encodeXMLs(out, "\n\n"); + try { + if (sol!=null && x!=Sig.UNIV && x!=Sig.SIGINT && x!=Sig.SEQIDX) { + ts = (A4TupleSet)(sol.eval(x)); + for(A4Tuple t: ts.minus(ts2)) Util.encodeXMLs(out, " \n"); + } + } catch(Throwable ex) { + throw new ErrorFatal("Error evaluating sig " + x.label, ex); + } + if (x instanceof SubsetSig) for(Sig p:((SubsetSig)x).parents) Util.encodeXMLs(out, " \n"); + out.print("\n"); + for(Field field: x.getFields()) writeField(field); + return ts; + } + + /** Write the given Field. */ + private void writeField(Field x) throws Err { + try { + if (sol==null && x.isMeta!=null) return; // when writing the metamodel, skip the metamodel fields! + if (x.type().hasNoTuple()) return; // we do not allow "none" in the XML file's type declarations + if (rep!=null) rep.write(x); + Util.encodeXMLs(out, "\n\n"); + writeExpr("", x); + out.print("\n"); + } catch(Throwable ex) { + throw new ErrorFatal("Error evaluating field "+x.sig.label+"."+x.label, ex); + } + } + + /** Write the given Skolem. */ + private void writeSkolem(ExprVar x) throws Err { + try { + if (sol==null) return; // when writing a metamodel, skip the skolems + if (x.type().hasNoTuple()) return; // we do not allow "none" in the XML file's type declarations + StringBuilder sb = new StringBuilder(); + Util.encodeXMLs(sb, "\n\n"); + if (writeExpr(sb.toString(), x)) { out.print("\n"); } + } catch(Throwable ex) { + throw new ErrorFatal("Error evaluating skolem "+x.label, ex); + } + } + + /** If sol==null, write the list of Sigs as a Metamodel, else write the solution as an XML file. */ + private A4SolutionWriter(A4Reporter rep, A4Solution sol, Iterable sigs, int bitwidth, int maxseq, String originalCommand, String originalFileName, PrintWriter out, Iterable extraSkolems) throws Err { + this.rep = rep; + this.out = out; + this.sol = sol; + for (Sig s:sigs) if (s instanceof PrimSig && ((PrimSig)s).parent==Sig.UNIV) toplevels.add((PrimSig)s); + out.print("\n"); + writesig(Sig.UNIV); + for (Sig s:sigs) if (s instanceof SubsetSig) writesig(s); + if (sol!=null) for (ExprVar s:sol.getAllSkolems()) { if (rep!=null) rep.write(s); writeSkolem(s); } + int m=0; + if (sol!=null && extraSkolems!=null) for(Func f:extraSkolems) if (f.count()==0 && f.call().type().hasTuple()) { + String label = f.label; + while(label.length()>0 && label.charAt(0)=='$') label=label.substring(1); + label="$"+label; + try { + if (rep!=null) rep.write(f.call()); + StringBuilder sb = new StringBuilder(); + Util.encodeXMLs(sb, "\n\n"); + if (writeExpr(sb.toString(), f.call())) { out.print("\n"); } + m++; + } catch(Throwable ex) { + throw new ErrorFatal("Error evaluating skolem "+label, ex); + } + } + out.print("\n\n"); + } + + /** If this solution is a satisfiable solution, this method will write it out in XML format. */ + static void writeInstance(A4Reporter rep, A4Solution sol, PrintWriter out, Iterable extraSkolems, Map sources) throws Err { + if (!sol.satisfiable()) throw new ErrorAPI("This solution is unsatisfiable."); + try { + Util.encodeXMLs(out, "\n\n"); + new A4SolutionWriter(rep, sol, sol.getAllReachableSigs(), sol.getBitwidth(), sol.getMaxSeq(), sol.getOriginalCommand(), sol.getOriginalFilename(), out, extraSkolems); + if (sources!=null) for(Map.Entry e: sources.entrySet()) { + Util.encodeXMLs(out, "\n\n"); + } + out.print("\n\n"); + } catch(Throwable ex) { + if (ex instanceof Err) throw (Err)ex; else throw new ErrorFatal("Error writing the solution XML file.", ex); + } + if (out.checkError()) throw new ErrorFatal("Error writing the solution XML file."); + } + + /** Write the metamodel as <instance>..</instance> in XML format. */ + public static void writeMetamodel(ConstList sigs, String originalFilename, PrintWriter out) throws Err { + try { + new A4SolutionWriter(null, null, sigs, 4, 4, "show metamodel", originalFilename, out, null); + } catch(Throwable ex) { + if (ex instanceof Err) throw (Err)ex; else throw new ErrorFatal("Error writing the solution XML file.", ex); + } + if (out.checkError()) throw new ErrorFatal("Error writing the solution XML file."); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/A4Tuple.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/A4Tuple.java new file mode 100644 index 00000000..b4b6f91b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/A4Tuple.java @@ -0,0 +1,65 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.translator; + +import edu.mit.csail.sdg.alloy4compiler.ast.Type; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; +import kodkod.instance.Tuple; + +/** Immutable; represents a single Alloy tuple; comparison is by identity rather than by value. */ + +public final class A4Tuple { + + /** The Kodkod tuple. */ + private final Tuple tuple; + + /** The A4Solution that this came from. */ + private final A4Solution sol; + + /** Construct a Tuple from the kodkod Tuple, while renaming each atom using the atom2name map in sol. + *
NOTE: caller must ensure the Kodkod tuple is not modified, since we expect the resulting A4Tuple to be constant. + */ + A4Tuple(Tuple tuple, A4Solution sol) { + this.tuple = tuple; + this.sol = sol; + } + + /** Returns the arity. */ + public int arity() { return tuple.arity(); } + + /** Returns the type constructed by taking the product for each sig in this tuple. */ + public Type type() { + Type ans = null; + for(int i=0; i0) sb.append("->"); + sb.append(atom(i)); + } + return sb.toString(); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/A4TupleSet.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/A4TupleSet.java new file mode 100644 index 00000000..5ced6fed --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/A4TupleSet.java @@ -0,0 +1,116 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.translator; + +import java.util.Iterator; +import java.util.NoSuchElementException; +import edu.mit.csail.sdg.alloy4.ErrorAPI; +import kodkod.instance.Tuple; +import kodkod.instance.TupleSet; + +/** Immutable; represents a collection of Alloy tuples; comparison is by identity rather than by value. */ + +public final class A4TupleSet implements Iterable { + + /** The Kodkod tupleset. */ + private final TupleSet tuples; + + /** The A4Solution that this came from. */ + private final A4Solution sol; + + /** Construct a TupleSet from the kodkod TupleSet, while renaming each atom using the atom2name map in sol. + *
NOTE: caller must ensure the Kodkod tupleset is not modified, since we expect the resulting A4Tupleset to be constant. + */ + A4TupleSet(TupleSet tuples, A4Solution sol) { + this.tuples = tuples; + this.sol = sol; + } + + /** Return the underlying Kodkod tupleset. */ + public TupleSet debugGetKodkodTupleset() { return tuples.clone(); } + + /** Returns a read-only iterator that iterates over each tuple in this TupleSet. */ + public Iterator iterator() { + return new Iterator() { + private final Iterator it = tuples.iterator(); + public final boolean hasNext() { return it.hasNext(); } + public final A4Tuple next() { + if (!it.hasNext()) throw new NoSuchElementException(); + return new A4Tuple(it.next(), sol); + } + public final void remove() { throw new UnsupportedOperationException(); } + }; + } + + /** Returns the arity. */ + public int arity() { return tuples.arity(); } + + /** Returns the number of tuples in this tuple set. */ + public int size() { return tuples.size(); } + + /** Construct a new tupleset as the product of this and that; this and that must be come from the same solution. */ + public A4TupleSet product(A4TupleSet that) throws ErrorAPI { + if (sol != that.sol) throw new ErrorAPI("A4TupleSet.product() requires 2 tuplesets from the same A4Solution."); + return new A4TupleSet(tuples.product(that.tuples), sol); + } + + /** Construct a new tupleset as the union of this and that; this and that must be come from the same solution. + * Note: if that==null, then the method returns this A4TupleSet as-is. */ + public A4TupleSet plus(A4TupleSet that) throws ErrorAPI { + if (that==null) return this; + if (sol != that.sol) throw new ErrorAPI("A4TupleSet.plus() requires 2 tuplesets from the same A4Solution."); + if (arity() != that.arity()) throw new ErrorAPI("A4TupleSet.plus() requires 2 tuplesets with the same arity."); + if (this==that || tuples.size()==0) return that; else if (that.tuples.size()==0) return this; // special short cut + TupleSet ts = tuples.clone(); + ts.addAll(that.tuples); + if (tuples.size()==ts.size()) return this; + if (that.tuples.size()==ts.size()) return that; + return new A4TupleSet(ts, sol); + } + + /** Construct a new tupleset as the subtraction of this and that; this and that must be come from the same solution. + * Note: if that==null, then the method returns this A4TupleSet as-is. */ + public A4TupleSet minus(A4TupleSet that) throws ErrorAPI { + if (that==null) return this; + if (sol != that.sol) throw new ErrorAPI("A4TupleSet.minus() requires 2 tuplesets from the same A4Solution."); + if (arity() != that.arity()) throw new ErrorAPI("A4TupleSet.minus() requires 2 tuplesets with the same arity."); + if (tuples.size()==0 || that.tuples.size()==0) return this; // special short cut + TupleSet ts = tuples.clone(); + ts.removeAll(that.tuples); + if (tuples.size()!=ts.size()) return new A4TupleSet(ts, sol); else return this; + } + + /** Construct a new tupleset as the intersection of this and that; this and that must be come from the same solution. */ + public A4TupleSet intersect(A4TupleSet that) throws ErrorAPI { + if (sol != that.sol) throw new ErrorAPI("A4TupleSet.intersect() requires 2 tuplesets from the same A4Solution."); + if (arity() != that.arity()) throw new ErrorAPI("A4TupleSet.intersect() requires 2 tuplesets with the same arity."); + if (this.tuples.size()==0) return this; // special short cut + if (that.tuples.size()==0) return that; // special short cut + TupleSet ts = tuples.clone(); + ts.retainAll(that.tuples); + if (tuples.size()!=ts.size()) return new A4TupleSet(ts, sol); else return this; + } + + /** Prints a human-readable description of this TupleSet. */ + @Override public String toString() { + StringBuilder sb=new StringBuilder("{"); + for(A4Tuple t:this) { + if (sb.length()>1) sb.append(", "); + sb.append(t); + } + return sb.append('}').toString(); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/BookExamples.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/BookExamples.java new file mode 100644 index 00000000..17da3a0b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/BookExamples.java @@ -0,0 +1,374 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.translator; + +import static kodkod.engine.Solution.Outcome.SATISFIABLE; +import static kodkod.engine.Solution.Outcome.TRIVIALLY_SATISFIABLE; +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; +import kodkod.ast.BinaryExpression; +import kodkod.ast.Formula; +import kodkod.ast.Relation; +import kodkod.ast.Expression; +import kodkod.engine.Solver; +import kodkod.engine.Solution; +import kodkod.engine.satlab.SATFactory; +import kodkod.instance.Bounds; +import kodkod.instance.Tuple; +import kodkod.instance.TupleFactory; +import kodkod.instance.TupleSet; + +/** Immutable; this class stores the set of solutions from the book, for teaching purpose, + * so that users of the tool will see the same illustration as the book and not get confused by SAT solver nondeterminism. + */ + +final class BookExamples { + + // It calls the following methods on a bounds-computed A4Solution object: + // getAllReachableSigs(), getFactory(), getBounds(), a2k(), kr2typeCLEAR() + + /** Returns the Sig if the list of sig contains a sig with the given label, else returns null. */ + private static Sig hasSig (Iterable sigs, String label) { + for(Sig s:sigs) if (s.label.equals(label)) return s; + return null; + } + + /** If one of the solution is a solution to the given problem, return it, else return null. */ + static Solution trial (A4Reporter rep, A4Solution frame, Formula formula, Solver solver, boolean check) { + TupleFactory fac = frame.getFactory(); + Solution sol = null; + Iterable sigs = frame.getAllReachableSigs(); + if (hasSig(sigs, "this/Book")!=null) { + Tuple B0N0A0 = t_tuple(fac, "Book$0", "Name$0", "Addr$0"); + Tuple B0N1A0 = t_tuple(fac, "Book$0", "Name$1", "Addr$0"); + Tuple B0N2A0 = t_tuple(fac, "Book$0", "Name$2", "Addr$0"); + Tuple B0N2A1 = t_tuple(fac, "Book$0", "Name$2", "Addr$1"); + Tuple B0N1A1 = t_tuple(fac, "Book$0", "Name$1", "Addr$1"); + Tuple B1N0A0 = t_tuple(fac, "Book$1", "Name$0", "Addr$0"); + Tuple B1N2A1 = t_tuple(fac, "Book$1", "Name$2", "Addr$1"); + Tuple B1N1A1 = t_tuple(fac, "Book$1", "Name$1", "Addr$1"); + Tuple B000 = t_tuple(fac, "Book$0", "Target$0", "Target$0"); + Tuple B001 = t_tuple(fac, "Book$0", "Target$0", "Target$1"); + Tuple B002 = t_tuple(fac, "Book$0", "Target$0", "Target$2"); + Tuple B010 = t_tuple(fac, "Book$0", "Target$1", "Target$0"); + Tuple B101 = t_tuple(fac, "Book$1", "Target$0", "Target$1"); + Tuple B110 = t_tuple(fac, "Book$1", "Target$1", "Target$0"); + Tuple B102 = t_tuple(fac, "Book$1", "Target$0", "Target$2"); + Tuple B210 = t_tuple(fac, "Book$2", "Target$1", "Target$0"); + Tuple B202 = t_tuple(fac, "Book$2", "Target$0", "Target$2"); + Tuple B212 = t_tuple(fac, "Book$2", "Target$1", "Target$2"); + Tuple B302 = t_tuple(fac, "Book$3", "Target$0", "Target$2"); + Tuple B310 = t_tuple(fac, "Book$3", "Target$1", "Target$0"); + Tuple B312 = t_tuple(fac, "Book$3", "Target$1", "Target$2"); + if (sol==null && B000!=null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 2.9", + "Book$0", "", "this/Book", "", + "Target$0", "", "this/Alias", "", + "", "this/Group", "", + "", "this/Addr", "", + B000, "", "this/Book", "addr", + }); + if (sol==null && B001!=null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 2.10", + "Book$0", "", "this/Book", "", + "", "this/Alias", "", + "Target$0", "", "this/Group", "", + "Target$1", "Target$2", "", "this/Addr", "", + B001, B002, "", "this/Book", "addr", + }); + if (sol==null && B001!=null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 2.11", + "Book$0", "", "this/Book", "", + "Target$0", "", "this/Alias", "", + "", "this/Group", "", + "Target$1", "Target$2", "", "this/Addr", "", + B001, B002, "", "this/Book", "addr", + }); + if (sol==null && B001!=null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 2.12", + "Book$0", "", "this/Book", "", + "Target$0", "", "this/Alias", "", + "Target$1", "", "this/Group", "", + "", "this/Addr", "", + B001, "", "this/Book", "addr", + }); + if (sol==null && B010!=null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 2.13", + "Book$0", "Book$1", "", "this/Book", "", + "", "this/Alias", "", + "Target$0", "Target$1", "", "this/Group", "", + "Target$2", "", "this/Addr", "", + B010, B110, B102, "", "this/Book", "addr", + }); + if (sol==null && B312!=null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 2.15", + "Book$0", "Book$1", "Book$2", "Book$3", "", "this/Book", "", + "", "this/Alias", "", + "Target$0", "Target$1", "", "this/Group", "", + "Target$2", "", "this/Addr", "", + B102, B210, B202, B212, B302, B312, "", "this/Book", "addr", + }); + if (sol==null && B101!=null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 2.16", + "Book$0", "Book$1", "Book$2", "Book$3", "", "this/Book", "", + "Target$1", "", "this/Alias", "", + "Target$0", "", "this/Group", "", + "", "this/Addr", "", + B101, "", "this/Book", "addr", + }); + if (sol==null && B102!=null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 2.17", + "Book$0", "Book$1", "Book$2", "Book$3", "", "this/Book", "", + "Target$0", "", "this/Alias", "", + "Target$1", "", "this/Group", "", + "Target$2", "", "this/Addr", "", + B102, B210, B310, B302, "", "this/Book", "addr", + }); + if (sol==null && B0N0A0!=null && check) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 2.6", + "Book$0", "Book$1", "", "this/Book", "", + "Addr$0", "", "this/Addr", "", + "Name$0", "", "this/Name", "", + B0N0A0, "", "this/Book", "addr", + }); + if (sol==null && B1N0A0!=null && !check) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 2.4", + "Book$0", "Book$1", "", "this/Book", "", + "Addr$0", "", "this/Addr", "", + "Name$0", "", "this/Name", "", + B1N0A0, "", "this/Book", "addr", + }); + if (sol==null && B0N2A1!=null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 2.5", + "Book$0", "Book$1", "", "this/Book", "", + "Addr$0", "Addr$1", "", "this/Addr", "", + "Name$0", "Name$1", "Name$2", "", "this/Name", "", + B0N2A1, B0N1A1, B1N2A1, B1N1A1, B1N0A0, "", "this/Book", "addr", + }); + if (sol==null && B0N0A0!=null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 2.1", + "Book$0", "", "this/Book", "", + "Addr$0", "", "this/Addr", "", + "Name$0", "", "this/Name", "", + B0N0A0, "", "this/Book", "addr", + }); + if (sol==null && B0N0A0!=null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 2.2", + "Book$0", "", "this/Book", "", + "Addr$0", "", "this/Addr", "", + "Name$0", "Name$1", "Name$2", "", "this/Name", "", + B0N0A0, B0N1A0, B0N2A0, "", "this/Book", "addr", + }); + if (sol==null && B0N0A0!=null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 2.3", + "Book$0", "", "this/Book", "", + "Addr$0", "Addr$1", "", "this/Addr", "", + "Name$0", "Name$1", "Name$2", "", "this/Name", "", + B0N0A0, B0N1A0, B0N2A1, "", "this/Book", "addr", + }); + if (sol==null && B001!=null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 5.2", + "Book$0", "Book$1", "", "this/Book", "", + "Target$0", "", "this/Name", "", + "Target$1", "", "this/Addr", "", + B001, B101, "", "this/Book", "addr", + }); + if (sol==null && B102!=null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 5.3", + "Book$0", "Book$1", "", "this/Book", "", + "Target$0", "Target$1", "", "this/Name", "", + "Target$2", "", "this/Addr", "", + B010, B110, B102, "", "this/Book", "addr", + }); + } + else if (hasSig(sigs, "this/Woman")!=null) { + Tuple man0_woman0 = t_tuple(fac, "Person$1", "Person$0"); + Tuple man1_woman0 = t_tuple(fac, "Person$2", "Person$0"); + Tuple man0_woman1 = t_tuple(fac, "Person$1", "Person$3"); + Tuple man1_woman1 = t_tuple(fac, "Person$2", "Person$3"); + if (sol==null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 4.2", + "Person$1", "", "this/Man", "", + "Person$0", "", "this/Woman", "", + man0_woman0, "", "this/Man", "wife", + man0_woman0, "", "this/Person", "mother", + "", "this/Person", "father", + }); + if (sol==null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 4.3", + "Person$1", "Person$2", "", "this/Man", "", + "Person$0", "Person$3", "", "this/Woman", "", + man1_woman0, man0_woman1, "", "this/Man", "wife", + man1_woman1, man0_woman0, "", "this/Person", "mother", + "", "this/Person", "father", + }); + } + else if (hasSig(sigs, "this/Process")!=null) { + String p0="Process$0", p1="Process$1", p2="Process$2"; + String t0="Time$0", t1="Time$1", t2="Time$2", t3="Time$3"; + Tuple s20=t_tuple(fac,p2,p0), s01=t_tuple(fac,p0,p1), s12=t_tuple(fac,p1,p2); + Tuple d000=t_tuple(fac,p0,p0,t0), d110=t_tuple(fac,p1,p1,t0), d220=t_tuple(fac,p2,p2,t0); + Tuple d001=t_tuple(fac,p0,p0,t1), d021=t_tuple(fac,p0,p2,t1), d111=t_tuple(fac,p1,p1,t1); + Tuple d002=t_tuple(fac,p0,p0,t2), d112=t_tuple(fac,p1,p1,t2), d122=t_tuple(fac,p1,p2,t2); + Tuple d003=t_tuple(fac,p0,p0,t3), d113=t_tuple(fac,p1,p1,t3), d223=t_tuple(fac,p2,p2,t3); + if (sol==null && d000!=null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 6.4", + s20, s01, s12, "", "this/Process", "succ", + d000,d110,d220,d001,d021,d111,d002,d112,d122,d003,d113,d223,"","this/Process","toSend", + t_tuple(fac,p2,t3),"","this/Process","elected", + }); + } + else if (hasSig(sigs, "this/Desk")!=null) { + String g0="Guest$0", g1="Guest$1", r="Room$0", k0="Key$0", k1="Key$1"; + String t0="Time$0", t1="Time$1", t2="Time$2", t3="Time$3", t4="Time$4", t5="Time$5"; + String c0="Card$0", c1="Card$1"; + if (sol==null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig E.3", + t_tuple(fac,c0,k0), t_tuple(fac,c1,k1), "", "this/Card", "fst", + t_tuple(fac,c0,k1), t_tuple(fac,c1,k0), "", "this/Card", "snd", + t_tuple(fac,g0,c0,t1), + t_tuple(fac,g0,c0,t2), t_tuple(fac,g1,c1,t2), + t_tuple(fac,g0,c0,t3), t_tuple(fac,g1,c1,t3), + t_tuple(fac,g0,c0,t4), t_tuple(fac,g1,c1,t4), + t_tuple(fac,g0,c0,t5), t_tuple(fac,g1,c1,t5), "", "this/Guest", "cards", + t_tuple(fac,r,k0,t0), t_tuple(fac,r,k0,t1), t_tuple(fac,r,k0,t2), + t_tuple(fac,r,k1,t3), t_tuple(fac,r,k0,t4), t_tuple(fac,r,k1,t5), "", "this/Room", "key", + t_tuple(fac,k1,t1), + t_tuple(fac,k0,t2), t_tuple(fac,k1,t2), + t_tuple(fac,k0,t3), t_tuple(fac,k1,t3), + t_tuple(fac,k0,t4), t_tuple(fac,k1,t4), + t_tuple(fac,k0,t5), t_tuple(fac,k1,t5), "", "this/Desk", "issued", + t_tuple(fac,r,k0,t0), t_tuple(fac,r,k1,t1), t_tuple(fac,r,k0,t2), + t_tuple(fac,r,k0,t3), t_tuple(fac,r,k0,t4), t_tuple(fac,r,k0,t5), "", "this/Desk", "prev" + }); + } + else if (hasSig(sigs, "this/FrontDesk")!=null) { + String g0="Guest$0", g1="Guest$1", r="Room$0", k0="Key$0", k1="Key$1", k2="Key$2"; + String t0="Time$0", t1="Time$1", t2="Time$2", t3="Time$3", t4="Time$4"; + Tuple G0=t_tuple(fac,g0), G1=t_tuple(fac,g1); + Tuple K0=t_tuple(fac,r,k0), K1=t_tuple(fac,r,k1), K2=t_tuple(fac,r,k2); + Tuple K0T0=t_tuple(fac,r,k0,t0), K0T1=t_tuple(fac,r,k0,t1), K0T2=t_tuple(fac,r,k0,t2); + Tuple K0T3=t_tuple(fac,r,k0,t3), K1T4=t_tuple(fac,r,k1,t4); + Tuple F1=t_tuple(fac,r,k0,t0), F2=t_tuple(fac,r,k1,t1), F3=t_tuple(fac,r,k1,t2); + Tuple F4=t_tuple(fac,r,k2,t3), F5=t_tuple(fac,r,k2,t4); + Tuple GK1=t_tuple(fac,g0,k1,t1), GK2=t_tuple(fac,g0,k1,t2), GK3=t_tuple(fac,g0,k1,t3); + Tuple GK4=t_tuple(fac,g1,k2,t3), GK5=t_tuple(fac,g0,k1,t4), GK6=t_tuple(fac,g1,k2,t4); + Tuple O1=t_tuple(fac,r,g0,t1), O2=t_tuple(fac,r,g1,t3), O3=t_tuple(fac,r,g1,t4); + if (sol==null && K0T0!=null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 6.13", + G0, G1, "", "this/Guest", "", + K0, K1, K2, "", "this/Room", "keys", + K0T0, K0T1, K0T2, K0T3, K1T4, "", "this/Room", "currentKey", + F1, F2, F3, F4, F5, "", "this/FrontDesk", "lastKey", + GK1, GK2, GK3, GK4, GK5, GK6, "", "this/Guest", "keys", + O1, O2, O3, "", "this/FrontDesk", "occupant", + "Event$0", "Event$1", "", "this/Checkin", "", + "Event$2", "", "this/Checkout", "", + "Event$3", "", "this/Entry", "", + t_tuple(fac,"Event$0",t0), + t_tuple(fac,"Event$2",t1), + t_tuple(fac,"Event$1",t2), + t_tuple(fac,"Event$3",t3), "", "this/Event", "pre", + }); + if (sol==null && K0T0!=null) + sol=trial(rep, fac, solver, sigs, formula, frame, new Object[]{"Fig 6.6", + G0, G1, "", "this/Guest", "", + K0, K1, K2, "", "this/Room", "keys", + K0T0, K0T1, K0T2, K0T3, K1T4, "", "this/Room", "currentKey", + F1, F2, F3, F4, F5, "", "this/FrontDesk", "lastKey", + GK1, GK2, GK3, GK4, GK5, GK6, "", "this/Guest", "keys", + O1, O2, O3, "", "this/FrontDesk", "occupant", + }); + } + return sol; + } + + /** This tries a particular solution against the formula. */ + private static Solution trial (A4Reporter rep, TupleFactory fac, Solver solver, Iterable sigs, Formula f, A4Solution frame, Object[] t) { + try { + frame.kr2typeCLEAR(); + Bounds b = null; + TupleSet ts = null; + for(int i=1; i0) { // This means it's a unary Tuple containing the given atom + Tuple xx = fac.tuple((String)x); + if (ts==null) ts=fac.noneOf(1); + ts.add(xx); + continue; + } + if (x instanceof Tuple) { // This means it's a Tuple + Tuple xx=(Tuple)x; + if (ts==null) ts=fac.noneOf(xx.arity()); + ts.add(xx); + continue; + } + if (x instanceof String) { // The empty string means the sig name follows here + i++; + if (i>=t.length-1 || !(t[i] instanceof String) || !(t[i+1] instanceof String)) return null; + String sigName = (String)(t[i]); + i++; + String fieldName = (String)(t[i]); + Sig first = hasSig(sigs,sigName); + if (first==null) return null; + Expression expr = null; + if (fieldName.length()==0) { + expr=frame.a2k(first); + } else { + for(Field field:first.getFields()) if (field.label.equals(fieldName)) { + expr=frame.a2k(field); + while(expr instanceof BinaryExpression) expr=((BinaryExpression)expr).right(); + break; + } + } + if (!(expr instanceof Relation)) return null; + if (b==null) b = frame.getBounds(); // We delay the expansive Bounds.clone() until we really find a possible match + if (ts==null) ts = fac.noneOf(expr.arity()); + if (!ts.containsAll(b.lowerBound((Relation)expr))) return null; // Sanity check + if (!b.upperBound((Relation)expr).containsAll(ts)) return null; // Sanity check + b.boundExactly((Relation)expr, ts); + ts=null; + continue; + } + } + SATFactory sat = solver.options().solver(); + Solution sol; + try { + solver.options().setSolver(SATFactory.DefaultSAT4J); + sol = solver.solve(f,b); + } finally { + solver.options().setSolver(sat); + } + if (sol==null || (sol.outcome()!=SATISFIABLE && sol.outcome()!=TRIVIALLY_SATISFIABLE)) return null; + if (rep!=null) rep.debug("Comment: "+t[0]+"\n"); + return sol; + } catch(Throwable ex) { + return null; + } + } + + /** This constructs a Kodkod Tuple from the list of atoms, and returns null if no such Tuple can be constructed. */ + private static Tuple t_tuple (TupleFactory factory, Object... atoms) { + try { + if (atoms.length <= 0) return null; + return factory.tuple(atoms); + } catch(Throwable ex) { + return null; + } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/BoundsComputer.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/BoundsComputer.java new file mode 100644 index 00000000..77726b68 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/BoundsComputer.java @@ -0,0 +1,329 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.translator; + +import java.util.ArrayList; +import java.util.List; +import java.util.LinkedHashMap; +import java.util.Map; +import kodkod.ast.Decls; +import kodkod.ast.Expression; +import kodkod.ast.Formula; +import kodkod.ast.Relation; +import kodkod.ast.Variable; +import kodkod.instance.Tuple; +import kodkod.instance.TupleFactory; +import kodkod.instance.TupleSet; +import kodkod.instance.Universe; +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprBinary; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprConstant; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprList; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprUnary; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Type; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.SubsetSig; + +/** Immutable; this class assigns each sig and field to some Kodkod relation or expression, then set the bounds. */ + +final class BoundsComputer { + + // It calls these A4Solution methods... + // getFactory(), query(), a2k(), addRel(), addSig(), addField(), addFormula() + + /** Stores the reporter that will receive diagnostic messages. */ + private final A4Reporter rep; + + /** Stores the scope, bounds, and other settings necessary for performing a solve. */ + private final A4Solution sol; + + /** Stores the factory. */ + private final TupleFactory factory; + + /** Stores the computed scope for each sig. */ + private final ScopeComputer sc; + + /** Stores the upperbound for each sig. */ + private final Map ub = new LinkedHashMap(); + + /** Stores the lowerbound for each sig. */ + private final Map lb = new LinkedHashMap(); + + //==============================================================================================================// + + /** Computes the lowerbound from bottom-up; it will also set a suitable initial value for each sig's upperbound. + * Precondition: sig is not a builtin sig + */ + private TupleSet computeLowerBound(List atoms, final PrimSig sig) throws Err { + int n = sc.sig2scope(sig); + TupleSet lower = factory.noneOf(1); + for(PrimSig c:sig.children()) lower.addAll(computeLowerBound(atoms, c)); + TupleSet upper = lower.clone(); + boolean isExact = sc.isExact(sig); + if (isExact || sig.isTopLevel()) for(n=n-upper.size(); n>0; n--) { + Tuple atom = atoms.remove(atoms.size()-1); + // If MUST lb.get(c).size()) ub.get(c).addAll(x); + computeUpperBound(c); + } + } + + //==============================================================================================================// + + /** Allocate relations for nonbuiltin PrimSigs bottom-up. */ + private Expression allocatePrimSig(PrimSig sig) throws Err { + // Recursively allocate all children expressions, and form the union of them + Expression sum = null; + for(PrimSig child:sig.children()) { + Expression childexpr=allocatePrimSig(child); + if (sum==null) { sum=childexpr; continue; } + // subsigs are disjoint + sol.addFormula(sum.intersection(childexpr).no(), child.isSubsig); + sum = sum.union(childexpr); + } + TupleSet lower = lb.get(sig).clone(), upper = ub.get(sig).clone(); + if (sum == null) { + // If sig doesn't have children, then sig should make a fresh relation for itself + sum = sol.addRel(sig.label, lower, upper); + } else if (sig.isAbstract == null) { + // If sig has children, and sig is not abstract, then create a new relation to act as the remainder. + for(PrimSig child:sig.children()) { + // Remove atoms that are KNOWN to be in a subsig; + // it's okay to mistakenly leave some atoms in, since we will never solve for the "remainder" relation directly; + // instead, we union the remainder with the children, then solve for the combined solution. + // (Thus, the more we can remove, the more efficient it gets, but it is not crucial for correctness) + TupleSet childTS = sol.query(false, sol.a2k(child), false); + lower.removeAll(childTS); + upper.removeAll(childTS); + } + sum = sum.union(sol.addRel(sig.label+" remainder", lower, upper)); + } + sol.addSig(sig, sum); + return sum; + } + + //==============================================================================================================// + + /** Allocate relations for SubsetSig top-down. */ + private Expression allocateSubsetSig(SubsetSig sig) throws Err { + // We must not visit the same SubsetSig more than once, so if we've been here already, then return the old value right away + Expression sum = sol.a2k(sig); + if (sum!=null && sum!=Expression.NONE) return sum; + // Recursively form the union of all parent expressions + TupleSet ts = factory.noneOf(1); + for(Sig parent:sig.parents) { + Expression p = (parent instanceof PrimSig) ? sol.a2k(parent) : allocateSubsetSig((SubsetSig)parent); + ts.addAll(sol.query(true, p, false)); + if (sum==null) sum=p; else sum=sum.union(p); + } + // If subset is exact, then just use the "sum" as is + if (sig.exact) { sol.addSig(sig, sum); return sum; } + // Allocate a relation for this subset sig, then bound it + rep.bound("Sig "+sig+" in "+ts+"\n"); + Relation r = sol.addRel(sig.label, null, ts); + sol.addSig(sig, r); + // Add a constraint that it is INDEED a subset of the union of its parents + sol.addFormula(r.in(sum), sig.isSubset); + return r; + } + + //==============================================================================================================// + + /** Helper method that returns the constraint that the sig has exactly "n" elements, or at most "n" elements */ + private Formula size(Sig sig, int n, boolean exact) { + Expression a = sol.a2k(sig); + if (n<=0) return a.no(); + if (n==1) return exact ? a.one() : a.lone(); + Formula f = exact ? Formula.TRUE : null; + Decls d = null; + Expression sum = null; + while(n>0) { + n--; + Variable v = Variable.unary("v" + Integer.toString(TranslateAlloyToKodkod.cnt++)); + kodkod.ast.Decl dd = v.oneOf(a); + if (d==null) d=dd; else d=dd.and(d); + if (sum==null) sum=v; else { if (f!=null) f=v.intersection(sum).no().and(f); sum=v.union(sum); } + } + if (f!=null) return sum.eq(a).and(f).forSome(d); else return a.no().or(sum.eq(a).forSome(d)); + } + + //==============================================================================================================// + + /** If ex is a simple combination of Relations, then return that combination, else return null. */ + private Expression sim(Expr ex) { + while(ex instanceof ExprUnary) { + ExprUnary u = (ExprUnary)ex; + if (u.op!=ExprUnary.Op.NOOP && u.op!=ExprUnary.Op.EXACTLYOF) break; + ex = u.sub; + } + if (ex instanceof ExprBinary) { + ExprBinary b = (ExprBinary)ex; + if (b.op==ExprBinary.Op.ARROW || b.op==ExprBinary.Op.PLUS || b.op==ExprBinary.Op.JOIN) { + Expression left = sim(b.left); if (left==null) return null; + Expression right = sim(b.right); if (right==null) return null; + if (b.op==ExprBinary.Op.ARROW) return left.product(right); + if (b.op==ExprBinary.Op.PLUS) return left.union(right); else return left.join(right); + } + } + if (ex instanceof ExprConstant) { + switch(((ExprConstant)ex).op) { + case EMPTYNESS: return Expression.NONE; + } + } + if (ex==Sig.NONE) return Expression.NONE; + if (ex==Sig.SIGINT) return Expression.INTS; + if (ex instanceof Sig) return sol.a2k((Sig)ex); + if (ex instanceof Field) return sol.a2k((Field)ex); + return null; + } + + /** Computes the bounds for sigs/fields, then construct a BoundsComputer object that you can query. */ + private BoundsComputer(A4Reporter rep, A4Solution sol, ScopeComputer sc, Iterable sigs) throws Err { + this.sc = sc; + this.factory = sol.getFactory(); + this.rep = rep; + this.sol = sol; + // Figure out the sig bounds + final Universe universe = factory.universe(); + final int atomN = universe.size(); + final List atoms = new ArrayList(atomN); + for(int i=atomN-1; i>=0; i--) atoms.add(factory.tuple(universe.atom(i))); + for(Sig s:sigs) if (!s.builtin && s.isTopLevel()) computeLowerBound(atoms, (PrimSig)s); + for(Sig s:sigs) if (!s.builtin && s.isTopLevel()) computeUpperBound((PrimSig)s); + // Bound the sigs + for(Sig s:sigs) if (!s.builtin && s.isTopLevel()) allocatePrimSig((PrimSig)s); + for(Sig s:sigs) if (s instanceof SubsetSig) allocateSubsetSig((SubsetSig)s); + // Bound the fields + again: + for(Sig s:sigs) { + while (s.isOne!=null && s.getFieldDecls().size()==2 && s.getFields().size()==2 && s.getFacts().size()==1) { + // Let's check whether this is a total ordering on an enum... + Expr fact = s.getFacts().get(0).deNOP(), b1 = s.getFieldDecls().get(0).expr.deNOP(), b2 = s.getFieldDecls().get(1).expr.deNOP(), b3; + if (!(fact instanceof ExprList) || !(b1 instanceof ExprUnary) || !(b2 instanceof ExprBinary)) break; + ExprList list = (ExprList)fact; + if (list.op!=ExprList.Op.TOTALORDER || list.args.size()!=3) break; + if (((ExprUnary)b1).op!=ExprUnary.Op.SETOF) break; else b1 = ((ExprUnary)b1).sub.deNOP(); + if (((ExprBinary)b2).op!=ExprBinary.Op.ARROW) break; else { b3 = ((ExprBinary)b2).right.deNOP(); b2 = ((ExprBinary)b2).left.deNOP(); } + if (!(b1 instanceof PrimSig) || b1!=b2 || b1!=b3) break; + PrimSig sub = (PrimSig)b1; + Field f1 = s.getFields().get(0), f2 = s.getFields().get(1); + if (sub.isEnum==null || !list.args.get(0).isSame(sub) || !list.args.get(1).isSame(s.join(f1)) || !list.args.get(2).isSame(s.join(f2))) break; + // Now, we've confirmed it is a total ordering on an enum. Let's pre-bind the relations + TupleSet me = sol.query(true, sol.a2k(s), false), firstTS = factory.noneOf(2), lastTS = null, nextTS = factory.noneOf(3); + if (me.size()!=1 || me.arity()!=1) break; + int n = sub.children().size(); + for(PrimSig c: sub.children()) { + TupleSet TS = sol.query(true, sol.a2k(c), false); + if (TS.size()!=1 || TS.arity()!=1) { firstTS=factory.noneOf(2); nextTS=factory.noneOf(3); break; } + if (lastTS==null) { firstTS=me.product(TS); lastTS=TS; continue; } + nextTS.addAll(me.product(lastTS).product(TS)); + lastTS=TS; + } + if (firstTS.size()!=(n>0 ? 1 : 0) || nextTS.size() != n-1) break; + sol.addField(f1, sol.addRel(s.label+"."+f1.label, firstTS, firstTS)); + sol.addField(f2, sol.addRel(s.label+"."+f2.label, nextTS, nextTS)); + rep.bound("Field "+s.label+"."+f1.label+" == "+firstTS+"\n"); + rep.bound("Field "+s.label+"."+f2.label+" == "+nextTS+"\n"); + continue again; + } + for(Field f:s.getFields()) { + boolean isOne = s.isOne!=null; + if (isOne && f.decl().expr.mult()==ExprUnary.Op.EXACTLYOF) { + Expression sim = sim(f.decl().expr); + if (sim!=null) { + rep.bound("Field "+s.label+"."+f.label+" defined to be "+sim+"\n"); + sol.addField(f, sol.a2k(s).product(sim)); + continue; + } + } + Type t = isOne ? Sig.UNIV.type().join(f.type()) : f.type(); + TupleSet ub = factory.noneOf(t.arity()); + for(List p:t.fold()) { + TupleSet upper=null; + for(PrimSig b:p) { + TupleSet tmp = sol.query(true, sol.a2k(b), false); + if (upper==null) upper=tmp; else upper=upper.product(tmp); + } + ub.addAll(upper); + } + Relation r = sol.addRel(s.label+"."+f.label, null, ub); + sol.addField(f, isOne ? sol.a2k(s).product(r) : r); + } + } + // Add any additional SIZE constraints + for(Sig s:sigs) if (!s.builtin) { + Expression exp = sol.a2k(s); + TupleSet upper = sol.query(true,exp,false), lower=sol.query(false,exp,false); + final int n = sc.sig2scope(s); + if (s.isOne!=null && (lower.size()!=1 || upper.size()!=1)) { + rep.bound("Sig "+s+" in "+upper+" with size==1\n"); + sol.addFormula(exp.one(), s.isOne); + continue; + } + if (s.isSome!=null && lower.size()<1) sol.addFormula(exp.some(), s.isSome); + if (s.isLone!=null && upper.size()>1) sol.addFormula(exp.lone(), s.isLone); + if (n<0) continue; // This means no scope was specified + if (lower.size()==n && upper.size()==n && sc.isExact(s)) { + rep.bound("Sig "+s+" == "+upper+"\n"); + } + else if (sc.isExact(s)) { + rep.bound("Sig "+s+" in "+upper+" with size=="+n+"\n"); + sol.addFormula(size(s,n,true), Pos.UNKNOWN); + } + else if (upper.size()<=n){ + rep.bound("Sig "+s+" in "+upper+"\n"); + } + else { + rep.bound("Sig "+s+" in "+upper+" with size<="+n+"\n"); + sol.addFormula(size(s,n,false), Pos.UNKNOWN); + } + } + } + + //==============================================================================================================// + + /** Assign each sig and field to some Kodkod relation or expression, then set the bounds. */ + static void compute (A4Reporter rep, A4Solution sol, ScopeComputer sc, Iterable sigs) throws Err { + new BoundsComputer(rep, sol, sc, sigs); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/ConvToConjunction.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/ConvToConjunction.java new file mode 100644 index 00000000..cb362c2f --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/ConvToConjunction.java @@ -0,0 +1,102 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.translator; + +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprBinary; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprList; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprCall; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprConstant; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprITE; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprLet; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprQt; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprUnary; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.VisitReturn; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; + +/** Immutable; this class rearranges the AST to promote as many clauses up to the top level as possible + * (in order to get better precision unsat core results) + */ + +final class ConvToConjunction extends VisitReturn { + + /** {@inheritDoc} */ + @Override public Expr visit(ExprBinary x) throws Err { + if (x.op == ExprBinary.Op.AND) { + Expr a = visitThis(x.left); + Expr b = visitThis(x.right); + return a.and(b); + } + return x; + } + + /** {@inheritDoc} */ + @Override public Expr visit(ExprQt x) throws Err { + if (x.op == ExprQt.Op.ALL) { + Expr s = x.sub.deNOP(); + if (s instanceof ExprBinary && ((ExprBinary)s).op==ExprBinary.Op.AND) { + Expr a = visitThis(x.op.make(Pos.UNKNOWN, Pos.UNKNOWN, x.decls, ((ExprBinary)s).left)); + Expr b = visitThis(x.op.make(Pos.UNKNOWN, Pos.UNKNOWN, x.decls, ((ExprBinary)s).right)); + return a.and(b); + } + } + return x; + } + + /** {@inheritDoc} */ + @Override public Expr visit(ExprUnary x) throws Err { + if (x.op == ExprUnary.Op.NOOP) { + return visitThis(x.sub); + } + if (x.op == ExprUnary.Op.NOT) { + Expr s = x.sub.deNOP(); + if (s instanceof ExprBinary && ((ExprBinary)s).op==ExprBinary.Op.OR) { + Expr a = visitThis(((ExprBinary)s).left.not()); + Expr b = visitThis(((ExprBinary)s).right.not()); + return a.and(b); + } + } + return x; + } + + /** {@inheritDoc} */ + @Override public Expr visit(ExprList x) { return x; } + + /** {@inheritDoc} */ + @Override public Expr visit(ExprCall x) { return x; } + + /** {@inheritDoc} */ + @Override public Expr visit(ExprConstant x) { return x; } + + /** {@inheritDoc} */ + @Override public Expr visit(ExprITE x) { return x; } + + /** {@inheritDoc} */ + @Override public Expr visit(ExprLet x) { return x; } + + /** {@inheritDoc} */ + @Override public Expr visit(ExprVar x) { return x; } + + /** {@inheritDoc} */ + @Override public Expr visit(Sig x) { return x; } + + /** {@inheritDoc} */ + @Override public Expr visit(Field x) { return x; } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/ScopeComputer.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/ScopeComputer.java new file mode 100644 index 00000000..fbeda696 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/ScopeComputer.java @@ -0,0 +1,404 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.translator; + +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.NONE; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.SEQIDX; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.SIGINT; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.STRING; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.UNIV; + +import java.util.ArrayList; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Set; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorAPI; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.SafeList; +import edu.mit.csail.sdg.alloy4.UniqueNameGenerator; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.CommandScope; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprCall; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprUnary; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprUnary.Op; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.VisitQuery; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; +import edu.mit.csail.sdg.alloy4compiler.ast.Type.ProductType; + +/** Immutable; this class computes the scopes for each sig and computes the bitwidth and maximum sequence length. + * + *

The scopes are determined as follows: + * + *

"run x": every topsig is scoped to <= 3 elements. + * + *

"run x for N": every topsig is scoped to <= N elements. + * + *

"run x for N but N1 SIG1, N2 SIG2...": + *
Every sig following "but" is constrained explicitly. + *
Any topsig that is + *
a) not listed, and + *
b) its scope is not derived otherwise + *
will be scoped to have <= N elements. + * + *

"run x for N1 SIG1, N2 SIG2..." + *
Every sig following "but" is constrained explicitly. + *
Any topsig that is + *
a) not listed, and + *
b) its scope is not derived otherwise + *
we will give an error message. + * + *

Please see ScopeComputer.java for the exact rules for deriving the missing scopes. + */ + +final class ScopeComputer { + + // It calls A4Solution's constructor + + /** Stores the reporter that will receive diagnostic messages. */ + private final A4Reporter rep; + + /** Stores the command that we're computing the scope for. */ + private final Command cmd; + + /** The integer bitwidth of this solution's model; always between 1 and 30. */ + private int bitwidth = 4; + + /** The maximum sequence length; always between 0 and (2^(bitwidth-1))-1. */ + private int maxseq = 4; + + /** The number of STRING atoms to allocate; -1 if it was not specified. */ + private int maxstring = (-1); + + /** The scope for each sig. */ + private final IdentityHashMap sig2scope = new IdentityHashMap(); + + /** The sig's scope is exact iff it is in exact.keySet() (the value is irrelevant). */ + private final IdentityHashMap exact = new IdentityHashMap(); + + /** The list of atoms. */ + private final List atoms = new ArrayList(); + + /** This UniqueNameGenerator allows each sig's atoms to be distinct strings. */ + private final UniqueNameGenerator un = new UniqueNameGenerator(); + + /** Returns the scope for a sig (or -1 if we don't know). */ + public int sig2scope(Sig sig) { + if (sig==SIGINT) return 1<=0) throw new ErrorSyntax(cmd.pos, "Sig \""+sig+"\" already has a scope of "+old+", so we cannot set it to be "+newValue); + sig2scope.put((PrimSig)sig, newValue); + rep.scope("Sig "+sig+" scope <= "+newValue+"\n"); + } + + /** Returns whether the scope of a sig is exact or not. */ + public boolean isExact(Sig sig) { + return sig==SIGINT || sig==SEQIDX || sig==STRING || ((sig instanceof PrimSig) && exact.containsKey(sig)); + } + + /** Make the given sig "exact". */ + private void makeExact(Pos pos, Sig sig) throws Err { + if (!(sig instanceof PrimSig)) throw new ErrorSyntax(pos, "Cannot specify a scope for a subset signature \""+sig+"\""); + exact.put(sig, sig); + } + + /** Modifies the integer bitwidth of this solution's model (and sets the max sequence length to 0) */ + private void setBitwidth(Pos pos, int newBitwidth) throws ErrorAPI, ErrorSyntax { + if (newBitwidth<0) throw new ErrorSyntax(pos, "Cannot specify a bitwidth less than 0"); + if (newBitwidth>30) throw new ErrorSyntax(pos, "Cannot specify a bitwidth greater than 30"); + bitwidth = newBitwidth; + maxseq = 0; + sig2scope.put(SIGINT, bitwidth < 1 ? 0 : 1< max()) throw new ErrorSyntax(pos, "With integer bitwidth of "+bitwidth+", you cannot have sequence length longer than "+max()); + if (newMaxSeq < 0) newMaxSeq = 0; //throw new ErrorSyntax(pos, "The maximum sequence length cannot be negative."); + maxseq = newMaxSeq; + sig2scope.put(SEQIDX, maxseq); + } + + /** Returns the largest allowed integer. */ + private int max() { return Util.max(bitwidth); } + + /** Returns the smallest allowed integer. */ + private int min() { return Util.min(bitwidth); } + + //===========================================================================================================================// + + /** If A is abstract, unscoped, and all children are scoped, then set A's scope to be the sum; + * if A is abstract, scoped, and every child except one is scoped, then set that child's scope to be the difference. + */ + private boolean derive_abstract_scope (Iterable sigs) throws Err { + boolean changed=false; + again: + for(Sig s:sigs) if (!s.builtin && (s instanceof PrimSig) && s.isAbstract!=null) { + SafeList subs = ((PrimSig)s).children(); + if (subs.size()==0) continue; + Sig missing=null; + int sum=0; + for(Sig c:subs) { + int cn = sig2scope(c); + if (cn<0) { if (missing==null) { missing=c; continue; } else { continue again; } } + sum=sum+cn; + if (sum<0) throw new ErrorSyntax(cmd.pos, "The number of atoms exceeds the internal limit of "+Integer.MAX_VALUE); + } + int sn = sig2scope(s); + if (sn<0) { + if (missing!=null) continue; + sig2scope(s, sum); + changed=true; + } else if (missing!=null) { + sig2scope(missing, (sn sigs) throws Err { + boolean changed=false; + final int overall = (cmd.overall<0 && cmd.scope.size()==0) ? 3 : cmd.overall; + for(Sig s:sigs) if (!s.builtin && s.isTopLevel() && sig2scope(s)<0) { + if (s.isEnum!=null) { sig2scope(s, 0); continue; } // enum without children should get the empty set + if (overall<0) throw new ErrorSyntax(cmd.pos, "You must specify a scope for sig \""+s+"\""); + sig2scope(s, overall); + changed=true; + } + return changed; + } + + //===========================================================================================================================// + + /** If A is not toplevel, and we haven't been able to derive its scope yet, then give it its parent's scope. */ + private boolean derive_scope_from_parent (Iterable sigs) throws Err { + boolean changed=false; + Sig trouble=null; + for(Sig s:sigs) if (!s.builtin && !s.isTopLevel() && sig2scope(s)<0 && (s instanceof PrimSig)) { + PrimSig p = ((PrimSig)s).parent; + int pb = sig2scope(p); + if (pb>=0) {sig2scope(s,pb); changed=true;} else {trouble=s;} + } + if (changed) return true; + if (trouble==null) return false; + throw new ErrorSyntax(cmd.pos,"You must specify a scope for sig \""+trouble+"\""); + } + + //===========================================================================================================================// + + /** Computes the number of atoms needed for each sig (and add these atoms to this.atoms) */ + private int computeLowerBound(final PrimSig sig) throws Err { + if (sig.builtin) return 0; + int n=sig2scope(sig), lower=0; + boolean isExact = isExact(sig); + // First, figure out what atoms *MUST* be in this sig + for(PrimSig c:sig.children()) lower = lower + computeLowerBound(c); + // Bump up the scope if the sum of children exceed the scope for this sig + if (nlower && (isExact || sig.isTopLevel())) { + // Figure out how many new atoms to make + n = n-lower; + // Pick a name for them + String name=sig.label; + if (name.startsWith("this/")) name=name.substring(5); + name=un.make(name); + // Now, generate each atom using the format "SIGNAME$INDEX" + // By prepending the index with 0 so that they're the same width, we ensure they sort lexicographically. + StringBuilder sb=new StringBuilder(); + for(int i=0; i sigs, Command cmd) throws Err { + this.rep = rep; + this.cmd = cmd; + boolean shouldUseInts = areIntsUsed(sigs, cmd); + // Process each sig listed in the command + for(CommandScope entry:cmd.scope) { + Sig s = entry.sig; + int scope = entry.startingScope; + boolean exact = entry.isExact; + if (s==UNIV) throw new ErrorSyntax(cmd.pos, "You cannot set a scope on \"univ\"."); + if (s==SIGINT) throw new ErrorSyntax(cmd.pos, + "You can no longer set a scope on \"Int\". " + +"The number of atoms in Int is always exactly equal to 2^(i" + + "nteger bitwidth).\n"); + if (s==SEQIDX) throw new ErrorSyntax(cmd.pos, + "You cannot set a scope on \"seq/Int\". " + +"To set the maximum allowed sequence length, use the seq keyword.\n"); + if (s==STRING) { + if (maxstring>=0) throw new ErrorSyntax(cmd.pos, "Sig \"String\" already has a scope of "+maxstring+", so we cannot set it to be "+scope); + if (!exact) throw new ErrorSyntax(cmd.pos, "Sig \"String\" must have an exact scope."); + maxstring = scope; + continue; + } + if (s==NONE) throw new ErrorSyntax(cmd.pos, "You cannot set a scope on \"none\"."); + if (s.isEnum!=null) throw new ErrorSyntax(cmd.pos, "You cannot set a scope on the enum \""+s.label+"\""); + if (s.isOne!=null && scope!=1) throw new ErrorSyntax(cmd.pos, + "Sig \""+s+"\" has the multiplicity of \"one\", so its scope must be 1, and cannot be "+scope); + if (s.isLone!=null && scope>1) throw new ErrorSyntax(cmd.pos, + "Sig \""+s+"\" has the multiplicity of \"lone\", so its scope must 0 or 1, and cannot be "+scope); + if (s.isSome!=null && scope<1) throw new ErrorSyntax(cmd.pos, + "Sig \""+s+"\" has the multiplicity of \"some\", so its scope must 1 or above, and cannot be "+scope); + sig2scope(s, scope); + if (exact) makeExact(cmd.pos, s); + } + // Force "one" sigs to be exactly one, and "lone" to be at most one + for(Sig s:sigs) if (s instanceof PrimSig) { + if (s.isOne!=null) { makeExact(cmd.pos, s); sig2scope(s,1); } else if (s.isLone!=null && sig2scope(s)!=0) sig2scope(s,1); + } + // Derive the implicit scopes + while(true) { + if (derive_abstract_scope(sigs)) { do {} while(derive_abstract_scope(sigs)); continue; } + if (derive_overall_scope(sigs)) { do {} while(derive_overall_scope(sigs)); continue; } + if (derive_scope_from_parent(sigs)) { do {} while(derive_scope_from_parent(sigs)); continue; } + break; + } + // Set the initial scope on "int" and "Int" and "seq" + int maxseq=cmd.maxseq, bitwidth=cmd.bitwidth; + if (bitwidth<0) { bitwidth = (shouldUseInts ? 4 : 0); } + setBitwidth(cmd.pos, bitwidth); + if (maxseq<0) { + if (cmd.overall>=0) maxseq=cmd.overall; else maxseq=4; + int max = Util.max(bitwidth); + if (maxseq > max) maxseq = max; + } + setMaxSeq(cmd.pos, maxseq); + // Generate the atoms and the universe + for(Sig s:sigs) if (s.isTopLevel()) computeLowerBound((PrimSig)s); + int max = max(), min = min(); + if (max >= min) for(int i=min; i<=max; i++) atoms.add(""+i); + } + + /** Whether or not Int appears in the relation types found in these sigs */ + private boolean areIntsUsed(Iterable sigs, Command cmd) { + /* check for Int-typed relations */ + for (Sig s : sigs) { + for (Field f : s.getFields()) { + for (ProductType pt : f.type()) { + for (int k = 0; k < pt.arity(); k++) { + if (pt.get(k) == SIGINT || pt.get(k) == SEQIDX) + return true; + } + } + } + } + /* check expressions; look for CAST2SIGING (Int[]) */ + try { + Object intTriggerNode; + intTriggerNode = cmd.formula.accept(new VisitQuery() { + @Override + public Object visit(ExprCall x) throws Err { + // skip integer arithmetic functions, because their + // arguments are always explicitly cast to SIGINT using Int[] + if (x.fun.label.startsWith("integer/")) + return null; + return super.visit(x); + } + + @Override + public Object visit(ExprUnary x) throws Err { + if (x.op == Op.CAST2SIGINT) + return x; + return super.visit(x); + } + }); + if (intTriggerNode != null) return true; + } catch (Err e) {} + + return false; + } + + //===========================================================================================================================// + + /** Computes the scopes for each sig and computes the bitwidth and maximum sequence length. + * + *

The scopes are determined as follows: + * + *

"run x": every topsig is scoped to <= 3 elements. + * + *

"run x for N": every topsig is scoped to <= N elements. + * + *

"run x for N but N1 SIG1, N2 SIG2...": + *
Every sig following "but" is constrained explicitly. + *
Any topsig that is + *
a) not listed, and + *
b) its scope is not derived otherwise + *
will be scoped to have <= N elements. + * + *

"run x for N1 SIG1, N2 SIG2..." + *
Every sig following "but" is constrained explicitly. + *
Any topsig that is + *
a) not listed, and + *
b) its scope is not derived otherwise + *
we will give an error message. + * + *

Please see ScopeComputer.java for the exact rules for deriving the missing scopes. + */ + static Pair compute (A4Reporter rep, A4Options opt, Iterable sigs, Command cmd) throws Err { + ScopeComputer sc = new ScopeComputer(rep, sigs, cmd); + Set set = cmd.getAllStringConstants(sigs); + if (sc.maxstring>=0 && set.size()>sc.maxstring) rep.scope("Sig String expanded to contain all "+set.size()+" String constant(s) referenced by this command.\n"); + for(int i=0; set.size()(sol, sc); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/Simplifier.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/Simplifier.java new file mode 100644 index 00000000..0f9ad5ef --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/Simplifier.java @@ -0,0 +1,280 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.translator; + +import java.util.Iterator; +import java.util.List; +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.MailBug; +import kodkod.ast.BinaryExpression; +import kodkod.ast.BinaryFormula; +import kodkod.ast.ComparisonFormula; +import kodkod.ast.Expression; +import kodkod.ast.Formula; +import kodkod.ast.NaryFormula; +import kodkod.ast.Relation; +import kodkod.ast.operator.ExprCompOperator; +import kodkod.ast.operator.ExprOperator; +import kodkod.ast.operator.FormulaOperator; +import kodkod.instance.TupleSet; + +/** Immutable; this class shrinks the unknowns as much as possible in order to reduce the number of variables in final CNF. + * + *

Currently it recognizes the following patterns: + * + *

(1) When it sees "A in B", it will try to derive a safe upperbound for B, and then remove + * any excess unknowns from A's upperbound. + * + *

(2) When it sees "A = B", it will try to simplify A assuming "A in B", and then simplify B assuming "B in A". + */ + +public class Simplifier { + + /** Reporter for receiving debug messages. */ + private A4Reporter rep = null; + + /** The A4Solution object we are attempting to simplify. */ + private A4Solution sol = null; + + /** Construct a Simplifier object. */ + public Simplifier() { } + + /* Stores the equivalence relation discovered so far. */ + //private final IdentityHashMap> equiv = new IdentityHashMap>(); + + /** Simplify sol.bounds() based on the set of formulas, or to modify the formulas list itself. + * Subclasses should override this method to implement different simplification algorithms. + * (Note: this method is allowed to modify the "formulas" array if it sees an opportunity for optimization) + */ + public boolean simplify(A4Reporter rep, A4Solution sol, List formulas) throws Err { + this.rep = rep; + this.sol = sol; + while(true) { + //equiv.clear(); + for(Formula f: formulas) if (!simplify_eq(f)) return false; + for(Formula f: formulas) if (!simplify_in(f)) return false; + /* + if (equiv.size()==0) return true; + // We have to construct this replacer from scratch, since each time it will retain some info we don't want + final AbstractReplacer ar = new AbstractReplacer(new kodkod.util.collections.IdentityHashSet()) { + @Override public Expression visit(Relation relation) { + List list = equiv.get(relation); + if (list!=null) return list.get(0); else return relation; + } + }; + for(Map.Entry> e: equiv.entrySet()) System.out.println("Equiv: "+e); System.out.flush(); + for(int i=formulas.size()-1; i>=0; i--) { + Formula OLD = formulas.get(i); + Formula NEW = OLD.accept(ar); + if (OLD!=NEW) { System.out.println("OLD->NEW: "+OLD+" ===> "+NEW); System.out.flush(); } + formulas.set(i, NEW); + } + */ + return true; + } + } + + /** Simplify (a.(a->b)) into b when semantically equivalent */ + private final Expression condense(Expression x) { + while (x instanceof BinaryExpression) { + BinaryExpression b = (BinaryExpression)x; + if (b.op() == ExprOperator.JOIN && b.left() instanceof Relation && b.right() instanceof BinaryExpression) { + Relation r = (Relation) (b.left()); + try { + if (sol.query(true, r, false).size()!=1) return x; + if (sol.query(false, r, false).size()!=1) return x; + } catch(Err er) { + return x; + } + b = (BinaryExpression)(b.right()); + if (b.op() == ExprOperator.PRODUCT && b.left()==r) { + x = b.right(); + continue; + } + } + break; + } + return x; + } + + /** Simplify the bounds based on the fact that "a == b"; return false if we discover the formula is unsat. */ + private final boolean simplify_equal(Expression a, Expression b) { + a = condense(a); + b = condense(b); + /* + System.out.println("A: "+a+" B: "+b); System.out.flush(); + if (a instanceof Relation && b instanceof Relation && a!=b) { + List al = equiv.get(a); + List bl = equiv.get(b); + if (al==null) { Expression oldA=a; al=bl; bl=null; a=b; b=oldA; } + if (al==null) { + al = new ArrayList(); + al.add(a); + al.add(b); + equiv.put(a, al); + equiv.put(b, al); + System.out.println("BothNewEquivalent: "+a+" "+b); System.out.flush(); + } else if (bl==null) { + al.add(b); + equiv.put(b, al); + System.out.println("NewEquivalent: "+a+" "+b); System.out.flush(); + } else if (al!=bl) { + al.addAll(bl); + for(Node x: bl) equiv.put(x, al); + System.out.println("MergeEquivalent: "+a+" "+b); System.out.flush(); + } + } else*/ + if (a instanceof Relation || b instanceof Relation) { + try { + TupleSet a0 = sol.query(false, a, false), a1 = sol.query(true, a, false); + TupleSet b0 = sol.query(false, b, false), b1 = sol.query(true, b, false); + if (a instanceof Relation && a0.size()"+(a1.size()-b0.size())+"\n"); + sol.shrink((Relation)a, a0=b0, a1); + } + if (a instanceof Relation && a1.size()>b1.size() && b1.containsAll(a0) && a1.containsAll(b1)) { + rep.debug("Comment: Simplify "+a+" "+(a1.size()-a0.size())+"->"+(b1.size()-a0.size())+"\n"); + sol.shrink((Relation)a, a0, a1=b1); + } + if (b instanceof Relation && b0.size()"+(b1.size()-a0.size())+"\n"); + sol.shrink((Relation)b, b0=a0, b1); + } + if (b instanceof Relation && b1.size()>a1.size() && a1.containsAll(b0) && b1.containsAll(a1)) { + rep.debug("Comment: Simplify "+b+" "+(b1.size()-b0.size())+"->"+(a1.size()-b0.size())+"\n"); + sol.shrink((Relation)b, b0, b1=a1); + } + } catch(Exception ex) {} + } + return true; + } + + /** Simplify the bounds based on the fact that "a is subset of b"; return false if we discover the formula is unsat. */ + private final boolean simplify_in(Expression a, Expression b) { + a = condense(a); + b = condense(b); + if (a instanceof Relation) { + try { + Relation r = (Relation)a; + TupleSet ub = sol.query(true, r, false), lb = sol.query(false, r, false), t = sol.approximate(b); + t.retainAll(ub); + if (!t.containsAll(lb)) { rep.debug("Comment: Simplify "+a+" "+ub.size()+"->false\n"); return false; } // This means the upperbound is shrunk BELOW the lowerbound. + if (t.size() < ub.size()) { rep.debug("Comment: Simplify "+a+" "+ub.size()+"->"+t.size()+"\n"); sol.shrink(r,lb,t); } + } catch(Throwable ex) { + rep.debug("Comment: Simplify "+a+" exception: "+ex+"\n"+MailBug.dump(ex).trim()+"\n"); // Not fatal; let's report it to the debug() reporter + } + } + return true; + } + + // ALTERNATIVE VERSION THAT COMPUTES LOWER BOUNDS AS WELL +// /** Simplify the bounds based on the fact that "a is subset of b"; return false if we discover the formula is unsat. */ +// private final boolean simplify_in(Expression a, Expression b) { +// a = condense(a); +// b = condense(b); +// if (a instanceof Relation) { +// return simpIn((Relation)a, b, true); +// } +// if (b instanceof Relation) { +// return simpIn((Relation)b, a, false); +// } +// return true; +// } +// +// private final boolean simpIn(Relation r, Expression b, boolean bIsUpper) { +// try { +// TupleSet ub = sol.query(true, r, false); +// TupleSet lb = sol.query(false, r, false); +// TupleSet t = sol.approximate(b); +// t.retainAll(ub); +// if (bIsUpper) { +// if (!t.containsAll(lb)) { +// // This means the upperbound is shrunk BELOW the lowerbound. +// rep.debug("Comment: Simplify upper "+r+" "+ub.size()+"->false\n"); +// return false; +// } +// if (t.size() < ub.size()) { +// rep.debug("Comment: Simplify upper "+r+" "+ub.size()+"->"+t.size()+"\n"); +// sol.shrink(r,lb,t); +// } +// } else { +// if (!ub.containsAll(t)) { +// // This means the upperbound is shrunk BELOW the lowerbound. +// rep.debug("Comment: Simplify lower "+r+" "+lb.size()+"->false\n"); +// return false; +// } +// if (lb.size() < t.size()) { +// rep.debug("Comment: Simplify lower "+r+" "+lb.size()+"->"+t.size()+"\n"); +// sol.shrink(r,t,ub); +// } +// } +// } catch(Throwable ex) { +// rep.debug("Comment: Simplify "+r+" exception: "+ex+"\n"+MailBug.dump(ex).trim()+"\n"); // Not fatal; let's report it to the debug() reporter +// } +// return true; +// } + + /** Simplify the bounds based on the fact that "form is true"; return false if we discover the formula is unsat. */ + private final boolean simplify_in (Formula form) { + if (form instanceof NaryFormula) { + NaryFormula f = (NaryFormula)form; + if (f.op() == FormulaOperator.AND) { + for(Iterator i = f.iterator(); i.hasNext();) if (!simplify_in(i.next())) return false; + } + } + if (form instanceof BinaryFormula) { + BinaryFormula f = (BinaryFormula)form; + if (f.op() == FormulaOperator.AND) { + return simplify_in(f.left()) && simplify_in(f.right()); + } + } + if (form instanceof ComparisonFormula) { + ComparisonFormula f = (ComparisonFormula)form; + if (f.op() == ExprCompOperator.SUBSET) { + if (!simplify_in(f.left(), f.right())) return false; + } + if (f.op() == ExprCompOperator.EQUALS) { + if (!simplify_in(f.left(), f.right())) return false; + if (!simplify_in(f.right(), f.left())) return false; + } + } + return true; + } + + /** Simplify the bounds based on the fact that "form is true"; return false if we discover the formula is unsat. */ + private final boolean simplify_eq (Formula form) { + if (form instanceof NaryFormula) { + NaryFormula f = (NaryFormula)form; + if (f.op() == FormulaOperator.AND) { + for(Iterator i = f.iterator(); i.hasNext();) if (!simplify_eq(i.next())) return false; + } + } + if (form instanceof BinaryFormula) { + BinaryFormula f = (BinaryFormula)form; + if (f.op() == FormulaOperator.AND) { + return simplify_eq(f.left()) && simplify_eq(f.right()); + } + } + if (form instanceof ComparisonFormula) { + ComparisonFormula f = (ComparisonFormula)form; + if (f.op() == ExprCompOperator.EQUALS) { + if (!simplify_equal(f.left(), f.right())) return false; + } + } + return true; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/TranslateAlloyToKodkod.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/TranslateAlloyToKodkod.java new file mode 100644 index 00000000..ab49ef22 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/TranslateAlloyToKodkod.java @@ -0,0 +1,1048 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.translator; + +import static edu.mit.csail.sdg.alloy4.Util.tail; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.UNIV; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import kodkod.ast.BinaryExpression; +import kodkod.ast.Decls; +import kodkod.ast.ExprToIntCast; +import kodkod.ast.Expression; +import kodkod.ast.Formula; +import kodkod.ast.IntConstant; +import kodkod.ast.IntExpression; +import kodkod.ast.IntToExprCast; +import kodkod.ast.QuantifiedFormula; +import kodkod.ast.Relation; +import kodkod.ast.Variable; +import kodkod.ast.operator.ExprOperator; +import kodkod.engine.CapacityExceededException; +import kodkod.engine.fol2sat.HigherOrderDeclException; +import kodkod.instance.Tuple; +import kodkod.instance.TupleFactory; +import kodkod.instance.TupleSet; +import kodkod.util.ints.IntVector; +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.ConstMap; +import edu.mit.csail.sdg.alloy4.Env; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.CommandScope; +import edu.mit.csail.sdg.alloy4compiler.ast.Decl; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprBinary; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprCall; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprConstant; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprHasName; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprITE; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprLet; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprList; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprQt; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprUnary; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import edu.mit.csail.sdg.alloy4compiler.ast.Func; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Type; +import edu.mit.csail.sdg.alloy4compiler.ast.VisitReturn; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; + +/** Translate an Alloy AST into Kodkod AST then attempt to solve it using Kodkod. */ + +public final class TranslateAlloyToKodkod extends VisitReturn { + + static int cnt = 0; + + /** This is used to detect "function recursion" (which we currently do not allow); + * also, by knowing the current function name, we can provide a more meaningful name for skolem variables + */ + private final List current_function = new ArrayList(); + + /** This maps the current local variables (LET, QUANT, Function Param) to the actual Kodkod Expression/IntExpression/Formula. */ + private Env env = new Env(); + + /** If frame!=null, it stores the scope, bounds, and other settings necessary for performing a solve. */ + private final A4Solution frame; + + /** If frame==null, it stores the mapping from each Sig/Field/Skolem/Atom to its corresponding Kodkod expression. */ + private final ConstMap a2k; + + /** If frame==null, it stores the mapping from each String literal to its corresponding Kodkod expression. */ + private final ConstMap s2k; + + /** The current reporter. */ + private A4Reporter rep; + + /** If nonnull, it's the current command. */ + private final Command cmd; + + /** The bitwidth. */ + private final int bitwidth; + + /** The minimum allowed integer. */ + private final int min; + + /** The maximum allowed integer. */ + private final int max; + + /** The maximum allowed loop unrolling and recursion. */ + private final int unrolls; + + /** Construct a translator based on the given list of sigs and the given command. + * @param rep - if nonnull, it's the reporter that will receive diagnostics and progress reports + * @param opt - the solving options (must not be null) + * @param sigs - the list of sigs (must not be null, and must be a complete list) + * @param cmd - the command to solve (must not be null) + */ + private TranslateAlloyToKodkod (A4Reporter rep, A4Options opt, Iterable sigs, Command cmd) throws Err { + this.unrolls = opt.unrolls; + this.rep = (rep != null) ? rep : A4Reporter.NOP; + this.cmd = cmd; + Pair pair = ScopeComputer.compute(this.rep, opt, sigs, cmd); + this.frame = pair.a; + this.bitwidth = pair.a.getBitwidth(); + this.min = pair.a.min(); + this.max = pair.a.max(); + this.a2k = null; + this.s2k = null; + BoundsComputer.compute(rep, frame, pair.b, sigs); + } + + /** Construct a translator based on a already-fully-constructed association map. + * @param bitwidth - the integer bitwidth to use + * @param unrolls - the maximum number of loop unrolling and recursion allowed + * @param a2k - the mapping from Alloy sig/field/skolem/atom to the corresponding Kodkod expression + */ + private TranslateAlloyToKodkod (int bitwidth, int unrolls, Map a2k, Map s2k) throws Err { + this.unrolls = unrolls; + if (bitwidth<0) throw new ErrorSyntax("Cannot specify a bitwidth less than 0"); + if (bitwidth>30) throw new ErrorSyntax("Cannot specify a bitwidth greater than 30"); + this.rep = A4Reporter.NOP; + this.cmd = null; + this.frame = null; + this.bitwidth = bitwidth; + this.max = Util.max(bitwidth); + this.min = Util.min(bitwidth); + this.a2k = ConstMap.make(a2k); + this.s2k = ConstMap.make(s2k); + } + + /** Associate the given formula with the given expression, then return the formula as-is. */ + private Formula k2pos(Formula f, Expr e) throws Err { + if (k2pos_enabled) if (frame!=null) frame.k2pos(f, e); + return f; + } + private boolean k2pos_enabled = true; + + /** Returns the expression corresponding to the given sig. */ + private Expression a2k(Sig x) throws Err { if (a2k!=null) return a2k.get(x); else return frame.a2k(x); } + + /** Returns the expression corresponding to the given field. */ + private Expression a2k(Field x) throws Err { if (a2k!=null) return a2k.get(x); else return frame.a2k(x); } + + /** Returns the expression corresponding to the given skolem/atom. */ + private Expression a2k(ExprVar x) throws Err { if (a2k!=null) return a2k.get(x); else return frame.a2k(x); } + + /** Returns the expression corresponding to the given string literal. */ + private Expression s2k(String x) throws Err { if (s2k!=null) return s2k.get(x); else return frame.a2k(x); } + + //==============================================================================================================// + + /** Stores the list of "totalOrder predicates" that we constructed. */ + private final List totalOrderPredicates = new ArrayList(); + + /** Conjoin the constraints for "field declarations" and "fact" paragraphs */ + private void makeFacts(Expr facts) throws Err { + rep.debug("Generating facts...\n"); + // convert into a form that hopefully gives better unsat core + facts = (Expr) (new ConvToConjunction()).visitThis(facts); + // add the field facts and appended facts + for(Sig s: frame.getAllReachableSigs()) { + for(Decl d: s.getFieldDecls()) { + k2pos_enabled = false; + for(ExprHasName n: d.names) { + Field f = (Field)n; + Expr form = s.decl.get().join(f).in(d.expr); + form = s.isOne==null ? form.forAll(s.decl) : ExprLet.make(null, (ExprVar)(s.decl.get()), s, form); + frame.addFormula(cform(form), f); + // Given the above, we can be sure that every column is well-bounded (except possibly the first column). + // Thus, we need to add a bound that the first column is a subset of s. + if (s.isOne==null) { + Expression sr = a2k(s), fr = a2k(f); + for(int i=f.type().arity(); i>1; i--) fr=fr.join(Relation.UNIV); + frame.addFormula(fr.in(sr), f); + } + } + if (s.isOne==null && d.disjoint2!=null) for(ExprHasName f: d.names) { + Decl that = s.oneOf("that"); + Expr formula = s.decl.get().equal(that.get()).not().implies(s.decl.get().join(f).intersect(that.get().join(f)).no()); + frame.addFormula(cform(formula.forAll(that).forAll(s.decl)), d.disjoint2); + } + if (d.names.size()>1 && d.disjoint!=null) { frame.addFormula(cform(ExprList.makeDISJOINT(d.disjoint, null, d.names)), d.disjoint); } + } + k2pos_enabled = true; + for(Expr f: s.getFacts()) { + Expr form = s.isOne==null ? f.forAll(s.decl) : ExprLet.make(null, (ExprVar)(s.decl.get()), s, f); + frame.addFormula(cform(form), f); + } + } + k2pos_enabled = true; + recursiveAddFormula(facts); + } + + /** Break up x into conjuncts then add them each as a fact. */ + private void recursiveAddFormula(Expr x) throws Err { + if (x instanceof ExprList && ((ExprList)x).op==ExprList.Op.AND) { + for(Expr e: ((ExprList)x).args) recursiveAddFormula(e); + } else { + frame.addFormula(cform(x), x); + } + } + + //==============================================================================================================// + + private static final class GreedySimulator extends Simplifier { + private List totalOrderPredicates = null; + private Iterable allSigs = null; + private ConstList growableSigs = null; + private A4Solution partial = null; + public GreedySimulator() { } + private TupleSet convert(TupleFactory factory, Expr f) throws Err { + TupleSet old = ((A4TupleSet) (partial.eval(f))).debugGetKodkodTupleset(); + TupleSet ans = factory.noneOf(old.arity()); + for(Tuple oldT: old) { + Tuple newT = null; + for(int i=0; i unused) throws Err { + TupleFactory factory = sol.getFactory(); + TupleSet oldUniv = convert(factory, Sig.UNIV); + Set oldAtoms = new HashSet(); for(Tuple t: oldUniv) oldAtoms.add(t.atom(0)); + for(Sig s: allSigs) { + // The case below is STRICTLY an optimization; the entire statement can be removed without affecting correctness + if (s.isOne!=null && s.getFields().size()==2) + for(int i=0; i+3 sigs, Command usercommand, A4Options opt) throws Exception { + // FIXTHIS: if the next command has a "smaller scope" than the last command, we would get a Kodkod exception... + // FIXTHIS: if the solver is "toCNF" or "toKodkod" then this method will throw an Exception... + // FIXTHIS: does solution enumeration still work when we're doing a greedy solve? + TranslateAlloyToKodkod tr = null; + try { + long start = System.currentTimeMillis(); + GreedySimulator sim = new GreedySimulator(); + sim.allSigs = sigs; + sim.partial = null; + A4Reporter rep2 = new A4Reporter(rep) { + private boolean first = true; + public void translate(String solver, int bitwidth, int maxseq, int skolemDepth, int symmetry) { if (first) super.translate(solver, bitwidth, maxseq, skolemDepth, symmetry); first=false; } + public void resultSAT(Object command, long solvingTime, Object solution) { } + public void resultUNSAT(Object command, long solvingTime, Object solution) { } + }; + // Form the list of commands + List commands = new ArrayList(); + while(usercommand!=null) { commands.add(usercommand); usercommand = usercommand.parent; } + // For each command... + A4Solution sol = null; + for(int i=commands.size()-1; i>=0; i--) { + Command cmd = commands.get(i); + sim.growableSigs = cmd.getGrowableSigs(); + while(cmd != null) { + rep.debug(cmd.scope.toString()); + usercommand = cmd; + tr = new TranslateAlloyToKodkod(rep2, opt, sigs, cmd); + tr.makeFacts(cmd.formula); + sim.totalOrderPredicates = tr.totalOrderPredicates; + sol = tr.frame.solve(rep2, cmd, sim.partial==null || cmd.check ? new Simplifier() : sim, false); + if (!sol.satisfiable() && !cmd.check) { + start = System.currentTimeMillis() - start; + if (sim.partial==null) { rep.resultUNSAT(cmd, start, sol); return sol; } else { rep.resultSAT(cmd, start, sim.partial); return sim.partial; } + } + if (sol.satisfiable() && cmd.check) { + start = System.currentTimeMillis() - start; + rep.resultSAT(cmd, start, sol); return sol; + } + sim.partial = sol; + if (sim.growableSigs.isEmpty()) break; + for(Sig s: sim.growableSigs) { + CommandScope sc = cmd.getScope(s); + if (sc.increment > sc.endingScope - sc.startingScope) {cmd=null; break;} + cmd = cmd.change(s, sc.isExact, sc.startingScope+sc.increment, sc.endingScope, sc.increment); + } + } + } + if (sol.satisfiable()) rep.resultSAT(usercommand, System.currentTimeMillis()-start, sol); else rep.resultUNSAT(usercommand, System.currentTimeMillis()-start, sol); + return sol; + } catch(CapacityExceededException ex) { + throw rethrow(ex); + } catch(HigherOrderDeclException ex) { + Pos p = tr!=null ? tr.frame.kv2typepos(ex.decl().variable()).b : Pos.UNKNOWN; + throw new ErrorType(p, "Analysis cannot be performed since it requires higher-order quantification that could not be skolemized."); + } + } + + /** Based on the specified "options", execute one command and return the resulting A4Solution object. + * + * @param rep - if nonnull, we'll send compilation diagnostic messages to it + * @param sigs - the list of sigs; this list must be complete + * @param cmd - the Command to execute + * @param opt - the set of options guiding the execution of the command + * + * @return null if the user chose "save to FILE" as the SAT solver, + * and nonnull if the solver finishes the entire solving and is either satisfiable or unsatisfiable. + *

If the return value X is satisfiable, you can call X.next() to get the next satisfying solution X2; + * and you can call X2.next() to get the next satisfying solution X3... until you get an unsatisfying solution. + */ + public static A4Solution execute_command (A4Reporter rep, Iterable sigs, Command cmd, A4Options opt) throws Err { + if (rep==null) rep = A4Reporter.NOP; + TranslateAlloyToKodkod tr = null; + try { + if (cmd.parent!=null || !cmd.getGrowableSigs().isEmpty()) return execute_greedyCommand(rep, sigs, cmd, opt); + tr = new TranslateAlloyToKodkod(rep, opt, sigs, cmd); + tr.makeFacts(cmd.formula); + return tr.frame.solve(rep, cmd, new Simplifier(), false); + } catch(UnsatisfiedLinkError ex) { + throw new ErrorFatal("The required JNI library cannot be found: "+ex.toString().trim(), ex); + } catch(CapacityExceededException ex) { + throw rethrow(ex); + } catch(HigherOrderDeclException ex) { + Pos p = tr!=null ? tr.frame.kv2typepos(ex.decl().variable()).b : Pos.UNKNOWN; + throw new ErrorType(p, "Analysis cannot be performed since it requires higher-order quantification that could not be skolemized."); + } catch(Throwable ex) { + if (ex instanceof Err) throw (Err)ex; else throw new ErrorFatal("Unknown exception occurred: "+ex, ex); + } + } + + /** Based on the specified "options", execute one command and return the resulting A4Solution object. + * + *

Note: it will first test whether the model fits one of the model from the "Software Abstractions" book; + * if so, it will use the exact instance that was in the book. + * + * @param rep - if nonnull, we'll send compilation diagnostic messages to it + * @param sigs - the list of sigs; this list must be complete + * @param cmd - the Command to execute + * @param opt - the set of options guiding the execution of the command + * + * @return null if the user chose "save to FILE" as the SAT solver, + * and nonnull if the solver finishes the entire solving and is either satisfiable or unsatisfiable. + *

If the return value X is satisfiable, you can call X.next() to get the next satisfying solution X2; + * and you can call X2.next() to get the next satisfying solution X3... until you get an unsatisfying solution. + */ + public static A4Solution execute_commandFromBook (A4Reporter rep, Iterable sigs, Command cmd, A4Options opt) throws Err { + if (rep==null) rep = A4Reporter.NOP; + TranslateAlloyToKodkod tr = null; + try { + if (cmd.parent!=null || !cmd.getGrowableSigs().isEmpty()) return execute_greedyCommand(rep, sigs, cmd, opt); + tr = new TranslateAlloyToKodkod(rep, opt, sigs, cmd); + tr.makeFacts(cmd.formula); + return tr.frame.solve(rep, cmd, new Simplifier(), true); + } catch(UnsatisfiedLinkError ex) { + throw new ErrorFatal("The required JNI library cannot be found: "+ex.toString().trim(), ex); + } catch(CapacityExceededException ex) { + throw rethrow(ex); + } catch(HigherOrderDeclException ex) { + Pos p = tr!=null ? tr.frame.kv2typepos(ex.decl().variable()).b : Pos.UNKNOWN; + throw new ErrorType(p, "Analysis cannot be performed since it requires higher-order quantification that could not be skolemized."); + } catch(Throwable ex) { + if (ex instanceof Err) throw (Err)ex; else throw new ErrorFatal("Unknown exception occurred: "+ex, ex); + } + } + + /** Translate the Alloy expression into an equivalent Kodkod Expression or IntExpression or Formula object. + * @param sol - an existing satisfiable A4Solution object + * @param expr - this is the Alloy expression we want to translate + */ + public static Object alloy2kodkod(A4Solution sol, Expr expr) throws Err { + if (expr.ambiguous && !expr.errors.isEmpty()) expr = expr.resolve(expr.type(), null); + if (!expr.errors.isEmpty()) throw expr.errors.pick(); + TranslateAlloyToKodkod tr = new TranslateAlloyToKodkod(sol.getBitwidth(), sol.unrolls(), sol.a2k(), sol.s2k()); + Object ans; + try { + ans = tr.visitThis(expr); + } catch(UnsatisfiedLinkError ex) { + throw new ErrorFatal("The required JNI library cannot be found: "+ex.toString().trim()); + } catch(CapacityExceededException ex) { + throw rethrow(ex); + } catch(HigherOrderDeclException ex) { + throw new ErrorType("Analysis cannot be performed since it requires higher-order quantification that could not be skolemized."); + } catch(Throwable ex) { + if (ex instanceof Err) throw (Err)ex; + throw new ErrorFatal("Unknown exception occurred: "+ex, ex); + } + if ((ans instanceof IntExpression) || (ans instanceof Formula) || (ans instanceof Expression)) return ans; + throw new ErrorFatal("Unknown internal error encountered in the evaluator."); + } + + //==============================================================================================================// + + /** Convenience method that evalutes x and casts the result to be a Kodkod Formula. + * @return the formula - if x evaluates to a Formula + * @throws ErrorFatal - if x does not evaluate to a Formula + */ + private Formula cform(Expr x) throws Err { + if (!x.errors.isEmpty()) throw x.errors.pick(); + Object y=visitThis(x); + if (y instanceof Formula) return (Formula)y; + throw new ErrorFatal(x.span(), "This should have been a formula.\nInstead it is "+y); + } + + /** Convenience method that evalutes x and cast the result to be a Kodkod IntExpression. + * @return the integer expression - if x evaluates to an IntExpression + * @throws ErrorFatal - if x does not evaluate to an IntExpression + */ + private IntExpression cint(Expr x) throws Err { + if (!x.errors.isEmpty()) throw x.errors.pick(); + return toInt(x, visitThis(x)); + } + + private IntExpression toInt(Expr x, Object y) throws Err, ErrorFatal { + // simplify: if y is int[Int[sth]] then return sth + if (y instanceof ExprToIntCast) { + ExprToIntCast y2 = (ExprToIntCast) y; + if (y2.expression() instanceof IntToExprCast) + return ((IntToExprCast)y2.expression()).intExpr(); + } + // simplify: if y is Int[sth], then return sth + if (y instanceof IntToExprCast) + return ((IntToExprCast) y).intExpr(); + if (y instanceof IntExpression) + return (IntExpression)y; + //[AM]: maybe this conversion should be removed + if (y instanceof Expression) return ((Expression) y).sum(); + throw new ErrorFatal(x.span(), "This should have been an integer expression.\nInstead it is "+y); + } + + /** Convenience method that evaluаtes x and cast the result to be a Kodkod Expression. + * @return the expression - if x evaluates to an Expression + * @throws ErrorFatal - if x does not evaluate to an Expression + */ + private Expression cset(Expr x) throws Err { + if (!x.errors.isEmpty()) throw x.errors.pick(); + return toSet(x, visitThis(x)); + } + + private Expression toSet(Expr x, Object y) throws Err, ErrorFatal { + if (y instanceof Expression) return (Expression)y; + if (y instanceof IntExpression) return ((IntExpression) y).toExpression(); + throw new ErrorFatal(x.span(), "This should have been a set or a relation.\nInstead it is "+y); + } + + //==============================================================================================================// + + /** Given a variable name "name", prepend the current function name to form a meaningful "skolem name". + * (Note: this function does NOT, and need NOT guarantee that the name it generates is unique) + */ + private String skolem(String name) { + if (current_function.size()==0) { + if (cmd!=null && cmd.label.length()>0 && cmd.label.indexOf('$')<0) return cmd.label+"_"+name; else return name; + } + Func last=current_function.get(current_function.size()-1); + String funcname=tail(last.label); + if (funcname.indexOf('$')<0) return funcname+"_"+name; else return name; + } + + //==============================================================================================================// + + /** If x = SOMETHING->RELATION where SOMETHING.arity==1, then return the RELATION, else return null. */ + private static Relation right(Expression x) { + if (!(x instanceof BinaryExpression)) return null; + BinaryExpression bin = (BinaryExpression)x; + if (bin.op() != ExprOperator.PRODUCT) return null; + if (bin.left().arity()==1 && bin.right() instanceof Relation) return (Relation)(bin.right()); else return null; + } + + //==============================================================================================================// + + /*============================*/ + /* Evaluates an ExprITE node. */ + /*============================*/ + + /** {@inheritDoc} */ + @Override public Object visit(ExprITE x) throws Err { + Formula c = cform(x.cond); + Object l = visitThis(x.left); + if (l instanceof Formula) { + Formula c1 = c.implies((Formula)l); + Formula c2 = c.not().implies(cform(x.right)); + return k2pos(c1.and(c2), x); + } + if (l instanceof Expression) { + return c.thenElse((Expression)l, cset(x.right)); + } + return c.thenElse((IntExpression)l, cint(x.right)); + } + + /*============================*/ + /* Evaluates an ExprLet node. */ + /*============================*/ + + /** {@inheritDoc} */ + @Override public Object visit(ExprLet x) throws Err { + env.put(x.var, visitThis(x.expr)); + Object ans = visitThis(x.sub); + env.remove(x.var); + return ans; + } + + /*=================================*/ + /* Evaluates an ExprConstant node. */ + /*=================================*/ + + /** {@inheritDoc} */ + @Override public Object visit(ExprConstant x) throws Err { + switch(x.op) { + case MIN: return IntConstant.constant(min); //TODO + case MAX: return IntConstant.constant(max); //TODO + case NEXT: return A4Solution.KK_NEXT; + case TRUE: return Formula.TRUE; + case FALSE: return Formula.FALSE; + case EMPTYNESS: return Expression.NONE; + case IDEN: return Expression.IDEN.intersection(a2k(UNIV).product(Expression.UNIV)); + case STRING: + Expression ans = s2k(x.string); + if (ans==null) throw new ErrorFatal(x.pos, "String literal "+x+" does not exist in this instance.\n"); + return ans; + case NUMBER: + int n=x.num(); + //[am] const +// if (nmax) throw new ErrorType(x.pos, "Current bitwidth is set to "+bitwidth+", thus this integer constant "+n+" is bigger than the maximum integer "+max); + return IntConstant.constant(n).toExpression(); + } + throw new ErrorFatal(x.pos, "Unsupported operator ("+x.op+") encountered during ExprConstant.accept()"); + } + + /*==============================*/ + /* Evaluates an ExprUnary node. */ + /*==============================*/ + + /** {@inheritDoc} */ + @Override public Object visit(ExprUnary x) throws Err { + switch(x.op) { + case EXACTLYOF: case SOMEOF: case LONEOF: case ONEOF: case SETOF: return cset(x.sub); + case NOOP: return visitThis(x.sub); + case NOT: return k2pos( cform(x.sub).not() , x ); + case SOME: return k2pos( cset(x.sub).some() , x); + case LONE: return k2pos( cset(x.sub).lone() , x); + case ONE: return k2pos( cset(x.sub).one() , x); + case NO: return k2pos( cset(x.sub).no() , x); + case TRANSPOSE: return cset(x.sub).transpose(); + case CARDINALITY: return cset(x.sub).count(); + case CAST2SIGINT: return cint(x.sub).toExpression(); + case CAST2INT: return sum(cset(x.sub)); + case RCLOSURE: + Expression iden=Expression.IDEN.intersection(a2k(UNIV).product(Relation.UNIV)); + return cset(x.sub).closure().union(iden); + case CLOSURE: return cset(x.sub).closure(); + } + throw new ErrorFatal(x.pos, "Unsupported operator ("+x.op+") encountered during ExprUnary.visit()"); + } + + /** Performs int[x]; contains an efficiency shortcut that simplifies int[Int[x]] to x. */ + private IntExpression sum(Expression x) { + if (x instanceof IntToExprCast) return ((IntToExprCast)x).intExpr(); else return x.sum(); + } + + /*============================*/ + /* Evaluates an ExprVar node. */ + /*============================*/ + + /** {@inheritDoc} */ + @Override public Object visit(ExprVar x) throws Err { + Object ans=env.get(x); + if (ans==null) ans=a2k(x); + if (ans==null) throw new ErrorFatal(x.pos, "Variable \""+x+"\" is not bound to a legal value during translation.\n"); + return ans; + } + + /*=========================*/ + /* Evaluates a Field node. */ + /*=========================*/ + + /** {@inheritDoc} */ + @Override public Object visit(Field x) throws Err { + Expression ans = a2k(x); + if (ans==null) throw new ErrorFatal(x.pos, "Field \""+x+"\" is not bound to a legal value during translation.\n"); + return ans; + } + + /*=======================*/ + /* Evaluates a Sig node. */ + /*=======================*/ + + /** {@inheritDoc} */ + @Override public Object visit(Sig x) throws Err { + Expression ans = a2k(x); + if (ans==null) + throw new ErrorFatal(x.pos, "Sig \""+x+"\" is not bound to a legal value during translation.\n"); + return ans; + } + + /*=============================*/ + /* Evaluates an ExprCall node. */ + /*=============================*/ + + /** Caches parameter-less functions to a Kodkod Expression, Kodkod IntExpression, or Kodkod Formula. */ + private final Map cacheForConstants = new IdentityHashMap(); + + /** {@inheritDoc} */ + @Override public Object visit(ExprCall x) throws Err { + final Func f = x.fun; + final Object candidate = f.count()==0 ? cacheForConstants.get(f) : null; + if (candidate!=null) return candidate; + final Expr body = f.getBody(); + if (body.type().arity()<0 || body.type().arity()!=f.returnDecl.type().arity()) throw new ErrorType(body.span(), "Function return value not fully resolved."); + final int n = f.count(); + int maxRecursion = unrolls; + for(Func ff:current_function) if (ff==f) { + if (maxRecursion<0) { + throw new ErrorSyntax(x.span(), ""+f+" cannot call itself recursively!"); + } + if (maxRecursion==0) { + Type t = f.returnDecl.type(); + if (t.is_bool) return Formula.FALSE; + if (t.is_int()) return IntConstant.constant(0); + int i = t.arity(); + Expression ans = Expression.NONE; + while(i>1) { ans = ans.product(Expression.NONE); i--; } + return ans; + } + maxRecursion--; + } + Env newenv = new Env(); + for(int i=0; i oldenv = env; + env = newenv; + current_function.add(f); + Object ans = visitThis(body); + env = oldenv; + current_function.remove(current_function.size()-1); + if (ans instanceof Formula) k2pos((Formula)ans, x); + if (f.count()==0) cacheForConstants.put(f, ans); + return ans; + } + + /*================================*/ + /* Evaluates an ExprList node. */ + /*================================*/ + + /** Helper method that merge a list of conjuncts or disjoints while minimizing the AST depth (external caller should use i==1) */ + private Formula getSingleFormula(boolean isConjunct, int i, List formulas) throws Err { + // We actually build a "binary heap" where node X's two children are node 2X and node 2X+1 + int n = formulas.size(); + if (n==0) return isConjunct ? Formula.TRUE : Formula.FALSE; + Formula me = cform(formulas.get(i-1)), other; + int child1=i+i, child2=child1+1; + if (child1n) return me; + other = getSingleFormula(isConjunct, child1, formulas); if (isConjunct) me=me.and(other); else me=me.or(other); + if (child2<1 || child2>n) return me; + other = getSingleFormula(isConjunct, child2, formulas); if (isConjunct) me=me.and(other); else me=me.or(other); + return me; + } + + /** {@inheritDoc} */ + @Override public Object visit(ExprList x) throws Err { + if (x.op == ExprList.Op.AND || x.op == ExprList.Op.OR) { + if (x.args.size()==0) return (x.op==ExprList.Op.AND) ? Formula.TRUE : Formula.FALSE; + Formula answer = getSingleFormula(x.op==ExprList.Op.AND, 1, x.args); + return k2pos(answer, x); + } + if (x.op == ExprList.Op.TOTALORDER) { + Expression elem = cset(x.args.get(0)), first = cset(x.args.get(1)), next = cset(x.args.get(2)); + if (elem instanceof Relation && first instanceof Relation && next instanceof Relation) { + Relation lst = frame.addRel("", null, frame.query(true, (Relation)elem, false)); + totalOrderPredicates.add((Relation)elem); totalOrderPredicates.add((Relation)first); totalOrderPredicates.add(lst); totalOrderPredicates.add((Relation)next); + return k2pos(((Relation)next).totalOrder((Relation)elem, (Relation)first, lst), x); + } + Formula f1 = elem.in(first.join(next.reflexiveClosure())); // every element is in the total order + Formula f2 = next.join(first).no(); // first element has no predecessor + Variable e = Variable.unary("v" + Integer.toString(cnt++)); + Formula f3 = e.eq(first).or(next.join(e).one()); // each element (except the first) has one predecessor + Formula f4 = e.eq(elem.difference(next.join(elem))).or(e.join(next).one()); // each element (except the last) has one successor + Formula f5 = e.in(e.join(next.closure())).not(); // there are no cycles + return k2pos(f3.and(f4).and(f5).forAll(e.oneOf(elem)).and(f1).and(f2), x); + } + // This says no(a&b) and no((a+b)&c) and no((a+b+c)&d)... + // Emperically this seems to be more efficient than "no(a&b) and no(a&c) and no(b&c)" + Formula answer = null; + Expression a = null; + for(Expr arg:x.args) { + Expression b=cset(arg); + if (a==null) {a=b;continue;} + if (answer==null) answer=a.intersection(b).no(); else answer=a.intersection(b).no().and(answer); + a=a.union(b); + } + if (answer!=null) return k2pos(answer, x); else return Formula.TRUE; + } + + /*===============================*/ + /* Evaluates an ExprBinary node. */ + /*===============================*/ + + /** {@inheritDoc} */ + @Override public Object visit(ExprBinary x) throws Err { + Expr a=x.left, b=x.right; + Expression s, s2, eL, eR; IntExpression i; Formula f; Object objL, objR; + switch(x.op) { + case IMPLIES: f=cform(a).not().or(cform(b)); return k2pos(f,x); + case IN: return k2pos(isIn(cset(a),b), x); + case NOT_IN: return k2pos(isIn(cset(a),b).not(), x); + case LT: i=cint(a); f=i.lt(cint(b)); return k2pos(f,x); + case LTE: i=cint(a); f=i.lte(cint(b)); return k2pos(f,x); + case GT: i=cint(a); f=i.gt(cint(b)); return k2pos(f,x); + case GTE: i=cint(a); f=i.gte(cint(b)); return k2pos(f,x); + case NOT_LT: i=cint(a); f=i.lt(cint(b)).not(); return k2pos(f,x); + case NOT_LTE: i=cint(a); f=i.lte(cint(b)).not(); return k2pos(f,x); + case NOT_GT: i=cint(a); f=i.gt(cint(b)).not(); return k2pos(f,x); + case NOT_GTE: i=cint(a); f=i.gte(cint(b)).not(); return k2pos(f,x); + case AND: f=cform(a); f=f.and(cform(b)); return k2pos(f,x); + case OR: f=cform(a); f=f.or(cform(b)); return k2pos(f,x); + case IFF: f=cform(a); f=f.iff(cform(b)); return k2pos(f,x); + case PLUSPLUS: s=cset(a); return s.override(cset(b)); + case MUL: i=cint(a); return i.multiply(cint(b)); + case DIV: i=cint(a); return i.divide(cint(b)); + case REM: i=cint(a); return i.modulo(cint(b)); + case SHL: i=cint(a); return i.shl(cint(b)); + case SHR: i=cint(a); return i.shr(cint(b)); + case SHA: i=cint(a); return i.sha(cint(b)); + case PLUS: + return cset(a).union(cset(b)); + //[AM] +// obj = visitThis(a); +// if (obj instanceof IntExpression) { i=(IntExpression)obj; return i.plus(cint(b)); } +// s = (Expression)obj; return s.union(cset(b)); + case IPLUS: + return cint(a).plus(cint(b)); + case MINUS: + // Special exception to allow "0-8" to not throw an exception, where 7 is the maximum allowed integer (when bitwidth==4) + // (likewise, when bitwidth==5, then +15 is the maximum allowed integer, and we want to allow 0-16 without throwing an exception) + if (a instanceof ExprConstant && ((ExprConstant)a).op==ExprConstant.Op.NUMBER && ((ExprConstant)a).num()==0) + if (b instanceof ExprConstant && ((ExprConstant)b).op==ExprConstant.Op.NUMBER && ((ExprConstant)b).num()==max+1) + return IntConstant.constant(min); + return cset(a).difference(cset(b)); + //[AM] +// obj=visitThis(a); +// if (obj instanceof IntExpression) { i=(IntExpression)obj; return i.minus(cint(b));} +// s=(Expression)obj; return s.difference(cset(b)); + case IMINUS: + return cint(a).minus(cint(b)); + case INTERSECT: + s=cset(a); return s.intersection(cset(b)); + case ANY_ARROW_SOME: case ANY_ARROW_ONE: case ANY_ARROW_LONE: + case SOME_ARROW_ANY: case SOME_ARROW_SOME: case SOME_ARROW_ONE: case SOME_ARROW_LONE: + case ONE_ARROW_ANY: case ONE_ARROW_SOME: case ONE_ARROW_ONE: case ONE_ARROW_LONE: + case LONE_ARROW_ANY: case LONE_ARROW_SOME: case LONE_ARROW_ONE: case LONE_ARROW_LONE: + case ISSEQ_ARROW_LONE: + case ARROW: + s=cset(a); return s.product(cset(b)); + case JOIN: + a=a.deNOP(); s=cset(a); s2=cset(b); + if (a instanceof Sig && ((Sig)a).isOne!=null && s2 instanceof BinaryExpression) { + BinaryExpression bin = (BinaryExpression)s2; + if (bin.op()==ExprOperator.PRODUCT && bin.left()==s) return bin.right(); + } + return s.join(s2); + case EQUALS: + objL = visitThis(a); + objR = visitThis(b); + eL = toSet(a, objL); + eR = toSet(b, objR); + if (eL instanceof IntToExprCast && eR instanceof IntToExprCast) + f = ((IntToExprCast) eL).intExpr().eq(((IntToExprCast) eR).intExpr()); + else + f = eL.eq(eR); + return k2pos(f, x); + case NOT_EQUALS: + objL = visitThis(a); + objR = visitThis(b); + eL = toSet(a, objL); + eR = toSet(b, objR); + if (eL instanceof IntToExprCast && eR instanceof IntToExprCast) + f = ((IntToExprCast) eL).intExpr().eq(((IntToExprCast) eR).intExpr()).not(); + else + f = eL.eq(eR).not(); + return k2pos(f, x); + case DOMAIN: + s=cset(a); + s2=cset(b); + for(int j=s2.arity(); j>1; j--) s=s.product(Expression.UNIV); + return s.intersection(s2); + case RANGE: + s=cset(a); + s2=cset(b); + for(int j=s.arity(); j>1; j--) s2=Expression.UNIV.product(s2); + return s.intersection(s2); + } + throw new ErrorFatal(x.pos, "Unsupported operator ("+x.op+") encountered during ExprBinary.accept()"); + } + + /** Helper method that translates the formula "a in b" into a Kodkod formula. */ + private Formula isIn(Expression a, Expr right) throws Err { + Expression b; + if (right instanceof ExprBinary && right.mult!=0 && ((ExprBinary)right).op.isArrow) { + // Handles possible "binary" or higher-arity multiplicity + return isInBinary(a, (ExprBinary)right); + } + switch(right.mult()) { + case EXACTLYOF: b=cset(right); return a.eq(b); + case ONEOF: b=cset(right); return a.one().and(a.in(b)); + case LONEOF: b=cset(right); return a.lone().and(a.in(b)); + case SOMEOF: b=cset(right); return a.some().and(a.in(b)); + default: b=cset(right); return a.in(b); + } + } + + //[AM] + private static boolean am = true; + + /** Helper method that translates the formula "r in (a ?->? b)" into a Kodkod formula. */ + private Formula isInBinary(Expression r, ExprBinary ab) throws Err { + final Expression a=cset(ab.left), b=cset(ab.right); + Decls d=null, d2=null; + Formula ans1, ans2; + // "R in A ->op B" means for each tuple a in A, there are "op" tuples in r that begins with a. + Expression atuple=null, ar=r; + for(int i=a.arity(); i>0; i--) { + Variable v=Variable.unary("v" + Integer.toString(cnt++)); + if (!am) { + if (a.arity()==1) d=v.oneOf(a); else if (d==null) d=v.oneOf(Relation.UNIV); else d=v.oneOf(Relation.UNIV).and(d); + } else { + d = am(a, d, i, v); + } + ar=v.join(ar); + if (atuple==null) atuple=v; else atuple=atuple.product(v); + } + ans1=isIn(ar, ab.right); + switch(ab.op) { + case ISSEQ_ARROW_LONE: + case ANY_ARROW_LONE: case SOME_ARROW_LONE: case ONE_ARROW_LONE: case LONE_ARROW_LONE: ans1=ar.lone().and(ans1); break; + case ANY_ARROW_ONE: case SOME_ARROW_ONE: case ONE_ARROW_ONE: case LONE_ARROW_ONE: ans1=ar.one().and(ans1); break; + case ANY_ARROW_SOME: case SOME_ARROW_SOME: case ONE_ARROW_SOME: case LONE_ARROW_SOME: ans1=ar.some().and(ans1); break; + } + if (a.arity()>1) { Formula tmp=isIn(atuple, ab.left); if (tmp!=Formula.TRUE) ans1=tmp.implies(ans1); } + ans1=ans1.forAll(d); + // "R in A op-> B" means for each tuple b in B, there are "op" tuples in r that end with b. + Expression btuple=null, rb=r; + for(int i=b.arity(); i>0; i--) { + Variable v=Variable.unary("v" + Integer.toString(cnt++)); + if (!am) { + if (b.arity()==1) d2=v.oneOf(b); else if (d2==null) d2=v.oneOf(Relation.UNIV); else d2=v.oneOf(Relation.UNIV).and(d2); + } else { + d2 = am(b, d2, i, v); + } + rb=rb.join(v); + if (btuple==null) btuple=v; else btuple=v.product(btuple); + } + ans2=isIn(rb, ab.left); + switch(ab.op) { + case LONE_ARROW_ANY: case LONE_ARROW_SOME: case LONE_ARROW_ONE: case LONE_ARROW_LONE: ans2=rb.lone().and(ans2); break; + case ONE_ARROW_ANY: case ONE_ARROW_SOME: case ONE_ARROW_ONE: case ONE_ARROW_LONE: ans2=rb.one().and(ans2); break; + case SOME_ARROW_ANY: case SOME_ARROW_SOME: case SOME_ARROW_ONE: case SOME_ARROW_LONE: ans2=rb.some().and(ans2); break; + } + if (b.arity()>1) { Formula tmp=isIn(btuple, ab.right); if (tmp!=Formula.TRUE) ans2=tmp.implies(ans2); } + ans2=ans2.forAll(d2); + // Now, put everything together + Formula ans=r.in(a.product(b)).and(ans1).and(ans2); + if (ab.op==ExprBinary.Op.ISSEQ_ARROW_LONE) { + Expression rr=r; + while(rr.arity()>1) rr=rr.join(Relation.UNIV); + ans=rr.difference(rr.join(A4Solution.KK_NEXT)).in(A4Solution.KK_ZERO).and(ans); + } + return ans; + } + + private Decls am(final Expression a, Decls d, int i, Variable v) { + kodkod.ast.Decl ddd; + if (a.arity() == 1) { + assert i == 1; + ddd = v.oneOf(a); + } else { + ddd = v.oneOf(a.project(IntConstant.constant(i - 1))); + } + if (d == null) + d = ddd; + else + d = ddd.and(d); + return d; + } + + /*===========================*/ + /* Evaluates an ExprQt node. */ + /*===========================*/ + + /** Adds a "one of" in front of X if X is unary and does not have a declared multiplicity. */ + private static Expr addOne(Expr x) { + Expr save = x; + while(x instanceof ExprUnary) { + switch(((ExprUnary)x).op) { + case EXACTLYOF: case SETOF: case ONEOF: case LONEOF: case SOMEOF: return save; + case NOOP: x = ((ExprUnary)x).sub; continue; + default: break; + } + } + return (x.type().arity()!=1) ? x : ExprUnary.Op.ONEOF.make(x.span(), x); + } + + /** Helper method that translates the quantification expression "op vars | sub" */ + private Object visit_qt(final ExprQt.Op op, final ConstList xvars, final Expr sub) throws Err { + if (op == ExprQt.Op.NO) { + return visit_qt(ExprQt.Op.ALL, xvars, sub.not()); + } + if (op == ExprQt.Op.ONE || op == ExprQt.Op.LONE) { + boolean ok = true; + for(int i=0; i guards = new ArrayList(); + for(Decl dep: xvars) { + final Expr dexexpr = addOne(dep.expr); + final Expression dv = cset(dexexpr); + for(ExprHasName dex: dep.names) { + final Variable v = Variable.nary(skolem(dex.label), dex.type().arity()); + final kodkod.ast.Decl newd; + env.put((ExprVar)dex, v); + if (dex.type().arity()!=1) { + guards.add(isIn(v, dexexpr)); + newd = v.setOf(dv); + } else switch(dexexpr.mult()) { + case SETOF: newd = v.setOf(dv); break; + case SOMEOF: newd = v.someOf(dv); break; + case LONEOF: newd = v.loneOf(dv); break; + default: newd = v.oneOf(dv); + } + if (frame!=null) frame.kv2typepos(v, dex.type(), dex.pos); + if (dd==null) dd = newd; else dd = dd.and(newd); + } + } + final Formula ans = (op==ExprQt.Op.SUM) ? null : cform(sub) ; + final IntExpression ians = (op!=ExprQt.Op.SUM) ? null : cint(sub) ; + for(Decl d: xvars) for(ExprHasName v: d.names) env.remove((ExprVar)v); + if (op==ExprQt.Op.COMPREHENSION) return ans.comprehension(dd); // guards.size()==0, since each var has to be unary + if (op==ExprQt.Op.SUM) return ians.sum(dd); // guards.size()==0, since each var has to be unary + if (op==ExprQt.Op.SOME) { + if (guards.size()==0) return ans.forSome(dd); + guards.add(ans); + return Formula.and(guards).forSome(dd); + } else { + if (guards.size()==0) return ans.forAll(dd); + return Formula.and(guards).implies(ans).forAll(dd); + } + } + + /** {@inheritDoc} */ + @Override public Object visit(ExprQt x) throws Err { + Expr xx = x.desugar(); + if (xx instanceof ExprQt) x = (ExprQt)xx; else return visitThis(xx); + Object ans = visit_qt(x.op, x.decls, x.sub); + if (ans instanceof Formula) k2pos((Formula)ans, x); + return ans; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/TranslateKodkodToJava.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/TranslateKodkodToJava.java new file mode 100644 index 00000000..a306aa95 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4compiler/translator/TranslateKodkodToJava.java @@ -0,0 +1,632 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4compiler.translator; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.ArrayList; +import java.util.IdentityHashMap; +import java.util.Map; +import java.io.PrintWriter; +import java.io.StringWriter; +import kodkod.ast.BinaryExpression; +import kodkod.ast.BinaryFormula; +import kodkod.ast.BinaryIntExpression; +import kodkod.ast.ComparisonFormula; +import kodkod.ast.Comprehension; +import kodkod.ast.ConstantExpression; +import kodkod.ast.ConstantFormula; +import kodkod.ast.Decl; +import kodkod.ast.Decls; +import kodkod.ast.ExprToIntCast; +import kodkod.ast.IfExpression; +import kodkod.ast.IfIntExpression; +import kodkod.ast.IntComparisonFormula; +import kodkod.ast.IntConstant; +import kodkod.ast.IntExpression; +import kodkod.ast.IntToExprCast; +import kodkod.ast.NaryExpression; +import kodkod.ast.NaryFormula; +import kodkod.ast.NaryIntExpression; +import kodkod.ast.Node; +import kodkod.ast.ProjectExpression; +import kodkod.ast.MultiplicityFormula; +import kodkod.ast.NotFormula; +import kodkod.ast.QuantifiedFormula; +import kodkod.ast.Relation; +import kodkod.ast.RelationPredicate; +import kodkod.ast.UnaryExpression; +import kodkod.ast.SumExpression; +import kodkod.ast.UnaryIntExpression; +import kodkod.ast.Variable; +import kodkod.ast.Expression; +import kodkod.ast.Formula; +import kodkod.ast.RelationPredicate.Function; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; +import kodkod.instance.Bounds; +import kodkod.instance.TupleSet; +import kodkod.instance.Tuple; +import kodkod.util.ints.IndexedEntry; +import kodkod.util.nodes.PrettyPrinter; + +/** Translate a Kodkod formula node to an equivalent Java program that solves the formula. + * + *

Requirements: atoms must be String objects (since we cannot possibly + * output a Java source code that can re-generate arbitrary Java objects). + */ + +public final class TranslateKodkodToJava implements VoidVisitor { + + /** Count the height of the given Kodkod AST tree. */ + public static int countHeight(Node node) { + ReturnVisitor vis = new ReturnVisitor() { + private int max(int a, int b) { return (a>=b) ? a : b; } + private int max(int a, int b, int c) { return (a>=b) ? (a>=c ? a : c) : (b>=c ? b: c); } + public Integer visit(Relation x) { return 1; } + public Integer visit(IntConstant x) { return 1; } + public Integer visit(ConstantFormula x) { return 1; } + public Integer visit(Variable x) { return 1; } + public Integer visit(ConstantExpression x) { return 1; } + public Integer visit(NotFormula x) { return 1 + x.formula().accept(this); } + public Integer visit(IntToExprCast x) { return 1 + x.intExpr().accept(this); } + public Integer visit(Decl x) { return 1 + x.expression().accept(this); } + public Integer visit(ExprToIntCast x) { return 1 + x.expression().accept(this); } + public Integer visit(UnaryExpression x) { return 1 + x.expression().accept(this); } + public Integer visit(UnaryIntExpression x) { return 1 + x.intExpr().accept(this); } + public Integer visit(MultiplicityFormula x) { return 1 + x.expression().accept(this); } + public Integer visit(BinaryExpression x) { return 1 + max(x.left().accept(this), x.right().accept(this)); } + public Integer visit(ComparisonFormula x) { return 1 + max(x.left().accept(this), x.right().accept(this)); } + public Integer visit(BinaryFormula x) { return 1 + max(x.left().accept(this), x.right().accept(this)); } + public Integer visit(BinaryIntExpression x) { return 1 + max(x.left().accept(this), x.right().accept(this)); } + public Integer visit(IntComparisonFormula x) { return 1 + max(x.left().accept(this), x.right().accept(this)); } + public Integer visit(IfExpression x) { return 1 + max(x.condition().accept(this), x.thenExpr().accept(this), x.elseExpr().accept(this)); } + public Integer visit(IfIntExpression x) { return 1 + max(x.condition().accept(this), x.thenExpr().accept(this), x.elseExpr().accept(this)); } + public Integer visit(SumExpression x) { return 1 + max(x.decls().accept(this), x.intExpr().accept(this)); } + public Integer visit(QuantifiedFormula x) { return 1 + max(x.decls().accept(this), x.formula().accept(this)); } + public Integer visit(Comprehension x) { return 1 + max(x.decls().accept(this), x.formula().accept(this)); } + public Integer visit(Decls x) { + int max = 0, n = x.size(); + for(int i=0; i t = x.columns(); t.hasNext();) { max = max(max, t.next().accept(this)); } + return max; + } + public Integer visit(RelationPredicate x) { + if (x instanceof Function) { + Function f = ((Function)x); + return max(f.domain().accept(this), f.range().accept(this)); + } + return 1; + } + public Integer visit(NaryExpression x) { + int max = 0; + for(int m=0, n=x.size(), i=0; i Requirement: atoms must be String objects (since we cannot possibly + * output a Java source code that can re-generate arbitrary Java objects). + * + * @param formula - the formula to convert + * @param bitwidth - the integer bitwidth + * @param atoms - an iterator over the set of all atoms + * @param bounds - the Kodkod bounds object to use + * @param atomMap - if nonnull, it is used to map the atom name before printing + */ + public static String convert + (Formula formula, int bitwidth, Iterable atoms, Bounds bounds, Map atomMap) { + StringWriter string=new StringWriter(); + PrintWriter file=new PrintWriter(string); + new TranslateKodkodToJava(file, formula, bitwidth, atoms, bounds, atomMap); + if (file.checkError()) { + return ""; // shouldn't happen + } else { + return string.toString(); + } + } + + /** The PrintWriter that is receiving the text. */ + private final PrintWriter file; + + /** This caches nodes that we have already generated. */ + private final IdentityHashMap map=new IdentityHashMap(); + + /** Given a node, return its name (if no name has been chosen, then make a new name) */ + private String makename(Node obj) { + if (map.containsKey(obj)) return null; + String name="x"+(map.size()); + map.put(obj, name); + return name; + } + + /** Given a node, call the visitor to dump its text out, then return its name. */ + private String make(Node x) { x.accept(this); return map.get(x); } + + /** Constructor is private, so that the only way to access this class is via the static convert() method. */ + private TranslateKodkodToJava + (PrintWriter pw, Formula x, int bitwidth, Iterable atoms, Bounds bounds, Map atomMap) { + file=pw; + file.printf("import java.util.Arrays;%n"); + file.printf("import java.util.List;%n"); + file.printf("import kodkod.ast.*;%n"); + file.printf("import kodkod.ast.operator.*;%n"); + file.printf("import kodkod.instance.*;%n"); + file.printf("import kodkod.engine.*;%n"); + file.printf("import kodkod.engine.satlab.SATFactory;%n"); + file.printf("import kodkod.engine.config.Options;%n%n"); + + file.printf("/* %n"); + file.printf(" ==================================================%n"); + file.printf(" kodkod formula: %n"); + file.printf(" ==================================================%n"); + file.print(PrettyPrinter.print(x, 4) + "\n"); + file.printf(" ==================================================%n"); + file.printf("*/%n"); + file.printf("public final class Test {%n%n"); + file.printf("public static void main(String[] args) throws Exception {%n%n"); + ArrayList atomlist=new ArrayList(); + for(Object a:atoms) { + String b = atomMap==null ? null : atomMap.get(a); + atomlist.add(b==null ? a.toString() : b); + } + Collections.sort(atomlist); + for(Relation r:bounds.relations()) { + String name=makename(r); + int a=r.arity(); + if (a==1) + file.printf("Relation %s = Relation.unary(\"%s\");%n", name, r.name()); + else + file.printf("Relation %s = Relation.nary(\"%s\", %d);%n", name, r.name(), a); + } + file.printf("%nList atomlist = Arrays.asList(%n"); + int j=(-1); + for(String a:atomlist) { + if (j!=(-1)) file.printf(","); else j=0; + if (j==5) {file.printf("%n "); j=0;} else {file.printf(" "); j++;} + file.printf("\"%s\"", a); + } + file.printf("%n);%n%n"); + file.printf("Universe universe = new Universe(atomlist);%n"); + file.printf("TupleFactory factory = universe.factory();%n"); + file.printf("Bounds bounds = new Bounds(universe);%n%n"); + for(Relation r:bounds.relations()) { + String n=map.get(r); + TupleSet upper=bounds.upperBound(r); + TupleSet lower=bounds.lowerBound(r); + printTupleset(n+"_upper", upper, atomMap); + if (upper.equals(lower)) { + file.printf("bounds.boundExactly(%s, %s_upper);%n%n",n,n); + } + else if (lower.size()==0) { + file.printf("bounds.bound(%s, %s_upper);%n%n",n,n); + } + else { + printTupleset(n+"_lower", lower, atomMap); + file.printf("bounds.bound(%s, %s_lower, %s_upper);%n%n",n,n,n); + } + } + for(IndexedEntry i:bounds.intBounds()) { + for(Tuple t:i.value()) { + Object a = t.atom(0); + String b = (atomMap!=null ? atomMap.get(a) : null); + String c = (b!=null? b : a.toString()); + file.printf("bounds.boundExactly(%d,factory.range(" + +"factory.tuple(\"%s\"),factory.tuple(\"%s\")));%n", i.index(), c, c); + } + } + file.printf("%n"); + String result=make(x); + file.printf("%nSolver solver = new Solver();"); + file.printf("%nsolver.options().setSolver(SATFactory.DefaultSAT4J);"); + file.printf("%nsolver.options().setBitwidth(%d);",bitwidth != 0 ? bitwidth : 1); + file.printf("%nsolver.options().setFlatten(false);"); + file.printf("%nsolver.options().setIntEncoding(Options.IntEncoding.TWOSCOMPLEMENT);"); + file.printf("%nsolver.options().setSymmetryBreaking(20);"); + file.printf("%nsolver.options().setSkolemDepth(0);"); + file.printf("%nSystem.out.println(\"Solving...\");"); + file.printf("%nSystem.out.flush();"); + file.printf("%nSolution sol = solver.solve(%s,bounds);", result); + file.printf("%nSystem.out.println(sol.toString());"); + file.printf("%n}}%n"); + file.close(); + } + + /** Print the tupleset using the name n. */ + private void printTupleset(String n, TupleSet ts, Map atomMap) { + file.printf("TupleSet %s = factory.noneOf(%d);%n", n, ts.arity()); + for(Tuple t:ts) { + file.printf("%s.add(",n); + for(int i=0; i names=new ArrayList(); + for(Iterator i = x.columns(); i.hasNext(); ) { names.add(make(i.next())); } + for(int i=0; i 0; i--) { + // get enough space into the buffer for the cnf header, which will be written last + buffer.append(' '); + } + buffer.append('\n'); + } catch (Exception ex) { + throw new RuntimeException("WriteCNF failed.", ex); + } + } + + /** Helper method that flushes the buffer. */ + private void flush() { + try { + cnf.writeBytes(buffer.toString()); + buffer.setLength(0); + } catch (IOException ex) { + throw new RuntimeException("WriteCNF failed.", ex); + } + } + + /** {@inheritDoc} */ + @Override protected void finalize() throws Throwable { + super.finalize(); + free(); + } + + /** {@inheritDoc} */ + public void free() { Util.close(cnf); } + + /** {@inheritDoc} */ + public void addVariables(int numVars) { if (numVars >= 0) vars += numVars; } + + /** {@inheritDoc} */ + public boolean addClause(int[] lits) { + if (lits.length>0) { + clauses++; + if (buffer.length() > capacity) flush(); + for(int i=0; i exactly 1 INSTANCE + 0 or more SOURCE + +INSTANCE = 0 or more PRIMSIG + 0 or more SUBSETSIG + 0 or more FIELD + 0 or more SKOLEM + +PRIMSIG = 0 or more ATOM + +SUBSETSIG = 0 or more ATOM + 1 or more TYPE + +FIELD = 0 or more TUPLE + 1 or more TYPES + +SKOLEM = 0 or more TUPLE + 1 or more TYPES + +TUPLE = 1 or more ATOM +ATOM = + +TYPES = 1 or more TYPE +TYPE = + +SOURCE = diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/Artist.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/Artist.java new file mode 100644 index 00000000..4566fd6a --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/Artist.java @@ -0,0 +1,204 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4graph; + +import static java.awt.BasicStroke.CAP_ROUND; +import static java.awt.BasicStroke.JOIN_ROUND; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.geom.CubicCurve2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import edu.mit.csail.sdg.alloy4.OurPDFWriter; + +/** This class abstracts the drawing operations so that we can + * draw the graph using different frameworks such as Java2D or PDF. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final strictfp class Artist { + + /** The font name. */ + private static final String fontName = "Lucida Grande"; + + /** The font size. */ + private static final int fontSize = 12; + + /** The corresponding Graphics2D object. */ + private Graphics2D gr; + + /** The corresponding OurPDFWriter. */ + private OurPDFWriter pdf; + + /** Construct an artist that acts as a wrapper around the given Graphics2D object. */ + public Artist(Graphics2D graphics2D) { this.gr=graphics2D; this.pdf=null; } + + /** Construct an artist that acts as a wrapper around the given OurPDFWriter object. */ + public Artist(OurPDFWriter pdfWriter) { this.gr=null; this.pdf=pdfWriter; } + + /** Shifts the coordinate space by the given amount. */ + public void translate(int x, int y) { if (gr!=null) gr.translate(x,y); else pdf.shiftCoordinateSpace(x, y); } + + /** Draws a circle of the given radius, centered at (0,0) */ + public void drawCircle(int radius) { if (gr!=null) gr.drawArc(-radius, -radius, radius*2, radius*2, 0, 360); else pdf.drawCircle(radius, false); } + + /** Fills a circle of the given radius, centered at (0,0) */ + public void fillCircle(int radius) { if (gr!=null) gr.fillArc(-radius, -radius, radius*2, radius*2, 0, 360); else pdf.drawCircle(radius, true); } + + /** Draws a line from (x1,y1) to (x2,y2) */ + public void drawLine(int x1, int y1, int x2, int y2) { if (gr!=null) gr.drawLine(x1,y1,x2,y2); else pdf.drawLine(x1, y1, x2, y2); } + + /** Changes the current color. */ + public void setColor(Color color) { if (gr!=null) gr.setColor(color); else pdf.setColor(color); } + + /** Returns true if left<=x<=right or right<=x<=left. */ + private static boolean in(double left, double x, double right) { return (left<=x && x<=right) || (right<=x && x<=left); } + + /** Draws the given curve smoothly (assuming the curve is monotonic vertically) */ + public void drawSmoothly(Curve curve) { + final int smooth=15; + double cx=0, cy=0, slope; + for(int n=curve.list.size(), i=0; i0) { c.ctrlx1=cx; c.ctrly1=cy; } + if (c2==null) { draw(c,false); return; } + if ((c.x1c.x2 && c2.x2>c2.x1)) slope=0; else slope=(c2.x2-c.x1)/(c2.y2-c.y1); + double tmp=c.y2-smooth, tmpx=c.x2-smooth*slope; + if (tmp>c.ctrly1 && tmpc2.y1 && tmp2 NOTE: as a special guarantee, if gr2d==null, then this method returns immediately without doing anything. + *

NOTE: just like the typical AWT and Swing methods, this method can be called only by the AWT event dispatching thread. + */ + public void set(DotStyle style, double scale) { + if (gr!=null) { + BasicStroke bs; + switch(style) { + case BOLD: bs=new BasicStroke(scale>1 ? (float)(2.6d/scale) : 2.6f); break; + case DOTTED: bs=new BasicStroke(scale>1 ? (float)(1.3d/scale) : 1.3f, CAP_ROUND, JOIN_ROUND, 15f, dot, 0f); break; + case DASHED: bs=new BasicStroke(scale>1 ? (float)(1.3d/scale) : 1.3f, CAP_ROUND, JOIN_ROUND, 15f, dashed, 5f); break; + default: bs=new BasicStroke(scale>1 ? (float)(1.3d/scale) : 1.3f); + } + gr.setStroke(bs); + return; + } + switch(style) { + case BOLD: pdf.setBoldLine(); return; + case DOTTED: pdf.setDottedLine(); return; + case DASHED: pdf.setDashedLine(); return; + default: pdf.setNormalLine(); return; + } + } + + /** Saves the current font boldness. */ + private boolean fontBoldness = false; + + /** Changes the current font. */ + public void setFont(boolean fontBoldness) { + calc(); + if (gr!=null) gr.setFont(fontBoldness ? cachedBoldFont : cachedPlainFont); else this.fontBoldness=fontBoldness; + } + + /** Draws the given string at (x,y) */ + public void drawString(String text, int x, int y) { + if (text.length()==0) return; + if (gr!=null) { gr.drawString(text,x,y); return; } + calc(); + Font font = (fontBoldness ? cachedBoldFont : cachedPlainFont); + GlyphVector gv = font.createGlyphVector(new FontRenderContext(null,false,false), text); + translate(x,y); + draw(gv.getOutline(), true); + translate(-x,-y); + } + + /** If nonnull, it caches a Graphics2D object for calculating string bounds. */ + private static Graphics2D cachedGraphics = null; + + /** If nonnull, it caches a FontMetrics object associated with the nonbold font. */ + private static FontMetrics cachedPlainMetrics = null; + + /** If nonnull, it caches a FontMetrics object associated with the bold font. */ + private static FontMetrics cachedBoldMetrics = null; + + /** If nonnull, it caches the nonbold Font. */ + private static Font cachedPlainFont = null; + + /** If nonnull, it caches the bold Font. */ + private static Font cachedBoldFont = null; + + /** If nonnegative, it caches the maximum ascent of the font. */ + private static int cachedMaxAscent = -1; + + /** If nonnegative, it caches the maximum descent of the font. */ + private static int cachedMaxDescent = -1; + + /** Allocates the nonbold and bold fonts, then calculates the max ascent and descent. */ + private static void calc() { + if (cachedMaxDescent >= 0) return; // already done + BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); + cachedGraphics = (Graphics2D)(image.getGraphics()); + cachedPlainMetrics = cachedGraphics.getFontMetrics(cachedPlainFont = new Font(fontName, Font.PLAIN, fontSize)); + cachedBoldMetrics = cachedGraphics.getFontMetrics(cachedBoldFont = new Font(fontName, Font.BOLD, fontSize)); + cachedGraphics.setFont(cachedPlainFont); + cachedMaxAscent = cachedPlainMetrics.getMaxAscent(); + cachedMaxDescent = cachedPlainMetrics.getMaxDescent(); + } + + /** Returns the max ascent when drawing text using the given font size and font boldness settings. */ + public static int getMaxAscent() { + calc(); + return cachedMaxAscent; + } + + /** Returns the sum of the max ascent and max descent when drawing text using the given font size and font boldness settings. */ + public static int getMaxAscentAndDescent() { + calc(); + return cachedMaxAscent + cachedMaxDescent; + } + + /** Returns the bounding box when drawing the given string using the given font size and font boldness settings. */ + public static Rectangle2D getBounds(boolean fontBoldness, String string) { + calc(); + return (fontBoldness ? cachedBoldMetrics : cachedPlainMetrics).getStringBounds(string, cachedGraphics); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/AvailableSpace.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/AvailableSpace.java new file mode 100644 index 00000000..51e0a8a5 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/AvailableSpace.java @@ -0,0 +1,61 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4graph; + +import java.util.ArrayList; +import java.util.List; + +/** Mutable; this allows you to compute whether a rectangle overlaps with a set of rectangles or not. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final class AvailableSpace { + + /** Mutable; represents a rectangle. */ + static final class Box { + /** (x,y) is the top-left corner. */ int x, y; + /** (w,h) is the width and height. */ final int w, h; + public Box(int x, int y, int w, int h) { this.x=x; this.y=y; this.w=w; this.h=h; } + } + + /** The list of existing rectangles; we ensure every rectangle in here has width>0 and height>0. */ + private List list = new ArrayList(); + + /** Construct an empty space. */ + public AvailableSpace() { } + + /** Returns true if the given rectangle does not overlap with any existing rectangle in this space. */ + public boolean ok(int x, int y, int w, int h) { + if (w<=0 || h<=0) return true; // always okay + for(Box box: list) { + if ((x >= box.x && x <= box.x+box.w-1) || (x+w >= box.x+1 && x+w <= box.x+box.w)) + if ((y >= box.y && y <= box.y+box.h-1) || (y+h >= box.y+1 && y+h <= box.y+box.h)) return false; + if ((box.x >= x && box.x <= x+w-1) || (box.x+box.w >= x+1 && box.x+box.w <= x+w)) + if ((box.y >= y && box.y <= y+h-1) || (box.y+box.h >= y+1 && box.y+box.h <= y+h)) return false; + } + return true; + } + + /** Add the given rectangle to the list of rectangles in this space. */ + public void add(int x, int y, int w, int h) { + if (w<=0 || h<=0) return; // no-op + list.add(new Box(x, y, w, h)); + } + + /** Erases the list of rectangles in this space. */ + public void clear() { list.clear(); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/Curve.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/Curve.java new file mode 100644 index 00000000..abd555fd --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/Curve.java @@ -0,0 +1,219 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4graph; + +import java.util.ArrayList; +import java.util.List; +import java.awt.geom.CubicCurve2D; + +/** Mutable; represents a connected path. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +final class Curve { + + /** starting position and ending position. */ + public double startX, startY, endX, endY; + + /** The list of segments in this curve. */ + public final List list = new ArrayList(); + + /** Construct a curve starting at the given location. */ + public Curve(double startX, double startY) { + this.startX=startX; this.endX=startX; + this.startY=startY; this.endY=startY; + } + + /** Make a deep copy of this Curve object. */ + public Curve dup() { + Curve ans = new Curve(startX, startY); + ans.endX = endX; + ans.endY = endY; + for(CubicCurve2D.Double x:list) { + CubicCurve2D.Double c = new CubicCurve2D.Double(); + c.setCurve(x); + ans.list.add(c); + } + return ans; + } + /** Precondition: this.lastX==next.firstX and this.lastY==next.firstY. + * Note: the resulting Curve will still share the same CubicCurve2D objects as this and that. */ + Curve join(Curve that) { + Curve ans = new Curve(startX, startY); + ans.list.addAll(list); + ans.list.addAll(that.list); + ans.endX=that.endX; + ans.endY=that.endY; + return ans; + } + + /** Produce a cubic bezier curve representing a straightline segment from (x1,y1) to (x2,y2) */ + private static CubicCurve2D.Double makeline(double x1, double y1, double x2, double y2) { + return new CubicCurve2D.Double(x1, y1, (x2-x1)*0.3+x1, (y2-y1)*0.3+y1, (x2-x1)*0.6+x1, (y2-y1)*0.6+y1, x2, y2); + } + + /** Add a straightline segment to (ax,ay) */ + public Curve lineTo(double ax, double ay) { + list.add(makeline(endX, endY, ax, ay)); + this.endX = ax; + this.endY = ay; + return this; + } + + /** Add a cubic bezier segment to (cx,cy) using (ax,ay) and (bx,by) as the two control points. */ + public Curve cubicTo(double ax, double ay, double bx, double by, double cx, double cy) { + list.add(new CubicCurve2D.Double(endX, endY, ax, ay, bx, by, cx, cy)); + this.endX = cx; + this.endY = cy; + return this; + } + + /** Returns true if (x1,y1)..(x2,y2) intersects (x,y3)..(x,y4) */ + private static boolean intersects(double x1, double y1, double x2, double y2, double x, double y3, double y4) { + if (!(y3=n) list.clear(); + while(i>0 && !list.isEmpty()) { list.remove(0); i--; } + if (list.isEmpty()) { list.add(new CubicCurve2D.Double(startX=endX, startY=endY, endX,endY, endX,endY, endX,endY)); return; } + CubicCurve2D.Double tmp=new CubicCurve2D.Double(); + divide(t-di, list.get(0), new CubicCurve2D.Double(), tmp); + list.get(0).setCurve(tmp); + startX=tmp.x1; + startY=tmp.y1; + } + + /** Chop the end of this curve. */ + public void chopEnd(double t) { + int n=list.size(); + t=t*n; + double di=StrictMath.floor(t); + int i=(int)di; + // + if (i<0) list.clear(); + if (i>=n) return; + while(i+1 Precondition: the curve is monotonic in the vertical direction. + */ + public double getXatY(double y, double startT, double endT, double defaultValue) { + double a=startT, b=endT, ay=getY(a), by=getY(b); + if (ay>by) { double tmp=ay; ay=by; by=tmp; a=endT; b=startT; } + if (!(ay<=y && y<=by)) return defaultValue; + while(StrictMath.abs(a-b)>0.001D) { + double t=(a+b)/2, ty=getY(t); + if (ty==y) {a=t;break;} else if (ty=n) return endX; else return getX(list.get(i), t-di); + } + + /** Returns the y position at the given point 0 <= t <= 1 */ + public double getY(double t) { + int n=list.size(); + t=t*n; + double di=StrictMath.floor(t); + int i=(int)di; + if (i<0) return startY; else if (i>=n) return endY; else return getY(list.get(i), t-di); + } + + /** Returns the x position of the given segment at the given point 0 <= t <= 1 */ + private double getX(CubicCurve2D.Double curve, double t) { + double px=(curve.ctrlx1-curve.x1)*t+curve.x1, qx=(curve.ctrlx2-curve.ctrlx1)*t+curve.ctrlx1, rx=(curve.x2-curve.ctrlx2)*t+curve.ctrlx2; + double sx=(qx-px)*t+px, tx=(rx-qx)*t+qx; + return (tx-sx)*t+sx; + } + + /** Returns the y position of the given segment at the given point 0 <= t <= 1 */ + private double getY(CubicCurve2D.Double curve, double t) { + double py=(curve.ctrly1-curve.y1)*t+curve.y1, qy=(curve.ctrly2-curve.ctrly1)*t+curve.ctrly1, ry=(curve.y2-curve.ctrly2)*t+curve.ctrly2; + double sy=(qy-py)*t+py, ty=(ry-qy)*t+qy; + return (ty-sy)*t+sy; + } + + /** Given 0<=t<=1 and an existing curve, divide it into two chunks and store the two chunks into "first" and "second" */ + public static void divide(double t, CubicCurve2D.Double curve, CubicCurve2D.Double first, CubicCurve2D.Double second) { + // This algorithm uses de Casteljau's algorithm for chopping one bezier curve into two bezier curves + first.x1 = curve.x1; + second.x2 = curve.x2; + first.ctrlx1 = (1-t)*curve.x1 + t*curve.ctrlx1; + double x = (1-t)*curve.ctrlx1 + t*curve.ctrlx2; + second.ctrlx2 = (1-t)*curve.ctrlx2 + t*curve.x2; + first.ctrlx2 = (1-t)*first.ctrlx1 + t*x; + second.ctrlx1 = (1-t)*x + t*second.ctrlx2; + second.x1 = first.x2 = (1-t)*first.ctrlx2 + t*second.ctrlx1; + // now that we've computed the x coordinates, we now compute the y coordinates + first.y1 = curve.y1; + second.y2 = curve.y2; + first.ctrly1 = (1-t)*curve.y1 + t*curve.ctrly1; + double y = (1-t)*curve.ctrly1 + t*curve.ctrly2; + second.ctrly2 = (1-t)*curve.ctrly2 + t*curve.y2; + first.ctrly2 = (1-t)*first.ctrly1 + t*y; + second.ctrly1 = (1-t)*y + t*second.ctrly2; + second.y1 = first.y2 = (1-t)*first.ctrly2 + t*second.ctrly1; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/DotColor.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/DotColor.java new file mode 100644 index 00000000..1425307e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/DotColor.java @@ -0,0 +1,133 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4graph; + +import java.awt.Color; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.swing.Icon; +import edu.mit.csail.sdg.alloy4.OurUtil; + +/** Immutable; this defines the set of possible colors. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public enum DotColor { + + MAGIC("Magic", "magic"), + YELLOW("Yellow", "gold", "yellow", "lightgoldenrod", "yellow"), + GREEN("Green", "limegreen", "green2","darkolivegreen2","chartreuse2"), + BLUE("Blue", "cornflowerblue", "blue", "cadetblue", "cyan"), + RED("Red", "palevioletred", "red", "salmon", "magenta"), + GRAY("Gray", "lightgray"), + WHITE("White", "white"), + BLACK("Black", "black"); + + /** The text to display. */ + private final String displayText; + + /** The list of colors to use, corresponding to the current palette; + * if there are more palette choices than colors.size(), then the extra palettes would all use the first color. */ + private final List colors = new ArrayList(); + + /** The list of icons to show, corresponding to the current palette; + * if there are more palette choices than icons.size(), then the extra palettes would all use the first icon. */ + private final List icons = new ArrayList(); + + /** Construct a new DotColor. */ + private DotColor(String text, String... colors) { + displayText = text; + for(int i=0; i name2color = new HashMap(); + + /** Returns the list of values that the user is allowed to select from. */ + public static Object[] valuesWithout(DotColor exclude) { + Object[] ans = new Object[values().length - 1]; + int i = 0; + for(DotColor d: values()) if (d != exclude) ans[i++] = d; + return ans; + } + + /** Returns the Icon that will be displayed in the GUI to represent this value, when used with the given palette. */ + public Icon getIcon(DotPalette pal) { + int i = 0; + for(Object choice: DotPalette.values()) { + if (i >= icons.size()) break; + if (pal == choice) return icons.get(i); + i++; + } + return icons.get(0); + } + + /** Convert this color into its corresponding Java Color object. */ + public Color getColor(DotPalette pal) { + String name = getDotText(pal); + Color ans = name2color.get(name); + if (ans!=null) return ans; + else if (name.equals("palevioletred")) ans = new Color(222,113,148); + else if (name.equals("red")) ans = new Color(255,0,0); + else if (name.equals("salmon")) ans = new Color(255,130,115); + else if (name.equals("magenta")) ans = new Color(255,0,255); + else if (name.equals("limegreen")) ans = new Color(49,207,49); + else if (name.equals("green2")) ans = new Color(0,239,0); + else if (name.equals("darkolivegreen2")) ans = new Color(189,239,107); + else if (name.equals("chartreuse2")) ans = new Color(115,239,0); + else if (name.equals("gold")) ans = new Color(255,215,0); + else if (name.equals("yellow")) ans = new Color(255,255,0); + else if (name.equals("lightgoldenrod")) ans = new Color(239,223,132); + else if (name.equals("cornflowerblue")) ans = new Color(99,150,239); + else if (name.equals("blue")) ans = new Color(0,0,255); + else if (name.equals("cadetblue")) ans = new Color(90,158,165); + else if (name.equals("cyan")) ans = new Color(0,255,255); + else if (name.equals("lightgray")) ans = new Color(214,214,214); + else if (name.equals("white")) ans = Color.WHITE; + else ans = Color.BLACK; + name2color.put(name, ans); + return ans; + } + + /** Returns the String that should be written into the dot file for this value, when used with the given palette. */ + public String getDotText(DotPalette pal) { + int i = 0; + for(Object choice: DotPalette.values()) { + if (i >= colors.size()) break; + if (pal == choice) return colors.get(i); + i++; + } + return colors.get(0); + } + + /** Returns the String that will be displayed in the GUI to represent this value. */ + public String getDisplayedText() { return displayText; } + + /** This method is used in parsing the XML value into a valid color; returns null if there is no match. */ + public static DotColor parse(String x) { + if (x != null) for(DotColor d: values()) if (d.toString().equals(x)) return d; + return null; + } + + /** This value is used in writing XML. */ + @Override public String toString() { return displayText; } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/DotDirection.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/DotDirection.java new file mode 100644 index 00000000..f11c5060 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/DotDirection.java @@ -0,0 +1,37 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4graph; + +/** Immutable; this defines the set of possible edge directions. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public enum DotDirection { + + /** Going forward. */ FORWARD("forward"), + /** Going backward. */ BACK("back"), + /** Going both ways. */ BOTH("both"); + + /** The text to display. */ + private final String displayText; + + /** Constructs a new DotDirection object. */ + private DotDirection(String text) { this.displayText = text; } + + /** Returns the String that should be written into the dot file for this value, when used with the given palette. */ + public String getDotText() { return displayText; } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/DotPalette.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/DotPalette.java new file mode 100644 index 00000000..26c5315e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/DotPalette.java @@ -0,0 +1,48 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4graph; + +/** Immutable; this defines the set of possible color palettes. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public enum DotPalette { + + // Note: if you change the order, you must also change the ordering of the colors in DotColor class. + /** Classic palette. */ CLASSIC("Classic"), + /** Standard palette. */ STANDARD("Standard"), + /** Martha palette. */ MARTHA("Martha"), + /** Neon palette. */ NEON("Neon"); + + /** The text to display. */ + private final String displayText; + + /** Constructs a DotPalette object with the given label. */ + private DotPalette(String displayText) { this.displayText = displayText; } + + /** This method is used in parsing the XML value into a valid DotPalette; returns null if there is no match. */ + public static DotPalette parse(String x) { + if (x != null) for(DotPalette d: values()) if (d.toString().equals(x)) return d; + return null; + } + + /** Returns the String that will be displayed in the GUI to represent this value. */ + public String getDisplayedText() { return displayText; } + + /** This value is used in writing XML. */ + @Override public String toString() { return displayText; } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/DotShape.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/DotShape.java new file mode 100644 index 00000000..2d722109 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/DotShape.java @@ -0,0 +1,82 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4graph; + +import javax.swing.Icon; +import edu.mit.csail.sdg.alloy4.OurUtil; + +/** Immutable; this defines the set of possible node shapes (BOX, CIRCLE, ELLIPSE...) + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public enum DotShape { + + /** Ellipse */ ELLIPSE("Ellipse", "ellipse"), + /** Box */ BOX("Box", "box"), + /** Circle */ CIRCLE("Circle", "circle"), + /** Egg */ EGG("Egg", "egg"), + /** Triangle */ TRIANGLE("Triangle", "triangle"), + /** Diamond */ DIAMOND("Diamond", "diamond"), + /** Trapezoid */ TRAPEZOID("Trapezoid", "trapezium"), + /** Parallelogram */ PARALLELOGRAM("Parallelogram", "parallelogram"), + /** House */ HOUSE("House", "house"), + /** Hexagon */ HEXAGON("Hexagon", "hexagon"), + /** Octagon */ OCTAGON("Octagon", "octagon"), + /** Double Circle */ DOUBLE_CIRCLE("Dbl Circle", "doublecircle"), + /** Double Octagon */ DOUBLE_OCTAGON("Dbl Octagon", "doubleoctagon"), + /** Triple Octagon */ TRIPLE_OCTAGON("Tpl Octagon", "tripleoctagon"), + /** Inverted Triangle */ INV_TRIANGLE("Inv Triangle", "invtriangle"), + /** Inverted House */ INV_HOUSE("Inv House", "invhouse"), + /** Inverted Trapezoid */ INV_TRAPEZOID("Inv Trapezoid", "invtrapezium"), + /** Lined Diamond */ M_DIAMOND("Lined Diamond", "Mdiamond"), + /** Lined Square */ M_SQUARE("Lined Square", "Msquare"), + /** Lined Circle */ M_CIRCLE("Lined Circle", "Mcircle"); + + /** The description of this line style. */ + private final String name; + + /** The icon for this line style. */ + private final Icon icon; + + /** The corresponding DOT attribute. */ + private final String dotName; + + /** Constructs a DotShape object. */ + private DotShape(String name, String dotName) { + this.name = name; + this.icon = OurUtil.loadIcon("icons/ShapeIcons/" + dotName + ".gif"); + this.dotName = dotName; + } + + /** Returns the String that will be displayed in the GUI to represent this value. */ + public String getDisplayedText() { return name; } + + /** Returns the String that should be written into the dot file for this value, when used with the given palette. */ + public String getDotText() { return dotName; } + + /** Returns the Icon that will be displayed in the GUI to represent this value, when used with the given palette. */ + public Icon getIcon() { return icon; } + + /** This method is used in parsing the XML value into a valid Shape; returns null if there is no match. */ + public static DotShape parse(String x) { + if (x != null) for(DotShape d: values()) if (d.name.equals(x)) return d; + return null; + } + + /** This value is used in writing XML. */ + @Override public String toString() { return name; } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/DotStyle.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/DotStyle.java new file mode 100644 index 00000000..7e9221e5 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/DotStyle.java @@ -0,0 +1,73 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4graph; + +import javax.swing.Icon; +import edu.mit.csail.sdg.alloy4.OurUtil; + +/** Immutable; this defines the set of possible line styles (SOLID, DASHED, DOTTED...) + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public enum DotStyle { + + /** Solid line. */ + SOLID("Solid", "solid"), + + /** Dashed line. */ + DASHED("Dashed", "dashed"), + + /** Dotted line. */ + DOTTED("Dotted", "dotted"), + + /** Bold line. */ + BOLD("Bold", "bold"); + + /** The description of this line style. */ + private final String name; + + /** The icon for this line style. */ + private final Icon icon; + + /** The corresponding DOT attribute. */ + private final String dotName; + + /** Constructs a DotStyle object. */ + private DotStyle(String name, String dotName) { + this.name = name; + this.icon = OurUtil.loadIcon("icons/StyleIcons/" + dotName + ".gif"); + this.dotName = dotName; + } + + /** Returns the String that will be displayed in the GUI to represent this value. */ + public String getDisplayedText() { return name; } + + /** Returns the String that should be written into the dot file for this value, when used with the given palette. */ + public String getDotText() { return dotName; } + + /** Returns the Icon that will be displayed in the GUI to represent this value, when used with the given palette. */ + public Icon getIcon() { return icon; } + + /** This method is used in parsing the XML value into a valid style; returns null if there is no match. */ + public static DotStyle parse(String x) { + if (x != null) for(DotStyle d: values()) if (d.name.equals(x)) return d; + return null; + } + + /** This value is used in writing XML. */ + @Override public String toString() { return name; } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/Graph.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/Graph.java new file mode 100644 index 00000000..ea327590 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/Graph.java @@ -0,0 +1,762 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4graph; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.IdentityHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; +import java.awt.Color; +import java.awt.geom.Line2D; +import java.awt.geom.RoundRectangle2D; +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.alloy4.Util; +import static edu.mit.csail.sdg.alloy4graph.Artist.getBounds; + +/** Mutable; represents a graph. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final strictfp class Graph { + + //================================ adjustable options ========================================================================// + + /** Minimum horizontal distance between adjacent nodes. */ + static final int xJump = 30; + + /** Minimum vertical distance between adjacent layers. */ + static final int yJump = 60; + + /** The horizontal distance between the first self-loop and the node itself. */ + static final int selfLoopA = 40; + + /** The horizontal padding to put on the left side of a self-loop's edge label. */ + static final int selfLoopGL = 2; + + /** The horizontal padding to put on the right side of a self-loop's edge label. */ + static final int selfLoopGR = 20; + + /** The maximum ascent and descent. We deliberately do NOT make this field "static" because only AWT thread can call Artist. */ + private final int ad = Artist.getMaxAscentAndDescent(); + + //=============================== fields ======================================================================================// + + /** The default magnification. */ + final double defaultScale; + + /** The left edge. */ + private int left = 0; + + /** The top edge. */ + private int top = 0; + + /** The bottom edge. */ + private int bottom = 0; + + /** The total width of the graph; this value is computed by layout(). */ + private int totalWidth = 0; + + /** The total height of the graph; this value is computed by layout(). */ + private int totalHeight = 0; + + /** The height of each layer. */ + int[] layerPH = null; + + /** The list of layers; must stay in sync with GraphNode.graph and GraphNode.layer + * (empty iff there are no nodes; every node is always in exactly one layer, and appears exactly once in that layer) + */ + final List> layerlist = new ArrayList>(); + + /** The list of nodes; must stay in sync with GraphNode.graph and GraphNode.pos + * (every node is in exactly one graph's nodelist, and appears exactly once in that graph's nodelist) + */ + final List nodelist = new ArrayList(); + + /** The list of edges; must stay in sync with GraphEdge.a.graph and GraphEdge.b.graph + * (every edge is in exactly one graph's edgelist, and appears exactly once in that graph's edgelist) + */ + final List edgelist = new ArrayList(); + + /** An unmodifiable view of the list of nodes. */ + public final List nodes = Collections.unmodifiableList(nodelist); + + /** An unmodifiable view of the list of edges. */ + public final List edges = Collections.unmodifiableList(edgelist); + + /** An unmodifiable empty list. */ + private final List emptyListOfNodes = Collections.unmodifiableList(new ArrayList(0)); + + //============================================================================================================================// + + /** Constructs an empty Graph object. */ + public Graph(double defaultScale) { this.defaultScale = defaultScale; } + + /** Assuming layout() has been called, this returns the left edge. */ + public int getLeft() { return left; } + + /** Assuming layout() has been called, this returns the top edge. */ + public int getTop() { return top; } + + /** Assuming layout() has been called, this returns the total width. */ + public int getTotalWidth() { return totalWidth; } + + /** Assuming layout() has been called, this returns the total height. */ + public int getTotalHeight() { return totalHeight; } + + /** Returns an unmodifiable view of the list of nodes in the given layer (0..#layer-1); return an empty list if no such layer. */ + List layer(int i) { + if (i>=0 && i list = layerlist.get(layer); + GraphNode n1 = list.get(node1), n2 = list.get(node2); + list.set(node1, n2); + list.set(node2, n1); + } + + /** Sort the list of nodes according to the order in the given list. */ + void sortNodes(Iterable newOrder) { + // The nodes that are common to this.nodelist and newOrder are moved to the front of the list, in the given order. + // The nodes that are in this.nodelist but not in newOrder are moved to the back in an unspecified order. + // The nodes that are in newOrder but not in this.nodelist are ignored. + int i=0, n=nodelist.size(); + again: + for(GraphNode x:newOrder) for(int j=i; j comparator) { Collections.sort(layerlist.get(layer), comparator); } + + /** A list of legends; each legend is an Object with the associated text label and color. */ + private final SortedMap,Pair> legends = new TreeMap,Pair>(); + + /** Add a legend with the given object and the associated text label; if color==null, that means we will + * still add this legend into the list of legends, but this legend will be hidden. + */ + public void addLegend(Comparable object, String label, Color color) { legends.put(object, new Pair(label,color)); } + + //============================================================================================================================// + + /** Layout step #1: assign a total order on the nodes. */ + private void layout_assignOrder() { + // This is an implementation of the GR algorithm described by Peter Eades, Xuemin Lin, and William F. Smyth + // in "A Fast & Effective Heuristic for the Feedback Arc Set Problem" + // in Information Processing Letters, Volume 47, Number 6, Pages 319-323, 1993 + final int num = nodes.size(); + if ((Integer.MAX_VALUE-1)/2 < num) throw new OutOfMemoryError(); + // Now, allocate 2n+1 bins labeled -n .. n + // Note: inside this method, whenever we see #in and #out, we ignore repeated edges. + // Note: since Java ArrayList always start at 0, we'll index it by adding "n" to it. + final List> bins = new ArrayList>(2*num+1); + for(int i=0; i<2*num+1; i++) bins.add(new LinkedList()); + // For each N, figure out its in-neighbors and out-neighbors, then put it in the correct bin + ArrayList> grIN=new ArrayList>(num); + ArrayList> grOUT=new ArrayList>(num); + int[] grBIN=new int[num]; + for(GraphNode n: nodes) { + int ni = n.pos(); + LinkedList in=new LinkedList(), out=new LinkedList(); + for(GraphEdge e: n.ins) { GraphNode a = e.a(); if (!in.contains(a)) in.add(a); } + for(GraphEdge e: n.outs) { GraphNode b = e.b(); if (!out.contains(b)) out.add(b); } + grIN.add(in); + grOUT.add(out); + grBIN[ni] = (out.size()==0) ? 0 : (in.size()==0 ? (2*num) : (out.size()-in.size()+num)); + bins.get(grBIN[ni]).add(n); + // bin[0] = { v | #out=0 } + // bin[n + d] = { v | d=#out-#in and #out!=0 and #in!=0 } for -n < d < n + // bin[n + n] = { v | #in=0 and #out>0 } + } + // Main loop + final LinkedList s1=new LinkedList(), s2=new LinkedList(); + while(true) { + GraphNode x=null; + if (!bins.get(0).isEmpty()) { + // If a sink exists, take a sink X and prepend X to S2 + x = bins.get(0).remove(bins.get(0).size()-1); + s1.add(x); + } else for(int j=2*num; j>0; j--) { + // Otherwise, let x be a source if one exists, or a node with the highest #out-#in. Then append X to S1. + List bin=bins.get(j); + int sz=bin.size(); + if (sz>0) { x=bin.remove(sz-1); s2.addFirst(x); break; } + } + if (x==null) break; // This means we're done; else, delete X from its bin, and move each of X's neighbor into their new bin + bins.get(grBIN[x.pos()]).remove(x); + for(GraphNode n:grIN.get(x.pos())) grOUT.get(n.pos()).remove(x); + for(GraphNode n:grOUT.get(x.pos())) grIN.get(n.pos()).remove(x); + for(GraphNode n:Util.fastJoin(grIN.get(x.pos()), grOUT.get(x.pos()))) { + int ni=n.pos(), out=grOUT.get(ni).size(), in=grIN.get(ni).size(); + int b=(out==0)?0:(in==0?(2*num):(out-in+num)); + if (grBIN[ni]!=b) { bins.get(grBIN[ni]).remove(n); grBIN[ni]=b; bins.get(b).add(n); } + } + } + sortNodes(Util.fastJoin(s1,s2)); + } + + //============================================================================================================================// + + /** Layout step #2: reverses all backward edges. */ + private void layout_backEdges() { + for(GraphEdge e: edges) if (e.a().pos() < e.b().pos()) e.set(e.bhead(), e.ahead()).reverse(); + } + + //============================================================================================================================// + + /** Layout step #3: assign the nodes into one or more layers, then return the number of layers. */ + private int layout_decideLayer() { + // Here, for each node X, I compute its maximum length to a sink; if X is a sink, its length to sink is 0. + final int n = nodes.size(); + int[] len = new int[n]; + for(GraphNode x: nodes) { + // Since we ensured that arrows only ever go from a node with bigger pos() to a node with smaller pos(), + // we can compute the "len" array in O(n) time by visiting each node IN THE SORTED ORDER + int max=0; + for(GraphEdge e: x.outs) { + GraphNode y = e.b(); + int yLen = len[y.pos()]+1; + if (max < yLen) max = yLen; + } + len[x.pos()] = max; + } + // Now, we simply do the simplest thing: assign each node to the layer corresponding to its max-length-to-sink. + for(GraphNode x: nodes) x.setLayer(len[x.pos()]); + // Now, apply a simple trick: whenever every one of X's incoming edge is more than one layer above, then move X up + while(true) { + boolean changed = false; + for(GraphNode x: nodes) if (x.ins.size() > 0) { + int closestLayer=layers()+1; + for(GraphEdge e: x.ins) { + int y = e.a().layer(); + if (closestLayer>y) closestLayer=y; + } + if (closestLayer-1>x.layer()) { x.setLayer(closestLayer-1); changed=true; } + } + if (!changed) break; + } + // All done! + return layers(); + } + + //============================================================================================================================// + + /** Layout step #4: add dummy nodes so that each edge only goes between adjacent layers. */ + private void layout_dummyNodesIfNeeded() { + for(final GraphEdge edge: new ArrayList(edges)) { + GraphEdge e = edge; + GraphNode a = e.a(), b=e.b(); + while(a.layer() - b.layer() > 1) { + GraphNode tmp = a; + a = new GraphNode(a.graph, e.uuid).set((DotShape)null); + a.setLayer(tmp.layer()-1); + // now we have three nodes in the vertical order of "tmp", "a", then "b" + e.change(a); // let old edge go from "tmp" to "a" + e = new GraphEdge(a, b, e.uuid, "", e.ahead(), e.bhead(), e.style(), e.color(), e.group); // let new edge go from "a" to "b" + } + } + } + + //============================================================================================================================// + + /** Layout step #5: decide the order of the nodes within each layer. */ + private void layout_reorderPerLayer() { + // This uses the original Barycenter heuristic + final IdentityHashMap map = new IdentityHashMap(); + final double[] bc = new double[nodes.size()+1]; + int i=1; for(GraphNode n:layer(0)) { bc[n.pos()] = i; i++; } + for(int layer=0; layer() { + public int compare(GraphNode o1, GraphNode o2) { + // If the two nodes have the same barycenter, we use their ordering that was established during layout_assignOrder() + if (o1==o2) return 0; + int n = Double.compare(bc[o1.pos()], bc[o2.pos()]); if (n!=0) return n; else if (o1.pos() nodes) { + // This implementation uses the iterative approach described in the paper "Layout of Bayesian Networks" + // by Kim Marriott, Peter Moulder, Lucas Hope, and Charles Twardy + final int n = nodes.size(); + if (n==0) return; + final Block[] block = new Block[n+1]; + block[0] = new Block(); // The sentinel block + for(int i=1; i<=n; i++) { + Block b = new Block(nodes.get(i-1), i); + block[i] = b; + while(block[b.first-1].posn + block[b.first-1].width > b.posn) { + b = new Block(block[b.first-1], b); + block[b.last] = b; + block[b.first] = b; + } + } + int i=1; + while(true) { + Block b = block[i]; + double tmp = b.posn + (nodes.get(b.first-1).getWidth() + nodes.get(b.first-1).getReserved() + xJump)/2D; + nodes.get(i-1).setX((int)tmp); + for(i=i+1; i<=b.last; i++) { + GraphNode v1 = nodes.get(i-1); + GraphNode v2 = nodes.get(i-2); + int xsep = (v1.getWidth() + v1.getReserved() + v2.getWidth() + v2.getReserved())/2 + xJump; + v1.setX(v2.x() + xsep); + } + i=b.last+1; + if (i>n) break; + } + } + + /** This computes the des() value as described in the paper. + *

The desired location of V = ("sum e:in(V) | wt(e) * phi(start of e)" + "sum e:out(V) | wt(e) * phi(end of e)") / wt(v) + */ + private static double des(GraphNode n) { + int wt = wt(n); + if (wt==0) return 0; // This means it has no "in" edges and no "out" edges + double ans=0; + for(GraphEdge e: n.ins) ans += ((double)e.weight()) * e.a().x(); + for(GraphEdge e: n.outs) ans += ((double)e.weight()) * e.b().x(); + return ans/wt; + } + + /** This computes the wt() value as described in the paper. + *

The weight of a node is the sum of the weights of its in-edges and out-edges. + */ + private static int wt(GraphNode n) { + int ans=0; + for(GraphEdge e: n.ins) ans += e.weight(); + for(GraphEdge e: n.outs) ans += e.weight(); + return ans; + } + + /** This corresponds to the Block structure described in the paper. */ + private static final class Block { + /** These fields are described in the paper. */ + private final int first, last, weight; + /** These fields are described in the paper. */ + private final double width, posn, wposn; + /** This constructs a regular block. */ + public Block(GraphNode v, int i) { + first=i; last=i; width=v.getWidth()+v.getReserved()+xJump; posn=des(v)-(width/2); weight=wt(v); wposn=weight*posn; + } + /** This merges the two existing blocks into a new block. */ + public Block(Block a, Block b) { + first=a.first; last=b.last; width=a.width+b.width; + wposn=a.wposn+b.wposn-a.width*b.weight; weight=a.weight+b.weight; posn=wposn/weight; + } + /** This constructs a sentinel block. */ + public Block() { + posn=Double.NEGATIVE_INFINITY; first=0; last=0; weight=0; width=0; wposn=0; + } + } + + //============================================================================================================================// + + /** For each edge coming out of this layer of nodes, add bends to it if it currently overlaps some nodes inappropriately. */ + private void checkUpperCollision(List top) { + final int room=2; // This is how much we need to stay clear of a node's boundary + for(int i=0; i=right) for(int j=i+1; j=0; j--) { // This edge goes from top-right to bottom-left + GraphNode c=top.get(j); + if (c.shape()==null) continue; // You can intersect thru a dummy node + double ctop=c.y()-c.getHeight()/2, cright=c.x()+c.getWidth()/2, cbottom=c.y()+c.getHeight()/2; + e.path().bendDown(cright, ctop-room, cbottom+room, 3); + } + } + } + } + + //============================================================================================================================// + + /** For each edge going into this layer of nodes, add bends to it if it currently overlaps some nodes inappropriately. */ + private void checkLowerCollision(List bottom) { + final int room=2; // This is how much we need to stay clear of a node's boundary + for(int i=0; i=0; j--) { // This edge goes from top-left to bottom-right + GraphNode c=bottom.get(j); + if (c.shape()==null) continue; // You can intersect thru a dummy node + double ctop=c.y()-c.getHeight()/2, cright=c.x()+c.getWidth()/2, cbottom=c.y()+c.getHeight()/2; + e.path().bendUp(cright, ctop-room, cbottom+room, 3); + } + else if (a.x()>=right) for(int j=i+1; j b.layer()) { GraphNode tmp=a; a=b; b=tmp; } + Line2D.Double line = new Line2D.Double(a.x(), a.y(), b.x(), b.y()); + for(GraphNode n:nodes) if (n!=a && n!=b && a.layer()=0; layer--) { + int x=5; // So that we're not touching the left-edge of the window + int h=0; + for(GraphNode n: layer(layer)) { + int nHeight = n.getHeight(), nWidth = n.getWidth(); + n.setX(x + nWidth/2); + if (h < nHeight) h = nHeight; + x = x + nWidth + n.getReserved() + 20; + } + layerPH[layer] = h; + } + + // If there are more than one layer, then iteratively refine the X position of each component 3 times; 4 is a good number + if (layers>1) { + // It's important to NOT DO THIS when layers<=1, because without edges the nodes will overlap each other into the center + for(int i=0; i<3; i++) for(int layer=0; layer=0; layer--) { + final int ph = layerPH[layer]; + for(GraphNode n:layer(layer)) n.setY(py + ph/2); + py = py + ph + yJump; + } + + relayout_edges(true); + + // Since we're doing layout for the first time, we need to explicitly set top and bottom, since + // otherwise "recalcBound" will merely "extend top and bottom" as needed. + recalcBound(true); + } + + //============================================================================================================================// + + /** Re-establish top/left/width/height. */ + void recalcBound(boolean fresh) { + if (nodes.size()==0) { top=0; bottom=10; totalHeight=10; left=0; totalWidth=10; return; } + if (fresh) { top=nodes.get(0).y()-nodes.get(0).getHeight()/2-5; bottom=nodes.get(0).y()+nodes.get(0).getHeight()/2+5; } + // Find the leftmost and rightmost pixel + int minX = nodes.get(0).x() - nodes.get(0).getWidth()/2 - 5; + int maxX = nodes.get(0).x() + nodes.get(0).getWidth()/2 + nodes.get(0).getReserved() + 5; + for(GraphNode n: nodes) { + int min = n.x() - n.getWidth()/2 - 5; if (minX>min) minX=min; + int max = n.x() + n.getWidth()/2 + n.getReserved() + 5; if (maxX0 && e.getLabelH()>0) { + int x1=e.getLabelX(), x2=x1+e.getLabelW()-1; + if (minX>x1) minX=x1; + if (maxX=0; layer--) { + for(GraphNode n: layer(layer)) { + int ytop = n.y()-n.getHeight()/2-5; if (top > ytop) top=ytop; + int ybottom = n.y()+n.getHeight()/2+5; if (bottom < ybottom) bottom=ybottom; + } + } + totalHeight = bottom-top; + int widestLegend = 0, legendHeight = 30; + for(Pair e: legends.values()) { + if (e.b==null) continue; // that means this legend is not visible + int widthOfLegend = (int) getBounds(true, e.a).getWidth(); + if (widestLegend < widthOfLegend) widestLegend = widthOfLegend; + legendHeight += ad; + } + if (widestLegend>0) { + left -= (widestLegend+10); + totalWidth += (widestLegend*2+10); + if (totalHeight() { + public int compare(GraphNode o1, GraphNode o2) { + if (o1.x()o2.x()) return 1; + return 0; + } + }); + // Ensure that nodes are not bunched up together horizontally. + List layer=new ArrayList(layer(i)); + for(int j=layer.size()/2; j>=0 && j0 && j0; layer--) { + List top=layer(layer), bottom=layer(layer-1); + checkUpperCollision(top); checkLowerCollision(bottom); checkUpperCollision(top); + } + // Now, for each edge, adjust its arrowhead and label. + AvailableSpace sp = new AvailableSpace(); + for(GraphNode n: nodes) if (n.shape()!=null) sp.add(n.x()-n.getWidth()/2, n.y()-n.getHeight()/2, n.getWidth()+n.getReserved(), n.getHeight()); + for(GraphEdge e: edges) { e.layout_arrowHead(); e.repositionLabel(sp); } + } + + //============================================================================================================================// + + /** Assuming everything was laid out already, but nodes in layer[i] just moved horizontally, this re-layouts edges to+from layer i. */ + void relayout_edges(int i) { + if (nodes.size()==0) return; // The rest of the code assumes there is at least one node + for(GraphNode n: layer(i)) for(GraphEdge e: n.selfs) { e.resetPath(); e.layout_arrowHead(); } + if (i>0) { + List top=layer(i), bottom=layer(i-1); + for(GraphNode n: top) for(GraphEdge e: n.outs) e.resetPath(); + checkUpperCollision(top); checkLowerCollision(bottom); checkUpperCollision(top); + } + if (i top=layer(i+1), bottom=layer(i); + for(GraphNode n: top) for(GraphEdge e: n.outs) e.resetPath(); + checkUpperCollision(top); checkLowerCollision(bottom); checkUpperCollision(top); + } + // Now, for each edge, adjust its arrowhead and label. + AvailableSpace sp = new AvailableSpace(); + for(GraphNode n:nodes) if (n.shape()!=null) sp.add(n.x()-n.getWidth()/2, n.y()-n.getHeight()/2, n.getWidth()+n.getReserved(), n.getHeight()); + for(GraphEdge e:edges) { e.layout_arrowHead(); e.repositionLabel(sp); } + } + + //============================================================================================================================// + + /** Locates the node or edge at the given (X,Y) location. */ + public Object find(double scale, int mouseX, int mouseY) { + int h = getTop() + 10 - ad; + double x = mouseX/scale + getLeft(), y = mouseY/scale + getTop(); + for(Map.Entry,Pair> e: legends.entrySet()) { + if (e.getValue().b == null) continue; + h = h + ad; + if (y=h+ad) continue; + int w = (int) getBounds(true, e.getValue().a).getWidth(); + if (x>=getLeft()+10 && x<=getLeft()+10+w) return e.getKey(); + } + for(GraphNode n: nodes) { + if (n.shape()==null && Math.abs(n.x()-x)<10 && Math.abs(n.y()-y)<10) return n; + if (n.contains(x,y)) return n; + } + for(GraphEdge e: edges) { + if (e.a() != e.b()) { + double dx; + dx = e.path().getXatY(y, 0, 1, Double.NaN); if (!Double.isNaN(dx) && StrictMath.abs(x-dx)<12/scale) return e; + } else { + double dx; + dx = e.path().getXatY(y, 0.25, 0.75, Double.NaN); if (!Double.isNaN(dx) && StrictMath.abs(x-dx)<12/scale) return e; + dx = e.path().getXatY(y, 0, 0.25, Double.NaN); if (!Double.isNaN(dx) && StrictMath.abs(x-dx)<12/scale) return e; + dx = e.path().getXatY(y, 0.75, 1, Double.NaN); if (!Double.isNaN(dx) && StrictMath.abs(x-dx)<12/scale) return e; + } + } + return null; + } + + //============================================================================================================================// + + /** Assuming layout has been performed, this draws the graph with the given magnification scale. */ + void draw(Artist gr, double scale, Object highlight, boolean showLegends) { + if (nodes.size()==0) return; // The rest of this procedure assumes there is at least one node + Object group = null; + GraphNode highFirstNode = null, highLastNode = null; + GraphEdge highFirstEdge = null, highLastEdge = null; + if (highlight instanceof GraphEdge) { + highFirstEdge = (GraphEdge)highlight; + highLastEdge = highFirstEdge; + group = highFirstEdge.group; + while(highFirstEdge.a().shape() == null) highFirstEdge = highFirstEdge.a().ins.get(0); + while(highLastEdge.b().shape() == null) highLastEdge = highLastEdge.b().outs.get(0); + highFirstNode=highFirstEdge.a(); + highLastNode=highLastEdge.b(); + } else if (!(highlight instanceof GraphNode) && highlight!=null) { + group = highlight; + } + // Since drawing an edge will automatically draw all segments if they're connected via dummy nodes, + // we must make sure we only draw out edges from non-dummy-nodes + int maxAscent = Artist.getMaxAscent(); + for(GraphNode n:nodes) if (n.shape()!=null) { + for(GraphEdge e:n.outs) if (e.group!=group) e.draw(gr, scale, highFirstEdge, group); + for(GraphEdge e:n.selfs) if (e.group!=group) e.draw(gr, scale, highFirstEdge, group); + } + if (group!=null) { + for(GraphNode n:nodes) if (n.shape()!=null) { + for(GraphEdge e:n.outs) if (e.group==group && e!=highFirstEdge) e.draw(gr, scale, highFirstEdge, group); + for(GraphEdge e:n.selfs) if (e.group==group && e!=highFirstEdge) e.draw(gr, scale, highFirstEdge, group); + } + if (highFirstEdge!=null) highFirstEdge.draw(gr, scale, highFirstEdge, group); + } + for(GraphNode n:nodes) if (highFirstNode!=n && highLastNode!=n) n.draw(gr, scale, n==highlight); + if (highFirstNode!=null) highFirstNode.draw(gr, scale, true); + if (highLastNode!=null && highLastNode!=highFirstNode) highLastNode.draw(gr, scale, true); + if (highFirstEdge!=null) highFirstEdge.drawLabel(gr, highFirstEdge.color(), new Color(255,255,255,160)); + // show legends? + if (!showLegends || legends.size()==0) return; + boolean groupFound=false; + int y=0, maxWidth=0; + for(Map.Entry,Pair> e:legends.entrySet()) { + if (e.getValue().b==null) continue; + if (group!=null && e.getKey()==group) groupFound=true; + int w = (int) getBounds(true, e.getValue().a).getWidth(); + if (maxWidth,Pair> e:legends.entrySet()) { + Color color = e.getValue().b; + if (color==null) continue; + gr.setFont((groupFound && e.getKey()==group) || !groupFound); + gr.setColor((!groupFound || e.getKey()==group) ? color : Color.GRAY); + gr.drawString(e.getValue().a, 8, y+maxAscent); + y = y + ad; + } + } + + //============================================================================================================================// + + /** Helper method that encodes a String for printing into a DOT file. */ + static String esc(String name) { + if (name.indexOf('\"') < 0) return name; + StringBuilder out = new StringBuilder(); + for(int i=0; i + * Thread Safety: Can be called only by the AWT event thread. + */ + +public final strictfp class GraphEdge { + + // =============================== adjustable options + // =========================================================================== + + /** The angle (in radian) to fan out the arrow head, if the line is not bold. */ + private final double smallFan = StrictMath.toRadians(16); + + /** The angle (in radian) to fan out the arrow head, if the line is bold. */ + private final double bigFan = StrictMath.toRadians(32); + + // =============================== cached for performance efficiency + // ============================================================ + + /** + * The maximum ascent and descent. We deliberately do NOT make this field "static" because only + * AWT thread can call Artist. + */ + private final int ad = Artist.getMaxAscentAndDescent(); + + // =============================== fields + // ======================================================================================= + + /** + * a user-provided annotation that will be associated with this edge (can be null) (need not be + * unique) + */ + public final Object uuid; + + /** + * a user-provided annotation that will be associated with this edge (all edges with same group + * will be highlighted together) + */ + public final Object group; + + /** + * The "from" node; must stay in sync with GraphNode.ins and GraphNode.outs and GraphNode.selfs + */ + private GraphNode a; + + /** The "to" node; must stay in sync with GraphNode.ins and GraphNode.outs and GraphNode.selfs */ + private GraphNode b; + + /** + * The label (can be ""); NOTE: label will be drawn only if the start node is not a dummy node. + */ + private final String label; + + /** Whether to draw an arrow head on the "from" node; default is false. */ + private boolean ahead = false; + + /** Whether to draw an arrow head on the "to" node; default is true. */ + private boolean bhead = true; + + /** The color of the edge; default is BLACK; never null. */ + private Color color = Color.BLACK; + + /** The line-style of the edge; default is SOLID; never null. */ + private DotStyle style = DotStyle.SOLID; + + /** The edge weight; default is 1; always between 1 and 10000 inclusively. */ + private int weight = 1; + + /** The location and size of the label box; initially (0, 0, label.width, label.height) */ + private final AvailableSpace.Box labelbox; + + /** The actual path corresponding to this edge; initially null until it's computed. */ + private Curve path = null; + + // =========================================================================s==================================================== + + /** + * Construct an edge from "from" to "to" with the given arrow head settings, then add the edge to + * the graph. + */ + GraphEdge(final GraphNode from, final GraphNode to, final Object uuid, final String label, + final boolean drawArrowHeadOnFrom, final boolean drawArrowHeadOnTo, final DotStyle style, + final Color color, Object group) { + if (group instanceof GraphNode) { + throw new IllegalArgumentException("group cannot be a GraphNode"); + } + if (group instanceof GraphEdge) { + throw new IllegalArgumentException("group cannot be a GraphEdge"); + } + if (group == null) { + group = new Object(); + } + this.a = from; + this.b = to; + if (this.a.graph != this.b.graph) { + throw new IllegalArgumentException("You cannot draw an edge between two different graphs."); + } + if (this.a == this.b) { + this.a.selfs.add(this); + } else { + this.a.outs.add(this); + this.b.ins.add(this); + } + this.a.graph.edgelist.add(this); + this.uuid = uuid; + this.group = group; + this.label = label == null ? "" : label; + this.ahead = drawArrowHeadOnFrom; + this.bhead = drawArrowHeadOnTo; + if (style != null) { + this.style = style; + } + if (color != null) { + this.color = color; + } + if (this.label.length() > 0) { + final Rectangle2D box = Artist.getBounds(false, label); + this.labelbox = new AvailableSpace.Box(0, 0, (int) box.getWidth(), (int) box.getHeight()); + } else { + this.labelbox = new AvailableSpace.Box(0, 0, 0, 0); + } + } + + /** Construct an edge from "from" to "to", then add the edge to the graph. */ + public GraphEdge(final GraphNode from, final GraphNode to, final Object uuid, final String label, + final Object group) { + this(from, to, uuid, label, false, true, null, null, group); + } + + /** Returns the "from" node. */ + public GraphNode a() { + return this.a; + } + + /** Returns true if we will draw an arrow head on the "from" node. */ + public boolean ahead() { + return this.ahead; + } + + /** Returns the "to" node. */ + public GraphNode b() { + return this.b; + } + + /** Returns true if we will draw an arrow head on the "to" node. */ + public boolean bhead() { + return this.bhead; + } + + /** Changes the "to" node to the given node. */ + void change(final GraphNode newTo) { + if (this.b.graph != newTo.graph) { + throw new IllegalArgumentException("You cannot draw an edge between two different graphs."); + } + if (this.a == this.b) { + this.a.selfs.remove(this); + } else { + this.a.outs.remove(this); + this.b.ins.remove(this); + } + this.b = newTo; + if (this.a == this.b) { + this.a.selfs.add(this); + } else { + this.a.outs.add(this); + this.b.ins.add(this); + } + } + + /** Returns the line color; never null. */ + public Color color() { + return this.color; + } + + /** + * Assuming this edge's coordinates have been properly assigned, and given the current zoom scale, + * draw the edge. + */ + void draw(final Artist gr, final double scale, final GraphEdge highEdge, final Object highGroup) { + final int top = this.a.graph.getTop(), left = this.a.graph.getLeft(); + gr.translate(-left, -top); + if (highEdge == this) { + gr.setColor(this.color); + gr.set(DotStyle.BOLD, scale); + } else if (highEdge == null && highGroup == null || highGroup == this.group) { + gr.setColor(this.color); + gr.set(this.style, scale); + } else { + gr.setColor(Color.LIGHT_GRAY); + gr.set(this.style, scale); + } + if (this.a == this.b) { + gr.draw(this.path); + } else { + // Concatenate this path and its connected segments into a single VizPath object, then draw it + Curve p = null; + GraphEdge e = this; + while (e.a.shape() == null) { + e = e.a.ins.get(0); // Let e be the first segment of this chain of connected segments + } + while (true) { + p = p == null ? e.path : p.join(e.path); + if (e.b.shape() != null) { + break; + } + e = e.b.outs.get(0); + } + gr.drawSmoothly(p); + } + // if (this.style == DotStyle.DOTTED || this.style == DotStyle.DASHED) { + // gr.set(DotStyle.SOLID, scale); + // } + if (this.uuid instanceof AlloyTuple && ((AlloyTuple) this.uuid).isDashed) { + gr.set(DotStyle.DASHED, scale); + } else { + gr.set(DotStyle.SOLID, scale); + } + gr.translate(left, top); + if (highEdge == null && highGroup == null && this.label.length() > 0) { + this.drawLabel(gr, this.color, null); + } + this.drawArrowhead(gr, scale, highEdge, highGroup); + } + + /** + * Assuming this edge's coordinates have been assigned, and given the current zoom scale, draw the + * arrow heads. + */ + private void drawArrowhead(final Artist gr, final double scale, final GraphEdge highEdge, + final Object highGroup) { + final double tipLength = this.ad * 0.6D; + final int top = this.a.graph.getTop(), left = this.a.graph.getLeft(); + // Check to see if this edge is highlighted or not + double fan = this.style == DotStyle.BOLD ? this.bigFan : this.smallFan; + if (highEdge == this) { + fan = this.bigFan; + gr.setColor(this.color); + gr.set(DotStyle.BOLD, scale); + } else if (highEdge == null && highGroup == null || highGroup == this.group) { + gr.setColor(this.color); + gr.set(this.style, scale); + } else { + gr.setColor(Color.LIGHT_GRAY); + gr.set(this.style, scale); + } + for (GraphEdge e = this;; e = e.b.outs.get(0)) { + if (e.ahead && e.a.shape() != null || e.bhead && e.b.shape() != null) { + final Curve cv = e.path(); + if (e.ahead && e.a.shape() != null) { + final CubicCurve2D.Double bez = cv.list.get(0); + final double ax = bez.x1, ay = bez.y1, bx = bez.ctrlx1, by = bez.ctrly1; + final double t = StrictMath.PI + StrictMath.atan2(ay - by, ax - bx); + final double gx1 = ax + tipLength * StrictMath.cos(t - fan), + gy1 = ay + tipLength * StrictMath.sin(t - fan); + final double gx2 = ax + tipLength * StrictMath.cos(t + fan), + gy2 = ay + tipLength * StrictMath.sin(t + fan); + final GeneralPath gp = new GeneralPath(); + gp.moveTo((float) (gx1 - left), (float) (gy1 - top)); + gp.lineTo((float) (ax - left), (float) (ay - top)); + gp.lineTo((float) (gx2 - left), (float) (gy2 - top)); + gp.closePath(); + gr.draw(gp, true); + if (((AlloyTuple) this.uuid).getAtoms().get(0).changed + && ((AlloyTuple) this.uuid).getAtoms().get(1).impacted + .contains(((AlloyTuple) this.uuid).getAtoms().get(0).getOriginalName())) { + gr.setColor(Color.BLACK); + gr.drawString(" !", (int) gx1 - left + 5, (int) gy1 - top); + } + } + if (e.bhead && e.b.shape() != null) { + final CubicCurve2D.Double bez = cv.list.get(cv.list.size() - 1); + final double bx = bez.x2, by = bez.y2, ax = bez.ctrlx2, ay = bez.ctrly2; + final double t = StrictMath.PI + StrictMath.atan2(by - ay, bx - ax); + final double gx1 = bx + tipLength * StrictMath.cos(t - fan), + gy1 = by + tipLength * StrictMath.sin(t - fan); + final double gx2 = bx + tipLength * StrictMath.cos(t + fan), + gy2 = by + tipLength * StrictMath.sin(t + fan); + final GeneralPath gp = new GeneralPath(); + gp.moveTo((float) (gx1 - left), (float) (gy1 - top)); + gp.lineTo((float) (bx - left), (float) (by - top)); + gp.lineTo((float) (gx2 - left), (float) (gy2 - top)); + gp.closePath(); + gr.draw(gp, true); + if (((AlloyTuple) this.uuid).getAtoms().get(0).changed + && ((AlloyTuple) this.uuid).getAtoms().get(1).impacted + .contains(((AlloyTuple) this.uuid).getAtoms().get(0).getOriginalName())) { + gr.setColor(Color.BLACK); + gr.drawString(" !", (int) gx1 - left + 3, (int) gy1 - top); + } + } + } + if (e.b.shape() != null) { + break; + } + } + } + + /** + * Assuming this edge's coordinates have been properly assigned, and given the desired color, draw + * the edge label. + */ + void drawLabel(final Artist gr, final Color color, final Color erase) { + if (this.label.length() > 0) { + final int top = this.a.graph.getTop(), left = this.a.graph.getLeft(); + gr.translate(-left, -top); + if (erase != null && this.a != this.b) { + final Rectangle2D.Double rect = new Rectangle2D.Double(this.labelbox.x, this.labelbox.y, + this.labelbox.w, this.labelbox.h); + gr.setColor(erase); + gr.draw(rect, true); + } + gr.setColor(color); + gr.drawString(this.label, this.labelbox.x, this.labelbox.y + Artist.getMaxAscent()); + // if (((AlloyTuple) uuid).getAtoms().get(0).changed + // && ((AlloyTuple) uuid).getAtoms().get(1).impacted) + // gr.drawString(" !", labelbox.x - 15, labelbox.y + Artist.getMaxAscent()); + gr.translate(left, top); + return; + } + } + + /** Return the height of the label box. */ + public int getLabelH() { + return this.labelbox.h; + } + + /** Return the width of the label box. */ + public int getLabelW() { + return this.labelbox.w; + } + + /** Return the X coordinate of the top-left corner of the label box. */ + public int getLabelX() { + return this.labelbox.x; + } + + /** Return the Y coordinate of the top-left corner of the label box. */ + public int getLabelY() { + return this.labelbox.y; + } + + /** Returns the label on this edge. */ + public String label() { + return this.label; + } + + /** Positions the arrow heads of the given edge properly. */ + void layout_arrowHead() { + final Curve c = this.path(); + if (this.ahead() && this.a.shape() != null) { + double in = 0D, out = 1D; + while (StrictMath.abs(out - in) > 0.0001D) { + final double t = (in + out) / 2; + if (this.a.contains(c.getX(t), c.getY(t))) { + in = t; + } else { + out = t; + } + } + c.chopStart(in); + } + if (this.bhead() && this.b.shape() != null) { + double in = 1D, out = this.a == this.b ? 0.5D : 0D; + while (StrictMath.abs(out - in) > 0.0001D) { + final double t = (in + out) / 2; + if (this.b.contains(c.getX(t), c.getY(t))) { + in = t; + } else { + out = t; + } + } + c.chopEnd(in); + } + } + + /** + * Returns the current path; if the path was not yet assigned, it returns a straight line from + * "from" node to "to" node. + */ + Curve path() { + if (this.path == null) { + this.resetPath(); + } + return this.path; + } + + /** + * Given that this edge is already well-laid-out, this method moves the label hoping to + * avoid/minimize overlap. + */ + void repositionLabel(final AvailableSpace sp) { + if (this.label.length() == 0 || this.a == this.b) { + return; // labels on self-edges are already re-positioned by GraphEdge.resetPath() + } + final int gap = this.style == DotStyle.BOLD ? 4 : 2; // If the line is bold, we need to shift + // the + // label to the right a little bit + boolean failed = false; + Curve p = this.path; + for (GraphNode a = this.a; a.shape() == null;) { + final GraphEdge e = a.ins.get(0); + a = e.a; + p = e.path().join(p); + } + for (GraphNode b = this.b; b.shape() == null;) { + final GraphEdge e = b.outs.get(0); + b = e.b; + p = p.join(e.path()); + } + for (double t = 0.5D;; t = t + 0.05D) { + if (t >= 1D) { + failed = true; + t = 0.7D; + } + double x1 = p.getX(t), y = p.getY(t), x2 = p.getXatY(y + this.labelbox.h, t, 1D, x1); + int x = (int) (x1 < x2 ? x2 + gap : x1 + gap); + if (failed || sp.ok(x, (int) y, this.labelbox.w, this.labelbox.h)) { + sp.add(this.labelbox.x = x, this.labelbox.y = (int) y, this.labelbox.w, this.labelbox.h); + return; + } + final double t2 = 1D - t; + x1 = p.getX(t2); + y = p.getY(t2); + x2 = p.getXatY(y + this.labelbox.h, t2, 1D, x1); + x = (int) (x1 < x2 ? x2 + gap : x1 + gap); + if (sp.ok(x, (int) y, this.labelbox.w, this.labelbox.h)) { + sp.add(this.labelbox.x = x, this.labelbox.y = (int) y, this.labelbox.w, this.labelbox.h); + return; + } + } + } + + /** + * Reset the path as a straightline from the center of the "from" node to the center of the "to" + * node. + */ + void resetPath() { + final double ax = this.a.x(), ay = this.a.y(); + if (this.a == this.b) { + double w = 0; + for (int n = this.a.selfs.size(), i = 0; i < n; i++) { + if (i == 0) { + w = this.a.getWidth() / 2 + Graph.selfLoopA; + } else { + w = w + Artist.getBounds(false, this.a.selfs.get(i - 1).label()).getWidth() + + Graph.selfLoopGL + Graph.selfLoopGR; + } + final GraphEdge e = this.a.selfs.get(i); + if (e != this) { + continue; + } + final double h = this.a.getHeight() / 2D * 0.7D, k = 0.55238D, + wa = this.a.getWidth() / 2.0D, wb = w - wa; + e.path = new Curve(ax, ay); + e.path.cubicTo(ax, ay - k * h, ax + wa - k * wa, ay - h, ax + wa, ay - h); + e.path.cubicTo(ax + wa + k * wb, ay - h, ax + wa + wb, ay - k * h, ax + wa + wb, ay); + e.path.cubicTo(ax + wa + wb, ay + k * h, ax + wa + k * wb, ay + h, ax + wa, ay + h); + e.path.cubicTo(ax + wa - k * wa, ay + h, ax, ay + k * h, ax, ay); + e.labelbox.x = (int) (ax + w + Graph.selfLoopGL); + e.labelbox.y = (int) (ay - Artist.getBounds(false, e.label()).getHeight() / 2); + break; + } + } else { + int i = 0, n = 0; + for (final GraphEdge e : this.a.outs) { + if (e == this) { + i = n++; + } else if (e.b == this.b) { + n++; + } + } + final double cx = this.b.x(), cy = this.b.y(); + double bx = (ax + cx) / 2; + final double by = (ay + cy) / 2; + this.path = new Curve(ax, ay); + if (n > 1 && (n & 1) == 1) { + if (i < n / 2) { + bx = bx - (n / 2 - i) * 10; + } else if (i > n / 2) { + bx = bx + (i - n / 2) * 10; + } + this.path.lineTo(bx, by).lineTo(cx, cy); + } else if (n > 1) { + if (i < n / 2) { + bx = bx - (n / 2 - i) * 10 + 5; + } else { + bx = bx + (i - n / 2) * 10 + 5; + } + this.path.lineTo(bx, by).lineTo(cx, cy); + } else { + this.path.lineTo(cx, cy); + } + } + } + + /** Swaps the "from" node and "to" node. */ + void reverse() { + if (this.a == this.b) { + return; + } + this.a.outs.remove(this); + this.b.ins.remove(this); + this.a.ins.add(this); + this.b.outs.add(this); + final GraphNode x = this.a; + this.a = this.b; + this.b = x; + } + + /** + * Sets whether we will draw an arrow head on the "from" node, and whether we will draw an arrow + * head on the "to" node. + */ + public GraphEdge set(final boolean from, final boolean to) { + this.ahead = from; + this.bhead = to; + return this; + } + + /** Sets the line color. */ + public GraphEdge set(final Color color) { + if (color != null) { + this.color = color; + } + return this; + } + + /** Sets the line style. */ + public GraphEdge set(final DotStyle style) { + if (style != null) { + this.style = style; + } + return this; + } + + /** Sets the edge weight between 1 and 10000. */ + public GraphEdge set(int weightBetween1And10000) { + if (weightBetween1And10000 < 1) { + weightBetween1And10000 = 1; + } + if (weightBetween1And10000 > 10000) { + weightBetween1And10000 = 10000; + } + this.weight = weightBetween1And10000; + return this; + } + + /** Returns the line style; never null. */ + public DotStyle style() { + return this.style; + } + + /** Returns a DOT representation of this edge (or "" if the start node is a dummy node) */ + @Override + public String toString() { + final GraphNode a = this.a; + GraphNode b = this.b; + if (a.shape() == null) { + return ""; // This means this edge is virtual + } + while (b.shape() == null) { + b = b.outs.get(0).b; + } + String color = Integer.toHexString(this.color.getRGB() & 0xFFFFFF); + while (color.length() < 6) { + color = "0" + color; + } + final StringBuilder out = new StringBuilder(); + out.append("\"N" + a.pos() + "\""); + out.append(" -> "); + out.append("\"N" + b.pos() + "\""); + out.append(" ["); + out.append("uuid = \"" + (this.uuid == null ? "" : Graph.esc(this.uuid.toString())) + "\""); + out.append(", color = \"#" + color + "\""); + out.append(", fontcolor = \"#" + color + "\""); + out.append(", style = \"" + this.style.getDotText() + "\""); + out.append(", label = \"" + Graph.esc(this.label) + "\""); + out.append(", dir = \"" + (this.ahead && this.bhead ? "both" : this.bhead ? "forward" : "back") + + "\""); + out.append(", weight = \"" + this.weight + "\""); + out.append("]\n"); + return out.toString(); + } + + /** Returns the edge weight (which is always between 1 and 10000 inclusively). */ + public int weight() { + return this.weight; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/GraphNode.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/GraphNode.java new file mode 100644 index 00000000..43d9491a --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/GraphNode.java @@ -0,0 +1,1028 @@ +/* + * Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4graph; + +import java.awt.Color; +import java.awt.Polygon; +import java.awt.Shape; +import java.awt.geom.GeneralPath; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import edu.mit.csail.sdg.alloy4viz.AlloyAtom; + +/** + * Mutable; represents a graphical node. + * + *

+ * Thread Safety: Can be called only by the AWT event thread. + */ + +public final strictfp class GraphNode { + + // =============================== adjustable options + // ================================================== + + /** This determines the minimum width of a dummy node. */ + private static final int dummyWidth = 30; + + /** This determines the minimum height of a dummy node. */ + private static final int dummyHeight = 10; + + /** + * This determines the minimum amount of padding added above, left, right, and below the text + * label. + */ + private static final int labelPadding = 5; + + /** Color to use to show a highlighted node. */ + private static final Color COLOR_CHOSENNODE = Color.LIGHT_GRAY; + + // =============================== cached for performance =================================== + + /** + * Caches the value of sqrt(3.0). The extra digits in the definition will be truncated by the Java + * compiler. + */ + private static final double sqrt3 = 1.7320508075688772935274463415058723669428052538103806280558D; + + /** + * Caches the value of sin(36 degree). The extra digits in the definition will be truncated by the + * Java compiler. + */ + private static final double sin36 = 0.5877852522924731291687059546390727685976524376431459910723D; + + /** + * Caches the value of cos(36 degree). The extra digits in the definition will be truncated by the + * Java compiler. + */ + private static final double cos36 = 0.8090169943749474241022934171828190588601545899028814310677D; + + /** + * Caches the value of cos(18 degree). The extra digits in the definition will be truncated by the + * Java compiler. + */ + private static final double cos18 = 0.9510565162951535721164393333793821434056986341257502224473D; + + /** + * Caches the value of tan(18 degree). The extra digits in the definition will be truncated by the + * Java compiler. + */ + private static final double tan18 = 0.3249196962329063261558714122151344649549034715214751003078D; + + public static int xLabel, yLabel; + + // =============================== these fields do not affect the computed bounds + // =============================================== + + /** + * The maximum ascent and descent. We deliberately do NOT make this field "static" because only + * AWT thread can call Artist. + */ + private final int ad = Artist.getMaxAscentAndDescent(); + + /** + * a user-provided annotation that will be associated with this node (can be null) (need not be + * unique) + */ + public final Object uuid; + + /** + * The X coordinate of the center of the node; modified by tweak(), layout_computeX(), layout(), + * and relayout_edges() + */ + private int centerX = 0; + + /** + * The Y coordinate of the center of the node; modified by tweak(), layout_computeX(), layout(), + * and relayout_edges() + */ + private int centerY = 0; + + /** + * The graph that this node belongs to; must stay in sync with Graph.nodelist and Graph.layerlist + */ + final Graph graph; + + /** The layer that this node is in; must stay in sync with Graph.layerlist */ + private int layer = 0; + + /** + * The current position of this node in the graph's node list; must stay in sync with + * Graph.nodelist + */ + int pos; + + /** + * The "in" edges not including "self" edges; must stay in sync with GraphEdge.a and GraphEdge.b + */ + final LinkedList ins = new LinkedList<>(); + + // =============================== these fields affect the computed bounds + // =================================================== + + /** + * The "out" edges not including "self" edges; must stay in sync with GraphEdge.a and GraphEdge.b + */ + final LinkedList outs = new LinkedList<>(); + + /** + * The "self" edges; must stay in sync with GraphEdge.a and GraphEdge.b + *

+ * When this value changes, we should invalidate the previously computed bounds information. + */ + final LinkedList selfs = new LinkedList<>(); + + /** + * The font boldness. + *

+ * When this value changes, we should invalidate the previously computed bounds information. + */ + private boolean fontBold = false; + + /** + * The node labels; if null or empty, then the node has no labels. + *

+ * When this value changes, we should invalidate the previously computed bounds information. + */ + private List labels = null; + + /** + * The node color; never null. + *

+ * When this value changes, we should invalidate the previously computed bounds information. + */ + private Color color = Color.WHITE; + + /** + * The line style; never null. + *

+ * When this value changes, we should invalidate the previously computed bounds information. + */ + private DotStyle style = DotStyle.SOLID; + + // ============================ these fields are computed by calcBounds() + // ========================================= + + /** + * The node shape; if null, then the node is a dummy node. + *

+ * When this value changes, we should invalidate the previously computed bounds information. + */ + private DotShape shape = DotShape.BOX; + + /** If (updown>=0), this is the distance from the center to the top edge. */ + private int updown = -1; + + /** If (updown>=0), this is the distance from the center to the left edge. */ + private int side = 0; + + /** + * If (updown>=0), this is the vertical distance between the center of the text label and the + * center of the node. + */ + private int yShift = 0; + + /** If (updown>=0), this is the width of the text label. */ + private int width = 0; + + /** If (updown>=0), this is the height of the text label. */ + private int height = 0; + + /** + * If (updown>=0), this is the amount of space on the right set-aside for self-loops (which is 0 + * if node has no self loops) + */ + private int reserved = 0; + + /** + * If (updown>=0 and shape!=null), this is the bounding polygon. Note: if not null, it must be + * either a GeneralPath or a Polygon. + */ + private Shape poly = null; + + /** + * If (updown>=0 and shape!=null and poly2!=null), then poly2 will also be drawn during the draw() + * method. Note: if not null, it must be either a GeneralPath or a Polygon. + */ + private Shape poly2 = null; + + /** + * If (updown>=0 and shape!=null and poly3!=null), then poly3 will also be drawn during the draw() + * method. Note: if not null, it must be either a GeneralPath or a Polygon. + */ + private Shape poly3 = null; + + public Artist artist; + + // =================================================================================================== + + /** Create a new node with the given list of labels, then add it to the given graph. */ + public GraphNode(final Graph graph, final Object uuid, final String... labels) { + this.uuid = uuid; + this.graph = graph; + this.pos = graph.nodelist.size(); + graph.nodelist.add(this); + if (graph.layerlist.size() == 0) { + graph.layerlist.add(new ArrayList()); + } + graph.layerlist.get(0).add(this); + if (labels != null && labels.length > 0) { + this.labels = new ArrayList<>(labels.length); + for (int i = 0; i < labels.length; i++) { + this.labels.add(labels[i]); + } + } + } + + /** Add the given label after the existing labels, then invalidate the computed bounds. */ + public GraphNode addLabel(final String label) { + if (label == null || label.length() == 0) { + return this; + } + if (this.labels == null) { + this.labels = new ArrayList<>(); + } + this.labels.add(label); + this.updown = -1; + return this; + } + + /** (Re-)calculate this node's bounds. */ + void calcBounds() { + this.reserved = this.yShift = 0; + this.width = 2 * GraphNode.labelPadding; + if (this.width < GraphNode.dummyWidth) { + this.side = GraphNode.dummyWidth / 2; + } + this.height = this.width; + if (this.height < GraphNode.dummyHeight) { + this.updown = GraphNode.dummyHeight / 2; + } + this.poly = this.poly2 = this.poly3 = null; + if (this.shape == null) { + return; + } + Polygon poly = new Polygon(); + if (this.labels != null) { + for (int i = 0; i < this.labels.size(); i++) { + final String t = this.labels.get(i); + final Rectangle2D rect = Artist.getBounds(this.fontBold, t); + final int ww = (int) rect.getWidth() + 1; // Round it up + if (this.width < ww) { + this.width = ww; + } + this.height = this.height + this.ad; + } + } + int hw = (this.width + 1) / 2 + GraphNode.labelPadding; + if (hw < this.ad / 2) { + hw = this.ad / 2; + } + this.width = hw * 2; + this.side = hw; + int hh = (this.height + 1) / 2 + GraphNode.labelPadding; + if (hh < this.ad / 2) { + hh = this.ad / 2; + } + this.height = hh * 2; + this.updown = hh; + switch (this.shape) { + case HOUSE: { + this.yShift = this.ad / 2; + this.updown = this.updown + this.yShift; + poly.addPoint(-hw, this.yShift - hh); + poly.addPoint(0, -this.updown); + poly.addPoint(hw, this.yShift - hh); + poly.addPoint(hw, this.yShift + hh); + poly.addPoint(-hw, this.yShift + hh); + break; + } + case INV_HOUSE: { + this.yShift = -this.ad / 2; + this.updown = this.updown - this.yShift; + poly.addPoint(-hw, this.yShift - hh); + poly.addPoint(hw, this.yShift - hh); + poly.addPoint(hw, this.yShift + hh); + poly.addPoint(0, this.updown); + poly.addPoint(-hw, this.yShift + hh); + break; + } + case TRIANGLE: + case INV_TRIANGLE: { + int dx = (int) (this.height / GraphNode.sqrt3); + dx = dx + 1; + if (dx < 6) { + dx = 6; + } + int dy = (int) (hw * GraphNode.sqrt3); + dy = dy + 1; + if (dy < 6) { + dy = 6; + } + dy = dy / 2 * 2; + this.side += dx; + this.updown += dy / 2; + if (this.shape == DotShape.TRIANGLE) { + this.yShift = dy / 2; + poly.addPoint(0, -this.updown); + poly.addPoint(hw + dx, this.updown); + poly.addPoint(-hw - dx, this.updown); + } else { + this.yShift = -dy / 2; + poly.addPoint(0, this.updown); + poly.addPoint(hw + dx, -this.updown); + poly.addPoint(-hw - dx, -this.updown); + } + break; + } + case HEXAGON: { + this.side += this.ad; + poly.addPoint(-hw - this.ad, 0); + poly.addPoint(-hw, -hh); + poly.addPoint(hw, -hh); + poly.addPoint(hw + this.ad, 0); + poly.addPoint(hw, hh); + poly.addPoint(-hw, hh); + break; + } + case TRAPEZOID: { + this.side += this.ad; + poly.addPoint(-hw, -hh); + poly.addPoint(hw, -hh); + poly.addPoint(hw + this.ad, hh); + poly.addPoint(-hw - this.ad, hh); + break; + } + case INV_TRAPEZOID: { + this.side += this.ad; + poly.addPoint(-hw - this.ad, -hh); + poly.addPoint(hw + this.ad, -hh); + poly.addPoint(hw, hh); + poly.addPoint(-hw, hh); + break; + } + case PARALLELOGRAM: { + this.side += this.ad; + poly.addPoint(-hw, -hh); + poly.addPoint(hw + this.ad, -hh); + poly.addPoint(hw, hh); + poly.addPoint(-hw - this.ad, hh); + break; + } + case M_DIAMOND: + case DIAMOND: { + if (this.shape == DotShape.M_DIAMOND) { + if (hw < 10) { + hw = 10; + this.side = 10; + this.width = 20; + } + if (hh < 10) { + hh = 10; + this.updown = 10; + this.height = 20; + } + } + this.updown += hw; + this.side += hh; + poly.addPoint(-hw - hh, 0); + poly.addPoint(0, -hh - hw); + poly.addPoint(hw + hh, 0); + poly.addPoint(0, hh + hw); + break; + } + case M_SQUARE: { + if (hh < hw) { + hh = hw; + } else { + hw = hh; + } + if (hh < 6) { + hh = 6; + hw = 6; + } + this.width = hw * 2; + this.side = hw; + this.height = hh * 2; + this.updown = hh; + this.side += 4; + this.updown += 4; + poly.addPoint(-hw - 4, -hh - 4); + poly.addPoint(hw + 4, -hh - 4); + poly.addPoint(hw + 4, hh + 4); + poly.addPoint(-hw - 4, hh + 4); + break; + } + case OCTAGON: + case DOUBLE_OCTAGON: + case TRIPLE_OCTAGON: { + final int dx = this.width / 3, dy = this.ad; + this.updown += dy; + poly.addPoint(-hw, -hh); + poly.addPoint(-hw + dx, -hh - dy); + poly.addPoint(hw - dx, -hh - dy); + poly.addPoint(hw, -hh); + poly.addPoint(hw, hh); + poly.addPoint(hw - dx, hh + dy); + poly.addPoint(-hw + dx, hh + dy); + poly.addPoint(-hw, hh); + if (this.shape == DotShape.OCTAGON) { + break; + } + final double c = StrictMath.sqrt(dx * dx + dy * dy), a = dx * dy / c, k = (a + 5) * dy / dx, + r = StrictMath.sqrt((a + 5) * (a + 5) + k * k) - dy; + final double dx1 = (r - 5) * dx / dy, dy1 = -((dx + 5D) * dy / dx - dy - r); + int x1 = (int) StrictMath.round(dx1), y1 = (int) StrictMath.round(dy1); + this.updown += 5; + this.side += 5; + this.poly2 = poly; + poly = new Polygon(); + poly.addPoint(-hw - 5, -hh - y1); + poly.addPoint(-hw + dx - x1, -hh - dy - 5); + poly.addPoint(hw - dx + x1, -hh - dy - 5); + poly.addPoint(hw + 5, -hh - y1); + poly.addPoint(hw + 5, hh + y1); + poly.addPoint(hw - dx + x1, hh + dy + 5); + poly.addPoint(-hw + dx - x1, hh + dy + 5); + poly.addPoint(-hw - 5, hh + y1); + if (this.shape == DotShape.DOUBLE_OCTAGON) { + break; + } + this.updown += 5; + this.side += 5; + this.poly3 = poly; + poly = new Polygon(); + x1 = (int) StrictMath.round(dx1 * 2); + y1 = (int) StrictMath.round(dy1 * 2); + poly.addPoint(-hw - 10, -hh - y1); + poly.addPoint(-hw + dx - x1, -hh - dy - 10); + poly.addPoint(hw - dx + x1, -hh - dy - 10); + poly.addPoint(hw + 10, -hh - y1); + poly.addPoint(hw + 10, hh + y1); + poly.addPoint(hw - dx + x1, hh + dy + 10); + poly.addPoint(-hw + dx - x1, hh + dy + 10); + poly.addPoint(-hw - 10, hh + y1); + break; + } + case M_CIRCLE: + case CIRCLE: + case DOUBLE_CIRCLE: { + int radius = (int) StrictMath.sqrt(hw * (double) hw + (double) hh * hh) + 2; + if (this.shape == DotShape.DOUBLE_CIRCLE) { + radius = radius + 5; + } + final int L = (int) (radius / GraphNode.cos18) + 2, a = (int) (L * GraphNode.sin36), + b = (int) (L * GraphNode.cos36), c = (int) (radius * GraphNode.tan18); + poly.addPoint(-L, 0); + poly.addPoint(-b, a); + poly.addPoint(-c, L); + poly.addPoint(c, L); + poly.addPoint(b, a); + poly.addPoint(L, 0); + poly.addPoint(b, -a); + poly.addPoint(c, -L); + poly.addPoint(-c, -L); + poly.addPoint(-b, -a); + this.updown = L; + this.side = L; + break; + } + case EGG: + case ELLIPSE: { + final int pad = this.ad / 2; + this.side += pad; + this.updown += pad; + final int d = this.shape == DotShape.ELLIPSE ? 0 : this.ad / 2; + final GeneralPath path = new GeneralPath(); + path.moveTo(-this.side, d); + path.quadTo(-this.side, -this.updown, 0, -this.updown); + path.quadTo(this.side, -this.updown, this.side, d); + path.quadTo(this.side, this.updown, 0, this.updown); + path.quadTo(-this.side, this.updown, -this.side, d); + path.closePath(); + this.poly = path; + } + default: { // BOX + if (this.shape != DotShape.BOX) { + final int d = this.ad / 2; + hw = hw + d; + this.side = hw; + hh = hh + d; + this.updown = hh; + } + poly.addPoint(-hw, -hh); + poly.addPoint(hw, -hh); + poly.addPoint(hw, hh); + poly.addPoint(-hw, hh); + } + } + if (this.shape != DotShape.EGG && this.shape != DotShape.ELLIPSE) { + this.poly = poly; + } + for (int i = 0; i < this.selfs.size(); i++) { + if (i == 0) { + this.reserved = this.side + Graph.selfLoopA; + continue; + } + final String label = this.selfs.get(i - 1).label(); + this.reserved = this.reserved + (int) Artist.getBounds(false, label).getWidth() + + Graph.selfLoopGL + Graph.selfLoopGR; + } + if (this.reserved > 0) { + final String label = this.selfs.get(this.selfs.size() - 1).label(); + this.reserved = this.reserved + (int) Artist.getBounds(false, label).getWidth() + + Graph.selfLoopGL + Graph.selfLoopGR; + } + } + + /** Returns true if the node contains the given point or not. */ + boolean contains(final double x, final double y) { + if (this.shape == null) { + return false; + } else if (this.updown < 0) { + this.calcBounds(); + } + return this.poly.contains(x - this.centerX, y - this.centerY); + } + + /** + * Draws this node at its current (x, y) location; this method will call calcBounds() if + * necessary. + */ + void draw(final Artist gr, final double scale, final boolean highlight) { + if (this.shape == null) { + return; + } else if (this.updown < 0) { + this.calcBounds(); + } + final int top = this.graph.getTop(), left = this.graph.getLeft(); + gr.set(this.style, scale); + gr.translate(this.centerX - left, this.centerY - top); + gr.setFont(this.fontBold); + if (highlight) { + gr.setColor(GraphNode.COLOR_CHOSENNODE); + } else { + gr.setColor(this.color); + } + if (this.shape == DotShape.CIRCLE || this.shape == DotShape.M_CIRCLE + || this.shape == DotShape.DOUBLE_CIRCLE) { + final int hw = this.width / 2, hh = this.height / 2; + int radius = (int) StrictMath.sqrt(hw * (double) hw + (double) hh * hh) + 2; + if (this.shape == DotShape.DOUBLE_CIRCLE) { + radius = radius + 5; + } + gr.fillCircle(radius); + gr.setColor(Color.BLACK); + gr.drawCircle(radius); + // if (this.style == DotStyle.DOTTED || this.style == DotStyle.DASHED) { + // gr.set(DotStyle.SOLID, scale); + // } + if (this.uuid instanceof AlloyAtom && ((AlloyAtom) this.uuid).isDashed) { + gr.set(DotStyle.DASHED, scale); + } else { + gr.set(DotStyle.SOLID, scale); + } + if (this.shape == DotShape.M_CIRCLE && 10 * radius >= 25 && radius > 5) { + final int d = (int) StrictMath.sqrt(10 * radius - 25.0D); + if (d > 0) { + gr.drawLine(-d, -radius + 5, d, -radius + 5); + gr.drawLine(-d, radius - 5, d, radius - 5); + } + } + if (this.shape == DotShape.DOUBLE_CIRCLE) { + gr.drawCircle(radius - 5); + } + } else { + gr.draw(this.poly, true); + gr.setColor(Color.BLACK); + gr.draw(this.poly, false); + if (this.poly2 != null) { + gr.draw(this.poly2, false); + } + if (this.poly3 != null) { + gr.draw(this.poly3, false); + } + // if (this.style == DotStyle.DOTTED || this.style == DotStyle.DASHED) { + // gr.set(DotStyle.SOLID, scale); + // } + if (this.uuid instanceof AlloyAtom && ((AlloyAtom) this.uuid).isDashed) { + gr.set(DotStyle.DASHED, scale); + } else { + gr.set(DotStyle.SOLID, scale); + } + if (this.shape == DotShape.M_DIAMOND) { + gr.drawLine(-this.side + 8, -8, -this.side + 8, 8); + gr.drawLine(-8, -this.side + 8, 8, -this.side + 8); + gr.drawLine(this.side - 8, -8, this.side - 8, 8); + gr.drawLine(-8, this.side - 8, 8, this.side - 8); + } + if (this.shape == DotShape.M_SQUARE) { + gr.drawLine(-this.side, -this.side + 8, -this.side + 8, -this.side); + gr.drawLine(this.side, -this.side + 8, this.side - 8, -this.side); + gr.drawLine(-this.side, this.side - 8, -this.side + 8, this.side); + gr.drawLine(this.side, this.side - 8, this.side - 8, this.side); + } + } + gr.set(DotStyle.SOLID, scale); + final int clr = this.color.getRGB() & 0xFFFFFF; + gr.setColor(clr == 0x000000 || clr == 0xff0000 || clr == 0x0000ff ? Color.WHITE : Color.BLACK); + if (this.labels != null && this.labels.size() > 0) { + final int x = -this.width / 2; + int y = this.yShift + -this.labels.size() * this.ad / 2; + for (int i = 0; i < this.labels.size(); i++) { + final String t = this.labels.get(i); + int w = (int) Artist.getBounds(this.fontBold, t).getWidth() + 1; // Round it up + if (this.width > w) { + w = (this.width - w) / 2; + } else { + w = 0; + } + gr.drawString(t, x + w, y + Artist.getMaxAscent()); + if (this.uuid instanceof AlloyAtom && ((AlloyAtom) this.uuid).changed) { + gr.drawString(" *", x + w - 15, y + Artist.getMaxAscent() - 15); + } + this.artist = gr; + GraphNode.xLabel = x + w; + GraphNode.yLabel = y + Artist.getMaxAscent(); + + y = y + this.ad; + } + } + gr.translate(left - this.centerX, top - this.centerY); + } + + /** + * Returns the bounding rectangle (with 2*xfluff added to the width, and 2*yfluff added to the + * height) + */ + Rectangle2D getBoundingBox(final int xfluff, final int yfluff) { + if (this.updown < 0) { + this.calcBounds(); + } + return new Rectangle2D.Double(this.x() - this.side - xfluff, this.y() - this.updown - yfluff, + this.side + this.side + xfluff + xfluff, this.updown + this.updown + yfluff + yfluff); + } + + /** Returns the node height. */ + int getHeight() { + if (this.updown < 0) { + this.calcBounds(); + } + return this.updown + this.updown; + } + + /** + * Returns the amount of space we need to reserve on the right hand side for the self edges (0 if + * this has no self edges now) + */ + int getReserved() { + if (this.selfs.isEmpty()) { + return 0; + } else if (this.updown < 0) { + this.calcBounds(); + } + return this.reserved; + } + + /** Returns the node width. */ + int getWidth() { + if (this.updown < 0) { + this.calcBounds(); + } + return this.side + this.side; + } + + /** Returns an unmodifiable view of the list of "in" edges. */ + public List inEdges() { + return Collections.unmodifiableList(this.ins); + } + + /** Returns the layer that this node is in. */ + int layer() { + return this.layer; + } + + /** Returns an unmodifiable view of the list of "out" edges. */ + public List outEdges() { + return Collections.unmodifiableList(this.outs); + } + + /** + * Returns the node's current position in the node list, which is always between 0 and + * node.size()-1 + */ + int pos() { + return this.pos; + } + + /** Returns an unmodifiable view of the list of "self" edges. */ + public List selfEdges() { + return Collections.unmodifiableList(this.selfs); + } + + /** Changes the node color, then invalidate the computed bounds. */ + public GraphNode set(final Color color) { + if (this.color != color && color != null) { + this.color = color; + this.updown = -1; + } + return this; + } + + /** + * Changes the node shape (where null means change the node into a dummy node), then invalidate + * the computed bounds. + */ + public GraphNode set(final DotShape shape) { + if (this.shape != shape) { + this.shape = shape; + this.updown = -1; + } + return this; + } + + /** Changes the line style, then invalidate the computed bounds. */ + public GraphNode set(final DotStyle style) { + if (this.style != style && style != null) { + this.style = style; + this.updown = -1; + } + return this; + } + + /** Changes the font boldness, then invalidate the computed bounds. */ + public GraphNode setFontBoldness(final boolean bold) { + if (this.fontBold != bold) { + this.fontBold = bold; + this.updown = -1; + } + return this; + } + + /** + * Changes the layer that this node is in; the new layer must be 0 or greater. + *

+ * If a node is removed from a layer, the order of the other nodes in that layer remain unchanged. + *

+ * If a node is added to a new layer, then it is added to the right of the original rightmost node + * in that layer. + */ + void setLayer(final int newLayer) { + if (newLayer < 0) { + throw new IllegalArgumentException("The layer cannot be negative!"); + } + if (this.layer == newLayer) { + return; + } + this.graph.layerlist.get(this.layer).remove(this); + this.layer = newLayer; + while (this.layer >= this.graph.layerlist.size()) { + this.graph.layerlist.add(new ArrayList()); + } + this.graph.layerlist.get(this.layer).add(this); + } + + /** + * Changes the X coordinate of the center of the node, without invalidating the computed bounds. + */ + void setX(final int x) { + this.centerX = x; + } + + /** + * Changes the Y coordinate of the center of the node, without invalidating the computed bounds. + */ + void setY(final int y) { + this.centerY = y; + } + + /** Helper method that sets the Y coordinate of every node in a given layer. */ + private void setY(final int layer, final int y) { + for (final GraphNode n : this.graph.layer(layer)) { + n.centerY = y; + } + } + + /** Returns the node shape (or null if the node is a dummy node). */ + DotShape shape() { + return this.shape; + } + + /** Helper method that shifts a node down. */ + private void shiftDown(int y) { + final int[] ph = this.graph.layerPH; + final int yJump = Graph.yJump / 6; + int i = this.layer(); + this.setY(i, y); + y = y + ph[i] / 2; // y is now the bottom-most edge of this layer + for (i--; i >= 0; i--) { + final List list = this.graph.layer(i); + final GraphNode first = list.get(0); + if (first.centerY - ph[i] / 2 - yJump < y) { + this.setY(i, y + ph[i] / 2 + yJump); + } + y = first.centerY + ph[i] / 2; + } + this.graph.relayout_edges(false); + } + + /** Helper method that shifts a node left. */ + private void shiftLeft(final List peers, int i, int x) { + final int xJump = Graph.xJump / 3; + this.centerX = x; + x = x - (this.shape == null ? 0 : this.side); // x is now the left-most edge of this node + for (i--; i >= 0; i--) { + final GraphNode node = peers.get(i); + final int side = node.shape == null ? 0 : node.side; + if (node.centerX + side + node.getReserved() + xJump > x) { + node.centerX = x - side - node.getReserved() - xJump; + } + x = node.centerX - side; + } + } + + /** Helper method that shifts a node right. */ + private void shiftRight(final List peers, int i, int x) { + final int xJump = Graph.xJump / 3; + this.centerX = x; + x = x + (this.shape == null ? 0 : this.side) + this.getReserved(); // x is now the right most + // edge of this node + for (i++; i < peers.size(); i++) { + final GraphNode node = peers.get(i); + final int side = node.shape == null ? 0 : node.side; + if (node.centerX - side - xJump < x) { + node.centerX = x + side + xJump; + } + x = node.centerX + side + node.getReserved(); + } + } + + /** Helper method that shifts a node up. */ + private void shiftUp(int y) { + final int[] ph = this.graph.layerPH; + final int yJump = Graph.yJump / 6; + int i = this.layer(); + this.setY(i, y); + y = y - ph[i] / 2; // y is now the top-most edge of this layer + for (i++; i < this.graph.layers(); i++) { + final List list = this.graph.layer(i); + final GraphNode first = list.get(0); + if (first.centerY + ph[i] / 2 + yJump > y) { + this.setY(i, y - ph[i] / 2 - yJump); + } + y = first.centerY - ph[i] / 2; + } + this.graph.relayout_edges(false); + } + + /** Helper method that swaps a node towards the left. */ + private void swapLeft(final List peers, int i, final int x) { + final int side = this.shape == null ? 2 : this.side; + final int left = x - side; + while (true) { + if (i == 0) { + this.centerX = x; + return; + } // no clash possible + final GraphNode other = peers.get(i - 1); + final int otherSide = other.shape == null ? 0 : other.side; + final int otherRight = other.centerX + otherSide + other.getReserved(); + if (otherRight < left) { + this.centerX = x; + return; + } // no clash + this.graph.swapNodes(this.layer(), i, i - 1); + i--; + if (other.shape != null) { + other.shiftRight(peers, i + 1, x + side + this.getReserved() + otherSide); + } + } + } + + /** Helper method that swaps a node towards the right. */ + private void swapRight(final List peers, int i, final int x) { + final int side = this.shape == null ? 2 : this.side; + final int right = x + side + this.getReserved(); + while (true) { + if (i == peers.size() - 1) { + this.centerX = x; + return; + } // no clash possible + final GraphNode other = peers.get(i + 1); + final int otherSide = other.shape == null ? 0 : other.side; + final int otherLeft = other.centerX - otherSide; + if (otherLeft > right) { + this.centerX = x; + return; + } // no clash + this.graph.swapNodes(this.layer(), i, i + 1); + i++; + if (other.shape != null) { + other.shiftLeft(peers, i - 1, x - side - other.getReserved() - otherSide); + } + } + } + + /** Returns a DOT representation of this node (or "" if this is a dummy node) */ + @Override + public String toString() { + if (this.shape == null) { + return ""; // This means it's a virtual node + } + final int rgb = this.color.getRGB() & 0xFFFFFF; + final String text = rgb == 0xFF0000 || rgb == 0x0000FF || rgb == 0 ? "FFFFFF" : "000000"; + String main = Integer.toHexString(rgb); + while (main.length() < 6) { + main = "0" + main; + } + final StringBuilder out = new StringBuilder(); + out.append("\"N" + this.pos + "\""); + out.append(" ["); + out.append("uuid=\""); + if (this.uuid != null) { + out.append(Graph.esc(this.uuid.toString())); + } + out.append("\", label=\""); + boolean first = true; + if (this.labels != null) { + for (final String label : this.labels) { + if (label.length() > 0) { + out.append((first ? "" : "\\n") + Graph.esc(label)); + first = false; + } + } + } + out.append("\", color=\"#" + main + "\""); + out.append(", fontcolor = \"#" + text + "\""); + out.append(", shape = \"" + this.shape.getDotText() + "\""); + out.append(", style = \"filled, " + this.style.getDotText() + "\""); + out.append("]\n"); + return out.toString(); + } + + /** + * Assuming the graph is already laid out, this shifts this node (and re-layouts nearby + * nodes/edges as necessary) + */ + void tweak(final int x, final int y) { + if (this.centerX == x && this.centerY == y) { + return; // If no change, then return right away + } + final List layer = this.graph.layer(this.layer()); + final int n = layer.size(); + int i; + for (i = 0; i < n; i++) { + if (layer.get(i) == this) { + break; // Figure out this node's position in its layer + } + } + if (this.centerX > x) { + this.swapLeft(layer, i, x); + } else if (this.centerX < x) { + this.swapRight(layer, i, x); + } + if (this.centerY > y) { + this.shiftUp(y); + } else if (this.centerY < y) { + this.shiftDown(y); + } else { + this.graph.relayout_edges(this.layer()); + } + this.graph.recalcBound(false); + } + + // =================================================================================================== + + /** Returns the X coordinate of the center of the node. */ + public int x() { + return this.centerX; + } + + // =================================================================================================== + + /** Returns the Y coordinate of the center of the node. */ + public int y() { + return this.centerY; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/GraphViewer.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/GraphViewer.java new file mode 100644 index 00000000..a307d9fb --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4graph/GraphViewer.java @@ -0,0 +1,440 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4graph; + +import static java.awt.event.InputEvent.BUTTON1_MASK; +import static java.awt.event.InputEvent.BUTTON3_MASK; +import static java.awt.event.InputEvent.CTRL_MASK; +import static java.awt.Color.WHITE; +import static java.awt.Color.BLACK; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JRadioButton; +import javax.swing.JTextField; +import javax.swing.JViewport; +import javax.swing.border.EmptyBorder; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import edu.mit.csail.sdg.alloy4.OurDialog; +import edu.mit.csail.sdg.alloy4.OurPDFWriter; +import edu.mit.csail.sdg.alloy4.OurPNGWriter; +import edu.mit.csail.sdg.alloy4.OurUtil; +import edu.mit.csail.sdg.alloy4.Util; + +/** This class displays the graph. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final strictfp class GraphViewer extends JPanel { + + /** This ensures the class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** The graph that we are displaying. */ + private final Graph graph; + + /** The current amount of zoom. */ + private double scale = 1d; + + /** The currently hovered GraphNode or GraphEdge or group, or null if there is none. */ + private Object highlight = null; + + /** The currently selected GraphNode or GraphEdge or group, or null if there is none. */ + private Object selected = null; + + /** The button that initialized the drag-and-drop; this value is undefined when we're not currently doing drag-and-drop. */ + private int dragButton = 0; + + /** The right-click context menu associated with this JPanel. */ + public final JPopupMenu pop = new JPopupMenu(); + + /** Locates the node or edge at the given (X,Y) location. */ + private Object alloyFind(int mouseX, int mouseY) { return graph.find(scale, mouseX, mouseY); } + + /** Returns the annotation for the node or edge at location x,y (or null if none) */ + public Object alloyGetAnnotationAtXY(int mouseX, int mouseY) { + Object obj = alloyFind(mouseX, mouseY); + if (obj instanceof GraphNode) return ((GraphNode)obj).uuid; + if (obj instanceof GraphEdge) return ((GraphEdge)obj).uuid; + return null; + } + + /** Returns the annotation for the currently selected node/edge (or null if none) */ + public Object alloyGetSelectedAnnotation() { + if (selected instanceof GraphNode) return ((GraphNode)selected).uuid; + if (selected instanceof GraphEdge) return ((GraphEdge)selected).uuid; + return null; + } + + /** Returns the annotation for the currently highlighted node/edge (or null if none) */ + public Object alloyGetHighlightedAnnotation() { + if (highlight instanceof GraphNode) return ((GraphNode)highlight).uuid; + if (highlight instanceof GraphEdge) return ((GraphEdge)highlight).uuid; + return null; + } + + /** Stores the mouse positions needed to calculate drag-and-drop. */ + private int oldMouseX=0, oldMouseY=0, oldX=0, oldY=0; + + /** Repaint this component. */ + public void alloyRepaint() { + Container c=getParent(); + while(c!=null) { if (c instanceof JViewport) break; else c=c.getParent(); } + setSize((int)(graph.getTotalWidth()*scale), (int)(graph.getTotalHeight()*scale)); + if (c!=null) { c.invalidate(); c.repaint(); c.validate(); } else { invalidate(); repaint(); validate(); } + } + + /** Construct a GraphViewer that displays the given graph. */ + public GraphViewer(final Graph graph) { + OurUtil.make(this, BLACK, WHITE, new EmptyBorder(0,0,0,0)); + setBorder(null); + this.scale = graph.defaultScale; + this.graph = graph; + graph.layout(); + final JMenuItem zoomIn = new JMenuItem("Zoom In"); + final JMenuItem zoomOut = new JMenuItem("Zoom Out"); + final JMenuItem zoomToFit = new JMenuItem("Zoom to Fit"); + final JMenuItem print = new JMenuItem("Export to PNG or PDF"); + pop.add(zoomIn); + pop.add(zoomOut); + pop.add(zoomToFit); + pop.add(print); + ActionListener act = new ActionListener() { + public void actionPerformed(ActionEvent e) { + Container c=getParent(); + while(c!=null) { if (c instanceof JViewport) break; else c=c.getParent(); } + if (e.getSource() == print) alloySaveAs(); + if (e.getSource() == zoomIn) { scale=scale*1.33d; if (!(scale<500d)) scale=500d; } + if (e.getSource() == zoomOut) { scale=scale/1.33d; if (!(scale>0.1d)) scale=0.1d; } + if (e.getSource() == zoomToFit) { + if (c==null) return; + int w=c.getWidth()-15, h=c.getHeight()-15; // 15 gives a comfortable round-off margin + if (w<=0 || h<=0) return; + double scale1 = ((double)w)/graph.getTotalWidth(), scale2 = ((double)h)/graph.getTotalHeight(); + if (scale1 Note: we intentionally choose to make it an instance field rather than a static field, + * since we want to make sure we only instantiate it from the AWT Event Dispatching thread. + */ + private final Color badColor = new Color(255,200,200); + + /** This synchronized field stores the most recent DPI value. */ + private static volatile double oldDPI=72; + + /** True if we are currently in the middle of a DocumentListener already. */ + private boolean recursive=false; + + /** This updates the three input boxes and the three accompanying text labels, then return the width in pixels. */ + private int alloyRefresh (int who, double ratio, JTextField w1, JLabel w2, JTextField h1, JLabel h2, JTextField d1, JLabel d2, JLabel msg) { + if (recursive) return 0; + try { + recursive=true; + w1.setBackground(WHITE); h1.setBackground(WHITE); d1.setBackground(WHITE); + boolean bad=false; + double w; try { w=Double.parseDouble(w1.getText()); } catch(NumberFormatException ex) { w=0; } + double h; try { h=Double.parseDouble(h1.getText()); } catch(NumberFormatException ex) { h=0; } + double d; try { d=Double.parseDouble(d1.getText()); } catch(NumberFormatException ex) { d=0; } + if (who==1) { h=((int)(w*100/ratio))/100D; h1.setText(""+h); } // Maintains aspect ratio + if (who==2) { w=((int)(h*100*ratio))/100D; w1.setText(""+w); } // Maintains aspect ratio + if (!(d>=0.01) || !(d<=10000)) { + bad=true; + d1.setBackground(badColor); + msg.setText("DPI must be between 0.01 and 10000"); + } + if (!(h>=0.01) || !(h<=10000)) { + bad=true; + h1.setBackground(badColor); + msg.setText("Height must be between 0.01 and 10000"); + if (who==1) h1.setText(""); + } + if (!(w>=0.01) || !(w<=10000)) { + bad=true; + w1.setBackground(badColor); + msg.setText("Width must be between 0.01 and 10000"); + if (who==2) w1.setText(""); + } + if (bad) { w2.setText(" inches"); h2.setText(" inches"); return 0; } else msg.setText(" "); + w2.setText(" inches ("+(int)(w*d)+" pixels)"); + h2.setText(" inches ("+(int)(h*d)+" pixels)"); + return (int)(w*d); + } finally { + recursive=false; + } + } + + /** Export the current drawing as a PNG or PDF file by asking the user for the filename and the image resolution. */ + public void alloySaveAs() { + // Figure out the initial width, height, and DPI that we might want to suggest to the user + final double ratio=((double)(graph.getTotalWidth()))/graph.getTotalHeight(); + double dpi, iw=8.5D, ih=((int)(iw*100/ratio))/100D; // First set the width to be 8.5inch and compute height accordingly + if (ih>11D) { ih=11D; iw=((int)(ih*100*ratio))/100D; } // If too tall, then set height=11inch, and compute width accordingly + synchronized(GraphViewer.class) { dpi=oldDPI; } + // Prepare the dialog box + final JLabel msg = OurUtil.label(" ", Color.RED); + final JLabel w = OurUtil.label("Width: "+((int)(graph.getTotalWidth()*scale))+" pixels"); + final JLabel h = OurUtil.label("Height: "+((int)(graph.getTotalHeight()*scale))+" pixels"); + final JTextField w1 = new JTextField(""+iw); final JLabel w0 = OurUtil.label("Width: "), w2 = OurUtil.label(""); + final JTextField h1 = new JTextField(""+ih); final JLabel h0 = OurUtil.label("Height: "), h2 = OurUtil.label(""); + final JTextField d1 = new JTextField(""+(int)dpi); final JLabel d0 = OurUtil.label("Resolution: "), d2 = OurUtil.label(" dots per inch"); + final JTextField dp1 = new JTextField(""+(int)dpi);final JLabel dp0 = OurUtil.label("Resolution: "), dp2 = OurUtil.label(" dots per inch"); + alloyRefresh(0, ratio, w1, w2, h1, h2, d1, d2, msg); + Dimension dim = new Dimension(100,20); + w1.setMaximumSize(dim); w1.setPreferredSize(dim); w1.setEnabled(false); + h1.setMaximumSize(dim); h1.setPreferredSize(dim); h1.setEnabled(false); + d1.setMaximumSize(dim); d1.setPreferredSize(dim); d1.setEnabled(false); + dp1.setMaximumSize(dim); dp1.setPreferredSize(dim); dp1.setEnabled(false); + w1.getDocument().addDocumentListener(new DocumentListener() { + public void changedUpdate(DocumentEvent e) { alloyRefresh(1,ratio,w1,w2,h1,h2,d1,d2,msg); } + public void insertUpdate(DocumentEvent e) { changedUpdate(null); } + public void removeUpdate(DocumentEvent e) { changedUpdate(null); } + }); + h1.getDocument().addDocumentListener(new DocumentListener() { + public void changedUpdate(DocumentEvent e) { alloyRefresh(2,ratio,w1,w2,h1,h2,d1,d2,msg); } + public void insertUpdate(DocumentEvent e) { changedUpdate(null); } + public void removeUpdate(DocumentEvent e) { changedUpdate(null); } + }); + d1.getDocument().addDocumentListener(new DocumentListener() { + public void changedUpdate(DocumentEvent e) { alloyRefresh(3,ratio,w1,w2,h1,h2,d1,d2,msg); } + public void insertUpdate(DocumentEvent e) { changedUpdate(null); } + public void removeUpdate(DocumentEvent e) { changedUpdate(null); } + }); + final JRadioButton b1 = new JRadioButton("As a PNG with the window's current magnification:", true); + final JRadioButton b2 = new JRadioButton("As a PNG with a specific width, height, and resolution:", false); + final JRadioButton b3 = new JRadioButton("As a PDF with the given resolution:", false); + b1.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + b2.setSelected(false); b3.setSelected(false); + if (!b1.isSelected()) b1.setSelected(true); + w1.setEnabled(false); h1.setEnabled(false); d1.setEnabled(false); dp1.setEnabled(false); msg.setText(" "); + w1.setBackground(WHITE); h1.setBackground(WHITE); d1.setBackground(WHITE); + } + }); + b2.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + b1.setSelected(false); b3.setSelected(false); + if (!b2.isSelected()) b2.setSelected(true); + w1.setEnabled(true); h1.setEnabled(true); d1.setEnabled(true); dp1.setEnabled(false); msg.setText(" "); + alloyRefresh(1,ratio,w1,w2,h1,h2,d1,d2,msg); + } + }); + b3.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + b1.setSelected(false); b2.setSelected(false); + if (!b3.isSelected()) b3.setSelected(true); + w1.setEnabled(false); h1.setEnabled(false); d1.setEnabled(false); dp1.setEnabled(true); msg.setText(" "); + w1.setBackground(WHITE); h1.setBackground(WHITE); d1.setBackground(WHITE); + } + }); + // Ask whether the user wants to change the width, height, and DPI + double myScale; + while(true) { + if (!OurDialog.getInput("Export as PNG or PDF", new Object[]{ + b1, OurUtil.makeH(20, w, null), OurUtil.makeH(20, h, null), " ", + b2, OurUtil.makeH(20, w0, w1, w2, null), + OurUtil.makeH(20, h0, h1, h2, null), + OurUtil.makeH(20, d0, d1, d2, null), + OurUtil.makeH(20, msg, null), + b3, OurUtil.makeH(20, dp0, dp1, dp2, null) + })) return; + // Let's validate the values + if (b2.isSelected()) { + int widthInPixel=alloyRefresh(3,ratio,w1,w2,h1,h2,d1,d2,msg); + String err = msg.getText().trim(); + if (err.length()>0) continue; + dpi=Double.parseDouble(d1.getText()); + myScale=((double)widthInPixel)/graph.getTotalWidth(); + int heightInPixel=(int)(graph.getTotalHeight()*myScale); + if (widthInPixel>4000 || heightInPixel>4000) + if (!OurDialog.yesno("The image dimension ("+widthInPixel+"x"+heightInPixel+") is very large. Are you sure?")) + continue; + } else if (b3.isSelected()) { + try { dpi=Double.parseDouble(dp1.getText()); } catch(NumberFormatException ex) { dpi=(-1); } + if (dpi<50 || dpi>3000) { OurDialog.alert("The DPI must be between 50 and 3000."); continue; } + myScale=0; // This field is unused for PDF generation + } else { + dpi=72; + myScale=scale; + } + break; + } + // Ask the user for a filename + File filename; + if (b3.isSelected()) + filename = OurDialog.askFile(false, null, ".pdf", "PDF file"); + else + filename = OurDialog.askFile(false, null, ".png", "PNG file"); + if (filename==null) return; + if (filename.exists() && !OurDialog.askOverwrite(filename.getAbsolutePath())) return; + // Attempt to write the PNG or PDF file + try { + System.gc(); // Try to avoid possible premature out-of-memory exceptions + if (b3.isSelected()) + alloySaveAsPDF(filename.getAbsolutePath(), (int)dpi); + else + alloySaveAsPNG(filename.getAbsolutePath(), myScale, dpi, dpi); + synchronized(GraphViewer.class) { oldDPI=dpi; } + Util.setCurrentDirectory(filename.getParentFile()); + } catch(Throwable ex) { + OurDialog.alert("An error has occured in writing the output file:\n" + ex); + } + } + + /** Export the current drawing as a PDF file with the given image resolution. */ + public void alloySaveAsPDF(String filename, int dpi) throws IOException { + try { + double xwidth = dpi*8L+(dpi/2L); // Width is up to 8.5 inch + double xheight = dpi*11L; // Height is up to 11 inch + double scale1 = (xwidth-dpi) / graph.getTotalWidth(); // We leave 0.5 inch on the left and right + double scale2 = (xheight-dpi) / graph.getTotalHeight(); // We leave 0.5 inch on the left and right + if (scale1 + * Thread Safety: Can be called only by the AWT event thread. + */ + +public final class AlloyAtom implements Comparable { + public boolean isDashed = false; + public boolean changed = false; + + public ArrayList impacted = new ArrayList<>(); + + /** The original name of this atom from the original Kodkod or other analysis. */ + private final String originalName; + + /** The most specific AlloyType that this atom belongs to. */ + private final AlloyType type; + + /** + * The index is a number that differentiates atoms of the same AlloyType; one special convention: + * (this atom is the only atom with this type) iff (index==Integer.MAX_VALUE) + */ + private final int index; + + /** Create a new AlloyAtom with the given type and index. */ + public AlloyAtom(final AlloyType type, final int index) { + this.type = type; + this.index = index; + this.originalName = type.getName() + "." + index; + } + + /** Create a new AlloyAtom with the given type, index, and label. */ + public AlloyAtom(final AlloyType type, final int index, final String originalName) { + this.type = type; + this.index = index; + this.originalName = originalName; + } + + /** + * Compare first by type, then by index, then by the original names.
+ * We guarantee x.equals(y) iff x.compareTo(y)==0 + * + *

+ * As a special cosmetic enhancement: if we're comparing integer atoms, we want to ignore the + * difference between seqInt and Int. + */ + @Override + public int compareTo(final AlloyAtom otherAtom) { + if (otherAtom == null) { + return 1; + } + AlloyType at = this.type; + if (at.equals(AlloyType.SEQINT)) { + at = AlloyType.INT; + } + AlloyType bt = otherAtom.type; + if (bt.equals(AlloyType.SEQINT)) { + bt = AlloyType.INT; + } + // This renaming is necessary in order to make sure the comparison is transitive. + // For example, assuming seq/Int comprises 0..3, then we want atom0 < atom5, + // even though atom0's TYPENAME > atom5's TYPENAME. + // On the other hand, if you have an atom X with type X, then we want to make sure X>5 just like + // X>0 + // (even though lexically, the type name "X" < the type name "seq/Int" + if (at.equals(AlloyType.INT) && bt.equals(AlloyType.INT)) { + return this.index < otherAtom.index ? -1 : this.index > otherAtom.index ? 1 : 0; + } + final int result = at.compareTo(bt); + if (result != 0) { + return result; + } + // We don't want to use the "return (index-otherAtom.index);" trick, + // especially since singleton sets will have index of Integer.MAX_VALUE. + if (this.index != otherAtom.index) { + return this.index < otherAtom.index ? -1 : 1; + } + return this.originalName.compareTo(otherAtom.originalName); + } + + /** Two AlloyAtoms are equal if they have the same type, same index, and same original name. */ + @Override + public boolean equals(final Object other) { + if (!(other instanceof AlloyAtom)) { + return false; + } + if (other == this) { + return true; + } + final AlloyAtom otherAtom = (AlloyAtom) other; + return this.index == otherAtom.index && this.type.equals(otherAtom.type) + && this.originalName.equals(otherAtom.originalName); + } + + public String getOriginalName() { + return this.originalName; + } + + /** Return the type of the AlloyAtom. */ + public AlloyType getType() { + return this.type; + } + + /** + * Return a label for this atom as recommended by a theme (theme can be null if there's no theme + * to consult). + */ + public String getVizName(final VizState theme, final boolean numberAtoms) { + if (theme != null) { + if (theme.useOriginalName() || this.type.getName().equals("String")) { + return this.originalName; + } + if (this.index == Integer.MAX_VALUE && this.type.getName().equals("Int") + && theme.label.get(this.type).length() == 0) { + // Special handling for Meta Model. (Only meta model could have index==MAX_VALUE) + return "Int"; + } + if (this.index == Integer.MIN_VALUE && this.type.getName().equals("seq/Int") + && theme.label.get(this.type).length() == 0) { + // Special handling for Meta Model. (Only meta model could have index==MIN_VALUE) + return "seq/Int"; + } + if (this.index == Integer.MAX_VALUE || !numberAtoms) { + return theme.label.get(this.type); + } else { + return theme.label.get(this.type) + this.index; + } + } + if (this.type.getName().equals("Int")) { + return "" + this.index; // Special override to display integers better + } + if (this.type.getName().equals("seq/Int")) { + return "" + this.index; // Special override to display integers better + } + if (this.index == Integer.MAX_VALUE || !numberAtoms) { + return this.type.getName(); + } else { + return this.type.getName() + this.index; + } + } + + /** Returns a hash code based on the type and index. */ + @Override + public int hashCode() { + return 7 * this.type.hashCode() + 5 * this.index + 17 * this.originalName.hashCode(); + } + + /** Provides a human-readable label for debugging purpose. */ + @Override + public String toString() { + return this.getVizName(null, true); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyElement.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyElement.java new file mode 100644 index 00000000..3f0f1cdf --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyElement.java @@ -0,0 +1,33 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4viz; + +/** Immutable; it's the abstract superclass extended by AlloyType, AlloySet, and AlloyRelation. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public abstract class AlloyElement implements Comparable { + + /** The name of the element. */ + private final String name; + + /** Returns the name of this element. */ + public String getName() { return name; } + + /** Constructs a new AlloyElement with that name. */ + AlloyElement(String name) { this.name=name; } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyInstance.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyInstance.java new file mode 100644 index 00000000..d1cb3046 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyInstance.java @@ -0,0 +1,316 @@ +/* + * Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4viz; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; + +/** + * Immutable; represents an Alloy instance that can be displayed in the visualizer. + * + *

+ * Thread Safety: Can be called only by the AWT event thread. + */ + +public final class AlloyInstance { + + /** The original A4Solution object. */ + final A4Solution originalA4; // FIXTHIS: eventually we shouldn't need this field... + + /** If true, it is a metamodel, else it is not a metamodel. */ + public final boolean isMetamodel; + + /** The original filename of the model that generated this instance; can be "" if unknown. */ + public final String filename; + + /** The original command that generated this instance; can be "" if unknown. */ + public final String commandname; + + /** The AlloyModel that this AlloyInstance is an instance of. */ + public final AlloyModel model; + + /** + * Maps each AlloyAtom to the AlloySet(s) it is in; its keySet is considered the universe of all + * atoms.
+ * The constructor ensures every AlloySet here is in model.getSets()
+ * Furthermore, every AlloyAtom's type is in model.getTypes()
+ * Finally, if an atom A is in a set S, we guarantee that A.type is equal or subtype of S.type + */ + public Map> atom2sets; + + /** + * Maps each AlloyType to the AlloyAtom(s) in that type; it is derived from atom2sets.keySet() + * directly.
+ * Thus, every AlloyType here is in model.getTypes(), and every AlloyAtom here is in + * atom2sets.keySet()
+ * Furthermore, the constructor ensures that if an atom is in a subtype, it is also in the + * supertype. + */ + private final Map> type2atoms; + + /** + * Maps each AlloySet to the AlloyAtom(s) in that set; it is derived from atom2sets directly.
+ * Thus, every AlloySet here is in model.getSets(), and every AlloyAtom here is in + * atom2sets.keySet()
+ * Finally, if an atom A is in a set S, we guarantee that A.type is equal or subtype of S.type + */ + private final Map> set2atoms; + + /** + * Maps each AlloyRelation to a set of AlloyTuple(s).
+ * The constructor ensures every AlloyRelation here is in model.getRelations()
+ * Furthermore, every AlloyAtom in every AlloyTuple here is in atom2sets.keySet()
+ * Finally, if a tuple T is in a relation R, we guarantee that T is a legal tuple for R (Meaning + * T.arity==R.arity, and for each i, T.getAtom(i).type is equal or subtype of R.getType(i).) + */ + public final Map> rel2tuples; + + /** This always stores an empty unmodifiable list of atoms. */ + private static final List noAtom = ConstList.make(); + + /** This always stores an empty unmodifiable list of sets. */ + private static final List noSet = ConstList.make(); + + /** This always stores an empty unmodifiable set of tuples. */ + private static final Set noTuple = + Collections.unmodifiableSet(new TreeSet()); + + /** + * Create a new instance. + * + * @param filename - the original filename of the model that generated this instance; can be "" if + * unknown + * @param commandname - the original command that generated this instance; can be "" if unknown + * @param model - the AlloyModel that this AlloyInstance is an instance of + * @param atom2sets - maps each atom to the set(s) it is in; its KeySet is considered the universe + * of all atoms + * @param rel2tuples - maps each relation to the tuple(s) it is in + *

+ * (The constructor will ignore any atoms, sets, types, and relations not in the model. So + * there's no need to explicitly filter them out prior to passing "atom2sets" and + * "rel2tuples" to the constructor.) + */ + public AlloyInstance(A4Solution originalA4, String filename, String commandname, AlloyModel model, + Map> atom2sets, Map> rel2tuples, + boolean isMetamodel) { + this.originalA4 = originalA4; + this.filename = filename; + this.commandname = commandname; + this.model = model; + this.isMetamodel = isMetamodel; + // First, construct atom2sets (Use a treemap because we want its keyset to be sorted) + { + Map> a2s = new TreeMap>(); + for (Map.Entry> e : atom2sets.entrySet()) { + AlloyAtom atom = e.getKey(); + if (!model.hasType(atom.getType())) + continue; // We discard any AlloyAtom whose type is not in this model + // We discard any AlloySet not in this model; and we discard AlloySet(s) that don't match + // the atom's type + List sets = new ArrayList(); + for (AlloySet set : e.getValue()) + if (model.getSets().contains(set) + && model.isEqualOrSubtype(atom.getType(), set.getType())) + sets.add(set); + Collections.sort(sets); + a2s.put(atom, ConstList.make(sets)); + } + this.atom2sets = Collections.unmodifiableMap(a2s); + } + // Next, construct set2atoms + { + Map> s2a = new LinkedHashMap>(); + for (Map.Entry> e : this.atom2sets.entrySet()) + for (AlloySet set : e.getValue()) { + List atoms = s2a.get(set); + if (atoms == null) { + atoms = new ArrayList(); + s2a.put(set, atoms); + } + atoms.add(e.getKey()); + } + for (AlloySet set : model.getSets()) { + List atoms = s2a.get(set); + if (atoms == null) + continue; + Collections.sort(atoms); + s2a.put(set, Collections.unmodifiableList(atoms)); + } + this.set2atoms = Collections.unmodifiableMap(s2a); + } + // Next, construct type2atoms + { + Map> t2a = new LinkedHashMap>(); + for (AlloyAtom a : this.atom2sets.keySet()) { + for (AlloyType t = a.getType(); t != null; t = model.getSuperType(t)) { + List atoms = t2a.get(t); + if (atoms == null) { + atoms = new ArrayList(); + t2a.put(t, atoms); + } + atoms.add(a); + } + } + for (AlloyType t : model.getTypes()) { + List atoms = t2a.get(t); + if (atoms == null) + continue; + Collections.sort(atoms); + t2a.put(t, Collections.unmodifiableList(atoms)); + } + this.type2atoms = Collections.unmodifiableMap(t2a); + } + // Finally, construct rel2tuples + Map> r2t = new LinkedHashMap>(); + for (Map.Entry> e : rel2tuples.entrySet()) { + AlloyRelation rel = e.getKey(); + if (!model.getRelations().contains(rel)) + continue; // We discard any AlloyRelation not in this model + Set tuples = new TreeSet(); + for (AlloyTuple tuple : e.getValue()) { + if (tuple.getArity() != rel.getArity()) + continue; // The arity must match + for (int i = 0;; i++) { + if (i == tuple.getArity()) { + tuples.add(tuple); + break; + } + AlloyAtom a = tuple.getAtoms().get(i); + if (!this.atom2sets.containsKey(a)) + break; // Every atom must exist + if (!model.isEqualOrSubtype(a.getType(), rel.getTypes().get(i))) + break; // Atom must match the type + } + } + if (tuples.size() != 0) + r2t.put(rel, Collections.unmodifiableSet(tuples)); + } + this.rel2tuples = Collections.unmodifiableMap(r2t); + } + + /** Returns an unmodifiable sorted set of all AlloyAtoms in this AlloyInstance. */ + public Set getAllAtoms() { + return Collections.unmodifiableSet(atom2sets.keySet()); + } + + /** + * Returns an unmodifiable sorted list of AlloySet(s) that this atom is in; answer can be an empty + * list. + */ + public List atom2sets(AlloyAtom atom) { + List answer = atom2sets.get(atom); + return answer != null ? answer : noSet; + } + + /** + * Returns an unmodifiable sorted list of AlloyAtom(s) in this type; answer can be an empty list. + */ + public List type2atoms(AlloyType type) { + List answer = type2atoms.get(type); + return answer != null ? answer : noAtom; + } + + /** + * Returns an unmodifiable sorted list of AlloyAtom(s) in this set; answer can be an empty list. + */ + public List set2atoms(AlloySet set) { + List answer = set2atoms.get(set); + return answer != null ? answer : noAtom; + } + + /** + * Returns an unmodifiable sorted set of AlloyTuple(s) in this relation; answer can be an empty + * set. + */ + public Set relation2tuples(AlloyRelation rel) { + Set answer = rel2tuples.get(rel); + return answer != null ? answer : noTuple; + } + + /** + * Two instances are equal if they have the same filename, same commands, same model, and same + * atoms and tuples relationships. + */ + @Override + public boolean equals(Object other) { + if (!(other instanceof AlloyInstance)) + return false; + if (other == this) + return true; + AlloyInstance x = (AlloyInstance) other; + if (!filename.equals(x.filename)) + return false; + if (!commandname.equals(x.commandname)) + return false; + if (!model.equals(x.model)) + return false; + if (!atom2sets.equals(x.atom2sets)) + return false; + if (!type2atoms.equals(x.type2atoms)) + return false; + if (!set2atoms.equals(x.set2atoms)) + return false; + if (!rel2tuples.equals(x.rel2tuples)) + return false; + return true; + } + + /** Computes a hash code based on the same information used in equals(). */ + @Override + public int hashCode() { + int n = 5 * filename.hashCode() + 7 * commandname.hashCode(); + n = n + 7 * atom2sets.hashCode() + 31 * type2atoms.hashCode() + 71 * set2atoms.hashCode() + + 3 * rel2tuples.hashCode(); + return 17 * n + model.hashCode(); + } + + /** Returns a textual dump of the instance. */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Instance's model:\n"); + sb.append(model.toString()); + sb.append("Instance's atom2sets:\n"); + for (Map.Entry> entry : atom2sets.entrySet()) { + sb.append(" "); + sb.append(entry.getKey()); + sb.append(" "); + sb.append(entry.getValue()); + sb.append('\n'); + } + sb.append("Instance's rel2tuples:\n"); + for (Map.Entry> entry : rel2tuples.entrySet()) { + sb.append(" "); + sb.append(entry.getKey()); + sb.append(" "); + sb.append(entry.getValue()); + sb.append('\n'); + } + return sb.toString(); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyModel.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyModel.java new file mode 100644 index 00000000..5e56581d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyModel.java @@ -0,0 +1,241 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4viz; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.ConstList.TempList; + +/** Immutable; represents an Alloy model. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final class AlloyModel { + + /** An unmodifiable sorted set of all types in this model. */ + private final Set types; + + /** An unmodifiable sorted set of all sets in this model. + *
AlloyModel's constructor guarantees that, for each set here, set.getType() is in this.types + */ + private final Set sets; + + /** An unmodifiable sorted set of all relations in this model. + *
AlloyModel's constructor guarantees that, for each relation here, relation.getTypes() are in this.types + */ + private final Set relations; + + /** If A extends B, then "(A,B)" will be in this map. + * + *

AlloyModel's constructor ensures the following: + *
(1) hierachy.keySet() is always a subset of this.types + *
(2) hierachy.valueSet() is always a subset of this.types + *
(3) "univ" is never in the keySet + *
(4) null is never in the keySet nor valueSet + *
(5) there is no cycle in this relation + */ + private final Map hierarchy; + + /** The map from name to AlloyType. + *
AlloyModel's constructor guarantees that this.name2types.values() has the same entries as this.types + */ + private final Map name2types = new HashMap(); + + /** Returns true iff the nodes x, map.get(x), map.get(map.get(x))... form an infinite chain of nonnull objects. + * @param map - a map from AlloyType to AlloyType + * @param x - the AlloyType object we want to check + */ + public static boolean isCycle(Map map, AlloyType x) { + int i=(-5), n=map.size(); + while(x!=null) { x=map.get(x); i++; if (i>=n) return true; } + return false; + } + + /** Construct a new AlloyModel object. + * @param types - the types; we will always add "univ" to it if it's not there already + * @param sets - the sets + * @param rels - the relations + * @param map - we consult this "sig to parent sig" map and extract the mappings relevant to this model. + * (If we detect a cycle, we will arbitrarily break the cycle) + */ + public AlloyModel(Collection types + , Collection sets + , Collection rels + , Map map) { + // The following 3 have to be tree sets, since we want to keep them sorted + Set allTypes = new TreeSet(); + Set allSets = new TreeSet(); + Set allRelations = new TreeSet(); + allTypes.addAll(types); + allTypes.add(AlloyType.UNIV); + for(AlloySet s:sets) if (allTypes.contains(s.getType())) allSets.add(s); + for(AlloyRelation r:rels) if (allTypes.containsAll(r.getTypes())) allRelations.add(r); + this.types=Collections.unmodifiableSet(allTypes); + this.sets=Collections.unmodifiableSet(allSets); + this.relations=Collections.unmodifiableSet(allRelations); + Map newmap=new LinkedHashMap(); + for(AlloyType type:allTypes) { + AlloyType sup = isCycle(map,type) ? null : map.get(type); + if (sup==null || !allTypes.contains(sup)) sup=AlloyType.UNIV; + newmap.put(type,sup); + } + newmap.remove(AlloyType.UNIV); // This ensures univ is not in hierarchy's keySet + this.hierarchy=Collections.unmodifiableMap(newmap); + for(AlloyType t: this.types) this.name2types.put(t.getName(), t); + } + + /** Construct a new AlloyModel object. + * @param types - the types ; we will always add "univ" to it if it's not there already + * @param sets - the sets + * @param rels - the relations + * @param old - we consult this model's "sig to parent sig" map, and extract the mappings relevant to this model. + */ + public AlloyModel(Collection types, + Collection sets, + Collection rels, + AlloyModel old) { + this(types, sets, rels, old.hierarchy); + } + + /** If type==univ, return null; otherwise, return a nonnull AlloyType object representing its super type. + *
(In particular, if "type" does not exist in this model, we'll return "univ" as the answer). + */ + public AlloyType getSuperType(AlloyType type) { + if (type.getName().equals("univ")) return null; + AlloyType answer=hierarchy.get(type); + return answer==null ? AlloyType.UNIV : answer; + } + + /** If type==univ, return null; otherwise, + * return a nonnull AlloyType object representing its topmost non-univ super type. + * + *

Thus, if "type" is in this model, but its supertype is univ, then we'll return type as-is. + *

Note: if "type" does not exist in this model, we'll return it as-is. + */ + public AlloyType getTopmostSuperType(AlloyType type) { + if (type==null || type.equals(AlloyType.UNIV)) return null; + while (true) { + AlloyType top = getSuperType(type); + if (top==null || top.equals(AlloyType.UNIV)) break; + type=top; + } + return type; + } + + /** Returns a sorted, unmodifiable list of types that are direct or indirect subtypes of the given type. + *
This method will search recursively, so if the subtypes themselves have subtypes, they too are included. + *
If type==null, or it does not exist in this model, or it has no subsigs, then we return an empty set. + */ + public ConstList getSubTypes(AlloyType type) { + TempList subtypes = new TempList(); + for (AlloyType subType:types) if (isSubtype(subType,type)) subtypes.add(subType); + return subtypes.makeConst(); // Since this.types is sorted, the result is already sorted. + } + + /** Returns a sorted, unmodifiable list of types that are direct subtypes of the given type. + *
This method will only return types that are direct subtypes of the given argument. + *
If type==null, or it does not exist in this model, or it has no subsigs, then we return an empty set. + */ + public ConstList getDirectSubTypes(AlloyType type) { + TempList subtypes = new TempList(); + for (AlloyType subType: types) if (isDirectSubtype(subType,type)) subtypes.add(subType); + return subtypes.makeConst(); // Since this.types is sorted, the result is already sorted. + } + + /** Returns true iff "subType" is a direct or indirect subsig of "superType". + *
If subType==null or superType==null, it always returns false. + */ + public boolean isSubtype(AlloyType subType, AlloyType superType) { + if (subType==null || superType==null || !types.contains(subType) || subType.equals(AlloyType.UNIV)) + return false; + while(subType!=null) { + subType=getSuperType(subType); // Do this before calling equals(), since we want isSubtype(X,X)==false + if (superType.equals(subType)) return true; + } + return false; + } + + /** Returns true iff "subType" is a direct subsig of "superType". + *
If subType==null or superType==null, it always returns false. + */ + public boolean isDirectSubtype(AlloyType subType, AlloyType superType) { + if (subType==null || superType==null || !types.contains(subType) || subType.equals(AlloyType.UNIV)) + return false; + if (superType.equals(AlloyType.UNIV) && hierarchy.get(subType)==null) return true; + return superType.equals(hierarchy.get(subType)); + } + + /** Returns true iff "subType" is equal to, or is a direct or indirect subsig of "superType". + *
If subType==null or superType==null, it always returns false. + */ + public boolean isEqualOrSubtype(AlloyType subType, AlloyType superType) { + if (superType==null) return false; + while(subType!=null) { + if (superType.equals(subType)) return true; + subType=getSuperType(subType); + } + return false; + } + + /** Two AlloyModel objects are equal if they have the same types, sets, relations, and extension relationship. */ + @Override public boolean equals(Object other) { + if (!(other instanceof AlloyModel)) return false; + if (other==this) return true; + AlloyModel x=(AlloyModel)other; + return types.equals(x.types) && sets.equals(x.sets) + && relations.equals(x.relations) && hierarchy.equals(x.hierarchy); + } + + /** Compute a hashcode based on the types, sets, relations, and the extension relationship. */ + @Override public int hashCode() { + return types.hashCode()+3*sets.hashCode()+5*relations.hashCode()+7*hierarchy.hashCode(); + } + + /** Returns true if this model contains the given type. */ + public boolean hasType(AlloyType type) { return types.contains(type); } + + /** Returns the AlloyType object if this model contains the given type; or return null otherwise. */ + public AlloyType hasType(String name) { return name2types.get(name); } + + /** Returns the AlloyRelation object if this model contains the given relation; or return null otherwise. */ + public AlloySet hasSet(String name, AlloyType type) { + for(AlloySet s:sets) if (s.getName().equals(name) && s.getType().equals(type)) return s; + return null; + } + + /** Returns the AlloyRelation object if this model contains the given relation; or return null otherwise. */ + public AlloyRelation hasRelation(String name, List types) { + for(AlloyRelation r:relations) if (r.getName().equals(name) && r.getTypes().equals(types)) return r; + return null; + } + + /** Returns an unmodifiable sorted set of all AlloyType(s) in this model. */ + public Set getTypes() { return types; } + + /** Returns an unmodifiable sorted set of all AlloySet(s) in this model. */ + public Set getSets() { return sets; } + + /** Returns an unmodifiable sorted set of all AlloyRelation(s) in this model. */ + public Set getRelations() { return relations; } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyNodeElement.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyNodeElement.java new file mode 100644 index 00000000..f817815b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyNodeElement.java @@ -0,0 +1,27 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4viz; + +/** Immutable; it's the abstract superclass extended by both AlloyType and AlloySet. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public abstract class AlloyNodeElement extends AlloyElement { + + /** Constructs an AlloyNodeElement object with that name. */ + AlloyNodeElement(String name) { super(name); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyProjection.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyProjection.java new file mode 100644 index 00000000..4222a3e3 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyProjection.java @@ -0,0 +1,95 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4viz; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; + +/** Immutable; represents a set of types to be projected, plus the exact atom chosen for each type to be projected. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final class AlloyProjection { + + /** Its keySet is the set of types to be projected; each type is associated with the atom chosen to be projected. + * + *

Its keySet is guaranteed to be sorted. + * + *

For each type t in the keyset, map.get(t) is an AlloyAtom + * (indicating the atom in t that we chose to project over). + * + *

Note: there's no way for this class to confirm that a chosen atom is really + * in that type (since the atom may be in a subtype, and thus the atom.type() won't be exactly the same as t). + * Thus, classes that use AlloyProjection objects need to do their own sanity check. + */ + private final Map map; + + /** Constructs a new AlloyProjection object based on the set of types to be projected and the exact atoms chosen. + * @param map - this map describes the set of types to be projected and the exact atoms chosen to be projected + * + *

For each type t in map.keySet(), + *
map.get(t) is an AlloyAtom (indicating the atom in t that we chose to project over). + * + *

Note: there's no way for this class to confirm that a chosen atom is really + * in that type (since the atom may be in a subtype, and thus the atom.type() won't be exactly the same). + * Thus, classes that use AlloyProjection objects need to do their own sanity check. + */ + public AlloyProjection(Map map) { + Map mymap = new TreeMap(); + for(Map.Entry e:map.entrySet()) { + if (e.getKey()!=null && e.getValue()!=null) + mymap.put(e.getKey(), e.getValue()); + } + this.map=Collections.unmodifiableMap(mymap); + } + + /** Constructs an empty AlloyProjection object, with an empty projection list. */ + public AlloyProjection() { + this.map=Collections.unmodifiableMap(new TreeMap()); + } + + /** Return the sorted unmodifiable collection of types we are projecting. */ + public Collection getProjectedTypes() { return map.keySet(); } + + /** Return the atom chosen for that type; + * returns null if that type is not projected. + */ + public AlloyAtom getProjectedAtom(AlloyType type) { return map.get(type); } + + /** Returns a human readable dump of this object. */ + @Override public String toString() { + boolean first=true; + String ans="Projection["; + for(Map.Entry e:map.entrySet()) { + if (first) first=false; else ans=ans+", "; + ans=ans+e.getKey().getName()+":"+e.getValue().getVizName(null,true); + } + return ans+"]"; + } + + /** AlloyProjections are equal if they are projecting over the same types, each type with the same chosen value. */ + @Override public boolean equals(Object other) { + if (!(other instanceof AlloyProjection)) return false; + if (other==this) return true; + return map.equals(((AlloyProjection)other).map); + } + + /** Computes a hashcode based on the types and the atoms chosen for each type. */ + @Override public int hashCode() { return map.hashCode(); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyRelation.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyRelation.java new file mode 100644 index 00000000..05cc88bc --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyRelation.java @@ -0,0 +1,118 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4viz; + +import java.util.Collection; +import java.util.List; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.ConstList.TempList; + +/** Immutable; represents an Alloy relation of 2 or higher arity. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final class AlloyRelation extends AlloyElement { + + /** This caches an instance of the "extends" AlloyRelation, so we don't have to keep re-constructing it. */ + public static final AlloyRelation EXTENDS = new AlloyRelation("extends", false, false, Util.asList(AlloyType.UNIV, AlloyType.UNIV)); + + /** This caches an instance of the "in" AlloyRelation, so we don't have to keep re-constructing it. */ + public static final AlloyRelation IN = new AlloyRelation("in", false, false, Util.asList(AlloyType.SET, AlloyType.UNIV)); + + /** The unmodifiable list of types. */ + private final ConstList types; + + /** Records whether this relation is known to be "private"; NOTE: this value is NOT USED during equals() comparison. */ + public final boolean isPrivate; + + /** Records whether this relation is known to be "meta"; NOTE: this value is NOT USED during equals() comparison. */ + public final boolean isMeta; + + /** Constructs a new AlloyRelation with that name and that list of types; types.size() must be 2 or above. */ + public AlloyRelation(String name, boolean isPrivate, boolean isMeta, List types) { + super(name); + if (types==null || types.size()<2) + throw new RuntimeException("An AlloyRelation object must have 2 or more types."); + this.types = ConstList.make(types); + this.isPrivate = isPrivate; + this.isMeta = isMeta; + } + + /** Project this relation and return an unmodifiable list of remaining types (after removing zero or more columns) + * @param columns - the collection of columns to remove (0 is the first column, 1 is the second column...) + */ + public List project(Collection columns) { + TempList list = new TempList(types.size()); + for(int i=0; i getTypes() { return types; } + + /** Returns the arity of the relation. */ + public int getArity() { return types.size(); } + + /** When comparing two AlloyRelation objects, we first compare the name, then the arity, then the types. + *
We guarantee x.equals(y) iff x.compareTo(y)==0 + */ + public int compareTo(AlloyRelation other) { + if (other==null) return 1; + // First compare the names. + int n=Util.slashComparator.compare(getName(), other.getName()); if (n!=0) return n; + // Now compare the arity of the two relations + int arity = types.size(); + if (arity!=other.types.size()) return (arity We guarantee x.equals(y) iff x.compareTo(y)==0 + */ + public int compareTo(AlloyElement other) { + if (!(other instanceof AlloyRelation)) return 1; + return compareTo((AlloyRelation)other); + } + + /** This value is used to display this type in the Visualizer's customization screen. */ + @Override public String toString() { + String answer = ""; + boolean first = true; + for(AlloyType type: getTypes()) { + if (first) {first=false; answer=answer+getName()+" : ";} else answer=answer+" -> "; + answer=answer+type.getName(); + } + return answer; + } + + /** Two relations are equal if they have the same name, and the same list of types. */ + @Override public boolean equals(Object other) { + if (!(other instanceof AlloyRelation)) return false; + if (other==this) return true; + AlloyRelation otherRelation = (AlloyRelation)other; + return getName().equals(otherRelation.getName()) && types.equals(otherRelation.types); + } + + /** Computes a hash code based on the name and the list of types. */ + @Override public int hashCode() { return 5*getName().hashCode() + 7*types.hashCode(); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloySet.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloySet.java new file mode 100644 index 00000000..70df7ff6 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloySet.java @@ -0,0 +1,87 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4viz; + +import edu.mit.csail.sdg.alloy4.Util; + +/** Immutable; represents an Alloy set in an instance. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final class AlloySet extends AlloyNodeElement { + + /** The parent type of this AlloySet. */ + private final AlloyType type; + + /** Records whether this relation is known to be "private"; NOTE: this value is NOT USED during equals() comparison. */ + public final boolean isPrivate; + + /** Records whether this relation is known to be "meta"; NOTE: this value is NOT USED during equals() comparison. */ + public final boolean isMeta; + + /** Constructs a new AlloySet object. */ + public AlloySet(String name, boolean isPrivate, boolean isMeta, AlloyType type) { + super(name); this.type=type; this.isPrivate=isPrivate; this.isMeta=isMeta; + } + + /** Returns the parent type of the AlloySet. */ + public AlloyType getType() { return type; } + + /** When comparing two AlloySet objects, we first compare their names, then their types. + *
We guarantee x.equals(y) iff x.compareTo(y)==0 + */ + public int compareTo(AlloySet other) { + if (other==null) return 1; + int n=Util.slashComparator.compare(getName(), other.getName()); + return n!=0 ? n : type.compareTo(other.type); + } + + /** When comparing two AlloySet objects, we first compare their names, then their types. + *
We guarantee x.equals(y) iff x.compareTo(y)==0 + */ + public int compareTo(AlloyNodeElement other) { + if (!(other instanceof AlloySet)) return 1; + AlloySet x=(AlloySet)other; + int n=Util.slashComparator.compare(getName(), x.getName()); + return n!=0 ? n : type.compareTo(x.type); + } + + /** When comparing two AlloySet objects, we first compare their names, then their types. + *
We guarantee x.equals(y) iff x.compareTo(y)==0 + */ + public int compareTo(AlloyElement other) { + if (other instanceof AlloyRelation) return -1; + if (!(other instanceof AlloySet)) return 1; + AlloySet x = (AlloySet)other; + int n=Util.slashComparator.compare(getName(), x.getName()); + return n!=0 ? n : type.compareTo(x.type); + } + + /** This value is used to display this type in the Visualizer's customization screen. */ + @Override public String toString() { return getName()+" : "+getType().getName(); } + + /** Two sets are equal if they have the same name and the same type. */ + @Override public boolean equals(Object other) { + if (!(other instanceof AlloySet)) return false; + if (other==this) return true; + AlloySet otherSet = (AlloySet)other; + return getName().equals(otherSet.getName()) && type.equals(otherSet.type); + } + + /** Compute a hash code based on the name and the type. */ + @Override public int hashCode() { return 5*type.hashCode() + 7*getName().hashCode(); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyTuple.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyTuple.java new file mode 100644 index 00000000..94658f7e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/AlloyTuple.java @@ -0,0 +1,107 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4viz; + +import java.util.Collection; +import java.util.ArrayList; +import java.util.List; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.ConstList.TempList; + +/** Immutable; represents an Alloy tuple. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final class AlloyTuple implements Comparable { + public boolean isDashed = false; + /** The unmodifiable list of atoms in this tuple. */ + private final ConstList atoms; + + /** Creates a new AlloyTuple containing the atoms specified by the list; atoms.size() must be 2 or above. */ + public AlloyTuple(List atoms) { + if (atoms==null || atoms.size()<2) + throw new RuntimeException("An AlloyTuple object must have 2 or more atoms."); + this.atoms = ConstList.make(atoms); + } + + /** Creates a new AlloyTuple containing the atoms specified by the list; atoms.size() must be 2 or above. */ + public AlloyTuple(AlloyAtom... atoms) { + if (atoms==null || atoms.length<2) + throw new RuntimeException("An AlloyTuple object must have 2 or more atoms."); + this.atoms = Util.asList(atoms); + } + + /** Project this tuple and return an unmodifiable list of remaining atoms (after removing zero or more columns) + * @param columns - the collection of columns to remove (0 is the first column, 1 is the second column...) + */ + public ConstList project(Collection columns) { + TempList list = new TempList(atoms.size()); + for(int i=0; i getAtoms() { return atoms; } + + /** Returns the first AlloyAtom in this AlloyTuple. */ + public AlloyAtom getStart() { return atoms.get(0); } + + /** Returns the last AlloyAtom in this AlloyTuple. */ + public AlloyAtom getEnd() { return atoms.get(atoms.size()-1); } + + /** Returns a new AlloyTuple whose list of atoms is the same but in reverse. */ + public AlloyTuple reverse() { + List newlist = new ArrayList(atoms.size()); + for(int i=atoms.size()-1; i>=0; i--) newlist.add(atoms.get(i)); + return new AlloyTuple(newlist); + } + + /** Provides a human-readable description of this AlloyTuple. */ + @Override public String toString() { + String s="<"; + for(int i=0; i"; + } + + /** Two tuples are first compared based on length; if the length is the same, we compare atom-by-atom. + *
We guarantee x.equals(y) iff x.compareTo(y)==0 + */ + public int compareTo(AlloyTuple that) { + if (that==null) return 1; + if (atoms.size() < that.atoms.size()) return -1; + if (atoms.size() > that.atoms.size()) return 1; + for(int i=0; iThread Safety: Can be called only by the AWT event thread. + */ + +public final class AlloyType extends AlloyNodeElement { + + /** This caches an instance of the "univ" AlloyType, so we don't have to keep re-constructing it. */ + public static final AlloyType UNIV=new AlloyType("univ", false, false, true, false, false, false); + + /** This caches an instance of the "Int" AlloyType, so we don't have to keep re-constructing it. */ + public static final AlloyType INT=new AlloyType("Int", false, false, true, false, false, false); + + /** This caches an instance of the "seq/Int" AlloyType, so we don't have to keep re-constructing it. */ + public static final AlloyType SEQINT=new AlloyType("seq/Int", false, false, true, false, false, false); + + /** This caches an instance of the "String" AlloyType, so we don't have to keep re-constructing it. */ + public static final AlloyType STRING=new AlloyType("String", false, false, true, false, false, false); + + /** This caches an instance of the "set" AlloyType, so we don't have to keep re-constructing it. */ + public static final AlloyType SET=new AlloyType("set", false, false, false, false, false, false); + + /** Constructs an AlloyType object with that name. */ + public AlloyType(String name, boolean isOne, boolean isAbstract, boolean isBuiltin, boolean isPrivate, boolean isMeta, boolean isEnum) { + super(name); + this.isOne = isOne; + this.isAbstract = isAbstract; + this.isBuiltin = isBuiltin; + this.isPrivate = isPrivate; + this.isMeta = isMeta; + this.isEnum = isEnum; + } + + /** Records whether this sig is known to be "one"; NOTE: this value is NOT USED during equals() comparison. */ + public final boolean isOne; + + /** Records whether this sig is known to be "abstract"; NOTE: this value is NOT USED during equals() comparison. */ + public final boolean isAbstract; + + /** Records whether this sig is known to be "builtin"; NOTE: this value is NOT USED during equals() comparison. */ + public final boolean isBuiltin; + + /** Records whether this sig is known to be "private"; NOTE: this value is NOT USED during equals() comparison. */ + public final boolean isPrivate; + + /** Records whether this sig is known to be "meta"; NOTE: this value is NOT USED during equals() comparison. */ + public final boolean isMeta; + + /** Records whether this sig is known to be "enum"; NOTE: this value is NOT USED during equals() comparison. */ + public final boolean isEnum; + + /** When comparing two AlloyType objects, we compare their names. + *
We guarantee x.equals(y) iff x.compareTo(y)==0 + */ + public int compareTo(AlloyType other) { + if (other==null) return 1; + return Util.slashComparator.compare(getName(), other.getName()); + } + + /** When comparing two AlloyType objects, we compare their names. + *
We guarantee x.equals(y) iff x.compareTo(y)==0 + */ + public int compareTo(AlloyNodeElement other) { + if (other==null) return 1; + if (!(other instanceof AlloyType)) return -1; + return Util.slashComparator.compare(getName(), ((AlloyType)other).getName()); + } + + /** When comparing two AlloyType objects, we compare their names. + *
We guarantee x.equals(y) iff x.compareTo(y)==0 + */ + public int compareTo(AlloyElement other) { + if (other==null) return 1; + if (!(other instanceof AlloyType)) return -1; + return Util.slashComparator.compare(getName(), ((AlloyType)other).getName()); + } + + /** This value is used to display this type in the Visualizer's customization screen. */ + @Override public String toString() { return getName(); } + + /** Two types are equal if they have the same name. */ + @Override public boolean equals(Object other) { + if (!(other instanceof AlloyType)) return false; + if (other==this) return true; + return getName().equals(((AlloyType)other).getName()); + } + + /** Compute a hash code based on the name. */ + @Override public int hashCode() { return getName().hashCode(); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/MagicColor.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/MagicColor.java new file mode 100644 index 00000000..afb6cfd6 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/MagicColor.java @@ -0,0 +1,238 @@ +/* + * Alloy Analyzer 4 -- Copyright (c) 2007-2008, Derek Rayside + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4viz; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.ConstList.TempList; +import edu.mit.csail.sdg.alloy4graph.DotColor; +import edu.mit.csail.sdg.alloy4graph.DotPalette; +import edu.mit.csail.sdg.alloy4graph.DotShape; +import static edu.mit.csail.sdg.alloy4graph.DotShape.BOX; +import static edu.mit.csail.sdg.alloy4graph.DotShape.DIAMOND; +import static edu.mit.csail.sdg.alloy4graph.DotShape.TRAPEZOID; +import static edu.mit.csail.sdg.alloy4graph.DotShape.HOUSE; +import static edu.mit.csail.sdg.alloy4graph.DotShape.ELLIPSE; +import static edu.mit.csail.sdg.alloy4graph.DotShape.EGG; +import static edu.mit.csail.sdg.alloy4graph.DotShape.HEXAGON; +import static edu.mit.csail.sdg.alloy4graph.DotShape.OCTAGON; +import static edu.mit.csail.sdg.alloy4graph.DotShape.INV_HOUSE; +import static edu.mit.csail.sdg.alloy4graph.DotShape.INV_TRAPEZOID; +import static edu.mit.csail.sdg.alloy4graph.DotShape.INV_TRIANGLE; +import static edu.mit.csail.sdg.alloy4graph.DotShape.DOUBLE_OCTAGON; +import static edu.mit.csail.sdg.alloy4graph.DotShape.TRIPLE_OCTAGON; +import static edu.mit.csail.sdg.alloy4graph.DotShape.M_CIRCLE; +import static edu.mit.csail.sdg.alloy4graph.DotShape.M_DIAMOND; +import static edu.mit.csail.sdg.alloy4graph.DotShape.M_SQUARE; +import static edu.mit.csail.sdg.alloy4graph.DotShape.PARALLELOGRAM; +import edu.mit.csail.sdg.alloy4graph.DotStyle; + +/** + * This class implements the automatic visualization inference. + * + *

+ * Thread Safety: Can be called only by the AWT event thread. + */ + +public final class MagicColor { + + /** The VizState object that we're going to configure. */ + private final VizState vizState; + + /** Constructor. */ + private MagicColor(final VizState vizState) { + this.vizState = vizState; + } + + /** Main method to infer settings. */ + public static void magic(final VizState vizState) { + vizState.setNodePalette(DotPalette.MARTHA); + final MagicColor st = new MagicColor(vizState); + st.nodeNames(); + st.nodeShape(); + st.nodeColour(); + st.skolemColour(); + } + + + /** + * SYNTACTIC/VISUAL: Determine colours for nodes. + * + * when do we color things and what is the meaning of color + *

    + *
  • symmetry breaking: colors only matter up to recoloring (diff from shape!) + *
  • color substitutes for name/label + *
+ */ + private void nodeColour() { + final Set visibleUserTypes = MagicUtil.visibleUserTypes(vizState); + final Set uniqueColourTypes; + if (visibleUserTypes.size() <= 5) { + // can give every visible user type its own shape + uniqueColourTypes = visibleUserTypes; + } else { + // give every top-level visible user type its own shape + uniqueColourTypes = MagicUtil.partiallyVisibleUserTopLevelTypes(vizState); + } + int index = 0; + for (final AlloyType t : uniqueColourTypes) { + vizState.nodeColor.put(t, (DotColor) DotColor.valuesWithout(DotColor.MAGIC)[index]); + index = (index + 1) % DotColor.valuesWithout(DotColor.MAGIC).length; + } + } + + /** SYNTACTIC/VISUAL: Determine colour highlighting for skolem constants. */ + private void skolemColour() { + final Set sets = vizState.getCurrentModel().getSets(); + for (final AlloySet s : sets) { + // change the style + vizState.nodeStyle.put(s, DotStyle.BOLD); + // change the label + String label = vizState.label.get(s); + final int lastUnderscore = label.lastIndexOf('_'); + if (lastUnderscore >= 0) { + label = label.substring(lastUnderscore + 1); + } + vizState.label.put(s, label); + } + } + + /** The list of shape families. */ + private static final List> families; + + static { + TempList> list = new TempList>(); + list.add(Util.asList(BOX, TRAPEZOID, HOUSE)); + list.add(Util.asList(ELLIPSE, EGG)); + list.add(Util.asList(HEXAGON, OCTAGON, DOUBLE_OCTAGON, TRIPLE_OCTAGON)); + list.add(Util.asList(INV_TRIANGLE, INV_HOUSE, INV_TRAPEZOID)); + list.add(Util.asList(M_DIAMOND, M_SQUARE, M_CIRCLE)); + list.add(Util.asList(PARALLELOGRAM, DIAMOND)); + families = list.makeConst(); + } + + + /** + * SYNTACTIC/VISUAL: Determine shapes for nodes. + *
    + *
  • trapezoid, hexagon, rectangle, ellipse, circle, square -- no others + *
  • actual shape matters -- do not break symmetry as with color + *
  • ellipse by default + *
  • circle if special extension of ellipse + *
  • rectangle if lots of attributes + *
  • square if special extension of rectangle + *
  • when to use other shapes? + * + *
+ */ + private void nodeShape() { + final Set> usedShapeFamilies = new LinkedHashSet>(); + final Set topLevelTypes = MagicUtil.partiallyVisibleUserTopLevelTypes(vizState); + + for (final AlloyType t : topLevelTypes) { + + // get the type family + final Set subTypes = MagicUtil.visibleSubTypes(vizState, t); + final boolean isTvisible = MagicUtil.isActuallyVisible(vizState, t); + final int size = subTypes.size() + (isTvisible ? 1 : 0); + // log("TopLevelType: " + t + " -- " + subTypes + " " + size); + + // match it to a shape family + // 1. look for exact match + boolean foundExactMatch = false; + for (final List shapeFamily : families) { + if (size == shapeFamily.size() && !usedShapeFamilies.contains(shapeFamily)) { + // found a match! + usedShapeFamilies.add(shapeFamily); + assignNodeShape(t, subTypes, isTvisible, shapeFamily); + foundExactMatch = true; + break; + } + } + if (foundExactMatch) + continue; + // 2. look for approximate match + List approxShapeFamily = null; + int approxShapeFamilyDistance = Integer.MAX_VALUE; + for (final List shapeFamily : families) { + if (size <= shapeFamily.size() && !usedShapeFamilies.contains(shapeFamily)) { + // found a potential match + final int distance = shapeFamily.size() - size; + if (distance < approxShapeFamilyDistance) { + // it's a closer fit than the last match, keep it for now + approxShapeFamily = shapeFamily; + approxShapeFamilyDistance = distance; + } + } + } + if (approxShapeFamily != null) { + // use the best approximate match that we just found + usedShapeFamilies.add(approxShapeFamily); + assignNodeShape(t, subTypes, isTvisible, approxShapeFamily); + } + // 3. re-use a shape family matched to something else -- just give up for now + } + } + + + /** Helper for nodeShape(). */ + private void assignNodeShape(final AlloyType t, final Set subTypes, + final boolean isTvisible, final List shapeFamily) { + int index = 0; + // shape for t, if visible + if (isTvisible) { + final DotShape shape = shapeFamily.get(index++); + // log("AssignNodeShape " + t + " " + shape); + vizState.shape.put(t, shape); + } + // shapes for visible subtypes + for (final AlloyType subt : subTypes) { + final DotShape shape = shapeFamily.get(index++); + // log("AssignNodeShape " + subt + " " + shape); + vizState.shape.put(subt, shape); + } + } + + /** + * SYNTACTIC/VISUAL: Should the names of nodes be displayed on them? + * + * when should names be used? + *
    + *
  • not when only a single sig (e.g. state machine with only one 'node' sig) + *
  • not when only a single relation + *
  • check for single things _after_ hiding things by default + *
+ */ + private void nodeNames() { + final Set visibleUserTypes = MagicUtil.visibleUserTypes(vizState); + // trim names + for (final AlloyType t : visibleUserTypes) { + // trim label before last slash + MagicUtil.trimLabelBeforeLastSlash(vizState, t); + } + // hide names if there's only one node type visible + if (1 == visibleUserTypes.size()) { + vizState.label.put(visibleUserTypes.iterator().next(), ""); + } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/MagicLayout.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/MagicLayout.java new file mode 100644 index 00000000..5815636a --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/MagicLayout.java @@ -0,0 +1,302 @@ +/* + * Alloy Analyzer 4 -- Copyright (c) 2007-2008, Derek Rayside + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4viz; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4graph.DotColor; + +/** + * This class implements the automatic visualization inference. + * + *

+ * Thread Safety: Can be called only by the AWT event thread. + */ + +public final class MagicLayout { + + /** The VizState object that we're going to configure. */ + private final VizState vizState; + + private Set enumerationTypes = new LinkedHashSet(); + private Set singletonTypes = new LinkedHashSet(); + private AlloyType projectionType = null; + private Set spineRelations = Collections.emptySet(); + + /** Constructor. */ + private MagicLayout(final VizState vizState) { + this.vizState = vizState; + } + + /** Main method to infer settings. */ + public static void magic(final VizState vizState) { + vizState.resetTheme(); + final MagicLayout st = new MagicLayout(vizState); + st.identifyEnumerationTypes(); + st.projection(); + st.nodeVisibility(); + st.spine(); + st.attributes(); + st.edgeLabels(); + } + + /** + * SYNTACTIC: An enumeration follows the pattern "abstract sig Colour; one sig Red; one sig Blue". + */ + private void identifyEnumerationTypes() { + final AlloyModel model = vizState.getCurrentModel(); + final Set types = model.getTypes(); + for (final AlloyType t : types) { + if (enumerationTypes.contains(t)) + continue; // we've already checked this one, don't muck with it now + if (t.isOne) + singletonTypes.add(t); + if (!t.isBuiltin && t.isAbstract) { + List subTypes = model.getSubTypes(t); + int numberOfSingletonSubtypes = 0; + for (AlloyType st : subTypes) { + if (st.isOne) { + numberOfSingletonSubtypes++; + singletonTypes.add(st); + } + } + if (subTypes.size() == numberOfSingletonSubtypes) { // we have a winner! + enumerationTypes.add(t); + enumerationTypes.addAll(subTypes); + for (final AlloyType st : subTypes) { + // all of the subtypes in the enumeration should have visibility inherited + // so that the user only needs to make the abstract supertype visible if we made a + // mistake hiding these things + vizState.nodeVisible.put(st, null); + } + // hide unless these are the source of some relation + boolean visible = false; + for (AlloyRelation r : model.getRelations()) { + AlloyType sourceType = r.getTypes().get(0); + if (t.equals(sourceType) || subTypes.contains(sourceType)) { + visible = true; + break; + } + } + vizState.nodeVisible.put(t, visible); // log("VizInference: visible status of enumeration + // type " + t + " " + visible); + } + } + } + + } + + /** + * SEMANTIC/LAYOUT: Determine at most one relation to project over. + * + * When do we project over a sig? Do we ever project over more than one? + *

    + *
  • pick 0 or 1 things to project over + *
  • match names: Time, State, Tick, TimeStep + *
  • if ord is opened over the sig + *
  • if present in several ternary relations (i.e. if it will help viz high arity relations) + *
  • position in relation (always end or always beginning) + *
  • should we try to catch projections such as the one over birthday books? + *
  • pattern match (b,b') to catch transition relations + *
  • add combo box in GUI (?) + *
+ */ + private void projection() { + // only fiddle with this if it hasn't already been set somewhere else + if (projectionType == null && vizState.getProjectedTypes().isEmpty()) { + AlloyModel model = vizState.getCurrentModel(); + // final Set candidateTypes = new HashSet(); + Map scores = new LinkedHashMap(); + for (AlloyType t : model.getTypes()) { + scores.put(t, 0); + // does it have a name like State, Time, etc + if (hasLikelyProjectionTypeName(t.getName())) { + scores.put(t, scores.get(t) + 1); + } + // is it in some ternary relation? + for (AlloyRelation r : model.getRelations()) { + if (r.getArity() > 2 && r.getTypes().contains(t)) + scores.put(t, scores.get(t) + 1); + } + } + // now we have the scores, see who the winners are: + int max = 0; + final Set winners = new LinkedHashSet(); + for (final Map.Entry e : scores.entrySet()) { + if (e.getValue() == max) + winners.add(e.getKey()); + if (e.getValue() > max) { + max = e.getValue(); + winners.clear(); + winners.add(e.getKey()); + } + } + if (max < 2) { + // no winner, don't project + // log("VizInference: no candidate type to project on."); + } else { + if (winners.size() > 1) { + // we have a tie ... what to do? + // log("VizInference: projection tie. " + winners); + } + final AlloyType winner = winners.iterator().next(); + // pick one arbitrarily for now ... + // log("VizInference: projecting on " + max + " " + winner); + projectionType = winner; + vizState.project(projectionType); + } + + } + } + + private final static ConstList LIKELY_PROJECTION_TYPE_NAMES = + Util.asList("State", "TrainState", "Time", "Tick", "TimeStep"); + + private final boolean hasLikelyProjectionTypeName(final String n) { + for (String s : LIKELY_PROJECTION_TYPE_NAMES) + if (n.startsWith(s) || n.endsWith(s)) + return true; + return false; + } + + /** + * SEMANTIC/LAYOUT: Determine some relations to be the spine (ie, influence the layout). + * + * Which relations should be used to layout? all? none? clever? + *
    + *
  • interesting example: 2d game grid + *
  • ex: toplogical sort -- layout tree and list, not cnxn between them + *
  • look for homogenius binary relation (a -> a) + *
  • may be several relations defining the spine + *
+ * + */ + private void spine() { + AlloyModel model = vizState.getCurrentModel(); + Set relations = model.getRelations(); + if (!relations.isEmpty()) { + // only mess with the relations if there are some + // only binary relations are candidates + Set spines = new LinkedHashSet(); + for (AlloyRelation r : relations) { + if (r.getArity() == 2) { + List rtypes = r.getTypes(); + AlloyType targetType = rtypes.get(1); + // only a spine if the target is not an enumeration type + if (!enumerationTypes.contains(targetType)) { + spines.add(r); + } + // however, binary relations named parent should be layed out backwards + if (r.getName().equals("parent")) { + vizState.layoutBack.put(r, true); + } + } + } + // do we have any spines? if so, use them, if not use all relations + spineRelations = spines.isEmpty() ? relations : spines; + } + // set everything to not influence layout + for (AlloyRelation r : relations) { + vizState.constraint.put(r, false); + vizState.edgeColor.put(r, DotColor.GRAY); + } + // set spines to influence layout + for (AlloyRelation s : spineRelations) { + vizState.constraint.put(s, null); + // inherit the default color, which should be black + vizState.edgeColor.put(s, null); + } + + } + + /** + * SEMANTIC/LAYOUT: Determine whether non-projection, non-spine relations should be shown as + * attributes or edges. + * + *
    + *
  • binary vs. higher arity -- only make binary attributes + *
  • use attributes on-demand to reduce clutter, not blindly + *
  • functional relations should be attributes (what about a tree?) + *
  • never make something an edge and an attribute + * + *
+ * + */ + private void attributes() { + AlloyModel model = vizState.getCurrentModel(); + for (AlloyRelation r : model.getRelations()) { + List rTypes = r.getTypes(); + if (r.getArity() == 2 && !rTypes.contains(projectionType) && !spineRelations.contains(r)) { + // it's binary, non-projection and non-spine + AlloyType targetType = rTypes.get(1); + if (enumerationTypes.contains(targetType)) { + // target is an enumeration: we have an attribute + vizState.attribute.put(r, true); + vizState.edgeVisible.put(r, false); + } + } + } + } + + + /** PRESENTATIONAL: Labels for edges. */ + private void edgeLabels() { + AlloyModel model = vizState.getCurrentModel(); + int relationsAsEdges = 0; + AlloyRelation visibleRelation = null; + for (AlloyRelation r : model.getRelations()) { + Boolean v = vizState.edgeVisible.get(r); + if (v == null || v.booleanValue()) { + // it's visible + relationsAsEdges++; + visibleRelation = r; + // remove text before last slash + MagicUtil.trimLabelBeforeLastSlash(vizState, r); + } + } + // If there's only one relation visible as an edge, and it's binary, then no need to label it. + if (1 == relationsAsEdges && visibleRelation.getArity() == 2) { + vizState.label.put(visibleRelation, ""); + } + } + + + /** SYNTACTIC/VISUAL: Hide some things. */ + private void nodeVisibility() { + AlloyModel model = vizState.getCurrentModel(); + Set types = model.getTypes(); + for (AlloyType t : types) + if (!t.isBuiltin && MagicUtil.isActuallyVisible(vizState, t) + && t.getName().endsWith("/Ord")) { + vizState.nodeVisible.put(t, false); + } + for (AlloySet s : model.getSets()) + if (MagicUtil.isActuallyVisible(vizState, s) && s.getName().endsWith("/Ord")) { + vizState.nodeVisible.put(s, false); + } + + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/MagicUtil.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/MagicUtil.java new file mode 100644 index 00000000..61f13bcd --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/MagicUtil.java @@ -0,0 +1,148 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2007-2008, Derek Rayside + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4viz; + +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +/** This class implements the automatic visualization inference. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +final class MagicUtil { + + /** Constructor. + */ + private MagicUtil() {} + + static void trimLabelBeforeLastSlash(final VizState vizState, final AlloyElement x) { + vizState.label.put(x, trimBeforeLastSlash(vizState.label.get(x))); + } + + static String trimBeforeLastSlash(final String label) { + final int lastSlash = label.lastIndexOf('/'); + if (lastSlash >= 0) { + return label.substring(lastSlash+1); + } else { + return label; + } + } + + + /** Determines whether a type is actually visible -- ie, if it has an inherited value, + * looks up the hierarchy until that is resolved. NB: abstract types are not actually visible. + * @param t + * @return true if this type will be shown to the user, false if this type will be hidden from the user + */ + static boolean isActuallyVisible(final VizState vizState, final AlloyType t) { + if (t.isAbstract) return false; + final Boolean V = vizState.nodeVisible.get(t); + if (V != null) return V; + + // inherited value, find out the real deal + final AlloyModel model = vizState.getCurrentModel(); + AlloyType parent = model.getSuperType(t); + while (parent != null) { + final Boolean pV = vizState.nodeVisible.get(parent); + if (pV != null) break; // found a real setting + parent = model.getSuperType(parent); + } + if (parent == null) { + // made it to univ without finding a real setting + return true; + } else { + // found a concrete setting, use it + return vizState.nodeVisible.get(parent); + } + } + + static boolean isActuallyVisible(final VizState vizState, final AlloySet s) { + final Boolean V = vizState.nodeVisible.get(s); + if (V != null) return V; + + return isActuallyVisible(vizState, s.getType()); + } + + /** Returns all of the visible user-types in the current model. + * @param vizState + */ + static Set visibleUserTypes(final VizState vizState) { + final Set result = new LinkedHashSet(); + final AlloyModel model = vizState.getCurrentModel(); + for (final AlloyType t : model.getTypes()) { + if (!t.isBuiltin && MagicUtil.isActuallyVisible(vizState, t)) { + result.add(t); + } + } + return Collections.unmodifiableSet(result); + } + + /** Returns all of the top-level types in the original model. + * @param vizState + */ + static Set topLevelTypes(final VizState vizState) { + final Set result = new LinkedHashSet(); + final AlloyModel model = vizState.getOriginalModel(); + for (final AlloyType t : model.getTypes()) { + if (vizState.isTopLevel(t)) { + result.add(t); + } + } + return Collections.unmodifiableSet(result); + } + + /** Returns every top-level user type that is itself visible or has a visible subtype. + * @param vizState + */ + static Set partiallyVisibleUserTopLevelTypes(final VizState vizState) { + final AlloyModel model = vizState.getOriginalModel(); + final Set visibleUserTypes = visibleUserTypes(vizState); + //final Set topLevelTypes = topLevelTypes(vizState); + + final Set result = new LinkedHashSet(); + + for (final AlloyType t : visibleUserTypes) { + if (visibleUserTypes.contains(t)) { + result.add(model.getTopmostSuperType(t)); + } + } + + return Collections.unmodifiableSet(result); + } + + /** Returns the set of visible subtypes for the given type. + * @param vizState + * @param type + */ + static Set visibleSubTypes(final VizState vizState, final AlloyType type) { + final AlloyModel model = vizState.getCurrentModel(); + final List subTypes = model.getSubTypes(type); + final Set visibleUserTypes = visibleUserTypes(vizState); + final Set result = new LinkedHashSet(); + + for (final AlloyType st : subTypes) { + if (visibleUserTypes.contains(st)) { + result.add(st); + } + } + + return Collections.unmodifiableSet(result); + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/StaticGraphMaker.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/StaticGraphMaker.java new file mode 100644 index 00000000..02ff4395 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/StaticGraphMaker.java @@ -0,0 +1,361 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4viz; + +import java.awt.Color; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import javax.swing.JPanel; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4graph.DotColor; +import edu.mit.csail.sdg.alloy4graph.DotDirection; +import edu.mit.csail.sdg.alloy4graph.DotPalette; +import edu.mit.csail.sdg.alloy4graph.DotShape; +import edu.mit.csail.sdg.alloy4graph.DotStyle; +import edu.mit.csail.sdg.alloy4graph.GraphEdge; +import edu.mit.csail.sdg.alloy4graph.Graph; +import edu.mit.csail.sdg.alloy4graph.GraphNode; +import edu.mit.csail.sdg.alloy4graph.GraphViewer; + +/** This utility class generates a graph for a particular index of the projection. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final class StaticGraphMaker { + + /** The theme customization. */ + private final VizState view; + + /** The projected instance for the graph currently being generated. */ + private final AlloyInstance instance; + + /** The projected model for the graph currently being generated. */ + private final AlloyModel model; + + /** The map that contains all edges and what the AlloyTuple that each edge corresponds to. */ + private final Map edges = new LinkedHashMap(); + + /** The map that contains all nodes and what the AlloyAtom that each node corresponds to. */ + private final Map nodes = new LinkedHashMap(); + + /** This maps each atom to the node representing it; if an atom doesn't have a node, it won't be in the map. */ + private final Map atom2node = new LinkedHashMap(); + + /** This stores a set of additional labels we want to add to an existing node. */ + private final Map> attribs = new LinkedHashMap>(); + + /** The resulting graph. */ + private final Graph graph; + + /** Produces a single Graph from the given Instance and View and choice of Projection */ + public static JPanel produceGraph(AlloyInstance instance, VizState view, AlloyProjection proj) throws ErrorFatal { + view = new VizState(view); + if (proj == null) proj = new AlloyProjection(); + Graph graph = new Graph(view.getFontSize() / 12.0D); + new StaticGraphMaker(graph, instance, view, proj); + if (graph.nodes.size()==0) new GraphNode(graph, "", "Due to your theme settings, every atom is hidden.", "Please click Theme and adjust your settings."); + return new GraphViewer(graph); + } + + /** The list of colors, in order, to assign each legend. */ + private static final List colorsClassic = Util.asList( + new Color(228,26,28) + ,new Color(166,86,40) + ,new Color(255,127,0) + ,new Color(77,175,74) + ,new Color(55,126,184) + ,new Color(152,78,163) + ); + + /** The list of colors, in order, to assign each legend. */ + private static final List colorsStandard = Util.asList( + new Color(227,26,28) + ,new Color(255,127,0) + ,new Color(251*8/10,154*8/10,153*8/10) + ,new Color(51,160,44) + ,new Color(31,120,180) + ); + + /** The list of colors, in order, to assign each legend. */ + private static final List colorsMartha = Util.asList( + new Color(231,138,195) + ,new Color(252,141,98) + ,new Color(166,216,84) + ,new Color(102,194,165) + ,new Color(141,160,203) + ); + + /** The list of colors, in order, to assign each legend. */ + private static final List colorsNeon = Util.asList( + new Color(231,41,138) + ,new Color(217,95,2) + ,new Color(166,118,29) + ,new Color(102,166,30) + ,new Color(27,158,119) + ,new Color(117,112,179) + ); + + /** The constructor takes an Instance and a View, then insert the generate graph(s) into a blank cartoon. */ + private StaticGraphMaker (Graph graph, AlloyInstance originalInstance, VizState view, AlloyProjection proj) throws ErrorFatal { + final boolean hidePrivate = view.hidePrivate(); + final boolean hideMeta = view.hideMeta(); + final Map magicColor = new TreeMap(); + final Map rels = new TreeMap(); + this.graph = graph; + this.view = view; + instance = StaticProjector.project(originalInstance, proj); + model = instance.model; + for (AlloyRelation rel: model.getRelations()) { + rels.put(rel, null); + } + List colors; + if (view.getEdgePalette() == DotPalette.CLASSIC) colors = colorsClassic; + else if (view.getEdgePalette() == DotPalette.STANDARD) colors = colorsStandard; + else if (view.getEdgePalette() == DotPalette.MARTHA) colors = colorsMartha; + else colors = colorsNeon; + int ci = 0; + for (AlloyRelation rel: model.getRelations()) { + DotColor c = view.edgeColor.resolve(rel); + Color cc = (c==DotColor.MAGIC) ? colors.get(ci) : c.getColor(view.getEdgePalette()); + int count = ((hidePrivate && rel.isPrivate) || !view.edgeVisible.resolve(rel)) ? 0 : edgesAsArcs(hidePrivate, hideMeta, rel, colors.get(ci)); + rels.put(rel, count); + magicColor.put(rel, cc); + if (count>0) ci = (ci+1)%(colors.size()); + } + for (AlloyAtom atom: instance.getAllAtoms()) { + List sets = instance.atom2sets(atom); + if (sets.size()>0) { + for (AlloySet s: sets) + if (view.nodeVisible.resolve(s) && !view.hideUnconnected.resolve(s)) + {createNode(hidePrivate, hideMeta, atom); break;} + } else if (view.nodeVisible.resolve(atom.getType()) && !view.hideUnconnected.resolve(atom.getType())) { + createNode(hidePrivate, hideMeta, atom); + } + } + for (AlloyRelation rel: model.getRelations()) + if (!(hidePrivate && rel.isPrivate)) + if (view.attribute.resolve(rel)) + edgesAsAttribute(rel); + for(Map.Entry> e: attribs.entrySet()) { + Set set = e.getValue(); + if (set!=null) for(String s: set) if (s.length() > 0) e.getKey().addLabel(s); + } + for(Map.Entry e: rels.entrySet()) { + Color c = magicColor.get(e.getKey()); + if (c==null) c = Color.BLACK; + int n = e.getValue(); + if (n>0) graph.addLegend(e.getKey(), e.getKey().getName()+": "+n, c); else graph.addLegend(e.getKey(), e.getKey().getName(), null); + } + } + + /** Return the node for a specific AlloyAtom (create it if it doesn't exist yet). + * @return null if the atom is explicitly marked as "Don't Show". + */ + private GraphNode createNode(final boolean hidePrivate, final boolean hideMeta, final AlloyAtom atom) { + GraphNode node = atom2node.get(atom); + if (node!=null) return node; + if ( (hidePrivate && atom.getType().isPrivate) + || (hideMeta && atom.getType().isMeta) + || !view.nodeVisible(atom, instance)) return null; + // Make the node + DotColor color = view.nodeColor(atom, instance); + DotStyle style = view.nodeStyle(atom, instance); + if (atom.isDashed) { + style = DotStyle.DASHED; + } + DotShape shape = view.shape(atom, instance); + String label = atomname(atom, false); + node = new GraphNode(graph, atom, label).set(shape).set(color.getColor(view.getNodePalette())).set(style); + // Get the label based on the sets and relations + String setsLabel=""; + boolean showLabelByDefault = view.showAsLabel.get(null); + for (AlloySet set: instance.atom2sets(atom)) { + String x = view.label.get(set); if (x.length()==0) continue; + Boolean showLabel = view.showAsLabel.get(set); + if ((showLabel==null && showLabelByDefault) || (showLabel!=null && showLabel.booleanValue())) + setsLabel += ((setsLabel.length()>0?", ":"")+x); + } + if (setsLabel.length()>0) { + Set list = attribs.get(node); + if (list==null) attribs.put(node, list=new TreeSet()); + list.add("("+setsLabel+")"); + } + nodes.put(node,atom); + atom2node.put(atom,node); + return node; + } + + /** Create an edge for a given tuple from a relation (if neither start nor end node is explicitly invisible) */ + private boolean createEdge(final boolean hidePrivate, final boolean hideMeta, AlloyRelation rel, AlloyTuple tuple, boolean bidirectional, Color magicColor) { + // This edge represents a given tuple from a given relation. + // + // If the tuple's arity==2, then the label is simply the label of the relation. + // + // If the tuple's arity>2, then we append the node labels for all the intermediate nodes. + // eg. Say a given tuple is (A,B,C,D) from the relation R. + // An edge will be drawn from A to D, with the label "R [B, C]" + if ((hidePrivate && tuple.getStart().getType().isPrivate) + ||(hideMeta && tuple.getStart().getType().isMeta) + || !view.nodeVisible(tuple.getStart(), instance)) return false; + if ((hidePrivate && tuple.getEnd().getType().isPrivate) + ||(hideMeta && tuple.getEnd().getType().isMeta) + || !view.nodeVisible(tuple.getEnd(), instance)) return false; + GraphNode start = createNode(hidePrivate, hideMeta, tuple.getStart()); + GraphNode end = createNode(hidePrivate, hideMeta, tuple.getEnd()); + if (start==null || end==null) return false; + boolean layoutBack = view.layoutBack.resolve(rel); + String label = view.label.get(rel); + if (tuple.getArity() > 2) { + StringBuilder moreLabel = new StringBuilder(); + List atoms=tuple.getAtoms(); + for (int i=1; i1) moreLabel.append(", "); + moreLabel.append(atomname(atoms.get(i),false)); + } + if (label.length()==0) { /* label=moreLabel.toString(); */ } + else { label=label+(" ["+moreLabel+"]"); } + } + DotDirection dir = bidirectional ? DotDirection.BOTH : (layoutBack ? DotDirection.BACK : DotDirection.FORWARD); + DotStyle style = view.edgeStyle.resolve(rel); + if (tuple.isDashed) { + style = DotStyle.DASHED; + } + DotColor color = view.edgeColor.resolve(rel); + int weight = view.weight.get(rel); + GraphEdge e = new GraphEdge((layoutBack ? end : start), (layoutBack ? start : end), tuple, label, rel); + if (color == DotColor.MAGIC && magicColor != null) e.set(magicColor); else e.set(color.getColor(view.getEdgePalette())); + e.set(style); + e.set(dir!=DotDirection.FORWARD, dir!=DotDirection.BACK); + e.set(weight<1 ? 1 : (weight>100 ? 10000 : 100*weight)); + edges.put(e, tuple); + return true; + } + + /** Create edges for every visible tuple in the given relation. */ + private int edgesAsArcs(final boolean hidePrivate, final boolean hideMeta, AlloyRelation rel, Color magicColor) { + int count = 0; + if (!view.mergeArrows.resolve(rel)) { + // If we're not merging bidirectional arrows, simply create an edge for each tuple. + for (AlloyTuple tuple: instance.relation2tuples(rel)) if (createEdge(hidePrivate, hideMeta, rel, tuple, false, magicColor)) count++; + return count; + } + // Otherwise, find bidirectional arrows and only create one edge for each pair. + Set tuples = instance.relation2tuples(rel); + Set ignore = new LinkedHashSet(); + for (AlloyTuple tuple: tuples) { + if (!ignore.contains(tuple)) { + AlloyTuple reverse = tuple.getArity()>2 ? null : tuple.reverse(); + // If the reverse tuple is in the same relation, and it is not a self-edge, then draw it as a <-> arrow. + if (reverse!=null && tuples.contains(reverse) && !reverse.equals(tuple)) { + ignore.add(reverse); + if (createEdge(hidePrivate, hideMeta, rel, tuple, true, magicColor)) count = count + 2; + } else { + if (createEdge(hidePrivate, hideMeta, rel, tuple, false, magicColor)) count = count + 1; + } + } + } + return count; + } + + /** Attach tuple values as attributes to existing nodes. */ + private void edgesAsAttribute(AlloyRelation rel) { + // If this relation wants to be shown as an attribute, + // then generate the annotations and attach them to each tuple's starting node. + // Eg. + // If (A,B) and (A,C) are both in the relation F, + // then the A node would have a line that says "F: B, C" + // Eg. + // If (A,B,C) and (A,D,E) are both in the relation F, + // then the A node would have a line that says "F: B->C, D->E" + // Eg. + // If (A,B,C) and (A,D,E) are both in the relation F, and B belongs to sets SET1 and SET2, + // and SET1's "show in relational attribute" is on, + // and SET2's "show in relational attribute" is on, + // then the A node would have a line that says "F: B (SET1, SET2)->C, D->E" + // + Map map = new LinkedHashMap(); + for (AlloyTuple tuple: instance.relation2tuples(rel)) { + GraphNode start=atom2node.get(tuple.getStart()); + if (start==null) continue; // null means the node won't be shown, so we can't show any attributes + String attr=""; + List atoms=tuple.getAtoms(); + for (int i=1; i1) attr+="->"; + attr+=atomname(atoms.get(i),true); + } + if (attr.length()==0) continue; + String oldattr=map.get(start); + if (oldattr!=null && oldattr.length()>0) attr=oldattr+", "+attr; + if (attr.length()>0) map.put(start,attr); + } + for (Map.Entry e: map.entrySet()) { + GraphNode node = e.getKey(); + Set list = attribs.get(node); + if (list==null) attribs.put(node, list=new TreeSet()); + String attr = e.getValue(); + if (view.label.get(rel).length()>0) attr = view.label.get(rel) + ": " + attr; + list.add(attr); + } + } + + /** Return the label for an atom. + * @param atom - the atom + * @param showSets - whether the label should also show the sets that this atom belongs to + * + *

eg. If atom A is the 3rd atom in type T, and T's label is "Person", + * then the return value would be "Person3". + * + *

eg. If atom A is the only atom in type T, and T's label is "Person", + * then the return value would be "Person". + * + *

eg. If atom A is the 3rd atom in type T, and T's label is "Person", + * and T belongs to the sets Set1, Set2, and Set3. + * However, only Set1 and Set2 have "show in relational attribute == on", + * then the return value would be "Person (Set1, Set2)". + */ + private String atomname(AlloyAtom atom, boolean showSets) { + String label = atom.getVizName(view, view.number.resolve(atom.getType())); + if (!showSets) return label; + String attr = ""; + boolean showInAttrByDefault = view.showAsAttr.get(null); + for (AlloySet set: instance.atom2sets(atom)) { + String x = view.label.get(set); if (x.length()==0) continue; + Boolean showAsAttr = view.showAsAttr.get(set); + if ((showAsAttr==null && showInAttrByDefault) || (showAsAttr!=null && showAsAttr)) + attr += ((attr.length()>0?", ":"")+x); + } + if (label.length()==0) return (attr.length()>0) ? ("("+attr+")") : ""; + return (attr.length()>0) ? (label+" ("+attr+")") : label; + } + + static String esc(String name) { + if (name.indexOf('\"') < 0) return name; + StringBuilder out = new StringBuilder(); + for(int i=0; iThread Safety: Can be called only by the AWT event thread. + */ + +public final class StaticInstanceReader { + + /** The resulting AlloyInstance object. */ + private final AlloyInstance ans; + + /** This is the list of toplevel sigs. */ + private final List toplevels = new ArrayList(); + + /** This maps each Sig to its corresponding Visualizer AlloyType. */ + private final LinkedHashMap sig2type = new LinkedHashMap(); + + /** This maps each Sig ot its corresponding unique VIsualizer AlloyAtom (if isMeta is true). */ + private final LinkedHashMap sig2atom = new LinkedHashMap(); + + /** This stores the "extends" relationship among sigs (if isMeta is true). */ + private final LinkedHashSet exts = new LinkedHashSet(); + + /** This stores the "in" relationship among sigs (if isMeta is true). */ + private final LinkedHashSet ins = new LinkedHashSet(); + + /** This stores the set of Visualizer AlloySet objects we created. */ + private final Set sets = new LinkedHashSet(); + + /** This maps each Visualizer AlloyRelation to its set of (possibly 0) tuples. */ + private final Map> rels = new LinkedHashMap>(); + + /** For each sig A and B, if A extends B, and B is not univ, then (A,B) will be in this map. */ + private final Map ts = new LinkedHashMap(); + + /** This maps each Visualizer AlloyAtom to its set of (possibly 0) AlloySet that contains it. */ + private final Map> atom2sets = new LinkedHashMap>(); + + /** This maps each AlloyAtom label to the AlloyAtom we created for it. */ + private final Map string2atom = new LinkedHashMap(); + + /** Create a new AlloyType whose label is unambiguous with any existing one. */ + private AlloyType makeType(String label, boolean isOne, boolean isAbstract, boolean isBuiltin, boolean isPrivate, boolean isMeta, boolean isEnum) { + if (label.startsWith("this/")) label = label.substring(5); + while(true) { + AlloyType ans = new AlloyType(label, isOne, isAbstract, isBuiltin, isPrivate, isMeta, isEnum); + if (!sig2type.values().contains(ans)) return ans; + label=label+"'"; + } + } + + /** Create a new AlloySet whose label is unambiguous with any existing one. */ + private AlloySet makeSet(String label, boolean isPrivate, boolean isMeta, AlloyType type) { + while(label.equals(Sig.UNIV.label) || label.equals(Sig.SIGINT.label) || label.equals(Sig.SEQIDX.label) || label.equals(Sig.STRING.label)) label=label+"'"; + while(true) { + AlloySet ans = new AlloySet(label, isPrivate, isMeta, type); + if (!sets.contains(ans)) return ans; + label=label+"'"; + } + } + + /** Create a new AlloyRelation whose label is unambiguous with any existing one. */ + private AlloyRelation makeRel(String label, boolean isPrivate, boolean isMeta, List types) { + while(label.equals(Sig.UNIV.label) || label.equals(Sig.SIGINT.label) || label.equals(Sig.SEQIDX.label) || label.equals(Sig.STRING.label)) label=label+"'"; + while(true) { + AlloyRelation ans = new AlloyRelation(label, isPrivate, isMeta, types); + if (!rels.containsKey(ans)) return ans; + label=label+"'"; + } + } + + /** Returns the AlloyType corresponding to the given sig; create an AlloyType for it if none existed before. */ + private AlloyType sig(PrimSig s) throws Err { + if (s==Sig.NONE) throw new ErrorFatal("Unexpected sig \"none\" encountered."); + AlloyType ans = sig2type.get(s); + if (ans == null) { + ans = makeType(s.label, s.isOne!=null, s.isAbstract!=null, false, s.isPrivate!=null, s.isMeta!=null, s.isEnum!=null); + sig2type.put(s, ans); + if (s.parent!=Sig.UNIV) ts.put(ans, sig(s.parent)); + } + return ans; + } + + /** Returns the AlloyType corresponding to the given sig; create an AlloyType for it if none existed before. */ + private AlloyType sigMETA(PrimSig s) throws Err { + if (s==Sig.NONE) throw new ErrorFatal("Unexpected sig \"none\" encountered."); + AlloyType type = sig2type.get(s); + if (type != null) return type; + if (s==Sig.UNIV) type=AlloyType.UNIV; + else if (s==Sig.SIGINT) type=AlloyType.INT; + else if (s==Sig.SEQIDX) type=AlloyType.SEQINT; + else if (s==Sig.STRING) type=AlloyType.STRING; + else type = makeType(s.label, s.isOne!=null, s.isAbstract!=null, false, s.isPrivate!=null, s.isMeta!=null, s.isEnum!=null); + sig2type.put(s, type); + AlloyAtom atom = new AlloyAtom(type, (type==AlloyType.SEQINT ? Integer.MIN_VALUE : Integer.MAX_VALUE), s.label); + atom2sets.put(atom, new LinkedHashSet()); + sig2atom.put(s, atom); + if (s.parent!=Sig.UNIV && s.parent!=null) + ts.put(type, sigMETA(s.parent)); + if (s.parent!=null) + exts.add(new AlloyTuple(atom, sig2atom.get(s.parent))); + Iterable children = (s==Sig.UNIV ? toplevels : s.children()); + for(PrimSig sub:children) sigMETA(sub); + return type; + } + + /** Returns the AlloyType corresponding to the given sig; create an AlloyType for it if none existed before. */ + private void sigMETA(SubsetSig s) throws Err { + AlloyAtom atom; + AlloyType type = sig2type.get(s); + if (type != null) return; + type = makeType(s.label, s.isOne!=null, s.isAbstract!=null, false, s.isPrivate!=null, s.isMeta!=null, s.isEnum!=null); + atom = new AlloyAtom(type, Integer.MAX_VALUE, s.label); + atom2sets.put(atom, new LinkedHashSet()); + sig2atom.put(s, atom); + sig2type.put(s, type); + ts.put(type, AlloyType.SET); + for(Sig p: ((SubsetSig)s).parents) { + if (p instanceof SubsetSig) sigMETA((SubsetSig)p); else sigMETA((PrimSig)p); + ins.add(new AlloyTuple(atom, sig2atom.get(p))); + } + } + + /** Constructs the atoms corresponding to the given sig. */ + private void atoms(A4Solution sol, PrimSig s) throws Err { + Expr sum=Sig.NONE; + for(PrimSig c:s.children()) { sum=sum.plus(c); atoms(sol, c); } + A4TupleSet ts = (A4TupleSet) (sol.eval(s.minus(sum))); // This ensures that atoms will be associated with the most specific sig + for(A4Tuple z: ts) { + String atom = z.atom(0); + int i, dollar = atom.lastIndexOf('$'); + try { i = Integer.parseInt(dollar>=0 ? atom.substring(dollar+1) : atom); } catch(NumberFormatException ex) { i = Integer.MAX_VALUE; } + AlloyAtom at = new AlloyAtom(sig(s), ts.size()==1 ? Integer.MAX_VALUE : i, atom); + atom2sets.put(at, new LinkedHashSet()); + string2atom.put(atom, at); + } + } + + /** Construct an AlloySet or AlloyRelation corresponding to the given expression. */ + private void setOrRel(A4Solution sol, String label, Expr expr, boolean isPrivate, boolean isMeta) throws Err { + for(List ps:expr.type().fold()) { + if (ps.size()==1) { + PrimSig t = ps.get(0); + AlloySet set = makeSet(label, isPrivate, isMeta, sig(t)); + sets.add(set); + for(A4Tuple tp: (A4TupleSet)(sol.eval(expr.intersect(t)))) { + atom2sets.get(string2atom.get(tp.atom(0))).add(set); + } + } else { + Expr mask = null; + List types = new ArrayList(ps.size()); + for(int i=0; i ts = new LinkedHashSet(); + for(A4Tuple tp: (A4TupleSet)(sol.eval(expr.intersect(mask)))) { + AlloyAtom[] atoms = new AlloyAtom[tp.arity()]; + for(int i=0; i element."); + boolean isMeta = "yes".equals(inst.getAttribute("metamodel")); + A4Solution sol = A4SolutionReader.read(new ArrayList(), root); + for (Sig s:sol.getAllReachableSigs()) if (s instanceof PrimSig && ((PrimSig)s).parent==Sig.UNIV) toplevels.add((PrimSig)s); + if (!isMeta) { + sig2type.put(Sig.UNIV, AlloyType.UNIV); + sig2type.put(Sig.SIGINT, AlloyType.INT); + sig2type.put(Sig.SEQIDX, AlloyType.SEQINT); + sig2type.put(Sig.STRING, AlloyType.STRING); + ts.put(AlloyType.SEQINT, AlloyType.INT); + for(int i=sol.min(), max=sol.max(), maxseq=sol.getMaxSeq(); i<=max; i++) { + AlloyAtom at = new AlloyAtom(i>=0 && i()); + string2atom.put(""+i, at); + } + for(Sig s:sol.getAllReachableSigs()) if (!s.builtin && s instanceof PrimSig) sig((PrimSig)s); + for(Sig s:toplevels) if (!s.builtin || s==Sig.STRING) atoms(sol, (PrimSig)s); + for(Sig s:sol.getAllReachableSigs()) if (s instanceof SubsetSig) setOrRel(sol, s.label, s, s.isPrivate!=null, s.isMeta!=null); + for(Sig s:sol.getAllReachableSigs()) for(Field f:s.getFields()) setOrRel(sol, f.label, f, f.isPrivate!=null, f.isMeta!=null); + for(ExprVar s:sol.getAllSkolems()) setOrRel(sol, s.label, s, false, false); + } + if (isMeta) { + sigMETA(Sig.UNIV); + for(Sig s:sol.getAllReachableSigs()) if (s instanceof SubsetSig) sigMETA((SubsetSig)s); + for(Sig s:sol.getAllReachableSigs()) for(Field f:s.getFields()) { + for(List ps:f.type().fold()) { + List types = new ArrayList(ps.size()); + AlloyAtom[] tuple = new AlloyAtom[ps.size()]; + for(int i=0; i0) { sig2type.put(null, AlloyType.SET); rels.put(AlloyRelation.IN, ins); } + AlloyAtom univAtom = sig2atom.get(Sig.UNIV); + AlloyAtom intAtom = sig2atom.get(Sig.SIGINT); + AlloyAtom seqAtom = sig2atom.get(Sig.SEQIDX); + AlloyAtom strAtom = sig2atom.get(Sig.STRING); + for(Set t: rels.values()) for(AlloyTuple at: t) if (at.getAtoms().contains(univAtom)) { univAtom=null; break; } + for(Set t: rels.values()) for(AlloyTuple at: t) if (at.getAtoms().contains(intAtom)) { intAtom=null; break; } + for(Set t: rels.values()) for(AlloyTuple at: t) if (at.getAtoms().contains(seqAtom)) { seqAtom=null; break; } + for(Set t: rels.values()) for(AlloyTuple at: t) if (at.getAtoms().contains(strAtom)) { strAtom=null; break; } + if (univAtom!=null) { + for(Iterator it=exts.iterator(); it.hasNext();) { + AlloyTuple at=it.next(); + if (at.getStart()==univAtom || at.getEnd()==univAtom) it.remove(); + } + atom2sets.remove(univAtom); + } + if (strAtom!=null) { + for(Iterator it=exts.iterator(); it.hasNext();) { + AlloyTuple at=it.next(); + if (at.getStart()==strAtom || at.getEnd()==strAtom) it.remove(); + } + atom2sets.remove(strAtom); + } + if (intAtom!=null && seqAtom!=null) { + for(Iterator it=exts.iterator(); it.hasNext();) { + AlloyTuple at=it.next(); + if (at.getStart()==intAtom || at.getEnd()==intAtom || at.getStart()==seqAtom || at.getEnd()==seqAtom) it.remove(); + } + atom2sets.remove(intAtom); + atom2sets.remove(seqAtom); + } + if (exts.size()>0) { rels.put(AlloyRelation.EXTENDS, exts); } + } + AlloyModel am = new AlloyModel(sig2type.values(), sets, rels.keySet(), ts); + ans=new AlloyInstance(sol, sol.getOriginalFilename(), sol.getOriginalCommand(), am, atom2sets, rels, isMeta); + } + + /** Parse the file into an AlloyInstance if possible. */ + public static AlloyInstance parseInstance(File file) throws Err { + try { + return (new StaticInstanceReader(new XMLNode(file))).ans; + } catch(IOException ex) { + throw new ErrorFatal("Error reading the XML file: " + ex, ex); + } + } + + /** Parse the file into an AlloyInstance if possible, then close the Reader afterwards. */ + public static AlloyInstance parseInstance(Reader reader) throws Err { + try { + return (new StaticInstanceReader(new XMLNode(reader))).ans; + } catch(IOException ex) { + throw new ErrorFatal("Error reading the XML file: " + ex, ex); + } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/StaticProjector.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/StaticProjector.java new file mode 100644 index 00000000..de320816 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/StaticProjector.java @@ -0,0 +1,190 @@ +/* + * Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4viz; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * This utility class performs projection of AlloyModel and AlloyInstance. + * + *

+ * Thread Safety: Can be called only by the AWT event thread. + */ + +public final class StaticProjector { + + /** Constructor is private, since this utility class never needs to be instantiated. */ + private StaticProjector() {} + + /** + * Given an unprojected model, project it over the given collection of AlloyType(s). + * + * @param unprojectedModel - the original unprojected model + * @param typesToBeProjected - the collection of types to project over + */ + public static AlloyModel project(AlloyModel unprojectedModel, + Collection typesToBeProjected) { + return project(unprojectedModel, typesToBeProjected, null); + } + + /** + * Given an unprojected model, project it over the given collection of AlloyType(s). + * + * @param unprojectedModel - the original unprojected model + * @param typesToBeProjected - the collection of types to project over + * @param data - if nonnull, this method will record into this map how the relations are changed + * by the projection + *

+ * For every relation R that gets altered to become a new AlloySet or a new AlloyRelation, + * data.get(R) will give us a list of integers indicating the columns deleted from R due to + * the projection. (For example, if an original relation A->B->C->D becomes B->D, then the + * list of integers will be (0,2) indicating the first and third columns were removed). + *

+ * If a relation R remains unchanged during the projection, then data.get(R) will return an + * empty list. + *

+ * If a relation R is totally deleted, due to the projection, then R won't be in + * data.keySet(). + */ + private static AlloyModel project(AlloyModel unprojectedModel, + Collection typesToBeProjected, Map> data) { + Set types = new LinkedHashSet(unprojectedModel.getTypes()); + List sets = new ArrayList(unprojectedModel.getSets()); + List relations = new ArrayList(); + // Get rid of all projected types, as well as their subtypes. + for (AlloyType type : typesToBeProjected) { + types.remove(type); + types.removeAll(unprojectedModel.getSubTypes(type)); + } + types.add(AlloyType.UNIV); // "univ" has to be a type + // Now go over the relations... + for (AlloyRelation rel : unprojectedModel.getRelations()) { + List relTypes = new ArrayList(rel.getTypes()); + List indices = new ArrayList(); + int currentIndex = 0; + // For each type in a relation, if it is a removed type, remove it and keep track of its + // index. + for (Iterator relTypesIter = relTypes.iterator(); relTypesIter.hasNext();) { + if (!types.contains(relTypesIter.next())) { + relTypesIter.remove(); + indices.add(currentIndex); + } + currentIndex++; + } + // If the relation still contains at least two types, it becomes a new relation + if (relTypes.size() > 1) { + relations.add(new AlloyRelation(rel.getName(), rel.isPrivate, rel.isMeta, relTypes)); + if (data != null) + data.put(rel, indices); + } + // If it contains only one type, it becomes a new set. + else if (relTypes.size() == 1) { + sets.add(new AlloySet(rel.getName(), rel.isPrivate, rel.isMeta, relTypes.get(0))); + if (data != null) + data.put(rel, indices); + } + } + // Finally, go through the sets and remove any whose type was removed. + for (Iterator setsIter = sets.iterator(); setsIter.hasNext();) { + AlloySet set = setsIter.next(); + if (!types.contains(set.getType())) + setsIter.remove(); + } + return new AlloyModel(types, sets, relations, unprojectedModel); + } + + /** + * Project an instance over the given list of types (and their associated chosen atom). + * + * @param oldInstance - the original unprojected instance + * @param projection - the list of types to be projected and their associated chosen atoms + * + *

+ * For each type t in projection.getProjectedTypes: + * + *

+ * (1) If t doesn't exist in the instance, then we will simply ignore t. + * + *

+ * (2) Otherwise, if t has one or more atoms in the original instance,
+ * then projection.getProjectedAtom(t) must be one of the atoms (indicating the chosen atom + * for that type)
+ * else projection.getProjectedAtom(t) must be null.
+ * If rule (2) is violated, then some tuples may not show up in the return value. + */ + public static AlloyInstance project(AlloyInstance oldInstance, AlloyProjection projection) { + Map> data = new LinkedHashMap>(); + Map> atom2sets = new LinkedHashMap>(); + Map> rel2tuples = + new LinkedHashMap>(); + AlloyModel newModel = project(oldInstance.model, projection.getProjectedTypes(), data); + // First put all the atoms from the old instance into the new one + for (AlloyAtom atom : oldInstance.getAllAtoms()) { + atom2sets.put(atom, new LinkedHashSet(oldInstance.atom2sets(atom))); + } + // Now, decide what tuples to generate + for (AlloyRelation r : oldInstance.model.getRelations()) { + List list = data.get(r); + if (list == null) + continue; // This means that relation was deleted entirely + tupleLabel: for (AlloyTuple oldTuple : oldInstance.relation2tuples(r)) { + for (Integer i : list) { + // If an atom in the original tuple should be projected, but it doesn't match the + // chosen atom for that type, then this tuple must not be included in the new instance + AlloyAtom a = oldTuple.getAtoms().get(i); + AlloyType bt = r.getTypes().get(i); + bt = oldInstance.model.getTopmostSuperType(bt); + if (!a.equals(projection.getProjectedAtom(bt))) + continue tupleLabel; + } + List newTuple = oldTuple.project(list); + List newObj = r.project(list); + if (newObj.size() > 1 && newTuple.size() > 1) { + AlloyRelation r2 = new AlloyRelation(r.getName(), r.isPrivate, r.isMeta, newObj); + Set answer = rel2tuples.get(r2); + if (answer == null) + rel2tuples.put(r2, answer = new LinkedHashSet()); + AlloyTuple newT = new AlloyTuple(newTuple); + newT.isDashed = oldTuple.isDashed; + answer.add(newT); + } else if (newObj.size() == 1 && newTuple.size() == 1) { + AlloyAtom a = newTuple.get(0); + Set answer = atom2sets.get(a); + if (answer == null) + atom2sets.put(a, answer = new LinkedHashSet()); + answer.add(new AlloySet(r.getName(), r.isPrivate, r.isMeta, newObj.get(0))); + } + } + } + // Here, we don't have to explicitly filter out "illegal" atoms/tuples/... + // (that is, atoms that belong to types that no longer exist, etc). + // That's because AlloyInstance's constructor must do the check too, so there's no point in + // doing that twice. + return new AlloyInstance(oldInstance.originalA4, oldInstance.filename, oldInstance.commandname, + newModel, atom2sets, rel2tuples, oldInstance.isMetamodel); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/StaticThemeReaderWriter.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/StaticThemeReaderWriter.java new file mode 100644 index 00000000..151c257d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/StaticThemeReaderWriter.java @@ -0,0 +1,465 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4viz; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.XMLNode; +import edu.mit.csail.sdg.alloy4graph.DotColor; +import edu.mit.csail.sdg.alloy4graph.DotPalette; +import edu.mit.csail.sdg.alloy4graph.DotShape; +import edu.mit.csail.sdg.alloy4graph.DotStyle; + +/** This utility class contains methods to read and write VizState customizations. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final class StaticThemeReaderWriter { + + /** Constructor is private, since this utility class never needs to be instantiated. */ + private StaticThemeReaderWriter() { } + + /** Read the XML file and merge its settings into an existing VizState object. */ + public static void readAlloy(String filename, VizState theme) throws IOException { + File file = new File(filename); + try { + XMLNode elem = new XMLNode(file); + for(XMLNode sub: elem.getChildren("view")) parseView(sub,theme); + } catch(Throwable e) { + throw new IOException("The file \""+file.getPath()+"\" is not a valid XML file, or an error occurred in reading."); + } + } + + /** Write the VizState's customizations into a new file (which will be overwritten if it exists). */ + public static void writeAlloy(String filename, VizState theme) throws IOException { + PrintWriter bw = new PrintWriter(filename,"UTF-8"); + bw.write("\n\n\n"); + if (theme!=null) { + try { + writeView(bw, theme); + } catch(IOException ex) { + Util.close(bw); + throw new IOException("Error writing to the file \""+filename+"\""); + } + } + bw.write("\n\n"); + if (!Util.close(bw)) throw new IOException("Error writing to the file \""+filename+"\""); + } + + /*============================================================================================*/ + + /** Does nothing if the element is malformed. */ + private static void parseView(final XMLNode x, VizState now) { + /* + * + * .. + * + * + * 0 or more NODE or EDGE + * + */ + if (!x.is("view")) return; + for(XMLNode xml:x) { + if (xml.is("projection")) { + now.deprojectAll(); + for(AlloyType t:parseProjectionList(now,xml)) now.project(t); + } + } + if (has(x,"useOriginalAtomNames")) now.useOriginalName(getbool(x,"useOriginalAtomNames")); + if (has(x,"hidePrivate")) now.hidePrivate(getbool(x,"hidePrivate")); + if (has(x,"hideMeta")) now.hideMeta(getbool(x,"hideMeta")); + if (has(x,"fontsize")) now.setFontSize(getint(x,"fontsize")); + if (has(x,"nodetheme")) now.setNodePalette(parseDotPalette(x,"nodetheme")); + if (has(x,"edgetheme")) now.setEdgePalette(parseDotPalette(x,"edgetheme")); + for(XMLNode xml:x) { + if (xml.is("defaultnode")) parseNodeViz(xml, now, null); + else if (xml.is("defaultedge")) parseEdgeViz(xml, now, null); + else if (xml.is("node")) { + for(XMLNode sub:xml.getChildren("type")) { + AlloyType t=parseAlloyType(now,sub); if (t!=null) parseNodeViz(xml, now, t); + } + for(XMLNode sub:xml.getChildren("set")) { + AlloySet s=parseAlloySet(now,sub); if (s!=null) parseNodeViz(xml, now, s); + } + } + else if (xml.is("edge")) { + for(XMLNode sub:xml.getChildren("relation")) { + AlloyRelation r=parseAlloyRelation(now,sub); if (r!=null) parseEdgeViz(xml, now, r); + } + } + } + } + + /*============================================================================================*/ + + /** Writes nothing if the argument is null. */ + private static void writeView(PrintWriter out, VizState view) throws IOException { + if (view==null) return; + VizState defaultView=new VizState(view.getOriginalInstance()); + out.write("\n"); + if (view.getProjectedTypes().size()>0) writeProjectionList(out, view.getProjectedTypes()); + out.write("\n\n\n\n"); + // === nodes === + Set types = new TreeSet(); + types.addAll(view.getOriginalModel().getTypes()); + types.addAll(view.getCurrentModel().getTypes()); + types.addAll(view.getOriginalModel().getSets()); + types.addAll(view.getCurrentModel().getSets()); + Map> viz2node=new TreeMap>(); + for(AlloyNodeElement t:types) { + String str=writeNodeViz(view,defaultView,t); + Set nodes=viz2node.get(str); + if (nodes==null) viz2node.put(str, nodes=new TreeSet()); + nodes.add(t); + } + for(Map.Entry> e:viz2node.entrySet()) { + out.write("\n\n"); + for(AlloyNodeElement ts:e.getValue()) { + if (ts instanceof AlloyType) writeAlloyType(out,(AlloyType)ts); + else if (ts instanceof AlloySet) writeAlloySet(out,(AlloySet)ts); + } + out.write("\n"); + } + // === edges === + Set rels = new TreeSet(); + rels.addAll(view.getOriginalModel().getRelations()); + rels.addAll(view.getCurrentModel().getRelations()); + Map> viz2edge=new TreeMap>(); + for(AlloyRelation r:rels) { + String str=writeEdgeViz(view,defaultView,r); + if (str.length()==0) continue; + Set edges=viz2edge.get(str); + if (edges==null) viz2edge.put(str, edges=new TreeSet()); + edges.add(r); + } + for(Map.Entry> e:viz2edge.entrySet()) { + out.write("\n\n"); + for(AlloyRelation r:e.getValue()) writeAlloyRelation(out,r); + out.write("\n"); + } + // === done === + out.write("\n\n"); + } + + /*============================================================================================*/ + + /** Return null if the element is malformed. */ + private static AlloyType parseAlloyType(VizState now, XMLNode x) { + /* class AlloyType implements AlloyNodeElement { + * String name; + * } + * + */ + if (!x.is("type")) return null; + String name=x.getAttribute("name"); + if (name.length()==0) return null; else return now.getCurrentModel().hasType(name); + } + + /** Writes nothing if the argument is null. */ + private static void writeAlloyType(PrintWriter out, AlloyType x) throws IOException { + if (x!=null) Util.encodeXMLs(out, " \n"); + } + + /*============================================================================================*/ + + /** Return null if the element is malformed. */ + private static AlloySet parseAlloySet(VizState now, XMLNode x) { + /* class AlloySet implements AlloyNodeElement { + * String name; + * AlloyType type; + * } + * + */ + if (!x.is("set")) return null; + String name=x.getAttribute("name"), type=x.getAttribute("type"); + if (name.length()==0 || type.length()==0) return null; + AlloyType t=now.getCurrentModel().hasType(type); + if (t==null) return null; else return now.getCurrentModel().hasSet(name, t); + } + + /** Writes nothing if the argument is null. */ + private static void writeAlloySet(PrintWriter out, AlloySet x) throws IOException { + if (x!=null) Util.encodeXMLs(out," \n"); + } + + /*============================================================================================*/ + + /** Return null if the element is malformed. */ + private static AlloyRelation parseAlloyRelation(VizState now, XMLNode x) { + /* + * + * 2 or more + * + */ + List ans=new ArrayList(); + if (!x.is("relation")) return null; + String name=x.getAttribute("name"); + if (name.length()==0) return null; + for(XMLNode sub:x.getChildren("type")) { + String typename=sub.getAttribute("name"); + if (typename.length()==0) return null; + AlloyType t = now.getCurrentModel().hasType(typename); + if (t==null) return null; + ans.add(t); + } + if (ans.size()<2) return null; else return now.getCurrentModel().hasRelation(name, ans); + } + + /** Writes nothing if the argument is null. */ + private static void writeAlloyRelation(PrintWriter out, AlloyRelation x) throws IOException { + if (x==null) return; + Util.encodeXMLs(out, " "); + for(AlloyType t:x.getTypes()) Util.encodeXMLs(out, " "); + out.write(" \n"); + } + + /*============================================================================================*/ + + /** Always returns a nonnull (though possibly empty) set of AlloyType. */ + private static Set parseProjectionList(VizState now, XMLNode x) { + /* + * + * 0 or more + * + */ + Set ans=new TreeSet(); + if (x.is("projection")) for(XMLNode sub:x.getChildren("type")) { + String name=sub.getAttribute("name"); + if (name.length()==0) continue; + AlloyType t = now.getOriginalModel().hasType(name); + if (t!=null) ans.add(t); + } + return ans; + } + + /** Writes an empty Projection tag if the argument is null or empty */ + private static void writeProjectionList(PrintWriter out, Set types) throws IOException { + if (types==null || types.size()==0) { out.write("\n\n"); return; } + out.write("\n"); + for(AlloyType t:types) Util.encodeXMLs(out, " "); + out.write(" \n"); + } + + /*============================================================================================*/ + + /** Do nothing if the element is malformed; note: x can be null. */ + private static void parseNodeViz(XMLNode xml, VizState view, AlloyNodeElement x) { + /* + * + * zero or more SET or TYPE + * + * + * Each attribute, if omitted, means "no change". + * Note: BOOLEAN is tristate. + */ + if (has(xml,"visible")) view.nodeVisible.put (x, getbool(xml, "visible")); + if (has(xml,"hideunconnected")) view.hideUnconnected.put (x, getbool(xml, "hideunconnected")); + if (x==null || x instanceof AlloySet) { + AlloySet s=(AlloySet)x; + if (has(xml,"showlabel")) view.showAsLabel.put (s, getbool(xml, "showlabel")); + if (has(xml,"showinattr")) view.showAsAttr.put (s, getbool(xml, "showinattr")); + } + if (x==null || x instanceof AlloyType) { + AlloyType t=(AlloyType)x; + if (has(xml,"numberatoms")) view.number.put (t, getbool(xml, "numberatoms")); + } + if (has(xml,"style")) view.nodeStyle.put(x, parseDotStyle(xml)); + if (has(xml,"color")) view.nodeColor.put(x, parseDotColor(xml)); + if (has(xml,"shape")) view.shape .put(x, parseDotShape(xml)); + if (has(xml,"label")) view.label .put(x, xml.getAttribute("label")); + } + + /** Returns the String representation of an AlloyNodeElement's settings. */ + private static String writeNodeViz(VizState view, VizState defaultView, AlloyNodeElement x) throws IOException { + StringWriter sw=new StringWriter(); + PrintWriter out=new PrintWriter(sw); + writeBool(out, "visible", view.nodeVisible.get(x), defaultView.nodeVisible.get(x)); + writeBool(out, "hideunconnected", view.hideUnconnected.get(x), defaultView.hideUnconnected.get(x)); + if (x==null || x instanceof AlloySet) { + AlloySet s=(AlloySet)x; + writeBool(out, "showlabel", view.showAsLabel.get(s), defaultView.showAsLabel.get(s)); + writeBool(out, "showinattr", view.showAsAttr.get(s), defaultView.showAsAttr.get(s)); + } + if (x==null || x instanceof AlloyType) { + AlloyType t=(AlloyType)x; + writeBool(out, "numberatoms", view.number.get(t), defaultView.number.get(t)); + } + writeDotStyle(out, view.nodeStyle.get(x), defaultView.nodeStyle.get(x)); + writeDotShape(out, view.shape.get(x), defaultView.shape.get(x)); + writeDotColor(out, view.nodeColor.get(x), defaultView.nodeColor.get(x)); + if (x!=null && !view.label.get(x).equals(defaultView.label.get(x))) + Util.encodeXMLs(out, " label=\"", view.label.get(x), "\""); + if (out.checkError()) throw new IOException("PrintWriter IO Exception!"); + return sw.toString(); + } + + /*============================================================================================*/ + + /** Do nothing if the element is malformed; note: x can be null. */ + private static void parseEdgeViz(XMLNode xml, VizState view, AlloyRelation x) { + /* + * + * zero or more RELATION + * + * + * Each attribute, if omitted, means "no change". + * Note: BOOLEAN is tristate. + */ + if (has(xml,"visible")) view.edgeVisible.put (x, getbool(xml,"visible")); + if (has(xml,"attribute")) view.attribute .put (x, getbool(xml,"attribute")); + if (has(xml,"merge")) view.mergeArrows.put (x, getbool(xml,"merge")); + if (has(xml,"layout")) view.layoutBack .put (x, getbool(xml,"layout")); + if (has(xml,"constraint")) view.constraint .put (x, getbool(xml,"constraint")); + if (has(xml,"style")) view.edgeStyle .put (x, parseDotStyle(xml)); + if (has(xml,"color")) view.edgeColor .put (x, parseDotColor(xml)); + if (has(xml,"weight")) view.weight .put (x, getint (xml,"weight")); + if (has(xml,"label")) view.label .put (x, xml.getAttribute("label")); + } + + /** Returns the String representation of an AlloyRelation's settings. */ + private static String writeEdgeViz(VizState view, VizState defaultView, AlloyRelation x) throws IOException { + StringWriter sw=new StringWriter(); + PrintWriter out=new PrintWriter(sw); + writeDotColor(out, view.edgeColor.get(x), defaultView.edgeColor.get(x)); + writeDotStyle(out, view.edgeStyle.get(x), defaultView.edgeStyle.get(x)); + writeBool(out, "visible", view.edgeVisible.get(x), defaultView.edgeVisible.get(x)); + writeBool(out, "merge", view.mergeArrows.get(x), defaultView.mergeArrows.get(x)); + writeBool(out, "layout", view.layoutBack.get(x), defaultView.layoutBack.get(x)); + writeBool(out, "attribute", view.attribute.get(x), defaultView.attribute.get(x)); + writeBool(out, "constraint",view.constraint.get(x), defaultView.constraint.get(x)); + if (view.weight.get(x) != defaultView.weight.get(x)) out.write(" weight=\"" + view.weight.get(x) + "\""); + if (x!=null && !view.label.get(x).equals(defaultView.label.get(x))) + Util.encodeXMLs(out, " label=\"", view.label.get(x), "\""); + if (out.checkError()) throw new IOException("PrintWriter IO Exception!"); + return sw.toString(); + } + + /*============================================================================================*/ + + /** Returns null if the attribute doesn't exist, or is malformed. */ + private static DotPalette parseDotPalette(XMLNode x, String key) { + return DotPalette.parse(x.getAttribute(key)); + } + + /** Writes nothing if value==defaultValue. */ + private static void writeDotPalette(PrintWriter out, String key, DotPalette value, DotPalette defaultValue) throws IOException { + if (value!=defaultValue) Util.encodeXMLs(out, " "+key+"=\"", value==null?"inherit":value.toString(), "\""); + } + + /*============================================================================================*/ + + /** Returns null if the attribute doesn't exist, or is malformed. */ + private static DotColor parseDotColor(XMLNode x) { return DotColor.parse(x.getAttribute("color")); } + + /** Writes nothing if value==defaultValue. */ + private static void writeDotColor(PrintWriter out, DotColor value, DotColor defaultValue) throws IOException { + if (value!=defaultValue) Util.encodeXMLs(out, " color=\"", value==null?"inherit":value.toString(), "\""); + } + + /*============================================================================================*/ + + /** Returns null if the attribute doesn't exist, or is malformed. */ + private static DotShape parseDotShape(XMLNode x) { return DotShape.parse(x.getAttribute("shape")); } + + /** Writes nothing if value==defaultValue. */ + private static void writeDotShape(PrintWriter out, DotShape value, DotShape defaultValue) throws IOException { + if (value!=defaultValue) Util.encodeXMLs(out, " shape=\"", value==null?"inherit":value.toString(), "\""); + } + + /*============================================================================================*/ + + /** Returns null if the attribute doesn't exist, or is malformed. */ + private static DotStyle parseDotStyle(XMLNode x) { return DotStyle.parse(x.getAttribute("style")); } + + /** Writes nothing if value==defaultValue. */ + private static void writeDotStyle(PrintWriter out, DotStyle value, DotStyle defaultValue) throws IOException { + if (value!=defaultValue) Util.encodeXMLs(out, " style=\"", value==null?"inherit":value.toString(), "\""); + } + + /*============================================================================================*/ + + /** Returns null if the attribute doesn't exist, or is malformed. */ + private static Boolean getbool(XMLNode x, String attr) { + String value=x.getAttribute(attr); + if (value.equalsIgnoreCase("yes") || value.equalsIgnoreCase("true")) return Boolean.TRUE; + if (value.equalsIgnoreCase("no") || value.equalsIgnoreCase("false")) return Boolean.FALSE; + return null; + } + + /** Writes nothing if the value is equal to the default value. */ + private static void writeBool(PrintWriter out, String key, Boolean value, Boolean defaultValue) throws IOException { + if (value==null && defaultValue==null) return; + if (value!=null && defaultValue!=null && value.booleanValue()==defaultValue.booleanValue()) return; + out.write(' '); + out.write(key); + if (value==null) out.write("=\"inherit\""); else out.write(value ? "=\"yes\"":"=\"no\""); + } + + /*============================================================================================*/ + + /** Returns true if the XML element has the given attribute. */ + private static boolean has(XMLNode x, String attr) { + return x.getAttribute(attr,null)!=null; + } + + /** Returns 0 if the attribute doesn't exist, or is malformed. */ + private static int getint(XMLNode x, String attr) { + String value=x.getAttribute(attr); + int i; + try { + i=Integer.parseInt(value); + } catch(NumberFormatException ex) { + i=0; + } + return i; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/VizCustomizationPanel.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/VizCustomizationPanel.java new file mode 100644 index 00000000..dd63e603 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/VizCustomizationPanel.java @@ -0,0 +1,473 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4viz; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; +import javax.swing.BoxLayout; +import javax.swing.Icon; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSpinner; +import javax.swing.JSplitPane; +import javax.swing.JTextField; +import javax.swing.SpinnerNumberModel; +import javax.swing.border.EmptyBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.tree.TreePath; +import edu.mit.csail.sdg.alloy4.Listener; +import edu.mit.csail.sdg.alloy4.OurBorder; +import edu.mit.csail.sdg.alloy4.OurCombobox; +import edu.mit.csail.sdg.alloy4.OurCheckbox; +import edu.mit.csail.sdg.alloy4.OurTree; +import edu.mit.csail.sdg.alloy4.OurUtil; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4graph.DotColor; +import edu.mit.csail.sdg.alloy4graph.DotPalette; +import edu.mit.csail.sdg.alloy4graph.DotShape; +import edu.mit.csail.sdg.alloy4graph.DotStyle; + +/** GUI panel for making customization changes. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final class VizCustomizationPanel extends JPanel { + + /** This ensures the class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** The TREE NODE representing the root of the customization panel. */ + private static final Object ROOT = new Object(); + + /** The TREE NODE representing the GENERAL OPTIONS panel. */ + private static final Object GENERAL = new Object(); + + /** The TREE NODE representing the GENERAL NODES panel. */ + private static final Object NODES = new Object(); + + /** The TREE NODE representing the GENERAL EDGES panel. */ + private static final Object EDGES = new Object(); + + /** This is the VizState object that this customization panel will customize. */ + private final VizState vizState; + + /** This is the background color for the upper-half of the customization panel. */ + private static final Color wcolor = new Color(0.9f, 0.9f, 0.9f); + + /** This is the upper-half of the customization panel. */ + private final JPanel zoomPane; + + /** The JSplitPane separating this customization panel with the main graph panel. */ + private final JSplitPane divider; + + /** If it's an instance of AlloyElement, that means it's the latest selected type/set/relation. + * If it's GENERAL, NODES, or EDGES, that means the latest selected panel is + * the General Graph Settings, Default Type+Set, or Default Relation panels respectively. + * All else, that means the zoom panel is empty. + */ + private Object lastElement = null; + + //=============================================================================================================// + + /** Constructs a customization panel. + * @param divider - the JSplitPane separating the left-customization-half with the right-graph-half + * @param vizState - the VizState object that will be customized by this customization panel + */ + public VizCustomizationPanel(JSplitPane divider, VizState vizState) { + this.divider = divider; + this.vizState = vizState; + setBorder(null); + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + zoomPane = new JPanel(); + zoomPane.setBorder(new OurBorder(false,false,true,false)); + zoomPane.setLayout(new BoxLayout(zoomPane, BoxLayout.Y_AXIS)); + zoomPane.setAlignmentX(0f); + zoomPane.setBackground(wcolor); + remakeAll(); + } + + //=============================================================================================================// + + /** This method selects a particular treenode and shows the details of a particular Type/Set/Relation. + *

+ * If x is an instance of AlloyElement, that means it's the latest selected type/set/relation. + * If x is GENERAL, NODES, or EDGES, that means the latest selected panel is + * the General Graph Settings, Default Type+Set, or Default Relation panels respectively. + */ + private void zoom(Object x) { + lastElement = x; + zoomPane.removeAll(); + if (x instanceof AlloyNodeElement) makeNodeOptionsPanel(zoomPane, (AlloyNodeElement)x); + else if (x instanceof AlloyRelation) makeEdgeOptionsPanel(zoomPane, (AlloyRelation)x); + else if (x == GENERAL) createGeneralWidget(zoomPane); + else if (x == NODES) createDefaultNodeWidget(zoomPane); + else if (x == EDGES) createDefaultEdgeWidget(zoomPane); + else { + // The following 2 lines make sure the panel doesn't get too small on Mac + zoomPane.add(OurUtil.makeH(wcolor, new JLabel(" "), (Object)null)); + zoomPane.add(OurUtil.makeH(new Dimension(250, 200), wcolor, (Object)null)); + } + Dimension dim = zoomPane.getPreferredSize(); + if (divider!=null && divider.getDividerLocation()dim.width) dim.width=divider.getDividerLocation(); + dim.height = 150; + zoomPane.setPreferredSize(dim); + dim.width = 450; + zoomPane.setMinimumSize(dim); + zoomPane.repaint(); + validate(); + } + + //=============================================================================================================// + + /** Regenerate all the customization widgets based on the latest settings. */ + public void remakeAll() { + // Make the tree + final OurTree tree = new OurTree(12) { + private static final long serialVersionUID = 0; + private final AlloyModel old = vizState.getOriginalModel(), now = vizState.getCurrentModel(); + private final boolean hidePrivate = vizState.hidePrivate(), hideMeta = vizState.hideMeta(); + { + do_start(); + setRootVisible(false); + setShowsRootHandles(false); + listeners.add(new Listener() { + public Object do_action(Object sender, Event event) { return null; } + public Object do_action(Object sender, Event event, Object arg) { zoom(arg); return null; } + }); + } + @Override public String convertValueToText(Object value, boolean sel, boolean expand, boolean leaf, int i, boolean focus) { + if (value==GENERAL) return "general graph settings"; + if (value==NODES) return "types and sets"; + if (value==EDGES) return "relations"; + if (value instanceof AlloyType) { + AlloyType x = (AlloyType)value; + if (vizState.getCurrentModel().hasType(x)) return "sig "+typename(x)+""; + return "sig "+typename(x)+" (projected)"; + } + if (value instanceof AlloySet) return "set "+ ((AlloySet)value).getName() + ""; + if (value instanceof AlloyRelation) return value.toString(); else return ""; + } + @Override public List do_ask(Object parent) { + ArrayList ans = new ArrayList(); + if (parent==ROOT) { ans.add(GENERAL); ans.add(NODES); ans.add(EDGES); } + else if (parent==NODES) { ans.add(AlloyType.UNIV); } + else if (parent==EDGES) { + for (AlloyRelation rel: vizState.getCurrentModel().getRelations()) + if (!(hidePrivate && rel.isPrivate) && !(hideMeta && rel.isMeta)) ans.add(rel); + } else if (parent instanceof AlloyType) { + AlloyType type = (AlloyType)parent; + for (AlloySet s:now.getSets()) + if (!(hidePrivate && s.isPrivate) && !(hideMeta && s.isMeta) && s.getType().equals(type)) ans.add(s); + if (!type.isEnum) for(AlloyType t: old.getDirectSubTypes(type)) + if (!(hidePrivate && t.isPrivate) && !(hideMeta && t.isMeta)) + if (now.hasType(t) || vizState.canProject(t)) ans.add(t); + } + return ans; + } + @Override public boolean do_isDouble(Object object) { return object==NODES || object==EDGES; } + @Override public Object do_root() { return ROOT; } + }; + // Pre-expand the entire tree. + TreePath last = null; + for(int i=0; i " + Util.encode(rel.toString()) + "")); + parent.add(OurUtil.makeH(10, labelText, wcolor, 5, color, 5, style, 3, weightPanel, 2, null)); + parent.add(OurUtil.makeHT(wcolor, 10, panel1, 15, panel2, 2, null)); + } + + //=============================================================================================================// + + /** Generates the "general graph settings" widgets, and add them to "parent". */ + private void createGeneralWidget(JPanel parent) { + final List fontSizes = Util.asList(9,10,11,12,14,16,18,20,22,24,26,28,32,36,40,44,48,54,60,66,72); + JLabel nLabel = OurUtil.label("Node Color Palette:"); + JLabel eLabel = OurUtil.label("Edge Color Palette:"); + JLabel aLabel = OurUtil.label("Use original atom names:"); + JLabel pLabel = OurUtil.label("Hide private sigs/relations:"); + JLabel mLabel = OurUtil.label("Hide meta sigs/relations:"); + JLabel fLabel = OurUtil.label("Font Size:"); + JComboBox fontSize = new OurCombobox(false, fontSizes.toArray(), 60, 32, vizState.getFontSize()) { + private static final long serialVersionUID = 0; + @Override public void do_changed(Object value) { if (fontSizes.contains(value)) vizState.setFontSize((Integer)value); } + }; + JComboBox nodepal = new OurCombobox(false, DotPalette.values(), 100, 32, vizState.getNodePalette()) { + private static final long serialVersionUID = 0; + @Override public String do_getText(Object value) { return ((DotPalette)value).getDisplayedText(); } + @Override public void do_changed(Object value) { vizState.setNodePalette((DotPalette)value); } + }; + JComboBox edgepal = new OurCombobox(false, DotPalette.values(), 100, 32, vizState.getEdgePalette()) { + private static final long serialVersionUID = 0; + @Override public String do_getText(Object value) { return ((DotPalette)value).getDisplayedText(); } + @Override public void do_changed(Object value) { vizState.setEdgePalette((DotPalette)value); } + }; + JPanel name = new OurCheckbox("", "Whether the visualizer should use the original atom names as-is.", vizState.useOriginalName() ? OurCheckbox.ON : OurCheckbox.OFF) { + private static final long serialVersionUID = 0; + public Icon do_action() { boolean x = vizState.useOriginalName(); vizState.useOriginalName(!x); return (!x ? ON : OFF); } + }; + JPanel priv = new OurCheckbox("", "Whether the visualizer should hide private sigs, sets, and relations by default.", vizState.hidePrivate() ? OurCheckbox.ON : OurCheckbox.OFF) { + private static final long serialVersionUID = 0; + public Icon do_action() { boolean x = vizState.hidePrivate(); vizState.hidePrivate(!x); remakeAll(); return (!x ? ON : OFF); } + }; + JPanel meta = new OurCheckbox("", "Whether the visualizer should hide meta sigs, sets, and relations by default.", vizState.hideMeta() ? OurCheckbox.ON : OurCheckbox.OFF) { + private static final long serialVersionUID = 0; + public Icon do_action() { boolean x = vizState.hideMeta(); vizState.hideMeta(!x); remakeAll(); return (!x ? ON : OFF); } + }; + parent.add(makelabel(" General Graph Settings:")); + parent.add(OurUtil.makeH(wcolor, new Dimension(6, 6))); + parent.add(OurUtil.makeH(wcolor, 25, nLabel, 5, nodepal, 8, aLabel, 5, name, 2, null)); + parent.add(OurUtil.makeH(wcolor, 25, eLabel, 5, edgepal, 8, fLabel, 5, fontSize, 2, null)); + parent.add(OurUtil.makeH(wcolor, 25, pLabel, 5, priv, 2, null)); + parent.add(OurUtil.makeH(wcolor, 25, mLabel, 5, meta, 2, null)); + } + + //=============================================================================================================// + + /** Generates the "default type and set settings" widgets, and add them to "parent". */ + private void createDefaultNodeWidget(JPanel parent) { + JComboBox color = new OurCombobox(false, DotColor.valuesWithout(DotColor.MAGIC), 110, 35, vizState.nodeColor.get(null)) { + private static final long serialVersionUID = 0; + @Override public String do_getText(Object value) { return ((DotColor)value).getDisplayedText(); } + @Override public Icon do_getIcon(Object value) { return ((DotColor)value).getIcon(vizState.getNodePalette()); } + @Override public void do_changed(Object value) { vizState.nodeColor.put(null, (DotColor)value); } + }; + JComboBox shape = new OurCombobox(false, DotShape.values(), 135, 35, vizState.shape.get(null)) { + private static final long serialVersionUID = 0; + @Override public String do_getText(Object value) { return ((DotShape)value).getDisplayedText(); } + @Override public Icon do_getIcon(Object value) { return ((DotShape)value).getIcon(); } + @Override public void do_changed(Object value) { vizState.shape.put(null, (DotShape)value); } + }; + JComboBox style = new OurCombobox(false, DotStyle.values(), 110, 35, vizState.nodeStyle.get(null)) { + private static final long serialVersionUID = 0; + @Override public String do_getText(Object value) { return ((DotStyle)value).getDisplayedText(); } + @Override public Icon do_getIcon(Object value) { return ((DotStyle)value).getIcon(); } + @Override public void do_changed(Object value) { vizState.nodeStyle.put(null, (DotStyle)value); } + }; + JPanel vis = vizState.nodeVisible .pick("Show", "Show members of type as nodes"); + JPanel hide = vizState.hideUnconnected.pick("Hide unconnected nodes", "Hide nodes without arcs"); + JPanel num = vizState.number .pick("Number nodes", "Attach atom number to node label as suffix"); + JPanel label= vizState.showAsLabel .pick("Show as labels", "Show members as labels"); + JPanel attr = vizState.showAsAttr .pick("Show in relation attributes", "Show set membership of endpoints when relation attributes are enabled"); + parent.add(makelabel(" Default Type and Set Settings:")); + parent.add(OurUtil.makeH(wcolor, 10, color, 7, style, 7, shape, 2, null)); + JPanel a=OurUtil.makeVL(wcolor, vis, num, label), b=OurUtil.makeVL(wcolor, hide, attr); + parent.add(OurUtil.makeHT(wcolor, 10, a, 10, b, 2, null)); + } + + //=============================================================================================================// + + /** Generates the "default relation settings" widgets, and add them to "parent". */ + private void createDefaultEdgeWidget(JPanel parent) { + JComboBox colorComboE = new OurCombobox(false, DotColor.valuesWithout(DotColor.WHITE), 110, 35, vizState.edgeColor.get(null)) { + private static final long serialVersionUID = 0; + @Override public String do_getText(Object value) { return ((DotColor)value).getDisplayedText(); } + @Override public Icon do_getIcon(Object value) { return ((DotColor)value).getIcon(vizState.getEdgePalette()); } + @Override public void do_changed(Object value) { vizState.edgeColor.put(null, (DotColor)value); } + }; + JComboBox outlineComboE = new OurCombobox(false, DotStyle.values(), 110, 35, vizState.edgeStyle.get(null)) { + private static final long serialVersionUID = 0; + @Override public String do_getText(Object value) { return ((DotStyle)value).getDisplayedText(); } + @Override public Icon do_getIcon(Object value) { return ((DotStyle)value).getIcon(); } + @Override public void do_changed(Object value) { vizState.edgeStyle.put(null, (DotStyle)value); } + }; + JPanel dispCBE = vizState.edgeVisible.pick("Show as arcs", "Show relations as arcs"); + JPanel mergeCBE = vizState.mergeArrows.pick("Merge arrows", "Merge opposing arrows of the same relation"); + JPanel constraintCBE = vizState.constraint .pick("Influence layout", "Whether this edge influences the graph layout"); + JPanel attrCBE = vizState.attribute .pick("Show as attributes", "Show relations as attributes on nodes"); + JPanel laybackCBE = vizState.layoutBack .pick("Layout backwards", "Layout graph as if arcs were reversed"); + parent.add(makelabel(" Default Relation Settings:")); + parent.add(OurUtil.makeH(wcolor, 10, colorComboE, 8, outlineComboE, 2, null)); + JPanel a=OurUtil.makeVL(wcolor, dispCBE, attrCBE, constraintCBE, 10), b=OurUtil.makeVL(wcolor, laybackCBE, mergeCBE); + parent.add(OurUtil.makeHT(wcolor, 10, a, 10, b, 2, null)); + } + + //=============================================================================================================// + + /** Convenient helper method that returns a description of an AlloyType (and what it extends). */ + private String typename(AlloyType type) { + if (type.equals(AlloyType.UNIV)) return "univ"; + AlloyType sup=vizState.getOriginalModel().getSuperType(type); + if (sup!=null && !sup.equals(AlloyType.UNIV)) return type.getName()+" extends "+sup.getName(); + return type.getName(); + } + + /** Generates a black JLabel for the given String. */ + private static JLabel makelabel(String label) { return OurUtil.label(label, OurUtil.getVizFont().deriveFont(Font.BOLD)); } + + /** Project over the given type if we are allowed to. */ + private void projectAlloyType(AlloyType type) { vizState.project(type); remakeAll(); } + + /** Unproject over the given type if it is currently projected. */ + private void deprojectAlloyType(AlloyType type) { vizState.deproject(type); remakeAll(); } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/VizGUI.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/VizGUI.java new file mode 100644 index 00000000..62b00c67 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/VizGUI.java @@ -0,0 +1,1025 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4viz; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.prefs.Preferences; +import javax.swing.Box; +import javax.swing.Icon; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JSplitPane; +import javax.swing.JToolBar; +import javax.swing.plaf.basic.BasicSplitPaneUI; +import edu.mit.csail.sdg.alloy4.Computer; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.OurBorder; +import edu.mit.csail.sdg.alloy4.OurCheckbox; +import edu.mit.csail.sdg.alloy4.OurConsole; +import edu.mit.csail.sdg.alloy4.OurDialog; +import edu.mit.csail.sdg.alloy4.Runner; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.OurUtil; +import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.alloy4.Util.IntPref; +import edu.mit.csail.sdg.alloy4.Util.StringPref; +import edu.mit.csail.sdg.alloy4graph.GraphViewer; +import static edu.mit.csail.sdg.alloy4.OurUtil.menu; +import static edu.mit.csail.sdg.alloy4.OurUtil.menuItem; + +/** GUI main window for the visualizer. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final class VizGUI implements ComponentListener { + + /** The background color for the toolbar. */ + private static final Color background = new Color(0.9f, 0.9f, 0.9f); + + /** The icon for a "checked" menu item. */ + private static final Icon iconYes = OurUtil.loadIcon("images/menu1.gif"); + + /** The icon for an "unchecked" menu item. */ + private static final Icon iconNo = OurUtil.loadIcon("images/menu0.gif"); + + /** Whether the JVM should shutdown after the last file is closed. */ + private final boolean standalone; + + /** The current display mode. */ + private VisualizerMode currentMode = VisualizerMode.get(); + + /** The JFrame for the main GUI window; or null if we intend to display the graph inside a user-given JPanel instead. */ + private final JFrame frame; + + /** The toolbar. */ + private final JToolBar toolbar; + + /** The projection popup menu. */ + private final JPopupMenu projectionPopup; + + /** The buttons on the toolbar. */ + private final JButton projectionButton, openSettingsButton, closeSettingsButton, + magicLayout, loadSettingsButton, saveSettingsButton, saveAsSettingsButton, + resetSettingsButton, updateSettingsButton, openEvaluatorButton, closeEvaluatorButton, enumerateButton, + vizButton, treeButton, txtButton/*, dotButton, xmlButton*/; + + /** This list must contain all the display mode buttons (that is, vizButton, xmlButton...) */ + private final List solutionButtons = new ArrayList(); + + /** The "theme" menu. */ + private final JMenu thememenu; + + /** The "window" menu. */ + private final JMenu windowmenu; + + /** The "show next" menu item. */ + private final JMenuItem enumerateMenu; + + /** Current font size. */ + private int fontSize=12; + + /** 0: theme and evaluator are both invisible; 1: theme is visible; 2: evaluator is visible. */ + private int settingsOpen=0; + + /** The current instance and visualization settings; null if none is loaded. */ + private VizState myState=null; + + /** Returns the current visualization settings (and you can call getOriginalInstance() on it to get the current instance). + * If you make changes to the state, you should call doApply() on the VizGUI object to refresh the screen. + */ + public VizState getVizState() { return myState; } + + /** The customization panel to the left; null if it is not yet loaded. */ + private VizCustomizationPanel myCustomPanel=null; + + /** The evaluator panel to the left; null if it is not yet loaded. */ + private OurConsole myEvaluatorPanel=null; + + /** The graphical panel to the right; null if it is not yet loaded. */ + private VizGraphPanel myGraphPanel=null; + + /** The splitpane between the customization panel and the graph panel. */ + private final JSplitPane splitpane; + + /** The tree or graph or text being displayed on the right hand side. */ + private JComponent content=null; + + /** Returns the JSplitPane containing the customization/evaluator panel in the left and the graph on the right. */ + public JSplitPane getPanel() { return splitpane; } + + /** The last known divider position between the customization panel and the graph panel. */ + private int lastDividerPosition=0; + + /** If nonnull, you can pass in an expression to be evaluated. + * If it throws an exception, that means an error has occurred. + */ + private final Computer evaluator; + + /** If nonnull, you can pass in an XML file to find the next solution. */ + private final Computer enumerator; + + //==============================================================================================// + + /** The current theme file; "" if there is no theme file loaded. */ + private String thmFileName=""; + + /** Returns the current THM filename; "" if no theme file is currently loaded. */ + public String getThemeFilename() { return thmFileName; } + + //==============================================================================================// + + /** The current XML file; "" if there is no XML file loaded. */ + private String xmlFileName=""; + + /** Returns the current XML filename; "" if no file is currently loaded. */ + public String getXMLfilename() { return xmlFileName; } + + //==============================================================================================// + + /** The list of XML files loaded in this session so far. */ + private final List xmlLoaded=new ArrayList(); + + /** Return the list of XML files loaded in this session so far. */ + public ConstList getInstances() { return ConstList.make(xmlLoaded); } + + //==============================================================================================// + + /** This maps each XML filename to a descriptive title. */ + private Map xml2title = new LinkedHashMap(); + + /** Returns a short descriptive title associated with an XML file. */ + public String getInstanceTitle(String xmlFileName) { + String answer = xml2title.get(Util.canon(xmlFileName)); + return (answer==null) ? "(unknown)" : answer; + } + + //==============================================================================================// + + /** Add a vertical divider to the toolbar. */ + private void addDivider() { + JPanel divider = OurUtil.makeH(new Dimension(1, 40), Color.LIGHT_GRAY); + divider.setAlignmentY(0.5f); + if (!Util.onMac()) toolbar.add(OurUtil.makeH(5,background)); else toolbar.add(OurUtil.makeH(5)); + toolbar.add(divider); + if (!Util.onMac()) toolbar.add(OurUtil.makeH(5,background)); else toolbar.add(OurUtil.makeH(5)); + } + + //======== The Preferences ======================================================================================// + //======== Note: you must make sure each preference has a unique key ============================================// + + /** This enum defines the set of possible visualizer modes. */ + private enum VisualizerMode { + /** Visualize using graphviz's dot. */ Viz("graphviz"), +// /** See the DOT content. */ DOT("dot"), +// /** See the XML content. */ XML("xml"), + /** See the instance as text. */ TEXT("txt"), + /** See the instance as a tree. */ Tree("tree"); + /** This is a unique String for this value; it should be kept consistent in future versions. */ + private final String id; + /** Constructs a new VisualizerMode value with the given id. */ + private VisualizerMode(String id) { this.id=id; } + /** Given an id, return the enum value corresponding to it (if there's no match, then return Viz). */ + private static VisualizerMode parse(String id) { + for(VisualizerMode vm: values()) if (vm.id.equals(id)) return vm; + return Viz; + } + /** Saves this value into the Java preference object. */ + public void set() { Preferences.userNodeForPackage(Util.class).put("VisualizerMode",id); } + /** Reads the current value of the Java preference object (if it's not set, then return Viz). */ + public static VisualizerMode get() { return parse(Preferences.userNodeForPackage(Util.class).get("VisualizerMode","")); } + }; + + /** The latest X corrdinate of the Alloy Visualizer window. */ + private static final IntPref VizX = new IntPref("VizX",0,-1,65535); + + /** The latest Y corrdinate of the Alloy Visualizer window. */ + private static final IntPref VizY = new IntPref("VizY",0,-1,65535); + + /** The latest width of the Alloy Visualizer window. */ + private static final IntPref VizWidth = new IntPref("VizWidth",0,-1,65535); + + /** The latest height of the Alloy Visualizer window. */ + private static final IntPref VizHeight = new IntPref("VizHeight",0,-1,65535); + + /** The first file in Alloy Visualizer's "open recent theme" list. */ + private static final StringPref Theme0 = new StringPref("Theme0"); + + /** The second file in Alloy Visualizer's "open recent theme" list. */ + private static final StringPref Theme1 = new StringPref("Theme1"); + + /** The third file in Alloy Visualizer's "open recent theme" list. */ + private static final StringPref Theme2 = new StringPref("Theme2"); + + /** The fourth file in Alloy Visualizer's "open recent theme" list. */ + private static final StringPref Theme3 = new StringPref("Theme3"); + + //==============================================================================================// + + /** If true, that means the event handlers should return a Runner encapsulating them, rather than perform the actual work. */ + private boolean wrap = false; + + /** Wraps the calling method into a Runnable whose run() will call the calling method with (false) as the only argument. */ + private Runner wrapMe() { + final String name; + try { throw new Exception(); } catch(Exception ex) { name = ex.getStackTrace()[1].getMethodName(); } + Method[] methods = getClass().getDeclaredMethods(); + Method m=null; + for(int i=0; i Note: if standalone==false and xmlFileName.length()==0, then we will initially hide the window. + */ + public VizGUI(boolean standalone, String xmlFileName, JMenu windowmenu) { + this(standalone, xmlFileName, windowmenu, null, null); + } + + /** Creates a new visualization GUI window; this method can only be called by the AWT event thread. + * @param standalone - whether the JVM should shutdown after the last file is closed + * @param xmlFileName - the filename of the incoming XML file; "" if there's no file to open + * @param windowmenu - if standalone==false and windowmenu!=null, then this will be added as a menu on the menubar + * @param enumerator - if it's not null, it provides solution enumeration ability + * @param evaluator - if it's not null, it provides solution evaluation ability + * + *

Note: if standalone==false and xmlFileName.length()==0, then we will initially hide the window. + */ + public VizGUI(boolean standalone, String xmlFileName, JMenu windowmenu, Computer enumerator, Computer evaluator) { + this(standalone, xmlFileName, windowmenu, enumerator, evaluator, true); + } + + /** Creates a new visualization GUI window; this method can only be called by the AWT event thread. + * @param standalone - whether the JVM should shutdown after the last file is closed + * @param xmlFileName - the filename of the incoming XML file; "" if there's no file to open + * @param windowmenu - if standalone==false and windowmenu!=null, then this will be added as a menu on the menubar + * @param enumerator - if it's not null, it provides solution enumeration ability + * @param evaluator - if it's not null, it provides solution evaluation ability + * @param makeWindow - if false, then we will only construct the JSplitPane, without making the window + * + *

Note: if standalone==false and xmlFileName.length()==0 and makeWindow==true, then we will initially hide the window. + */ + public VizGUI(boolean standalone, String xmlFileName, JMenu windowmenu, Computer enumerator, Computer evaluator, boolean makeWindow) { + + this.enumerator = enumerator; + this.standalone = standalone; + this.evaluator = evaluator; + this.frame = makeWindow ? new JFrame("Alloy Visualizer") : null; + + // Figure out the desired x, y, width, and height + int screenWidth=OurUtil.getScreenWidth(), screenHeight=OurUtil.getScreenHeight(); + int width=VizWidth.get(); + if (width<0) width=screenWidth-150; else if (width<100) width=100; + if (width>screenWidth) width=screenWidth; + int height=VizHeight.get(); + if (height<0) height=screenHeight-150; else if (height<100) height=100; + if (height>screenHeight) height=screenHeight; + int x=VizX.get(); if (x<0 || x>screenWidth-10) x=0; + int y=VizY.get(); if (y<0 || y>screenHeight-10) y=0; + + // Create the menubar + JMenuBar mb = new JMenuBar(); + try { + wrap = true; + JMenu fileMenu = menu(mb, "&File", null); + menuItem(fileMenu, "Open...", 'O', 'O', doLoad()); + JMenu exportMenu = menu(null, "&Export To", null); + menuItem(exportMenu, "Dot...", 'D', 'D', doExportDot()); + menuItem(exportMenu, "XML...", 'X', 'X', doExportXml()); + fileMenu.add(exportMenu); + menuItem(fileMenu, "Close", 'W', 'W', doClose()); + if (standalone) menuItem(fileMenu, "Quit", 'Q', 'Q', doCloseAll()); else menuItem(fileMenu, "Close All", 'A', doCloseAll()); + JMenu instanceMenu = menu(mb, "&Instance", null); + enumerateMenu = menuItem(instanceMenu, "Show Next Solution", 'N', 'N', doNext()); + thememenu = menu(mb, "&Theme", doRefreshTheme()); + if (standalone || windowmenu==null) windowmenu = menu(mb, "&Window", doRefreshWindow()); + this.windowmenu = windowmenu; + } finally { + wrap = false; + } + mb.add(windowmenu); + thememenu.setEnabled(false); + windowmenu.setEnabled(false); + if (frame!=null) frame.setJMenuBar(mb); + + // Create the toolbar + projectionPopup = new JPopupMenu(); + projectionButton = new JButton("Projection: none"); + projectionButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + repopulateProjectionPopup(); + if (projectionPopup.getComponentCount()>0) projectionPopup.show(projectionButton, 10, 10); + } + }); + repopulateProjectionPopup(); + toolbar = new JToolBar(); + toolbar.setVisible(false); + toolbar.setFloatable(false); + toolbar.setBorder(null); + if (!Util.onMac()) toolbar.setBackground(background); + try { + wrap = true; + vizButton=makeSolutionButton("Viz", "Show Visualization", "images/24_graph.gif", doShowViz()); +// dotButton=makeSolutionButton("Dot", "Show the Dot File for the Graph", "images/24_plaintext.gif", doShowDot()); +// xmlButton=makeSolutionButton("XML", "Show XML", "images/24_plaintext.gif", doShowXML()); + txtButton=makeSolutionButton("Txt", "Show the textual output for the Graph", "images/24_plaintext.gif", doShowTxt()); + treeButton=makeSolutionButton("Tree", "Show Tree", "images/24_texttree.gif", doShowTree()); + if (frame!=null) addDivider(); + toolbar.add(closeSettingsButton=OurUtil.button("Close", "Close the theme customization panel", "images/24_settings_close2.gif", doCloseThemePanel())); + toolbar.add(updateSettingsButton=OurUtil.button("Apply", "Apply the changes to the current theme", "images/24_settings_apply2.gif", doApply())); + toolbar.add(openSettingsButton=OurUtil.button("Theme", "Open the theme customization panel", "images/24_settings.gif", doOpenThemePanel())); + toolbar.add(magicLayout=OurUtil.button("Magic Layout", "Automatic theme customization (will reset current theme)", "images/24_settings_apply2.gif", doMagicLayout())); + toolbar.add(openEvaluatorButton=OurUtil.button("Evaluator", "Open the evaluator", "images/24_settings.gif", doOpenEvalPanel())); + toolbar.add(closeEvaluatorButton=OurUtil.button("Close Evaluator", "Close the evaluator", "images/24_settings_close2.gif", doCloseEvalPanel())); + toolbar.add(enumerateButton=OurUtil.button("Next", "Show the next solution", "images/24_history.gif", doNext())); + toolbar.add(projectionButton); + toolbar.add(loadSettingsButton=OurUtil.button("Load", "Load the theme customization from a theme file", "images/24_open.gif", doLoadTheme())); + toolbar.add(saveSettingsButton=OurUtil.button("Save", "Save the current theme customization", "images/24_save.gif", doSaveTheme())); + toolbar.add(saveAsSettingsButton=OurUtil.button("Save As", "Save the current theme customization as a new theme file", "images/24_save.gif", doSaveThemeAs())); + toolbar.add(resetSettingsButton=OurUtil.button("Reset", "Reset the theme customization", "images/24_settings_close2.gif", doResetTheme())); + } finally { + wrap = false; + } + settingsOpen=0; + + // Create the horizontal split pane + splitpane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); + splitpane.setOneTouchExpandable(false); + splitpane.setResizeWeight(0.); + splitpane.setContinuousLayout(true); + splitpane.setBorder(null); + ((BasicSplitPaneUI)(splitpane.getUI())).getDivider().setBorder(new OurBorder(false,true,false,false)); + + // Display the window, then proceed to load the input file + if (frame!=null) { + frame.pack(); + if (!Util.onMac() && !Util.onWindows()) { + // many Window managers do not respect ICCCM2; this should help avoid the Title Bar being shifted "off screen" + if (x<30) { if (x<0) x=0; width=width-(30-x); x=30; } + if (y<30) { if (y<0) y=0; height=height-(30-y); y=30; } + if (width<100) width=100; + if (height<100) height=100; + } + frame.setSize(width, height); + frame.setLocation(x, y); + frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + try { wrap=true; frame.addWindowListener(doClose()); } finally { wrap=false; } + frame.addComponentListener(this); + } + if (xmlFileName.length()>0) doLoadInstance(xmlFileName); + } + + /** Invoked when the Visualizationwindow is resized. */ + public void componentResized(ComponentEvent e) { + componentMoved(e); + } + + /** Invoked when the Visualizationwindow is moved. */ + public void componentMoved(ComponentEvent e) { + if (frame!=null) { + VizWidth.set(frame.getWidth()); + VizHeight.set(frame.getHeight()); + VizX.set(frame.getX()); + VizY.set(frame.getY()); + } + } + + /** Invoked when the Visualizationwindow is shown. */ + public void componentShown(ComponentEvent e) { } + + /** Invoked when the Visualizationwindow is hidden. */ + public void componentHidden(ComponentEvent e) { } + + /** Helper method that repopulates the Porjection popup menu. */ + private void repopulateProjectionPopup() { + int num=0; + String label="Projection: none"; + if (myState==null) { projectionButton.setEnabled(false); return; } + projectionButton.setEnabled(true); + projectionPopup.removeAll(); + final Set projected = myState.getProjectedTypes(); + for(final AlloyType t: myState.getOriginalModel().getTypes()) if (myState.canProject(t)) { + final boolean on = projected.contains(t); + final JMenuItem m = new JMenuItem(t.getName(), on ? OurCheckbox.ON : OurCheckbox.OFF); + m.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (on) myState.deproject(t); else myState.project(t); + updateDisplay(); + } + }); + projectionPopup.add(m); + if (on) { num++; if (num==1) label="Projected over "+t.getName(); } + } + projectionButton.setText(num>1 ? ("Projected over "+num+" sigs") : label); + } + + /** Helper method that refreshes the right-side visualization panel with the latest settings. */ + private void updateDisplay() { + if (myState==null) return; + // First, update the toolbar + currentMode.set(); + for(JButton button:solutionButtons) button.setEnabled(settingsOpen!=1); + switch (currentMode) { + case Tree: treeButton.setEnabled(false); break; + case TEXT: txtButton.setEnabled(false); break; +// case XML: xmlButton.setEnabled(false); break; +// case DOT: dotButton.setEnabled(false); break; + default: vizButton.setEnabled(false); + } + final boolean isMeta = myState.getOriginalInstance().isMetamodel; + vizButton.setVisible(frame!=null); + treeButton.setVisible(frame!=null); + txtButton.setVisible(frame!=null); +// dotButton.setVisible(frame!=null); +// xmlButton.setVisible(frame!=null); + magicLayout.setVisible((settingsOpen==0 || settingsOpen==1) && currentMode==VisualizerMode.Viz); + projectionButton.setVisible((settingsOpen==0 || settingsOpen==1) && currentMode==VisualizerMode.Viz); + openSettingsButton.setVisible( settingsOpen==0 && currentMode==VisualizerMode.Viz); + loadSettingsButton.setVisible(frame==null && settingsOpen==1 && currentMode==VisualizerMode.Viz); + saveSettingsButton.setVisible(frame==null && settingsOpen==1 && currentMode==VisualizerMode.Viz); + saveAsSettingsButton.setVisible(frame==null && settingsOpen==1 && currentMode==VisualizerMode.Viz); + resetSettingsButton.setVisible(frame==null && settingsOpen==1 && currentMode==VisualizerMode.Viz); + closeSettingsButton.setVisible(settingsOpen==1 && currentMode==VisualizerMode.Viz); + updateSettingsButton.setVisible(settingsOpen==1 && currentMode==VisualizerMode.Viz); + openEvaluatorButton.setVisible(!isMeta && settingsOpen==0 && evaluator!=null); + closeEvaluatorButton.setVisible(!isMeta && settingsOpen==2 && evaluator!=null); + enumerateMenu.setEnabled(!isMeta && settingsOpen==0 && enumerator!=null); + enumerateButton.setVisible(!isMeta && settingsOpen==0 && enumerator!=null); + toolbar.setVisible(true); + // Now, generate the graph or tree or textarea that we want to display on the right + if (frame!=null) frame.setTitle(makeVizTitle()); + switch (currentMode) { + case Tree: { + final VizTree t = new VizTree(myState.getOriginalInstance().originalA4, makeVizTitle(), fontSize); + final JScrollPane scroll = OurUtil.scrollpane(t, Color.BLACK, Color.WHITE, new OurBorder(true, false, true, false)); + scroll.addFocusListener(new FocusListener() { + public final void focusGained(FocusEvent e) { t.requestFocusInWindow(); } + public final void focusLost(FocusEvent e) { } + }); + content = scroll; + break; + } + case TEXT: { + String textualOutput = myState.getOriginalInstance().originalA4.toString(); + content = getTextComponent(textualOutput); + break; + } +// case XML: { +// content=getTextComponent(xmlFileName); +// break; +// } + default: { + if (myGraphPanel==null) { + myGraphPanel=new VizGraphPanel(myState, false); + } else { + myGraphPanel.seeDot(false); + myGraphPanel.remakeAll(); + } + } + content=myGraphPanel; + } + // Now that we've re-constructed "content", let's set its font size + if (currentMode != VisualizerMode.Tree) { + content.setFont(OurUtil.getVizFont().deriveFont((float)fontSize)); + content.invalidate(); + content.repaint(); + content.validate(); + } + // Now, display them! + final Box instanceTopBox = Box.createHorizontalBox(); + instanceTopBox.add(toolbar); + final JPanel instanceArea = new JPanel(new BorderLayout()); + instanceArea.add(instanceTopBox, BorderLayout.NORTH); + instanceArea.add(content, BorderLayout.CENTER); + instanceArea.setVisible(true); + if (!Util.onMac()) { instanceTopBox.setBackground(background); instanceArea.setBackground(background); } + JComponent left = null; + if (settingsOpen==1) { + if (myCustomPanel==null) myCustomPanel = new VizCustomizationPanel(splitpane,myState); else myCustomPanel.remakeAll(); + left = myCustomPanel; + } else if (settingsOpen>1) { + if (myEvaluatorPanel==null) + myEvaluatorPanel = new OurConsole(evaluator, true, + "The ", true, "Alloy Evaluator ", false, + "allows you to type\nin Alloy expressions and see their values.\nFor example, ", true, + "univ", false, " shows the list of all atoms.\n(You can press UP and DOWN to recall old inputs).\n"); + try { evaluator.compute(new File(xmlFileName)); } catch(Exception ex) { } // exception should not happen + left = myEvaluatorPanel; + left.setBorder(new OurBorder(false, false, false, false)); + } + if (frame!=null && frame.getContentPane()==splitpane) lastDividerPosition=splitpane.getDividerLocation(); + splitpane.setRightComponent(instanceArea); + splitpane.setLeftComponent(left); + if (left!=null) { + Dimension dim = left.getPreferredSize(); + if (lastDividerPosition<50 && frame!=null) lastDividerPosition = frame.getWidth()/2; + if (lastDividerPosition400) lastDividerPosition = 400; + splitpane.setDividerLocation(lastDividerPosition); + } + if (frame!=null) frame.setContentPane(splitpane); + if (settingsOpen!=2) content.requestFocusInWindow(); else myEvaluatorPanel.requestFocusInWindow(); + repopulateProjectionPopup(); + if (frame!=null) frame.validate(); else splitpane.validate(); + } + + /** Helper method that creates a button and add it to both the "SolutionButtons" list, as well as the toolbar. */ + private JButton makeSolutionButton(String label, String toolTip, String image, ActionListener mode) { + JButton button = OurUtil.button(label, toolTip, image, mode); + solutionButtons.add(button); + toolbar.add(button); + return button; + } + + /** Helper method that returns a concise description of the instance currently being displayed. */ + private String makeVizTitle() { + String filename = (myState!=null ? myState.getOriginalInstance().filename : ""); + String commandname = (myState!=null ? myState.getOriginalInstance().commandname : ""); + int i=filename.lastIndexOf('/'); + if (i>=0) filename=filename.substring(i+1); + i=filename.lastIndexOf('\\'); + if (i>=0) filename=filename.substring(i+1); + int n=filename.length(); + if (n>4 && filename.substring(n-4).equalsIgnoreCase(".als")) filename=filename.substring(0,n-4); + if (filename.length()>0) return "("+filename+") "+commandname; else return commandname; + } + + /** Helper method that inserts "filename" into the "recently opened THEME file list". */ + private void addThemeHistory(String filename) { + String name0=Theme0.get(), name1=Theme1.get(), name2=Theme2.get(); + if (name0.equals(filename)) return; else {Theme0.set(filename); Theme1.set(name0);} + if (name1.equals(filename)) return; else Theme2.set(name1); + if (name2.equals(filename)) return; else Theme3.set(name2); + } + + /** Helper method returns a JTextArea containing the given text. */ + private JComponent getTextComponent(String text) { + final JTextArea ta = OurUtil.textarea(text, 10, 10, false, true); + final JScrollPane ans = new JScrollPane(ta, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED) { + private static final long serialVersionUID = 0; + @Override public void setFont(Font font) { ta.setFont(font); } + }; + ans.setBorder(new OurBorder(true, false, true, false)); + return ans; + } + +// /** Helper method that reads a file and then return a JTextArea containing it. */ +// private JComponent getTextComponentFromFile(String filename) { +// String text = ""; +// try { text="\n"+Util.readAll(filename); } catch(IOException ex) { text="# Error reading from "+filename; } +// return getTextComponent(text); +// } + + /** Returns the GraphViewer that contains the graph; can be null if the graph hasn't been loaded yet. */ + public GraphViewer getViewer() { + if (null == myGraphPanel) return null; + return myGraphPanel.alloyGetViewer(); + } + + /** Load the XML instance. */ + public void loadXML(final String fileName, boolean forcefully) { + final String xmlFileName = Util.canon(fileName); + File f = new File(xmlFileName); + if (forcefully || !xmlFileName.equals(this.xmlFileName)) { + AlloyInstance myInstance; + try { + if (!f.exists()) throw new IOException("File " + xmlFileName + " does not exist."); + myInstance = StaticInstanceReader.parseInstance(f); + } catch (Throwable e) { + xmlLoaded.remove(fileName); + xmlLoaded.remove(xmlFileName); + OurDialog.alert("Cannot read or parse Alloy instance: "+xmlFileName+"\n\nError: "+e.getMessage()); + if (xmlLoaded.size()>0) { loadXML(xmlLoaded.get(xmlLoaded.size()-1), false); return; } + doCloseAll(); + return; + } + if (myState==null) myState=new VizState(myInstance); else myState.loadInstance(myInstance); + repopulateProjectionPopup(); + xml2title.put(xmlFileName, makeVizTitle()); + this.xmlFileName = xmlFileName; + } + if (!xmlLoaded.contains(xmlFileName)) xmlLoaded.add(xmlFileName); + toolbar.setEnabled(true); + settingsOpen=0; + thememenu.setEnabled(true); + windowmenu.setEnabled(true); + if (frame!=null) { + frame.setVisible(true); + frame.setTitle("Alloy Visualizer "+Version.version()+" loading... Please wait..."); + OurUtil.show(frame); + } + updateDisplay(); + } + + /** This method loads a specific theme file. */ + public boolean loadThemeFile(String filename) { + if (myState==null) return false; // Can only load if there is a VizState loaded + filename = Util.canon(filename); + try { + myState.loadPaletteXML(filename); + } catch (IOException ex) { + OurDialog.alert("Error: " + ex.getMessage()); + return false; + } + repopulateProjectionPopup(); + if (myCustomPanel!=null) myCustomPanel.remakeAll(); + if (myGraphPanel!=null) myGraphPanel.remakeAll(); + addThemeHistory(filename); + thmFileName=filename; + updateDisplay(); + return true; + } + + /** This method saves a specific current theme (if filename==null, it asks the user); returns true if it succeeded. */ + public boolean saveThemeFile(String filename) { + if (myState==null) return false; // Can only save if there is a VizState loaded + if (filename==null) { + File file=OurDialog.askFile(false, null, ".thm", ".thm theme files"); + if (file==null) return false; + if (file.exists()) if (!OurDialog.askOverwrite(Util.canon(file.getPath()))) return false; + Util.setCurrentDirectory(file.getParentFile()); + filename = file.getPath(); + } + filename = Util.canon(filename); + try { + myState.savePaletteXML(filename); + filename = Util.canon(filename); // Since the canon name may have changed + addThemeHistory(filename); + } catch (Throwable er) { + OurDialog.alert("Error saving the theme.\n\nError: " + er.getMessage()); + return false; + } + thmFileName = filename; + return true; + } + + //========================================= EVENTS ============================================================================================ + + /** This method changes the font size for everything (except the graph) */ + public void doSetFontSize(int fontSize) { + this.fontSize = fontSize; + if (!(content instanceof VizGraphPanel)) updateDisplay(); else content.setFont(OurUtil.getVizFont().deriveFont((float)fontSize)); + } + + /** This method asks the user for a new XML instance file to load. */ + private Runner doLoad() { + if (wrap) return wrapMe(); + File file=OurDialog.askFile(true, null, ".xml", ".xml instance files"); + if (file==null) return null; + Util.setCurrentDirectory(file.getParentFile()); + loadXML(file.getPath(), true); + return null; + } + + /** This method loads a new XML instance file if it's not the current file. */ + private Runner doLoadInstance(String fileName) { + if (!wrap) loadXML(fileName, false); + return wrapMe(fileName); + } + + /** This method closes the current instance; if there are previously loaded files, we will load one of them; + * otherwise, this window will set itself as invisible (if not in standalone mode), + * or it will terminate the entire application (if in standalone mode). + */ + private Runner doClose() { + if (wrap) return wrapMe(); + xmlLoaded.remove(xmlFileName); + if (xmlLoaded.size()>0) { doLoadInstance(xmlLoaded.get(xmlLoaded.size()-1)); return null; } + if (standalone) System.exit(0); else if (frame!=null) frame.setVisible(false); + return null; + } + + /** This method closes every XML file. + * If in standalone mode, the JVM will then shutdown, otherwise it will just set the window invisible. + */ + private Runner doCloseAll() { + if (wrap) return wrapMe(); + xmlLoaded.clear(); + xmlFileName=""; + if (standalone) System.exit(0); else if (frame!=null) frame.setVisible(false); + return null; + } + + /** This method refreshes the "theme" menu. */ + private Runner doRefreshTheme() { + if (wrap) return wrapMe(); + String defaultTheme = System.getProperty("alloy.theme0"); + thememenu.removeAll(); + try { + wrap=true; + menuItem(thememenu, "Load Theme...", 'L', doLoadTheme()); + if (defaultTheme!=null && defaultTheme.length()>0 && (new File(defaultTheme)).isDirectory()) + menuItem(thememenu, "Load Sample Theme...", 'B', doLoadSampleTheme()); + menuItem(thememenu, "Save Theme", 'S', doSaveTheme()); + menuItem(thememenu, "Save Theme As...", 'A', doSaveThemeAs()); + menuItem(thememenu, "Reset Theme", 'R', doResetTheme()); + } finally { + wrap=false; + } + return null; + } + + /** This method asks the user for a new theme file to load. */ + private Runner doLoadTheme() { + if (wrap) return wrapMe(); + String defaultTheme=System.getProperty("alloy.theme0"); + if (defaultTheme==null) defaultTheme=""; + if (myState==null) return null; // Can only load if there is a VizState loaded + if (myState.changedSinceLastSave()) { + char opt = OurDialog.askSaveDiscardCancel("The current theme"); + if (opt=='c') return null; + if (opt=='s' && !saveThemeFile(thmFileName.length()==0 ? null : thmFileName)) return null; + } + File file=OurDialog.askFile(true, null, ".thm", ".thm theme files"); + if (file!=null) { Util.setCurrentDirectory(file.getParentFile()); loadThemeFile(file.getPath()); } + return null; + } + + /** This method asks the user for a new theme file (from the default Alloy4 distribution) to load. */ + private Runner doLoadSampleTheme() { + if (wrap) return wrapMe(); + String defaultTheme=System.getProperty("alloy.theme0"); + if (defaultTheme==null) defaultTheme=""; + if (myState==null) return null; // Can only load if there is a VizState loaded + if (myState.changedSinceLastSave()) { + char opt = OurDialog.askSaveDiscardCancel("The current theme"); + if (opt=='c') return null; + if (opt=='s' && !saveThemeFile(thmFileName.length()==0 ? null : thmFileName)) return null; + } + File file=OurDialog.askFile(true, defaultTheme, ".thm", ".thm theme files"); + if (file!=null) loadThemeFile(file.getPath()); + return null; + } + + /** This method saves the current theme. */ + private Runner doSaveTheme() { + if (!wrap) saveThemeFile(thmFileName.length()==0 ? null : thmFileName); + return wrapMe(); + } + + /** This method saves the current theme to a new ".thm" file. */ + private Runner doSaveThemeAs() { + if (wrap) return wrapMe(); + File file=OurDialog.askFile(false, null, ".thm", ".thm theme files"); + if (file==null) return null; + if (file.exists()) if (!OurDialog.askOverwrite(Util.canon(file.getPath()))) return null; + Util.setCurrentDirectory(file.getParentFile()); + saveThemeFile(file.getPath()); + return null; + } + + private Runner doExportDot() { + if (wrap) return wrapMe(); + File file=OurDialog.askFile(false, null, ".dot", ".dot graph files"); + if (file==null) return null; + if (file.exists()) if (!OurDialog.askOverwrite(Util.canon(file.getPath()))) return null; + Util.setCurrentDirectory(file.getParentFile()); + String filename = Util.canon(file.getPath()); + try { + Util.writeAll(filename, myGraphPanel.toDot()); + } catch (Throwable er) { + OurDialog.alert("Error saving the theme.\n\nError: " + er.getMessage()); + } + return null; + } + + private Runner doExportXml() { + if (wrap) return wrapMe(); + File file=OurDialog.askFile(false, null, ".xml", ".xml XML files"); + if (file==null) return null; + if (file.exists()) if (!OurDialog.askOverwrite(Util.canon(file.getPath()))) return null; + Util.setCurrentDirectory(file.getParentFile()); + String filename = Util.canon(file.getPath()); + try { + Util.writeAll(filename, Util.readAll(xmlFileName)); + } catch (Throwable er) { + OurDialog.alert("Error saving XML instance.\n\nError: " + er.getMessage()); + } + return null; + } + + /** This method resets the current theme. */ + private Runner doResetTheme() { + if (wrap) return wrapMe(); + if (myState==null) return null; + if (!OurDialog.yesno("Are you sure you wish to clear all your customizations?", "Yes, clear them", "No, keep them")) return null; + myState.resetTheme(); + repopulateProjectionPopup(); + if (myCustomPanel!=null) myCustomPanel.remakeAll(); + if (myGraphPanel!=null) myGraphPanel.remakeAll(); + thmFileName=""; + updateDisplay(); + return null; + } + + /** This method modifies the theme using a set of heuristics. */ + private Runner doMagicLayout() { + if (wrap) return wrapMe(); + if (myState==null) return null; + if (!OurDialog.yesno("This will clear your original customizations. Are you sure?", "Yes, clear them", "No, keep them")) return null; + myState.resetTheme(); + try { MagicLayout.magic(myState); MagicColor.magic(myState); } catch(Throwable ex) { } + repopulateProjectionPopup(); + if (myCustomPanel!=null) myCustomPanel.remakeAll(); + if (myGraphPanel!=null) myGraphPanel.remakeAll(); + updateDisplay(); + return null; + } + + /** This method refreshes the "window" menu. */ + private Runner doRefreshWindow() { + if (wrap) return wrapMe(); + windowmenu.removeAll(); + try { + wrap=true; + for(final String f:getInstances()) { + JMenuItem it = new JMenuItem("Instance: "+getInstanceTitle(f), null); + it.setIcon(f.equals(getXMLfilename())?iconYes:iconNo); + it.addActionListener(doLoadInstance(f)); + windowmenu.add(it); + } + } finally { + wrap=false; + } + return null; + } + + /** This method inserts "Minimize" and "Maximize" entries into a JMenu. */ + public void addMinMaxActions(JMenu menu) { + try { + wrap=true; + menuItem(menu, "Minimize", 'M', doMinimize(), iconNo); + menuItem(menu, "Zoom", doZoom(), iconNo); + } finally { + wrap=false; + } + } + + /** This method minimizes the window. */ + private Runner doMinimize() { + if (!wrap && frame!=null) OurUtil.minimize(frame); + return wrapMe(); + } + + /** This method alternatingly maximizes or restores the window. */ + private Runner doZoom() { + if (!wrap && frame!=null) OurUtil.zoom(frame); + return wrapMe(); + } + + /** This method attempts to derive the next satisfying instance. */ + private Runner doNext() { + if (wrap) return wrapMe(); + if (settingsOpen!=0) return null; + if (xmlFileName.length()==0) { + OurDialog.alert("Cannot display the next solution since no instance is currently loaded."); + } else if (enumerator==null) { + OurDialog.alert("Cannot display the next solution since the analysis engine is not loaded with the visualizer."); + } else { + try { enumerator.compute(xmlFileName); } catch(Throwable ex) { OurDialog.alert(ex.getMessage()); } + } + return null; + } + + /** This method updates the graph with the current theme customization. */ + private Runner doApply() { + if (!wrap) updateDisplay(); + return wrapMe(); + } + + /** This method opens the theme customization panel if closed. */ + private Runner doOpenThemePanel() { + if (!wrap) { settingsOpen=1; updateDisplay(); } + return wrapMe(); + } + + /** This method closes the theme customization panel if open. */ + private Runner doCloseThemePanel() { + if (!wrap) { settingsOpen=0; updateDisplay(); } + return wrapMe(); + } + + /** This method opens the evaluator panel if closed. */ + private Runner doOpenEvalPanel() { + if (!wrap) { settingsOpen=2; updateDisplay(); } + return wrapMe(); + } + + /** This method closes the evaluator panel if open. */ + private Runner doCloseEvalPanel() { + if (!wrap) { settingsOpen=0; updateDisplay(); } + return wrapMe(); + } + + /** This method changes the display mode to show the instance as a graph (the return value is always null). */ + public Runner doShowViz() { + if (!wrap) { currentMode=VisualizerMode.Viz; updateDisplay(); return null; } + return wrapMe(); + } + + /** This method changes the display mode to show the instance as a tree (the return value is always null). */ + public Runner doShowTree() { + if (!wrap) { currentMode=VisualizerMode.Tree; updateDisplay(); return null; } + return wrapMe(); + } + + /** + * This method changes the display mode to show the equivalent dot text (the + * return value is always null). + */ + public Runner doShowTxt() { + if (!wrap) { currentMode = VisualizerMode.TEXT; updateDisplay(); return null; } + return wrapMe(); + } + +// /** This method changes the display mode to show the equivalent dot text (the return value is always null). */ +// public Runner doShowDot() { +// if (!wrap) { currentMode=VisualizerMode.DOT; updateDisplay(); return null; } +// return wrapMe(); +// } +// +// /** This method changes the display mode to show the instance as XML (the return value is always null). */ +// public Runner doShowXML() { +// if (!wrap) { currentMode=VisualizerMode.XML; updateDisplay(); return null; } +// return wrapMe(); +// } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/VizGraphPanel.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/VizGraphPanel.java new file mode 100644 index 00000000..1d96dc91 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/VizGraphPanel.java @@ -0,0 +1,366 @@ +/* + * Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4viz; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTextArea; +import javax.swing.SwingConstants; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; + +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.OurBorder; +import edu.mit.csail.sdg.alloy4.OurCombobox; +import edu.mit.csail.sdg.alloy4.OurUtil; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4graph.GraphViewer; + +/** + * GUI panel that houses the actual graph, as well as any projection comboboxes. + * + *

+ * Thread Safety: Can be called only by the AWT event thread. + */ + +public final class VizGraphPanel extends JPanel { + + /** Inner class that displays a combo box of possible projection atom choices. */ + final class TypePanel extends JPanel { + /** This ensures the class can be serialized reliably. */ + private static final long serialVersionUID = 0; + /** The type being projected. */ + private final AlloyType type; + /** + * The list of atoms; can be an empty list if there are no atoms in this type to be projected. + */ + private final List atoms; + /** The list of atom names; atomnames.empty() iff atoms.isEmpty() */ + private final String[] atomnames; + /** The combo box showing the possible atoms to choose from. */ + private final JComboBox atomCombo; + + /** + * Constructs a new TypePanel. + * + * @param type - the type being projected + * @param atoms - the list of possible projection atom choices + */ + private TypePanel(final AlloyType type, List atoms, final AlloyAtom initialValue) { + super(); + final JButton left, right; + int initialIndex = 0; + this.type = type; + atoms = new ArrayList(atoms); + Collections.sort(atoms); + this.atoms = ConstList.make(atoms); + this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); + this.setBorder(null); + this.atomnames = new String[this.atoms.size()]; + for (int i = 0; i < this.atoms.size(); i++) { + this.atomnames[i] = this.atoms.get(i).getVizName(VizGraphPanel.this.vizState, true); + if (this.atoms.get(i).equals(initialValue)) { + initialIndex = i; + } + } + this.add(left = new JButton("<<")); + this.add(Box.createRigidArea(new Dimension(2, 2))); + this.add(this.atomCombo = + new OurCombobox(this.atomnames.length < 1 ? new String[] {" "} : this.atomnames)); + this.add(Box.createRigidArea(new Dimension(2, 2))); + this.add(right = new JButton(">>")); + left.setVerticalAlignment(SwingConstants.CENTER); + right.setVerticalAlignment(SwingConstants.CENTER); + final Dimension dim = this.atomCombo.getPreferredSize(); + final int idealWidth = Util.onMac() ? 120 : 80; + if (dim.width < idealWidth) { + dim.width = idealWidth + 20; + this.atomCombo.setMinimumSize(dim); + this.atomCombo.setPreferredSize(dim); + } + left.setEnabled(initialIndex > 0); + right.setEnabled(initialIndex < this.atomnames.length - 1); + this.atomCombo.setSelectedIndex(initialIndex); + if (Util.onMac()) { + this.atomCombo.setBorder(BorderFactory.createEmptyBorder(4, 1, 0, 1)); + } + left.addActionListener(new ActionListener() { + @Override + public final void actionPerformed(final ActionEvent e) { + final int curIndex = TypePanel.this.atomCombo.getSelectedIndex(); + if (curIndex > 0) { + TypePanel.this.atomCombo.setSelectedIndex(curIndex - 1); + } + } + }); + right.addActionListener(new ActionListener() { + @Override + public final void actionPerformed(final ActionEvent e) { + final int curIndex = TypePanel.this.atomCombo.getSelectedIndex(); + if (curIndex < TypePanel.this.atomCombo.getItemCount() - 1) { + TypePanel.this.atomCombo.setSelectedIndex(curIndex + 1); + } + } + }); + this.atomCombo.addActionListener(new ActionListener() { + @Override + public final void actionPerformed(final ActionEvent e) { + left.setEnabled(TypePanel.this.atomCombo.getSelectedIndex() > 0); + right.setEnabled( + TypePanel.this.atomCombo.getSelectedIndex() < TypePanel.this.atomnames.length - 1); + VizGraphPanel.this.remakeAll(); + VizGraphPanel.this.getParent().invalidate(); + VizGraphPanel.this.getParent().repaint(); + } + }); + } + + /** Returns the currently-selected atom; returns null if the list is empty. */ + public AlloyAtom getAlloyAtom() { + final int i = this.atomCombo.getSelectedIndex(); + if (i >= 0 && i < this.atoms.size()) { + return this.atoms.get(i); + } else { + return null; + } + } + + /** Returns the entire list of atoms; could be an empty set. */ + public List getAlloyAtoms() { + return this.atoms; + } + + /** Returns the AlloyType associated with this TypePanel. */ + public AlloyType getAlloyType() { + return this.type; + } + + /** True if this TypePanel object does not need to be rebuilt. */ + private boolean upToDate(final AlloyType type, List atoms) { + if (!this.type.equals(type)) { + return false; + } + atoms = new ArrayList(atoms); + Collections.sort(atoms); + if (!this.atoms.equals(atoms)) { + return false; + } + for (int i = 0; i < this.atoms.size(); i++) { + final String n = this.atoms.get(i).getVizName(VizGraphPanel.this.vizState, true); + if (!this.atomnames[i].equals(n)) { + return false; + } + } + return true; + } + } + + /** This ensures the class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** This is the current customization settings. */ + private final VizState vizState; + + /** Whether the user wants to see the DOT source code or not. */ + private boolean seeDot = false; + + /** The current GraphViewer (or null if we are not looking at a GraphViewer) */ + private GraphViewer viewer = null; + + /** The scrollpane containing the upperhalf of the panel (showing the graph) */ + private final JScrollPane diagramScrollPanel; + + /** The upperhalf of the panel (showing the graph). */ + private final JPanel graphPanel; + + /** The lowerhalf of the panel (showing the comboboxes for choosing the projected atoms). */ + private final JPanel navPanel; + + /** The splitpane separating the graphPanel and the navPanel. */ + private final JSplitPane split; + + /** The current projection choice; null if no projection is in effect. */ + private AlloyProjection currentProjection = null; + + /** This is the list of TypePanel(s) we've already constructed. */ + private final Map type2panel = new TreeMap(); + + /** + * Create a splitpane showing the graph on top, as well as projection comboboxes on the bottom. + * + * @param vizState - the current visualization settings + * @param seeDot - true if we want to see the DOT source code, false if we want it rendered as a + * graph + */ + public VizGraphPanel(final VizState vizState, final boolean seeDot) { + final Border b = new EmptyBorder(0, 0, 0, 0); + OurUtil.make(this, Color.BLACK, Color.WHITE, b); + this.seeDot = seeDot; + this.vizState = vizState; + this.setLayout(new GridLayout()); + this.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE)); + this.navPanel = new JPanel(); + final JScrollPane navscroll = OurUtil.scrollpane(this.navPanel); + this.graphPanel = OurUtil.make(new JPanel(), Color.BLACK, Color.WHITE, b); + // graphPanel.addMouseListener(new MouseAdapter() { + // @Override public void mousePressed(MouseEvent ev) { + // // We let Ctrl+LeftClick bring up the popup menu, just like RightClick, + // // since many Mac mouses do not have a right button. + // if (viewer==null) return; + // else if (ev.getButton()==MouseEvent.BUTTON3) { } + // else if (ev.getButton()==MouseEvent.BUTTON1 && ev.isControlDown()) { } + // else return; + // viewer.alloyPopup(graphPanel, ev.getX(), ev.getY()); + // } + // }); + this.diagramScrollPanel = + OurUtil.scrollpane(this.graphPanel, new OurBorder(true, true, true, false)); + this.diagramScrollPanel.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() { + @Override + public void adjustmentValueChanged(final AdjustmentEvent e) { + VizGraphPanel.this.diagramScrollPanel.invalidate(); + VizGraphPanel.this.diagramScrollPanel.repaint(); + VizGraphPanel.this.diagramScrollPanel.validate(); + } + }); + this.diagramScrollPanel.getHorizontalScrollBar() + .addAdjustmentListener(new AdjustmentListener() { + @Override + public void adjustmentValueChanged(final AdjustmentEvent e) { + VizGraphPanel.this.diagramScrollPanel.invalidate(); + VizGraphPanel.this.diagramScrollPanel.repaint(); + VizGraphPanel.this.diagramScrollPanel.validate(); + } + }); + this.split = + OurUtil.splitpane(JSplitPane.VERTICAL_SPLIT, this.diagramScrollPanel, navscroll, 0); + this.split.setResizeWeight(1.0); + this.split.setDividerSize(0); + this.add(this.split); + this.remakeAll(); + } + + /** + * Retrieves the actual GraphViewer object that contains the graph (or null if the graph hasn't + * loaded yet) + */ + public GraphViewer alloyGetViewer() { + return this.viewer; + } + + public JPanel getGraphPanel() { + return this.graphPanel; + } + + /** We override the paint method to auto-resize the divider. */ + @Override + public void paint(final Graphics g) { + super.paint(g); + this.split.setDividerLocation(this.split.getSize().height - this.split.getInsets().bottom + - this.split.getDividerSize() - this.split.getRightComponent().getPreferredSize().height); + } + + /** Regenerate the comboboxes and the graph. */ + public void remakeAll() { + final Map map = new LinkedHashMap(); + this.navPanel.removeAll(); + for (final AlloyType type : this.vizState.getProjectedTypes()) { + final List atoms = this.vizState.getOriginalInstance().type2atoms(type); + TypePanel tp = this.type2panel.get(type); + if (tp != null && tp.getAlloyAtom() != null && !atoms.contains(tp.getAlloyAtom())) { + tp = null; + } + if (tp != null && tp.getAlloyAtom() == null && atoms.size() > 0) { + tp = null; + } + if (tp != null && !tp.upToDate(type, atoms)) { + tp = null; + } + if (tp == null) { + this.type2panel.put(type, tp = new TypePanel(type, atoms, null)); + } + this.navPanel.add(tp); + map.put(tp.getAlloyType(), tp.getAlloyAtom()); + } + this.currentProjection = new AlloyProjection(map); + final JPanel graph = this.vizState.getGraph(this.currentProjection); + if (this.seeDot && graph instanceof GraphViewer) { + this.viewer = null; + final JTextArea txt = OurUtil.textarea(graph.toString(), 10, 10, false, true, this.getFont()); + this.diagramScrollPanel.setViewportView(txt); + } else { + if (graph instanceof GraphViewer) { + this.viewer = (GraphViewer) graph; + } else { + this.viewer = null; + } + this.graphPanel.removeAll(); + this.graphPanel.add(graph); + this.diagramScrollPanel.setViewportView(this.graphPanel); + this.diagramScrollPanel.invalidate(); + this.diagramScrollPanel.repaint(); + this.diagramScrollPanel.validate(); + } + } + + /** Changes whether we are seeing the DOT source or not. */ + public void seeDot(final boolean yesOrNo) { + if (this.seeDot == yesOrNo) { + return; + } + this.seeDot = yesOrNo; + this.remakeAll(); + } + + /** Changes the font. */ + @Override + public void setFont(final Font font) { + super.setFont(font); + if (this.diagramScrollPanel != null) { + this.diagramScrollPanel.getViewport().getView().setFont(font); + } + } + + public String toDot() { + return this.vizState.getGraph(this.currentProjection).toString(); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/VizState.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/VizState.java new file mode 100644 index 00000000..9569139f --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/VizState.java @@ -0,0 +1,448 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4viz; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.Set; +import java.util.TreeSet; +import javax.swing.Icon; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import edu.mit.csail.sdg.alloy4.ConstSet; +import edu.mit.csail.sdg.alloy4.MailBug; +import edu.mit.csail.sdg.alloy4.OurCheckbox; +import edu.mit.csail.sdg.alloy4.OurUtil; +import edu.mit.csail.sdg.alloy4graph.DotColor; +import edu.mit.csail.sdg.alloy4graph.DotPalette; +import edu.mit.csail.sdg.alloy4graph.DotShape; +import edu.mit.csail.sdg.alloy4graph.DotStyle; + +/** Mutable; this stores an unprojected model as well as the current theme customization. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final class VizState { + + /** Construct a new VizState (with default theme settings) for the given instance; if world!=null, it is the root of the AST. + */ + public VizState(AlloyInstance originalInstance) { + this.originalInstance = originalInstance; + this.currentModel = originalInstance.model; + resetTheme(); + loadInstance(originalInstance); + } + + /** Make a copy of an existing VizState object. */ + public VizState(VizState old) { + originalInstance = old.originalInstance; + currentModel = old.currentModel; + projectedTypes = new TreeSet(old.projectedTypes); + useOriginalNames = old.useOriginalNames; + hidePrivate = old.hidePrivate; + hideMeta = old.hideMeta; + fontSize = old.fontSize; + nodePalette = old.nodePalette; + edgePalette = old.edgePalette; + nodeColor.putAll(old.nodeColor); + nodeStyle.putAll(old.nodeStyle); + nodeVisible.putAll(old.nodeVisible); + label.putAll(old.label); + number.putAll(old.number); + hideUnconnected.putAll(old.hideUnconnected); + showAsAttr.putAll(old.showAsAttr); + showAsLabel.putAll(old.showAsLabel); + shape.putAll(old.shape); + weight.putAll(old.weight); + attribute.putAll(old.attribute); + mergeArrows.putAll(old.mergeArrows); + constraint.putAll(old.constraint); + layoutBack.putAll(old.layoutBack); + edgeColor.putAll(old.edgeColor); + edgeStyle.putAll(old.edgeStyle); + edgeVisible.putAll(old.edgeVisible); + changedSinceLastSave = false; + } + + /** Clears the current theme. */ + public void resetTheme() { + currentModel = originalInstance.model; + projectedTypes.clear(); + useOriginalNames = false; + hidePrivate = true; + hideMeta = true; + fontSize = 12; + nodePalette = DotPalette.CLASSIC; + edgePalette = DotPalette.CLASSIC; + nodeColor.clear(); nodeColor.put(null, DotColor.WHITE); + nodeStyle.clear(); nodeStyle.put(null, DotStyle.SOLID); + nodeVisible.clear(); nodeVisible.put(null, true); + label.clear(); label.put(null, ""); + number.clear(); number.put(null, true); + hideUnconnected.clear(); hideUnconnected.put(null, false); + showAsAttr.clear(); showAsAttr.put(null, false); + showAsLabel.clear(); showAsLabel.put(null, true); + shape.clear(); shape.put(null, DotShape.ELLIPSE); + weight.clear(); weight.put(null, 0); + attribute.clear(); attribute.put(null, false); + mergeArrows.clear(); mergeArrows.put(null, true); + constraint.clear(); constraint.put(null, true); + layoutBack.clear(); layoutBack.put(null, false); + edgeColor.clear(); edgeColor.put(null, DotColor.MAGIC); + edgeStyle.clear(); edgeStyle.put(null, DotStyle.SOLID); + edgeVisible.clear(); edgeVisible.put(null, true); + // Provide some nice defaults for "Int" and "seq/Int" type + AlloyType sigint=AlloyType.INT; + label.put(sigint,""); + number.put(sigint,true); + hideUnconnected.put(sigint,true); + AlloyType seqidx=AlloyType.SEQINT; + label.put(seqidx,""); + number.put(seqidx,true); + hideUnconnected.put(seqidx,true); + // Provide some nice defaults for meta model stuff + AlloyType set=AlloyType.SET; + AlloyRelation ext=AlloyRelation.EXTENDS, in=AlloyRelation.IN; + shape.put(null,DotShape.BOX); nodeColor.put(null,DotColor.YELLOW); nodeStyle.put(null,DotStyle.SOLID); + shape.put(set,DotShape.ELLIPSE); nodeColor.put(set,DotColor.BLUE); label.put(set,""); + edgeColor.put(ext,DotColor.BLACK); weight.put(ext,100); layoutBack.put(ext,true); + edgeColor.put(in,DotColor.BLACK); weight.put(in,100); layoutBack.put(in,true); + // Done + cache.clear(); + changedSinceLastSave=false; + } + + /** Load a new instance into this VizState object (the input argument is treated as a new unprojected instance); + * if world!=null, it is the root of the AST + */ + public void loadInstance(AlloyInstance unprojectedInstance) { + this.originalInstance=unprojectedInstance; + for (AlloyType t:getProjectedTypes()) if (!unprojectedInstance.model.hasType(t)) projectedTypes.remove(t); + currentModel = StaticProjector.project(unprojectedInstance.model, projectedTypes); + cache.clear(); + } + + /** Erase the current theme customizations and then load it from a file. + * @throws IOException - if an error occurred + */ + public void loadPaletteXML(String filename) throws IOException { + resetTheme(); + StaticThemeReaderWriter.readAlloy(filename,this); + cache.clear(); + changedSinceLastSave=false; + } + + /** Saves the current theme to a file (which will be overwritten if it exists already). + * @throws IOException - if an error occurred + */ + public void savePaletteXML(String filename) throws IOException { + StaticThemeReaderWriter.writeAlloy(filename,this); + changedSinceLastSave=false; + } + + /** Caches previously generated graphs. */ + private LinkedHashMap cache=new LinkedHashMap(); + + /** Generate a VizGraphPanel for a given projection choice, using the current settings. */ + public JPanel getGraph(AlloyProjection projectionChoice) { + JPanel ans = cache.get(projectionChoice); + if (ans!=null) return ans; + AlloyInstance inst = originalInstance; + try { + ans = StaticGraphMaker.produceGraph(inst, this, projectionChoice); + cache.put(projectionChoice, ans); + } catch(Throwable ex) { + String msg = "An error has occurred: " + ex + "\n\nStackTrace:\n" + MailBug.dump(ex) + "\n"; + JScrollPane scroll = OurUtil.scrollpane(OurUtil.textarea(msg, 0, 0, false, false)); + ans = new JPanel(); + ans.setLayout(new BorderLayout()); + ans.add(scroll, BorderLayout.CENTER); + ans.setBackground(Color.WHITE); + } + ans.setBorder(null); + return ans; + } + + /** True if the theme has been modified since last save. */ + private boolean changedSinceLastSave=false; + + /** True if the theme has been modified since last save. */ + public boolean changedSinceLastSave() { return changedSinceLastSave; } + + /** Sets the "changed since last save" flag, then flush any cached generated graphs. */ + private void change() { changedSinceLastSave=true; cache.clear(); } + + /** If oldValue is different from newValue, then sets the "changed since last save" flag and flush the cache. */ + private void changeIf(Object oldValue, Object newValue) { + if (oldValue==null) { if (newValue==null) return; } else { if (oldValue.equals(newValue)) return; } + change(); + } + + /*============================================================================================*/ + + /** If x is an AlloyType, x is not univ, then return its parent (which could be univ); + * If x is an AlloySet, then return x's type; + * All else, return null. + */ + private AlloyType parent(AlloyElement x, AlloyModel model) { + if (x instanceof AlloySet) return ((AlloySet)x).getType(); + if (x instanceof AlloyType) return model.getSuperType((AlloyType)x); + return null; + } + + /*============================================================================================*/ + + /** The original unprojected instance. */ + private AlloyInstance originalInstance; + + /** Returns the original unprojected model. */ + public AlloyInstance getOriginalInstance() { return originalInstance; } + + /** Returns the original unprojected model. */ + public AlloyModel getOriginalModel() { return originalInstance.model; } + + /*============================================================================================*/ + + /** The current (possibly projected) model. */ + private AlloyModel currentModel; + + /** Returns the current (possibly projected) model. */ + public AlloyModel getCurrentModel() { return currentModel; } + + /*============================================================================================*/ + + /** The set of types we are currently projecting over. */ + private Set projectedTypes = new TreeSet(); + + /** Gets an unmodifiable copy of the set of types we are currently projecting over. */ + public ConstSet getProjectedTypes() { return ConstSet.make(projectedTypes); } + + /** Returns true iff the type is not univ, and it is a toplevel type. */ + public boolean canProject(final AlloyType type) { return isTopLevel(type); } + + /** Returns true iff the type is not univ, and it is a toplevel type. */ + public boolean isTopLevel(final AlloyType type) { + return AlloyType.UNIV.equals(originalInstance.model.getSuperType(type)); + } + + /** Adds type to the list of projected types if it's a toplevel type. */ + public void project(AlloyType type) { + if (canProject(type)) if (projectedTypes.add(type)) { + currentModel = StaticProjector.project(originalInstance.model, projectedTypes); + change(); + } + } + + /** Removes type from the list of projected types if it is currently projected. */ + public void deproject(AlloyType type) { + if (projectedTypes.remove(type)) { + currentModel = StaticProjector.project(originalInstance.model, projectedTypes); + change(); + } + } + + /** Removes every entry from the list of projected types. */ + public void deprojectAll() { + if (projectedTypes.size()>0) { + projectedTypes.clear(); + currentModel = StaticProjector.project(originalInstance.model, projectedTypes); + change(); + } + } + + /*============================================================================================*/ + + /** Whether to use the original atom names. */ + private boolean useOriginalNames = false; + + /** Returns whether we will use original atom names. */ + public boolean useOriginalName() { return useOriginalNames; } + + /** Sets whether we will use original atom names or not. */ + public void useOriginalName(Boolean newValue) { + if (newValue!=null && useOriginalNames!=newValue) { change(); useOriginalNames=newValue; } + } + + /*============================================================================================*/ + + /** Whether to hide private sigs/fields/relations. */ + private boolean hidePrivate = false; + + /** Returns whether we will hide private sigs/fields/relations. */ + public boolean hidePrivate() { return hidePrivate; } + + /** Sets whether we will hide private sigs/fields/relations. */ + public void hidePrivate(Boolean newValue) { + if (newValue!=null && hidePrivate!=newValue) { change(); hidePrivate=newValue; } + } + + /*============================================================================================*/ + + /** Whether to hide meta sigs/fields/relations. */ + private boolean hideMeta = true; + + /** Returns whether we will hide meta sigs/fields/relations. */ + public boolean hideMeta() { return hideMeta; } + + /** Sets whether we will hide meta sigs/fields/relations. */ + public void hideMeta(Boolean newValue) { + if (newValue!=null && hideMeta!=newValue) { change(); hideMeta=newValue; } + } + + /*============================================================================================*/ + + /** The graph's font size. */ + private int fontSize = 12; + + /** Returns the font size. */ + public int getFontSize() { return fontSize; } + + /** Sets the font size. */ + public void setFontSize(int n) { if (fontSize!=n && fontSize>0) { change(); fontSize=n; } } + + /*============================================================================================*/ + + /** The default node palette. */ + private DotPalette nodePalette; + + /** Gets the default node palette. */ + public DotPalette getNodePalette() { return nodePalette; } + + /** Sets the default node palette. */ + public void setNodePalette(DotPalette x) { + if (nodePalette!=x && x!=null) {change(); nodePalette=x;} + } + + /*============================================================================================*/ + + /** The default edge palette. */ + private DotPalette edgePalette; + + /** Gets the default edge palette. */ + public DotPalette getEdgePalette() { return edgePalette; } + + /** Sets the default edge palette. */ + public void setEdgePalette(DotPalette x) { + if (edgePalette!=x && x!=null) {change(); edgePalette=x;} + } + + /*============================================================================================*/ + + + // An important invariant to maintain: every map here must map null to a nonnull value. + public final MInt weight = new MInt(); + public final MString label = new MString(); + public final MMap nodeColor = new MMap(); + public final MMap edgeColor = new MMap(); + public final MMap nodeStyle = new MMap(); + public final MMap edgeStyle = new MMap(); + public final MMap shape = new MMap(); + public final MMap attribute = new MMap(true, false); + public final MMap mergeArrows = new MMap(true, false); + public final MMap constraint = new MMap(true, false); + public final MMap layoutBack = new MMap(true, false); + public final MMap edgeVisible = new MMap(true, false); + public final MMap nodeVisible = new MMap(true, false); + public final MMap number = new MMap(true, false); + public final MMap hideUnconnected = new MMap(true, false); + public final MMap showAsAttr = new MMap(true, false); + public final MMap showAsLabel = new MMap(true, false); + + public final class MInt { + private final LinkedHashMap map = new LinkedHashMap(); + private MInt() { } + private void clear() { map.clear(); change(); } + private void putAll(MInt x) { map.putAll(x.map); change(); } + public int get(AlloyElement x) { Integer ans=map.get(x); if (ans==null) return 0; else return ans; } + public void put(AlloyElement x, Integer v) { if (v==null || v<0) v=0; changeIf(map.put(x,v), v); } + } + + public final class MString { + private final LinkedHashMap map = new LinkedHashMap(); + private MString() { } + private void clear() { map.clear(); change(); } + private void putAll(MString x) { map.putAll(x.map); change(); } + public String get(AlloyElement x) { String ans=map.get(x); if (ans==null) ans=x.getName().trim(); return ans; } + public void put(AlloyElement x, String v) { if (x==null && v==null) v=""; if (x!=null && x.getName().equals(v)) v=null; changeIf(map.put(x,v), v); } + } + + public final class MMap { + private final LinkedHashMap map = new LinkedHashMap(); + private final T onValue; + private final T offValue; + private MMap() { onValue=null; offValue=null; } + private MMap(T on, T off) { this.onValue=on; this.offValue=off; } + private void clear() { map.clear(); change(); } + private void putAll(MMap x) { map.putAll(x.map); change(); } + public T get(AlloyElement obj) { return map.get(obj); } + public T resolve(AlloyElement obj) { + AlloyModel m = currentModel; + for(AlloyElement x=obj; ;x=parent(x,m)) { T v=map.get(x); if (v!=null) return v; } + } + /** Set the value for the given object; can be "null" to mean "inherit" */ + public void put(AlloyElement obj, T value) { + if (obj==null && value==null) return; + Object old = map.put(obj, value); + if ((old==null && value!=null) || (old!=null && !old.equals(value))) change(); + } + OurCheckbox pick(String label, String tooltip) { + return new OurCheckbox(label, tooltip, (Boolean.TRUE.equals(get(null)) ? OurCheckbox.ON : OurCheckbox.OFF)) { + private static final long serialVersionUID = 0; + public Icon do_action() { + T old = get(null); + boolean ans = (old!=null && old.equals(onValue)); + MMap.this.put(null, ans ? offValue : onValue); + return ans ? OFF : ON; + } + }; + } + OurCheckbox pick(final AlloyElement obj, final String label, final String tooltip) { + T a = get(obj), b = resolve(obj); + Icon icon = a==null ? (Boolean.TRUE.equals(b) ? OurCheckbox.INH_ON : OurCheckbox.INH_OFF) : (Boolean.TRUE.equals(a) ? OurCheckbox.ALL_ON : OurCheckbox.ALL_OFF); + return new OurCheckbox(label, tooltip, icon) { + private static final long serialVersionUID = 0; + public Icon do_action() { + T a = get(obj); + if (a==null) a=onValue; else if (a.equals(onValue)) a=offValue; else a=null; + MMap.this.put(obj, a); + return a==null ? (Boolean.TRUE.equals(resolve(obj)) ? INH_ON : INH_OFF) : (Boolean.TRUE.equals(a) ? ALL_ON : ALL_OFF); + } + }; + } + } + + // Reads the value for that type/set/relation. + // If x==null, then we guarantee the return value is nonnull + // If x!=null, then it may return null (which means "inherited") + // (Note: "label" and "weight" will never return null) + + // Reads the value for that atom based on an existing AlloyInstance; return value is never null. + public DotColor nodeColor (AlloyAtom a, AlloyInstance i) { for(AlloySet s:i.atom2sets(a)) {DotColor v=nodeColor.get(s); if (v!=null) return v;} return nodeColor.resolve (a.getType()); } + public DotStyle nodeStyle (AlloyAtom a, AlloyInstance i) { for(AlloySet s:i.atom2sets(a)) {DotStyle v=nodeStyle.get(s); if (v!=null) return v;} return nodeStyle.resolve (a.getType()); } + public DotShape shape (AlloyAtom a, AlloyInstance i) { for(AlloySet s:i.atom2sets(a)) {DotShape v=shape.get(s); if (v!=null) return v;} return shape.resolve (a.getType()); } + public boolean nodeVisible (AlloyAtom a, AlloyInstance i) { + // If it's in 1 or more set, then TRUE if at least one of them is TRUE. + // If it's in 0 set, then travel up the chain of AlloyType and return the first non-null value. + if (i.atom2sets(a).size()>0) { + for(AlloySet s:i.atom2sets(a)) if (nodeVisible.resolve(s)) return true; + return false; + } + return nodeVisible.resolve(a.getType()); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/VizTree.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/VizTree.java new file mode 100644 index 00000000..9d3dd202 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4viz/VizTree.java @@ -0,0 +1,151 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4viz; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprHasName; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Tuple; +import edu.mit.csail.sdg.alloy4compiler.translator.A4TupleSet; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.OurTree; +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.alloy4.Util; +import static edu.mit.csail.sdg.alloy4.Util.encode; + +/** GUI tree that displays an instance as a tree. + * + *

Thread Safety: Can be called only by the AWT event thread. + */ + +public final class VizTree extends OurTree { + + /** {@inheritDoc} */ + @Override public String convertValueToText(Object val, boolean selected, boolean expanded, boolean leaf, int row, boolean focus) { + String c = ">"; + if (onWindows) c = selected ? " style=\"color:#ffffff;\">" : " style=\"color:#000000;\">"; + if (val instanceof A4Solution) return " "; + if (val instanceof Sig) { + String label = ((Sig)val).label; + if (label.startsWith("this/")) label = label.substring(5); + return " "; + } + if (val instanceof ExprVar) return " "; + if (val instanceof String) return " "; + if (val instanceof Pair) return " )val).b)).label) + ""; + if (val instanceof A4Tuple) { + StringBuilder sb = new StringBuilder(" 1) sb.append(" -> "); + sb.append(encode(tp.atom(i))); + } + sb.append(""); + return sb.toString(); + } + return ""; + } + + /** {@inheritDoc} */ + @Override public Object do_root() { return instance; } + + /** {@inheritDoc} */ + @Override public List do_ask(Object parent) { + List ans = new ArrayList(); + try { + if (parent instanceof A4Solution) { + return toplevel; + } else if (parent instanceof Sig || parent instanceof ExprVar) { + A4TupleSet ts = (A4TupleSet) (instance.eval((Expr)parent)); + for(A4Tuple t: ts) ans.add(t.atom(0)); + } else if (parent instanceof String) { + String atom = (String)parent; + for(Sig s: instance.getAllReachableSigs()) for(Field f: s.getFields()) for(A4Tuple t: instance.eval(f)) { + if (t.atom(0).equals(atom)) { ans.add(new Pair(atom, f)); break; } + } + for(ExprVar f: instance.getAllSkolems()) if (f.type().arity()>1) for(A4Tuple t: (A4TupleSet)(instance.eval(f))) { + if (t.atom(0).equals(atom)) { ans.add(new Pair(atom, f)); break; } + } + } else if (parent instanceof Pair) { + Pair p = (Pair)parent; + ExprHasName rel = (ExprHasName) (p.b); + String atom = (String) (p.a); + for(A4Tuple tuple: (A4TupleSet) (instance.eval(rel))) if (tuple.atom(0).equals(atom)) { + if (tuple.arity()==2) ans.add(tuple.atom(1)); else ans.add(tuple); + } + } else if (parent instanceof A4Tuple) { + A4Tuple tp = (A4Tuple)parent; + for(int i=1; i() { + public int compare(Object a, Object b) { + String t1, t2; + if (a instanceof Pair) { t1=((ExprHasName)(((Pair)a).b)).label; t2=((ExprHasName)(((Pair)b).b)).label; } + else { t1=a.toString(); t2=b.toString(); } + int i = t1.compareToIgnoreCase(t2); + if (i!=0) return i; else return t1.compareTo(t2); + } + }); + return ans; + } catch(Err er) { + return ans; + } + } + + /** This ensures the class can be serialized reliably. */ + private static final long serialVersionUID = 0; + + /** Caches whether we're on Windows or not. */ + private final boolean onWindows; + + /** The title of this tree. */ + private final String title; + + /** The instance being displayed. */ + private final A4Solution instance; + + /** The list of toplevel nodes to show. */ + private final List toplevel; + + /** Constructs a tree to display the given instance. */ + public VizTree(A4Solution instance, String title, int fontSize) { + super(fontSize); + this.instance = instance; + this.title = title; + this.onWindows = Util.onWindows(); + ArrayList toplevel = new ArrayList(); + for(Sig s: instance.getAllReachableSigs()) if (s!=Sig.UNIV && s!=Sig.SEQIDX && s!=Sig.NONE) toplevel.add(s); + for(ExprVar v: instance.getAllSkolems()) if (v.type().arity()==1 && v.label.startsWith("$")) toplevel.add(v); + Collections.sort(toplevel, new Comparator() { + public int compare(Object a, Object b) { + String t1, t2; + if (a instanceof Sig) { t1=((Sig)a).label; if (b instanceof ExprVar) return -1; else t2=((Sig)b).label; } + else { t1=((ExprVar)a).label; if (b instanceof Sig) return 1; else t2=((ExprVar)b).label; } + return Util.slashComparator.compare(t1, t2); + } + }); + this.toplevel = Collections.unmodifiableList(toplevel); + do_start(); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/DemoFileSystem.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/DemoFileSystem.java new file mode 100644 index 00000000..acedc665 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/DemoFileSystem.java @@ -0,0 +1,157 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4whole; + +import static edu.mit.csail.sdg.alloy4.A4Reporter.NOP; +import java.util.LinkedHashSet; +import java.util.Set; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4compiler.ast.Attr; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.Decl; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprConstant; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprHasName; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Options; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.TranslateAlloyToKodkod; + +/** This class demonstrates how to access Alloy4 via the API, by modeling a simple file system. */ + +public class DemoFileSystem { + + /* Helper methods to simplify using the API for this example. */ + + Set sigs = new LinkedHashSet(); + + PrimSig makeSig(String name, boolean isAbstract, boolean isOne) throws Err { + PrimSig ans = new PrimSig(name, (isAbstract ? Attr.ABSTRACT : null), (isOne ? Attr.ONE : null)); + sigs.add(ans); + return ans; + } + + PrimSig makeSig(PrimSig parent, String name, boolean isAbstract, boolean isOne) throws Err { + PrimSig ans = new PrimSig(name, parent, (isAbstract ? Attr.ABSTRACT : null), (isOne ? Attr.ONE : null)); + sigs.add(ans); + return ans; + } + + void runFor3(Expr expr) throws Err { + A4Options opt = new A4Options(); + Command cmd = new Command(false, 3, 3, 3, expr.and(fact)); + A4Solution sol = TranslateAlloyToKodkod.execute_command(NOP, sigs, cmd, opt); + System.out.println(sol.toString().trim()); + if (sol.satisfiable()) { + System.out.println("In particular, File = " + sol.eval(file)); + System.out.println("In particular, Dir = " + sol.eval(dir)); + System.out.println("In particular, contains = " + sol.eval(contains)); + System.out.println("In particular, parent = " + sol.eval(parent)); + } + System.out.println(); + } + + /* These corresponds to the helper predicates/functions provided in util/*.als */ + + static Expr acyclic(Expr r) throws Err { + Decl d = r.join(Sig.UNIV).oneOf("x"); // x is a variable over the domain of r + ExprHasName x = d.get(); + return x.in(x.join(r.closure())).not().forAll(d); // (x !in x.^r) for all x + } + + /* Here are definitions common to all instances. */ + + PrimSig obj=null, dir=null, file=null, root=null; + + Field parent=null, contains=null; + + Expr fact=ExprConstant.TRUE; + + void makeDomain() throws Err { + // abstract sig Obj { parent: lone Dir } + // abstract sig Dir extends Obj { contains: set Obj } + // abstract sig File extends Obj { } + // one sig Root extends Dir { } + obj = makeSig("Obj", true, false); + dir = makeSig(obj, "Dir", true, false); + file = makeSig(obj, "File", true, false); + root = makeSig(dir, "Root", false, true); + parent = obj.addField("parent", dir.loneOf()); + contains = dir.addField("contains", obj.setOf()); + // fact { all x:Obj-Root | one x.parent } + Decl x = obj.minus(root).oneOf("x"); + fact = x.get().join(parent).one().forAll(x).and(fact); + // fact { contains = ~ parent } + fact = contains.equal(parent.transpose()).and(fact); + // fact { acyclic[contains] } + fact = acyclic(contains).and(fact); + } + + /* Here is instance number 1. */ + + void makeInstance1() throws Err { + // file = F1, F2, F3 + // dir = Root, D1, D2 + // F1.parent = D1 + // F2.parent = D2 + // F3.parent = D2 + // D2.parent = D1 + // D1.parent = Root + PrimSig file1 = makeSig(file, "F1", false, true); + PrimSig file2 = makeSig(file, "F2", false, true); + PrimSig file3 = makeSig(file, "F3", false, true); + PrimSig dir1 = makeSig(dir, "D1", false, true); + PrimSig dir2 = makeSig(dir, "D2", false, true); + fact = file1.join(parent).equal(dir1).and(fact); + fact = file2.join(parent).equal(dir2).and(fact); + fact = file3.join(parent).equal(dir2).and(fact); + fact = dir2.join(parent).equal(dir1).and(fact); + fact = dir1.join(parent).equal(root).and(fact); + } + + /* Here is instance number 2. */ + + void makeInstance2() throws Err { + // dir = Root, D1, D2 + // D2.parent = D1 + // D1.parent = D2 + PrimSig dir1 = makeSig(dir, "D1", false, true); + PrimSig dir2 = makeSig(dir, "D2", false, true); + fact = dir2.join(parent).equal(dir1).and(fact); + fact = dir1.join(parent).equal(dir2).and(fact); + } + + private DemoFileSystem() { } + + /* The main driver. */ + + public static void main(String[] args) throws Err { + + DemoFileSystem x; + + x = new DemoFileSystem(); + x.makeDomain(); + x.makeInstance1(); + x.runFor3(x.file.some()); // run { some file } + + x = new DemoFileSystem(); + x.makeDomain(); + x.makeInstance1(); + x.runFor3(acyclic(x.contains).not()); // run { !acyclic[contains] } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/ExampleUsingTheAPI.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/ExampleUsingTheAPI.java new file mode 100644 index 00000000..99418b74 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/ExampleUsingTheAPI.java @@ -0,0 +1,94 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4whole; + +import java.util.Arrays; +import java.util.List; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4compiler.ast.Attr; +import edu.mit.csail.sdg.alloy4compiler.ast.Decl; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprConstant; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.Func; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Options; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.TranslateAlloyToKodkod; +import static edu.mit.csail.sdg.alloy4compiler.ast.Sig.UNIV; +import static edu.mit.csail.sdg.alloy4.A4Reporter.NOP; + +/** This class demonstrates how to access Alloy4 via the API. */ + +public final class ExampleUsingTheAPI { + + public static void main(String[] args) throws Err { + + // Chooses the Alloy4 options + A4Options opt = new A4Options(); + opt.solver = A4Options.SatSolver.SAT4J; + + // abstract sig A {} + PrimSig A = new PrimSig("A", Attr.ABSTRACT); + + // sig B {} + PrimSig B = new PrimSig("B"); + + // one sig A1 extends A {} + PrimSig A1 = new PrimSig("A1", A, Attr.ONE); + + // one sig A2 extends A {} + PrimSig A2 = new PrimSig("A2", A, Attr.ONE); + + // A { f: B lone->lone B } + Expr f = A.addField("f", B.lone_arrow_lone(B)); + // Since (B lone->lone B) is not unary, the default is "setOf", meaning "f:set (B lone->lone B)" + + // A { g: B } + Expr g = A.addField("g", B); + // The line above is the same as: A.addField(null, "g", B.oneOf()) since B is unary. + // If you want "setOf", you need: A.addField(null, "g", B.setOf()) + + // pred someG { some g } + Func someG = new Func(null, "SomeG", null, null, g.some()); + + // pred atMostThree[x:univ, y:univ] { #(x+y) >= 3 } + Decl x = UNIV.oneOf("x"); + Decl y = UNIV.oneOf("y"); + Expr body = x.get().plus(y.get()).cardinality().lte(ExprConstant.makeNUMBER(3)); + Func atMost3 = new Func(null, "atMost3", Util.asList(x,y), null, body); + + List sigs = Arrays.asList(new Sig[]{A, B, A1, A2}); + + // run { some A && atMostThree[B,B] } for 3 but 3 int, 3 seq + Expr expr1 = A.some().and(atMost3.call(B,B)); + Command cmd1 = new Command(false, 3, 3, 3, expr1); + A4Solution sol1 = TranslateAlloyToKodkod.execute_command(NOP, sigs, cmd1, opt); + System.out.println("[Solution1]:"); + System.out.println(sol1.toString()); + + // run { some f && SomeG[] } for 3 but 2 int, 1 seq, 5 A, exactly 6 B + Expr expr2 = f.some().and(someG.call()); + Command cmd2 = new Command(false, 3, 2, 1, expr2); + cmd2 = cmd2.change(A, false, 5); + cmd2 = cmd2.change(B, true, 6); + A4Solution sol2 = TranslateAlloyToKodkod.execute_command(NOP, sigs, cmd2, opt); + System.out.println("[Solution2]:"); + System.out.println(sol2.toString()); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/ExampleUsingTheCompiler.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/ExampleUsingTheCompiler.java new file mode 100644 index 00000000..aa9f2570 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/ExampleUsingTheCompiler.java @@ -0,0 +1,92 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4whole; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; +import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Options; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.TranslateAlloyToKodkod; +import edu.mit.csail.sdg.alloy4viz.VizGUI; + +/** This class demonstrates how to access Alloy4 via the compiler methods. */ + +public final class ExampleUsingTheCompiler { + + /* + * Execute every command in every file. + * + * This method parses every file, then execute every command. + * + * If there are syntax or type errors, it may throw + * a ErrorSyntax or ErrorType or ErrorAPI or ErrorFatal exception. + * You should catch them and display them, + * and they may contain filename/line/column information. + */ + public static void main(String[] args) throws Err { + + // The visualizer (We will initialize it to nonnull when we visualize an Alloy solution) + VizGUI viz = null; + + // Alloy4 sends diagnostic messages and progress reports to the A4Reporter. + // By default, the A4Reporter ignores all these events (but you can extend the A4Reporter to display the event for the user) + A4Reporter rep = new A4Reporter() { + // For example, here we choose to display each "warning" by printing it to System.out + @Override public void warning(ErrorWarning msg) { + System.out.print("Relevance Warning:\n"+(msg.toString().trim())+"\n\n"); + System.out.flush(); + } + }; + + for(String filename:args) { + + // Parse+typecheck the model + System.out.println("=========== Parsing+Typechecking "+filename+" ============="); + Module world = CompUtil.parseEverything_fromFile(rep, null, filename); + + // Choose some default options for how you want to execute the commands + A4Options options = new A4Options(); + options.solver = A4Options.SatSolver.SAT4J; + + for (Command command: world.getAllCommands()) { + // Execute the command + System.out.println("============ Command "+command+": ============"); + A4Solution ans = TranslateAlloyToKodkod.execute_command(rep, world.getAllReachableSigs(), command, options); + // Print the outcome + System.out.println(ans); + // If satisfiable... + if (ans.satisfiable()) { + // You can query "ans" to find out the values of each set or type. + // This can be useful for debugging. + // + // You can also write the outcome to an XML file + ans.writeXML("alloy_example_output.xml"); + // + // You can then visualize the XML file by calling this: + if (viz==null) { + viz = new VizGUI(false, "alloy_example_output.xml", null); + } else { + viz.loadXML("alloy_example_output.xml", true); + } + } + } + } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/Helper.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/Helper.java new file mode 100644 index 00000000..f9bb3d49 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/Helper.java @@ -0,0 +1,55 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4whole; + +import java.util.Map; +import java.util.HashMap; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Tuple; +import edu.mit.csail.sdg.alloy4compiler.translator.A4TupleSet; + +/** This class contains convenient methods for people using Alloy4 API. + * These methods are provided for your convenience, and any discovered bug will be fixed, + * but these methods are not part of the official Alloy4 API and individual methods may be removed in the future if necessary. + */ + +public final class Helper { + + /** + * Given an A4Solution, return a map that maps every atom to its most specific signature. + * + *

For example, suppose we have "sig Animal { }" and "sig Dog, Cat extends Animal { }". + * Suppose the solution says Animal={A$1, A$2, A$3, A$4} and Dog={A$1} and Cat={A$2, A$3}. + * This method will return a map that maps A$1 to Dog, A$2 to Cat, A$3 to Cat, and A$4 to Animal. + * (A$1 is both an Animal and a Dog, but Dog is a subtype of Animal, so Dog is A$1's most specific signature) + */ + public static Map atom2sig(A4Solution solution) throws Err { + Map map = new HashMap(); + for(Sig s: solution.getAllReachableSigs()) if (s instanceof PrimSig) for(A4Tuple t: (A4TupleSet) solution.eval(s)) { + // We skip over SubsetSig and only care about PrimSig + String atom = t.atom(0); + PrimSig old = map.get(atom); + if (old==null || ((PrimSig)s).isSameOrDescendentOf(old)) { map.put(atom, (PrimSig)s); } + } + return map; + } + + /** Constructor is private, since this utility class never needs to be instantiated. */ + private Helper() { } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/InternalTest.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/InternalTest.java new file mode 100644 index 00000000..f989cb2e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/InternalTest.java @@ -0,0 +1,175 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4whole; + +import java.io.StringReader; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.MailBug; +import edu.mit.csail.sdg.alloy4.SafeList; +import edu.mit.csail.sdg.alloy4.XMLNode; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; +import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Options; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.A4SolutionReader; +import edu.mit.csail.sdg.alloy4compiler.translator.TranslateAlloyToKodkod; + +/** API-specific regression test suite; the larger collection of models that test both the compiler and translator are in models/tests/*.als */ + +final class InternalTest { + + private static void check(boolean condition) throws Exception { + if (!condition) throw new RuntimeException("Assertion failure: condition should be TRUE"); + } + + private static void check(Object a, Object b) { + if (a==null) { + if (b!=null) throw new AssertionError("a is null, but b is "+b); + } else if (b==null) { + throw new AssertionError("b is null, but a is "+a); + } else if (!a.equals(b)) { + throw new AssertionError("a!=b\n" + "a=" + a + "\nb=" + b + "\n"); + } + } + + static void test1() throws Exception { + XMLNode xml = new XMLNode(new StringReader( + "" + + "" + + " " + + " " + + " " + + " " + + "" + + " " + + " " + + " " + + "" + + "" + + " " + + " " + + "" + + "" + + "")); + Sig state = new Sig.PrimSig("State"); + A4Solution sol = A4SolutionReader.read(Arrays.asList(state), xml); + SafeList skolems = new SafeList(sol.getAllSkolems()); + check(skolems.size()==1); + check(skolems.get(0).label, "$Deadlock_s"); + check(skolems.get(0).type(), state.type()); + // + Sig state2 = new Sig.PrimSig("State"); + Field field2 = state2.addField("len", Sig.SIGINT); + sol = A4SolutionReader.read(Arrays.asList(state2), xml); + SafeList skolems2 = new SafeList(sol.getAllSkolems()); + check(skolems2.size()==1); + check(skolems2.get(0).label, "$Deadlock_s"); + check(skolems2.get(0).type(), state2.type()); + check(""+sol.eval(field2.cardinality()), "-2"); + } + + static void test2() throws Exception { + test1(); + XMLNode xml = new XMLNode(new StringReader( + "" + + "" + + " " + + " " + + " " + + " " + + "" + + " " + + " " + + "" + + "" + + "")); + Sig activity = new Sig.PrimSig("Act"); + A4Solution sol = A4SolutionReader.read(Arrays.asList(activity), xml); + SafeList skolems = new SafeList(sol.getAllSkolems()); + check(skolems.size()==1); + check(skolems.get(0).label, "$x"); + check(skolems.get(0).type(), Sig.SEQIDX.type().product(activity.type())); + } + + static void test3() throws Exception { + XMLNode xml = new XMLNode(new StringReader( + "" + + "" + + " " + + " " + + " " + + " " + + " " + + "" + + "")); + String err = ""; + try { A4SolutionReader.read(null, xml); } catch(Throwable ex) { err=ex.toString(); } + check(err.contains("cyclic inheritance")); + } + + /** Displays the amount of memory taken per solution enumeration. */ + public static void main2(String[] args) throws Exception { + String filename = "models/examples/algorithms/dijkstra.als"; + Module world = CompUtil.parseEverything_fromFile(A4Reporter.NOP, null, filename); + A4Options options = new A4Options(); + for (Command command: world.getAllCommands()) { + A4Solution ans = TranslateAlloyToKodkod.execute_command(A4Reporter.NOP, world.getAllReachableSigs(), command, options); + while(ans.satisfiable()) { + String hc = "Answer: " + ans.toString().hashCode(); + System.gc(); + System.gc(); + System.gc(); + Thread.sleep(500); + System.gc(); + System.gc(); + System.gc(); + Thread.sleep(500); + long t = Runtime.getRuntime().totalMemory(), f = Runtime.getRuntime().freeMemory(), m = Runtime.getRuntime().maxMemory(); + System.out.println(hc + " total=" + t + " free=" + f + " max="+m); System.out.flush(); + ans=ans.next(); + } + return; + } + } + + /** Runs every test case. */ + public static void main(String[] args) throws Exception { + try { + for(Method m: InternalTest.class.getDeclaredMethods()) { + String name = m.getName(); + if (name.startsWith("test")) { + System.out.print("Running "+name+"..."); System.out.flush(); + m.invoke(null, new Object[0]); + System.out.print(" Done.\n"); System.out.flush(); + } + } + } catch(Throwable ex) { + while(ex instanceof InvocationTargetException) ex=((InvocationTargetException)ex).getCause(); + System.out.println(); + System.out.flush(); + System.err.println("Error:\n"+MailBug.dump(ex).trim()+"\n"); + System.err.flush(); + System.exit(1); + } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/SimpleCLI.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/SimpleCLI.java new file mode 100644 index 00000000..25d8fb54 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/SimpleCLI.java @@ -0,0 +1,230 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4whole; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.RandomAccessFile; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.alloy4.XMLNode; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.Decl; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprHasName; +import edu.mit.csail.sdg.alloy4compiler.ast.Func; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; +import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Options; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.A4SolutionReader; +import edu.mit.csail.sdg.alloy4compiler.translator.A4SolutionWriter; +import edu.mit.csail.sdg.alloy4compiler.translator.TranslateAlloyToKodkod; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Options.SatSolver; +import edu.mit.csail.sdg.alloy4viz.StaticInstanceReader; + +/** This class is used by the Alloy developers to drive the regression test suite. + * For a more detailed guide on how to use Alloy API, please see "ExampleUsingTheCompiler.java" + */ + +public final class SimpleCLI { + + private static final class SimpleReporter extends A4Reporter { + + private final StringBuilder sb = new StringBuilder(); + + private final List warnings = new ArrayList(); + + private final RandomAccessFile os; + + public SimpleReporter() throws IOException { + os = new RandomAccessFile(".alloy.tmp","rw"); + os.setLength(0); + } + + public void flush() throws IOException { + if (sb.length()>65536) { + os.write(sb.toString().getBytes("UTF-8")); + sb.delete(0, sb.length()); + } + } + + public void close() throws IOException { + if (sb.length()>0) { + os.write(sb.toString().getBytes("UTF-8")); + sb.delete(0, sb.length()); + } + os.close(); + } + + @Override public void debug(String msg) { sb.append(msg); } + + @Override public void parse(String msg) { sb.append(msg); } + + @Override public void typecheck(String msg) { sb.append(msg); } + + @Override public void warning(ErrorWarning msg) { warnings.add(msg); } + + @Override public void scope(String msg) { sb.append(" "); sb.append(msg); } + + @Override public void bound(String msg) { sb.append(" "); sb.append(msg); } + + @Override public void translate(String solver, int bitwidth, int maxseq, int skolemDepth, int symmetry) { + sb.append(" Solver="+solver+" Bitwidth="+bitwidth+" MaxSeq="+maxseq+" Symmetry="+(symmetry>0 ? (""+symmetry) : "OFF")+"\n"); + } + + @Override public void solve(int primaryVars, int totalVars, int clauses) { + if (db) db(" "+totalVars+" vars. "+primaryVars+" primary vars. "+clauses+" clauses.\n"); + sb.append(" "+totalVars+" vars. "+primaryVars+" primary vars. "+clauses+" clauses. 12345ms.\n"); + } + + @Override public void resultCNF(String filename) {} + + @Override public void resultSAT(Object command, long solvingTime, Object solution) { + if (db) db(" SAT!\n"); + if (!(command instanceof Command)) return; + Command cmd = (Command)command; + sb.append(cmd.check ? " Counterexample found. " : " Instance found. "); + if (cmd.check) sb.append("Assertion is invalid"); else sb.append("Predicate is consistent"); + if (cmd.expects==0) sb.append(", contrary to expectation"); else if (cmd.expects==1) sb.append(", as expected"); + sb.append(". "+solvingTime+"ms.\n\n"); + } + + @Override public void resultUNSAT(Object command, long solvingTime, Object solution) { + if (db) db(" UNSAT!\n"); + if (!(command instanceof Command)) return; + Command cmd = (Command)command; + sb.append(cmd.check ? " No counterexample found." : " No instance found."); + if (cmd.check) sb.append(" Assertion may be valid"); else sb.append(" Predicate may be inconsistent"); + if (cmd.expects==1) sb.append(", contrary to expectation"); else if (cmd.expects==0) sb.append(", as expected"); + sb.append(". "+solvingTime+"ms.\n\n"); + } + } + + private static boolean db=true; + + private static void db(String msg) { System.out.print(msg); System.out.flush(); } + + private SimpleCLI() { } + + private static void validate(A4Solution sol) throws Exception { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + sol.writeXML(pw, null, null); + pw.flush(); + sw.flush(); + String txt = sw.toString(); + A4SolutionReader.read(new ArrayList(), new XMLNode(new StringReader(txt))).toString(); + StaticInstanceReader.parseInstance(new StringReader(txt)); + } + + public static void main(String[] args) throws Exception { + final boolean sat4j = "yes".equals(System.getProperty("sat4j")); + final boolean minisat = "yes".equals(System.getProperty("minisat")); + SatSolver solver = A4Options.SatSolver.make("mem", "mem", "/zweb/sat/mem"); + final SimpleReporter rep = new SimpleReporter(); + final StringBuilder sb = rep.sb; + for(String filename:args) { + try { + // Parse+Typecheck + rep.sb.append("\n\nMain file = "+filename+"\n"); + if (db) db("Parsing+Typechecking..."); + Module world = CompUtil.parseEverything_fromFile(rep, null, filename); + if (db) db(" ok\n"); + List cmds=world.getAllCommands(); + for(ErrorWarning msg: rep.warnings) rep.sb.append("Relevance Warning:\n" + (msg.toString().trim()) + "\n\n"); + rep.warnings.clear(); + // Do a detailed dump if we will not be executing the commands + if (args.length!=1) { + for(Module m:world.getAllReachableModules()) { + for(Sig x:m.getAllSigs()) { + sb.append("\nSig ").append(x.label).append(" at position ").append(x.pos).append("\n"); + for(Decl d:x.getFieldDecls()) for(ExprHasName f:d.names) { + sb.append("\nField ").append(f.label).append(" with type ").append(f.type()).append("\n"); + d.expr.toString(sb, 2); + } + rep.flush(); + } + for(Func x:m.getAllFunc()) { + sb.append("\nFun/pred ").append(x.label).append(" at position ").append(x.pos).append("\n"); + for(Decl d:x.decls) for(ExprHasName v:d.names) { v.toString(sb, 2); d.expr.toString(sb, 4); } + x.returnDecl.toString(sb, 2); + x.getBody().toString(sb, 4); + rep.flush(); + } + for(Pair x:m.getAllFacts()) { + sb.append("\nFact ").append(x.a).append("\n"); x.b.toString(sb, 4); + rep.flush(); + } + for(Pair x:m.getAllAssertions()) { + sb.append("\nAssertion ").append(x.a).append("\n"); x.b.toString(sb, 4); + rep.flush(); + } + if (m==world) for(Command x:m.getAllCommands()) { + sb.append("\nCommand ").append(x.label).append("\n"); + x.formula.toString(sb, 4); + rep.flush(); + } + } + continue; + } + // Validate the metamodel generation code + StringWriter metasb = new StringWriter(); + PrintWriter meta = new PrintWriter(metasb); + Util.encodeXMLs(meta, "\n\n\n"); + A4SolutionWriter.writeMetamodel(world.getAllReachableSigs(), filename, meta); + Util.encodeXMLs(meta, "\n"); + meta.flush(); + metasb.flush(); + String metaxml = metasb.toString(); + A4SolutionReader.read(new ArrayList(), new XMLNode(new StringReader(metaxml))); + StaticInstanceReader.parseInstance(new StringReader(metaxml)); + // Okay, now solve the commands + A4Options options = new A4Options(); + options.originalFilename = filename; + options.solverDirectory = "/zweb/zweb/tmp/alloy4/x86-freebsd"; + options.solver = sat4j ? A4Options.SatSolver.SAT4J : (minisat ? A4Options.SatSolver.MiniSatJNI : solver); + for (int i=0; i60) cc=cc.substring(0,55); + db("Executing "+cc+"...\n"); + } + rep.sb.append("Executing \""+c+"\"\n"); + options.skolemDepth=0; + A4Solution s = TranslateAlloyToKodkod.execute_commandFromBook(rep, world.getAllReachableSigs(), c, options); + if (s.satisfiable()) { validate(s); if (s.isIncremental()) { s=s.next(); if (s.satisfiable()) validate(s); } } + options.skolemDepth=2; + s = TranslateAlloyToKodkod.execute_commandFromBook(rep, world.getAllReachableSigs(), c, options); + if (s.satisfiable()) { validate(s); if (s.isIncremental()) { s=s.next(); if (s.satisfiable()) validate(s); } } + } + } catch(Throwable ex) { + rep.sb.append("\n\nException: "+ex); + } + if (db) { if (args.length!=1) db(" ERROR!\n"); else db("\n\n"); } + } + rep.close(); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/SimpleGUI.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/SimpleGUI.java new file mode 100644 index 00000000..6e65a622 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/SimpleGUI.java @@ -0,0 +1,2067 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4whole; + +import static edu.mit.csail.sdg.alloy4.OurUtil.menu; +import static edu.mit.csail.sdg.alloy4.OurUtil.menuItem; +import static java.awt.event.KeyEvent.VK_A; +import static java.awt.event.KeyEvent.VK_ALT; +import static java.awt.event.KeyEvent.VK_E; +import static java.awt.event.KeyEvent.VK_PAGE_DOWN; +import static java.awt.event.KeyEvent.VK_PAGE_UP; +import static java.awt.event.KeyEvent.VK_SHIFT; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Font; +import java.awt.GraphicsEnvironment; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Random; +import java.util.Scanner; +import java.util.Set; +import java.util.prefs.Preferences; + +import javax.swing.Box; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSeparator; +import javax.swing.JSplitPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.JToolBar; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.UIManager; +import javax.swing.WindowConstants; +import javax.swing.border.EmptyBorder; +import javax.swing.border.LineBorder; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; +import javax.swing.text.html.HTMLDocument; + +import kodkod.engine.fol2sat.HigherOrderDeclException; +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.Computer; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.Listener; +import edu.mit.csail.sdg.alloy4.MacUtil; +import edu.mit.csail.sdg.alloy4.MailBug; +import edu.mit.csail.sdg.alloy4.OurAntiAlias; +import edu.mit.csail.sdg.alloy4.OurBorder; +import edu.mit.csail.sdg.alloy4.OurCombobox; +import edu.mit.csail.sdg.alloy4.OurDialog; +import edu.mit.csail.sdg.alloy4.OurSyntaxWidget; +import edu.mit.csail.sdg.alloy4.OurTabbedSyntaxWidget; +import edu.mit.csail.sdg.alloy4.OurTree; +import edu.mit.csail.sdg.alloy4.OurUtil; +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Runner; +import edu.mit.csail.sdg.alloy4.Subprocess; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.Util.BooleanPref; +import edu.mit.csail.sdg.alloy4.Util.IntPref; +import edu.mit.csail.sdg.alloy4.Util.StringPref; +import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.alloy4.WorkerEngine; +import edu.mit.csail.sdg.alloy4.WorkerEngine.WorkerCallback; +import edu.mit.csail.sdg.alloy4.XMLNode; +import edu.mit.csail.sdg.alloy4compiler.ast.Browsable; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; +import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil; +import edu.mit.csail.sdg.alloy4compiler.sim.SimInstance; +import edu.mit.csail.sdg.alloy4compiler.sim.SimTuple; +import edu.mit.csail.sdg.alloy4compiler.sim.SimTupleset; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Options; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Options.SatSolver; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.A4SolutionReader; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Tuple; +import edu.mit.csail.sdg.alloy4compiler.translator.A4TupleSet; +import edu.mit.csail.sdg.alloy4viz.VizGUI; +import edu.mit.csail.sdg.alloy4whole.SimpleReporter.SimpleCallback1; +import edu.mit.csail.sdg.alloy4whole.SimpleReporter.SimpleTask1; +import edu.mit.csail.sdg.alloy4whole.SimpleReporter.SimpleTask2; + +/** Simple graphical interface for accessing various features of the analyzer. + * + *

Except noted below, methods in this class can only be called by the AWT event thread. + * + *

The methods that might get called from other threads are: + *
(1) the run() method in SatRunner is launched from a fresh thread + *
(2) the run() method in the instance watcher (in constructor) is launched from a fresh thread + */ + +public final class SimpleGUI implements ComponentListener, Listener { + + /** The latest welcome screen; each time we update the welcome screen, we increment this number. */ + private static final int welcomeLevel = 2; + + // Verify that the graphics environment is set up + static { + try { + GraphicsEnvironment.getLocalGraphicsEnvironment(); + } catch(Throwable ex) { + System.err.println("Unable to start the graphical environment."); + System.err.println("If you're on Mac OS X:"); + System.err.println(" Please make sure you are running as the current local user."); + System.err.println("If you're on Linux or FreeBSD:"); + System.err.println(" Please make sure your X Windows is configured."); + System.err.println(" You can verify this by typing \"xhost\"; it should not give an error message."); + System.err.flush(); + System.exit(1); + } + } + + //======== The Preferences ======================================================================================// + //======== Note: you must make sure each preference has a unique key ============================================// + + /** The list of allowable memory sizes. */ + private List allowedMemorySizes; + + /** True if Alloy Analyzer should let warning be nonfatal. */ + private static final BooleanPref WarningNonfatal = new BooleanPref("WarningNonfatal"); + + /** True if Alloy Analyzer should automatically visualize the latest instance. */ + private static final BooleanPref AutoVisualize = new BooleanPref("AutoVisualize"); + + /** True if Alloy Analyzer should insist on antialias. */ + private static final BooleanPref AntiAlias = new BooleanPref("AntiAlias"); + + /** True if Alloy Analyzer should record the raw Kodkod input and output. */ + private static final BooleanPref RecordKodkod = new BooleanPref("RecordKodkod"); + + /** True if Alloy Analyzer should enable the new Implicit This name resolution. */ + private static final BooleanPref ImplicitThis = new BooleanPref("ImplicitThis"); + + /** True if Alloy Analyzer should not report models that overflow. */ + private static final BooleanPref NoOverflow = new BooleanPref("NoOverflow"); + + /** The latest X corrdinate of the Alloy Analyzer's main window. */ + private static final IntPref AnalyzerX = new IntPref("AnalyzerX",0,-1,65535); + + /** The latest Y corrdinate of the Alloy Analyzer's main window. */ + private static final IntPref AnalyzerY = new IntPref("AnalyzerY",0,-1,65535); + + /** The latest width of the Alloy Analyzer's main window. */ + private static final IntPref AnalyzerWidth = new IntPref("AnalyzerWidth",0,-1,65535); + + /** The latest height of the Alloy Analyzer's main window. */ + private static final IntPref AnalyzerHeight = new IntPref("AnalyzerHeight",0,-1,65535); + + /** The latest font size of the Alloy Analyzer. */ + private static final IntPref FontSize = new IntPref("FontSize",9,12,72); + + /** The latest font name of the Alloy Analyzer. */ + private static final StringPref FontName = new StringPref("FontName","Lucida Grande"); + + /** The latest tab distance of the Alloy Analyzer. */ + private static final IntPref TabSize = new IntPref("TabSize",1,2,16); + + /** The latest welcome screen that the user has seen. */ + private static final IntPref Welcome = new IntPref("Welcome",0,0,1000); + + /** Whether syntax highlighting should be disabled or not. */ + private static final BooleanPref SyntaxDisabled = new BooleanPref("SyntaxHighlightingDisabled"); + + /** The number of recursion unrolls. */ + private static final IntPref Unrolls = new IntPref("Unrolls", -1, -1, 3); + + /** The skolem depth. */ + private static final IntPref SkolemDepth = new IntPref("SkolemDepth3", 0, 1, 4); + + /** The unsat core minimization strategy. */ + private static final IntPref CoreMinimization = new IntPref("CoreMinimization",0,2,2); + + /** The unsat core granularity. */ + private static final IntPref CoreGranularity = new IntPref("CoreGranularity",0,0,3); + + /** The amount of memory (in M) to allocate for Kodkod and the SAT solvers. */ + private static final IntPref SubMemory = new IntPref("SubMemory",16,768,65535); + + /** The amount of stack (in K) to allocate for Kodkod and the SAT solvers. */ + private static final IntPref SubStack = new IntPref("SubStack",16,8192,65536); + + /** The first file in Alloy Analyzer's "open recent" list. */ + private static final StringPref Model0 = new StringPref("Model0"); + + /** The second file in Alloy Analyzer's "open recent" list. */ + private static final StringPref Model1 = new StringPref("Model1"); + + /** The third file in Alloy Analyzer's "open recent" list. */ + private static final StringPref Model2 = new StringPref("Model2"); + + /** The fourth file in Alloy Analyzer's "open recent" list. */ + private static final StringPref Model3 = new StringPref("Model3"); + + /** This enum defines the set of possible message verbosity levels. */ + private enum Verbosity { + /** Level 0. */ DEFAULT("0", "low"), + /** Level 1. */ VERBOSE("1", "medium"), + /** Level 2. */ DEBUG("2", "high"), + /** Level 3. */ FULLDEBUG("3", "debug only"); + /** Returns true if it is greater than or equal to "other". */ + public boolean geq(Verbosity other) { return ordinal() >= other.ordinal(); } + /** This is a unique String for this value; it should be kept consistent in future versions. */ + private final String id; + /** This is the label that the toString() method will return. */ + private final String label; + /** Constructs a new Verbosity value with the given id and label. */ + private Verbosity(String id, String label) { this.id=id; this.label=label; } + /** Given an id, return the enum value corresponding to it (if there's no match, then return DEFAULT). */ + private static Verbosity parse(String id) { + for(Verbosity vb: values()) if (vb.id.equals(id)) return vb; + return DEFAULT; + } + /** Returns the human-readable label for this enum value. */ + @Override public final String toString() { return label; } + /** Saves this value into the Java preference object. */ + private void set() { Preferences.userNodeForPackage(Util.class).put("Verbosity",id); } + /** Reads the current value of the Java preference object (if it's not set, then return DEFAULT). */ + private static Verbosity get() { return parse(Preferences.userNodeForPackage(Util.class).get("Verbosity","")); } + }; + + //===================================================================================================// + + /** The JFrame for the main window. */ + private JFrame frame; + + /** The JFrame for the visualizer window. */ + private VizGUI viz; + + /** The "File", "Edit", "Run", "Option", "Window", and "Help" menus. */ + private JMenu filemenu, editmenu, runmenu, optmenu, windowmenu, windowmenu2, helpmenu; + + /** The toolbar. */ + private JToolBar toolbar; + + /** The various toolbar buttons. */ + private JButton runbutton, stopbutton, showbutton; + + /** The Splitpane. */ + private JSplitPane splitpane; + + /** The JLabel that displays the current line/column position, etc. */ + private JLabel status; + + /** Whether the editor has the focus, or the log window has the focus. */ + private boolean lastFocusIsOnEditor = true; + + /** The text editor. */ + private OurTabbedSyntaxWidget text; + + /** The "message panel" on the right. */ + private SwingLogPanel log; + + /** The scrollpane containing the "message panel". */ + private JScrollPane logpane; + + /** The last "find" that the user issued. */ + private String lastFind = ""; + + /** The last find is case-sensitive or not. */ + private boolean lastFindCaseSensitive = true; + + /** The last find is forward or not. */ + private boolean lastFindForward = true; + + /** The icon for a "checked" menu item. */ + private static final Icon iconYes = OurUtil.loadIcon("images/menu1.gif"); + + /** The icon for an "unchecked" menu item. */ + private static final Icon iconNo = OurUtil.loadIcon("images/menu0.gif"); + + /** The system-specific file separator (forward-slash on UNIX, back-slash on Windows, etc.) */ + private static final String fs = System.getProperty("file.separator"); + + /** The darker background color (for the MessageLog window and the Toolbar and the Status Bar, etc.) */ + private static final Color background = new Color(0.9f, 0.9f, 0.9f); + + /** If subrunning==true: 0 means SAT solving; 1 means metamodel; 2 means enumeration. */ + private int subrunningTask = 0; + + /** The amount of memory (in MB) currently allocated for this.subprocess */ + private int subMemoryNow = 0; + + /** The amount of stack (in KB) currently allocated for this.subprocess */ + private int subStackNow = 0; + + /** The list of commands (this field will be cleared to null when the text buffer is edited). */ + private List commands = null; + + /** The latest executed command. */ + private int latestCommand = 0; + + /** The current choices of SAT solver. */ + private List satChoices; + + /** The most recent Alloy version (as queried from alloy.mit.edu); -1 if alloy.mit.edu has not replied yet. */ + private int latestAlloyVersion = (-1); + + /** The most recent Alloy version name (as queried from alloy.mit.edu); "unknown" if alloy.mit.edu has not replied yet. */ + private String latestAlloyVersionName = "unknown"; + + /** If it's not "", then it is the XML filename for the latest satisfying instance or the latest metamodel. */ + private String latestInstance = ""; + + /** If it's not "", then it is the latest instance or metamodel during the most recent click of "Execute". */ + private String latestAutoInstance = ""; + + /** If true, that means the event handlers should return a Runner encapsulating them, rather than perform the actual work. */ + private boolean wrap = false; + + //====== helper methods =================================================// + + /** Inserts "filename" into the "recently opened file list". */ + private void addHistory(String filename) { + String name0=Model0.get(), name1=Model1.get(), name2=Model2.get(); + if (name0.equals(filename)) return; else {Model0.set(filename); Model1.set(name0);} + if (name1.equals(filename)) return; else Model2.set(name1); + if (name2.equals(filename)) return; else Model3.set(name2); + } + + /** Sets the flag "lastFocusIsOnEditor" to be true. */ + private Runner notifyFocusGained() { + if (wrap) return wrapMe(); + lastFocusIsOnEditor=true; + return null; + } + + /** Sets the flag "lastFocusIsOnEditor" to be false. */ + void notifyFocusLost() { lastFocusIsOnEditor=false; } + + /** Updates the status bar at the bottom of the screen. */ + private Runner notifyChange() { + if (wrap) return wrapMe(); + commands=null; + if (text==null) return null; // If this was called prior to the "text" being fully initialized + OurSyntaxWidget t = text.get(); + if (Util.onMac()) frame.getRootPane().putClientProperty("windowModified", Boolean.valueOf(t.modified())); + if (t.isFile()) frame.setTitle(t.getFilename()); else frame.setTitle("Alloy Analyzer "+Version.version()); + toolbar.setBorder(new OurBorder(false, false, text.count()<=1, false)); + int c = t.getCaret(); + int y = t.getLineOfOffset(c)+1; + int x = c - t.getLineStartOffset(y-1)+1; + status.setText("  Line "+y+", Column "+x + +(t.modified()?" [modified]":"")); + return null; + } + + /** Helper method that returns a hopefully very short name for a file name. */ + public static String slightlyShorterFilename(String name) { + if (name.toLowerCase(Locale.US).endsWith(".als")) { + int i=name.lastIndexOf('/'); + if (i>=0) name=name.substring(i+1); + i=name.lastIndexOf('\\'); + if (i>=0) name=name.substring(i+1); + return name.substring(0, name.length()-4); + } else if (name.toLowerCase(Locale.US).endsWith(".xml")) { + int i=name.lastIndexOf('/'); + if (i>0) i=name.lastIndexOf('/', i-1); + if (i>=0) name=name.substring(i+1); + i=name.lastIndexOf('\\'); + if (i>0) i=name.lastIndexOf('\\', i-1); + if (i>=0) name=name.substring(i+1); + return name.substring(0, name.length()-4); + } + return name; + } + + /** Copy the required files from the JAR into a temporary directory. */ + private void copyFromJAR() { + // Compute the appropriate platform + String os = System.getProperty("os.name").toLowerCase(Locale.US).replace(' ','-'); + if (os.startsWith("mac-")) os="mac"; else if (os.startsWith("windows-")) os="windows"; + String arch = System.getProperty("os.arch").toLowerCase(Locale.US).replace(' ','-'); + if (arch.equals("powerpc")) arch="ppc-"+os; else arch=arch.replaceAll("\\Ai[3456]86\\z","x86")+"-"+os; + if (os.equals("mac")) arch="x86-mac"; // our pre-compiled binaries are all universal binaries + // Find out the appropriate Alloy directory + final String platformBinary = alloyHome() + fs + "binary"; + // Write a few test files + try { + (new File(platformBinary)).mkdirs(); + Util.writeAll(platformBinary + fs + "tmp.cnf", "p cnf 3 1\n1 0\n"); + } catch(Err er) { + // The error will be caught later by the "berkmin" or "spear" test + } + // Copy the platform-dependent binaries + Util.copy(true, false, platformBinary, + arch+"/libminisat.so", arch+"/libminisatx1.so", arch+"/libminisat.jnilib", + arch+"/libminisatprover.so", arch+"/libminisatproverx1.so", arch+"/libminisatprover.jnilib", + arch+"/libzchaff.so", arch+"/libzchaffx1.so", arch+"/libzchaff.jnilib", + arch+"/berkmin", arch+"/spear"); + Util.copy(false, false, platformBinary, + arch+"/minisat.dll", arch+"/minisatprover.dll", arch+"/zchaff.dll", + arch+"/berkmin.exe", arch+"/spear.exe"); + // Copy the model files + Util.copy(false, true, alloyHome(), + "models/book/appendixA/addressBook1.als", "models/book/appendixA/addressBook2.als", "models/book/appendixA/barbers.als", + "models/book/appendixA/closure.als", "models/book/appendixA/distribution.als", "models/book/appendixA/phones.als", + "models/book/appendixA/prison.als", "models/book/appendixA/properties.als", "models/book/appendixA/ring.als", + "models/book/appendixA/spanning.als", "models/book/appendixA/tree.als", "models/book/appendixA/tube.als", "models/book/appendixA/undirected.als", + "models/book/appendixE/hotel.thm", "models/book/appendixE/p300-hotel.als", "models/book/appendixE/p303-hotel.als", "models/book/appendixE/p306-hotel.als", + "models/book/chapter2/addressBook1a.als", "models/book/chapter2/addressBook1b.als", "models/book/chapter2/addressBook1c.als", + "models/book/chapter2/addressBook1d.als", "models/book/chapter2/addressBook1e.als", "models/book/chapter2/addressBook1f.als", + "models/book/chapter2/addressBook1g.als", "models/book/chapter2/addressBook1h.als", "models/book/chapter2/addressBook2a.als", + "models/book/chapter2/addressBook2b.als", "models/book/chapter2/addressBook2c.als", "models/book/chapter2/addressBook2d.als", + "models/book/chapter2/addressBook2e.als", "models/book/chapter2/addressBook3a.als", "models/book/chapter2/addressBook3b.als", + "models/book/chapter2/addressBook3c.als", "models/book/chapter2/addressBook3d.als", "models/book/chapter2/theme.thm", + "models/book/chapter4/filesystem.als", "models/book/chapter4/grandpa1.als", + "models/book/chapter4/grandpa2.als", "models/book/chapter4/grandpa3.als", "models/book/chapter4/lights.als", + "models/book/chapter5/addressBook.als", "models/book/chapter5/lists.als", "models/book/chapter5/sets1.als", "models/book/chapter5/sets2.als", + "models/book/chapter6/hotel.thm", "models/book/chapter6/hotel1.als", "models/book/chapter6/hotel2.als", + "models/book/chapter6/hotel3.als", "models/book/chapter6/hotel4.als", "models/book/chapter6/mediaAssets.als", + "models/book/chapter6/memory/abstractMemory.als", "models/book/chapter6/memory/cacheMemory.als", + "models/book/chapter6/memory/checkCache.als", "models/book/chapter6/memory/checkFixedSize.als", + "models/book/chapter6/memory/fixedSizeMemory.als", "models/book/chapter6/memory/fixedSizeMemory_H.als", + "models/book/chapter6/ringElection.thm", "models/book/chapter6/ringElection1.als", "models/book/chapter6/ringElection2.als", + "models/examples/algorithms/dijkstra.als", "models/examples/algorithms/dijkstra.thm", + "models/examples/algorithms/messaging.als", "models/examples/algorithms/messaging.thm", + "models/examples/algorithms/opt_spantree.als", "models/examples/algorithms/opt_spantree.thm", + "models/examples/algorithms/peterson.als", + "models/examples/algorithms/ringlead.als", "models/examples/algorithms/ringlead.thm", + "models/examples/algorithms/s_ringlead.als", + "models/examples/algorithms/stable_mutex_ring.als", "models/examples/algorithms/stable_mutex_ring.thm", + "models/examples/algorithms/stable_orient_ring.als", "models/examples/algorithms/stable_orient_ring.thm", + "models/examples/algorithms/stable_ringlead.als", "models/examples/algorithms/stable_ringlead.thm", + "models/examples/case_studies/INSLabel.als", "models/examples/case_studies/chord.als", + "models/examples/case_studies/chord2.als", "models/examples/case_studies/chordbugmodel.als", + "models/examples/case_studies/com.als", "models/examples/case_studies/firewire.als", "models/examples/case_studies/firewire.thm", + "models/examples/case_studies/ins.als", "models/examples/case_studies/iolus.als", + "models/examples/case_studies/sync.als", "models/examples/case_studies/syncimpl.als", + "models/examples/puzzles/farmer.als", "models/examples/puzzles/farmer.thm", + "models/examples/puzzles/handshake.als", "models/examples/puzzles/handshake.thm", + "models/examples/puzzles/hanoi.als", "models/examples/puzzles/hanoi.thm", + "models/examples/systems/file_system.als", "models/examples/systems/file_system.thm", + "models/examples/systems/javatypes_soundness.als", + "models/examples/systems/lists.als", "models/examples/systems/lists.thm", + "models/examples/systems/marksweepgc.als", "models/examples/systems/views.als", + "models/examples/toys/birthday.als", "models/examples/toys/birthday.thm", + "models/examples/toys/ceilingsAndFloors.als", "models/examples/toys/ceilingsAndFloors.thm", + "models/examples/toys/genealogy.als", "models/examples/toys/genealogy.thm", + "models/examples/toys/grandpa.als", "models/examples/toys/grandpa.thm", + "models/examples/toys/javatypes.als", "models/examples/toys/life.als", "models/examples/toys/life.thm", + "models/examples/toys/numbering.als", "models/examples/toys/railway.als", "models/examples/toys/railway.thm", + "models/examples/toys/trivial.als", + "models/examples/tutorial/farmer.als", + "models/util/boolean.als", "models/util/graph.als", "models/util/integer.als", "models/util/natural.als", + "models/util/ordering.als", "models/util/relation.als", "models/util/seqrel.als", "models/util/sequence.als", + "models/util/sequniv.als", "models/util/ternary.als", "models/util/time.als" + ); + // Record the locations + System.setProperty("alloy.theme0", alloyHome() + fs + "models"); + System.setProperty("alloy.home", alloyHome()); + } + + /** Called when this window is resized. */ + public void componentResized(ComponentEvent e) { + componentMoved(e); + } + + /** Called when this window is moved. */ + public void componentMoved(ComponentEvent e) { + AnalyzerWidth.set(frame.getWidth()); + AnalyzerHeight.set(frame.getHeight()); + AnalyzerX.set(frame.getX()); + AnalyzerY.set(frame.getY()); + } + + /** Called when this window is shown. */ + public void componentShown(ComponentEvent e) {} + + /** Called when this window is hidden. */ + public void componentHidden(ComponentEvent e) {} + + /** Wraps the calling method into a Runnable whose run() will call the calling method with (false) as the only argument. */ + private Runner wrapMe() { + final String name; + try { throw new Exception(); } catch(Exception ex) { name = ex.getStackTrace()[1].getMethodName(); } + Method[] methods = getClass().getDeclaredMethods(); + Method m=null; + for(int i=0; i=0) ans=ans+tmp; + } + } + else if (x.isFile()) { + long tmp=x.length(); + if (ans>=0) ans=ans+tmp; + } + if (delete) x.delete(); + return ans; + } + + //===============================================================================================================// + + /** This method refreshes the "file" menu. */ + private Runner doRefreshFile() { + if (wrap) return wrapMe(); + try { + wrap = true; + filemenu.removeAll(); + menuItem(filemenu, "New", 'N', 'N', doNew()); + menuItem(filemenu, "Open...", 'O', 'O', doOpen()); + if (!Util.onMac()) + menuItem(filemenu, "Open Sample Models...", VK_ALT, 'O', doBuiltin()); + else + menuItem(filemenu, "Open Sample Models...", doBuiltin()); + JMenu recentmenu; + filemenu.add(recentmenu = new JMenu("Open Recent")); + menuItem(filemenu, "Reload all", 'R', 'R', doReloadAll()); + menuItem(filemenu, "Save", 'S', 'S', doSave()); + if (Util.onMac()) + menuItem(filemenu, "Save As...", VK_SHIFT, 'S', doSaveAs()); + else + menuItem(filemenu, "Save As...", 'A', doSaveAs()); + menuItem(filemenu, "Close", 'W', 'W', doClose()); + menuItem(filemenu, "Clear Temporary Directory", doClearTemp()); + menuItem(filemenu, "Quit", 'Q', (Util.onMac() ? -1 : 'Q'), doQuit()); + boolean found = false; + for(Util.StringPref p: new Util.StringPref[]{ Model0, Model1, Model2, Model3 }) { + String name = p.get(); + if (name.length()>0) { found = true; menuItem(recentmenu, name, doOpenFile(name)); } + } + recentmenu.addSeparator(); + menuItem(recentmenu, "Clear Menu", doClearRecent()); + recentmenu.setEnabled(found); + } finally { + wrap = false; + } + return null; + } + + /** This method performs File->New. */ + private Runner doNew() { + if (!wrap) { text.newtab(null); notifyChange(); doShow(); } + return wrapMe(); + } + + /** This method performs File->Open. */ + private Runner doOpen() { + if (wrap) return wrapMe(); + File file=OurDialog.askFile(true, null, ".als", ".als files"); + if (file!=null) { + Util.setCurrentDirectory(file.getParentFile()); + doOpenFile(file.getPath()); + } + return null; + } + + /** This method performs File->OpenBuiltinModels. */ + private Runner doBuiltin() { + if (wrap) return wrapMe(); + File file=OurDialog.askFile(true, alloyHome() + fs + "models", ".als", ".als files"); + if (file!=null) { + doOpenFile(file.getPath()); + } + return null; + } + + /** This method performs File->ReloadAll. */ + private Runner doReloadAll() { + if (!wrap) text.reloadAll(); + return wrapMe(); + } + + /** This method performs File->ClearRecentFiles. */ + private Runner doClearRecent() { + if (!wrap) { Model0.set(""); Model1.set(""); Model2.set(""); Model3.set(""); } + return wrapMe(); + } + + /** This method performs File->Save. */ + private Runner doSave() { + if (!wrap) { + String ans = text.save(false); + if (ans==null) return null; + notifyChange(); + addHistory(ans); + log.clearError(); + } + return wrapMe(); + } + + /** This method performs File->SaveAs. */ + private Runner doSaveAs() { + if (!wrap) { + String ans = text.save(true); + if (ans==null) return null; + notifyChange(); + addHistory(ans); + log.clearError(); + } + return wrapMe(); + } + + /** This method clears the temporary files and then reinitialize the temporary directory. */ + private Runner doClearTemp() { + if (!wrap) { + clearTemporarySpace(); + copyFromJAR(); + log.logBold("Temporary directory has been cleared.\n\n"); + log.logDivider(); + log.flush(); + } + return wrapMe(); + } + + /** This method performs File->Close. */ + private Runner doClose() { + if (!wrap) text.close(); + return wrapMe(); + } + + /** This method performs File->Quit. */ + private Runner doQuit() { + if (!wrap) if (text.closeAll()) { + try { WorkerEngine.stop(); } finally { System.exit(0); } + } + return wrapMe(); + } + + //===============================================================================================================// + + /** This method refreshes the "edit" menu. */ + private Runner doRefreshEdit() { + if (wrap) return wrapMe(); + try { + wrap = true; + boolean canUndo = text.get().canUndo(); + boolean canRedo = text.get().canRedo(); + editmenu.removeAll(); + menuItem(editmenu, "Undo", 'Z', 'Z', doUndo(), canUndo); + if (Util.onMac()) + menuItem(editmenu, "Redo", VK_SHIFT, 'Z', doRedo(), canRedo); + else + menuItem(editmenu, "Redo", 'Y', 'Y', doRedo(), canRedo); + editmenu.addSeparator(); + menuItem(editmenu, "Cut", 'X', 'X', doCut()); + menuItem(editmenu, "Copy", 'C', 'C', doCopy()); + menuItem(editmenu, "Paste", 'V', 'V', doPaste()); + editmenu.addSeparator(); + menuItem(editmenu, "Go To..." , 'T', 'T', doGoto()); + menuItem(editmenu, "Previous File" , VK_PAGE_UP, VK_PAGE_UP, doGotoPrevFile(), text.count()>1); + menuItem(editmenu, "Next File" , VK_PAGE_DOWN, VK_PAGE_DOWN, doGotoNextFile(), text.count()>1); + editmenu.addSeparator(); + menuItem(editmenu, "Find...", 'F', 'F', doFind()); + menuItem(editmenu, "Find Next", 'G', 'G', doFindNext()); + } finally { + wrap = false; + } + return null; + } + + /** This method performs Edit->Undo. */ + private Runner doUndo() { + if (!wrap) text.get().undo(); + return wrapMe(); + } + + /** This method performs Edit->Redo. */ + private Runner doRedo() { + if (!wrap) text.get().redo(); + return wrapMe(); + } + + /** This method performs Edit->Copy. */ + private Runner doCopy() { + if (!wrap) { if (lastFocusIsOnEditor) text.get().copy(); else log.copy(); } + return wrapMe(); + } + + /** This method performs Edit->Cut. */ + private Runner doCut() { + if (!wrap && lastFocusIsOnEditor) text.get().cut(); + return wrapMe(); + } + + /** This method performs Edit->Paste. */ + private Runner doPaste() { + if (!wrap && lastFocusIsOnEditor) text.get().paste(); + return wrapMe(); + } + + /** This method performs Edit->Find. */ + private Runner doFind() { + if (wrap) return wrapMe(); + JTextField x = OurUtil.textfield(lastFind,30); + x.selectAll(); + JCheckBox c = new JCheckBox("Case Sensitive?",lastFindCaseSensitive); + c.setMnemonic('c'); + JCheckBox b = new JCheckBox("Search Backward?",!lastFindForward); + b.setMnemonic('b'); + if (!OurDialog.getInput("Find", "Text:", x, " ", c, b)) return null; + if (x.getText().length() == 0) return null; + lastFind = x.getText(); + lastFindCaseSensitive = c.getModel().isSelected(); + lastFindForward = !b.getModel().isSelected(); + doFindNext(); + return null; + } + + /** This method performs Edit->FindNext. */ + private Runner doFindNext() { + if (wrap) return wrapMe(); + if (lastFind.length()==0) return null; + OurSyntaxWidget t = text.get(); + String all = t.getText(); + int i = Util.indexOf(all, lastFind, t.getCaret()+(lastFindForward?0:-1),lastFindForward,lastFindCaseSensitive); + if (i<0) { + i=Util.indexOf(all, lastFind, lastFindForward?0:(all.length()-1), lastFindForward, lastFindCaseSensitive); + if (i<0) { log.logRed("The specified search string cannot be found."); return null; } + log.logRed("Search wrapped."); + } else { + log.clearError(); + } + if (lastFindForward) t.moveCaret(i, i+lastFind.length()); else t.moveCaret(i+lastFind.length(), i); + t.requestFocusInWindow(); + return null; + } + + /** This method performs Edit->Goto. */ + private Runner doGoto() { + if (wrap) return wrapMe(); + JTextField y = OurUtil.textfield("", 10); + JTextField x = OurUtil.textfield("", 10); + if (!OurDialog.getInput("Go To", "Line Number:", y, "Column Number (optional):", x)) return null; + try { + OurSyntaxWidget t = text.get(); + int xx = 1, yy = Integer.parseInt(y.getText()), lineCount = t.getLineCount(); + if (yy<1) return null; + if (yy>lineCount) {log.logRed("This file only has "+lineCount+" line(s)."); return null;} + if (x.getText().length()!=0) xx=Integer.parseInt(x.getText()); + if (xx<1) {log.logRed("If the column number is specified, it must be 1 or greater."); return null;} + int caret = t.getLineStartOffset(yy-1); + int len = (yy==lineCount ? t.getText().length()+1 : t.getLineStartOffset(yy)) - caret; + if (xx>len) xx=len; + if (xx<1) xx=1; + t.moveCaret(caret+xx-1, caret+xx-1); + t.requestFocusInWindow(); + } catch(NumberFormatException ex) { + log.logRed("The number must be 1 or greater."); + } catch(Throwable ex) { + // This error is not important + } + return null; + } + + /** This method performs Edit->GotoPrevFile. */ + private Runner doGotoPrevFile() { + if (wrap) return wrapMe(); else {text.prev(); return null;} + } + + /** This method performs Edit->GotoNextFile. */ + private Runner doGotoNextFile() { + if (wrap) return wrapMe(); else {text.next(); return null;} + } + + //===============================================================================================================// + + /** This method refreshes the "run" menu. */ + private Runner doRefreshRun() { + if (wrap) return wrapMe(); + KeyStroke ac = KeyStroke.getKeyStroke(VK_E, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()); + try { + wrap = true; + runmenu.removeAll(); + menuItem(runmenu, "Execute Latest Command", 'E', 'E', doExecuteLatest()); + runmenu.add(new JSeparator()); + menuItem(runmenu, "Show Latest Instance", 'L', 'L', doShowLatest(), latestInstance.length()>0); + menuItem(runmenu, "Show Metamodel", 'M', 'M', doShowMetaModel()); + if (Version.experimental) menuItem(runmenu, "Show Parse Tree", 'P', doShowParseTree()); + menuItem(runmenu, "Open Evaluator", 'V', doLoadEvaluator()); + } finally { + wrap = false; + } + List cp = commands; + if (cp==null) { + try { + cp=CompUtil.parseOneModule_fromString(text.get().getText()); + } + catch(Err e) { + commands = null; + runmenu.getItem(0).setEnabled(false); + runmenu.getItem(3).setEnabled(false); + text.shade(new Pos(text.get().getFilename(), e.pos.x, e.pos.y, e.pos.x2, e.pos.y2)); + if ("yes".equals(System.getProperty("debug")) && Verbosity.get()==Verbosity.FULLDEBUG) + log.logRed("Fatal Exception!" + e.dump() + "\n\n"); + else + log.logRed(e.toString()+"\n\n"); + return null; + } + catch(Throwable e) { + commands = null; + runmenu.getItem(0).setEnabled(false); + runmenu.getItem(3).setEnabled(false); + log.logRed("Cannot parse the model.\n"+e.toString()+"\n\n"); + return null; + } + commands=cp; + } + text.clearShade(); + log.clearError(); // To clear any residual error message + if (cp==null) { runmenu.getItem(0).setEnabled(false); runmenu.getItem(3).setEnabled(false); return null; } + if (cp.size()==0) { runmenu.getItem(0).setEnabled(false); return null; } + if (latestCommand>=cp.size()) latestCommand=cp.size()-1; + runmenu.remove(0); + try { + wrap = true; + for(int i=0; i=2) { + JMenuItem y = new JMenuItem("Execute All", null); + y.setMnemonic(VK_A); + y.addActionListener(doRun(-1)); + runmenu.add(y,0); + runmenu.add(new JSeparator(),1); + } + } finally { + wrap = false; + } + return null; + } + + /** This method executes a particular RUN or CHECK command. */ + private Runner doRun(Integer commandIndex) { + if (wrap) return wrapMe(commandIndex); + final int index = commandIndex; + if (WorkerEngine.isBusy()) return null; + if (index==(-2)) subrunningTask=1; else subrunningTask=0; + latestAutoInstance=""; + if (index>=0) latestCommand=index; + if (index==-1 && commands!=null) { + latestCommand=commands.size()-1; + if (latestCommand<0) latestCommand=0; + } + // To update the accelerator to point to the command actually chosen + doRefreshRun(); + OurUtil.enableAll(runmenu); + if (commands==null) return null; + if (commands.size()==0 && index!=-2 && index!=-3) { log.logRed("There are no commands to execute.\n\n"); return null; } + int i=index; + if (i>=commands.size()) i=commands.size()-1; + SimpleCallback1 cb = new SimpleCallback1(this, null, log, Verbosity.get().ordinal(), latestAlloyVersionName, latestAlloyVersion); + SimpleTask1 task = new SimpleTask1(); + A4Options opt = new A4Options(); + opt.tempDirectory = alloyHome() + fs + "tmp"; + opt.solverDirectory = alloyHome() + fs + "binary"; + opt.recordKodkod = RecordKodkod.get(); + opt.noOverflow = NoOverflow.get(); + opt.unrolls = Version.experimental ? Unrolls.get() : (-1); + opt.skolemDepth = SkolemDepth.get(); + opt.coreMinimization = CoreMinimization.get(); + opt.coreGranularity = CoreGranularity.get(); + opt.originalFilename = Util.canon(text.get().getFilename()); + opt.solver = SatSolver.get(); + task.bundleIndex = i; + task.bundleWarningNonFatal = WarningNonfatal.get(); + task.map = text.takeSnapshot(); + task.options = opt.dup(); + task.resolutionMode = (Version.experimental && ImplicitThis.get()) ? 2 : 1; + task.tempdir = maketemp(); + try { + runmenu.setEnabled(false); + runbutton.setVisible(false); + showbutton.setEnabled(false); + stopbutton.setVisible(true); + int newmem = SubMemory.get(), newstack = SubStack.get(); + if (newmem != subMemoryNow || newstack != subStackNow) WorkerEngine.stop(); + if ("yes".equals(System.getProperty("debug")) && Verbosity.get()==Verbosity.FULLDEBUG) + WorkerEngine.runLocally(task, cb); + else + WorkerEngine.run(task, newmem, newstack, alloyHome() + fs + "binary", "", cb); + subMemoryNow = newmem; + subStackNow = newstack; + } catch(Throwable ex) { + WorkerEngine.stop(); + log.logBold("Fatal Error: Solver failed due to unknown reason.\n" + + "One possible cause is that, in the Options menu, your specified\n" + + "memory size is larger than the amount allowed by your OS.\n" + + "Also, please make sure \"java\" is in your program path.\n"); + log.logDivider(); + log.flush(); + doStop(2); + } + return null; + } + + /** This method stops the current run or check (how==0 means DONE, how==1 means FAIL, how==2 means STOP). */ + Runner doStop(Integer how) { + if (wrap) return wrapMe(how); + int h = how; + if (h!=0) { + if (h==2 && WorkerEngine.isBusy()) { WorkerEngine.stop(); log.logBold("\nSolving Stopped.\n"); log.logDivider(); } + WorkerEngine.stop(); + } + runmenu.setEnabled(true); + runbutton.setVisible(true); + showbutton.setEnabled(true); + stopbutton.setVisible(false); + if (latestAutoInstance.length()>0) { + String f=latestAutoInstance; + latestAutoInstance=""; + if (subrunningTask==2) viz.loadXML(f, true); else if (AutoVisualize.get() || subrunningTask==1) doVisualize("XML: "+f); + } + return null; + } + + /** This method executes the latest command. */ + private Runner doExecuteLatest() { + if (wrap) return wrapMe(); + doRefreshRun(); + OurUtil.enableAll(runmenu); + if (commands==null) return null; + int n=commands.size(); + if (n<=0) { log.logRed("There are no commands to execute.\n\n"); return null; } + if (latestCommand>=n) latestCommand=n-1; + if (latestCommand<0) latestCommand=0; + return doRun(latestCommand); + } + + /** This method displays the parse tree. */ + private Runner doShowParseTree() { + if (wrap) return wrapMe(); + doRefreshRun(); + OurUtil.enableAll(runmenu); + if (commands!=null) { + Module world = null; + try { + int resolutionMode = (Version.experimental && ImplicitThis.get()) ? 2 : 1; + A4Options opt = new A4Options(); + opt.tempDirectory = alloyHome() + fs + "tmp"; + opt.solverDirectory = alloyHome() + fs + "binary"; + opt.originalFilename = Util.canon(text.get().getFilename()); + world = CompUtil.parseEverything_fromFile(A4Reporter.NOP, text.takeSnapshot(), opt.originalFilename, resolutionMode); + } catch(Err er) { + text.shade(er.pos); + log.logRed(er.toString()+"\n\n"); + return null; + } + world.showAsTree(this); + } + return null; + } + + /** This method displays the meta model. */ + private Runner doShowMetaModel() { + if (wrap) return wrapMe(); + doRefreshRun(); + OurUtil.enableAll(runmenu); + if (commands!=null) doRun(-2); + return null; + } + + /** This method displays the latest instance. */ + private Runner doShowLatest() { + if (wrap) return wrapMe(); + if (latestInstance.length()==0) + log.logRed("No previous instances are available for viewing.\n\n"); + else + doVisualize("XML: "+latestInstance); + return null; + } + + /** This method happens when the user tries to load the evaluator from the main GUI. */ + private Runner doLoadEvaluator() { + if (wrap) return wrapMe(); + log.logRed("Note: the evaluator is now in the visualizer.\n" + +"Just click the \"Evaluator\" toolbar button\n" + +"when an instance is shown in the visualizer.\n"); + log.flush(); + return null; + } + + //===============================================================================================================// + + /** This method refreshes the "Window" menu for either the SimpleGUI window (isViz==false) or the VizGUI window (isViz==true). */ + private Runner doRefreshWindow(Boolean isViz) { + if (wrap) return wrapMe(isViz); + try { + wrap = true; + JMenu w = (isViz ? windowmenu2 : windowmenu); + w.removeAll(); + if (isViz) { + viz.addMinMaxActions(w); + } else { + menuItem(w, "Minimize", 'M', doMinimize(), iconNo); + menuItem(w, "Zoom", doZoom(), iconNo); + } + w.addSeparator(); + int i = 0; + for(String f: text.getFilenames()) { + JMenuItem it = new JMenuItem("Model: "+slightlyShorterFilename(f)+(text.modified(i) ? " *" : ""), null); + it.setIcon((f.equals(text.get().getFilename()) && !isViz) ? iconYes : iconNo); + it.addActionListener(f.equals(text.get().getFilename()) ? doShow() : doOpenFile(f)); + w.add(it); + i++; + } + if (viz!=null) for(String f:viz.getInstances()) { + JMenuItem it = new JMenuItem("Instance: "+viz.getInstanceTitle(f), null); + it.setIcon((isViz && f.equals(viz.getXMLfilename())) ? iconYes : iconNo); + it.addActionListener(doVisualize("XML: "+f)); + w.add(it); + } + } finally { + wrap = false; + } + return null; + } + + /** This method minimizes the window. */ + private Runner doMinimize() { + if (wrap) return wrapMe(); else {OurUtil.minimize(frame); return null;} + } + + /** This method alternatingly maximizes or restores the window. */ + private Runner doZoom() { + if (wrap) return wrapMe(); else {OurUtil.zoom(frame); return null;} + } + + /** This method bring this window to the foreground. */ + private Runner doShow() { + if (wrap) return wrapMe(); + OurUtil.show(frame); + text.get().requestFocusInWindow(); + return null; + } + + //===============================================================================================================// + + /** This method refreshes the "Option" menu. */ + private Runner doRefreshOption() { + if (wrap) return wrapMe(); + try { + wrap = true; + optmenu.removeAll(); + menuItem(optmenu, "Welcome Message at Start Up: "+(Welcome.get() < welcomeLevel ? "Yes" : "No"), doOptWelcome()); + // + final SatSolver now = SatSolver.get(); + final JMenu sat = new JMenu("SAT Solver: "+now); + for(SatSolver sc:satChoices) { menuItem(sat, ""+sc, doOptSolver(sc), sc==now?iconYes:iconNo); } + optmenu.add(sat); + // + menuItem(optmenu, "Warnings are Fatal: "+(WarningNonfatal.get()?"No":"Yes"), doOptWarning()); + // + final int mem = SubMemory.get(); + final JMenu subMemoryMenu = new JMenu("Maximum Memory to Use: " + mem + "M"); + for(int n: allowedMemorySizes) { + menuItem(subMemoryMenu, ""+n+"M", doOptMemory(n), n==mem?iconYes:iconNo); + } + optmenu.add(subMemoryMenu); + // + final int stack = SubStack.get(); + final JMenu subStackMenu = new JMenu("Maximum Stack to Use: " + stack + "k"); + boolean debug = "yes".equals(System.getProperty("debug")); + for(int n: new int[]{16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536}) { + if (debug || n>=1024) menuItem(subStackMenu, ""+n+"k", doOptStack(n), n==stack?iconYes:iconNo); + } + optmenu.add(subStackMenu); + // + final Verbosity vnow = Verbosity.get(); + final JMenu verb = new JMenu("Message Verbosity: "+vnow); + for(Verbosity vb: Verbosity.values()) { menuItem(verb, ""+vb, doOptVerbosity(vb), vb==vnow?iconYes:iconNo); } + optmenu.add(verb); + // + menuItem(optmenu, "Syntax Highlighting: "+(SyntaxDisabled.get()?"No":"Yes"), doOptSyntaxHighlighting()); + // + final int fontSize = FontSize.get(); + final JMenu size = new JMenu("Font Size: "+fontSize); + for(int n: new Integer[]{9,10,11,12,14,16,18,20,22,24,26,28,32,36,40,44,48,54,60,66,72}) { + menuItem(size, ""+n, doOptFontsize(n), n==fontSize?iconYes:iconNo); + } + optmenu.add(size); + // + menuItem(optmenu, "Font: "+FontName.get()+"...", doOptFontname()); + // + if (Util.onMac() || Util.onWindows()) menuItem(optmenu, "Use anti-aliasing: Yes", false); + else menuItem(optmenu, "Use anti-aliasing: "+(AntiAlias.get()?"Yes":"No"), doOptAntiAlias()); + // + final int tabSize = TabSize.get(); + final JMenu tabSizeMenu = new JMenu("Tab Size: "+tabSize); + for(int n=1; n<=12; n++) { menuItem(tabSizeMenu, ""+n, doOptTabsize(n), n==tabSize?iconYes:iconNo); } + optmenu.add(tabSizeMenu); + // + final int skDepth = SkolemDepth.get(); + final JMenu skDepthMenu = new JMenu("Skolem Depth: "+skDepth); + for(int n=0; n<=4; n++) { menuItem(skDepthMenu, ""+n, doOptSkolemDepth(n), n==skDepth?iconYes:iconNo); } + optmenu.add(skDepthMenu); + // + if (Version.experimental) { + final int unrolls = Unrolls.get(); + final JMenu unrollsMenu = new JMenu("Recursion Depth: "+(unrolls<0 ? "Disabled" : (""+unrolls))); + for(int n=(-1); n<=3; n++) { menuItem(unrollsMenu, (n<0 ? "Disabled" : (""+n)), doOptUnrolls(n), n==unrolls?iconYes:iconNo); } + optmenu.add(unrollsMenu); + } + // + final int min = CoreMinimization.get(); + final String[] minLabelLong=new String[]{"Slow (guarantees local minimum)", "Medium", "Fast (initial unsat core)"}; + final String[] minLabelShort=new String[]{"Slow", "Medium", "Fast"}; + final JMenu cmMenu = new JMenu("Unsat Core Minimization Strategy: "+minLabelShort[min]); + for(int n=0; n<=2; n++) { menuItem(cmMenu, minLabelLong[n], doOptCore(n), n==min?iconYes:iconNo); } + if (now!=SatSolver.MiniSatProverJNI) cmMenu.setEnabled(false); + optmenu.add(cmMenu); + // + final int gran = CoreGranularity.get(); + final String[] granLabelLong=new String[]{"Top-level conjuncts only", "Flatten the formula once at the beginning", "Flatten the formula at the beginning and after skolemizing", "In addition to flattening the formula twice, expand the quantifiers"}; + final String[] granLabelShort=new String[]{"Top-level", "Flatten once", "Flatten twice", "Expand quantifiers"}; + final JMenu cgMenu = new JMenu("Core Granularity: "+granLabelShort[gran]); + for(int n=0; n0) { + FontName.set(f); + text.setFont(f, size, TabSize.get()); + status.setFont(new Font(f, Font.PLAIN, size)); + log.setFontName(f); + } + return null; + } + + /** This method changes the font size. */ + private Runner doOptFontsize(Integer size) { + if (wrap) return wrapMe(size); + int n=size; + FontSize.set(n); + String f = FontName.get(); + text.setFont(f, n, TabSize.get()); + status.setFont(new Font(f, Font.PLAIN, n)); + log.setFontSize(n); + viz.doSetFontSize(n); + return null; + } + + /** This method changes the tab size. */ + private Runner doOptTabsize(Integer size) { + if (!wrap) { TabSize.set(size.intValue()); text.setFont(FontName.get(), FontSize.get(), size.intValue()); } + return wrapMe(size); + } + + /** This method changes the number of unrolls. */ + private Runner doOptUnrolls(Integer num) { + if (!wrap) Unrolls.set(num.intValue()); + return wrapMe(num); + } + + /** This method changes the skolem depth. */ + private Runner doOptSkolemDepth(Integer size) { + if (!wrap) SkolemDepth.set(size.intValue()); + return wrapMe(size); + } + + /** This method changes the speed of unsat core minimization (larger integer means faster but less optimal). */ + private Runner doOptCore(Integer speed) { + if (!wrap) CoreMinimization.set(speed.intValue()); + return wrapMe(speed); + } + + /** This method changes the granularity of the unsat core (larger integer means more granular). */ + private Runner doCoreGran(Integer gran) { + if (!wrap) CoreGranularity.set(gran.intValue()); + return wrapMe(gran); + } + + /** This method toggles the "antialias" checkbox. */ + private Runner doOptAntiAlias() { + if (!wrap) { boolean newValue = !AntiAlias.get(); AntiAlias.set(newValue); OurAntiAlias.enableAntiAlias(newValue); } + return wrapMe(); + } + + /** This method toggles the "visualize automatically" checkbox. */ + private Runner doOptAutoVisualize() { + if (!wrap) AutoVisualize.set(!AutoVisualize.get()); + return wrapMe(); + } + + /** This method toggles the "record Kodkod input/output" checkbox. */ + private Runner doOptRecordKodkod() { + if (!wrap) RecordKodkod.set(!RecordKodkod.get()); + return wrapMe(); + } + + /** This method toggles the "enable new `implicit this' name resolution" checkbox. */ + private Runner doOptImplicitThis() { + if (!wrap) ImplicitThis.set(!ImplicitThis.get()); + return wrapMe(); + } + + private Runner doOptNoOverflow() { + if (!wrap) NoOverflow.set(!NoOverflow.get()); + return wrapMe(); + } + + /** This method toggles the "syntax highlighting" checkbox. */ + private Runner doOptSyntaxHighlighting() { + if (!wrap) { + boolean flag = SyntaxDisabled.get(); + text.enableSyntax(flag); + SyntaxDisabled.set(!flag); + } + return wrapMe(); + } + + //===============================================================================================================// + + /** This method displays the about box. */ + private Runner doAbout() { + if (wrap) return wrapMe(); + OurDialog.showmsg("About Alloy Analyzer " + Version.version(), + OurUtil.loadIcon("images/logo.gif"), + "Alloy Analyzer " + Version.version(), + "Build date: " + Version.buildDate(), + " ", + "Lead developer: Felix Chang", + "Engine developer: Emina Torlak", + "Graphic design: Julie Pelaez", + "Project lead: Daniel Jackson", + " ", + "Please post comments and questions to the Alloy Community Forum at http://alloy.mit.edu/", + " ", + "Thanks to: Ilya Shlyakhter, Manu Sridharan, Derek Rayside, Jonathan Edwards, Gregory Dennis,", + "Robert Seater, Edmond Lau, Vincent Yeung, Sam Daitch, Andrew Yip, Jongmin Baek, Ning Song,", + "Arturo Arizpe, Li-kuo (Brian) Lin, Joseph Cohen, Jesse Pavel, Ian Schechter, and Uriel Schafer." + ); + return null; + } + + /** This method displays the help html. */ + private Runner doHelp() { + if (wrap) return wrapMe(); + try { + int w=OurUtil.getScreenWidth(), h=OurUtil.getScreenHeight(); + final JFrame frame = new JFrame(); + final JEditorPane html1 = new JEditorPane("text/html", ""); + final JEditorPane html2 = new JEditorPane("text/html", ""); + final HTMLDocument doc1 = (HTMLDocument) (html1.getDocument()); doc1.setAsynchronousLoadPriority(-1); + final HTMLDocument doc2 = (HTMLDocument) (html2.getDocument()); doc2.setAsynchronousLoadPriority(-1); + html1.setPage(this.getClass().getResource("/help/Nav.html")); + html2.setPage(this.getClass().getResource("/help/index.html")); + HyperlinkListener hl=new HyperlinkListener() { + public final void hyperlinkUpdate(HyperlinkEvent e) { + try { + if (e.getEventType()!=HyperlinkEvent.EventType.ACTIVATED) return; + if (e.getURL().getPath().endsWith("quit.htm")) { frame.dispose(); return; } + HTMLDocument doc = (HTMLDocument) (html2.getDocument()); + doc.setAsynchronousLoadPriority(-1); // So that we can catch any exception that may occur + html2.setPage(e.getURL()); + html2.requestFocusInWindow(); + } catch(Throwable ex) { } + } + }; + html1.setEditable(false); html1.setBorder(new EmptyBorder(3,3,3,3)); html1.addHyperlinkListener(hl); + html2.setEditable(false); html2.setBorder(new EmptyBorder(3,3,3,3)); html2.addHyperlinkListener(hl); + JScrollPane scroll1 = OurUtil.scrollpane(html1); + JScrollPane scroll2 = OurUtil.scrollpane(html2); + JSplitPane split = OurUtil.splitpane(JSplitPane.HORIZONTAL_SPLIT, scroll1, scroll2, 150); + split.setResizeWeight(0d); + frame.setTitle("Alloy Analyzer Online Guide"); + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(split, BorderLayout.CENTER); + frame.pack(); + frame.setSize(w-w/10, h-h/10); + frame.setLocation(w/20, h/20); + frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + frame.setVisible(true); + html2.requestFocusInWindow(); + } catch(Throwable ex) { return null; } + return null; + } + + /** This method displays the license box. */ + private Runner doLicense() { + if (wrap) return wrapMe(); + final String JAR = Util.jarPrefix(); + String alloytxt; + try { alloytxt = Util.readAll(JAR + "LICENSES" + File.separator + "Alloy.txt"); } catch(IOException ex) { return null; } + final JTextArea text = OurUtil.textarea(alloytxt, 15, 85, false, false, new EmptyBorder(2, 2, 2, 2), new Font("Monospaced", Font.PLAIN, 12)); + final JScrollPane scroll = OurUtil.scrollpane(text, new LineBorder(Color.DARK_GRAY, 1)); + final JComboBox combo = new OurCombobox(new String[]{"Alloy","Kodkod","JavaCup","SAT4J","ZChaff","MiniSat"}) { + private static final long serialVersionUID = 0; + @Override public void do_changed(Object value) { + if (value instanceof String) { + try { + String content = Util.readAll(JAR + "LICENSES" + File.separator + value + ".txt"); + text.setText(content); + } catch(IOException ex) { + text.setText("Sorry: an error has occurred in displaying the license file."); + } + } + text.setCaretPosition(0); + } + }; + OurDialog.showmsg("Copyright Notices", + "The source code for the Alloy Analyzer is available under the MIT license.", + " ", + "The Alloy Analyzer utilizes several third-party packages whose code may", + "be distributed under a different license. We are extremely grateful to", + "the authors of these packages for making their source code freely available.", + " ", + OurUtil.makeH(null, "See the copyright notice for: ", combo, null), + " ", + scroll + ); + return null; + } + + /** This method changes the latest instance. */ + void doSetLatest(String arg) { + latestInstance = arg; + latestAutoInstance = arg; + } + + /** The color to use for functions/predicate/paragraphs that contains part of the unsat core. */ + final Color supCoreColor = new Color(0.95f, 0.1f, 0.1f); + + /** The color to use for the unsat core. */ + final Color coreColor = new Color(0.9f, 0.4f, 0.4f); + + /** The color to use for functions/predicate used by the Unsat core. */ + final Color subCoreColor = new Color(0.9f, 0.7f, 0.7f); + + /** This method displays a particular instance or message. */ + @SuppressWarnings("unchecked") + Runner doVisualize(String arg) { + if (wrap) return wrapMe(arg); + text.clearShade(); + if (arg.startsWith("MSG: ")) { // MSG: message + OurDialog.showtext("Detailed Message", arg.substring(5)); + } + if (arg.startsWith("CORE: ")) { // CORE: filename + String filename = Util.canon(arg.substring(6)); + Pair,Set> hCore; + Set lCore; + InputStream is = null; + ObjectInputStream ois = null; + try { + is = new FileInputStream(filename); + ois = new ObjectInputStream(is); + hCore = (Pair,Set>) ois.readObject(); + lCore = (Set) ois.readObject(); + } catch(Throwable ex) { + log.logRed("Error reading or parsing the core \""+filename+"\"\n"); + return null; + } finally { + Util.close(ois); + Util.close(is); + } + text.clearShade(); + text.shade(hCore.b, subCoreColor, false); + text.shade(hCore.a, coreColor, false); + // shade again, because if not all files were open, some shadings will have no effect + text.shade(hCore.b, subCoreColor, false); + text.shade(hCore.a, coreColor, false); + } + if (arg.startsWith("POS: ")) { // POS: x1 y1 x2 y2 filename + Scanner s=new Scanner(arg.substring(5)); + int x1=s.nextInt(), y1=s.nextInt(), x2=s.nextInt(), y2=s.nextInt(); + String f=s.nextLine(); + if (f.length()>0 && f.charAt(0)==' ') f=f.substring(1); // Get rid of the space after Y2 + Pos p=new Pos(Util.canon(f), x1, y1, x2, y2); + text.shade(p); + } + if (arg.startsWith("CNF: ")) { // CNF: filename + String filename=Util.canon(arg.substring(5)); + try { String text=Util.readAll(filename); OurDialog.showtext("Text Viewer", text); } + catch(IOException ex) { log.logRed("Error reading the file \""+filename+"\"\n"); } + } + if (arg.startsWith("XML: ")) { // XML: filename + viz.loadXML(Util.canon(arg.substring(5)), false); + } + return null; + } + + /** This method opens a particular file. */ + private Runner doOpenFile(String arg) { + if (wrap) return wrapMe(arg); + String f=Util.canon(arg); + if (!text.newtab(f)) return null; + if (text.get().isFile()) addHistory(f); + doShow(); + text.get().requestFocusInWindow(); + log.clearError(); + return null; + } + + /** This object performs solution enumeration. */ + private final Computer enumerator = new Computer() { + public String compute(Object input) { + final String arg = (String)input; + OurUtil.show(frame); + if (WorkerEngine.isBusy()) + throw new RuntimeException("Alloy4 is currently executing a SAT solver command. Please wait until that command has finished."); + SimpleCallback1 cb = new SimpleCallback1(SimpleGUI.this, viz, log, Verbosity.get().ordinal(), latestAlloyVersionName, latestAlloyVersion); + SimpleTask2 task = new SimpleTask2(); + task.filename = arg; + try { + WorkerEngine.run(task, SubMemory.get(), SubStack.get(), alloyHome() + fs + "binary", "", cb); +// task.run(cb); + } catch(Throwable ex) { + WorkerEngine.stop(); + log.logBold("Fatal Error: Solver failed due to unknown reason.\n" + + "One possible cause is that, in the Options menu, your specified\n" + + "memory size is larger than the amount allowed by your OS.\n" + + "Also, please make sure \"java\" is in your program path.\n"); + log.logDivider(); + log.flush(); + doStop(2); + return arg; + } + subrunningTask=2; + runmenu.setEnabled(false); + runbutton.setVisible(false); + showbutton.setEnabled(false); + stopbutton.setVisible(true); + return arg; + } + }; + + /** Converts an A4TupleSet into a SimTupleset object. */ + private static SimTupleset convert(Object object) throws Err { + if (!(object instanceof A4TupleSet)) throw new ErrorFatal("Unexpected type error: expecting an A4TupleSet."); + A4TupleSet s = (A4TupleSet)object; + if (s.size()==0) return SimTupleset.EMPTY; + List list = new ArrayList(s.size()); + int arity = s.arity(); + for(A4Tuple t: s) { + String[] array = new String[arity]; + for(int i=0; i fc = new LinkedHashMap(); + XMLNode x = new XMLNode(new File(filename)); + if (!x.is("alloy")) throw new Exception(); + String mainname=null; + for(XMLNode sub: x) if (sub.is("instance")) { + mainname=sub.getAttribute("filename"); + break; + } + if (mainname==null) throw new Exception(); + for(XMLNode sub: x) if (sub.is("source")) { + String name = sub.getAttribute("filename"); + String content = sub.getAttribute("content"); + fc.put(name, content); + } + root = CompUtil.parseEverything_fromFile(A4Reporter.NOP, fc, mainname, (Version.experimental && ImplicitThis.get()) ? 2 : 1); + ans = A4SolutionReader.read(root.getAllReachableSigs(), x); + for(ExprVar a:ans.getAllAtoms()) { root.addGlobal(a.label, a); } + for(ExprVar a:ans.getAllSkolems()) { root.addGlobal(a.label, a); } + } catch(Throwable ex) { + throw new ErrorFatal("Failed to read or parse the XML file."); + } + try { + Expr e = CompUtil.parseOneExpression_fromString(root, str); + if ("yes".equals(System.getProperty("debug")) && Verbosity.get()==Verbosity.FULLDEBUG) { + SimInstance simInst = convert(root, ans); + return simInst.visitThis(e).toString() + (simInst.wasOverflow() ? " (OF)" : ""); + } else + return ans.eval(e).toString(); + } catch(HigherOrderDeclException ex) { + throw new ErrorType("Higher-order quantification is not allowed in the evaluator."); + } + } + }; + + /** Returns true iff the output says "s SATISFIABLE" (while ignoring comment lines and value lines) */ + private static boolean isSat(String output) { + int i=0, n=output.length(); + // skip COMMENT lines and VALUE lines + while(iscreenWidth) width=screenWidth; + int height=AnalyzerHeight.get(); + if (height<=0) height=screenHeight/10*8; else if (height<100) height=100; + if (height>screenHeight) height=screenHeight; + int x=AnalyzerX.get(); if (x<0) x=screenWidth/10; if (x>screenWidth-100) x=screenWidth-100; + int y=AnalyzerY.get(); if (y<0) y=screenHeight/10; if (y>screenHeight-100) y=screenHeight-100; + + // Put up a slash screen + final JFrame frame = new JFrame("Alloy Analyzer"); + frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + frame.pack(); + if (!Util.onMac() && !Util.onWindows()) { + String gravity = System.getenv("_JAVA_AWT_WM_STATIC_GRAVITY"); + if (gravity==null || gravity.length()==0) { + // many Window managers do not respect ICCCM2; this should help avoid the Title Bar being shifted "off screen" + if (x<30) { if (x<0) x=0; width=width-(30-x); x=30; } + if (y<30) { if (y<0) y=0; height=height-(30-y); y=30; } + } + if (width<100) width=100; + if (height<100) height=100; + } + frame.setSize(width,height); + frame.setLocation(x,y); + frame.setVisible(true); + frame.setTitle("Alloy Analyzer "+Version.version()+" loading... please wait..."); + final int windowWidth = width; + // We intentionally call setVisible(true) first before settings the "please wait" title, + // since we want the minimized window title on Linux/FreeBSD to just say Alloy Analyzer + + // Test the allowed memory sizes + final WorkerEngine.WorkerCallback c = new WorkerEngine.WorkerCallback() { + private final List allowed = new ArrayList(); + private final List toTry = new ArrayList(Arrays.asList(256,512,768,1024,1536,2048,2560,3072,3584,4096)); + private int mem; + public synchronized void callback(Object msg) { + if (toTry.size()==0) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { SimpleGUI.this.frame=frame; SimpleGUI.this.finishInit(args, allowed, windowWidth); } + }); + return; + } + try { mem=toTry.remove(0); WorkerEngine.stop(); WorkerEngine.run(dummyTask, mem, 128, "", "", this); return; } catch(IOException ex) { fail(); } + } + public synchronized void done() { + //System.out.println("Alloy4 can use "+mem+"M"); System.out.flush(); + allowed.add(mem); + callback(null); + } + public synchronized void fail() { + //System.out.println("Alloy4 cannot use "+mem+"M"); System.out.flush(); + callback(null); + } + }; + c.callback(null); + } + + private void finishInit(String[] args, List initialAllowedMemorySizes, int width) { + + // Add the listeners + try { + wrap = true; + frame.addWindowListener(doQuit()); + } finally { + wrap = false; + } + frame.addComponentListener(this); + + // initialize the "allowed memory sizes" array + allowedMemorySizes = new ArrayList(initialAllowedMemorySizes); + int newmem = SubMemory.get(); + if (!allowedMemorySizes.contains(newmem)) { + int newmemlen = allowedMemorySizes.size(); + if (allowedMemorySizes.contains(768) || newmemlen==0) + SubMemory.set(768); // a nice default value + else + SubMemory.set(allowedMemorySizes.get(newmemlen-1)); + } + + // Choose the appropriate font + int fontSize=FontSize.get(); + String fontName=FontName.get(); + while(true) { + if (!OurDialog.hasFont(fontName)) fontName="Lucida Grande"; else break; + if (!OurDialog.hasFont(fontName)) fontName="Verdana"; else break; + if (!OurDialog.hasFont(fontName)) fontName="Courier New"; else break; + if (!OurDialog.hasFont(fontName)) fontName="Lucida Grande"; + break; + } + FontName.set(fontName); + + // Copy required files from the JAR + copyFromJAR(); + final String binary = alloyHome() + fs + "binary"; + + // Create the menu bar + JMenuBar bar = new JMenuBar(); + try { + wrap = true; + filemenu = menu(bar, "&File", doRefreshFile()); + editmenu = menu(bar, "&Edit", doRefreshEdit()); + runmenu = menu(bar, "E&xecute", doRefreshRun()); + optmenu = menu(bar, "&Options", doRefreshOption()); + windowmenu = menu(bar, "&Window", doRefreshWindow(false)); + windowmenu2 = menu(null, "&Window", doRefreshWindow(true)); + helpmenu = menu(bar, "&Help", null); + if (!Util.onMac()) menuItem(helpmenu, "About Alloy...", 'A', doAbout()); + menuItem(helpmenu, "Quick Guide", 'Q', doHelp()); + menuItem(helpmenu, "See the Copyright Notices...", 'L', doLicense()); + } finally { + wrap = false; + } + + // Pre-load the visualizer + viz = new VizGUI(false, "", windowmenu2, enumerator, evaluator); + viz.doSetFontSize(FontSize.get()); + + // Create the toolbar + try { + wrap = true; + toolbar = new JToolBar(); + toolbar.setFloatable(false); + if (!Util.onMac()) toolbar.setBackground(background); + toolbar.add(OurUtil.button("New", "Starts a new blank model", "images/24_new.gif", doNew())); + toolbar.add(OurUtil.button("Open", "Opens an existing model", "images/24_open.gif", doOpen())); + toolbar.add(OurUtil.button("Reload", "Reload all the models from disk", "images/24_reload.gif", doReloadAll())); + toolbar.add(OurUtil.button("Save", "Saves the current model", "images/24_save.gif", doSave())); + toolbar.add(runbutton=OurUtil.button("Execute", "Executes the latest command", "images/24_execute.gif", doExecuteLatest())); + toolbar.add(stopbutton=OurUtil.button("Stop", "Stops the current analysis", "images/24_execute_abort2.gif", doStop(2))); + stopbutton.setVisible(false); + toolbar.add(showbutton=OurUtil.button("Show", "Shows the latest instance", "images/24_graph.gif", doShowLatest())); + toolbar.add(Box.createHorizontalGlue()); + toolbar.setBorder(new OurBorder(false,false,false,false)); + } finally { + wrap = false; + } + + // Choose the antiAlias setting + OurAntiAlias.enableAntiAlias(AntiAlias.get()); + + // Create the message area + logpane = OurUtil.scrollpane(null); + log = new SwingLogPanel(logpane, fontName, fontSize, background, Color.BLACK, new Color(.7f,.2f,.2f), this); + + // Create the text area + text = new OurTabbedSyntaxWidget(fontName, fontSize, TabSize.get()); + text.listeners.add(this); + text.enableSyntax(! SyntaxDisabled.get()); + + // Add everything to the frame, then display the frame + Container all=frame.getContentPane(); + all.setLayout(new BorderLayout()); + all.removeAll(); + JPanel lefthalf=new JPanel(); + lefthalf.setLayout(new BorderLayout()); + lefthalf.add(toolbar, BorderLayout.NORTH); + text.addTo(lefthalf, BorderLayout.CENTER); + splitpane = OurUtil.splitpane(JSplitPane.HORIZONTAL_SPLIT, lefthalf, logpane, width/2); + splitpane.setResizeWeight(0.5D); + status = OurUtil.make(OurAntiAlias.label(" "), new Font(fontName, Font.PLAIN, fontSize), Color.BLACK, background); + status.setBorder(new OurBorder(true,false,false,false)); + all.add(splitpane, BorderLayout.CENTER); + all.add(status, BorderLayout.SOUTH); + + // Generate some informative log messages + log.logBold("Alloy Analyzer "+Version.version()+" (build date: "+Version.buildDate()+")\n\n"); + + // If on Mac, then register an application listener + try { + wrap = true; + if (Util.onMac()) MacUtil.registerApplicationListener(doShow(), doAbout(), doOpenFile(""), doQuit()); + } finally { + wrap = false; + } + + // Add the new JNI location to the java.library.path + try { + System.setProperty("java.library.path", binary); + // The above line is actually useless on Sun JDK/JRE (see Sun's bug ID 4280189) + // The following 4 lines should work for Sun's JDK/JRE (though they probably won't work for others) + String[] newarray = new String[]{binary}; + java.lang.reflect.Field old = ClassLoader.class.getDeclaredField("usr_paths"); + old.setAccessible(true); + old.set(null,newarray); + } catch (Throwable ex) { } + + // Testing the SAT solvers + if (1==1) { + satChoices = SatSolver.values().makeCopy(); +// String test1 = Subprocess.exec(20000, new String[]{binary+fs+"berkmin", binary+fs+"tmp.cnf"}); +// if (!isSat(test1)) satChoices.remove(SatSolver.BerkMinPIPE); + satChoices.remove(SatSolver.BerkMinPIPE); + String test2 = Subprocess.exec(20000, new String[]{binary+fs+"spear", "--model", "--dimacs", binary+fs+"tmp.cnf"}); + if (!isSat(test2)) satChoices.remove(SatSolver.SpearPIPE); + if (!loadLibrary("minisat")) { + log.logBold("Warning: JNI-based SAT solver does not work on this platform.\n"); + log.log("This is okay, since you can still use SAT4J as the solver.\n"+ + "For more information, please visit http://alloy.mit.edu/alloy4/\n"); + log.logDivider(); + log.flush(); + satChoices.remove(SatSolver.MiniSatJNI); + } + if (!loadLibrary("minisatprover")) satChoices.remove(SatSolver.MiniSatProverJNI); + if (!loadLibrary("zchaff")) satChoices.remove(SatSolver.ZChaffJNI); + SatSolver now = SatSolver.get(); + if (!satChoices.contains(now)) { + now=SatSolver.ZChaffJNI; + if (!satChoices.contains(now)) now=SatSolver.SAT4J; + now.set(); + } + if (now==SatSolver.SAT4J && satChoices.size()>3 && satChoices.contains(SatSolver.CNF) && satChoices.contains(SatSolver.KK)) { + log.logBold("Warning: Alloy4 defaults to SAT4J since it is pure Java and very reliable.\n"); + log.log("For faster performance, go to Options menu and try another solver like MiniSat.\n"); + log.log("If these native solvers fail on your computer, remember to change back to SAT4J.\n"); + log.logDivider(); + log.flush(); + } + } + + // If the temporary directory has become too big, then tell the user they can "clear temporary directory". + long space = computeTemporarySpaceUsed(); + if (space<0 || space>=20*1024768) { + if (space<0) log.logBold("Warning: Alloy4's temporary directory has exceeded 1024M.\n"); + else log.logBold("Warning: Alloy4's temporary directory now uses "+(space/1024768)+"M.\n"); + log.log("To clear the temporary directory,\n" + +"go to the File menu and click \"Clear Temporary Directory\"\n"); + log.logDivider(); + log.flush(); + } + + // Refreshes all the menu items + doRefreshFile(); OurUtil.enableAll(filemenu); + doRefreshEdit(); OurUtil.enableAll(editmenu); + doRefreshRun(); OurUtil.enableAll(runmenu); + doRefreshOption(); + doRefreshWindow(false); OurUtil.enableAll(windowmenu); + frame.setJMenuBar(bar); + + // Open the given file, if a filename is given in the command line + for(String f:args) if (f.toLowerCase(Locale.US).endsWith(".als")) { + File file = new File(f); + if (file.exists() && file.isFile()) doOpenFile(file.getPath()); + } + + // Update the title and status bar + notifyChange(); + text.get().requestFocusInWindow(); + + // Launch the welcome screen if needed + if (!"yes".equals(System.getProperty("debug")) && Welcome.get() < welcomeLevel) { + JCheckBox again = new JCheckBox("Show this message every time you start the Alloy Analyzer"); + again.setSelected(true); + OurDialog.showmsg("Welcome", + "Thank you for using the Alloy Analyzer "+Version.version(), + " ", + "Version 4 of the Alloy Analyzer is a complete rewrite,", + "offering improvements in robustness, performance and usability.", + "Models written in Alloy 3 will require some small alterations to run in Alloy 4.", + " ", + "Here are some quick tips:", + " ", + "* Function calls now use [ ] instead of ( )", + " For more details, please see http://alloy.mit.edu/alloy4/quickguide/", + " ", + "* The Execute button always executes the latest command.", + " To choose which command to execute, go to the Execute menu.", + " ", + "* The Alloy Analyzer comes with a variety of sample models.", + " To see them, go to the File menu and click Open Sample Models.", + " ", + again + ); + doShow(); + if (!again.isSelected()) Welcome.set(welcomeLevel); + } + + // Periodically ask the MailBug thread to see if there is a newer version or not + final long now = System.currentTimeMillis(); + final Timer t = new Timer(800, null); + t.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int n = MailBug.latestBuildNumber(); + // If beyond 3 seconds, then we should stop because the log message may run into other user messages + if (System.currentTimeMillis() - now >= 3000 || n <= Version.buildNumber()) { t.stop(); return; } + latestAlloyVersion = n; + latestAlloyVersionName = MailBug.latestBuildName(); + log.logBold("An updated version of the Alloy Analyzer has been released.\n"); + log.log("Please visit alloy.mit.edu to download the latest version:\nVersion " + latestAlloyVersionName + "\n"); + log.logDivider(); + log.flush(); + t.stop(); + } + }); + t.start(); + } + + /** {@inheritDoc} */ + public Object do_action(Object sender, Event e) { + if (sender instanceof OurTabbedSyntaxWidget) switch(e) { + case FOCUSED: notifyFocusGained(); break; + case STATUS_CHANGE: notifyChange(); break; + } + return true; + } + + /** {@inheritDoc} */ + public Object do_action(Object sender, Event e, Object arg) { + if (sender instanceof OurTree && e==Event.CLICK && arg instanceof Browsable) { + Pos p = ((Browsable)arg).pos(); + if (p==Pos.UNKNOWN) p = ((Browsable)arg).span(); + text.shade(p); + } + return true; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/SimpleReporter.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/SimpleReporter.java new file mode 100644 index 00000000..eb3b201f --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/SimpleReporter.java @@ -0,0 +1,497 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4whole; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.ConstMap; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.MailBug; +import edu.mit.csail.sdg.alloy4.OurDialog; +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.alloy4.XMLNode; +import edu.mit.csail.sdg.alloy4.WorkerEngine.WorkerCallback; +import edu.mit.csail.sdg.alloy4.WorkerEngine.WorkerTask; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; +import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Options; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.A4SolutionReader; +import edu.mit.csail.sdg.alloy4compiler.translator.A4SolutionWriter; +import edu.mit.csail.sdg.alloy4compiler.translator.TranslateAlloyToKodkod; +import edu.mit.csail.sdg.alloy4viz.StaticInstanceReader; +import edu.mit.csail.sdg.alloy4viz.VizGUI; + +/** This helper method is used by SimpleGUI. */ + +final class SimpleReporter extends A4Reporter { + + public static final class SimpleCallback1 implements WorkerCallback { + private final SimpleGUI gui; + private final VizGUI viz; + private final SwingLogPanel span; + private final Set warnings = new HashSet(); + private final List results = new ArrayList(); + private int len2=0, len3=0, verbosity=0; + private final String latestName; + private final int latestVersion; + public SimpleCallback1(SimpleGUI gui, VizGUI viz, SwingLogPanel span, int verbosity, String latestName, int latestVersion) { + this.gui=gui; this.viz=viz; this.span=span; this.verbosity=verbosity; + this.latestName=latestName; this.latestVersion=latestVersion; + len2 = len3 = span.getLength(); + } + public void done() { if (viz!=null) span.setLength(len2); else span.logDivider(); span.flush(); gui.doStop(0); } + public void fail() { span.logBold("\nAn error has occurred!\n"); span.logDivider(); span.flush(); gui.doStop(1); } + public void callback(Object msg) { + if (msg==null) { span.logBold("Done\n"); span.flush(); return; } + if (msg instanceof String) { span.logBold( ((String)msg).trim() + "\n" ); span.flush(); return; } + if (msg instanceof Throwable) { + for(Throwable ex = (Throwable)msg; ex!=null; ex=ex.getCause()) { + if (ex instanceof OutOfMemoryError) { + span.logBold("\nFatal Error: the solver ran out of memory!\n" + "Try simplifying your model or reducing the scope,\n" + "or increase memory under the Options menu.\n"); + return; + } + if (ex instanceof StackOverflowError) { + span.logBold("\nFatal Error: the solver ran out of stack space!\n" + "Try simplifying your model or reducing the scope,\n" + "or increase stack under the Options menu.\n"); + return; + } + } + } + if (msg instanceof Err) { + Err ex = (Err)msg; + String text = "fatal"; + boolean fatal = false; + if (ex instanceof ErrorSyntax) text="syntax"; else if (ex instanceof ErrorType) text="type"; else fatal=true; + if (ex.pos==Pos.UNKNOWN) + span.logBold("A "+text+" error has occurred: "); + else + span.logLink("A "+text+" error has occurred: ", "POS: "+ex.pos.x+" "+ex.pos.y+" "+ex.pos.x2+" "+ex.pos.y2+" "+ex.pos.filename); + if (verbosity>2) { + span.log("(see the "); span.logLink("stacktrace", "MSG: "+ex.dump()); span.log(")\n"); + } else { + span.log("\n"); + } + span.logIndented(ex.msg.trim()); + span.log("\n"); + if (fatal && latestVersion>Version.buildNumber()) + span.logBold( + "\nNote: You are running Alloy build#"+Version.buildNumber()+ + ",\nbut the most recent is Alloy build#"+latestVersion+ + ":\n( version "+latestName+" )\nPlease try to upgrade to the newest version,"+ + "\nas the problem may have been fixed already.\n"); + span.flush(); + if (!fatal) gui.doVisualize("POS: "+ex.pos.x+" "+ex.pos.y+" "+ex.pos.x2+" "+ex.pos.y2+" "+ex.pos.filename); + return; + } + if (msg instanceof Throwable) { Throwable ex = (Throwable)msg; span.logBold(ex.toString().trim()+"\n"); span.flush(); return; } + if (!(msg instanceof Object[])) return; + Object[] array = (Object[]) msg; + if (array[0].equals("pop")) { span.setLength(len2); String x=(String)(array[1]); if (viz!=null && x.length()>0) OurDialog.alert(x); } + if (array[0].equals("declare")) { gui.doSetLatest((String)(array[1])); } + if (array[0].equals("S2")) { len3=len2=span.getLength(); span.logBold(""+array[1]); } + if (array[0].equals("R3")) { span.setLength(len3); span.log(""+array[1]); } + if (array[0].equals("link")) { span.logLink((String)(array[1]), (String)(array[2])); } + if (array[0].equals("bold")) { span.logBold(""+array[1]); } + if (array[0].equals("")) { span.log(""+array[1]); } + if (array[0].equals("scope") && verbosity>0) { span.log(" " + array[1]); } + if (array[0].equals("bound") && verbosity>1) { span.log(" " + array[1]); } + if (array[0].equals("resultCNF")) { results.add(null); span.setLength(len3); span.log(" File written to "+array[1]+"\n\n"); } + if (array[0].equals("debug") && verbosity>2) { span.log(" "+array[1]+"\n"); len2=len3=span.getLength(); } + if (array[0].equals("translate")) { span.log(" " + array[1]); len3 = span.getLength(); span.logBold(" Generating CNF...\n"); } + if (array[0].equals("solve")) { span.setLength(len3); span.log(" " + array[1]); len3=span.getLength(); span.logBold(" Solving...\n"); } + if (array[0].equals("warnings")) { + if (warnings.size()==0) span.setLength(len2); + else if (warnings.size()>1) span.logBold("Note: There were "+warnings.size()+" compilation warnings. Please scroll up to see them.\n\n"); + else span.logBold("Note: There was 1 compilation warning. Please scroll up to see them.\n\n"); + if (warnings.size()>0 && Boolean.FALSE.equals(array[1])) { + Pos e = warnings.iterator().next().pos; + gui.doVisualize("POS: "+e.x+" "+e.y+" "+e.x2+" "+e.y2+" "+e.filename); + span.logBold("Warnings often indicate errors in the model.\n" + +"Some warnings can affect the soundness of the analysis.\n" + +"To proceed despite the warnings, go to the Options menu.\n"); + } + } + if (array[0].equals("warning")) { + ErrorWarning e = (ErrorWarning)(array[1]); + if (!warnings.add(e)) return; + Pos p=e.pos; + span.logLink("Warning #"+warnings.size(), "POS: "+p.x+" "+p.y+" "+p.x2+" "+p.y2+" "+p.filename); + span.log("\n"); span.logIndented(e.msg.trim()); span.log("\n\n"); + } + if (array[0].equals("sat")) { + boolean chk = Boolean.TRUE.equals(array[1]); + int expects = (Integer) (array[2]); + String filename = (String) (array[3]), formula = (String) (array[4]); + results.add(filename); + (new File(filename)).deleteOnExit(); + gui.doSetLatest(filename); + span.setLength(len3); + span.log(" "); + span.logLink(chk ? "Counterexample" : "Instance", "XML: "+filename); + span.log(" found. "); + span.logLink(chk?"Assertion":"Predicate", formula); span.log(chk?" is invalid":" is consistent"); + if (expects==0) span.log(", contrary to expectation"); else if (expects==1) span.log(", as expected"); + span.log(". "+array[5]+"ms.\n\n"); + } + if (array[0].equals("metamodel")) { + String outf = (String) (array[1]); + span.setLength(len2); + (new File(outf)).deleteOnExit(); + gui.doSetLatest(outf); + span.logLink("Metamodel", "XML: "+outf); + span.log(" successfully generated.\n\n"); + } + if (array[0].equals("minimizing")) { + boolean chk = Boolean.TRUE.equals(array[1]); + int expects = (Integer) (array[2]); + span.setLength(len3); + span.log(chk ? " No counterexample found." : " No instance found."); + if (chk) span.log(" Assertion may be valid"); else span.log(" Predicate may be inconsistent"); + if (expects==1) span.log(", contrary to expectation"); else if (expects==0) span.log(", as expected"); + span.log(". "+array[4]+"ms.\n"); + span.logBold(" Minimizing the unsat core of "+array[3]+" entries...\n"); + } + if (array[0].equals("unsat")) { + boolean chk = Boolean.TRUE.equals(array[1]); + int expects = (Integer) (array[2]); + String formula = (String) (array[4]); + span.setLength(len3); + span.log(chk ? " No counterexample found. " : " No instance found. "); + span.logLink(chk ? "Assertion" : "Predicate", formula); + span.log(chk? " may be valid" : " may be inconsistent"); + if (expects==1) span.log(", contrary to expectation"); else if (expects==0) span.log(", as expected"); + if (array.length==5) { span.log(". "+array[3]+"ms.\n\n"); span.flush(); return; } + String core = (String) (array[5]); + int mbefore = (Integer) (array[6]), mafter = (Integer) (array[7]); + span.log(". "+array[3]+"ms.\n"); + if (core.length()==0) { results.add(""); span.log(" No unsat core is available in this case. "+array[8]+"ms.\n\n"); span.flush(); return; } + results.add(core); + (new File(core)).deleteOnExit(); + span.log(" "); + span.logLink("Core", core); + if (mbefore<=mafter) span.log(" contains "+mafter+" top-level formulas. "+array[8]+"ms.\n\n"); + else span.log(" reduced from "+mbefore+" to "+mafter+" top-level formulas. "+array[8]+"ms.\n\n"); + } + span.flush(); + } + } + + private void cb(Serializable... objs) { cb.callback(objs); } + + /** {@inheritDoc} */ + @Override public void resultCNF(final String filename) { cb("resultCNF", filename); } + + /** {@inheritDoc} */ + @Override public void warning(final ErrorWarning ex) { warn++; cb("warning", ex); } + + /** {@inheritDoc} */ + @Override public void scope(final String msg) { cb("scope", msg); } + + /** {@inheritDoc} */ + @Override public void bound(final String msg) { cb("bound", msg); } + + /** {@inheritDoc} */ + @Override public void debug(final String msg) { cb("debug", msg.trim()); } + + /** {@inheritDoc} */ + @Override public void translate(String solver, int bitwidth, int maxseq, int skolemDepth, int symmetry) { + lastTime = System.currentTimeMillis(); + cb("translate", "Solver="+solver+" Bitwidth="+bitwidth+" MaxSeq="+maxseq + + (skolemDepth==0?"":" SkolemDepth="+skolemDepth) + + " Symmetry="+(symmetry>0 ? (""+symmetry) : "OFF")+'\n'); + } + + /** {@inheritDoc} */ + @Override public void solve(final int primaryVars, final int totalVars, final int clauses) { + minimized=0; + cb("solve", ""+totalVars+" vars. "+primaryVars+" primary vars. "+clauses+" clauses. "+(System.currentTimeMillis()-lastTime)+"ms.\n"); + lastTime = System.currentTimeMillis(); + } + + /** {@inheritDoc} */ + @Override public void resultSAT(Object command, long solvingTime, Object solution) { + if (!(solution instanceof A4Solution) || !(command instanceof Command)) return; + A4Solution sol = (A4Solution)solution; + Command cmd = (Command)command; + String formula = recordKodkod ? sol.debugExtractKInput() : ""; + String filename = tempfile+".xml"; + synchronized(SimpleReporter.class) { + try { + cb("R3", " Writing the XML file..."); + if (latestModule!=null) writeXML(this, latestModule, filename, sol, latestKodkodSRC); + } catch(Throwable ex) { + cb("bold", "\n" + (ex.toString().trim()) + "\nStackTrace:\n" + (MailBug.dump(ex).trim()) + "\n"); + return; + } + latestKodkods.clear(); + latestKodkods.add(sol.toString()); + latestKodkod=sol; + latestKodkodXML=filename; + } + String formulafilename = ""; + if (formula.length()>0 && tempfile!=null) { + formulafilename = tempfile+".java"; + try { Util.writeAll(formulafilename, formula); formulafilename="CNF: "+formulafilename; } catch(Throwable ex) { formulafilename=""; } + } + cb("sat", cmd.check, cmd.expects, filename, formulafilename, System.currentTimeMillis()-lastTime); + } + + /** {@inheritDoc} */ + @Override public void minimizing(Object command, int before) { + if (!(command instanceof Command)) return; + Command cmd = (Command)command; + minimized = System.currentTimeMillis(); + cb("minimizing", cmd.check, cmd.expects, before, minimized-lastTime); + } + + /** {@inheritDoc} */ + @Override public void minimized(Object command, int before, int after) { minimizedBefore=before; minimizedAfter=after; } + + /** {@inheritDoc} */ + @Override public void resultUNSAT(Object command, long solvingTime, Object solution) { + if (!(solution instanceof A4Solution) || !(command instanceof Command)) return; + A4Solution sol = (A4Solution)solution; + Command cmd = (Command)command; + String originalFormula = recordKodkod ? sol.debugExtractKInput() : ""; + String corefilename="", formulafilename=""; + if (originalFormula.length()>0 && tempfile!=null) { + formulafilename=tempfile+".java"; + try { Util.writeAll(formulafilename, originalFormula); formulafilename="CNF: "+formulafilename; } catch(Throwable ex) { formulafilename=""; } + } + Pair,Set> core = sol.highLevelCore(); + if ((core.a.size()>0 || core.b.size()>0) && tempfile!=null) { + corefilename=tempfile+".core"; + OutputStream fs=null; + ObjectOutputStream os=null; + try { + fs=new FileOutputStream(corefilename); + os=new ObjectOutputStream(fs); + os.writeObject(core); + os.writeObject(sol.lowLevelCore()); + corefilename="CORE: "+corefilename; + } catch(Throwable ex) { + corefilename=""; + } finally { + Util.close(os); + Util.close(fs); + } + } + if (minimized==0) cb("unsat", cmd.check, cmd.expects, (System.currentTimeMillis()-lastTime), formulafilename); + else cb("unsat", cmd.check, cmd.expects, minimized-lastTime, formulafilename, corefilename, minimizedBefore, minimizedAfter, (System.currentTimeMillis()-minimized)); + } + + private final WorkerCallback cb; + + //========== These fields should be set each time we execute a set of commands + + /** Whether we should record Kodkod input/output. */ + private final boolean recordKodkod; + + /** The time that the last action began; we subtract it from System.currentTimeMillis() to determine the elapsed time. */ + private long lastTime=0; + + /** If we performed unsat core minimization, then this is the start of the minimization, else this is 0. */ + private long minimized = 0; + + /** The unsat core size before minimization. */ + private int minimizedBefore; + + /** The unsat core size after minimization. */ + private int minimizedAfter; + + /** The filename where we can write a temporary Java file or Core file. */ + private String tempfile=null; + + //========== These fields may be altered as each successful command generates a Kodkod or Metamodel instance + + /** The set of Strings already enumerated for this current solution. */ + private static final Set latestKodkods=new LinkedHashSet(); + + /** The A4Solution corresponding to the latest solution generated by Kodkod; this field must be synchronized. */ + private static A4Solution latestKodkod=null; + + /** The root Module corresponding to this.latestKodkod; this field must be synchronized. */ + private static Module latestModule=null; + + /** The source code corresponding to the latest solution generated by Kodkod; this field must be synchronized. */ + private static ConstMap latestKodkodSRC = null; + + /** The XML filename corresponding to the latest solution generated by Kodkod; this field must be synchronized. */ + private static String latestKodkodXML=null; + + /** The XML filename corresponding to the latest metamodel generated by TranslateAlloyToMetamodel; this field must be synchronized. */ + private static String latestMetamodelXML=null; + + /** Constructor is private. */ + private SimpleReporter(WorkerCallback cb, boolean recordKodkod) { this.cb=cb; this.recordKodkod=recordKodkod; } + + /** Helper method to write out a full XML file. */ + private static void writeXML(A4Reporter rep, Module mod, String filename, A4Solution sol, Map sources) throws Exception { + sol.writeXML(rep, filename, mod.getAllFunc(), sources); + if ("yes".equals(System.getProperty("debug"))) validate(filename); + } + + private int warn=0; + + /** Task that performs solution enumeration. */ + static final class SimpleTask2 implements WorkerTask { + private static final long serialVersionUID = 0; + public String filename = ""; + public transient WorkerCallback out = null; + private void cb(Object... objs) throws Exception { out.callback(objs); } + public void run(WorkerCallback out) throws Exception { + this.out = out; + cb("S2", "Enumerating...\n"); + A4Solution sol; + Module mod; + synchronized(SimpleReporter.class) { + if (latestMetamodelXML!=null && latestMetamodelXML.equals(filename)) + {cb("pop", "You cannot enumerate a metamodel.\n"); return;} + if (latestKodkodXML==null || !latestKodkodXML.equals(filename)) + {cb("pop", "You can only enumerate the solutions of the most-recently-solved command."); return;} + if (latestKodkod==null || latestModule==null || latestKodkodSRC==null) + {cb("pop", "Error: the SAT solver that generated the instance has exited,\nso we cannot enumerate unless you re-solve that command.\n"); return;} + sol=latestKodkod; + mod=latestModule; + } + if (!sol.satisfiable()) + {cb("pop", "Error: This command is unsatisfiable,\nso there are no solutions to enumerate."); return;} + if (!sol.isIncremental()) + {cb("pop", "Error: This solution was not generated by an incremental SAT solver.\n" + + "Currently only MiniSat and SAT4J are supported."); return;} + int tries=0; + while(true) { + sol=sol.next(); + if (!sol.satisfiable()) + {cb("pop", "There are no more satisfying instances.\n\n" + + "Note: due to symmetry breaking and other optimizations,\n" + + "some equivalent solutions may have been omitted."); return;} + String toString = sol.toString(); + synchronized(SimpleReporter.class) { + if (!latestKodkods.add(toString)) if (tries<100) { tries++; continue; } + // The counter is needed to avoid a Kodkod bug where sometimes we might repeat the same solution infinitely number of times; this at least allows the user to keep going + writeXML(null, mod, filename, sol, latestKodkodSRC); latestKodkod=sol; + } + cb("declare", filename); + return; + } + } + } + + /** Validate the given filename to see if it is a valid Alloy XML instance file. */ + private static void validate(String filename) throws Exception { + A4SolutionReader.read(new ArrayList(), new XMLNode(new File(filename))).toString(); + StaticInstanceReader.parseInstance(new File(filename)); + } + + /** Task that perform one command. */ + static final class SimpleTask1 implements WorkerTask { + private static final long serialVersionUID = 0; + public A4Options options; + public String tempdir; + public boolean bundleWarningNonFatal; + public int bundleIndex; + public int resolutionMode; + public Map map; + public SimpleTask1() { } + public void cb(WorkerCallback out, Object... objs) throws IOException { out.callback(objs); } + public void run(WorkerCallback out) throws Exception { + cb(out, "S2", "Starting the solver...\n\n"); + final SimpleReporter rep = new SimpleReporter(out, options.recordKodkod); + final Module world = CompUtil.parseEverything_fromFile(rep, map, options.originalFilename, resolutionMode); + final List sigs = world.getAllReachableSigs(); + final ConstList cmds = world.getAllCommands(); + cb(out, "warnings", bundleWarningNonFatal); + if (rep.warn>0 && !bundleWarningNonFatal) return; + List result = new ArrayList(cmds.size()); + if (bundleIndex==-2) { + final String outf=tempdir+File.separatorChar+"m.xml"; + cb(out, "S2", "Generating the metamodel...\n"); + PrintWriter of = new PrintWriter(outf, "UTF-8"); + Util.encodeXMLs(of, "\n\n\n"); + A4SolutionWriter.writeMetamodel(ConstList.make(sigs), options.originalFilename, of); + Util.encodeXMLs(of, "\n"); + Util.close(of); + if ("yes".equals(System.getProperty("debug"))) validate(outf); + cb(out, "metamodel", outf); + synchronized(SimpleReporter.class) { latestMetamodelXML=outf; } + } else for(int i=0; i0) result.add(tempCNF+".core"); + else result.add(""); + } + (new File(tempdir)).delete(); // In case it was UNSAT, or canceled... + if (result.size()>1) { + rep.cb("bold", "" + result.size() + " commands were executed. The results are:\n"); + for(int i=0; i1) rep.cb("bold", "Note: There were "+rep.warn+" compilation warnings. Please scroll up to see them.\n"); + if (rep.warn==1) rep.cb("bold", "Note: There was 1 compilation warning. Please scroll up to see it.\n"); + } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/SwingLogPanel.java b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/SwingLogPanel.java new file mode 100644 index 00000000..0d590551 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/edu/mit/csail/sdg/alloy4whole/SwingLogPanel.java @@ -0,0 +1,353 @@ +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package edu.mit.csail.sdg.alloy4whole; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextPane; +import javax.swing.border.EmptyBorder; +import javax.swing.text.AbstractDocument; +import javax.swing.text.BadLocationException; +import javax.swing.text.BoxView; +import javax.swing.text.Element; +import javax.swing.text.Style; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledDocument; +import javax.swing.text.StyledEditorKit; +import javax.swing.text.View; +import javax.swing.text.ViewFactory; +import edu.mit.csail.sdg.alloy4.OurAntiAlias; +import edu.mit.csail.sdg.alloy4.OurUtil; + +/** This helper method is used by SimpleGUI; only the AWT Event Thread may call methods in this class. */ + +final class SwingLogPanel { + + /** Try to wrap the input to about 60 characters per line; however, if a token is too long, we won't break it. */ + private static void linewrap(StringBuilder sb, String msg) { + StringTokenizer tokenizer=new StringTokenizer(msg,"\r\n\t "); + final int max=60; + int now=0; + while(tokenizer.hasMoreTokens()) { + String x=tokenizer.nextToken(); + if (now+1+x.length() > max) { + if (now>0) { sb.append('\n'); } + sb.append(x); + now=x.length(); + } else { + if (now>0) { now++; sb.append(' '); } + sb.append(x); + now=now+x.length(); + } + } + } + + /** This field buffers previous calls to log() so that we can write them out later in a single Swing call + * (If there is nothing buffered, this field can be an empty list or even null). + */ + private final List batch = new ArrayList(); + + /** The newly created JTextPane object that will display the log; null if this log has been destroyed. */ + private JTextPane log; + + /** The style to use when writing regular messages. */ + private final Style styleRegular; + + /** The style to use when writing bold messages. */ + private final Style styleBold; + + /** The style to use when writing red messages. */ + private final Style styleRed; + + /** This stores the JLabels used for displaying hyperlinks. */ + private final List links = new ArrayList(); + + /** When the window gains focus, we'll call handler.run(ev_logFocused); + * When a hyperlink is clicked, we'll call handler.run(evs_visualize, linkURL). + */ + private final SimpleGUI handler; + + /** The current length of the log, not counting any "red" error message at the end of the log. */ + private int lastSize = 0; + + /** The current font name. */ + private String fontName; + + /** The current font size. */ + private int fontSize; + + /** The color to use for hyperlinks when the mouse is not hovering over it. */ + private static final Color linkColor = new Color(0.3f, 0.3f, 0.9f); + + /** The color to use for a hyperlink when the mouse is hovering over it. */ + private static final Color hoverColor = new Color(0.9f, 0.3f, 0.3f); + + /** This stores a default ViewFactory that will handle the View requests that we don't care to override. */ + private static final ViewFactory defaultFactory = (new StyledEditorKit()).getViewFactory(); + + /** Constructs a new JTextPane logger, and put it inside an existing JScrollPane. + * @param parent - the existing JScrollPane to insert the JTextPane into + * @param fontName - the font name to use + * @param fontSize - the font size to use + * @param background - the background color to use + * @param regular - the color to use for regular messages + * @param red - the color to use for red messages + * @param handler - the SimpleGUI parent + */ + public SwingLogPanel( + final JScrollPane parent, String fontName, int fontSize, + final Color background, final Color regular, final Color red, + final SimpleGUI handler) { + this.handler = handler; + this.fontName = fontName; + this.fontSize = fontSize; + this.log = OurUtil.make(OurAntiAlias.pane(), Color.BLACK, background, new EmptyBorder(1,1,1,1), new Font(fontName, Font.PLAIN, fontSize)); + // This customized StyledEditorKit prevents line-wrapping up to 30000 pixels wide. + // 30000 is a good number; value higher than about 32768 will cause errors. + this.log.setEditorKit(new StyledEditorKit() { + private static final long serialVersionUID = 0; + @Override public final ViewFactory getViewFactory() { + return new ViewFactory() { + public final View create(Element x) { + if (!AbstractDocument.SectionElementName.equals(x.getName())) return defaultFactory.create(x); + return new BoxView(x, View.Y_AXIS) { + @Override public final float getMinimumSpan(int axis) { return super.getPreferredSpan(axis); } + @Override public final void layout(int width,int height) { super.layout(30000, height); } + }; + } + }; + } + }); + log.setEditable(false); + log.addFocusListener(new FocusListener() { + public final void focusGained(FocusEvent e) { if (handler!=null) handler.notifyFocusLost(); } + public final void focusLost(FocusEvent e) { } + }); + StyledDocument doc = log.getStyledDocument(); + styleRegular = doc.addStyle("regular", null); + StyleConstants.setFontFamily(styleRegular, fontName); + StyleConstants.setFontSize(styleRegular, fontSize); + StyleConstants.setForeground(styleRegular, regular); + styleBold = doc.addStyle("bold", styleRegular); + StyleConstants.setBold(styleBold, true); + styleRed = doc.addStyle("red", styleBold); + StyleConstants.setForeground(styleRed, red); + parent.setViewportView(log); + parent.setBackground(background); + } + + /** Write a horizontal separator into the log window. */ + public void logDivider() { + if (log==null) return; + clearError(); + StyledDocument doc = log.getStyledDocument(); + Style dividerStyle = doc.addStyle("bar", styleRegular); + JPanel jpanel = new JPanel(); + jpanel.setBackground(Color.LIGHT_GRAY); + jpanel.setPreferredSize(new Dimension(300,1)); // 300 is arbitrary, since it will auto-stretch + StyleConstants.setComponent(dividerStyle, jpanel); + reallyLog(".", dividerStyle); // Any character would do; "." will be replaced by the JPanel + reallyLog("\n\n", styleRegular); + log.setCaretPosition(doc.getLength()); + lastSize = doc.getLength(); + } + + /** Write a clickable link into the log window. */ + public void logLink(final String link, final String linkDestination) { + if (log==null || link.length()==0) return; + if (linkDestination==null || linkDestination.length()==0) { log(link); return; } + clearError(); + StyledDocument doc = log.getStyledDocument(); + Style linkStyle = doc.addStyle("link", styleRegular); + final JLabel label = OurUtil.make(OurAntiAlias.label(link), new Font(fontName, Font.BOLD, fontSize), linkColor); + label.setAlignmentY(0.8f); + label.setMaximumSize(label.getPreferredSize()); + label.addMouseListener(new MouseListener(){ + public final void mousePressed(MouseEvent e) { if (handler!=null) handler.doVisualize(linkDestination); } + public final void mouseClicked(MouseEvent e) { } + public final void mouseReleased(MouseEvent e) { } + public final void mouseEntered(MouseEvent e) { label.setForeground(hoverColor); } + public final void mouseExited(MouseEvent e) { label.setForeground(linkColor); } + }); + StyleConstants.setComponent(linkStyle, label); + links.add(label); + reallyLog(".", linkStyle); // Any character would do; the "." will be replaced by the JLabel + log.setCaretPosition(doc.getLength()); + lastSize = doc.getLength(); + } + + /** Write "msg" in regular style. */ + public void log(String msg) { if (log!=null && msg.length()>0) batch.add(msg); } + + /** Write "msg" in bold style. */ + public void logBold(String msg) { if (msg.length()>0) {clearError(); reallyLog(msg, styleBold);} } + + private void reallyLog(String text, Style style) { + if (log==null || text.length()==0) return; + int i=text.lastIndexOf('\n'), j=text.lastIndexOf('\r'); + if (i>=0 && i0) { + int i = msg.indexOf('\n'); + if (i>=0) { + linewrap(sb, msg.substring(0,i)); + sb.append('\n'); + msg=msg.substring(i+1); + } else { + linewrap(sb, msg); + break; + } + } + clearError(); + reallyLog(sb.toString(), styleRed); + } + + /** Write "msg" in regular style (with automatic line wrap). */ + public void logIndented (String msg) { + if (log==null || msg.length()==0) return; + StringBuilder sb=new StringBuilder(); + while(msg.length()>0) { + int i = msg.indexOf('\n'); + if (i>=0) { + linewrap(sb, msg.substring(0,i)); + sb.append('\n'); + msg=msg.substring(i+1); + } else { + linewrap(sb, msg); + break; + } + } + clearError(); + reallyLog(sb.toString(), styleRegular); + } + + /** Set the font name. */ + public void setFontName(String fontName) { + if (log==null) return; + this.fontName = fontName; + log.setFont(new Font(fontName, Font.PLAIN, fontSize)); + StyleConstants.setFontFamily(styleRegular, fontName); + StyleConstants.setFontFamily(styleBold, fontName); + StyleConstants.setFontFamily(styleRed, fontName); + StyleConstants.setFontSize(styleRegular, fontSize); + StyleConstants.setFontSize(styleBold, fontSize); + StyleConstants.setFontSize(styleRed, fontSize); + // Changes all existing text + StyledDocument doc=log.getStyledDocument(); + Style temp=doc.addStyle("temp", null); + StyleConstants.setFontFamily(temp, fontName); + StyleConstants.setFontSize(temp, fontSize); + doc.setCharacterAttributes(0, doc.getLength(), temp, false); + // Changes all existing hyperlinks + Font newFont = new Font(fontName, Font.BOLD, fontSize); + for(JLabel link: links) { link.setFont(newFont); } + } + + /** Set the font size. */ + public void setFontSize(int fontSize) { + if (log==null) return; + this.fontSize = fontSize; + setFontName(this.fontName); + } + + /** Set the background color. */ + public void setBackground(Color background) { + if (log==null) return; + log.setBackground(background); + } + + /** Query the current length of the log. */ + int getLength() { + if (log==null) return 0; + clearError(); + return log.getStyledDocument().getLength(); + } + + /** Truncate the log to the given length; if the log is shorter than the number given, then nothing happens. */ + void setLength(int newLength) { + if (log==null) return; + clearError(); + StyledDocument doc=log.getStyledDocument(); + int n=doc.getLength(); + if (n<=newLength) return; + try { + doc.remove(newLength, n-newLength); + } catch (BadLocationException e) { + // Harmless + } + if (lastSize>doc.getLength()) { lastSize=doc.getLength(); } + } + + /** This method copies the currently selected text in the log (if any) into the clipboard. */ + public void copy() { + if (log==null) return; + log.copy(); + } + + /** Removes any messages writtin in "red" style. */ + public void clearError() { + if (log==null) return; + // Since this class always removes "red" messages prior to writing anything, + // that means if there are any red messages, they will always be at the end of the JTextPane. + StyledDocument doc=log.getStyledDocument(); + int n=doc.getLength(); + if (n>lastSize) { + try {doc.remove(lastSize, n-lastSize);} catch (BadLocationException e) {} + } + if (batch.size()>0) { + for(String msg: batch) { reallyLog(msg, styleRegular); } + batch.clear(); + } + } + + /** Commits all outstanding writes (if the messages are buffered). */ + public void flush() { + if (log==null) return; + if (batch.size()>0) clearError(); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/help/image/error.gif b/Source/eu.modelwriter.alloyanalyzer/src/help/image/error.gif new file mode 100644 index 00000000..d37e28b4 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/help/image/error.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/help/image/general.gif b/Source/eu.modelwriter.alloyanalyzer/src/help/image/general.gif new file mode 100644 index 00000000..52976128 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/help/image/general.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/help/image/pref.gif b/Source/eu.modelwriter.alloyanalyzer/src/help/image/pref.gif new file mode 100644 index 00000000..eb2fd296 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/help/image/pref.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/help/image/theme.gif b/Source/eu.modelwriter.alloyanalyzer/src/help/image/theme.gif new file mode 100644 index 00000000..ad9e58d1 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/help/image/theme.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/help/image/toolbar.gif b/Source/eu.modelwriter.alloyanalyzer/src/help/image/toolbar.gif new file mode 100644 index 00000000..f3cbda1b Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/help/image/toolbar.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/help/image/toolbarviz.gif b/Source/eu.modelwriter.alloyanalyzer/src/help/image/toolbarviz.gif new file mode 100644 index 00000000..98abc4f5 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/help/image/toolbarviz.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/help/image/tree.gif b/Source/eu.modelwriter.alloyanalyzer/src/help/image/tree.gif new file mode 100644 index 00000000..40bd56a8 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/help/image/tree.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/help/image/viz.gif b/Source/eu.modelwriter.alloyanalyzer/src/help/image/viz.gif new file mode 100644 index 00000000..0f27b631 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/help/image/viz.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/help/image/xml.gif b/Source/eu.modelwriter.alloyanalyzer/src/help/image/xml.gif new file mode 100644 index 00000000..45316860 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/help/image/xml.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/black.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/black.gif new file mode 100644 index 00000000..bba84da2 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/black.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/blue.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/blue.gif new file mode 100644 index 00000000..e6b2a7e9 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/blue.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/cadetblue.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/cadetblue.gif new file mode 100644 index 00000000..d01b37fe Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/cadetblue.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/chartreuse2.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/chartreuse2.gif new file mode 100644 index 00000000..0502739f Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/chartreuse2.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/cornflowerblue.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/cornflowerblue.gif new file mode 100644 index 00000000..64a86a64 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/cornflowerblue.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/cyan.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/cyan.gif new file mode 100644 index 00000000..720fb8cd Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/cyan.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/darkolivegreen2.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/darkolivegreen2.gif new file mode 100644 index 00000000..827b3f9c Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/darkolivegreen2.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/gold.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/gold.gif new file mode 100644 index 00000000..f6dc8ce8 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/gold.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/green2.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/green2.gif new file mode 100644 index 00000000..5b689651 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/green2.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/lightgoldenrod.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/lightgoldenrod.gif new file mode 100644 index 00000000..27fb805b Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/lightgoldenrod.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/lightgray.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/lightgray.gif new file mode 100644 index 00000000..b3f1bfa7 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/lightgray.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/limegreen.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/limegreen.gif new file mode 100644 index 00000000..29edc92b Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/limegreen.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/magenta.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/magenta.gif new file mode 100644 index 00000000..8d3d29ca Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/magenta.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/magic.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/magic.gif new file mode 100644 index 00000000..61598714 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/magic.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/palevioletred.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/palevioletred.gif new file mode 100644 index 00000000..1de7a229 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/palevioletred.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/red.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/red.gif new file mode 100644 index 00000000..c7604a5a Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/red.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/salmon.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/salmon.gif new file mode 100644 index 00000000..1d3dca18 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/salmon.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/white.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/white.gif new file mode 100644 index 00000000..02a767d3 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/white.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/yellow.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/yellow.gif new file mode 100644 index 00000000..a09f1c23 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ColorIcons/yellow.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/Mcircle.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/Mcircle.gif new file mode 100644 index 00000000..49a659f8 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/Mcircle.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/Mdiamond.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/Mdiamond.gif new file mode 100644 index 00000000..071f9807 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/Mdiamond.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/Msquare.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/Msquare.gif new file mode 100644 index 00000000..2db39335 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/Msquare.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/box.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/box.gif new file mode 100644 index 00000000..788dee55 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/box.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/circle.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/circle.gif new file mode 100644 index 00000000..87fe62e4 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/circle.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/diamond.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/diamond.gif new file mode 100644 index 00000000..e0a1df4b Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/diamond.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/doublecircle.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/doublecircle.gif new file mode 100644 index 00000000..33156e8c Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/doublecircle.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/doubleoctagon.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/doubleoctagon.gif new file mode 100644 index 00000000..064307f3 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/doubleoctagon.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/egg.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/egg.gif new file mode 100644 index 00000000..3d49e5a9 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/egg.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/ellipse.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/ellipse.gif new file mode 100644 index 00000000..83dc2f41 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/ellipse.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/hexagon.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/hexagon.gif new file mode 100644 index 00000000..e85ae033 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/hexagon.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/house.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/house.gif new file mode 100644 index 00000000..4812b028 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/house.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/invhouse.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/invhouse.gif new file mode 100644 index 00000000..71dc4b83 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/invhouse.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/invtrapezium.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/invtrapezium.gif new file mode 100644 index 00000000..7eaf0c04 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/invtrapezium.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/invtriangle.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/invtriangle.gif new file mode 100644 index 00000000..c3394467 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/invtriangle.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/octagon.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/octagon.gif new file mode 100644 index 00000000..7ec0b4bb Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/octagon.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/parallelogram.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/parallelogram.gif new file mode 100644 index 00000000..a4925d03 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/parallelogram.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/trapezium.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/trapezium.gif new file mode 100644 index 00000000..2381a684 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/trapezium.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/triangle.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/triangle.gif new file mode 100644 index 00000000..730a1b0c Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/triangle.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/tripleoctagon.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/tripleoctagon.gif new file mode 100644 index 00000000..1f604228 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/ShapeIcons/tripleoctagon.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/StyleIcons/bold.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/StyleIcons/bold.gif new file mode 100644 index 00000000..dda8863b Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/StyleIcons/bold.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/StyleIcons/dashed.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/StyleIcons/dashed.gif new file mode 100644 index 00000000..b12004d2 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/StyleIcons/dashed.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/StyleIcons/dotted.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/StyleIcons/dotted.gif new file mode 100644 index 00000000..be61201c Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/StyleIcons/dotted.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/icons/StyleIcons/solid.gif b/Source/eu.modelwriter.alloyanalyzer/src/icons/StyleIcons/solid.gif new file mode 100644 index 00000000..7d837f15 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/icons/StyleIcons/solid.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/24_execute.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/24_execute.gif new file mode 100644 index 00000000..ddd93932 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/24_execute.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/24_execute_abort2.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/24_execute_abort2.gif new file mode 100644 index 00000000..332d42ab Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/24_execute_abort2.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/24_graph.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/24_graph.gif new file mode 100644 index 00000000..ac830a0a Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/24_graph.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/24_history.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/24_history.gif new file mode 100644 index 00000000..c18eb6b4 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/24_history.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/24_new.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/24_new.gif new file mode 100644 index 00000000..9d9f0ee2 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/24_new.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/24_open.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/24_open.gif new file mode 100644 index 00000000..de4696ce Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/24_open.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/24_plaintext.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/24_plaintext.gif new file mode 100644 index 00000000..7eace4b3 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/24_plaintext.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/24_reload.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/24_reload.gif new file mode 100644 index 00000000..2652ff48 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/24_reload.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/24_save.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/24_save.gif new file mode 100644 index 00000000..e243bd53 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/24_save.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings.gif new file mode 100644 index 00000000..0195f5bb Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_apply.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_apply.gif new file mode 100644 index 00000000..87fe2dc1 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_apply.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_apply2.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_apply2.gif new file mode 100644 index 00000000..b91773cb Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_apply2.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_apply3.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_apply3.gif new file mode 100644 index 00000000..7472cf1e Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_apply3.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_close.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_close.gif new file mode 100644 index 00000000..a550fa6d Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_close.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_close2.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_close2.gif new file mode 100644 index 00000000..652ad79f Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_close2.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_close3.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_close3.gif new file mode 100644 index 00000000..20f9c5fb Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_close3.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_close4.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_close4.gif new file mode 100644 index 00000000..50209486 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_close4.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_close5.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_close5.gif new file mode 100644 index 00000000..3c417b5e Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/24_settings_close5.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/24_texttree.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/24_texttree.gif new file mode 100644 index 00000000..ab735b1f Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/24_texttree.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/cb0.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/cb0.gif new file mode 100644 index 00000000..4e47578d Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/cb0.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/cb1.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/cb1.gif new file mode 100644 index 00000000..491dcb86 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/cb1.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/logo.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/logo.gif new file mode 100644 index 00000000..c23a7f05 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/logo.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/menu0.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/menu0.gif new file mode 100644 index 00000000..b1d498cd Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/menu0.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/menu1.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/menu1.gif new file mode 100644 index 00000000..f204c0b5 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/menu1.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/tcb01.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/tcb01.gif new file mode 100644 index 00000000..dd3972f8 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/tcb01.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/tcb02.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/tcb02.gif new file mode 100644 index 00000000..7755c002 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/tcb02.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/tcb03.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/tcb03.gif new file mode 100644 index 00000000..d3ad1e95 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/tcb03.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/images/tcb04.gif b/Source/eu.modelwriter.alloyanalyzer/src/images/tcb04.gif new file mode 100644 index 00000000..d0dff531 Binary files /dev/null and b/Source/eu.modelwriter.alloyanalyzer/src/images/tcb04.gif differ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/java_cup/runtime/DefaultSymbolFactory.java b/Source/eu.modelwriter.alloyanalyzer/src/java_cup/runtime/DefaultSymbolFactory.java new file mode 100644 index 00000000..0421f089 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/java_cup/runtime/DefaultSymbolFactory.java @@ -0,0 +1,54 @@ +package java_cup.runtime; + +import edu.mit.csail.sdg.alloy4.Pos; + +/** + * Default Implementation for SymbolFactory, creates + * plain old Symbols + * + * @version last updated 27-03-2006 + * @author Michael Petter + */ + +/* ************************************************* + class DefaultSymbolFactory + + interface for creating new symbols + ***************************************************/ +public class DefaultSymbolFactory implements SymbolFactory{ + // Factory methods + /** + * DefaultSymbolFactory for CUP. + * Users are strongly encoraged to use ComplexSymbolFactory instead, since + * it offers more detailed information about Symbols in source code. + * Yet since migrating has always been a critical process, You have the + * chance of still using the oldstyle Symbols. + * + *@deprecated as of CUP v11a + * replaced by the new java_cup.runtime.ComplexSymbolFactory + */ + //@deprecated + public DefaultSymbolFactory(){ + } + public Symbol newSymbol(String name ,int id, Symbol left, Symbol right, Object value){ + return new Symbol(id,left,right,value); + } + public Symbol newSymbol(String name, int id, Symbol left, Symbol right){ + return new Symbol(id,left,right); + } + public Symbol newSymbol(String name, int id, int left, int right, Object value){ + return new Symbol(id,left,right,value); + } + public Symbol newSymbol(String name, int id, int left, int right){ + return new Symbol(id,left,right); + } + public Symbol startSymbol(String name, int id, int state){ + return new Symbol(id,state); + } + public Symbol newSymbol(String name, int id){ + return new Symbol(id); + } + public Symbol newSymbol(String name, Pos pos, int id, Object value) { + return new Symbol(id,pos,value); + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/java_cup/runtime/Scanner.java b/Source/eu.modelwriter.alloyanalyzer/src/java_cup/runtime/Scanner.java new file mode 100644 index 00000000..53114c01 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/java_cup/runtime/Scanner.java @@ -0,0 +1,25 @@ +package java_cup.runtime; + +/** + * Defines the Scanner interface, which CUP uses in the default + * implementation of lr_parser.scan(). Integration + * of scanners implementing Scanner is facilitated. + * + * @version last updated 23-Jul-1999 + * @author David MacMahon + */ + +/* ************************************************* + Interface Scanner + + Declares the next_token() method that should be + implemented by scanners. This method is typically + called by lr_parser.scan(). End-of-file can be + indicated either by returning + new Symbol(lr_parser.EOF_sym()) or + null. + ***************************************************/ +public interface Scanner { + /** Return the next token, or null on end-of-file. */ + public Symbol next_token() throws java.lang.Exception; +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/java_cup/runtime/Symbol.java b/Source/eu.modelwriter.alloyanalyzer/src/java_cup/runtime/Symbol.java new file mode 100644 index 00000000..9a5d622c --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/java_cup/runtime/Symbol.java @@ -0,0 +1,119 @@ +package java_cup.runtime; + +import edu.mit.csail.sdg.alloy4.Pos; + +/** + * Defines the Symbol class, which is used to represent all terminals + * and nonterminals while parsing. The lexer should pass CUP Symbols + * and CUP returns a Symbol. + * + * @version last updated: 7/3/96 + * @author Frank Flannery + */ + +/* **************************************************************** + Class Symbol + what the parser expects to receive from the lexer. + the token is identified as follows: + sym: the symbol type + parse_state: the parse state. + value: is the lexical value of type Object + left : is the left position in the original input file + right: is the right position in the original input file + xleft: is the left position Object in the original input file + xright: is the left position Object in the original input file +******************************************************************/ + +public class Symbol { + +// TUM 20060327: Added new Constructor to provide more flexible way +// for location handling +/******************************* + *******************************/ + public Symbol(int id, Symbol left, Symbol right, Object o){ + this(id,left.left,right.right,o); + } + public Symbol(int id, Symbol left, Symbol right){ + this(id,left.left,right.right); + } +/******************************* + Constructor for l,r values + *******************************/ + + public Symbol(int id, int l, int r, Object o) { + this(id); + left = l; + right = r; + value = o; + } + +/******************************* + Constructor for no l,r values +********************************/ + + public Symbol(int id, Pos pos, Object o) { + this(id, -1, -1, o); + this.pos = pos; + } + +/***************************** + Constructor for no value + ***************************/ + + public Symbol(int id, int l, int r) { + this(id, l, r, null); + } + +/*********************************** + Constructor for no value or l,r +***********************************/ + + public Symbol(int sym_num) { + this(sym_num, -1); + left = -1; + right = -1; + } + +/*********************************** + Constructor to give a start state +***********************************/ + Symbol(int sym_num, int state) + { + sym = sym_num; + parse_state = state; + } + +/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The symbol number of the terminal or non terminal being represented */ + public int sym; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The parse state to be recorded on the parse stack with this symbol. + * This field is for the convenience of the parser and shouldn't be + * modified except by the parser. + */ + public int parse_state; + /** This allows us to catch some errors caused by scanners recycling + * symbols. For the use of the parser only. [CSA, 23-Jul-1999] */ + boolean used_by_parser = false; + +/******************************* + The data passed to parser + *******************************/ + + public Pos pos; + public int left, right; + public Object value; + + /***************************** + Printing this token out. (Override for pretty-print). + ****************************/ + public String toString() { return "#"+sym; } +} + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/java_cup/runtime/SymbolFactory.java b/Source/eu.modelwriter.alloyanalyzer/src/java_cup/runtime/SymbolFactory.java new file mode 100644 index 00000000..9b640d76 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/java_cup/runtime/SymbolFactory.java @@ -0,0 +1,35 @@ +package java_cup.runtime; + +import edu.mit.csail.sdg.alloy4.Pos; + +/** + * Creates the Symbols interface, which CUP uses as default + * + * @version last updated 27-03-2006 + * @author Michael Petter + */ + +/* ************************************************* + Interface SymbolFactory + + interface for creating new symbols + You can also use this interface for your own callback hooks + Declare Your own factory methods for creation of Objects in Your scanner! + ***************************************************/ +public interface SymbolFactory { + // Factory methods + /** + * Construction with left/right propagation switched on + */ + public Symbol newSymbol(String name, int id, Symbol left, Symbol right, Object value); + public Symbol newSymbol(String name, int id, Symbol left, Symbol right); + /** + * Construction with left/right propagation switched off + */ + public Symbol newSymbol(String name, Pos pos, int id, Object value); + public Symbol newSymbol(String name, int id); + /** + * Construction of start symbol + */ + public Symbol startSymbol(String name, int id, int state); +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/java_cup/runtime/lr_parser.java b/Source/eu.modelwriter.alloyanalyzer/src/java_cup/runtime/lr_parser.java new file mode 100644 index 00000000..1ac3d543 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/java_cup/runtime/lr_parser.java @@ -0,0 +1,1253 @@ + +package java_cup.runtime; + +import java.util.Stack; + +/** This class implements a skeleton table driven LR parser. In general, + * LR parsers are a form of bottom up shift-reduce parsers. Shift-reduce + * parsers act by shifting input onto a parse stack until the Symbols + * matching the right hand side of a production appear on the top of the + * stack. Once this occurs, a reduce is performed. This involves removing + * the Symbols corresponding to the right hand side of the production + * (the so called "handle") and replacing them with the non-terminal from + * the left hand side of the production.

+ * + * To control the decision of whether to shift or reduce at any given point, + * the parser uses a state machine (the "viable prefix recognition machine" + * built by the parser generator). The current state of the machine is placed + * on top of the parse stack (stored as part of a Symbol object representing + * a terminal or non terminal). The parse action table is consulted + * (using the current state and the current lookahead Symbol as indexes) to + * determine whether to shift or to reduce. When the parser shifts, it + * changes to a new state by pushing a new Symbol (containing a new state) + * onto the stack. When the parser reduces, it pops the handle (right hand + * side of a production) off the stack. This leaves the parser in the state + * it was in before any of those Symbols were matched. Next the reduce-goto + * table is consulted (using the new state and current lookahead Symbol as + * indexes) to determine a new state to go to. The parser then shifts to + * this goto state by pushing the left hand side Symbol of the production + * (also containing the new state) onto the stack.

+ * + * This class actually provides four LR parsers. The methods parse() and + * debug_parse() provide two versions of the main parser (the only difference + * being that debug_parse() emits debugging trace messages as it parses). + * In addition to these main parsers, the error recovery mechanism uses two + * more. One of these is used to simulate "parsing ahead" in the input + * without carrying out actions (to verify that a potential error recovery + * has worked), and the other is used to parse through buffered "parse ahead" + * input in order to execute all actions and re-synchronize the actual parser + * configuration.

+ * + * This is an abstract class which is normally filled out by a subclass + * generated by the JavaCup parser generator. In addition to supplying + * the actual parse tables, generated code also supplies methods which + * invoke various pieces of user supplied code, provide access to certain + * special Symbols (e.g., EOF and error), etc. Specifically, the following + * abstract methods are normally supplied by generated code: + *

+ *
short[][] production_table() + *
Provides a reference to the production table (indicating the index of + * the left hand side non terminal and the length of the right hand side + * for each production in the grammar). + *
short[][] action_table() + *
Provides a reference to the parse action table. + *
short[][] reduce_table() + *
Provides a reference to the reduce-goto table. + *
int start_state() + *
Indicates the index of the start state. + *
int start_production() + *
Indicates the index of the starting production. + *
int EOF_sym() + *
Indicates the index of the EOF Symbol. + *
int error_sym() + *
Indicates the index of the error Symbol. + *
Symbol do_action() + *
Executes a piece of user supplied action code. This always comes at + * the point of a reduce in the parse, so this code also allocates and + * fills in the left hand side non terminal Symbol object that is to be + * pushed onto the stack for the reduce. + *
void init_actions() + *
Code to initialize a special object that encapsulates user supplied + * actions (this object is used by do_action() to actually carry out the + * actions). + *
+ * + * In addition to these routines that must be supplied by the + * generated subclass there are also a series of routines that may + * be supplied. These include: + *
+ *
Symbol scan() + *
Used to get the next input Symbol from the scanner. + *
Scanner getScanner() + *
Used to provide a scanner for the default implementation of + * scan(). + *
int error_sync_size() + *
This determines how many Symbols past the point of an error + * must be parsed without error in order to consider a recovery to + * be valid. This defaults to 3. Values less than 2 are not + * recommended. + *
void report_error(String message, Object info) + *
This method is called to report an error. The default implementation + * simply prints a message to System.err and where the error occurred. + * This method is often replaced in order to provide a more sophisticated + * error reporting mechanism. + *
void report_fatal_error(String message, Object info) + *
This method is called when a fatal error that cannot be recovered from + * is encountered. In the default implementation, it calls + * report_error() to emit a message, then throws an exception. + *
void syntax_error(Symbol cur_token) + *
This method is called as soon as syntax error is detected (but + * before recovery is attempted). In the default implementation it + * invokes: report_error("Syntax error", null); + *
void unrecovered_syntax_error(Symbol cur_token) + *
This method is called if syntax error recovery fails. In the default + * implementation it invokes:
+ * report_fatal_error("Couldn't repair and continue parse", null); + *
+ * + * @see java_cup.runtime.Symbol + * @see java_cup.runtime.Symbol + * @see java_cup.runtime.virtual_parse_stack + * @version last updated: 7/3/96 + * @author Frank Flannery + */ +@SuppressWarnings("unchecked") +public abstract class lr_parser { + /*-----------------------------------------------------------*/ + /*--- Constructor(s) ----------------------------------------*/ + /*-----------------------------------------------------------*/ + + /** + * Simple constructor. + */ + public lr_parser() { + symbolFactory = new DefaultSymbolFactory(); + } + + /** + * Constructor that sets the default scanner. [CSA/davidm] + */ + public lr_parser(Scanner s) { + this(s,new DefaultSymbolFactory()); // TUM 20060327 old cup v10 Symbols as default + } + /** + * Constructor that sets the default scanner and a SymbolFactory + */ + public lr_parser(Scanner s, SymbolFactory symfac) { + this(); // in case default constructor someday does something + symbolFactory = symfac; + setScanner(s); + } + public SymbolFactory symbolFactory;// = new DefaultSymbolFactory(); + /** + * Whenever creation of a new Symbol is necessary, one should use this factory. + */ + public SymbolFactory getSymbolFactory(){ + return symbolFactory; + } + /*-----------------------------------------------------------*/ + /*--- (Access to) Static (Class) Variables ------------------*/ + /*-----------------------------------------------------------*/ + + /** The default number of Symbols after an error we much match to consider + * it recovered from. + */ + protected final static int _error_sync_size = 3; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The number of Symbols after an error we much match to consider it + * recovered from. + */ + protected int error_sync_size() {return _error_sync_size; } + + /*-----------------------------------------------------------*/ + /*--- (Access to) Instance Variables ------------------------*/ + /*-----------------------------------------------------------*/ + + /** Table of production information (supplied by generated subclass). + * This table contains one entry per production and is indexed by + * the negative-encoded values (reduce actions) in the action_table. + * Each entry has two parts, the index of the non-terminal on the + * left hand side of the production, and the number of Symbols + * on the right hand side. + */ + public abstract short[][] production_table(); + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The action table (supplied by generated subclass). This table is + * indexed by state and terminal number indicating what action is to + * be taken when the parser is in the given state (i.e., the given state + * is on top of the stack) and the given terminal is next on the input. + * States are indexed using the first dimension, however, the entries for + * a given state are compacted and stored in adjacent index, value pairs + * which are searched for rather than accessed directly (see get_action()). + * The actions stored in the table will be either shifts, reduces, or + * errors. Shifts are encoded as positive values (one greater than the + * state shifted to). Reduces are encoded as negative values (one less + * than the production reduced by). Error entries are denoted by zero. + * + * @see java_cup.runtime.lr_parser#get_action + */ + public abstract short[][] action_table(); + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The reduce-goto table (supplied by generated subclass). This + * table is indexed by state and non-terminal number and contains + * state numbers. States are indexed using the first dimension, however, + * the entries for a given state are compacted and stored in adjacent + * index, value pairs which are searched for rather than accessed + * directly (see get_reduce()). When a reduce occurs, the handle + * (corresponding to the RHS of the matched production) is popped off + * the stack. The new top of stack indicates a state. This table is + * then indexed by that state and the LHS of the reducing production to + * indicate where to "shift" to. + * + * @see java_cup.runtime.lr_parser#get_reduce + */ + public abstract short[][] reduce_table(); + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The index of the start state (supplied by generated subclass). */ + public abstract int start_state(); + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The index of the start production (supplied by generated subclass). */ + public abstract int start_production(); + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The index of the end of file terminal Symbol (supplied by generated + * subclass). + */ + public abstract int EOF_sym(); + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The index of the special error Symbol (supplied by generated subclass). */ + public abstract int error_sym(); + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Internal flag to indicate when parser should quit. */ + protected boolean _done_parsing = false; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** This method is called to indicate that the parser should quit. This is + * normally called by an accept action, but can be used to cancel parsing + * early in other circumstances if desired. + */ + public void done_parsing() + { + _done_parsing = true; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + /* Global parse state shared by parse(), error recovery, and + * debugging routines */ + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Indication of the index for top of stack (for use by actions). */ + protected int tos; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The current lookahead Symbol. */ + protected Symbol cur_token; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The parse stack itself. */ + protected Stack stack = new Stack(); + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Direct reference to the production table. */ + protected short[][] production_tab; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Direct reference to the action table. */ + protected short[][] action_tab; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Direct reference to the reduce-goto table. */ + protected short[][] reduce_tab; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** This is the scanner object used by the default implementation + * of scan() to get Symbols. To avoid name conflicts with existing + * code, this field is private. [CSA/davidm] */ + private Scanner _scanner; + + /** + * Simple accessor method to set the default scanner. + */ + public void setScanner(Scanner s) { _scanner = s; } + + /** + * Simple accessor method to get the default scanner. + */ + public Scanner getScanner() { return _scanner; } + + /*-----------------------------------------------------------*/ + /*--- General Methods ---------------------------------------*/ + /*-----------------------------------------------------------*/ + + /** Perform a bit of user supplied action code (supplied by generated + * subclass). Actions are indexed by an internal action number assigned + * at parser generation time. + * + * @param act_num the internal index of the action to be performed. + * @param parser the parser object we are acting for. + * @param stack the parse stack of that object. + * @param top the index of the top element of the parse stack. + */ + public abstract Symbol do_action( + int act_num, + lr_parser parser, + Stack stack, + int top) + throws java.lang.Exception; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** User code for initialization inside the parser. Typically this + * initializes the scanner. This is called before the parser requests + * the first Symbol. Here this is just a placeholder for subclasses that + * might need this and we perform no action. This method is normally + * overridden by the generated code using this contents of the "init with" + * clause as its body. + */ + public void user_init() throws java.lang.Exception { } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Initialize the action object. This is called before the parser does + * any parse actions. This is filled in by generated code to create + * an object that encapsulates all action code. + */ + protected abstract void init_actions() throws java.lang.Exception; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Get the next Symbol from the input (supplied by generated subclass). + * Once end of file has been reached, all subsequent calls to scan + * should return an EOF Symbol (which is Symbol number 0). By default + * this method returns getScanner().next_token(); this implementation + * can be overriden by the generated parser using the code declared in + * the "scan with" clause. Do not recycle objects; every call to + * scan() should return a fresh object. + */ + public Symbol scan() throws java.lang.Exception { + Symbol sym = getScanner().next_token(); + return (sym!=null) ? sym : getSymbolFactory().newSymbol("END_OF_FILE",EOF_sym()); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Report a fatal error. This method takes a message string and an + * additional object (to be used by specializations implemented in + * subclasses). Here in the base class a very simple implementation + * is provided which reports the error then throws an exception. + * + * @param message an error message. + * @param info an extra object reserved for use by specialized subclasses. + */ + public void report_fatal_error( + String message, + Object info) + throws java.lang.Exception + { + /* stop parsing (not really necessary since we throw an exception, but) */ + done_parsing(); + + /* use the normal error message reporting to put out the message */ + report_error(message, info); + + /* throw an exception */ + throw new Exception("Can't recover from previous error(s)"); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Report a non fatal error (or warning). This method takes a message + * string and an additional object (to be used by specializations + * implemented in subclasses). Here in the base class a very simple + * implementation is provided which simply prints the message to + * System.err. + * + * @param message an error message. + * @param info an extra object reserved for use by specialized subclasses. + */ + public void report_error(String message, Object info) + { + System.err.print(message); + System.err.flush(); + if (info instanceof Symbol) + if (((Symbol)info).left != -1) + System.err.println(" at character " + ((Symbol)info).left + + " of input"); + else System.err.println(""); + else System.err.println(""); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** This method is called when a syntax error has been detected and recovery + * is about to be invoked. Here in the base class we just emit a + * "Syntax error" error message. + * + * @param cur_token the current lookahead Symbol. + */ + public void syntax_error(Symbol cur_token) throws Exception + { + report_error("Syntax error", cur_token); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** This method is called if it is determined that syntax error recovery + * has been unsuccessful. Here in the base class we report a fatal error. + * + * @param cur_token the current lookahead Symbol. + */ + public void unrecovered_syntax_error(Symbol cur_token) + throws java.lang.Exception + { + report_fatal_error("Couldn't repair and continue parse", cur_token); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Fetch an action from the action table. The table is broken up into + * rows, one per state (rows are indexed directly by state number). + * Within each row, a list of index, value pairs are given (as sequential + * entries in the table), and the list is terminated by a default entry + * (denoted with a Symbol index of -1). To find the proper entry in a row + * we do a linear or binary search (depending on the size of the row). + * + * @param state the state index of the action being accessed. + * @param sym the Symbol index of the action being accessed. + */ + protected final short get_action(int state, int sym) + { + short tag; + int first, last, probe; + short[] row = action_tab[state]; + + /* linear search if we are < 10 entries */ + if (row.length < 20) + for (probe = 0; probe < row.length; probe++) + { + /* is this entry labeled with our Symbol or the default? */ + tag = row[probe++]; + if (tag == sym || tag == -1) + { + /* return the next entry */ + return row[probe]; + } + } + /* otherwise binary search */ + else + { + first = 0; + last = (row.length-1)/2 - 1; /* leave out trailing default entry */ + while (first <= last) + { + probe = (first+last)/2; + if (sym == row[probe*2]) + return row[probe*2+1]; + else if (sym > row[probe*2]) + first = probe+1; + else + last = probe-1; + } + + /* not found, use the default at the end */ + return row[row.length-1]; + } + + /* shouldn't happened, but if we run off the end we return the + default (error == 0) */ + return 0; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Fetch a state from the reduce-goto table. The table is broken up into + * rows, one per state (rows are indexed directly by state number). + * Within each row, a list of index, value pairs are given (as sequential + * entries in the table), and the list is terminated by a default entry + * (denoted with a Symbol index of -1). To find the proper entry in a row + * we do a linear search. + * + * @param state the state index of the entry being accessed. + * @param sym the Symbol index of the entry being accessed. + */ + protected final short get_reduce(int state, int sym) + { + short tag; + short[] row = reduce_tab[state]; + + /* if we have a null row we go with the default */ + if (row == null) + return -1; + + for (int probe = 0; probe < row.length; probe++) + { + /* is this entry labeled with our Symbol or the default? */ + tag = row[probe++]; + if (tag == sym || tag == -1) + { + /* return the next entry */ + return row[probe]; + } + } + /* if we run off the end we return the default (error == -1) */ + return -1; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** This method provides the main parsing routine. It returns only when + * done_parsing() has been called (typically because the parser has + * accepted, or a fatal error has been reported). See the header + * documentation for the class regarding how shift/reduce parsers operate + * and how the various tables are used. + */ +public Symbol parse() throws java.lang.Exception + { + /* the current action code */ + int act; + + /* the Symbol/stack element returned by a reduce */ + Symbol lhs_sym = null; + + /* information about production being reduced with */ + short handle_size, lhs_sym_num; + + /* set up direct reference to tables to drive the parser */ + + production_tab = production_table(); + action_tab = action_table(); + reduce_tab = reduce_table(); + + /* initialize the action encapsulation object */ + init_actions(); + + /* do user initialization */ + user_init(); + + /* get the first token */ + cur_token = scan(); + + /* push dummy Symbol with start state to get us underway */ + stack.removeAllElements(); + stack.push(getSymbolFactory().startSymbol("START", 0, start_state())); + tos = 0; + + /* continue until we are told to stop */ + for (_done_parsing = false; !_done_parsing; ) + { + /* Check current token for freshness. */ + if (cur_token.used_by_parser) + throw new Error("Symbol recycling detected (fix your scanner)."); + + /* current state is always on the top of the stack */ + + /* look up action out of the current state with the current input */ + act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym); + + /* decode the action -- > 0 encodes shift */ + if (act > 0) + { + /* shift to the encoded state by pushing it on the stack */ + cur_token.parse_state = act-1; + cur_token.used_by_parser = true; + stack.push(cur_token); + tos++; + + /* advance to the next Symbol */ + cur_token = scan(); + } + /* if its less than zero, then it encodes a reduce action */ + else if (act < 0) + { + /* perform the action for the reduce */ + lhs_sym = do_action((-act)-1, this, stack, tos); + + /* look up information about the production */ + lhs_sym_num = production_tab[(-act)-1][0]; + handle_size = production_tab[(-act)-1][1]; + + /* pop the handle off the stack */ + for (int i = 0; i < handle_size; i++) + { + stack.pop(); + tos--; + } + + /* look up the state to go to from the one popped back to */ + act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num); + + /* shift to that state */ + lhs_sym.parse_state = act; + lhs_sym.used_by_parser = true; + stack.push(lhs_sym); + tos++; + } + /* finally if the entry is zero, we have an error */ + else if (act == 0) + { + /* call user syntax error reporting routine */ + syntax_error(cur_token); + + /* try to error recover */ + if (!error_recovery(false)) + { + /* if that fails give up with a fatal syntax error */ + unrecovered_syntax_error(cur_token); + + /* just in case that wasn't fatal enough, end parse */ + done_parsing(); + } else { + lhs_sym = (Symbol)stack.peek(); + } + } + } + return lhs_sym; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Write a debugging message to System.err for the debugging version + * of the parser. + * + * @param mess the text of the debugging message. + */ + public void debug_message(String mess) + { + System.err.println(mess); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Dump the parse stack for debugging purposes. */ + public void dump_stack() + { + if (stack == null) + { + debug_message("# Stack dump requested, but stack is null"); + return; + } + + debug_message("============ Parse Stack Dump ============"); + + /* dump the stack */ + for (int i=0; i"); + if ((i%3)==2 || (i==(stack.size()-1))) { + debug_message(sb.toString()); + sb = new StringBuffer(" "); + } + } + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Perform a parse with debugging output. This does exactly the + * same things as parse(), except that it calls debug_shift() and + * debug_reduce() when shift and reduce moves are taken by the parser + * and produces various other debugging messages. + */ + public Symbol debug_parse() + throws java.lang.Exception + { + /* the current action code */ + int act; + + /* the Symbol/stack element returned by a reduce */ + Symbol lhs_sym = null; + + /* information about production being reduced with */ + short handle_size, lhs_sym_num; + + /* set up direct reference to tables to drive the parser */ + production_tab = production_table(); + action_tab = action_table(); + reduce_tab = reduce_table(); + + debug_message("# Initializing parser"); + + /* initialize the action encapsulation object */ + init_actions(); + + /* do user initialization */ + user_init(); + + /* the current Symbol */ + cur_token = scan(); + + debug_message("# Current Symbol is #" + cur_token.sym); + + /* push dummy Symbol with start state to get us underway */ + stack.removeAllElements(); + stack.push(getSymbolFactory().startSymbol("START",0, start_state())); + tos = 0; + + /* continue until we are told to stop */ + for (_done_parsing = false; !_done_parsing; ) + { + /* Check current token for freshness. */ + if (cur_token.used_by_parser) + throw new Error("Symbol recycling detected (fix your scanner)."); + + /* current state is always on the top of the stack */ + //debug_stack(); + + /* look up action out of the current state with the current input */ + act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym); + + /* decode the action -- > 0 encodes shift */ + if (act > 0) + { + /* shift to the encoded state by pushing it on the stack */ + cur_token.parse_state = act-1; + cur_token.used_by_parser = true; + debug_shift(cur_token); + stack.push(cur_token); + tos++; + + /* advance to the next Symbol */ + cur_token = scan(); + debug_message("# Current token is " + cur_token); + } + /* if its less than zero, then it encodes a reduce action */ + else if (act < 0) + { + /* perform the action for the reduce */ + lhs_sym = do_action((-act)-1, this, stack, tos); + + /* look up information about the production */ + lhs_sym_num = production_tab[(-act)-1][0]; + handle_size = production_tab[(-act)-1][1]; + + debug_reduce((-act)-1, lhs_sym_num, handle_size); + + /* pop the handle off the stack */ + for (int i = 0; i < handle_size; i++) + { + stack.pop(); + tos--; + } + + /* look up the state to go to from the one popped back to */ + act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num); + debug_message("# Reduce rule: top state " + + ((Symbol)stack.peek()).parse_state + + ", lhs sym " + lhs_sym_num + " -> state " + act); + + /* shift to that state */ + lhs_sym.parse_state = act; + lhs_sym.used_by_parser = true; + stack.push(lhs_sym); + tos++; + + debug_message("# Goto state #" + act); + } + /* finally if the entry is zero, we have an error */ + else if (act == 0) + { + /* call user syntax error reporting routine */ + syntax_error(cur_token); + + /* try to error recover */ + if (!error_recovery(true)) + { + /* if that fails give up with a fatal syntax error */ + unrecovered_syntax_error(cur_token); + + /* just in case that wasn't fatal enough, end parse */ + done_parsing(); + } else { + lhs_sym = (Symbol)stack.peek(); + } + } + } + return lhs_sym; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + /* Error recovery code */ + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Attempt to recover from a syntax error. This returns false if recovery + * fails, true if it succeeds. Recovery happens in 4 steps. First we + * pop the parse stack down to a point at which we have a shift out + * of the top-most state on the error Symbol. This represents the + * initial error recovery configuration. If no such configuration is + * found, then we fail. Next a small number of "lookahead" or "parse + * ahead" Symbols are read into a buffer. The size of this buffer is + * determined by error_sync_size() and determines how many Symbols beyond + * the error must be matched to consider the recovery a success. Next, + * we begin to discard Symbols in attempt to get past the point of error + * to a point where we can continue parsing. After each Symbol, we attempt + * to "parse ahead" though the buffered lookahead Symbols. The "parse ahead" + * process simulates that actual parse, but does not modify the real + * parser's configuration, nor execute any actions. If we can parse all + * the stored Symbols without error, then the recovery is considered a + * success. Once a successful recovery point is determined, we do an + * actual parse over the stored input -- modifying the real parse + * configuration and executing all actions. Finally, we return the the + * normal parser to continue with the overall parse. + * + * @param debug should we produce debugging messages as we parse. + */ + protected boolean error_recovery(boolean debug) + throws java.lang.Exception + { + if (debug) debug_message("# Attempting error recovery"); + + /* first pop the stack back into a state that can shift on error and + do that shift (if that fails, we fail) */ + if (!find_recovery_config(debug)) + { + if (debug) debug_message("# Error recovery fails"); + return false; + } + + /* read ahead to create lookahead we can parse multiple times */ + read_lookahead(); + + /* repeatedly try to parse forward until we make it the required dist */ + for (;;) + { + /* try to parse forward, if it makes it, bail out of loop */ + if (debug) debug_message("# Trying to parse ahead"); + if (try_parse_ahead(debug)) + { + break; + } + + /* if we are now at EOF, we have failed */ + if (lookahead[0].sym == EOF_sym()) + { + if (debug) debug_message("# Error recovery fails at EOF"); + return false; + } + + /* otherwise, we consume another Symbol and try again */ + // BUG FIX by Bruce Hutton + // Computer Science Department, University of Auckland, + // Auckland, New Zealand. + // It is the first token that is being consumed, not the one + // we were up to parsing + if (debug) + debug_message("# Consuming Symbol #" + lookahead[ 0 ].sym); + restart_lookahead(); + } + + /* we have consumed to a point where we can parse forward */ + if (debug) debug_message("# Parse-ahead ok, going back to normal parse"); + + /* do the real parse (including actions) across the lookahead */ + parse_lookahead(debug); + + /* we have success */ + return true; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Determine if we can shift under the special error Symbol out of the + * state currently on the top of the (real) parse stack. + */ + protected boolean shift_under_error() + { + /* is there a shift under error Symbol */ + return get_action(((Symbol)stack.peek()).parse_state, error_sym()) > 0; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Put the (real) parse stack into error recovery configuration by + * popping the stack down to a state that can shift on the special + * error Symbol, then doing the shift. If no suitable state exists on + * the stack we return false + * + * @param debug should we produce debugging messages as we parse. + */ + protected boolean find_recovery_config(boolean debug) + { + Symbol error_token; + int act; + + if (debug) debug_message("# Finding recovery state on stack"); + + /* Remember the right-position of the top symbol on the stack */ + Symbol right = ((Symbol)stack.peek());// TUM 20060327 removed .right + Symbol left = right;// TUM 20060327 removed .left + + /* pop down until we can shift under error Symbol */ + while (!shift_under_error()) + { + /* pop the stack */ + if (debug) + debug_message("# Pop stack by one, state was # " + + ((Symbol)stack.peek()).parse_state); + left = ((Symbol)stack.pop()); // TUM 20060327 removed .left + tos--; + + /* if we have hit bottom, we fail */ + if (stack.empty()) + { + if (debug) debug_message("# No recovery state found on stack"); + return false; + } + } + + /* state on top of the stack can shift under error, find the shift */ + act = get_action(((Symbol)stack.peek()).parse_state, error_sym()); + if (debug) + { + debug_message("# Recover state found (#" + + ((Symbol)stack.peek()).parse_state + ")"); + debug_message("# Shifting on error to state #" + (act-1)); + } + + /* build and shift a special error Symbol */ + error_token = getSymbolFactory().newSymbol("ERROR",error_sym(), left, right); + error_token.parse_state = act-1; + error_token.used_by_parser = true; + stack.push(error_token); + tos++; + + return true; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Lookahead Symbols used for attempting error recovery "parse aheads". */ + protected Symbol lookahead[]; + + /** Position in lookahead input buffer used for "parse ahead". */ + protected int lookahead_pos; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Read from input to establish our buffer of "parse ahead" lookahead + * Symbols. + */ + protected void read_lookahead() throws java.lang.Exception + { + /* create the lookahead array */ + lookahead = new Symbol[error_sync_size()]; + + /* fill in the array */ + for (int i = 0; i < error_sync_size(); i++) + { + lookahead[i] = cur_token; + cur_token = scan(); + } + + /* start at the beginning */ + lookahead_pos = 0; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Return the current lookahead in our error "parse ahead" buffer. */ + protected Symbol cur_err_token() { return lookahead[lookahead_pos]; } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Advance to next "parse ahead" input Symbol. Return true if we have + * input to advance to, false otherwise. + */ + protected boolean advance_lookahead() + { + /* advance the input location */ + lookahead_pos++; + + /* return true if we didn't go off the end */ + return lookahead_pos < error_sync_size(); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Reset the parse ahead input to one Symbol past where we started error + * recovery (this consumes one new Symbol from the real input). + */ + protected void restart_lookahead() throws java.lang.Exception + { + /* move all the existing input over */ + for (int i = 1; i < error_sync_size(); i++) + lookahead[i-1] = lookahead[i]; + + /* read a new Symbol into the last spot */ + // BUG Fix by Bruce Hutton + // Computer Science Department, University of Auckland, + // Auckland, New Zealand. [applied 5-sep-1999 by csa] + // The following two lines were out of order!! + lookahead[error_sync_size()-1] = cur_token; + cur_token = scan(); + + /* reset our internal position marker */ + lookahead_pos = 0; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Do a simulated parse forward (a "parse ahead") from the current + * stack configuration using stored lookahead input and a virtual parse + * stack. Return true if we make it all the way through the stored + * lookahead input without error. This basically simulates the action of + * parse() using only our saved "parse ahead" input, and not executing any + * actions. + * + * @param debug should we produce debugging messages as we parse. + */ + protected boolean try_parse_ahead(boolean debug) + throws java.lang.Exception + { + int act; + short lhs, rhs_size; + + /* create a virtual stack from the real parse stack */ + virtual_parse_stack vstack = new virtual_parse_stack(stack); + + /* parse until we fail or get past the lookahead input */ + for (;;) + { + /* look up the action from the current state (on top of stack) */ + act = get_action(vstack.top(), cur_err_token().sym); + + /* if its an error, we fail */ + if (act == 0) return false; + + /* > 0 encodes a shift */ + if (act > 0) + { + /* push the new state on the stack */ + vstack.push(act-1); + + if (debug) debug_message("# Parse-ahead shifts Symbol #" + + cur_err_token().sym + " into state #" + (act-1)); + + /* advance simulated input, if we run off the end, we are done */ + if (!advance_lookahead()) return true; + } + /* < 0 encodes a reduce */ + else + { + /* if this is a reduce with the start production we are done */ + if ((-act)-1 == start_production()) + { + if (debug) debug_message("# Parse-ahead accepts"); + return true; + } + + /* get the lhs Symbol and the rhs size */ + lhs = production_tab[(-act)-1][0]; + rhs_size = production_tab[(-act)-1][1]; + + /* pop handle off the stack */ + for (int i = 0; i < rhs_size; i++) + vstack.pop(); + + if (debug) + debug_message("# Parse-ahead reduces: handle size = " + + rhs_size + " lhs = #" + lhs + " from state #" + vstack.top()); + + /* look up goto and push it onto the stack */ + vstack.push(get_reduce(vstack.top(), lhs)); + if (debug) + debug_message("# Goto state #" + vstack.top()); + } + } + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Parse forward using stored lookahead Symbols. In this case we have + * already verified that parsing will make it through the stored lookahead + * Symbols and we are now getting back to the point at which we can hand + * control back to the normal parser. Consequently, this version of the + * parser performs all actions and modifies the real parse configuration. + * This returns once we have consumed all the stored input or we accept. + * + * @param debug should we produce debugging messages as we parse. + */ + protected void parse_lookahead(boolean debug) + throws java.lang.Exception + { + /* the current action code */ + int act; + + /* the Symbol/stack element returned by a reduce */ + Symbol lhs_sym = null; + + /* information about production being reduced with */ + short handle_size, lhs_sym_num; + + /* restart the saved input at the beginning */ + lookahead_pos = 0; + + if (debug) + { + debug_message("# Reparsing saved input with actions"); + debug_message("# Current Symbol is #" + cur_err_token().sym); + debug_message("# Current state is #" + + ((Symbol)stack.peek()).parse_state); + } + + /* continue until we accept or have read all lookahead input */ + while(!_done_parsing) + { + /* current state is always on the top of the stack */ + + /* look up action out of the current state with the current input */ + act = + get_action(((Symbol)stack.peek()).parse_state, cur_err_token().sym); + + /* decode the action -- > 0 encodes shift */ + if (act > 0) + { + /* shift to the encoded state by pushing it on the stack */ + cur_err_token().parse_state = act-1; + cur_err_token().used_by_parser = true; + if (debug) debug_shift(cur_err_token()); + stack.push(cur_err_token()); + tos++; + + /* advance to the next Symbol, if there is none, we are done */ + if (!advance_lookahead()) + { + if (debug) debug_message("# Completed reparse"); + + /* scan next Symbol so we can continue parse */ + // BUGFIX by Chris Harris : + // correct a one-off error by commenting out + // this next line. + /*cur_token = scan();*/ + + /* go back to normal parser */ + return; + } + + if (debug) + debug_message("# Current Symbol is #" + cur_err_token().sym); + } + /* if its less than zero, then it encodes a reduce action */ + else if (act < 0) + { + /* perform the action for the reduce */ + lhs_sym = do_action((-act)-1, this, stack, tos); + + /* look up information about the production */ + lhs_sym_num = production_tab[(-act)-1][0]; + handle_size = production_tab[(-act)-1][1]; + + if (debug) debug_reduce((-act)-1, lhs_sym_num, handle_size); + + /* pop the handle off the stack */ + for (int i = 0; i < handle_size; i++) + { + stack.pop(); + tos--; + } + + /* look up the state to go to from the one popped back to */ + act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num); + + /* shift to that state */ + lhs_sym.parse_state = act; + lhs_sym.used_by_parser = true; + stack.push(lhs_sym); + tos++; + + if (debug) debug_message("# Goto state #" + act); + + } + /* finally if the entry is zero, we have an error + (shouldn't happen here, but...)*/ + else if (act == 0) + { + report_fatal_error("Syntax error", lhs_sym); + return; + } + } + + + } + + /*-----------------------------------------------------------*/ + + /** Utility function: unpacks parse tables from strings */ + protected static short[][] unpackFromStrings(String[] sa) + { + // Concatanate initialization strings. + StringBuffer sb = new StringBuffer(sa[0]); + for (int i=1; i= real_stack.size()) return; + + /* get a copy of the first Symbol we have not transfered */ + stack_sym = (Symbol)real_stack.elementAt(real_stack.size()-1-real_next); + + /* record the transfer */ + real_next++; + + /* put the state number from the Symbol onto the virtual stack */ + vstack.push(new Integer(stack_sym.parse_state)); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Indicate whether the stack is empty. */ + public boolean empty() + { + /* if vstack is empty then we were unable to transfer onto it and + the whole thing is empty. */ + return vstack.empty(); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Return value on the top of the stack (without popping it). */ + public int top() throws java.lang.Exception + { + if (vstack.empty()) + throw new Exception( + "Internal parser error: top() called on empty virtual stack"); + + return ((Integer)vstack.peek()).intValue(); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Pop the stack. */ + public void pop() throws java.lang.Exception + { + if (vstack.empty()) + throw new Exception( + "Internal parser error: pop from empty virtual stack"); + + /* pop it */ + vstack.pop(); + + /* if we are now empty transfer an element (if there is one) */ + if (vstack.empty()) + get_from_real(); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Push a state number onto the stack. */ + public void push(int state_num) + { + vstack.push(new Integer(state_num)); + } + + /*-----------------------------------------------------------*/ + +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/BinaryExpression.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/BinaryExpression.java new file mode 100644 index 00000000..b664587f --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/BinaryExpression.java @@ -0,0 +1,126 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + +import kodkod.ast.operator.ExprOperator; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + + +/** + * A relational {@link kodkod.ast.Expression expression} with two children. + * + * @specfield left: Expression + * @specfield right: Expression + * @specfield op: ExprOperator + * @specfield op.binary() + * @invariant children = 0->left + 1->right + * @author Emina Torlak + */ +public final class BinaryExpression extends Expression { + private final ExprOperator op; + private final Expression left; + private final Expression right; + private final int arity; + + /** + * Constructs a new binary expression: left op right + * + * @ensures this.left' = left && this.right' = right && this.op' = op + * @throws NullPointerException - left = null || right = null || op = null + * @throws IllegalArgumentException - left and right cannot be combined with the specified operator. + */ + BinaryExpression(final Expression left, final ExprOperator op, final Expression right) { + switch(op) { + case UNION : case INTERSECTION : case DIFFERENCE : case OVERRIDE : + this.arity = left.arity(); + if (arity!=right.arity()) + throw new IllegalArgumentException("Incompatible arities: " + left + " and " + right); + break; + case JOIN : + this.arity = left.arity() + right.arity() - 2; + if (arity < 1) + throw new IllegalArgumentException("Incompatible arities: " + left + " and " + right); + break; + case PRODUCT : + this.arity = left.arity() + right.arity(); + break; + default : + throw new IllegalArgumentException("Not a binary operator: " + op); + } + + this.op = op; + this.left = left; + this.right = right; + + } + + /** + * Returns the arity of this binary expression. + * @return this.arity + * @see kodkod.ast.Expression#arity() + */ + public int arity() { + return arity; + } + + /** + * Returns this.op. + * @return this.op + */ + public ExprOperator op() { return op ; } + /** + * Returns the left child of this. + * @return this.left + */ + public Expression left() {return left;} + + /** + * Returns the right child of this. + * @return this.right + */ + public Expression right() {return right;} + + /** + * {@inheritDoc} + * @see kodkod.ast.Expression#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public E accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return "(" + left + " " + op + " " + right + ")"; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/BinaryFormula.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/BinaryFormula.java new file mode 100644 index 00000000..2a982a56 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/BinaryFormula.java @@ -0,0 +1,97 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + +import kodkod.ast.operator.FormulaOperator; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + +/** + * A {@link kodkod.ast.Formula formula} with two children. + * + * @specfield left: Formula + * @specfield right: Formula + * @specfield op: FormulaOperator + * @invariant children = 0->left + 1->right + * @author Emina Torlak + */ +public final class BinaryFormula extends Formula { + + private final Formula left; + private final Formula right; + private final FormulaOperator op; + + /** + * Constructs a new binary formula: left op right + * + * @ensures this.left' = left && this.right' = right && this.op' = op + * @throws NullPointerException - left = null || right = null || op = null + */ + BinaryFormula(Formula left, FormulaOperator op, Formula right) { + this.left = left; + this.right = right; + this.op = op; + } + + /** + * Returns the left child of this. + * @return this.left + */ + public Formula left() {return left;} + + /** + * Returns the right child of this. + * @return this.right + */ + public Formula right() {return right;} + + /** + * Returns the operator of this. + * @return this.op + */ + public FormulaOperator op() {return op;} + + /** + * {@inheritDoc} + * @see kodkod.ast.Formula#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public F accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return "(" + left + " " + op + " " + right + ")"; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/BinaryIntExpression.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/BinaryIntExpression.java new file mode 100644 index 00000000..c1faf40d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/BinaryIntExpression.java @@ -0,0 +1,98 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + + +import kodkod.ast.operator.IntOperator; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + +/** + * A binary integer expression such as x + y. + * @specfield left: IntExpression + * @specfield right: IntExpression + * @specfield op: IntOperator + * @specfield op.binary() + * @invariant children = 0->left + 1->right + * @author Emina Torlak + */ +public final class BinaryIntExpression extends IntExpression { + private final IntOperator op; + private final IntExpression left, right; + + /** + * Constructs a new binary int formula: left op right + * + * @ensures this.left' = left && this.right' = right && this.op' = op + * @throws NullPointerException - left = null || right = null || op = null + */ + public BinaryIntExpression(final IntExpression left, final IntOperator op, final IntExpression right) { + if (!op.binary()) throw new IllegalArgumentException("Not a binary operator: " + op); + this.left = left; + this.right = right; + this.op = op; + } + + /** + * Returns the left child of this. + * @return this.left + */ + public IntExpression left() {return left;} + + /** + * Returns the right child of this. + * @return this.right + */ + public IntExpression right() {return right;} + + /** + * Returns the operator of this. + * @return this.op + */ + public IntOperator op() {return op;} + + /** + * {@inheritDoc} + * @see kodkod.ast.IntExpression#accept(kodkod.ast.visitor.ReturnVisitor) + */ + @Override + public I accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.IntExpression#accept(kodkod.ast.visitor.VoidVisitor) + */ + @Override + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return "(" + left + " " + op + " " + right + ")"; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/ComparisonFormula.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/ComparisonFormula.java new file mode 100644 index 00000000..50a94db2 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/ComparisonFormula.java @@ -0,0 +1,104 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + +import kodkod.ast.operator.ExprCompOperator; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + + + +/** + * A formula that compares two expressions, e.g. x = y + * + * @specfield left: Expression + * @specfield right: Expression + * @specfield op: ExprCompOperator + * @invariant children = 0->left + 1->right + * @author Emina Torlak + */ +public final class ComparisonFormula extends Formula{ + private final Expression left; + private final Expression right; + private final ExprCompOperator op; + + /** + * Constructs a new comparison formula: left op right + * + * @ensures this.left' = left && this.right' = right && this.op' = op + * * @throws NullPointerException - left = null || right = null || op = null + * @throws IllegalArgumentException - left.arity != right.arity + */ + ComparisonFormula(Expression left, ExprCompOperator op, Expression right) { + if (left.arity()!=right.arity()) { + throw new IllegalArgumentException( + "Arity mismatch: " + left + "::" + left.arity() + + " and " + right + "::" + right.arity()); + } + this.left = left; + this.right = right; + this.op = op; + } + + /** + * Returns the left child of this. + * @return this.left + */ + public Expression left() {return left;} + + /** + * Returns the right child of this. + * @return this.right + */ + public Expression right() {return right;} + + /** + * Returns the operator of this. + * @return this.op + */ + public ExprCompOperator op() {return op;} + + /** + * {@inheritDoc} + * @see kodkod.ast.Formula#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public F accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return "(" + left + " " + op + " " + right + ")"; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Comprehension.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Comprehension.java new file mode 100644 index 00000000..fffb69fb --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Comprehension.java @@ -0,0 +1,107 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + + +import kodkod.ast.operator.Multiplicity; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + + + +/** + * A comprehension expression, e.g. { a: A, b: B | a.r = b } + * + * @specfield decls: Declarations + * @specfield formula: Formula + * @invariant arity = sum(decls.declarations().arity) + * @invariant children = 0->decls + 1->formula + * @author Emina Torlak + */ +public final class Comprehension extends Expression { + + private final Decls decls; + private final Formula formula; + + + /** + * Constructs a comprehension expression with the specified decls + * and formula + * + * @ensures this.decls' = decls && this.formula' = formula + * @throws NullPointerException - decls = null || formula = null + */ + Comprehension(Decls declarations, Formula formula) { + if (formula == null) throw new NullPointerException("null formula"); + for(Decl decl : declarations) { + if (decl.variable().arity()>1 || decl.multiplicity()!=Multiplicity.ONE) + throw new IllegalArgumentException("Cannot have a higher order declaration in a comprehension: "+decl); + } + this.decls = declarations; + this.formula = formula; + } + + /** + * @return this.formula + */ + public Formula formula() {return formula; } + + /** + * @return this.decls + */ + public Decls decls() {return decls;} + + /** + * Returns the arity of this comprehension expression, which is the sum + * of the arities of declared variables + * + * @return #this.decls + */ + public int arity() { + return decls.size(); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Expression#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public E accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return "{ " + decls().toString() + " | " + formula().toString() + " }"; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/ConstantExpression.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/ConstantExpression.java new file mode 100644 index 00000000..47835731 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/ConstantExpression.java @@ -0,0 +1,61 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + + +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + +/** + * A constant valued expression. + * + * @invariant no children + * @author Emina Torlak + */ +public final class ConstantExpression extends LeafExpression { + + /** + * Constructs a constant expression with the given arity. + */ + ConstantExpression(String name, int arity) { + super(name, arity); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Expression#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public E accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/ConstantFormula.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/ConstantFormula.java new file mode 100644 index 00000000..317d44be --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/ConstantFormula.java @@ -0,0 +1,74 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + + +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + +/** + * A constant {@link kodkod.ast.Formula formula}, true or false. + * + * @invariant no children + * @author Emina Torlak + */ +public abstract class ConstantFormula extends Formula { + private final boolean value; + /** + * Constructs a constant formula with the given value. + */ + ConstantFormula(boolean value) { + this.value = value; + } + + /** + * Returns the boolean value that corresponds to this + * constant formula. + * @return this=TRUE => true, false + */ + public final boolean booleanValue() { return value; } + + /** + * {@inheritDoc} + * @see kodkod.ast.Formula#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public F accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return String.valueOf(booleanValue()); + } +} + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Decl.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Decl.java new file mode 100644 index 00000000..76f2e886 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Decl.java @@ -0,0 +1,109 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + + +import kodkod.ast.operator.Multiplicity; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + + + + +/** + * A variable declaration, such as 'x : lone X'. Declarations + * are used with quantified formulas and comprehension expressions. + * + * @specfield variable: Variable + * @specfield expression: Expression + * @specfield multiplicity: LONE + ONE + SOME + SET + * @invariant variable.arity = expression.arity + * @invariant children = 0->variable + 1->expression + * @author Emina Torlak + */ +public final class Decl extends Decls { + + private final Variable variable; + private final Multiplicity mult; + private final Expression expression; + + /** + * Constructs a new declaration from the specified variable and + * expression, with the specified order. + * + * @ensures this.variable' = variable && this.expression' = expression && this.multiplicity' = mult + * @throws NullPointerException - variable = null || expression = null || mult = null + * @throws IllegalArgumentException - variable.arity != expression.arity + */ + Decl(Variable variable, Multiplicity mult, Expression expression) { + if (mult==Multiplicity.NO) + throw new IllegalArgumentException("NO is not a valid multiplicity in a declaration."); + if (variable.arity() != expression.arity()) + throw new IllegalArgumentException("Unmatched arities in a declaration: " + variable + " and " + expression); + if (mult != Multiplicity.SET && expression.arity()>1) + throw new IllegalArgumentException("Cannot use multiplicity " + mult + " with an expression of arity > 1."); + this.variable = variable; + this.mult = mult; + this.expression = expression; + } + + /** + * Returns the variable in this declaration. + * @return this.variable + */ + public Variable variable() { return variable; } + + /** + * Returns the multiplicity in this declaration. + * @return this.multiplicity + */ + public Multiplicity multiplicity() { return mult; } + + /** + * Returns the expression in this declaration. + * @return this.exresssion + */ + public Expression expression() { return expression; } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public D accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { return variable + ": " + mult + " " + expression; } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Decls.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Decls.java new file mode 100644 index 00000000..d6a6d2a2 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Decls.java @@ -0,0 +1,125 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + +import java.util.Arrays; +import java.util.Iterator; + +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; +import kodkod.util.collections.Containers; + + +/** + * A sequence of decls. + * + * @specfield size: int + * @specfield decls: [0..size) -> one Decl + * @invariant size > 0 + * @invariant children = decls + * @author Emina Torlak + */ +public class Decls extends Node implements Iterable { + private final Decl[] decls; + + /** + * Constructs a Decls object with itself as its sole + * declaration. This constructor can only be called + * from inside the Decl constructor; otherwise it will + * throw a ClassCastException. + * @ensures this.declarations' = 0->this + * @throws ClassCastException - this !in Decl + */ + Decls() { + this.decls = new Decl[]{ (Decl) this }; + } + + /** + * Constructs a new Decls with the specified head and tail. + * @requires head.size > 0 && tail.size > 0 + * @ensures this.size' = head.size + tail.size && + * (all i: [0..head.size) | this.decls[i] = head.decls[i]) && + * (all i: [head.size..this.size') | this.decls[i] = tail.decls[i]) + * @throws NullPointerException - head = null || tail is null + */ + private Decls(Decls head, Decls tail) { + this.decls = new Decl[head.size()+tail.size()]; + System.arraycopy(head.decls, 0, decls, 0, head.size()); + System.arraycopy(tail.decls, 0, decls, head.size(), tail.size()); + } + + /** + * Returns the number of decls in this Decls object. + * @return this.size + */ + public int size() { return decls.length; } + + /** + * Returns the ith declaration in this Decls sequence. + * @requires 0 <= i < this.size + * @return this.decls[i] + */ + public Decl get(int i) { return decls[i]; } + + /** + * Returns an unmodifiable iterator over the decls in this Decls object. + * @return an unmodifiable iterator over the decls in this Decls object. + */ + public Iterator iterator() { return Containers.iterate(decls); } + + /** + * Returns a sequence of this.size + other.size decls that has + * these decls as the prefix and the given decls as the suffix. + * @return {ds: Decls | ds.size = this.size + other.size && + * ds.decls = this.decls + + * {i: [this.size..this.size+other.size), d: Decl | d = other.decls[i-this.size] } + * @throws NullPointerException - decl = null + */ + public final Decls and(Decls other) { + return new Decls(this, other); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public D accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return Arrays.toString(decls); + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/ExprToIntCast.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/ExprToIntCast.java new file mode 100644 index 00000000..28e8a7ff --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/ExprToIntCast.java @@ -0,0 +1,94 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + + +import kodkod.ast.operator.ExprCastOperator; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + +/** + * An {@link kodkod.ast.IntExpression } representing the + * cardinality of an {@link kodkod.ast.Expression} or the + * sum of all the integer atoms contained in the expression. + * @specfield expression: Expression + * @specfield op: ExprCastOperator + * @invariant children = 0->expression + * @author Emina Torlak + */ +public final class ExprToIntCast extends IntExpression { + private final Expression expression; + private final ExprCastOperator op; + /** + * Constructs a new cardinality expression. + * + * @ensures this.expression' = expression && this.op' = op + * @throws NullPointerException - expression = null || op = null + * @throws IllegalArgumentException - op = SUM && child.arity != 1 + */ + ExprToIntCast(Expression child, ExprCastOperator op) { + if (child.arity()>1 && op==ExprCastOperator.SUM) + throw new IllegalArgumentException("cannot apply " + op + " to " + child); + this.expression = child; + this.op = op; + } + + /** + * Returns this.expression. + * @return this.expression + */ + public Expression expression() {return expression;} + + /** + * Returns this.op. + * @return this.op + */ + public ExprCastOperator op() { return op; } + + + /** + * {@inheritDoc} + * @see kodkod.ast.IntExpression#accept(kodkod.ast.visitor.ReturnVisitor) + */ + @Override + public I accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.IntExpression#accept(kodkod.ast.visitor.VoidVisitor) + */ + @Override + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return op + "("+expression.toString()+")"; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Expression.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Expression.java new file mode 100644 index 00000000..d2728b8c --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Expression.java @@ -0,0 +1,413 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + +import static kodkod.ast.operator.ExprCastOperator.CARDINALITY; +import static kodkod.ast.operator.ExprCastOperator.SUM; +import static kodkod.ast.operator.ExprCompOperator.EQUALS; +import static kodkod.ast.operator.ExprCompOperator.SUBSET; +import static kodkod.ast.operator.ExprOperator.CLOSURE; +import static kodkod.ast.operator.ExprOperator.DIFFERENCE; +import static kodkod.ast.operator.ExprOperator.INTERSECTION; +import static kodkod.ast.operator.ExprOperator.JOIN; +import static kodkod.ast.operator.ExprOperator.OVERRIDE; +import static kodkod.ast.operator.ExprOperator.PRODUCT; +import static kodkod.ast.operator.ExprOperator.REFLEXIVE_CLOSURE; +import static kodkod.ast.operator.ExprOperator.TRANSPOSE; +import static kodkod.ast.operator.ExprOperator.UNION; +import static kodkod.ast.operator.Multiplicity.LONE; +import static kodkod.ast.operator.Multiplicity.NO; +import static kodkod.ast.operator.Multiplicity.ONE; +import static kodkod.ast.operator.Multiplicity.SOME; + + +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; + +import kodkod.ast.operator.ExprCastOperator; +import kodkod.ast.operator.ExprCompOperator; +import kodkod.ast.operator.ExprOperator; +import kodkod.ast.operator.Multiplicity; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.util.collections.Containers; + +/** + * A relational expression. Unless otherwise noted, + * all methods in this class throw a NullPointerException when given + * null arguments. + * + * @specfield arity: int + * @invariant arity > 0 + * + * @author Emina Torlak + */ +public abstract class Expression extends Node { + + /** The universal relation: contains all atoms in a {@link kodkod.instance.Universe universe of discourse}. */ + public static final Expression UNIV = new ConstantExpression("univ", 1); + + /** The identity relation: maps all atoms in a {@link kodkod.instance.Universe universe of discourse} to themselves. */ + public static final Expression IDEN = new ConstantExpression("iden", 2); + + /** The empty relation: contains no atoms. */ + public static final Expression NONE = new ConstantExpression("none", 1); + + /** The integer relation: contains all atoms {@link kodkod.instance.Bounds bound} to integers */ + public static final Expression INTS = new ConstantExpression("ints", 1); + + /** + * Constructs a leaf expression + * @ensures no this.children' + */ + Expression() { } + + /** + * Returns the join of this and the specified expression. The effect + * of this method is the same as calling this.compose(JOIN, expr). + * @return this.compose(JOIN, expr) + */ + public final Expression join(Expression expr) { + return compose(JOIN,expr); + } + + /** + * Returns the product of this and the specified expression. The effect + * of this method is the same as calling this.compose(PRODUCT, expr). + * @return this.compose(PRODUCT, expr) + */ + public final Expression product(Expression expr) { + return compose(PRODUCT,expr); + } + + /** + * Returns the union of this and the specified expression. The effect + * of this method is the same as calling this.compose(UNION, expr). + * @return this.compose(UNION, expr) + */ + public final Expression union(Expression expr) { + return compose(UNION,expr); + } + + /** + * Returns the difference of this and the specified expression. The effect + * of this method is the same as calling this.compose(DIFFERENCE, expr). + * @return this.compose(DIFFERENCE, expr) + */ + public final Expression difference(Expression expr) { + return compose(DIFFERENCE,expr); + } + + /** + * Returns the intersection of this and the specified expression. The effect + * of this method is the same as calling this.compose(INTERSECTION, expr). + * @return this.compose(INTERSECTION, expr) + */ + public final Expression intersection(Expression expr) { + return compose(INTERSECTION,expr); + } + + /** + * Returns the relational override of this with the specified expression. The effect + * of this method is the same as calling this.compose(OVERRIDE, expr). + * @return this.compose(OVERRIDE, expr) + */ + public final Expression override(Expression expr) { + return compose(OVERRIDE,expr); + } + + /** + * Returns the composition of this and the specified expression, using the + * given binary operator. + * @requires op in ExprOperator.BINARY + * @return {e: Expression | e.left = this and e.right = expr and e.op = this } + */ + public final Expression compose(ExprOperator op, Expression expr) { + return new BinaryExpression(this, op, expr); + } + + /** + * Returns the union of the given expressions. The effect of this method is the + * same as calling compose(UNION, exprs). + * @return compose(UNION, exprs) + */ + public static Expression union(Expression...exprs) { + return compose(UNION, exprs); + } + + /** + * Returns the union of the given expressions. The effect of this method is the + * same as calling compose(UNION, exprs). + * @return compose(UNION, exprs) + */ + public static Expression union(Collection exprs) { + return compose(UNION, exprs); + } + + /** + * Returns the intersection of the given expressions. The effect of this method is the + * same as calling compose(INTERSECTION, exprs). + * @return compose(INTERSECTION, exprs) + */ + public static Expression intersection(Expression...exprs) { + return compose(INTERSECTION, exprs); + } + + /** + * Returns the intersection of the given expressions. The effect of this method is the + * same as calling compose(INTERSECTION, exprs). + * @return compose(INTERSECTION, exprs) + */ + public static Expression intersection(Collection exprs) { + return compose(INTERSECTION, exprs); + } + + /** + * Returns the product of the given expressions. The effect of this method is the + * same as calling compose(PRODUCT, exprs). + * @return compose(PRODUCT, exprs) + */ + public static Expression product(Expression...exprs) { + return compose(PRODUCT, exprs); + } + + /** + * Returns the product of the given expressions. The effect of this method is the + * same as calling compose(PRODUCT, exprs). + * @return compose(PRODUCT, exprs) + */ + public static Expression product(Collection exprs) { + return compose(PRODUCT, exprs); + } + + /** + * Returns the override of the given expressions. The effect of this method is the + * same as calling compose(OVERRIDE, exprs). + * @return compose(OVERRIDE, exprs) + */ + public static Expression override(Expression...exprs) { + return compose(OVERRIDE, exprs); + } + + /** + * Returns the override of the given expressions. The effect of this method is the + * same as calling compose(OVERRIDE, exprs). + * @return compose(OVERRIDE, exprs) + */ + public static Expression override(Collection exprs) { + return compose(OVERRIDE, exprs); + } + + /** + * Returns the composition of the given expressions using the given operator. + * @requires exprs.length = 2 => op.binary(), exprs.length > 2 => op.nary() + * @return exprs.length=1 => exprs[0] else {e: Expression | e.children = exprs and e.op = this } + */ + public static Expression compose(ExprOperator op, Expression...exprs) { + switch(exprs.length) { + case 0 : throw new IllegalArgumentException("Expected at least one argument: " + Arrays.toString(exprs)); + case 1 : return exprs[0]; + case 2 : return new BinaryExpression(exprs[0], op, exprs[1]); + default : return new NaryExpression(op, Containers.copy(exprs, new Expression[exprs.length])); + } + } + + /** + * Returns the composition of the given expressions using the given operator. + * @requires exprs.size() = 2 => op.binary(), exprs.size() > 2 => op.nary() + * @return exprs.size()=1 => exprs.iterator().next() else {e: Expression | e.children = exprs.toArray() and e.op = this } + */ + public static Expression compose(ExprOperator op, Collection exprs) { + switch(exprs.size()) { + case 0 : throw new IllegalArgumentException("Expected at least one argument: " + exprs); + case 1 : return exprs.iterator().next(); + case 2 : + final Iterator itr = exprs.iterator(); + return new BinaryExpression(itr.next(), op, itr.next()); + default : + return new NaryExpression(op, exprs.toArray(new Expression[exprs.size()])); + } + } + + + + /** + * Returns the transpose of this. The effect of this method is the same + * as calling this.apply(TRANSPOSE). + * @return this.apply(TRANSPOSE) + */ + public final Expression transpose() { + return apply(TRANSPOSE); + } + + /** + * Returns the transitive closure of this. The effect of this method is the same + * as calling this.apply(CLOSURE). + * @return this.apply(CLOSURE) + */ + public final Expression closure() { + return apply(CLOSURE); + } + + /** + * Returns the reflexive transitive closure of this. The effect of this + * method is the same + * as calling this.apply(REFLEXIVE_CLOSURE). + * @return this.apply(REFLEXIVE_CLOSURE) + */ + public final Expression reflexiveClosure() { + return apply(REFLEXIVE_CLOSURE); + } + + /** + * Returns the expression that results from applying the given unary operator + * to this. + * @requires op.unary() + * @return {e: Expression | e.expression = this && e.op = this } + * @throws IllegalArgumentException - this.arity != 2 + */ + public final Expression apply(ExprOperator op) { + return new UnaryExpression(op, this); + } + + /** + * Returns the projection of this expression onto the specified columns. + * @return {e: Expression | e = project(this, columns) } + * @throws IllegalArgumentException - columns.length < 1 + */ + public final Expression project(IntExpression... columns) { + return new ProjectExpression(this, columns); + } + + /** + * Returns the cardinality of this expression. The effect of this method is the + * same as calling this.apply(CARDINALITY). + * @return this.apply(CARDINALITY) + */ + public final IntExpression count() { + return apply(CARDINALITY); + } + + /** + * Returns the sum of the integer atoms in this expression. The effect of this method is the + * same as calling this.apply(SUM). + * @return this.apply(SUM) + */ + public final IntExpression sum() { + return apply(SUM); + } + + /** + * Returns the cast of this expression to an integer expression, + * that represents either the cardinality of this expression (if op is CARDINALITY) + * or the sum of the integer atoms it contains (if op is SUM). + * @return {e: IntExpression | e.op = op && e.expression = this} + */ + public final IntExpression apply(ExprCastOperator op) { + return new ExprToIntCast(this, op); + } + + /** + * Returns the formula 'this = expr'. The effect of this method is the same + * as calling this.compare(EQUALS, expr). + * @return this.compare(EQUALS, expr) + */ + public final Formula eq(Expression expr) { + return compare(EQUALS, expr); + } + + /** + * Returns the formula 'this in expr'. The effect of this method is the same + * as calling this.compare(SUBSET, expr). + * @return this.compare(SUBSET, expr) + */ + public final Formula in(Expression expr) { + return compare(SUBSET, expr); + } + + /** + * Returns the formula that represents the comparison of this and the + * given expression using the given comparison operator. + * @return {f: Formula | f.left = this && f.right = expr && f.op = op} + */ + public final Formula compare(ExprCompOperator op, Expression expr) { + return new ComparisonFormula(this, op, expr); + } + + /** + * Returns the formula 'some this'. The effect of this method is the same as calling + * this.apply(SOME). + * @return this.apply(SOME) + */ + public final Formula some() { + return apply(SOME); + } + + /** + * Returns the formula 'no this'. The effect of this method is the same as calling + * this.apply(NO). + * @return this.apply(NO) + */ + public final Formula no() { + return apply(NO); + } + + /** + * Returns the formula 'one this'. The effect of this method is the same as calling + * this.apply(ONE). + * @return this.apply(ONE) + */ + public final Formula one() { + return apply(ONE); + } + + /** + * Returns the formula 'lone this'. The effect of this method is the same as calling + * this.apply(LONE). + * @return this.apply(LONE) + */ + public final Formula lone() { + return apply(LONE); + } + + /** + * Returns the formula that results from applying the specified multiplicity to + * this expression. The SET multiplicity is not allowed. + * @return {f: Formula | f.multiplicity = mult && f.expression = this} + * @throws IllegalArgumentException - mult = SET + */ + public final Formula apply(Multiplicity mult) { + return new MultiplicityFormula(mult, this); + } + + /** + * Returns the arity of this expression. + * @return this.arity + */ + public abstract int arity(); + + /** + * Accepts the given visitor and returns the result. + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public abstract E accept(ReturnVisitor visitor); + } diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Formula.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Formula.java new file mode 100644 index 00000000..ad6603e2 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Formula.java @@ -0,0 +1,265 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + +import static kodkod.ast.operator.FormulaOperator.AND; +import static kodkod.ast.operator.FormulaOperator.IFF; +import static kodkod.ast.operator.FormulaOperator.IMPLIES; +import static kodkod.ast.operator.FormulaOperator.OR; +import static kodkod.ast.operator.Quantifier.ALL; +import static kodkod.ast.operator.Quantifier.SOME; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; + +import kodkod.ast.operator.FormulaOperator; +import kodkod.ast.operator.Quantifier; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.util.collections.Containers; + +/** + * A first-order formula. Unless otherwise noted, + * all methods in this class throw a NullPointerException when given + * null arguments. + * @author Emina Torlak + */ +public abstract class Formula extends Node { + + /** Constant formula true */ + public static final Formula TRUE = new ConstantFormula(true) {}; + + /** Constant formula false */ + public static final Formula FALSE = new ConstantFormula(false) {}; + + Formula() {} + + /** + * Returns the constant formula with the given value. + * @return value ? TRUE : FALSE + */ + public static Formula constant(boolean value) { return value ? TRUE : FALSE; } + + /** + * Returns the conjunction of this and the specified formula. The effect + * of this method is the same as calling this.compose(AND, formula). + * @return this.compose(AND, formula) + */ + public final Formula and(Formula formula) { + return compose(AND,formula); + } + + /** + * Returns the conjunction of this and the specified formula. The effect + * of this method is the same as calling this.compose(OR, formula). + * @return this.compose(OR, formula) + */ + public final Formula or(Formula formula) { + return compose(OR,formula); + } + + /** + * Returns a formula that equates this and the specified formula. The effect + * of this method is the same as calling this.compose(IFF, formula). + * @return this.compose(IFF, formula) + */ + public final Formula iff(Formula formula) { + return compose(IFF,formula); + } + + /** + * Returns the implication of the specified formula by this. The effect + * of this method is the same as calling this.compose(IMPLIES, formula). + * @return this.compose(IMPLIES, formula) + */ + public final Formula implies(Formula formula) { + return compose(IMPLIES,formula); + } + + + /** + * Returns the composition of this and the specified formula using the + * given binary operator. + * @return {f: Formula | f.left = this and f.right = formula and f.op = op } + */ + public final Formula compose(FormulaOperator op, Formula formula) { + return new BinaryFormula(this, op, formula); + } + + /** + * Returns the conjunction of the given formulas. The effect of this method is the + * same as calling compose(AND, formulas). + * @return compose(AND, formulas) + */ + public static Formula and(Formula...formulas) { + return compose(AND, formulas); + } + + /** + * Returns the conjunction of the given formulas. The effect of this method is the + * same as calling compose(AND, formulas). + * @return compose(AND, formulas) + */ + public static Formula and(Collection formulas) { + return compose(AND, formulas); + } + + /** + * Returns the disjunction of the given formulas. The effect of this method is the + * same as calling compose(OR, formulas). + * @return compose(OR, formulas) + */ + public static Formula or(Formula...formulas) { + return compose(OR, formulas); + } + + /** + * Returns the disjunction of the given formulas. The effect of this method is the + * same as calling compose(OR, formulas). + * @return compose(OR, formulas) + */ + public static Formula or(Collection formulas) { + return compose(OR, formulas); + } + + /** + * Returns the composition of the given formulas using the given operator. + * @requires formulas.length != 2 => op.nary() + * @return + *
 
+     *  formulas.length = 0 => constant(op=AND) else
+     * 	formulas.length=1 => formulas[0] else 
+     *  {e: Formula | e.children = formulas and e.op = this }
+     * 
+ */ + public static Formula compose(FormulaOperator op, Formula...formulas) { + switch(formulas.length) { + case 0 : + switch(op) { + case AND : return TRUE; + case OR : return FALSE; + default : throw new IllegalArgumentException("Expected at least one argument: " + Arrays.toString(formulas)); + } + case 1 : return formulas[0]; + case 2 : return new BinaryFormula(formulas[0], op, formulas[1]); + default : return new NaryFormula(op, Containers.copy(formulas, new Formula[formulas.length])); + } + } + + /** + * Returns the composition of the given formulas using the given operator. + * @requires formulas.size() != 2 => op.nary() + * @return + *
 
+     *  formulas.size() = 0 => constant(op=AND) else
+     *  formulas.size() = 1 => formulas.iterator().next() else 
+     *  {e: Formula | e.children = formulas.toArray() and e.op = this }
+     * 
+ */ + public static Formula compose(FormulaOperator op, Collection formulas) { + switch(formulas.size()) { + case 0 : + switch(op) { + case AND : return TRUE; + case OR : return FALSE; + default : throw new IllegalArgumentException("Expected at least one argument: " + formulas); + } + case 1 : return formulas.iterator().next(); + case 2 : + final Iterator itr = formulas.iterator(); + return new BinaryFormula(itr.next(), op, itr.next()); + default : + return new NaryFormula(op, formulas.toArray(new Formula[formulas.size()])); + } + } + + /** + * Returns a formula that represents a universal quantification of this + * formula over the given declarations. The effect of this method is the same + * as calling this.quantify(ALL, decls). + * @return this.quantify(ALL, decls) + */ + public final Formula forAll(Decls decls) { + return quantify(ALL, decls); + } + + /** + * Returns a formula that represents an existential quantification of this + * formula over the given declarations. The effect of this method is the same + * as calling this.quantify(SOME, decls). + * @return this.quantify(SOME, decls) + */ + public final Formula forSome(Decls decls) { + return quantify(SOME, decls); + } + + /** + * Returns a quantification of this formula using the given quantifier over + * the specified declarations. + * @return {f: Formula | f.decls = decls and f.formula = this and f.quantifier = quantifer } + */ + public final Formula quantify(Quantifier quantifier, Decls decls) { + return new QuantifiedFormula(quantifier, decls, this); + } + + /** + * Returns the comprehension expression constructed from this formula and + * the given declarations. + * @requires all d: decls.decls[int] | decl.variable.arity = 1 and decl.multiplicity = ONE + * @return {e: Expression | e.decls = decls and e.formula = this } + */ + public final Expression comprehension(Decls decls) { + return new Comprehension(decls,this); + } + + /** + * Returns the if expression constructed from this formula and the + * specified then and else expressions. + * @return {e: Expression | e.condition = this and e.thenExpr = thenExpr and e.elseExpr = elseExpr} + */ + public final Expression thenElse(Expression thenExpr, Expression elseExpr) { + return new IfExpression(this, thenExpr, elseExpr); + } + + /** + * Returns the if expression constructed from this formula and the + * specified then and else integer expressions. + * @return {e: IntExpression | e.condition = this and e.thenExpr = thenExpr and e.elseExpr = elseExpr} + */ + public final IntExpression thenElse(IntExpression thenExpr, IntExpression elseExpr) { + return new IfIntExpression(this, thenExpr, elseExpr); + } + + /** + * Returns the negation of this formula. + * @return {f : NotFormula | f.formula = this } + */ + public final Formula not() { + return new NotFormula(this); + } + + /** + * Accepts the given visitor and returns the result. + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public abstract F accept(ReturnVisitor visitor); +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/IfExpression.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/IfExpression.java new file mode 100644 index 00000000..72087b71 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/IfExpression.java @@ -0,0 +1,118 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + + +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + + +/** + * An expression whose value depends on the truth of a given condition. + * + * @specfield condition: Formula + * @specfield thenExpr: Expression + * @specfield elseExpr: Expression + * @invariant children = 0->condition + 1->thenExpr + 2->elseExpr + * @author Greg Dennis (gdennis@mit.edu) + * @author Emina Torlak + */ +public final class IfExpression extends Expression { + + private final Formula condition; + private final Expression thenExpr, elseExpr; + private final int arity; + + /** + * @ensures this.condition' = condition && this.thenExpr' = thenExpr && + * this.elseExpr' = elseExpr + * @throws IllegalArgumentException - thenExpr.arity != elseExpr.arity + */ + IfExpression(Formula condition, Expression thenExpr, Expression elseExpr) { + if (thenExpr.arity() != elseExpr.arity()) { + throw new IllegalArgumentException("Arity mismatch: " + + thenExpr + "::" + thenExpr.arity() + " and " + + elseExpr + "::" + elseExpr.arity()); + } + this.condition = condition; + this.thenExpr = thenExpr; + this.elseExpr = elseExpr; + this.arity = thenExpr.arity(); + } + + /** + * Returns the if-condition. + * @return this.condition + */ + public Formula condition() { + return condition; + } + + /** + * Returns the then-expression. + * @return this.thenExpr + */ + public Expression thenExpr() { + return thenExpr; + } + + /** + * Returns the else-expression. + * @return this.elseExpr + */ + public Expression elseExpr() { + return elseExpr; + } + + /** + * Returns the arity of this. + * @return this.arity + */ + @Override + public int arity() { + return arity; + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Expression#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public E accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ public String toString() { + return "(if " + condition + " then " + thenExpr + " else " + elseExpr + ")"; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/IfIntExpression.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/IfIntExpression.java new file mode 100644 index 00000000..9afba634 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/IfIntExpression.java @@ -0,0 +1,101 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + +/** + * An int expression whose value depends on the truth of a condition. + * + * @specfield condition: Formula + * @specfield thenExpr: IntExpression + * @specfield elseExpr: IntExpression + * @invariant children = 0->condition + 1->thenExpr + 2->elseExpr + * @author Emina Torlak + */ +public final class IfIntExpression extends IntExpression { + private final Formula condition; + private final IntExpression thenExpr, elseExpr; + + /** + * @ensures this.condition' = condition && this.thenExpr' = thenExpr && + * this.elseExpr' = elseExpr + */ + IfIntExpression(Formula condition, IntExpression thenExpr, + IntExpression elseExpr) { + this.condition = condition; + this.thenExpr = thenExpr; + this.elseExpr = elseExpr; + } + + /** + * Returns the if-condition. + * @return this.condition + */ + public Formula condition() { + return condition; + } + + /** + * Returns the then-expression. + * @return this.thenExpr + */ + public IntExpression thenExpr() { + return thenExpr; + } + + /** + * Returns the else-expression. + * @return this.elseExpr + */ + public IntExpression elseExpr() { + return elseExpr; + } + + /** + * {@inheritDoc} + * @see kodkod.ast.IntExpression#accept(kodkod.ast.visitor.ReturnVisitor) + */ + @Override + public I accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.IntExpression#accept(kodkod.ast.visitor.VoidVisitor) + */ + @Override + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return "(if " + condition + " then " + thenExpr + " else " + elseExpr + ")"; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/IntComparisonFormula.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/IntComparisonFormula.java new file mode 100644 index 00000000..1154c3f9 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/IntComparisonFormula.java @@ -0,0 +1,97 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + + + +import kodkod.ast.operator.IntCompOperator; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + +/** + * An integer comparison formula, e.g. x = y, x <= y, etc. + * + * @specfield left: IntExpression + * @specfield right: IntExpression + * @specfield op: IntCompOperator + * @invariant children = 0->left + 1->right + * @author Emina Torlak + */ +public final class IntComparisonFormula extends Formula { + private final IntCompOperator op; + private final IntExpression left, right; + + /** + * Constructs a new int comparison formula: left op right + * + * @ensures this.left' = left && this.right' = right && this.op' = op + * @throws NullPointerException - left = null || right = null || op = null + */ + IntComparisonFormula(final IntExpression left, final IntCompOperator op, final IntExpression right) { + this.left = left; + this.right = right; + this.op = op; + } + + /** + * Returns the left child of this. + * @return this.left + */ + public IntExpression left() {return left;} + + /** + * Returns the right child of this. + * @return this.right + */ + public IntExpression right() {return right;} + + /** + * Returns the operator of this. + * @return this.op + */ + public IntCompOperator op() {return op;} + + /** + * {@inheritDoc} + * @see kodkod.ast.Formula#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public F accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return "(" + left + " " + op + " " + right + ")"; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/IntConstant.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/IntConstant.java new file mode 100644 index 00000000..9bd365c4 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/IntConstant.java @@ -0,0 +1,108 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + + +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + +/** + * An integer constant (literal). + * @specfield value: int + * @invariant no children + * @author Emina Torlak + */ +public final class IntConstant extends IntExpression { + private final int value; + + /** + * Constructs an int constant. + * @ensures this.value' = value + */ + private IntConstant(int value) { + this.value = value; + } + + /** + * Returns an IntConstant corresponding to the given value. + * @return {c: IntConstant | c.value = value} + */ + public static IntConstant constant(int value) { + return new IntConstant(value); + } + + /** + * Returns this.value. + * @return this.value + */ + public int value() { + return value; + } + + /** + * Return true if o is an IntConstant with the same value as this. + * @return o in IntConstant && o.value = this.value + */ + public boolean equals(Object o) { + if (o==this) + return true; + else if (o instanceof IntConstant) + return value==((IntConstant) o).value; + else + return false; + } + + /** + * Return this.value + * @return this.value + */ + public int hashCode() { + return value; + } + + /** + * {@inheritDoc} + * @see kodkod.ast.IntExpression#accept(kodkod.ast.visitor.ReturnVisitor) + */ + @Override + public I accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.IntExpression#accept(kodkod.ast.visitor.VoidVisitor) + */ + @Override + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return String.valueOf(value); + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/IntExpression.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/IntExpression.java new file mode 100644 index 00000000..92e49d8e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/IntExpression.java @@ -0,0 +1,462 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + +import static kodkod.ast.operator.IntCastOperator.BITSETCAST; +import static kodkod.ast.operator.IntCastOperator.INTCAST; +import static kodkod.ast.operator.IntCompOperator.EQ; +import static kodkod.ast.operator.IntCompOperator.NEQ; +import static kodkod.ast.operator.IntCompOperator.GT; +import static kodkod.ast.operator.IntCompOperator.GTE; +import static kodkod.ast.operator.IntCompOperator.LT; +import static kodkod.ast.operator.IntCompOperator.LTE; +import static kodkod.ast.operator.IntOperator.ABS; +import static kodkod.ast.operator.IntOperator.AND; +import static kodkod.ast.operator.IntOperator.DIVIDE; +import static kodkod.ast.operator.IntOperator.MINUS; +import static kodkod.ast.operator.IntOperator.MODULO; +import static kodkod.ast.operator.IntOperator.MULTIPLY; +import static kodkod.ast.operator.IntOperator.NEG; +import static kodkod.ast.operator.IntOperator.NOT; +import static kodkod.ast.operator.IntOperator.OR; +import static kodkod.ast.operator.IntOperator.PLUS; +import static kodkod.ast.operator.IntOperator.SGN; +import static kodkod.ast.operator.IntOperator.SHA; +import static kodkod.ast.operator.IntOperator.SHL; +import static kodkod.ast.operator.IntOperator.SHR; +import static kodkod.ast.operator.IntOperator.XOR; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; + +import kodkod.ast.operator.IntCastOperator; +import kodkod.ast.operator.IntCompOperator; +import kodkod.ast.operator.IntOperator; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; +import kodkod.util.collections.Containers; + +/** + * A Node whose value is an integer + * rather than a relational expression. + * + * @author Emina Torlak + */ +public abstract class IntExpression extends Node { + + /** + * Constructs an IntExpression. + */ + IntExpression() {} + + /** + * Returns a formula stating that the given int expression and + * this have the same value. The effect + * of this method is the same as calling this.compare(EQ, intExpr). + * @return this.compare(EQ, intExpr) + */ + public final Formula eq(IntExpression intExpr) { + return this.compare(EQ, intExpr); + } + + public final Formula neq(IntExpression intExpr) { + return this.compare(NEQ, intExpr); + } + + /** + * Returns a formula stating that the value of this int expression is less than the + * value of the given int expression The effect + * of this method is the same as calling this.compare(LT, intExpr). + * @return this.compare(LT, intExpr) + */ + public final Formula lt(IntExpression intExpr) { + return this.compare(LT, intExpr); + } + + /** + * Returns a formula stating that the value of this int expression is less than + * or equal to the value of the given int expression The effect + * of this method is the same as calling this.compare(LTE, intExpr). + * @return this.compare(LTE, intExpr) + */ + public final Formula lte(IntExpression intExpr) { + return this.compare(LTE, intExpr); + } + + /** + * Returns a formula stating that the value of this int expression is greater than the + * value of the given int expression The effect + * of this method is the same as calling this.compare(GT, intExpr). + * @return this.compare(GT, intExpr) + */ + public final Formula gt(IntExpression intExpr) { + return this.compare(GT, intExpr); + } + + /** + * Returns a formula stating that the value of this int expression is greater than + * or equal to the value of the given int expression The effect + * of this method is the same as calling this.compare(GTE, intExpr). + * @return this.compare(GTE, intExpr) + */ + public final Formula gte(IntExpression intExpr) { + return this.compare(GTE, intExpr); + } + + /** + * Returns a formula comparing this and the given integer expression using the + * specified operator. + * @return {f: Formula | f.left = this and f.right = intExpr and f.op = op } + */ + public Formula compare(IntCompOperator op, IntExpression intExpr) { + if (op==null || intExpr==null) + throw new NullPointerException(); + return new IntComparisonFormula(this, op, intExpr); + } + + /** + * Returns an integer expression that is the sum of all + * values that this integer expression can take given the + * provided declarations. + * @return {e: IntExpression | e.decls = decls and e.intExpr = this } + */ + public final IntExpression sum(Decls decls) { + return new SumExpression(decls, this); + } + + /** + * Returns an IntExpression that represents the sum of this and + * the given int node. The effect of this method is the same as calling + * this.compose(PLUS, intExpr). + * @return this.compose(PLUS, intExpr) + */ + public final IntExpression plus(IntExpression intExpr) { + return compose(PLUS, intExpr); + } + + /** + * Returns an IntExpression that represents the difference between this and + * the given int node. The effect of this method is the same as calling + * this.compose(MINUS, intExpr). + * @return this.compose(MINUS, intExpr) + */ + public final IntExpression minus(IntExpression intExpr) { + return compose(MINUS, intExpr); + } + + /** + * Returns an IntExpression that represents the product of this and + * the given int node. The effect of this method is the same as calling + * this.compose(MULTIPLY, intExpr). + * @return this.compose(MULTIPLY, intExpr) + */ + public final IntExpression multiply(IntExpression intExpr) { + return compose(MULTIPLY, intExpr); + } + + /** + * Returns an IntExpression that represents the quotient of the division + * between this and the given int node. The effect of this method is the same as calling + * this.compose(DIVIDE, intExpr). + * @return this.compose(DIVIDE, intExpr) + */ + public final IntExpression divide(IntExpression intExpr) { + return compose(DIVIDE, intExpr); + } + + /** + * Returns an IntExpression that represents the remainder of the division + * between this and the given int node. The effect of this method is the same as calling + * this.compose(MODULO, intExpr). + * @return this.compose(MODULO, intExpr) + */ + public final IntExpression modulo(IntExpression intExpr) { + return compose(MODULO, intExpr); + } + + /** + * Returns an IntExpression that represents the bitwise AND of this and + * the given int node. The effect of this method is the same as calling + * this.compose(AND, intExpr). + * @return this.compose(AND, intExpr) + */ + public final IntExpression and(IntExpression intExpr) { + return compose(AND, intExpr); + } + + /** + * Returns an IntExpression that represents the bitwise OR of this and + * the given int node. The effect of this method is the same as calling + * this.compose(OR, intExpr). + * @return this.compose(OR, intExpr) + */ + public final IntExpression or(IntExpression intExpr) { + return compose(OR, intExpr); + } + + /** + * Returns an IntExpression that represents the bitwise XOR of this and + * the given int node. The effect of this method is the same as calling + * this.compose(XOR, intExpr). + * @return this.compose(XOR, intExpr) + */ + public final IntExpression xor(IntExpression intExpr) { + return compose(XOR, intExpr); + } + + /** + * Returns an IntExpression that represents the left shift of this by + * the given int node. The effect of this method is the same as calling + * this.compose(SHL, intExpr). + * @return this.compose(SHL, intExpr) + */ + public final IntExpression shl(IntExpression intExpr) { + return compose(SHL, intExpr); + } + + /** + * Returns an IntExpression that represents the right shift of this and + * the given int node, with zero extension. The effect of this method is the same as calling + * this.compose(SHR, intExpr). + * @return this.compose(SHR, intExpr) + */ + public final IntExpression shr(IntExpression intExpr) { + return compose(SHR, intExpr); + } + + /** + * Returns an IntExpression that represents the right shift of this and + * the given int node, with sign extension. The effect of this method is the same as calling + * this.compose(SHA, intExpr). + * @return this.compose(SHA, intExpr) + */ + public final IntExpression sha(IntExpression intExpr) { + return compose(SHA, intExpr); + } + + /** + * Returns an expression that combines this and the given integer expression using the + * specified operator. + * @requires op.binary() + * @return {e: IntExpression | e.left = this and e.right = intExpr and e.op = op } + */ + public final IntExpression compose(IntOperator op, IntExpression intExpr) { + if (op==null || intExpr==null) + throw new NullPointerException(); + return new BinaryIntExpression(this, op, intExpr); + } + + /** + * Returns the sum of the given int expressions. The effect of this method is the + * same as calling compose(PLUS, intExprs). + * @return compose(PLUS, intExprs) + */ + public static IntExpression plus(IntExpression...intExprs) { + return compose(PLUS, intExprs); + } + + /** + * Returns the plus of the given int expressions. The effect of this method is the + * same as calling compose(PLUS, intExprs). + * @return compose(PLUS, intExprs) + */ + public static IntExpression plus(Collection intExprs) { + return compose(PLUS, intExprs); + } + + /** + * Returns the product of the given int expressions. The effect of this method is the + * same as calling compose(MULTIPLY, intExprs). + * @return compose(MULTIPLY, intExprs) + */ + public static IntExpression multiply(IntExpression...intExprs) { + return compose(MULTIPLY, intExprs); + } + + /** + * Returns the product of the given int expressions. The effect of this method is the + * same as calling compose(MULTIPLY, intExprs). + * @return compose(MULTIPLY, intExprs) + */ + public static IntExpression multiply(Collection intExprs) { + return compose(MULTIPLY, intExprs); + } + + /** + * Returns the bitwise and of the given int expressions. The effect of this method is the + * same as calling compose(AND, intExprs). + * @return compose(AND, intExprs) + */ + public static IntExpression and(IntExpression...intExprs) { + return compose(AND, intExprs); + } + + /** + * Returns the bitwise and of the given int expressions. The effect of this method is the + * same as calling compose(AND, intExprs). + * @return compose(AND, intExprs) + */ + public static IntExpression and(Collection intExprs) { + return compose(AND, intExprs); + } + + /** + * Returns the bitwise or of the given int expressions. The effect of this method is the + * same as calling compose(OR, intExprs). + * @return compose(OR, intExprs) + */ + public static IntExpression or(IntExpression...intExprs) { + return compose(OR, intExprs); + } + + /** + * Returns the bitwise or of the given int expressions. The effect of this method is the + * same as calling compose(OR, intExprs). + * @return compose(OR, intExprs) + */ + public static IntExpression or(Collection intExprs) { + return compose(OR, intExprs); + } + + /** + * Returns the composition of the given int expressions using the given operator. + * @requires intExprs.length = 2 => op.binary(), intExprs.length > 2 => op.nary() + * @return intExprs.length=1 => intExprs[0] else {e: IntExpression | e.children = intExprs and e.op = this } + */ + public static IntExpression compose(IntOperator op, IntExpression...intExprs) { + switch(intExprs.length) { + case 0 : throw new IllegalArgumentException("Expected at least one argument: " + Arrays.toString(intExprs)); + case 1 : return intExprs[0]; + case 2 : return new BinaryIntExpression(intExprs[0], op, intExprs[1]); + default : + return new NaryIntExpression(op, Containers.copy(intExprs, new IntExpression[intExprs.length])); + } + } + + /** + * Returns the composition of the given int expressions using the given operator. + * @requires intExprs.length = 2 => op.binary(), intExprs.length > 2 => op.nary() + * @return intExprs.size() = 1 => intExprs.iterator().next() else {e: IntExpression | e.children = intExprs.toArray() and e.op = this } + */ + public static IntExpression compose(IntOperator op, Collection intExprs) { + switch(intExprs.size()) { + case 0 : throw new IllegalArgumentException("Expected at least one argument: " + intExprs); + case 1 : return intExprs.iterator().next(); + case 2 : + final Iterator itr = intExprs.iterator(); + return new BinaryIntExpression(itr.next(), op, itr.next()); + default : + return new NaryIntExpression(op, intExprs.toArray(new IntExpression[intExprs.size()])); + } + } + + /** + * Returns an IntExpression that represents the negation of this int expression. + * The effect of this method is the same as calling this.apply(NEG). + * @return this.apply(NEG) + */ + public final IntExpression negate() { + return apply(NEG); + } + + /** + * Returns an IntExpression that represents the bitwise negation of this int expression. + * The effect of this method is the same as calling this.apply(NOT). + * @return this.apply(NOT) + */ + public final IntExpression not() { + return apply(NOT); + } + + /** + * Returns an IntExpression that represents the absolute value of this int expression. + * The effect of this method is the same as calling this.apply(ABS). + * @return this.apply(ABS) + */ + public final IntExpression abs() { + return apply(ABS); + } + + /** + * Returns an IntExpression that represents the sign of this int expression. + * The effect of this method is the same as calling this.apply(SGN). + * @return this.apply(SGN) + */ + public final IntExpression signum() { + return apply(SGN); + } + + /** + * Returns an expression that represents the application of the given unary + * operator to this integer expression. + * @requires op.unary() + * @return {e: IntExpression | e.op = op and e.intExpr = this } + */ + public final IntExpression apply(IntOperator op) { + return new UnaryIntExpression(op, this); + } + + /** + * Returns an expression whose meaning is the singleton set containing the atom + * that represents the integer given by this integer expression. + * The effect of this method is the same as calling this.cast(INTCAST). + * @return this.cast(INTCAST) + */ + public final Expression toExpression() { + return cast(INTCAST); + } + + /** + * Returns an expression whose meaning is the set containing the atoms + * that represent the powers of 2 (bits) present in this integer expression. + * The effect of this method is the same as calling this.cast(BITSETCAST). + * @return this.cast(BITSETCAST) + */ + public final Expression toBitset() { + return cast(BITSETCAST); + } + + /** + * Returns an expression that is the relational representation of this + * integer expression specified by the given operator. + * @return an expression that is the relational representation of this + * integer expression specified by the given operator. + */ + public final Expression cast(IntCastOperator op) { + if (op==null) throw new NullPointerException(); + return new IntToExprCast(this, op); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public abstract I accept(ReturnVisitor visitor) ; + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public abstract void accept(VoidVisitor visitor); + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/IntToExprCast.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/IntToExprCast.java new file mode 100644 index 00000000..cf65d17a --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/IntToExprCast.java @@ -0,0 +1,101 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + +import kodkod.ast.operator.IntCastOperator; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + +/** + * Represents the conversion from an {@link kodkod.ast.IntExpression int expression } + * to an {@link kodkod.ast.Expression expression}. The meaning of the resulting + * expression is a singleton set containing the atom that represents the integer + * given by the wrapped int expression, if the conversion operator is INTCAST. + * Otherwise, the meaning is the set of powers of 2 that make up the given integer expression. + * @specfield intExpr: IntExpression + * @specfield op: IntCastOperator + * @invariant children = 0->intExpr + * @invariant arity = 1 + * @author Emina Torlak + */ +public final class IntToExprCast extends Expression { + private final IntExpression intExpr; + private final IntCastOperator op; + /** + * Constructs a new IntToExprCast. + * @requires intExpr != null && op != null + * @ensures this.intexpr' = intExpr + */ + IntToExprCast(IntExpression intExpr, IntCastOperator op) { + this.intExpr = intExpr; + this.op = op; + } + + /** + * Returns 1. + * @return 1 + */ + @Override + public int arity() { + return 1; + } + + /** + * Returns this.intExpr. + * @return this.intExpr + */ + public IntExpression intExpr() { + return intExpr; + } + + /** + * Returns this.op + * @return this.op + */ + public final IntCastOperator op() { + return op; + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Expression#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public E accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ public String toString() { + return op + "[" + intExpr + "]"; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/LeafExpression.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/LeafExpression.java new file mode 100644 index 00000000..539df1a1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/LeafExpression.java @@ -0,0 +1,82 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + +/** + * An expression with no children. + * {@link kodkod.ast.Relation Relation} and {@link kodkod.ast.Variable Variable} + * are examples of leaf exressions. Two leaf expressions are equal + * if and only if they refer to the same object. That is, + * leaf1.eauls(leaf2) <=> leaf1 == leaf2. A leaf has a name, which is + * basically a comment for the purpose of printing, viewing, etc. The name + * has no meaning otherwise. + * + * @specfield name: String + * @specfield arity: int + * @specfield no children + * @author Emina Torlak + */ +public abstract class LeafExpression extends Expression { + + private final int arity; + private final String name; + + /** + * Constructs a leaf with the specified name and arity + * + * @ensures this.name' = name && this.arity' = arity + * @throws IllegalArgumentException - arity < 1 + */ + LeafExpression(String name, int arity) { + if (arity < 1) { + throw new IllegalArgumentException("Arity must be at least 1: " + arity); + } + this.name = name; + this.arity = arity; + } + + + /** + * Returns the arity of this leaf. + * @return this.arity + */ + public final int arity() { + return arity; + } + + /** + * Returns the name of this leaf. + * @return this.name + */ + public final String name() { + return name; + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return name; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/MultiplicityFormula.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/MultiplicityFormula.java new file mode 100644 index 00000000..ba0e6ed7 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/MultiplicityFormula.java @@ -0,0 +1,91 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + + +import kodkod.ast.operator.Multiplicity; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + + +/** + * A multiplicity formula, e.g. some x + * + * @specfield expression: Expression + * @specfield multiplicity: (ONE + LONE + SOME + NO) + * @invariant children = 0->expression + * @author Emina Torlak + */ +public final class MultiplicityFormula extends Formula { + private final Expression expression; + private final Multiplicity multiplicity; + + /** + * Constructs a new multiplicity formula: multiplicity expression + * + * @ensures this.expression' = expression && this.multiplicity' = multiplicity + * @throws NullPointerException - multiplicity = null || expression = null + * @throws IllegalArgumentException - multiplicity = SET + */ + MultiplicityFormula(Multiplicity multiplicity, Expression expression) { + if (multiplicity==Multiplicity.SET) throw new IllegalArgumentException("invalid expression mulitplicity: SET"); + if (multiplicity== null || expression == null) throw new NullPointerException("null arg"); + this.multiplicity = multiplicity; + this.expression = expression; + } + + /** + * Returns the mulitplicity of this. + * @return this.multiplicity + */ + public Multiplicity multiplicity() { return multiplicity; } + + /** + * Returns the expression of this. + * @return this.expression + */ + public Expression expression() { return expression; } + + /** + * {@inheritDoc} + * @see kodkod.ast.Formula#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public F accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return multiplicity + " " + expression; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/NaryExpression.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/NaryExpression.java new file mode 100644 index 00000000..fee17a89 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/NaryExpression.java @@ -0,0 +1,149 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + +import java.util.Iterator; + +import kodkod.ast.operator.ExprOperator; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; +import kodkod.util.collections.Containers; + +/** + * A relational {@linkplain kodkod.ast.Expression expression} with more than two children, + * composed with an nary {@linkplain ExprOperator operator}. + * + * @specfield op: ExprOperator + * @invariant op.nary() + * @invariant #children > 2 + * @author Emina Torlak + */ +public final class NaryExpression extends Expression implements Iterable{ + private final ExprOperator op; + private final int arity; + private final Expression[] children; + + /** + * Constructs a new associative expression: op(children) + * @requires children array is not modified while in use by this associative expression + * @requires some op.op[children] + * @ensures this.children' = children && this.op' = op + */ + NaryExpression(ExprOperator op, Expression[] children) { + assert children.length>2; + if (!op.nary()) + throw new IllegalArgumentException("Cannot construct an nary expression using the non-nary operator " + op); + + this.op = op; + this.children = children; + + switch(op) { + case UNION : case INTERSECTION : case OVERRIDE : + this.arity = children[0].arity(); + for(int i = 1; i < children.length; i++) { + if (children[i].arity()!=arity) + throw new IllegalArgumentException("Incompatible arities: " + children[0] + " and " + children[i]); + } + break; + case PRODUCT : + int sum = 0; + for(Expression child : children) { sum += child.arity(); } + this.arity = sum; + break; + default : + throw new IllegalArgumentException("Unknown associative operator: " + op); + } + } + + /** + * Returns the arity of this associative expression. + * @return this.arity + * @see kodkod.ast.Expression#arity() + */ + public final int arity() { return arity; } + + /** + * Returns this.op. + * @return this.op + */ + public ExprOperator op() { return op ; } + + + /** + * Returns the number of children of this expression. + * @return #this.children + */ + public int size() { return children.length; } + + /** + * Returns the ith child of this associative expression. + * @requires 0 <= i < #this.children + * @return this.children[i] + */ + public Expression child(int i) { return children[i]; } + + /** + * Returns an iterator over this expression's children, + * in the increasing order of indices. + * @return an iterator over this expression's children, + * in the increasing order of indices. + */ + public Iterator iterator() { return Containers.iterate(children); } + + /** + * {@inheritDoc} + * @see kodkod.ast.Expression#accept(kodkod.ast.visitor.ReturnVisitor) + */ + @Override + public E accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + @Override + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + @Override + public String toString() { + final StringBuilder s = new StringBuilder("("); + s.append(child(0)); + for(int i = 1, size = size(); i < size; i++) { + s.append(" "); + s.append(op); + s.append(" "); + s.append(child(i)); + } + s.append(")"); + return s.toString(); + } + + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/NaryFormula.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/NaryFormula.java new file mode 100644 index 00000000..53a3cce3 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/NaryFormula.java @@ -0,0 +1,122 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + +import java.util.Iterator; + +import kodkod.ast.operator.FormulaOperator; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; +import kodkod.util.collections.Containers; + +/** + * A {@linkplain kodkod.ast.Formula formula} with more than two children, + * composed with an nary {@linkplain FormulaOperator operator}. + * + * @specfield op: FormulaOperator + * @invariant op.nary() + * @invariant #children > 2 + * @author Emina Torlak + */ +public final class NaryFormula extends Formula implements Iterable { + + private final FormulaOperator op; + private final Formula[] children; + + /** + * Constructs a new composite Formula: op(children) + * @requires children array is not modified while in use by this composite Formula + * @requires some op.op[children] + * @ensures this.children' = children && this.op' = op + */ + NaryFormula(FormulaOperator op, Formula[] children) { + assert children.length>2; + if (!op.nary()) + throw new IllegalArgumentException("Cannot construct an nary formula using the non-nary operator " + op); + this.op = op; + this.children = children; + } + + /** + * Returns the operator of this. + * @return this.op + */ + public FormulaOperator op() {return op;} + + /** + * Returns the number of children of this formula. + * @return #this.children + */ + public int size() { return children.length; } + + /** + * Returns the ith child of this formula. + * @requires 0 <= i < #this.children + * @return this.children[i] + */ + public Formula child(int i) { return children[i]; } + + /** + * Returns an iterator over this formula's children, + * in the increasing order of indices. + * @return an iterator over this formula's children, + * in the increasing order of indices. + */ + public Iterator iterator() { return Containers.iterate(children); } + + /** + * {@inheritDoc} + * @see kodkod.ast.Formula#accept(kodkod.ast.visitor.ReturnVisitor) + */ + @Override + public F accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + @Override + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + @Override + public String toString() { + final StringBuilder s = new StringBuilder("("); + s.append(child(0)); + for(int i = 1, size = size(); i < size; i++) { + s.append(" "); + s.append(op); + s.append(" "); + s.append(child(i)); + } + s.append(")"); + return s.toString(); + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/NaryIntExpression.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/NaryIntExpression.java new file mode 100644 index 00000000..84f07df9 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/NaryIntExpression.java @@ -0,0 +1,123 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + +import java.util.Iterator; + +import kodkod.ast.operator.IntOperator; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; +import kodkod.util.collections.Containers; + +/** + * A {@linkplain kodkod.ast.IntExpression int expression} with more than two children, + * composed with an nary {@linkplain IntOperator operator}. + * + * @specfield op: IntOperator + * @invariant op.nary() + * @invariant #children > 2 + * @author Emina Torlak + */ +public final class NaryIntExpression extends IntExpression implements Iterable { + + private final IntOperator op; + private final IntExpression[] children; + + /** + * Constructs a new composite IntExpression: op(children) + * @requires children array is not modified while in use by this composite IntExpression + * @requires some op.op[children] + * @ensures this.children' = children && this.op' = op + */ + NaryIntExpression(IntOperator op, IntExpression[] children) { + assert children.length>2; + if (!op.nary()) + throw new IllegalArgumentException("Cannot construct an nary int expression using the non-nary operator " + op); + this.op = op; + this.children = children; + } + + /** + * Returns the operator of this. + * @return this.op + */ + public IntOperator op() {return op;} + + /** + * Returns the number of children of this int expression. + * @return #this.children + */ + public int size() { return children.length; } + + /** + * Returns the ith child of this int expression. + * @requires 0 <= i < #this.children + * @return this.children[i] + */ + public IntExpression child(int i) { return children[i]; } + + /** + * Returns an iterator over this int expression's children, + * in the increasing order of indices. + * @return an iterator over this int expression's children, + * in the increasing order of indices. + */ + public Iterator iterator() { return Containers.iterate(children); } + + + /** + * {@inheritDoc} + * @see kodkod.ast.IntExpression#accept(kodkod.ast.visitor.ReturnVisitor) + */ + @Override + public I accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.IntExpression#accept(kodkod.ast.visitor.VoidVisitor) + */ + @Override + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + @Override + public String toString() { + final StringBuilder s = new StringBuilder("("); + s.append(child(0)); + for(int i = 1, size = size(); i < size; i++) { + s.append(" "); + s.append(op); + s.append(" "); + s.append(child(i)); + } + s.append(")"); + return s.toString(); + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Node.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Node.java new file mode 100644 index 00000000..5e4aa3a6 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Node.java @@ -0,0 +1,62 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + + +/** + * A node in the abstract syntax tree (DAG). A node + * can accept a ReturnVisitor and have a sequence of + * zero or more children. + * + * @specfield children: int ->lone Node + * @specfield components: set Node + * @invariant children.Node = { i: int | 0 <= i < #children } + * @invariant components= children[int] + * @author Emina Torlak + */ +public abstract class Node { + + /** + * Accepts the given visitor and returns the result + * of the visit (i.e. the result of the call visitor.visit(this)) + * @return the result of being visited by the given visitor + * @throws NullPointerException visitor = null + */ + public abstract Object accept(ReturnVisitor visitor); + + /** + * Accepts the given void visitor by calling visitor.visit(this). + * @throws NullPointerException visitor = null + */ + public abstract void accept(VoidVisitor visitor); + + /** + * Returns a string representation of this node. + * For a pretty-printed string, use {@linkplain kodkod.util.nodes.PrettyPrinter}. + * @return a string representation of this node + * @see kodkod.util.nodes.PrettyPrinter + */ + public abstract String toString(); +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/NotFormula.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/NotFormula.java new file mode 100644 index 00000000..a8cceba7 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/NotFormula.java @@ -0,0 +1,79 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + + +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + + +/** + * Negation of a {@link kodkod.ast.Formula formula}. + * + * @specfield formula: Formula + * @invariant children = 0->formula + * @author Emina Torlak + */ +public final class NotFormula extends Formula { + private final Formula formula; + + /** + * Constructs a new formula: !formula + * + * @ensures this.formula' = formula + * @throws NullPointerException - formula = null + */ + NotFormula(Formula child) { + if (child == null) throw new NullPointerException("formula"); + this.formula = child; + } + + /** + * Returns this.formula. + * @return this.formula + */ + public Formula formula() { return formula; } + + /** + * {@inheritDoc} + * @see kodkod.ast.Formula#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public F accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return "!" + formula; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/ProjectExpression.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/ProjectExpression.java new file mode 100644 index 00000000..d62da893 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/ProjectExpression.java @@ -0,0 +1,110 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + +import java.util.Arrays; +import java.util.Iterator; + +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; +import kodkod.util.collections.Containers; + +/** + * A general projection expression. For example, + * let [[e]] = {<a, b, c>, <d, e, f>, <d, g, f>}. Then, + * project(e, 1, 3) = {<a, c>, <d, f>} and project(e, 1, 1, 2) = {<a, a, b>, <d, d, e>, <d, d, g>}. + * + * @specfield expression: Expression + * @specfield columns: [0..arity) -> one IntExpression + * @invariant children = 0->expression + { i: int, e: IntExpression | columns[i-1] = e } + * @author Emina Torlak + */ +public final class ProjectExpression extends Expression { + private final Expression expr; + private final IntExpression[] columns; + + /** + * Constructs a new projection expression using the given + * expr and columns. + * @ensures this.expression' = expr && this.indices' = columns + */ + ProjectExpression(Expression expr, IntExpression... columns) { + if (columns.length==0) + throw new IllegalArgumentException("No columns specified for projection."); + this.expr = expr; + this.columns = new IntExpression[columns.length]; + System.arraycopy(columns, 0, this.columns, 0, columns.length); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Expression#arity() + */ + public int arity() { return columns.length; } + + /** + * Returns this.expression. + * @return this.expression + */ + public Expression expression() { return expr; } + + /** + * Returns an iterator over this.columns, in proper sequence. + * @return an iterator over this.columns, in proper sequence + */ + public Iterator columns() { + return Containers.iterate(columns); + } + + /** + * Returns the ith column. + * @requires 0 <= i < this.arity + * @return this.columns[i] + */ + public IntExpression column(int i) { return columns[i]; } + + /** + * {@inheritDoc} + * @see kodkod.ast.Expression#accept(kodkod.ast.visitor.ReturnVisitor) + */ + @Override + public E accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return expr.toString() + Arrays.toString(columns); + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/QuantifiedFormula.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/QuantifiedFormula.java new file mode 100644 index 00000000..08910d08 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/QuantifiedFormula.java @@ -0,0 +1,102 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + + +import kodkod.ast.operator.Quantifier; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + + +/** + * A quantified formula. + * + * @specfield decls: Declarations + * @specfield formula: Formula + * @specfield quantifier: Quantifier + * @invariant children = 0->decls + 1->formula + * @author Emina Torlak + */ +public final class QuantifiedFormula extends Formula { + private final Quantifier quantifier; + private final Decls decls; + private final Formula formula; + + /** + * Constructs a new quantified formula: quantifier decls | formula + * + * @ensures this.quantifier' = quantifier && this.decls' = decls && + * this.formula' = formula + * @throws NullPointerException - quantifier = null || decls = null || formula = null + */ + QuantifiedFormula(Quantifier quantifier, Decls declarations, Formula formula) { + if (quantifier == null || declarations == null || formula == null) { + throw new NullPointerException("null arg"); + } + this.quantifier = quantifier; + this.decls = declarations; + this.formula = formula; + } + + /** + * Returns this.formula. + * @return this.formula + */ + public Formula formula() { return formula; } + + /** + * Returns this.decls. + * @return this.decls + */ + public Decls decls() { return decls;} + + /** + * Returns this.quantifier. + * @return this.quantifier + */ + public Quantifier quantifier() { return quantifier; } + + /** + * {@inheritDoc} + * @see kodkod.ast.Formula#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public F accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return "(" + quantifier + " " + decls + " | " + formula + ")"; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Relation.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Relation.java new file mode 100644 index 00000000..c9f99979 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Relation.java @@ -0,0 +1,164 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + + +import kodkod.ast.operator.Multiplicity; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + + + + +/** + * A relation is a leaf expression. + * Two relations are the same if and only if they + * refer to the same object. That is, r1.equals(r2) <=> r1 == r2. Each + * variable has a name, which is basically a comment for the purpose of + * printing, viewing, etc. The name has no meaning otherwise. + * + *

Four methods for creating commonly used predicates over binary relations + * are provided: {@link #function(Expression, Expression)}, {@link #partialFunction(Expression, Expression)}, + * {@link #acyclic()}, and {@link #totalOrder(Relation, Relation, Relation)}. Using + * these methods to generate desired predicates will result in faster constraint solving + * than creating the same predicates via other API calls.

+ * + * @specfield name: String + * @specfield arity: int + * @invariant no children + * @author Emina Torlak + */ +public class Relation extends LeafExpression { + /** + * Constructs a relation with the specified name and arity. + * @ensures this.name' = name && this.arity' = arity + * @throws IllegalArgumentException - arity < 1 + */ + private Relation(String name, int arity) { + super(name,arity); + } + + /** + * Returns a new relation with the given name and arity. + * @return {r: Relation | r.arity = arity && r.name = name } + * @throws IllegalArgumentException - arity < 1 + */ + public static Relation nary(String name, int arity) { + return new Relation(name,arity); + } + + /** + * Returns a new unary relation with the given name. + * The effect of this method is the same as calling Relation.nary(name,1). + * @return {r: Relation | r.arity = 1 && r.name = name } + */ + public static Relation unary(String name) { + return new Relation(name,1); + } + + /** + * Returns a new binary relation with the given name. + * The effect of this method is the same as calling Relation.nary(name,2). + * @return {r: Relation | r.arity = 2 && r.name = name } + */ + public static Relation binary(String name) { + return new Relation(name, 2); + } + + /** + * Returns a ternary relation with the specified name. + * @return {r: Relation | r.name = name && r.arity = 3} + */ + public static Relation ternary(String name) { + return new Relation(name,3); + } + + + /** + * {@inheritDoc} + * @see kodkod.ast.Expression#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public E accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + + /** + * Returns a formula stating that this relation is acyclic. + * @return {f: Formula | f <=> no ^this & iden} + * @throws IllegalArgumentException - this.arity != 2 + */ + public Formula acyclic() { + return new RelationPredicate.Acyclic(this); + } + + /** + * Returns a formula stating that this relation is a total function + * with the specified domain and range. + * @return {f: Formula | f <=> this in domain->range && all v: domain | one v.this } + * @throws NullPointerException - domain = null || range = null + * @throws IllegalArgumentException - domain.arity != 1 || range.arity != 1 + * @throws IllegalArgumentException - this.arity != 2 + */ + public Formula function(Expression domain, Expression range) { + return new RelationPredicate.Function(this, domain, Multiplicity.ONE, range); + } + + /** + * Returns a formula stating that this relation is a partial function + * with the specified domain and range. + * @return {f: Formula | f <=> this in domain->range && all v: domain | lone v.this } + * @throws NullPointerException - domain = null || range = null + * @throws IllegalArgumentException - domain.arity != 1 || range.arity != 1 + * @throws IllegalArgumentException - this.arity != 2 + */ + public Formula partialFunction(Expression domain, Expression range) { + return new RelationPredicate.Function(this, domain, Multiplicity.LONE, range); + } + + /** + * Returns a formula stating that this relation imposes a total ordering + * over the atoms in the set ordered, and that thet first and + * last elements in the ordering are given by the relations first + * and last. + * @return {f: Formula | f <=> one first && one last && last in ordered && + * no this.first && no last.this && + * ordered = first.*this && + * all e: ordered - last | one e.this } + * @throws NullPointerException - any of the arguments are null + * @throws IllegalArgumentException - any of the argument relations' arities are greater than one + * @throws IllegalArgumentException - this.arity != 2 + */ + public Formula totalOrder(Relation ordered, Relation first, Relation last) { + return new RelationPredicate.TotalOrdering(this, ordered, first, last); + } + + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/RelationPredicate.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/RelationPredicate.java new file mode 100644 index 00000000..134f0af8 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/RelationPredicate.java @@ -0,0 +1,343 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + + +import kodkod.ast.operator.Multiplicity; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + +/** + * Represents common predicates on relations; e.g. + * predicates stating that a relation is a total function, + * partial function, acyclic, or a total ordering over + * a set of atoms. + * + * @specfield relation: Relation + * @specfield name: Name // name of the predicate + * @invariant relation.arity = 2 + * @author Emina Torlak + */ +public abstract class RelationPredicate extends Formula { + private final Relation relation; + + /** + * Constructs a new relation predicate for the given relation. + * @throws NullPointerException - relation = null + * @throws IllegalArgumentException - relation.arity != 2 + */ + private RelationPredicate(Relation relation) { + if (relation.arity() != 2) + throw new IllegalArgumentException("invalid arity: " + relation.arity()); + this.relation = relation; + } + + /** + * Returns the relation to which this predicate applies. + * @return this.relation + */ + public Relation relation() { + return relation; + } + + + /** + * Returns the name of this predicate. + * @return this.name + */ + public abstract Name name(); + + /** + * Turns this predicate into explicit constraiants. + * @return {f: Formula - RelationPredicate | f <=> this } + */ + public abstract Formula toConstraints(); + + /** + * {@inheritDoc} + * @see kodkod.ast.Formula#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public F accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + + /** + * Enumerates built-in predicates. + */ + public static enum Name { + /** Function predicate. */ + FUNCTION, + /** Partial function predicate. */ + //PARTIAL_FUNCTION, + /** Acyclic predicate. */ + ACYCLIC, + /** Total ordering predicate. */ + TOTAL_ORDERING + } + + /** + * Represents the acyclic predicate. The predicate states that + * the given relation is acyclic. + * @specfield relation: Relation + * @invariant name = ACYCLIC + * @invariant children = 0->relation + * @author Emina Torlak + */ + public static final class Acyclic extends RelationPredicate { + /** + * Constructs a new acyclic predicate over the given relation. + * @ensures this.relation' = relation && this.name' = ACYCLIC + * @throws IllegalArgumentException - relation.arity != 2 + */ + Acyclic(Relation relation) { + super(relation); + } + + /** + * Returns the name of this predicate. + * @return ACYCLIC + */ + @Override + public Name name() { + return Name.ACYCLIC; + } + + /** + * {@inheritDoc} + * @see kodkod.ast.RelationPredicate#toConstraints() + */ + @Override + public Formula toConstraints() { + return relation().closure().intersection(Expression.IDEN).no(); + } + + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return name() + "(" + relation() + ")"; + } + } + + /** + * Represents the function predicate. The predicate states that the given + * relation is a total or partial function with the specified + * domain and range. + * + * @specfield relation: Relation + * @specfield domain, range: Expression + * @specfield targetMult: ONE + LONE + * @invariant name = FUNCTION + * @invariant domain.arity = range.arity = 1 + * @invariant children = 0->relation + 1->domain + 2->range + * @author Emina Torlak + */ + public static final class Function extends RelationPredicate { + private final Expression domain, range; + private final Multiplicity targetMult; + /** + * Constructs a new function predicate over the given relation and domain, + * with the specified target multiplicity. + * @ensures this.name' = FUNCTION && this.relation' = relation && this.domain' = domain && + * this.range' = range + * @throws IllegalArgumentException - relation.arity != 2 || domain.arity != 1 || range.arity != 1 || + * targetMult !in ONE + LONE + */ + Function(Relation relation, Expression domain, Multiplicity targetMult, Expression range) { + super(relation); + if (targetMult != Multiplicity.ONE && targetMult != Multiplicity.LONE) + throw new IllegalArgumentException("invalid target multiplicity for a function: " + targetMult); + if (domain.arity() != 1 || range.arity() != 1) + throw new IllegalArgumentException("invalid arity: " + domain + " or " + range); + this.targetMult = targetMult; + this.domain = domain; + this.range = range; + } + + /** + * Returns the name of this predicate. + * @return this.name + */ + public Name name() { + return Name.FUNCTION; + } + + + /** + * Returns the target multiplicity of the function represented + * by this.relation. + * @return this.targetMult + */ + public Multiplicity targetMult() { + return targetMult; + } + + /** + * Returns the domain of this.relation. + * @return this.domain + */ + public Expression domain() { + return domain; + } + + /** + * Returns the range of this.relation. + * @return this.range + */ + public Expression range() { + return range; + } + + /** + * {@inheritDoc} + * @see kodkod.ast.RelationPredicate#toConstraints() + */ + @Override + public Formula toConstraints() { + // relation in domain->range + final Formula domainConstraint = relation().in(domain.product(range)); + // all v: domain | targetMult v.relation + final Variable v = Variable.unary("v"+relation().name()); + final Formula funConstraint = v.join(relation()).apply(targetMult).forAll(v.oneOf(domain)); + // relation in domain->range && all v: domain | targetMult v.relation + return domainConstraint.and(funConstraint); + } + + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return name() + "(" + relation() + ", " + + domain + " ->" + targetMult + " " + range + ")"; + } + } + + /** + * Represents the total ordering predicate. The predicate states that the given + * relation imposes a total ordering over the set ordered, + * and that the smallest/largest elements resulting from the ordering are given + * by the first/last relations. + * + * @specfield relation: Relation + * @specfield ordered, first, last: Relation + * @invariant name = TOTAL_ORDERING + * @invariant ordered.arity = first.arity = last.arity = 1 + * @invariant children = 0->relation + 1->ordered + 2->first + 3->last + */ + public static final class TotalOrdering extends RelationPredicate { + private final Relation first, last, ordered; + + /** + * Constructs a new total ordering predicate. + * @ensures this.relation' = relation && this.first' = first && this.last' = last && + * this.name' = TOTAL_ORDERING + * @throws NullPointerException - any of the arguments are null + * @throws IllegalArgumentException - relation.arity != 2 || first.arity != 1 || last.arity != 1 + **/ + TotalOrdering(Relation relation, Relation ordered, Relation first, Relation last) { + super(relation); + if (first.arity() != 1 || last.arity() != 1 || ordered.arity() != 1) + throw new IllegalArgumentException("invalid arity: " + first + " or " + last + " or " + ordered); + this.first = first; + this.last = last; + this.ordered = ordered; + } + + /** + * Returns the name of this predicate. + * @return TOTAL_ORDERING + */ + public Name name() { + return Name.TOTAL_ORDERING; + } + + /** + * Returns the relation representing the first element + * in the ordering imposed by this.relation. + * @return this.first + */ + public Relation first() { + return first; + } + + /** + * Returns the relation representing the last element + * in the ordering imposed by this.relation. + * @return this.last + */ + public Relation last() { + return last; + } + + /** + * Returns the relation representing the atoms which + * are ordered by this.relation. + * @return this.ordered + */ + public Relation ordered() { + return ordered; + } + + /** + * {@inheritDoc} + * @see kodkod.ast.RelationPredicate#toConstraints() + */ + @Override + public Formula toConstraints() { + // one first && one last && last in ordered + final Formula f0 = first.one().and(last.one()).and(last.in(ordered)); + // ordered = first.*relation + final Formula f1 = ordered.eq(first.join(relation().reflexiveClosure())); + // no relation.first && no last.relation + final Formula f2 = relation().join(first).no().and(last.join(relation()).no()); + // all e: ordered - last | one e.this + final Variable e = Variable.unary("e"+relation().name()); + final Formula f3 = e.join(relation()).one().forAll(e.oneOf(ordered.difference(last))); + + return and(f0, f1, f2, f3); + } + + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return name() + "(" + relation() + ", " + ordered + ", " + first + ", " + last + ")"; + } + + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/SumExpression.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/SumExpression.java new file mode 100644 index 00000000..535c1795 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/SumExpression.java @@ -0,0 +1,98 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + +import kodkod.ast.operator.Multiplicity; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + +/** + * Denotes the integer obtained by summing the values of an iteger expression ie + * for all values of a scalar x drawn from a set e. + * @specfield intExpr: IntExpression + * @specfield decls: Decls + * @specfield children = 0->decls + 1->intExpr + * @invariant all d: decls.children[int] | d.multiplicity = 1 + * @author Emina Torlak + */ +public final class SumExpression extends IntExpression { + private final Decls decls; + private final IntExpression intExpr; + + /** + * Constructs a sum expression + * @ensures this.decls' = decls && this.intExpr' = intExpr + * @throws IllegalArgumentException - some d: decls.children | d.multiplicty != ONE + */ + SumExpression(Decls decls, IntExpression intExpr) { + for(Decl d : decls) { + if (d.multiplicity()!=Multiplicity.ONE) + throw new IllegalArgumentException(d + " is not a scalar declaration."); + } + this.decls = decls; + this.intExpr = intExpr; + } + + /** + * Returns this.decls. + * @return this.decls + */ + public final Decls decls() { + return decls; + } + + /** + * Returns this.intExpr. + * @return this.intExpr + */ + public final IntExpression intExpr() { + return intExpr; + } + + /** + * {@inheritDoc} + * @see kodkod.ast.IntExpression#accept(kodkod.ast.visitor.ReturnVisitor) + */ + @Override + public I accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.IntExpression#accept(kodkod.ast.visitor.VoidVisitor) + */ + @Override + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return "(sum " + decls + " | " + intExpr + ")"; + } + + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/UnaryExpression.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/UnaryExpression.java new file mode 100644 index 00000000..1642f674 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/UnaryExpression.java @@ -0,0 +1,108 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + + +import kodkod.ast.operator.ExprOperator; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + +/** + * An {@link kodkod.ast.Expression expression} with one child. + * + * @specfield expression: Expression + * @specfield op: ExprOperator + * @invariant op.unary() + * @invariant children = 0->Expression + * @author Emina Torlak + */ +public final class UnaryExpression extends Expression { + private final Expression expression; + private final ExprOperator op; + private final int arity; + + /** + * Constructs a new unary expression: op expression + * + * @ensures this.expression' = expression && this.op' = op + * @throws NullPointerException - expression = null || op = null + * @throws IllegalArgumentException - op in {TRANSPOSE, CLOSURE, REFLEXIVE_CLOSURE} && child.arity != 2 + */ + UnaryExpression(ExprOperator op, Expression child) { + if (!op.unary()) { + throw new IllegalArgumentException("Not a unary operator: " + op); + } + if (child.arity()!=2) { + throw new IllegalArgumentException("Invalid arity: " + child + "::" + child.arity()); + } + this.expression = child; + this.op = op; + this.arity = 2; + } + + /** + * Returns the arity of this expression. + * @return this.arity + * @see kodkod.ast.Expression#arity() + */ + public int arity() { + return arity; + } + + /** + * Returns this.expression. + * @return this.expression + */ + public Expression expression() {return expression;} + + /** + * Returns this.op. + * @return this.op + */ + public ExprOperator op() {return op;} + + + /** + * {@inheritDoc} + * @see kodkod.ast.Expression#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public E accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return op.toString() + expression.toString(); + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/UnaryIntExpression.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/UnaryIntExpression.java new file mode 100644 index 00000000..e801075b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/UnaryIntExpression.java @@ -0,0 +1,87 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + +import kodkod.ast.operator.IntOperator; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + +/** + * A unary integer intExpr, e.g. -x. + * @specfield intExpr: IntExpression + * @specfield op: IntOperator + * @invariant op.unary() + * @invariant children = 0->intExpr + * @author Emina Torlak + */ +public final class UnaryIntExpression extends IntExpression { + private final IntOperator op; + private final IntExpression intExpr; + + /** + * Constructs a new unary int formula: op intExpr + * @ensures this.op' = op && this.intExpr' = intExpr + */ + UnaryIntExpression(IntOperator op, IntExpression intExpr) { + if (!op.unary()) throw new IllegalArgumentException("Not a unary operator: " + op); + this.op = op; + this.intExpr = intExpr; + } + + /** + * Returns the operator of this. + * @return this.op + */ + public IntOperator op() {return op;} + + /** + * Returns this.intExpr. + * @return this.intExpr + */ + public IntExpression intExpr() {return intExpr;} + + /** + * {@inheritDoc} + * @see kodkod.ast.IntExpression#accept(kodkod.ast.visitor.ReturnVisitor) + */ + @Override + public I accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.IntExpression#accept(kodkod.ast.visitor.VoidVisitor) + */ + @Override + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#toString() + */ + public String toString() { + return (op==IntOperator.NEG||op==IntOperator.NOT) ? "(" + op + intExpr + ")" : op + "(" + intExpr + ")" ; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Variable.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Variable.java new file mode 100644 index 00000000..79d312d9 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/Variable.java @@ -0,0 +1,151 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast; + +import kodkod.ast.operator.Multiplicity; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.ast.visitor.VoidVisitor; + +/** + * Represents a variable in a {@link QuantifiedFormula quantified formula}, + * a {@link Comprehension comprehension expression}, or a {@link SumExpression sum expression}. + * Two variables are the same if and only if they + * refer to the same object. That is, v1.eauls(v2) <=> v1 == v2. Each + * variable has a name, which is basically a comment for the purpose of + * printing, viewing, etc. The name has no meaning otherwise. The arity of + * a variable specifies the arity of expressions over which the variable can + * range. + * + * @specfield name: String + * @specfield arity: int + * @invariant no children + * @author Emina Torlak + */ +public final class Variable extends LeafExpression { + + /** + * Constructs a variable with the specified name and arity 1. + * @ensures this.name' = name && this.arity' = 1 + */ + private Variable(String name) { + super(name, 1); + } + + /** + * Constructs a variable with the specified name and arity. + * @ensures this.name' = name && this.arity' = arity + */ + private Variable(String name, int arity) { + super(name, arity); + } + + /** + * Returns a new variable with the specified name and arity 1. + * @ensures this.name' = name && this.arity' = 1 + */ + public static Variable unary(String name) { + return new Variable(name); + } + + /** + * Returns a new variable with the specified name and arity. + * @ensures this.name' = name && this.arity' = arity + * @throws IllegalArgumentException - arity < 1 + */ + public static Variable nary(String name, int arity) { + return new Variable(name, arity); + } + + /** + * Returns the declaration that constrains this variable to + * be bound to at most one element of the given expression: 'this: lone expr'. + * @return {d: Decl | d.variable = this && d.multiplicity = LONE && d.expression = expr } + * @throws NullPointerException - expr = null + * @throws IllegalArgumentException - this.arity != expr.arity || expr.arity != 1 + */ + public Decl loneOf(Expression expr) { + return new Decl(this, Multiplicity.LONE, expr); + } + + /** + * Returns the declaration that constrains this variable to + * be bound to exactly one element of the given expression: 'this: one expr'. + * @return {d: Decl | d.variable = this && d.multiplicity = ONE && d.expression = expr } + * @throws NullPointerException - expr = null + * @throws IllegalArgumentException - this.arity != expr.arity || expr.arity != 1 + */ + public Decl oneOf(Expression expr) { + return new Decl(this, Multiplicity.ONE, expr); + } + + /** + * Returns the declaration that constrains this variable to + * be bound to at least one element of the given expression: 'this: some expr'. + * @return {d: Decl | d.variable = this && d.multiplicity = SOME && d.expression = expr } + * @throws NullPointerException - expr = null + * @throws IllegalArgumentException - this.arity != expr.arity || expr.arity != 1 + */ + public Decl someOf(Expression expr) { + return new Decl(this, Multiplicity.SOME, expr); + } + + /** + * Returns the declaration that constrains this variable to + * be bound to a subset of the elements in the given expression: 'this: set expr'. + * @return {d: Decl | d.variable = this && d.multiplicity = SET && d.expression = expr } + * @throws NullPointerException - expr = null + * @throws IllegalArgumentException - this.arity != expr.arity + */ + public Decl setOf(Expression expr) { + return new Decl(this, Multiplicity.SET, expr); + } + + /** + * Returns the declaration that constrains this variable to + * be bound to the specified number of the elements in the given expression: 'this: mult expr'. + * @return {d: Decl | d.variable = this && d.multiplicity = mult && d.expression = expr } + * @throws NullPointerException - expression = null || mult = null + * @throws IllegalArgumentException - mult = NO + * @throws IllegalArgumentException - mult in ONE + LONE + SOME && expr.arity != 1 + * @throws IllegalArgumentException - this.arity != expr.arity + */ + public Decl declare(Multiplicity mult, Expression expr) { + return new Decl(this, mult, expr); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Expression#accept(kodkod.ast.visitor.ReturnVisitor) + */ + public E accept(ReturnVisitor visitor) { + return visitor.visit(this); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.Node#accept(kodkod.ast.visitor.VoidVisitor) + */ + public void accept(VoidVisitor visitor) { + visitor.visit(this); + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/operator/ExprCastOperator.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/operator/ExprCastOperator.java new file mode 100644 index 00000000..9012c268 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/operator/ExprCastOperator.java @@ -0,0 +1,12 @@ +package kodkod.ast.operator; + +/** + * Enumerates expression 'cast' operators. + */ +public enum ExprCastOperator { + /** The cardinality operator (#). */ + CARDINALITY { public String toString() { return "#"; } }, + /** The sum operator. */ + SUM { public String toString() { return "sum"; } }; + +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/operator/ExprCompOperator.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/operator/ExprCompOperator.java new file mode 100644 index 00000000..5548df76 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/operator/ExprCompOperator.java @@ -0,0 +1,11 @@ +package kodkod.ast.operator; + +/** + * Enumerates relational comparison operators. + */ +public enum ExprCompOperator { + /** Subset operator (in). */ + SUBSET { public String toString() { return "in"; } }, + /** Equality operator (=). */ + EQUALS { public String toString() { return "="; } }; +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/operator/ExprOperator.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/operator/ExprOperator.java new file mode 100644 index 00000000..18a50f6c --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/operator/ExprOperator.java @@ -0,0 +1,58 @@ +package kodkod.ast.operator; + + + + +/** + * Enumerates unary (~, ^, *), binary (+, &, ++, ->, -, .) and nary (+, &, ++, ->) expression operators. + * @specfield op: (int->lone Expression) -> Expression + * @invariant all args: seq Expression, out: Expression | args->out in op => (out.children = args && out.op = this) + */ +public enum ExprOperator { + /** Relational union (+) operator. */ + UNION { public String toString() { return "+"; } }, + /** Relational intersection (&) operator. */ + INTERSECTION { public String toString() { return "&"; } }, + /** Relational override (++) operator. */ + OVERRIDE { public String toString() { return "++"; } }, + /** Relational product (->) operator. */ + PRODUCT { public String toString() { return "->"; } }, + /** Relational difference (-) operator. */ + DIFFERENCE { public String toString() { return "-"; } }, + /** Relational join (.) operator. */ + JOIN { public String toString() { return "."; } }, + /** Transpose (~) operator. */ + TRANSPOSE { public String toString() { return "~";} }, + /** Transitive closure (^) operator. */ + CLOSURE { public String toString() { return "^";} }, + /** Reflexive transitive closure (*) operator. */ + REFLEXIVE_CLOSURE { public String toString() { return "*";} }; + + + static final int unary = TRANSPOSE.index() | CLOSURE.index() | REFLEXIVE_CLOSURE.index(); + + static final int binary = ~unary; + + static final int nary = UNION.index() | INTERSECTION.index() | OVERRIDE.index() | PRODUCT.index(); + + private final int index() { return 1<, <=>) and nary (&&, ||) logical operators. + * @specfield op: (int->lone Formula) -> Formula + * @invariant all args: seq Formula, out: Formula | args->out in op => (out.children = args && out.op = this) + */ +public enum FormulaOperator { + /** Logical AND operator. */ + AND { public String toString() { return "&&"; } }, + /** Logical OR operator. */ + OR { public String toString() { return "||"; } }, + /** Logical bi-implication operator. */ + IFF { public String toString() { return "<=>"; } }, + /** Logical implication operator. */ + IMPLIES { public String toString() { return "=>"; } }; + + static final int nary = (1<, <=, >=. + */ +public enum IntCompOperator { + /** `=' operator */ + EQ { public String toString() { return "="; } }, + /** `!=' operator */ + NEQ { public String toString() { return "!="; } }, + /** `<' operator */ + LT { public String toString() { return "<"; } }, + /** `<=' operator */ + LTE { public String toString() { return "<="; } }, + /** `>' operator */ + GT { public String toString() { return ">"; } }, + /** `>=' operator */ + GTE { public String toString() { return ">="; } }; +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/operator/IntOperator.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/operator/IntOperator.java new file mode 100644 index 00000000..ecfba9bd --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/operator/IntOperator.java @@ -0,0 +1,67 @@ +package kodkod.ast.operator; + + + +/** + * Enumerate unary (-, ~, abs, sgn), binary (+, *, &, |, -, /, %, >>, >>>, <<) and nary (+, *, &, |) operators on integer expressions. + * @specfield op: (int->lone IntExpression) -> IntExpression + * @invariant all args: seq IntExpression, out: IntExpression | args->out in op => (out.children = args && out.op = this) + */ +public enum IntOperator { + /** `+' operator */ + PLUS { public String toString() { return "+"; } }, + /** `*' operator */ + MULTIPLY { public String toString() { return "*"; } }, + /** `-' operator */ + MINUS { public String toString() { return "-"; } }, + /** `/' operator */ + DIVIDE { public String toString() { return "/"; } }, + /** `%' operator */ + MODULO { public String toString() { return "%"; } }, + /** Bitwise AND operator */ + AND { public String toString() { return "&"; } }, + /** Bitwise OR operator */ + OR { public String toString() { return "|"; } }, + /** Bitwise XOR operator */ + XOR { public String toString() { return "^"; } }, + /** Left shift operator */ + SHL { public String toString() { return "<<"; } }, + /** Right shift operator with zero extension */ + SHR { public String toString() { return ">>>"; } }, + /** Right shift operator with sign extension */ + SHA { public String toString() { return ">>"; } }, + /** unary negation (`-') operator */ + NEG { public String toString() { return "-"; } }, + /** bit negation (`~') operator */ + NOT { public String toString() { return "~"; } }, + /** absolute value function */ + ABS { public String toString() { return "abs";} }, + /** signum function */ + SGN { public String toString() { return "sgn"; } }; + + static final int unary = NEG.index() | NOT.index() | ABS.index() | SGN.index(); + + static final int binary = ~unary; + + static final int nary = PLUS.index() | MULTIPLY.index() | AND.index() | OR.index(); + + private final int index() { return 1<no expr: expr contains no elements. The 'no' multiplicity can only be used in a multiplicity formula. */ + NO { public String toString() { return "no"; }}, + /** lone expr: expr contains at most one element. */ + LONE { public String toString() { return "lone"; }}, + /** one expr: expr contains exactly one element. */ + ONE { public String toString() { return "one"; }}, + /** some expr: expr contains at least one element. */ + SOME { public String toString() { return "some"; }}, + /** v: set expr: v is a subset of expr. The 'set' multiplicity can only be used in a declaration. */ + SET { public String toString() { return "set"; }} +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/operator/Quantifier.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/operator/Quantifier.java new file mode 100644 index 00000000..d4a408a3 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/operator/Quantifier.java @@ -0,0 +1,11 @@ +package kodkod.ast.operator; + +/** + * Enumerates logical quantifiers. + */ +public enum Quantifier { + /** Universal quantifier. */ + ALL { public String toString() { return "all"; }}, + /** Existential quantifier. */ + SOME { public String toString() { return "some"; }} +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/visitor/AbstractCollector.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/visitor/AbstractCollector.java new file mode 100644 index 00000000..120b1608 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/visitor/AbstractCollector.java @@ -0,0 +1,591 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast.visitor; + +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.Set; + +import kodkod.ast.BinaryExpression; +import kodkod.ast.BinaryFormula; +import kodkod.ast.BinaryIntExpression; +import kodkod.ast.ComparisonFormula; +import kodkod.ast.Comprehension; +import kodkod.ast.ConstantExpression; +import kodkod.ast.ConstantFormula; +import kodkod.ast.Decl; +import kodkod.ast.Decls; +import kodkod.ast.ExprToIntCast; +import kodkod.ast.Expression; +import kodkod.ast.Formula; +import kodkod.ast.IfExpression; +import kodkod.ast.IfIntExpression; +import kodkod.ast.IntComparisonFormula; +import kodkod.ast.IntConstant; +import kodkod.ast.IntExpression; +import kodkod.ast.IntToExprCast; +import kodkod.ast.MultiplicityFormula; +import kodkod.ast.NaryExpression; +import kodkod.ast.NaryFormula; +import kodkod.ast.NaryIntExpression; +import kodkod.ast.Node; +import kodkod.ast.NotFormula; +import kodkod.ast.ProjectExpression; +import kodkod.ast.QuantifiedFormula; +import kodkod.ast.Relation; +import kodkod.ast.RelationPredicate; +import kodkod.ast.SumExpression; +import kodkod.ast.UnaryExpression; +import kodkod.ast.UnaryIntExpression; +import kodkod.ast.Variable; + +/** + *

A depth first collector. Subclasses should override the + * methods in which detection is performed to return the appropriate set. + * For example, a Variable collector could be implemented + * simply by subclassing this implementation and overriding + * the {@link #visit(Variable) } method to return a singleton set containing + * the input argument.

+ * + * @specfield cached: set Node // result of visiting these nodes will be cached + * @specfield cache: Node -> lone Set + * @specfield cached in cache.Node + * @author Emina Torlak + */ +public abstract class AbstractCollector implements + ReturnVisitor, Set, Set, Set> { + protected final Map> cache; + protected final Set cached; + + /** + * Constructs a depth first collector which will cache the results + * of visiting the given nodes and re-use them on subsequent visits. + * @ensures this.cached' = cached && no this.cache + */ + protected AbstractCollector(Set cached) { + this.cached = cached; + this.cache = new IdentityHashMap>(cached.size()); + } + + /** + * Constructs a depth-first collectior which will cache + * the results of visiting the given nodes in the given map, + * and re-use them on subsequent visits. + * @ensures this.cached' = cached && this.cache' = cache + */ + protected AbstractCollector(Set cached, Map> cache) { + this.cached = cached; + this.cache = cache; + } + /** + * If n has been visited and a value for it cached, + * the cached value is returned. Otherwise null is returned. + * @return this.cache[n] + */ + protected Set lookup(Node n) { + return cache.get(n); + } + + /** + * Caches the given value for the specified node, if + * this is a caching visitor, and returns it. + * @ensures n in this.cached => this.cache' = this.cache ++ n->reduce(val), this.cache' = this.cache + * @return val + */ + protected Set cache(Node n, Set val) { + if (cached.contains(n)) { + cache.put(n, reduce(val)); + } + return val; + } + + /** + * Returns the set that has the same contents as val, but that may + * be more efficiently implemented than val. + * @return val.size()=0 => Collections.EMPTY_SET, + * val.size()=1 => Collections.singleton(val.iterator().next()), + * val + */ + protected Set reduce(Set val) { + switch(val.size()) { + case 0 : return Collections.emptySet(); + case 1 : return Collections.singleton(val.iterator().next()); + default : return val; + } + } + + /** + * Returns a new, empty, modifiable set. + * @return a new, empty, modifiable set. + */ + protected abstract Set newSet() ; + + /** + * Calls lookup(decls) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * union of the sets returned by the children and returns it. + * @return let x = lookup(decls) | + * x != null => x, + * cache(decls, decls.declarations[0].accept(this) +...+ decls.declarations[decls.size-1].accept(this)) + */ + public Set visit(Decls decls) { + Set ret = lookup(decls); + if (ret!=null) return ret; + ret = newSet(); + for(Decl d: decls) { + ret.addAll(d.accept(this)); + } + return cache(decls, ret); + } + + /** + * Calls lookup(decl) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * union of the sets returned by the children and returns it. + * @return let x = lookup(decl) | + * x != null => x, + * cache(decls, decl.variable.accept(this) + decl.expression.accept(this)) + */ + public Set visit(Decl decl) { + Set ret = lookup(decl); + if (ret!=null) return ret; + ret = newSet(); + ret.addAll(decl.variable().accept(this)); + ret.addAll(decl.expression().accept(this)); + return cache(decl,ret); + } + + /** + * Returns Collections.EMPTY_SET + * @return Collections.EMPTY_SET + */ + @SuppressWarnings("unchecked") + public Set visit(Relation relation) { + return Collections.EMPTY_SET; + } + + /** + * Returns Collections.EMPTY_SET + * @return Collections.EMPTY_SET + */ + @SuppressWarnings("unchecked") + public Set visit(Variable variable) { + return Collections.EMPTY_SET; + } + + /** + * Returns Collections.EMPTY_SET + * @return Collections.EMPTY_SET + */ + @SuppressWarnings("unchecked") + public Set visit(ConstantExpression constExpr) { + return Collections.EMPTY_SET; + } + + /** + * Calls lookup(expr) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * union of the children's return values and returns it. + * @return let x = lookup(expr) | + * x != null => x, + * cache(expr, expr.child(0).accept(this) + .. + expr.child(expr.size()-1).accept(this)) + */ + public Set visit(NaryExpression expr) { + Set ret = lookup(expr); + if (ret!=null) return ret; + ret = newSet(); + for(Expression child : expr) { + ret.addAll(child.accept(this)); + } + return cache(expr, ret); + } + + /** + * Calls lookup(binExpr) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * union of the children's return values and returns it. + * @return let x = lookup(binExpr) | + * x != null => x, + * cache(binExpr, binExpr.left.accept(this) + binExpr.right.accept(this)) + */ + public Set visit(BinaryExpression binExpr) { + Set ret = lookup(binExpr); + if (ret!=null) return ret; + ret = newSet(); + ret.addAll(binExpr.left().accept(this)); + ret.addAll(binExpr.right().accept(this)); + return cache(binExpr, ret); + } + + /** + * Calls lookup(unaryExpr) and returns the cached value, if any. + * If no cached value exists, visits the child, caches its return value and returns it. + * @return let x = lookup(unaryExpr) | + * x != null => x, + * cache(unaryExpr, unaryExpr.expression.accept(this)) + */ + public Set visit(UnaryExpression unaryExpr) { + Set ret = lookup(unaryExpr); + if (ret!=null) return ret; + ret = newSet(); + ret.addAll(unaryExpr.expression().accept(this)); + return cache(unaryExpr,ret); + } + + /** + * Calls lookup(comprehension) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * union of the children's return values and returns it. + * @return let x = lookup(comprehension) | + * x != null => x, + * cache(comprehension, comprehension.declarations.accept(this) + comprehension.formula.accept(this)) + */ + public Set visit(Comprehension comprehension) { + Set ret = lookup(comprehension); + if (ret!=null) return ret; + ret = newSet(); + ret.addAll(comprehension.decls().accept(this)); + ret.addAll(comprehension.formula().accept(this)); + return cache(comprehension, ret); + } + + /** + * Calls lookup(ifExpr) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * union of the children's return values and returns it. + * @return let x = lookup(ifExpr) | + * x != null => x, + * cache(ifExpr, ifExpr.condition.accept(this) + ifExpr.thenExpr.accept(this) + ifExpr.elseExpr.accept(this)) + */ + public Set visit(IfExpression ifExpr) { + Set ret = lookup(ifExpr); + if (ret!=null) return ret; + ret = newSet(); + ret.addAll(ifExpr.condition().accept(this)); + ret.addAll(ifExpr.thenExpr().accept(this)); + ret.addAll(ifExpr.elseExpr().accept(this)); + return cache(ifExpr, ret); + } + + /** + * Calls lookup(project) and returns the cached value, if any. If no cached + * value exists, visits each child, caches the union of the children's return + * values and returns it. + * @return let x = lookup(project) | + * x != null => x, + * cache(project, project.expression.accept(this) + project.columns[int].accept(this)) + */ + public Set visit(ProjectExpression project) { + Set ret = lookup(project); + if (ret!=null) return ret; + ret = newSet(); + ret.addAll(project.expression().accept(this)); + for(int i = 0, arity = project.arity(); i < arity; i++) { + ret.addAll(project.column(i).accept(this)); + } + return cache(project,ret); + } + + /** + * Calls lookup(castExpr) and returns the cached value, if any. + * If no cached value exists, visits the child, caches its return value and returns it. + * @return let x = lookup(castExpr) | + * x != null => x, + * cache(intExpr, castExpr.intExpr.accept(this)) + */ + public Set visit(IntToExprCast castExpr) { + Set ret = lookup(castExpr); + if (ret!=null) return ret; + ret = newSet(); + ret.addAll(castExpr.intExpr().accept(this)); + return cache(castExpr,ret); + } + + /** + * Returns Collections.EMPTY_SET + * @return Collections.EMPTY_SET + */ + @SuppressWarnings("unchecked") + public Set visit(IntConstant intConst) { + return Collections.EMPTY_SET; + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * union of the children's return values and returns it. + * @return let x = lookup(intExpr) | + * x != null => x, + * cache(intExpr, intExpr.condition.accept(this) + intExpr.thenExpr.accept(this) + intExpr.elseExpr.accept(this)) + */ + public Set visit(IfIntExpression intExpr) { + Set ret = lookup(intExpr); + if (ret!=null) return ret; + ret = newSet(); + ret.addAll(intExpr.condition().accept(this)); + ret.addAll(intExpr.thenExpr().accept(this)); + ret.addAll(intExpr.elseExpr().accept(this)); + return cache(intExpr, ret); + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If no cached value exists, visits the child, caches its return value and returns it. + * @return let x = lookup(intExpr) | + * x != null => x, + * cache(intExpr, intExpr.expression.accept(this)) + */ + public Set visit(ExprToIntCast intExpr) { + Set ret = lookup(intExpr); + if (ret!=null) return ret; + ret = newSet(); + ret.addAll(intExpr.expression().accept(this)); + return cache(intExpr,ret); + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * union of the children's return values and returns it. + * @return let x = lookup(intExpr) | + * x != null => x, + * cache(intExpr, intExpr.child(0).accept(this) + .. + intExpr.child(intExpr.size()-1).accept(this)) + */ + public Set visit(NaryIntExpression intExpr) { + Set ret = lookup(intExpr); + if (ret!=null) return ret; + ret = newSet(); + for(IntExpression child : intExpr) { + ret.addAll(child.accept(this)); + } + return cache(intExpr, ret); + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * union of the children's return values and returns it. + * @return let x = lookup(intExpr) | + * x != null => x, + * cache(intExpr, intExpr.left.accept(this) + intExpr.right.accept(this)) + */ + public Set visit(BinaryIntExpression intExpr) { + Set ret = lookup(intExpr); + if (ret!=null) return ret; + ret = newSet(); + ret.addAll(intExpr.left().accept(this)); + ret.addAll(intExpr.right().accept(this)); + return cache(intExpr, ret); + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If no cached value exists, visits the child, caches its return value and returns it. + * @return let x = lookup(intExpr) | + * x != null => x, + * cache(intExpr, intExpr.expression.accept(this)) + */ + public Set visit(UnaryIntExpression intExpr) { + Set ret = lookup(intExpr); + if (ret!=null) return ret; + ret = newSet(); + ret.addAll(intExpr.intExpr().accept(this)); + return cache(intExpr,ret); + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * union of the children's return values and returns it. + * @return let x = lookup(intExpr) | + * x != null => x, + * cache(intExpr, intExpr.decls.accept(this) + intExpr.intExpr.accept(this)) + */ + public Set visit(SumExpression intExpr) { + Set ret = lookup(intExpr); + if (ret!=null) return ret; + ret = newSet(); + ret.addAll(intExpr.decls().accept(this)); + ret.addAll(intExpr.intExpr().accept(this)); + return cache(intExpr, ret); + } + + /** + * Calls lookup(intComp) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * union of the children's return values and returns it. + * @return let x = lookup(intComp) | + * x != null => x, + * cache(intComp, intComp.left.accept(this) + intComp.right.accept(this)) + */ + public Set visit(IntComparisonFormula intComp) { + Set ret = lookup(intComp); + if (ret!=null) return ret; + ret = newSet(); + ret.addAll(intComp.left().accept(this)); + ret.addAll(intComp.right().accept(this)); + return cache(intComp, ret); + } + + /** + * Calls lookup(quantFormula) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * union of the children's return values and returns it. + * @return let x = lookup(quantFormula) | + * x != null => x, + * cache(quantFormula, quantFormula.declarations.accept(this) + quantFormula.formula.accept(this)) + */ + public Set visit(QuantifiedFormula quantFormula) { + Set ret = lookup(quantFormula); + if (ret!=null) return ret; + ret = newSet(); + ret.addAll(quantFormula.decls().accept(this)); + ret.addAll(quantFormula.formula().accept(this)); + return cache(quantFormula, ret); + } + + /** + * Calls lookup(formula) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * union of the children's return values and returns it. + * @return let x = lookup(formula) | + * x != null => x, + * cache(formula, formula.child(0).accept(this) + .. + formula.child(formula.size()-1).accept(this)) + */ + public Set visit(NaryFormula formula) { + Set ret = lookup(formula); + if (ret!=null) return ret; + ret = newSet(); + for(Formula child : formula) { + ret.addAll(child.accept(this)); + } + return cache(formula, ret); + } + + /** + * Calls lookup(binFormula) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * union of the children's return values and returns it. + * @return let x = lookup(binFormula) | + * x != null => x, + * cache(binFormula, binFormula.left.accept(this) + binFormula.right.accept(this)) + */ + public Set visit(BinaryFormula binFormula) { + Set ret = lookup(binFormula); + if (ret!=null) return ret; + ret = newSet(); + ret.addAll(binFormula.left().accept(this)); + ret.addAll(binFormula.right().accept(this)); + return cache(binFormula, ret); + } + + /** + * Calls lookup(not) and returns the cached value, if any. + * If no cached value exists, visits the child, caches its return value and returns it. + * @return let x = lookup(not) | + * x != null => x, + * cache(not, not.formula.accept(this)) + */ + public Set visit(NotFormula not) { + Set ret = lookup(not); + if (ret!=null) return ret; + ret = newSet(); + ret.addAll(not.formula().accept(this)); + return cache(not, ret); + } + + /** + * Returns Collections.EMPTY_SET + * @return Collections.EMPTY_SET + */ + @SuppressWarnings("unchecked") + public Set visit(ConstantFormula constant) { + return Collections.EMPTY_SET; + } + + /** + * Calls lookup(compFormula) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * union of the children's return values and returns it. + * @return let x = lookup(compFormula) | + * x != null => x, + * cache(compFormula,compFormula.left.accept(this) + compFormula.right.accept(this)) + */ + public Set visit(ComparisonFormula compFormula) { + Set ret = lookup(compFormula); + if (ret!=null) return ret; + ret = newSet(); + ret.addAll(compFormula.left().accept(this)); + ret.addAll(compFormula.right().accept(this)); + return cache(compFormula, ret); + } + + /** + * Calls lookup(multFormula) and returns the cached value, if any. + * If no cached value exists, visits the child, caches its return value and returns it. + * @return let x = lookup(multFormula) | + * x != null => x, + * cache(multFormula, multFormula.expression.accept(this)) + */ + public Set visit(MultiplicityFormula multFormula) { + Set ret = lookup(multFormula); + if (ret!=null) return ret; + ret = newSet(); + ret.addAll(multFormula.expression().accept(this)); + return cache(multFormula, ret); + } + + /** + * Calls lookup(predicate) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * disjunction of the children's return values and returns it. + * @return let x = lookup(predicate) | + * x != null => x, + * cache(predicate, some n: predicate.children | n.accept(this)) + */ + public Set visit(RelationPredicate pred) { + Set ret = lookup(pred); + if (ret!=null) return ret; + ret = newSet(); + ret.addAll(pred.relation().accept(this)); + switch(pred.name()) { + case ACYCLIC : + break; + case FUNCTION : + final RelationPredicate.Function fp = (RelationPredicate.Function) pred; + ret.addAll(fp.domain().accept(this)); + ret.addAll(fp.range().accept(this)); + break; + case TOTAL_ORDERING : + final RelationPredicate.TotalOrdering tp = (RelationPredicate.TotalOrdering) pred; + ret.addAll(tp.ordered().accept(this)); + ret.addAll(tp.first().accept(this)); + ret.addAll(tp.last().accept(this)); + break; + default : + throw new IllegalArgumentException("unknown relation predicate: " + pred.name()); + } + return cache(pred,ret); + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/visitor/AbstractDetector.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/visitor/AbstractDetector.java new file mode 100644 index 00000000..1a039cae --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/visitor/AbstractDetector.java @@ -0,0 +1,480 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast.visitor; + +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.Set; + +import kodkod.ast.BinaryExpression; +import kodkod.ast.BinaryFormula; +import kodkod.ast.BinaryIntExpression; +import kodkod.ast.ComparisonFormula; +import kodkod.ast.Comprehension; +import kodkod.ast.ConstantExpression; +import kodkod.ast.ConstantFormula; +import kodkod.ast.Decl; +import kodkod.ast.Decls; +import kodkod.ast.ExprToIntCast; +import kodkod.ast.Expression; +import kodkod.ast.Formula; +import kodkod.ast.IfExpression; +import kodkod.ast.IfIntExpression; +import kodkod.ast.IntComparisonFormula; +import kodkod.ast.IntConstant; +import kodkod.ast.IntExpression; +import kodkod.ast.IntToExprCast; +import kodkod.ast.MultiplicityFormula; +import kodkod.ast.NaryExpression; +import kodkod.ast.NaryFormula; +import kodkod.ast.NaryIntExpression; +import kodkod.ast.Node; +import kodkod.ast.NotFormula; +import kodkod.ast.ProjectExpression; +import kodkod.ast.QuantifiedFormula; +import kodkod.ast.Relation; +import kodkod.ast.RelationPredicate; +import kodkod.ast.SumExpression; +import kodkod.ast.UnaryExpression; +import kodkod.ast.UnaryIntExpression; +import kodkod.ast.Variable; + +/** + *

A depth first detector. Subclasses should override the + * methods in which detection is performed to return TRUE. + * For example, a Variable detector could be implemented + * simply by subclassing this implementation and overriding + * the {@link #visit(Variable) } method to return TRUE.

+ * + * @specfield cached: set Node // result of visiting these nodes will be cached + * @specfield cache: Node -> lone Boolean + * @specfield cached in cache.Node + * @author Emina Torlak + */ +public abstract class AbstractDetector implements ReturnVisitor { + protected final Map cache; + protected final Set cached; + + /** + * Constructs a depth first detector which will cache the results + * of visiting the given nodes and re-use them on subsequent visits. + * @ensures this.cached' = cached && no this.cache + */ + protected AbstractDetector(Set cached) { + this.cached = cached; + this.cache = new IdentityHashMap(cached.size()); + } + + /** + * Constructs a depth-first detector which will cache + * the results of visiting the given nodes in the given map, + * and re-use them on subsequent visits. + * @ensures this.cached' = cached && this.cache' = cache + */ + protected AbstractDetector(Set cached, Map cache) { + this.cached = cached; + this.cache = cache; + } + + + /** + * If n has been visited and a value for it cached, + * the cached value is returned. Otherwise null is returned. + * @return this.cache[n] + */ + protected Boolean lookup(Node n) { + return cache.get(n); + } + + /** + * Caches the given value for the specified node, if + * this is a caching visitor, and returns Boolean.valueOf(val). + * @ensures n in this.cached => this.cache' = this.cache ++ n->Boolean.valueOf(val), this.cache' = this.cache + * @return Boolean.valueOf(val) + */ + protected Boolean cache(Node n, boolean val) { + final Boolean ret = Boolean.valueOf(val); + if (cached.contains(n)) + cache.put(n, ret); + return ret; + } + + /** + * Calls lookup(decls) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * disjunction of the children's return values and returns it. + * @return let x = lookup(decls) | + * x != null => x, + * cache(decls, some d: decls.declarations | d.accept(this)) + */ + public Boolean visit(Decls decls) { + final Boolean ret = lookup(decls); + if (ret!=null) return ret; + for(Decl d : decls) { + if (visit(d)) + return cache(decls, true); + } + return cache(decls, false); + } + + /** + * Calls lookup(decl) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * disjunction of the children's return values and returns it. + * @return let x = lookup(decl) | + * x != null => x, + * cache(decl, decl.variable.accept(this) || decl.expression.accept(this)) + */ + public Boolean visit(Decl decl) { + final Boolean ret = lookup(decl); + return (ret!=null) ? ret : cache(decl, decl.variable().accept(this) || decl.expression().accept(this)); + } + + /** + * Returns FALSE. + * @return FALSE + */ + public Boolean visit(Relation relation) { return Boolean.FALSE; } + + /** + * Returns FALSE. + * @return FALSE + */ + public Boolean visit(Variable variable) { return Boolean.FALSE; } + + /** + * Returns FALSE. + * @return FALSE + */ + public Boolean visit(ConstantExpression expr) { return Boolean.FALSE; } + + /** + * Calls lookup(expr) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * disjunction of the children's return values and returns it. + * @return let x = lookup(expr) | + * x != null => x, + * cache(expr, expr.child(0).accept(this) || ... || expr.child(expr.size()-1).accept(this)) + */ + public Boolean visit(NaryExpression expr) { + final Boolean ret = lookup(expr); + if (ret!=null) return ret; + for(Expression child : expr) { + if (child.accept(this)) + return cache(expr, true); + } + return cache(expr, false); + } + + /** + * Calls lookup(binExpr) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * disjunction of the children's return values and returns it. + * @return let x = lookup(binExpr) | + * x != null => x, + * cache(binExpr, binExpr.left.accept(this) || binExpr.right.accept(this)) + */ + public Boolean visit(BinaryExpression binExpr) { + final Boolean ret = lookup(binExpr); + return (ret!=null) ? ret : cache(binExpr, binExpr.left().accept(this) || binExpr.right().accept(this)); + } + + /** + * Calls lookup(expr) and returns the cached value, if any. + * If no cached value exists, visits the child, caches its return value and returns it. + * @return let x = lookup(expr) | + * x != null => x, + * cache(expr, expr.expression.accept(this)) + */ + public Boolean visit(UnaryExpression expr) { + final Boolean ret = lookup(expr); + return (ret!=null) ? ret : cache(expr, expr.expression().accept(this)); + } + + /** + * Calls lookup(expr) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * disjunction of the children's return values and returns it. + * @return let x = lookup(expr) | + * x != null => x, + * cache(expr, expr.decls.accept(this) || expr.formula.accept(this)) + */ + public Boolean visit(Comprehension expr) { + final Boolean ret = lookup(expr); + return (ret!=null) ? ret : cache(expr, expr.decls().accept(this) || expr.formula().accept(this)); + } + + /** + * Calls lookup(expr) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * disjunction of the children's return values and returns it. + * @return let x = lookup(expr) | + * x != null => x, + * cache(expr, expr.condition.accept(this) || expr.thenExpr.accept(this) || expr.elseExpr.accept(this)) + */ + public Boolean visit(IfExpression expr) { + final Boolean ret = lookup(expr); + return (ret!=null) ? ret : cache(expr, expr.condition().accept(this) || expr.thenExpr().accept(this) || expr.elseExpr().accept(this)); + } + + /** + * Calls lookup(project) and returns the cached value, if any. If no cached + * value exists, visits each child, caches the disjunction of the children's return + * values and returns it. + * @return let x = lookup(project) | + * x != null => x, + * cache(project, project.expression.accept(this) || project.columns[int].accept(this)) + */ + public Boolean visit(ProjectExpression project) { + final Boolean ret = lookup(project); + if (ret!=null) return ret; + if (project.expression().accept(this)) + return cache(project, true); + for(int i = 0, arity = project.arity(); i < arity; i++) { + if (project.column(i).accept(this)) + return cache(project, true); + } + return cache(project, false); + } + + /** + * Calls lookup(castExpr) and returns the cached value, if any. + * If no cached value exists, visits the child, caches its return value and returns it. + * @return let x = lookup(castExpr) | + * x != null => x, + * cache(intExpr, castExpr.intExpr.accept(this)) + */ + public Boolean visit(IntToExprCast castExpr) { + final Boolean ret = lookup(castExpr); + return (ret!=null) ? ret : cache(castExpr, castExpr.intExpr().accept(this)); + } + + /** + * Returns FALSE. + * @return FALSE + */ + public Boolean visit(IntConstant intConst) { return Boolean.FALSE; } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * disjunction of the children's return values and returns it. + * @return let x = lookup(intExpr) | + * x != null => x, + * cache(intExpr, intExpr.condition.accept(this) || intExpr.thenExpr.accept(this) || intExpr.elseExpr.accept(this)) + */ + public Boolean visit(IfIntExpression intExpr) { + final Boolean ret = lookup(intExpr); + return (ret!=null) ? ret : cache(intExpr, intExpr.condition().accept(this) || intExpr.thenExpr().accept(this) || intExpr.elseExpr().accept(this)); + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If no cached value exists, visits the child, caches its return value and returns it. + * @return let x = lookup(intExpr) | + * x != null => x, + * cache(intExpr, intExpr.expression.accept(this)) + */ + public Boolean visit(ExprToIntCast intExpr) { + final Boolean ret = lookup(intExpr); + return (ret!=null) ? ret : cache(intExpr, intExpr.expression().accept(this)); + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * disjunction of the children's return values and returns it. + * @return let x = lookup(intExpr) | + * x != null => x, + * cache(intExpr, intExpr.child(0).accept(this) || ... || intExpr.child(intExpr.size()-1).accept(this)) + */ + public Boolean visit(NaryIntExpression intExpr) { + final Boolean ret = lookup(intExpr); + if (ret!=null) return ret; + for(IntExpression child : intExpr) { + if (child.accept(this)) + return cache(intExpr, true); + } + return cache(intExpr, false); + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * disjunction of the children's return values and returns it. + * @return let x = lookup(intExpr) | + * x != null => x, + * cache(intExpr, intExpr.left.accept(this) || intExpr.right.accept(this)) + */ + public Boolean visit(BinaryIntExpression intExpr) { + final Boolean ret = lookup(intExpr); + return (ret!=null) ? ret : cache(intExpr, intExpr.left().accept(this) || intExpr.right().accept(this)); + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If no cached value exists, visits the child, caches its return value and returns it. + * @return let x = lookup(intExpr) | + * x != null => x, + * cache(intExpr, intExpr.expression.accept(this)) + */ + public Boolean visit(UnaryIntExpression intExpr) { + final Boolean ret = lookup(intExpr); + return (ret!=null) ? ret : cache(intExpr, intExpr.intExpr().accept(this)); + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * disjunction of the children's return values and returns it. + * @return let x = lookup(intExpr) | + * x != null => x, + * cache(intExpr, intExpr.decls.accept(this) || intExpr.intExpr.accept(this)) + */ + public Boolean visit(SumExpression intExpr) { + final Boolean ret = lookup(intExpr); + return (ret!=null) ? ret : cache(intExpr, intExpr.decls().accept(this) || intExpr.intExpr().accept(this)); + } + + /** + * Calls lookup(intComp) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * disjunction of the children's return values and returns it. + * @return let x = lookup(intComp) | + * x != null => x, + * cache(intComp, intComp.left.accept(this) || intComp.right.accept(this)) + */ + public Boolean visit(IntComparisonFormula intComp) { + final Boolean ret = lookup(intComp); + return (ret!=null) ? ret : cache(intComp, intComp.left().accept(this) || intComp.right().accept(this)); + } + + /** + * Calls lookup(quantFormula) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * disjunction of the children's return values and returns it. + * @return let x = lookup(quantFormula) | + * x != null => x, + * cache(quantFormula, quantFormula.declarations.accept(this) ||quantFormula.formula.accept(this)) + */ + public Boolean visit(QuantifiedFormula quantFormula) { + final Boolean ret = lookup(quantFormula); + return (ret!=null) ? ret : cache(quantFormula, quantFormula.decls().accept(this) || quantFormula.formula().accept(this)); + } + + /** + * Calls lookup(formula) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * disjunction of the children's return values and returns it. + * @return let x = lookup(formula) | + * x != null => x, + * cache(formula, formula.child(0).accept(this) || ... || formula.child(formula.size()-1).accept(this)) + */ + public Boolean visit(NaryFormula formula) { + final Boolean ret = lookup(formula); + if (ret!=null) return ret; + for(Formula child : formula) { + if (child.accept(this)) + return cache(formula, true); + } + return cache(formula, false); + } + + /** + * Calls lookup(binFormula) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * disjunction of the children's return values and returns it. + * @return let x = lookup(binFormula) | + * x != null => x, + * cache(binFormula, binFormula.left.accept(this) || binFormula.right.accept(this)) + */ + public Boolean visit(BinaryFormula binFormula) { + final Boolean ret = lookup(binFormula); + return (ret!=null) ? ret : cache(binFormula, binFormula.left().accept(this) || binFormula.right().accept(this)); + } + + /** + * Calls lookup(not) and returns the cached value, if any. + * If no cached value exists, visits the child, caches its return value and returns it. + * @return let x = lookup(not) | + * x != null => x, + * cache(not, not.formula.accept(this)) + */ + public Boolean visit(NotFormula not) { + final Boolean ret = lookup(not); + return (ret!=null) ? ret : cache(not, not.formula().accept(this)); + } + + /** + * Returns FALSE. + * @return FALSE + */ + public Boolean visit(ConstantFormula constant) { return Boolean.FALSE; } + + /** + * Calls lookup(exprComp) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * disjunction of the children's return values and returns it. + * @return let x = lookup(exprComp) | + * x != null => x, + * cache(exprComp,exprComp.left.accept(this) || exprComp.right.accept(this)) + */ + public Boolean visit(ComparisonFormula exprComp) { + final Boolean ret = lookup(exprComp); + return (ret!=null) ? ret : cache(exprComp, exprComp.left().accept(this) || exprComp.right().accept(this)); + } + + /** + * Calls lookup(multFormula) and returns the cached value, if any. + * If no cached value exists, visits the child, caches its return value and returns it. + * @return let x = lookup(multFormula) | + * x != null => x, + * cache(multFormula, multFormula.expression.accept(this)) + */ + public Boolean visit(MultiplicityFormula multFormula) { + final Boolean ret = lookup(multFormula); + return (ret!=null) ? ret : cache(multFormula, multFormula.expression().accept(this)); + } + + /** + * Calls lookup(predicate) and returns the cached value, if any. + * If no cached value exists, visits each child, caches the + * disjunction of the children's return values and returns it. + * @return let x = lookup(predicate) | + * x != null => x, + * cache(predicate, some n: predicate.children | n.accept(this)) + */ + public Boolean visit(RelationPredicate predicate) { + final Boolean ret = lookup(predicate); + if (ret!=null) return ret; + if (predicate.relation().accept(this)) + return cache(predicate, true); + if (predicate.name()==RelationPredicate.Name.FUNCTION) { + final RelationPredicate.Function fp = (RelationPredicate.Function) predicate; + return cache(predicate, fp.domain().accept(this) || fp.range().accept(this)); + } else if (predicate.name()==RelationPredicate.Name.TOTAL_ORDERING) { + final RelationPredicate.TotalOrdering tp = (RelationPredicate.TotalOrdering) predicate; + return cache(predicate, tp.ordered().accept(this) || tp.first().accept(this) || tp.last().accept(this)); + } + return cache(predicate, false); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/visitor/AbstractReplacer.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/visitor/AbstractReplacer.java new file mode 100644 index 00000000..a2b1aba9 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/visitor/AbstractReplacer.java @@ -0,0 +1,649 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast.visitor; + +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.Set; + +import kodkod.ast.BinaryExpression; +import kodkod.ast.BinaryFormula; +import kodkod.ast.BinaryIntExpression; +import kodkod.ast.ComparisonFormula; +import kodkod.ast.Comprehension; +import kodkod.ast.ConstantExpression; +import kodkod.ast.ConstantFormula; +import kodkod.ast.Decl; +import kodkod.ast.Decls; +import kodkod.ast.ExprToIntCast; +import kodkod.ast.Expression; +import kodkod.ast.Formula; +import kodkod.ast.IfExpression; +import kodkod.ast.IfIntExpression; +import kodkod.ast.IntComparisonFormula; +import kodkod.ast.IntConstant; +import kodkod.ast.IntExpression; +import kodkod.ast.IntToExprCast; +import kodkod.ast.MultiplicityFormula; +import kodkod.ast.NaryExpression; +import kodkod.ast.NaryFormula; +import kodkod.ast.NaryIntExpression; +import kodkod.ast.Node; +import kodkod.ast.NotFormula; +import kodkod.ast.ProjectExpression; +import kodkod.ast.QuantifiedFormula; +import kodkod.ast.Relation; +import kodkod.ast.RelationPredicate; +import kodkod.ast.SumExpression; +import kodkod.ast.UnaryExpression; +import kodkod.ast.UnaryIntExpression; +import kodkod.ast.Variable; +import kodkod.ast.operator.Multiplicity; + +/** + * A depth first replacer. The default implementation + * returns the tree to which it is applied. Reference + * equality is used to determine if two nodes are the same. + * + * @specfield cached: set Node // result of visiting these nodes will be cached + * @specfield cache: Node ->lone Node + * @invariant cached in cache.Node + * @author Emina Torlak + */ +public abstract class AbstractReplacer implements ReturnVisitor { + protected final Map cache; + protected final Set cached; + + /** + * Constructs a depth-first replaces which will cache + * the results of visiting the given nodes and re-use them + * on subsequent visits. + * @ensures this.cached' = cached && no this.cache' + */ + protected AbstractReplacer(Set cached) { + this.cached = cached; + this.cache = new IdentityHashMap(cached.size()); + } + + /** + * Constructs a depth-first replacer which will cache + * the results of visiting the given nodes in the given map, + * and re-use them on subsequent visits. + * @ensures this.cached' = cached && this.cache' = cache + */ + protected AbstractReplacer(Set cached, Map cache) { + this.cached = cached; + this.cache = cache; + } + + + /** + * If the given node has already been visited and its replacement + * cached, the cached value is returned. Otherwise, null is returned. + * @return this.cache[node] + */ + @SuppressWarnings("unchecked") + protected N lookup(N node) { + return (N) cache.get(node); + } + + /** + * Caches the given replacement for the specified node, if this is + * a caching visitor. Otherwise does nothing. The method returns + * the replacement node. + * @ensures node in this.cached => this.cache' = this.cache ++ node->replacement, + * this.cache' = this.cache + * @return replacement + */ + protected N cache(N node, N replacement) { + if (cached.contains(node)) { + cache.put(node, replacement); + } + return replacement; + } + + /** + * Calls lookup(decls) and returns the cached value, if any. + * If a replacement has not been cached, visits each of the children's + * variable and expression. If nothing changes, the argument is cached and + * returned, otherwise a replacement Decls object is cached and returned. + * @return { d: Decls | d.size = decls.size && + * all i: [0..d.size) | d.declarations[i] = decls.declarations[i].accept(this) } + */ + public Decls visit(Decls decls) { + Decls ret = lookup(decls); + if (ret!=null) return ret; + + Decls visitedDecls = null; + boolean allSame = true; + for(Decl decl : decls) { + Decls newDecl = visit(decl); + if (newDecl != decl) + allSame = false; + visitedDecls = (visitedDecls==null) ? newDecl : visitedDecls.and(newDecl); + } + ret = allSame ? decls : visitedDecls; + return cache(decls, ret); + } + + /** + * Calls lookup(decl) and returns the cached value, if any. + * If a replacement has not been cached, visits the declaration's + * variable and expression. If nothing changes, the argument is cached and + * returned, otherwise a replacement Decl object is cached and returned. + * @return { d: Declaration | d.variable = declaration.variable.accept(this) && + * d.multiplicity = decl.multiplicity && + * d.expression = declaration.expression.accept(this) + */ + public Decl visit(Decl decl) { + Decl ret = lookup(decl); + if (ret!=null) return ret; + + final Variable variable = (Variable) decl.variable().accept(this); + final Expression expression = decl.expression().accept(this); + ret = (variable==decl.variable() && expression==decl.expression()) ? + decl : variable.declare(decl.multiplicity(), expression); + return cache(decl,ret); + } + + /** + * Calls lookup(relation) and returns the cached value, if any. + * If a replacement has not been cached, the relation is cached and + * returned. + * @return relation + */ + public Expression visit(Relation relation) { + final Expression ret = lookup(relation); + return ret==null ? cache(relation,relation) : ret; + } + + /** + * Calls lookup(variable) and returns the cached value, if any. + * If a replacement has not been cached, the variable is cached and + * returned. + * @return variable + */ + public Expression visit(Variable variable) { + final Expression ret = lookup(variable); + return ret==null ? cache(variable,variable) : variable; + } + + /** + * Calls lookup(constExpr) and returns the cached value, if any. + * If a replacement has not been cached, the constExpr is cached and + * returned. + * @return constExpr + */ + public Expression visit(ConstantExpression constExpr) { + final Expression ret = lookup(constExpr); + return ret==null ? cache(constExpr,constExpr) : constExpr; + } + + /** + * Calls lookup(expr) and returns the cached value, if any. + * If a replacement has not been cached, visits the expr's + * children. If nothing changes, the argument is cached and + * returned, otherwise a replacement expr is cached and returned. + * @return { e: Expression | e.op = expr.op && #e.children = #expr.children && all i: [0..expr.children) | e.child(i) = expr.child(i).accept(this) } + */ + public Expression visit(NaryExpression expr) { + Expression ret = lookup(expr); + if (ret!=null) return ret; + + final Expression[] visited = new Expression[expr.size()]; + boolean allSame = true; + for(int i = 0 ; i < visited.length; i++) { + final Expression child = expr.child(i); + visited[i] = child.accept(this); + allSame = allSame && visited[i]==child; + } + + ret = allSame ? expr : Expression.compose(expr.op(), visited); + return cache(expr,ret); + } + + /** + * Calls lookup(binExpr) and returns the cached value, if any. + * If a replacement has not been cached, visits the expression's + * children. If nothing changes, the argument is cached and + * returned, otherwise a replacement expression is cached and returned. + * @return { b: BinaryExpression | b.left = binExpr.left.accept(this) && + * b.right = binExpr.right.accept(this) && b.op = binExpr.op } + */ + public Expression visit(BinaryExpression binExpr) { + Expression ret = lookup(binExpr); + if (ret!=null) return ret; + + final Expression left = binExpr.left().accept(this); + final Expression right = binExpr.right().accept(this); + ret = (left==binExpr.left() && right==binExpr.right()) ? + binExpr : left.compose(binExpr.op(), right); + return cache(binExpr,ret); + } + + /** + * Calls lookup(unaryExpr) and returns the cached value, if any. + * If a replacement has not been cached, visits the expression's + * child. If nothing changes, the argument is cached and + * returned, otherwise a replacement expression is cached and returned. + * @return { u: UnaryExpression | u.left = unaryExpr.expression.accept(this) && u.op = unaryExpr.op } + */ + public Expression visit(UnaryExpression unaryExpr) { + Expression ret = lookup(unaryExpr); + if (ret!=null) return ret; + + final Expression child = unaryExpr.expression().accept(this); + ret = (child==unaryExpr.expression()) ? + unaryExpr : child.apply(unaryExpr.op()); + return cache(unaryExpr,ret); + } + + /** + * Calls lookup(comprehension) and returns the cached value, if any. + * If a replacement has not been cached, visits the expression's + * children. If nothing changes, the argument is cached and + * returned, otherwise a replacement expression is cached and returned. + * @return { c: Comprehension | c.declarations = comprehension.declarations.accept(this) && + * c.formula = comprehension.formula.accept(this) } + */ + public Expression visit(Comprehension comprehension) { + Expression ret = lookup(comprehension); + if (ret!=null) return ret; + + final Decls decls = (Decls)comprehension.decls().accept(this); + final Formula formula = comprehension.formula().accept(this); + ret = (decls==comprehension.decls() && formula==comprehension.formula()) ? + comprehension : formula.comprehension(decls); + return cache(comprehension,ret); + } + + + /** + * Calls lookup(ifExpr) and returns the cached value, if any. + * If a replacement has not been cached, visits the expression's + * children. If nothing changes, the argument is cached and + * returned, otherwise a replacement expression is cached and returned. + * @return { i: IfExpression | i.condition = ifExpr.condition.accept(this) && + * i.thenExpr = ifExpr.thenExpr.accept(this) && + * i.elseExpr = ifExpr.elseExpr.accept(this) } + */ + public Expression visit(IfExpression ifExpr) { + Expression ret = lookup(ifExpr); + if (ret!=null) return ret; + + final Formula condition = ifExpr.condition().accept(this); + final Expression thenExpr = ifExpr.thenExpr().accept(this); + final Expression elseExpr = ifExpr.elseExpr().accept(this); + ret = (condition==ifExpr.condition() && thenExpr==ifExpr.thenExpr() && + elseExpr==ifExpr.elseExpr()) ? + ifExpr : condition.thenElse(thenExpr, elseExpr); + return cache(ifExpr,ret); + } + + /** + * Calls lookup(decls) and returns the cached value, if any. + * If a replacement has not been cached, visits each of the children's + * variable and expression. If nothing changes, the argument is cached and + * returned, otherwise a replacement Decls object is cached and returned. + * @return { d: Decls | d.size = decls.size && + * all i: [0..d.size) | d.declarations[i] = decls.declarations[i].accept(this) } + */ + public Expression visit(ProjectExpression project) { + Expression ret = lookup(project); + if (ret!=null) return ret; + + final Expression expr = project.expression().accept(this); + final IntExpression[] cols = new IntExpression[project.arity()]; + boolean allSame = expr==project.expression(); + for(int i = 0, arity = project.arity(); i < arity; i++) { + cols[i] = project.column(i).accept(this); + allSame = allSame && (cols[i]==project.column(i)); + } + ret = allSame ? project : expr.project(cols); + return cache(project, ret); + } + /** + * Calls lookup(castExpr) and returns the cached value, if any. If a replacement + * has not been cached, visits the expression's child. If nothing changes, the argument + * is cached and returned, otherwise a replacement expression is cached and returned. + * @return { e: Expression | e = castExpr.intExpr.accept(this).toExpression() } + */ + public Expression visit(IntToExprCast castExpr) { + Expression ret = lookup(castExpr); + if (ret!=null) return ret; + + final IntExpression intExpr = castExpr.intExpr().accept(this); + ret = (intExpr==castExpr.intExpr()) ? castExpr : intExpr.cast(castExpr.op()); + return cache(castExpr, ret); + } + + /** + * Calls lookup(intconst) and returns the cached value, if any. + * If a replacement has not been cached, the constant is cached and returned. + * @return intconst + */ + public IntExpression visit(IntConstant intconst) { + IntExpression ret = lookup(intconst); + return ret==null ? cache(intconst, intconst) : intconst; + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If a replacement has not been cached, visits the expression's + * children. If nothing changes, the argument is cached and + * returned, otherwise a replacement expression is cached and returned. + * @return { i: IfIntExpression | i.condition = intExpr.condition.accept(this) && + * i.thenExpr = intExpr.thenExpr.accept(this) && + * i.elseExpr = intExpr.elseExpr.accept(this) } + */ + public IntExpression visit(IfIntExpression intExpr) { + IntExpression ret = lookup(intExpr); + if (ret!=null) return ret; + + final Formula condition = intExpr.condition().accept(this); + final IntExpression thenExpr = intExpr.thenExpr().accept(this); + final IntExpression elseExpr = intExpr.elseExpr().accept(this); + ret = (condition==intExpr.condition() && thenExpr==intExpr.thenExpr() && + elseExpr==intExpr.elseExpr()) ? + intExpr : condition.thenElse(thenExpr, elseExpr); + return cache(intExpr,ret); + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If a replacement has not been cached, visits the expression's + * child. If nothing changes, the argument is cached and + * returned, otherwise a replacement expression is cached and returned. + * @return { i: ExprToIntCast | i.expression = intExpr.expression.accept(this) && i.op = intExpr.op} + */ + public IntExpression visit(ExprToIntCast intExpr) { + IntExpression ret = lookup(intExpr); + if (ret!=null) return ret; + + final Expression expr = intExpr.expression().accept(this); + ret = expr==intExpr.expression() ? intExpr : expr.apply(intExpr.op()); + return cache(intExpr, ret); + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If a replacement has not been cached, visits the intExpr's + * children. If nothing changes, the argument is cached and + * returned, otherwise a replacement intExpr is cached and returned. + * @return { e: IntExpression | e.op = intExpr.op && #e.children = #intExpr.children && all i: [0..intExpr.children) | e.child(i) = intExpr.child(i).accept(this) } + */ + public IntExpression visit(NaryIntExpression intExpr) { + IntExpression ret = lookup(intExpr); + if (ret!=null) return ret; + + final IntExpression[] visited = new IntExpression[intExpr.size()]; + boolean allSame = true; + for(int i = 0 ; i < visited.length; i++) { + final IntExpression child = intExpr.child(i); + visited[i] = child.accept(this); + allSame = allSame && visited[i]==child; + } + + ret = allSame ? intExpr : IntExpression.compose(intExpr.op(), visited); + return cache(intExpr,ret); + } + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If a replacement has not been cached, visits the expression's + * children. If nothing changes, the argument is cached and + * returned, otherwise a replacement expression is cached and returned. + * @return { c: IntExpression | [[c]] = intExpr.left.accept(this) op intExpr.right.accept(this) } + */ + public IntExpression visit(BinaryIntExpression intExpr) { + IntExpression ret = lookup(intExpr); + if (ret!=null) return ret; + + final IntExpression left = intExpr.left().accept(this); + final IntExpression right = intExpr.right().accept(this); + ret = (left==intExpr.left() && right==intExpr.right()) ? + intExpr : left.compose(intExpr.op(), right); + return cache(intExpr,ret); + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If a replacement has not been cached, visits the expression's + * child. If nothing changes, the argument is cached and + * returned, otherwise a replacement expression is cached and returned. + * @return { u: UnaryIntExpression | u.expression = intExpr.expression.accept(this) && u.op = intExpr.op } + */ + public IntExpression visit(UnaryIntExpression intExpr) { + IntExpression ret = lookup(intExpr); + if (ret!=null) return ret; + + final IntExpression child = intExpr.intExpr().accept(this); + ret = (child==intExpr.intExpr()) ? intExpr : child.apply(intExpr.op()); + return cache(intExpr,ret); + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If a replacement has not been cached, visits the expression's + * children. If nothing changes, the argument is cached and + * returned, otherwise a replacement expression is cached and returned. + * @return { c: IntExpression | [[c]] = sum intExpr.decls.accept(this) | intExpr.intExpr.accept(this) } + */ + public IntExpression visit(SumExpression intExpr) { + IntExpression ret = lookup(intExpr); + if (ret!=null) return ret; + + final Decls decls = intExpr.decls().accept(this); + final IntExpression expr = intExpr.intExpr().accept(this); + ret = (decls==intExpr.decls() && expr==intExpr.intExpr()) ? + intExpr : expr.sum(decls); + return cache(intExpr,ret); + } + + /** + * Calls lookup(intComp) and returns the cached value, if any. + * If a replacement has not been cached, visits the formula's + * children. If nothing changes, the argument is cached and + * returned, otherwise a replacement formula is cached and returned. + * @return { c: Formula | [[c]] = intComp.left.accept(this) op intComp.right.accept(this) } + */ + public Formula visit(IntComparisonFormula intComp) { + Formula ret = lookup(intComp); + if (ret!=null) return ret; + + final IntExpression left = intComp.left().accept(this); + final IntExpression right = intComp.right().accept(this); + ret = (left==intComp.left() && right==intComp.right()) ? + intComp : left.compare(intComp.op(), right); + return cache(intComp,ret); + } + + /** + * Calls lookup(constant) and returns the cached value, if any. + * If a replacement has not been cached, the constant is cached and + * returned. + * @return constant + */ + public Formula visit(ConstantFormula constant) { + final Formula ret = lookup(constant); + return ret==null ? cache(constant,constant) : constant; + } + + /** + * Calls lookup(quantFormula) and returns the cached value, if any. + * If a replacement has not been cached, visits the formula's + * children. If nothing changes, the argument is cached and + * returned, otherwise a replacement formula is cached and returned. + * @return { q: QuantifiedFormula | q.declarations = quantFormula.declarations.accept(this) && + * q.formula = quantFormula.formula.accept(this) } + */ + public Formula visit(QuantifiedFormula quantFormula) { + Formula ret = lookup(quantFormula); + if (ret!=null) return ret; + + final Decls decls = (Decls)quantFormula.decls().accept(this); + final Formula formula = quantFormula.formula().accept(this); + ret = (decls==quantFormula.decls() && formula==quantFormula.formula()) ? + quantFormula : formula.quantify(quantFormula.quantifier(), decls); + return cache(quantFormula,ret); + } + + /** + * Calls lookup(formula) and returns the cached value, if any. + * If a replacement has not been cached, visits the formula's + * children. If nothing changes, the argument is cached and + * returned, otherwise a replacement formula is cached and returned. + * @return { e: Expression | e.op = formula.op && #e.children = #formula.children && all i: [0..formula.children) | e.child(i) = formula.child(i).accept(this) } + */ + public Formula visit(NaryFormula formula) { + Formula ret = lookup(formula); + if (ret!=null) return ret; + + final Formula[] visited = new Formula[formula.size()]; + boolean allSame = true; + for(int i = 0 ; i < visited.length; i++) { + final Formula child = formula.child(i); + visited[i] = child.accept(this); + allSame = allSame && visited[i]==child; + } + + ret = allSame ? formula : Formula.compose(formula.op(), visited); + return cache(formula,ret); + } + + /** + * Calls lookup(binFormula) and returns the cached value, if any. + * If a replacement has not been cached, visits the formula's + * children. If nothing changes, the argument is cached and + * returned, otherwise a replacement formula is cached and returned. + * @return { b: BinaryFormula | b.left = binExpr.left.accept(this) && + * b.right = binExpr.right.accept(this) && b.op = binExpr.op } + */ + public Formula visit(BinaryFormula binFormula) { + Formula ret = lookup(binFormula); + if (ret!=null) return ret; + + final Formula left = binFormula.left().accept(this); + final Formula right = binFormula.right().accept(this); + ret = (left==binFormula.left() && right==binFormula.right()) ? + binFormula : left.compose(binFormula.op(), right); + return cache(binFormula,ret); + } + + /** + * Calls lookup(binFormula) and returns the cached value, if any. + * If a replacement has not been cached, visits the formula's + * child. If nothing changes, the argument is cached and + * returned, otherwise a replacement formula is cached and returned. + * @return { n: NotFormula | n.child = not.child.accept(this) } + */ + public Formula visit(NotFormula not) { + Formula ret = lookup(not); + if (ret!=null) return ret; + + final Formula child = not.formula().accept(this); + ret = (child==not.formula()) ? not : child.not(); + return cache(not,ret); + } + + /** + * Calls lookup(compFormula) and returns the cached value, if any. + * If a replacement has not been cached, visits the formula's + * children. If nothing changes, the argument is cached and + * returned, otherwise a replacement formula is cached and returned. + * @return { c: ComparisonFormula | c.left = compFormula.left.accept(this) && + * c.right = compFormula.right.accept(this) && + * c.op = compFormula.op } + */ + public Formula visit(ComparisonFormula compFormula) { + Formula ret = lookup(compFormula); + if (ret!=null) return ret; + + final Expression left = compFormula.left().accept(this); + final Expression right = compFormula.right().accept(this); + ret = (left==compFormula.left() && right==compFormula.right()) ? + compFormula : left.compare(compFormula.op(), right); + return cache(compFormula,ret); + } + + /** + * Calls lookup(multFormula) and returns the cached value, if any. + * If a replacement has not been cached, visits the formula's + * children. If nothing changes, the argument is cached and + * returned, otherwise a replacement formula is cached and returned. + * @return { m: MultiplicityFormula | m.multiplicity = multFormula.multiplicity && + * m.expression = multFormula.expression.accept(this) } + */ + public Formula visit(MultiplicityFormula multFormula) { + Formula ret = lookup(multFormula); + if (ret!=null) return ret; + + final Expression expression = multFormula.expression().accept(this); + ret = (expression==multFormula.expression()) ? + multFormula : expression.apply(multFormula.multiplicity()); + return cache(multFormula,ret); + } + + /** + * Calls lookup(pred) and returns the cached value, if any. + * If a replacement has not been cached, visits the formula's + * children. If nothing changes, the argument is cached and + * returned, otherwise a replacement formula is cached and returned. + * @return { p: RelationPredicate | p.name = pred.name && p.relation = pred.relation.accept(this) && + * p.name = FUNCTION => p.targetMult = pred.targetMult && + * p.domain = pred.domain.accept(this) && + * p.range = pred.range.accept(this), + * p.name = TOTAL_ORDERING => p.ordered = pred.ordered.accept(this) && + * p.first = pred.first.accept(this) && + * p.last = pred.last.accept(this) } + */ + public Formula visit(RelationPredicate pred) { + Formula ret = lookup(pred); + if (ret!=null) return ret; + + final Relation r = (Relation)pred.relation().accept(this); + switch(pred.name()) { + case ACYCLIC : + ret = (r==pred.relation()) ? pred : r.acyclic(); + break; + case FUNCTION : + final RelationPredicate.Function fp = (RelationPredicate.Function) pred; + final Expression domain = fp.domain().accept(this); + final Expression range = fp.range().accept(this); + ret = (r==fp.relation() && domain==fp.domain() && range==fp.range()) ? + fp : + (fp.targetMult()==Multiplicity.ONE ? r.function(domain, range) : r.partialFunction(domain,range)); + break; + case TOTAL_ORDERING : + final RelationPredicate.TotalOrdering tp = (RelationPredicate.TotalOrdering) pred; + final Relation ordered = (Relation) tp.ordered().accept(this); + final Relation first = (Relation)tp.first().accept(this); + final Relation last = (Relation)tp.last().accept(this); + ret = (r==tp.relation() && ordered==tp.ordered() && first==tp.first() && last==tp.last()) ? + tp : r.totalOrder(ordered, first, last); + break; + default : + throw new IllegalArgumentException("unknown relation predicate: " + pred.name()); + } + return cache(pred,ret); + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/visitor/AbstractVoidVisitor.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/visitor/AbstractVoidVisitor.java new file mode 100644 index 00000000..95be3e97 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/visitor/AbstractVoidVisitor.java @@ -0,0 +1,364 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast.visitor; + +import kodkod.ast.BinaryExpression; +import kodkod.ast.BinaryFormula; +import kodkod.ast.BinaryIntExpression; +import kodkod.ast.ComparisonFormula; +import kodkod.ast.Comprehension; +import kodkod.ast.ConstantExpression; +import kodkod.ast.ConstantFormula; +import kodkod.ast.Decl; +import kodkod.ast.Decls; +import kodkod.ast.ExprToIntCast; +import kodkod.ast.Expression; +import kodkod.ast.Formula; +import kodkod.ast.IfExpression; +import kodkod.ast.IfIntExpression; +import kodkod.ast.IntComparisonFormula; +import kodkod.ast.IntConstant; +import kodkod.ast.IntExpression; +import kodkod.ast.IntToExprCast; +import kodkod.ast.MultiplicityFormula; +import kodkod.ast.NaryExpression; +import kodkod.ast.NaryFormula; +import kodkod.ast.NaryIntExpression; +import kodkod.ast.Node; +import kodkod.ast.NotFormula; +import kodkod.ast.ProjectExpression; +import kodkod.ast.QuantifiedFormula; +import kodkod.ast.Relation; +import kodkod.ast.RelationPredicate; +import kodkod.ast.SumExpression; +import kodkod.ast.UnaryExpression; +import kodkod.ast.UnaryIntExpression; +import kodkod.ast.Variable; + +/** + * Implements a depth first traversal of the kodkod AST. + * + * @author Emina Torlak + */ +public abstract class AbstractVoidVisitor implements VoidVisitor { + + protected AbstractVoidVisitor() {} + + /** + * Returns true if this node has already been visited. + * Otherwise returns false. + * @return true if this node has already been visited. + */ + protected abstract boolean visited(Node n) ; + + /** + * Visits all the children of the given declarations node if + * this.visited(decls) returns false. Otherwise does nothing. + * @ensures all d: declarations.declarations | d.variable.accept(this) && d.expression.accept(this) + */ + public void visit(Decls decls) { + if (visited(decls)) return; + for (Decl decl : decls) { + decl.accept(this); + } + } + + /** + * Visits the variable and expression of this decl if + * this.visited(decl) returns false. Otherwise does nothing. + * @ensures decl.variable.accept(this) && decl.expression.accept(this) + */ + public void visit(Decl decl) { + if (visited(decl)) return; + decl.variable().accept(this); + decl.expression().accept(this); + } + + /** + * Does nothing. + */ + public void visit(Relation relation) {} + + /** + * Does nothing. + */ + public void visit(Variable variable) {} + + /** + * Does nothing. + */ + public void visit(ConstantExpression constExpr) {} + + /** + * Visits the children if this.visited(expr) returns false. Otherwise does nothing. + * @ensures all i: [0..#expr.children) | expr.child(i).accept(this) + */ + public void visit(NaryExpression expr) { + if (visited(expr)) return; + for(Expression child : expr) { + child.accept(this); + } + } + + /** + * Visits the left and right subexpressions if + * this.visited(binExpr) returns false. Otherwise does nothing. + * @ensures binExpr.left.accept(this) && binExpr.right.accept(this) + */ + public void visit(BinaryExpression binExpr) { + if (visited(binExpr)) return; + binExpr.left().accept(this); + binExpr.right().accept(this); + } + + /** + * Visits the subexpression if + * this.visited(unaryExpr) returns false. Otherwise does nothing. + * @ensures unaryExpr.expression.accept(this) + */ + public void visit(UnaryExpression unaryExpr) { + if (visited(unaryExpr)) return; + unaryExpr.expression().accept(this); + } + + /** + * Visits the declarations and the formula if + * this.visited(comprehension) returns false. Otherwise does nothing. + * @ensures comprehension.declarations.accept(this) && comprehension.formula.accept(this) + */ + public void visit(Comprehension comprehension) { + if (visited(comprehension)) return; + comprehension.decls().accept(this); + comprehension.formula().accept(this); + } + + /** + * Visits the if-condition, the then-expression, and the else-expression if + * this.visited(ifExpr) returns false. Otherwise does nothing. + * @ensures ifExpr.condition.accept(this) && ifExpr.thenExpr.accept(this) && + * ifExpr.elseExpr.accept(this) + */ + public void visit(IfExpression ifExpr) { + if (visited(ifExpr)) return; + ifExpr.condition().accept(this); + ifExpr.thenExpr().accept(this); + ifExpr.elseExpr().accept(this); + } + + /** + * Visits project.expression and project.columns if this.visited(project) returns false. + * Otherwise does nothing. + * @ensures project.expression.accept(this) && all i: project.arity | project.columns[i].accept(this) + */ + public void visit(ProjectExpression project) { + if (visited(project)) return; + project.expression().accept(this); + for(int i = 0, arity = project.arity(); i < arity; i++) { + project.column(i).accept(this); + } + } + + /** + * Visits castExpr.intExpr if + * this.visited(castExpr) returns false. Otherwise does nothing. + * @ensures castExpr.expression.accept(this) + */ + public void visit(IntToExprCast castExpr) { + if (visited(castExpr)) return; + castExpr.intExpr().accept(this); + } + + /** + * Does nothing. + */ + public void visit(IntConstant intConst) {} + + /** + * Visits the if-condition, the then-expression, and the else-expression if + * this.visited(intExpr) returns false. Otherwise does nothing. + * @ensures intExpr.condition.accept(this) && intExpr.thenExpr.accept(this) && + * intExpr.elseExpr.accept(this) + */ + public void visit(IfIntExpression intExpr) { + if (visited(intExpr)) return; + intExpr.condition().accept(this); + intExpr.thenExpr().accept(this); + intExpr.elseExpr().accept(this); + } + + /** + * Visits intExpr.expression if + * this.visited(intExpr) returns false. Otherwise does nothing. + * @ensures intExpr.expression.accept(this) + */ + public void visit(ExprToIntCast intExpr) { + if (visited(intExpr)) return; + intExpr.expression().accept(this); + } + + /** + * Visits the children if this.visited(intExpr) returns false. Otherwise does nothing. + * @ensures all i: [0..#intExpr.children) | intExpr.child(i).accept(this) + */ + public void visit(NaryIntExpression intExpr) { + if (visited(intExpr)) return; + for(IntExpression child : intExpr) { + child.accept(this); + } + } + + /** + * Visits the children of the given integer expression if + * this.visited(intExpr) returns false. Otherwise does nothing. + * @ensures intExpr.left.accept(this) && intExpr.right.accept(this) + */ + public void visit(BinaryIntExpression intExpr) { + if (visited(intExpr)) return; + intExpr.left().accept(this); + intExpr.right().accept(this); + } + + /** + * Visits the subexpression if + * this.visited(intExpr) returns false. Otherwise does nothing. + * @ensures unaryExpr.expression.accept(this) + */ + public void visit(UnaryIntExpression intExpr) { + if (visited(intExpr)) return; + intExpr.intExpr().accept(this); + } + + /** + * Visits the children of the given sum expression if + * this.visited(intExpr) returns false. Otherwise does nothing. + * @ensures intExpr.decls.accept(this) && intExpr.intExpr.accept(this) + */ + public void visit(SumExpression intExpr) { + if (visited(intExpr)) return; + intExpr.decls().accept(this); + intExpr.intExpr().accept(this); + } + + /** + * Visits the children of the given integer comparison formula if + * this.visited(intComp) returns false. Otherwise does nothing. + * @ensures intComp.left.accept(this) && intComp.right.accept(this) + */ + public void visit(IntComparisonFormula intComp) { + if (visited(intComp)) return; + intComp.left().accept(this); + intComp.right().accept(this); + } + + /** + * Visits the declarations and the formula if + * this.visited(quantFormula) returns false. Otherwise does nothing. + * @ensures quantFormula.declarations.accept(this) && quantFormula.formula.accept(this) + */ + public void visit(QuantifiedFormula quantFormula) { + if (visited(quantFormula)) return; + quantFormula.decls().accept(this); + quantFormula.formula().accept(this); + } + + /** + * Visits the children if this.visited(formula) returns false. Otherwise does nothing. + * @ensures all i: [0..#formula.children) | formula.child(i).accept(this) + */ + public void visit(NaryFormula formula) { + if (visited(formula)) return; + for(Formula child : formula) { + child.accept(this); + } + } + + /** + * Visits the left and right children if + * this.visited(binFormula) returns false. Otherwise does nothing. + * @ensures binFormula.left.accept(this) && binFormula.right.accept(this) + */ + public void visit(BinaryFormula binFormula) { + if (visited(binFormula)) return; + binFormula.left().accept(this); + binFormula.right().accept(this); + } + + /** + * Visits the subformula if + * this.visited(not) returns false. Otherwise does nothing. + * @ensures not.formula.accept(this) + */ + public void visit(NotFormula not) { + if (visited(not)) return; + not.formula().accept(this); + } + + /** + * Does nothing. + */ + public void visit(ConstantFormula constant) {} + + /** + * Visits the left and right children if + * this.visited(compFormula) returns false. Otherwise does nothing. + * @ensures compFormula.left.accept(this) && compFormula.right.accept(this) + */ + public void visit(ComparisonFormula compFormula) { + if (visited(compFormula)) return; + compFormula.left().accept(this); + compFormula.right().accept(this); + } + + /** + * Visits the formula if + * this.visited(multFormula) returns false. Otherwise does nothing. + * @ensures multFormula.expression.accept(this) + */ + public void visit(MultiplicityFormula multFormula) { + if (visited(multFormula)) return; + multFormula.expression().accept(this); + } + + /** + * Visits the children of the predicate if + * this.visited(pred) returns false. Otherwise does nothing. + * @ensures pred.relation.accept(this) && + * (pred.name = FUNCTION => pred.domain.accept(this) && pred.range.accept(this)) && + * (pred.name = TOTAL_ORDERING => + * pred.ordered.accept(this) && pred.first.accept(this) && pred.last.accept(this) ) + */ + public void visit(RelationPredicate pred) { + if (visited(pred)) return; + pred.relation().accept(this); + if (pred.name()==RelationPredicate.Name.FUNCTION) { + final RelationPredicate.Function fp = (RelationPredicate.Function) pred; + fp.domain().accept(this); + fp.range().accept(this); + } else if (pred.name()==RelationPredicate.Name.TOTAL_ORDERING) { + final RelationPredicate.TotalOrdering tp = (RelationPredicate.TotalOrdering) pred; + tp.ordered().accept(this); + tp.first().accept(this); + tp.last().accept(this); + } + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/visitor/ReturnVisitor.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/visitor/ReturnVisitor.java new file mode 100644 index 00000000..76b4562e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/visitor/ReturnVisitor.java @@ -0,0 +1,213 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast.visitor; + +import kodkod.ast.BinaryExpression; +import kodkod.ast.BinaryFormula; +import kodkod.ast.BinaryIntExpression; +import kodkod.ast.ComparisonFormula; +import kodkod.ast.Comprehension; +import kodkod.ast.ConstantExpression; +import kodkod.ast.ConstantFormula; +import kodkod.ast.Decl; +import kodkod.ast.Decls; +import kodkod.ast.ExprToIntCast; +import kodkod.ast.IfExpression; +import kodkod.ast.IfIntExpression; +import kodkod.ast.IntComparisonFormula; +import kodkod.ast.IntConstant; +import kodkod.ast.IntToExprCast; +import kodkod.ast.MultiplicityFormula; +import kodkod.ast.NaryExpression; +import kodkod.ast.NaryFormula; +import kodkod.ast.NaryIntExpression; +import kodkod.ast.NotFormula; +import kodkod.ast.ProjectExpression; +import kodkod.ast.QuantifiedFormula; +import kodkod.ast.Relation; +import kodkod.ast.RelationPredicate; +import kodkod.ast.SumExpression; +import kodkod.ast.UnaryExpression; +import kodkod.ast.UnaryIntExpression; +import kodkod.ast.Variable; + + +/** + * A visitor that visits every node in the AST, returning some value for each. + * The methods that visit an {@link kodkod.ast.Expression expression}, + * {@link kodkod.ast.Formula formula}, {@link kodkod.ast.Decls declarations}, + * and {@link kodkod.ast.IntExpression integer expression} and + * return values of types E, F, D, and I respectively. + * + * @author Emina Torlak + */ +public interface ReturnVisitor { + + /** + * Visits the given sequence of declarations and returns the result. + * @return the result of visiting decls + **/ + public D visit(Decls decls); + /** + * Visits the given declaration and returns the result. + * @return the result of visiting decl + **/ + public D visit(Decl decl); + + /** + * Visits the given relation and returns the result. + * @return the result of visiting relation + **/ + public E visit(Relation relation); + /** + * Visits the given variable and returns the result. + * @return the result of visiting variable + **/ + public E visit(Variable variable); + /** + * Visits the given constant expression and returns the result. + * @return the result of visiting constExpr + **/ + public E visit(ConstantExpression constExpr); + + /** + * Visits the given unary expression and returns the result. + * @return the result of visiting unaryExpr + **/ + public E visit(UnaryExpression unaryExpr); + /** + * Visits the given binary expression and returns the result. + * @return the result of visiting binExpr + **/ + public E visit(BinaryExpression binExpr); + /** + * Visits the given nary expression and returns the result. + * @return the result of visiting expr + **/ + public E visit(NaryExpression expr); + /** + * Visits the given comprehension and returns the result. + * @return the result of visiting comprehension + **/ + public E visit(Comprehension comprehension); + /** + * Visits the given if-then expression and returns the result. + * @return the result of visiting ifExpr + **/ + public E visit(IfExpression ifExpr); + /** + * Visits the given projection expression and returns the result. + * @return the result of visiting project + */ + public E visit(ProjectExpression project); + + /** + * Visits the given cast expression expression and returns the result. + * @return the result of visiting castExpr + **/ + public E visit(IntToExprCast castExpr); + + /** + * Visits the given integer constant and returns the result. + * @return the result of visiting intConst + */ + public I visit(IntConstant intConst); + /** + * Visits the given if-int-expression and returns the result. + * @return the result of visiting intExpr + */ + public I visit(IfIntExpression intExpr); + /** + * Visits the given unary integer expression and returns the result. + * @return the result of visiting intExpr + */ + public I visit(ExprToIntCast intExpr); + /** + * Visits the given nary expression and returns the result. + * @return the result of visiting intExpr + **/ + public I visit(NaryIntExpression intExpr); + /** + * Visits the given binary integer expression and returns the result. + * @return the result of visiting intExpr + */ + public I visit(BinaryIntExpression intExpr); + /** + * Visits the given unary integer expression and returns the result. + * @return the result of visiting intExpr + */ + public I visit(UnaryIntExpression intExpr); + /** + * Visits the given sum expression and returns the result. + * @return the result of visiting intExpr + */ + public I visit(SumExpression intExpr); + /** + * Visits the given integer comparison formula and returns the result. + * @return the result of visiting intcomp + */ + public F visit(IntComparisonFormula intComp); + + /** + * Visits the given quantified formula and returns the result. + * @return the result of visiting quantFormula + **/ + public F visit(QuantifiedFormula quantFormula); + /** + * Visits the given nary formula and returns the result. + * @return the result of visiting formula + **/ + public F visit(NaryFormula formula); + /** + * Visits the given binary formula and returns the result. + * @return the result of visiting binFormula + **/ + public F visit(BinaryFormula binFormula); + /** + * Visits the given negation and returns the result. + * @return the result of visiting not + **/ + public F visit(NotFormula not); + /** + * Visits the given constant formula and returns the result. + * @return the result of visiting constant + **/ + public F visit(ConstantFormula constant); + + /** + * Visits the given comparison formula and returns the result. + * @return the result of visiting compFormula + **/ + public F visit(ComparisonFormula compFormula); + /** + * Visits the given multiplicity formula and returns the result. + * @return the result of visiting multFormula + **/ + public F visit(MultiplicityFormula multFormula); + /** + * Visits the given relation predicate and returns the result. + * @return the result of visiting predicate + */ + public F visit(RelationPredicate predicate); + + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/visitor/VoidVisitor.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/visitor/VoidVisitor.java new file mode 100644 index 00000000..15757600 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/ast/visitor/VoidVisitor.java @@ -0,0 +1,183 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.ast.visitor; + +import kodkod.ast.BinaryExpression; +import kodkod.ast.BinaryFormula; +import kodkod.ast.BinaryIntExpression; +import kodkod.ast.ComparisonFormula; +import kodkod.ast.Comprehension; +import kodkod.ast.ConstantExpression; +import kodkod.ast.ConstantFormula; +import kodkod.ast.Decl; +import kodkod.ast.Decls; +import kodkod.ast.ExprToIntCast; +import kodkod.ast.IfExpression; +import kodkod.ast.IfIntExpression; +import kodkod.ast.IntComparisonFormula; +import kodkod.ast.IntConstant; +import kodkod.ast.IntToExprCast; +import kodkod.ast.MultiplicityFormula; +import kodkod.ast.NaryExpression; +import kodkod.ast.NaryFormula; +import kodkod.ast.NaryIntExpression; +import kodkod.ast.NotFormula; +import kodkod.ast.ProjectExpression; +import kodkod.ast.QuantifiedFormula; +import kodkod.ast.Relation; +import kodkod.ast.RelationPredicate; +import kodkod.ast.SumExpression; +import kodkod.ast.UnaryExpression; +import kodkod.ast.UnaryIntExpression; +import kodkod.ast.Variable; + +/** + * A visitor that visits every node in the AST. + * + * @author Emina Torlak + */ +public interface VoidVisitor { + + /** + * Visits the given sequence of declarations. + **/ + public void visit(Decls decls); + /** + * Visits the given declaration. + **/ + public void visit(Decl decl); + + /** + * Visits the given relation. + **/ + public void visit(Relation relation); + /** + * Visits the given variable. + **/ + public void visit(Variable variable); + /** + * Visits the given constant expression. + **/ + public void visit(ConstantExpression constExpr); + + /** + * Visits the given unary expression. + **/ + public void visit(UnaryExpression unaryExpr); + + /** + * Visits the given binary expression. + **/ + public void visit(BinaryExpression binExpr); + + /** + * Visits the given nary expression. + **/ + public void visit(NaryExpression expr); + + + /** + * Visits the given comprehension. + **/ + public void visit(Comprehension comprehension); + /** + * Visits the given if-then expression. + **/ + public void visit(IfExpression ifExpr); + /** + * Visits the given projection expression. + */ + public void visit(ProjectExpression project); + + + /** + * Visits the given integer cast expression. + */ + public void visit(IntToExprCast castExpr); + /** + * Visits the given integer constant. + */ + public void visit(IntConstant intConst); + /** + * Visits the given unary integer expression. + */ + public void visit(ExprToIntCast intExpr); + /** + * Visits the given if-int-expression. + */ + public void visit(IfIntExpression intExpr); + /** + * Visits the given nary int expression. + **/ + public void visit(NaryIntExpression intExpr); + /** + * Visits the given binary integer expression. + */ + public void visit(BinaryIntExpression intExpr); + /** + * Visits the given unary integer expression. + */ + public void visit(UnaryIntExpression intExpr); + /** + * Visits the given sum expression. + */ + public void visit(SumExpression intExpr); + /** + * Visits the given integer comparison formula. + */ + public void visit(IntComparisonFormula intComp); + + /** + * Visits the given quantified formula. + **/ + public void visit(QuantifiedFormula quantFormula); + /** + * Visits the given nary formula. + **/ + public void visit(NaryFormula formula); + /** + * Visits the given binary formula. + **/ + public void visit(BinaryFormula binFormula); + /** + * Visits the given negation. + **/ + public void visit(NotFormula not); + /** + * Visits the given constant formula. + **/ + public void visit(ConstantFormula constant); + + /** + * Visits the given comparison formula. + **/ + public void visit(ComparisonFormula compFormula); + /** + * Visits the given multiplicity formula. + **/ + public void visit(MultiplicityFormula multFormula); + /** + * Visits the given relation predicate. + */ + public void visit(RelationPredicate predicate); + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/AbortedException.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/AbortedException.java new file mode 100644 index 00000000..12a49de3 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/AbortedException.java @@ -0,0 +1,59 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine; + +/** + * Indicates that a solving or evaluation task has been aborted + * by calling Thread.interrupt on the solving (evaluation) thread. + * @author Emina Torlak + */ +public final class AbortedException extends RuntimeException { + + private static final long serialVersionUID = 201522560152091247L; + + /** + * Constructs an aborted exception with no message. + */ + AbortedException() {} + + /** + * Constructs an aborted exception with the given message. + */ + AbortedException(String message) { + super(message); + } + + /** + * Constructs an aborted exception with the given cause. + */ + AbortedException(Throwable cause) { + super(cause); + } + + /** + * Constructs an aborted exception with the given message and cause. + */ + AbortedException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/CapacityExceededException.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/CapacityExceededException.java new file mode 100644 index 00000000..92ef7287 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/CapacityExceededException.java @@ -0,0 +1,75 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine; + +import kodkod.util.ints.IntVector; + +/** + * Indicates that a problem construction or translation task failed because + * the capacity of the index representation was exceeded. + * @specfield dims: IntVector // contains a vector of dimensions which exceed the representation capacity + * @author Emina Torlak + */ +public final class CapacityExceededException extends RuntimeException { + + private static final long serialVersionUID = -8098615204149641969L; + private final IntVector dims; + + /** + * Constructs a CapacityExceededException from the given dimensions. + */ + public CapacityExceededException(IntVector dims) { + this.dims = dims; + } + + /** + * Constructs a CapacityExceededException with the given message and dimensions. + */ + public CapacityExceededException(String arg0, IntVector dims) { + super(arg0); + this.dims = dims; + } + + /** + * Constructs a CapacityExceededException with the given cause. + */ + public CapacityExceededException(Throwable arg0, IntVector dims) { + super(arg0); + this.dims = dims; + } + + /** + * Constructs a CapacityExceededException with the given message and cause. + */ + public CapacityExceededException(String arg0, Throwable arg1, IntVector dims) { + super(arg0, arg1); + this.dims = dims; + } + + /** + * Returns the vector of dimensions which, when multiplied together, exceed + * the representation capacity. + * @return this.dims + */ + public final IntVector dims() { return dims; } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/Cost.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/Cost.java new file mode 100644 index 00000000..8cb0c7b1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/Cost.java @@ -0,0 +1,46 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine; + +import kodkod.ast.Formula; +import kodkod.ast.Relation; +import kodkod.instance.Bounds; + +/** + * A cost function to be minimized during {@link kodkod.engine.Solver#solve(Formula, Bounds, Cost) solving}. + * In particular, each Cost is a total function from a set of {@link kodkod.ast.Relation relations} + * to a non-negative integer which represents the weight of one edge in the relation's value. (Hence, the + * total cost of a relation r in a given instance is s is #s.tuples(r) * edgeCost(r).) + * @specfield relations: set Relation // the domain of this cost function + * @specfield cost: relations -> one [0..) + * @author Emina Torlak + */ +public interface Cost { + + /** + * Returns the cost of one edge in the relational value of the given + * {@link Relation Relation instance}. + * @return this.cost[relation] + * @throws IllegalArgumentException - relation !in this.relations + */ + public abstract int edgeCost(Relation relation); +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/Evaluator.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/Evaluator.java new file mode 100644 index 00000000..d02f83b5 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/Evaluator.java @@ -0,0 +1,149 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine; + +import kodkod.ast.Expression; +import kodkod.ast.Formula; +import kodkod.ast.IntExpression; +import kodkod.engine.bool.BooleanMatrix; +import kodkod.engine.bool.Int; +import kodkod.engine.config.Options; +import kodkod.engine.fol2sat.Translator; +import kodkod.instance.Instance; +import kodkod.instance.TupleSet; + +/** + * An evaluator for relational formulas and expressions with + * respect to a given {@link kodkod.instance.Instance instance} + * and {@link kodkod.engine.config.Options options}. + * + *

Note: you may observe surprising (though correct) + * evaluator behavior if you do not use the same set of integer + * options (i.e. {@link kodkod.engine.config.Options#intEncoding() intEncoding} and {@link kodkod.engine.config.Options#bitwidth() bitwidth} + * when evaluating and solving a formula. For example, suppose that + * that an Instance i is a solution to a formula f found using options o. + * If you create an evaluator e such that e.instance = i, but e.options + * is an Options object with different integer settings than o, + * e.evalate(f) may return false.

+ * + * @specfield options: Options + * @specfield instance: Instance + * @author Emina Torlak + */ +public final class Evaluator { + private final Instance instance; + private final Options options; + private boolean wasOverflow; // [AM] was overflow detected during evaluation + + /** + * Constructs a new Evaluator for the given instance, using a + * default Options object. + * @ensures this.instance' = instance && this.options' = new Options() + * @throws NullPointerException - instance = null + */ + public Evaluator(Instance instance) { + this(instance, new Options()); + } + + /** + * Constructs a new Evaluator for the given instance and options + * @ensures this.instance' = instance && this.options' = options + * @throws NullPointerException - instance = null || options = null + */ + public Evaluator(Instance instance, Options options) { + if (instance==null || options==null) throw new NullPointerException(); + this.instance = instance; + this.options = options; + } + + /** + * Returns the Options object used by this evaluator. + * @return this.options + */ + public Options options() { return options; } + + /** + * Returns this.instance. Any modifications to the returned object + * will be reflected in the behavior of the evaluate methods. + * + * @return this.instance + */ + public Instance instance() { return instance; } + + /** + * Evaluates the specified formula with respect to the relation-tuple mappings + * given by this.instance and using this.options. + * @return true if formula is true with respect to this.instance and this.options; + * otherwise returns false + * @throws kodkod.engine.fol2sat.HigherOrderDeclException - the formula contains a higher order declaration + * @throws kodkod.engine.fol2sat.UnboundLeafException - the formula contains an undeclared variable or + * a relation not mapped by this.instance + */ + public boolean evaluate(Formula formula){ + if (formula == null) throw new NullPointerException("formula"); + return (Translator.evaluate(formula, instance, options)).booleanValue(); + } + + /** + * Evaluates the specified expession with respect to the relation-tuple mappings + * given by this.instance and using this.options. + * @return {@link kodkod.instance.TupleSet set} of tuples to which the expression evaluates given the + * mappings in this.instance and the options in this.options. + * @throws kodkod.engine.fol2sat.HigherOrderDeclException - the expression contains a higher order declaration + * @throws kodkod.engine.fol2sat.UnboundLeafException - the expression contains an undeclared variable or + * a relation not mapped by this.instance + */ + public TupleSet evaluate(Expression expression){ + if (expression == null) throw new NullPointerException("expression"); + final BooleanMatrix sol = Translator.evaluate(expression,instance,options); + return instance.universe().factory().setOf(expression.arity(), sol.denseIndices()); + } + + /** + * Evaluates the specified int expession with respect to the relation-tuple mappings + * given by this.instance and using this.options. + * @return the integer to which the expression evaluates given the + * mappings in this.instance and the options in this.options. + * @throws kodkod.engine.fol2sat.HigherOrderDeclException - intExpr contains a higher order declaration + * @throws kodkod.engine.fol2sat.UnboundLeafException - intExpr contains an undeclared variable or + * a relation not mapped by this.instance + */ + public int evaluate(IntExpression intExpr) { + if (intExpr == null) throw new NullPointerException("intexpression"); + final Int sol = Translator.evaluate(intExpr, instance, options); + this.wasOverflow = sol.defCond().isOverflowFlag(); + return sol.value(); + } + + /** Returns whether overflow was detected during evaluation */ //[AM] + public boolean wasOverflow() { + return wasOverflow; + } + + /** + * {@inheritDoc} + * @see java.lang.Object#toString() + */ + public String toString() { + return options + "\n" + instance; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/Proof.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/Proof.java new file mode 100644 index 00000000..76e87f4e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/Proof.java @@ -0,0 +1,129 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine; + +import java.util.Iterator; +import java.util.Map; + +import kodkod.ast.Formula; +import kodkod.ast.Node; +import kodkod.engine.config.Options; +import kodkod.engine.fol2sat.TranslationLog; +import kodkod.engine.fol2sat.TranslationRecord; +import kodkod.engine.satlab.ReductionStrategy; +import kodkod.util.nodes.Nodes; + +/** + * Contains a proof of unsatisfiability of a + * given FOL formula. + * + * @specfield log: TranslationLog // log of the translation of this.formula with respect to this.bounds + */ +public abstract class Proof { + private final TranslationLog log; + + /** + * Constructs a new Proof of unsatisfiability for log.formula. + * @ensures this.log = log + */ + Proof(TranslationLog log) { + this.log = log; + } + + /** + * Minimizes the proof of this.log.formula's unsatisfiability + * using the specified proof reduction strategy. The strategy + * argument is ignored (it can be null) if this.formula is + * trivially unsatisfiable with respect to this.bounds. In that + * case, the core is reduced using the trivial strategy + * that does one of the following: (1) if there is a + * root that simplified to FALSE, sets the minimal core + * to that root; or (2) if not, then there must be two + * roots that translated to x and -x, where x is a boolean + * literal, so we pick those two as the minimal core. + * + *

Note: the core minimization is performed at the level of the + * transformed formula, not the original formula if the problem was translated + * with a non-zero {@linkplain Options#coreGranularity() core granularity} setting. + * In other words, after this method has been called, {@linkplain #highLevelCore() highLevelCore()} + * returns a map M such that M.keySet() is a minimal core with respect to this.log.bounds. In contrast, + * {@linkplain Nodes#allRoots(Formula, java.util.Collection) Nodes.roots(this.log.originalFormula, M.values())} is + * unsatisfiable with respect this.log.originalBounds. These formulas, however, do not necessarily form a + * minimal core of this.log.originalFormula if the original problem was translated + * with a non-zero {@linkplain Options#coreGranularity() core granularity} setting.

+ * + * @ensures minimizes the proof of this.log.formula's unsatisfiability + * using the specified proof reduction strategy (or the trivial + * strategy if this.formula is trivially unsatisfiable with respect + * to this.bounds). + * + * @see kodkod.engine.satlab.ReductionStrategy + */ + public abstract void minimize(ReductionStrategy strategy); + + /** + * Returns an iterator over the {@link TranslationRecord log records} for the nodes + * that are in the unsatisfiable core of this.log.formula. The record objects returned by the iterator are not + * guaranteed to be immutable. In particular, the state of a record object + * returned by next() is guaranteed to remain the same only until the + * subsequent call to next(). + * @return an iterator over the {@link TranslationRecord log records} for the nodes + * that are in the unsatisfiable core of this.log.formula. + */ + public abstract Iterator core() ; + + /** + * Returns a map whose key set is the unsatisfiable subset of the top-level conjunctions of this.log.formula + * as given by {@linkplain #core() this.core()}. Each formula in the key set is mapped to the descendant of this.log.originalFormula + * from which it was derived by skolemization or by some other optimization. + * @return a map whose key set is the unsatisfiable subset of the top-level conjunctions of this.log.formula, + * as given by {@linkplain #core() this.core()}. Each formula in the key set is mapped to the descendant of this.log.originalFormula + * from which it was derived by skolemization or by some other optimization. + * @see #minimize(ReductionStrategy) + */ + public abstract Map highLevelCore() ; + + /** + * Returns the log of the translation that resulted + * in this proof. + * @return log of the translation that resulted in this proof + */ + public final TranslationLog log() { + return log; + } + + /** + * Returns a string representation of this proof. + * @return a string representation of this proof. + * @see java.lang.Object#toString() + */ +// public String toString() { +// final StringBuilder ret = new StringBuilder(); +// for(Formula f : highLevelCore()) { +// ret.append(" "); +// ret.append(f); +// ret.append("\n"); +// } +// return ret.toString(); +// } + +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ResolutionBasedProof.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ResolutionBasedProof.java new file mode 100644 index 00000000..d9e423b5 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ResolutionBasedProof.java @@ -0,0 +1,150 @@ +package kodkod.engine; + +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import kodkod.ast.Formula; +import kodkod.ast.Node; +import kodkod.ast.Variable; +import kodkod.ast.visitor.AbstractVoidVisitor; +import kodkod.engine.fol2sat.RecordFilter; +import kodkod.engine.fol2sat.TranslationLog; +import kodkod.engine.fol2sat.TranslationRecord; +import kodkod.engine.satlab.ReductionStrategy; +import kodkod.engine.satlab.ResolutionTrace; +import kodkod.engine.satlab.SATProver; +import kodkod.engine.ucore.StrategyUtils; +import kodkod.instance.TupleSet; +import kodkod.util.collections.IdentityHashSet; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.IntTreeSet; + +/** + * A proof of unsatisfiability based on a {@linkplain ResolutionTrace resolution trace} produced + * by a {@linkplain SATProver SATProver}. + * + * @author Emina Torlak + */ +final class ResolutionBasedProof extends Proof { + private SATProver solver; + private RecordFilter coreFilter; + private Map coreRoots; + + /** + * Constructs a new ResolutionRefutation that will extract the + * unsatisfiable core for log.formula from the given solver. + * @requires solver.solve() has been called and it returned false. + * @requires log.formula is the formula whose translation + * resulted in the given SATProver + * @ensures this.formula' = log.formula + */ + ResolutionBasedProof(SATProver solver, TranslationLog log) { + super(log); + this.solver = solver; + this.coreFilter = null; + this.coreRoots = null; + } + + /** + * Returns the connected core based on the given set of + * core variables. + * @requires coreVar = StrategyUtils.coreVars(solver.proof()); + * @return let formulas = (this.log.records[int] & literal.{i: int | abs(i) in coreVars}).formula | + * connected = {f: formulas | some s: set coreNodes | f + this.log.formula in s and (s - this.log.formula).~components in s } + */ + private Set connectedCore(final IntSet coreVars) { + final Set coreNodes = new IdentityHashSet(); + final RecordFilter filter = new RecordFilter() { + public boolean accept(Node node, Formula translated, int literal, Map env) { + return coreVars.contains(StrictMath.abs(literal)); + } + }; + for(Iterator itr = log().replay(filter); itr.hasNext(); ) { + coreNodes.add(itr.next().translated()); + } + final Set connected = new IdentityHashSet(); + final AbstractVoidVisitor traverser = new AbstractVoidVisitor() { + final Set visited = new IdentityHashSet(); + /** + * Returns true if the given node has been visited before or if + * it is not contained in this.nodes set. Otherwise adds + * the node to the connected set and returns false. + * @ensures this.visited' = this.visited + n + * @ensures n !in this.visited && n in coreNodes => + * connected' = connected + n else connected' = connected + * @return n in visited || n !in coreNodes + */ + protected boolean visited(Node n) { + if (visited.add(n) && coreNodes.contains(n)) { + connected.add((Formula)n); + return false; + } + return true; + } + }; + for(Formula root: log().roots()) { + root.accept(traverser); + } + return connected; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.Proof#core() + */ + public final Iterator core() { + if (coreFilter == null) { + coreFilter = new RecordFilter() { + final IntSet coreVariables = StrategyUtils.coreVars(solver.proof()); + final Set coreNodes = connectedCore(coreVariables); + public boolean accept(Node node, Formula translated, int literal, Map env) { + return coreNodes.contains(translated) && coreVariables.contains(StrictMath.abs(literal)); + } + }; + } + return log().replay(coreFilter); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.Proof#highLevelCore() + */ + public final Map highLevelCore() { + if (coreRoots == null) { + final RecordFilter unitFilter = new RecordFilter() { + final IntSet coreUnits = StrategyUtils.coreUnits(solver.proof()); + final Set roots = log().roots(); + public boolean accept(Node node, Formula translated, int literal, Map env) { + return roots.contains(translated) && coreUnits.contains(Math.abs(literal)); + } + + }; + coreRoots = new LinkedHashMap(); + final IntSet seenUnits = new IntTreeSet(); + for(Iterator itr = log().replay(unitFilter); itr.hasNext(); ) { + // it is possible that two top-level formulas have identical meaning, + // and are represented with the same core unit; in that case, we want only + // one of them in the core. + final TranslationRecord rec = itr.next(); + if (seenUnits.add(rec.literal())) { + coreRoots.put(rec.translated(), rec.node()); + } + } + coreRoots = Collections.unmodifiableMap(coreRoots); + } + return coreRoots; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.Proof#minimize(kodkod.engine.satlab.ReductionStrategy) + */ + public void minimize(ReductionStrategy strategy) { + solver.reduce(strategy); + coreFilter = null; + coreRoots = null; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/Solution.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/Solution.java new file mode 100644 index 00000000..d21594d6 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/Solution.java @@ -0,0 +1,188 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine; + + +import kodkod.instance.Instance; + +/** + * Represents the full solution to a formula: an + * instance if the formula is satisfiable or a + * proof of unsatisfiability if not. + * + * @specfield formula: Formula // the formula being solved + * @specfield bounds: Bounds // the bounds on the formula + * @author Emina Torlak + */ +public final class Solution { + private final Outcome outcome; + private final Statistics stats; + private final Instance instance; + private final Proof proof; + + + /** + * Constructs a Solution from the given values. + * @requires outcome != null && stats != null + * @requires outcome = SATISFIABLE || TRIVIALLY_SATISFIABLE => instance != null + */ + private Solution(Outcome outcome, Statistics stats, Instance instance, Proof proof) { + assert outcome != null && stats != null; + this.outcome = outcome; + this.stats = stats; + this.instance = instance; + this.proof = proof; + } + + /** + * Returns a new Solution with a SATISFIABLE outcome, given stats and instance. + * @return {s: Solution | s.outcome() = SATISFIABLE && s.stats() = stats && s.instance() = instance } + */ + static Solution satisfiable(Statistics stats, Instance instance) { + return new Solution(Outcome.SATISFIABLE, stats, instance, null); + } + + /** + * Returns a new Solution with a TRIVIALLY_SATISFIABLE outcome, given stats and instance. + * @return {s: Solution | s.outcome() = TRIVIALLY_SATISFIABLE && s.stats() = stats && s.instance() = instance } + */ + static Solution triviallySatisfiable(Statistics stats, Instance instance) { + return new Solution(Outcome.TRIVIALLY_SATISFIABLE, stats, instance, null); + } + + /** + * Returns a new Solution with a UNSATISFIABLE outcome, given stats and proof. + * @return {s: Solution | s.outcome() = UNSATISFIABLE && s.stats() = stats && s.proof() = proof } + */ + static Solution unsatisfiable(Statistics stats, Proof proof) { + return new Solution(Outcome.UNSATISFIABLE, stats, null, proof); + } + + /** + * Returns a new Solution with a TRIVIALLY_UNSATISFIABLE outcome, given stats and proof. + * @return {s: Solution | s.outcome() = TRIVIALLY_UNSATISFIABLE && s.stats() = stats && s.proof() = proof } + */ + static Solution triviallyUnsatisfiable(Statistics stats, Proof proof) { + return new Solution(Outcome.TRIVIALLY_UNSATISFIABLE, stats, null, proof); + } + + /** + * Returns the outcome of the attempt to find + * a model for this.formula. If the outcome is + * SATISFIABLE or TRIVIALLY_SATISFIABLE, a satisfying + * instance can be obtained by calling {@link #instance()}. + * If the formula is UNSATISFIABLE, a proof of unsatisfiability + * can be obtained by calling {@link #proof()} provided that + * translation logging was enabled and the unsatisfiability was + * determined using a core extracting + * {@link kodkod.engine.satlab.SATSolver sat solver}. + * Lastly, if the returned Outcome is + * or TRIVIALLY_UNSATISFIABLE, a proof of unsatisfiability can + * be obtained by calling {@link #proof()} provided that + * translation logging was enabled. + * @return an Outcome instance designating the + * satisfiability of this.formula with respect to this.bounds + */ + public Outcome outcome() { + return outcome; + } + + /** + * Returns a satisfiying instance for this.formula, if the + * value returned by {@link #outcome() this.outcome()} is either + * SATISFIABLE or TRIVIALLY_SATISFIABLE. Otherwise returns null. + * @return a satisfying instance for this.formula, if one exists. + */ + public Instance instance() { + return instance; + } + + /** + * Returns a proof of this.formula's unsatisfiability if the value + * returned by {@link #outcome() this.outcome()} is UNSATISFIABLE or + * TRIVIALLY_UNSATISFIABLE, translation logging was enabled during solving, + * and a core extracting {@link kodkod.engine.satlab.SATProver sat solver} (if any) + * was used to determine unsatisfiability. + * Otherwise, null is returned. + * @return a proof of this.formula's unsatisfiability, if one is available. + */ + public Proof proof() { + return proof; + } + + /** + * Returns the statistics gathered while solving + * this.formula. + * @return the statistics gathered while solving + * this.formula. + */ + public Statistics stats() { + return stats; + } + + /** + * Returns a string representation of this Solution. + * @return a string representation of this Solution. + */ + public String toString() { + final StringBuilder b = new StringBuilder(); + b.append("---OUTCOME---\n"); + b.append(outcome); + b.append("\n"); + if (instance!=null) { + b.append("\n---INSTANCE---\n"); + b.append(instance); + b.append("\n"); + } + if (proof!=null) { + b.append("\n---PROOF---\n"); + b.append(proof); + b.append("\n"); + } + b.append("\n---STATS---\n"); + b.append(stats); + b.append("\n"); + return b.toString(); + } + + /** + * Enumerates the possible outcomes of an attempt + * to find a model for a FOL formula. + */ + public static enum Outcome { + /** The formula is satisfiable with respect to the specified bounds. */ + SATISFIABLE, + /** The formula is unsatisfiable with respect to the specified bounds. */ + UNSATISFIABLE, + /** + * The formula is trivially satisfiable with respect to the specified bounds: + * a series of simple transformations reduces the formula to the constant TRUE. + **/ + TRIVIALLY_SATISFIABLE, + /** + * The formula is trivially unsatisfiable with respect to the specified bounds: + * a series of simple transformations reduces the formula to the constant FALSE. + */ + TRIVIALLY_UNSATISFIABLE + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/Solver.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/Solver.java new file mode 100644 index 00000000..6ec2f0d5 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/Solver.java @@ -0,0 +1,515 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; + +import kodkod.ast.Formula; +import kodkod.ast.Relation; +import kodkod.engine.config.Options; +import kodkod.engine.fol2sat.HigherOrderDeclException; +import kodkod.engine.fol2sat.Translation; +import kodkod.engine.fol2sat.TranslationLog; +import kodkod.engine.fol2sat.Translator; +import kodkod.engine.fol2sat.TrivialFormulaException; +import kodkod.engine.fol2sat.UnboundLeafException; +import kodkod.engine.satlab.SATAbortedException; +import kodkod.engine.satlab.SATMinSolver; +import kodkod.engine.satlab.SATProver; +import kodkod.engine.satlab.SATSolver; +import kodkod.instance.Bounds; +import kodkod.instance.Instance; +import kodkod.instance.TupleSet; +import kodkod.util.ints.IntIterator; +import kodkod.util.ints.IntSet; +import kodkod.util.nodes.PrettyPrinter; + + +/** + * A computational engine for solving relational formulae. + * A {@link kodkod.ast.Formula formula} is solved with respect to given + * {@link kodkod.instance.Bounds bounds} and {@link kodkod.engine.config.Options options}. + * + * @specfield options: Options + * @author Emina Torlak + */ +public final class Solver { + private final Options options; + + /** + * Constructs a new Solver with the default options. + * @ensures this.options' = new Options() + */ + public Solver() { + this.options = new Options(); + } + + /** + * Constructs a new Solver with the given options. + * @ensures this.options' = options + * @throws NullPointerException - options = null + */ + public Solver(Options options) { + if (options == null) + throw new NullPointerException(); + this.options = options; + } + + /** + * Returns the Options object used by this Solver + * to guide translation of formulas from first-order + * logic to cnf. + * @return this.options + */ + public Options options() { + return options; + } + + + + /** + * Attempts to satisfy the given formula with respect to the specified bounds, while + * minimizing the specified cost function. + * If the operation is successful, the method returns a Solution that contains either a minimal-cost + * instance of the formula or a proof of unsatisfiability. The latter is generated iff + * the SAT solver generated by this.options.solver() is a {@link SATProver SATProver} in addition + * to being a {@link kodkod.engine.satlab.SATMinSolver SATMinSolver}. + * + * @requires this.options.logTranslation==0 && this.options.solver.minimizer + * @return Solution to the formula with respect to the given bounds and cost + * @throws NullPointerException - formula = null || bounds = null || cost = null + * @throws kodkod.engine.fol2sat.UnboundLeafException - the formula contains an undeclared variable or + * a relation not mapped by the given bounds + * @throws kodkod.engine.fol2sat.HigherOrderDeclException - the formula contains a higher order declaration that cannot + * be skolemized, or it can be skolemized but this.options.skolemize is false. + * @throws AbortedException - this solving task was interrupted with a call to Thread.interrupt on this thread + * @throws IllegalArgumentException - some (formula.^children & Relation) - cost.relations + * @throws IllegalStateException - !this.options.solver.minimizer || this.options.logTranslation + * @see Solution + * @see Options + * @see Cost + */ + public Solution solve(Formula formula, Bounds bounds, Cost cost) + throws HigherOrderDeclException, UnboundLeafException, AbortedException { + + if (options.logTranslation()>0 || !options.solver().minimizer()) + throw new IllegalStateException(); + + final long startTransl = System.currentTimeMillis(); + try { + + final Translation translation = Translator.translate(formula, bounds, options); + final long endTransl = System.currentTimeMillis(); + + final SATMinSolver cnf = (SATMinSolver)translation.cnf(); + for(Relation r : bounds.relations()) { + IntSet vars = translation.primaryVariables(r); + if (vars != null) { + int rcost = cost.edgeCost(r); + for(IntIterator iter = vars.iterator(); iter.hasNext(); ) { + cnf.setCost(iter.next(), rcost); + } + } + } + + options.reporter().solvingCNF(0, cnf.numberOfVariables(), cnf.numberOfClauses()); + final long startSolve = System.currentTimeMillis(); + final boolean isSat = cnf.solve(); + final long endSolve = System.currentTimeMillis(); + + final Statistics stats = new Statistics(translation, endTransl - startTransl, endSolve - startSolve); + + return isSat ? sat(bounds, translation, stats) : unsat(translation, stats); + } catch (TrivialFormulaException trivial) { + final long endTransl = System.currentTimeMillis(); + return trivial(bounds, trivial, endTransl - startTransl); + } catch (SATAbortedException sae) { + throw new AbortedException(sae); + } + } + + /** + * Attempts to satisfy the given formula with respect to the specified bounds or + * prove the formula's unsatisfiability. + * If the operation is successful, the method returns a Solution that contains either + * an instance of the formula or an unsatisfiability proof. Note that an unsatisfiability + * proof will be constructed iff this.options specifies the use of a core extracting SATSolver. + * Additionally, the CNF variables in the proof can be related back to the nodes in the given formula + * iff this.options has translation logging enabled. Translation logging also requires that + * there are no subnodes in the given formula that are both syntactically shared and contain free variables. + * + * @return Solution to the formula with respect to the given bounds + * @throws NullPointerException - formula = null || bounds = null + * @throws kodkod.engine.fol2sat.UnboundLeafException - the formula contains an undeclared variable or + * a relation not mapped by the given bounds + * @throws kodkod.engine.fol2sat.HigherOrderDeclException - the formula contains a higher order declaration that cannot + * be skolemized, or it can be skolemized but this.options.skolemize is false. + * @throws AbortedException - this solving task was interrupted with a call to Thread.interrupt on this thread + * @see Solution + * @see Options + * @see Proof + */ + public Solution solve(Formula formula, Bounds bounds) + throws HigherOrderDeclException, UnboundLeafException, AbortedException { + + final long startTransl = System.currentTimeMillis(); + + try { + + final Translation translation = Translator.translate(formula, bounds, options); + final long endTransl = System.currentTimeMillis(); + + final SATSolver cnf = translation.cnf(); + + options.reporter().solvingCNF(translation.numPrimaryVariables(), cnf.numberOfVariables(), cnf.numberOfClauses()); + final long startSolve = System.currentTimeMillis(); + final boolean isSat = cnf.solve(); + final long endSolve = System.currentTimeMillis(); + + final Statistics stats = new Statistics(translation, endTransl - startTransl, endSolve - startSolve); + return isSat ? sat(bounds, translation, stats) : unsat(translation, stats); + + } catch (TrivialFormulaException trivial) { + final long endTransl = System.currentTimeMillis(); + return trivial(bounds, trivial, endTransl - startTransl); + } catch (SATAbortedException sae) { + throw new AbortedException(sae); + } + } + + /** + * Attempts to find all solutions to the given formula with respect to the specified bounds or + * to prove the formula's unsatisfiability. + * If the operation is successful, the method returns an iterator over n Solution objects. The outcome + * of the first n-1 solutions is SAT or trivially SAT, and the outcome of the nth solution is UNSAT + * or tirivally UNSAT. Note that an unsatisfiability + * proof will be constructed for the last solution iff this.options specifies the use of a core extracting SATSolver. + * Additionally, the CNF variables in the proof can be related back to the nodes in the given formula + * iff this.options has variable tracking enabled. Translation logging also requires that + * there are no subnodes in the given formula that are both syntactically shared and contain free variables. + * + * @return an iterator over all the Solutions to the formula with respect to the given bounds + * @throws NullPointerException - formula = null || bounds = null + * @throws kodkod.engine.fol2sat.UnboundLeafException - the formula contains an undeclared variable or + * a relation not mapped by the given bounds + * @throws kodkod.engine.fol2sat.HigherOrderDeclException - the formula contains a higher order declaration that cannot + * be skolemized, or it can be skolemized but this.options.skolemize is false. + * @throws AbortedException - this solving task was interrupted with a call to Thread.interrupt on this thread + * @throws IllegalStateException - !this.options.solver().incremental() + * @see Solution + * @see Options + * @see Proof + */ + public Iterator solveAll(final Formula formula, final Bounds bounds) + throws HigherOrderDeclException, UnboundLeafException, AbortedException { + + if (Options.isDebug()) flushFormula(formula, bounds); //[AM] + + if (!options.solver().incremental()) + throw new IllegalArgumentException("cannot enumerate solutions without an incremental solver."); + + return new SolutionIterator(formula, bounds, options); + } + + //[AM] + private void flushFormula(Formula formula, Bounds bounds) { + try { + File f = new File(System.getProperty("java.io.tmpdir"), "kk.txt"); + OutputStream os = new BufferedOutputStream(new FileOutputStream(f)); + os.write(PrettyPrinter.print(formula, 2).getBytes()); + os.write("\n================\n".getBytes()); + os.write(bounds.toString().getBytes()); + os.flush(); + os.close(); + } catch (Exception e) { + } + } + + /** + * {@inheritDoc} + * @see java.lang.Object#toString() + */ + public String toString() { + return options.toString(); + } + + /** + * Returns the result of solving a sat formula. + * @param bounds Bounds with which solve() was called + * @param translation the translation + * @param stats translation / solving stats + * @return the result of solving a sat formula. + */ + private static Solution sat(Bounds bounds, Translation translation, Statistics stats) { + final Solution sol = Solution.satisfiable(stats, padInstance(translation.interpret(), bounds)); + translation.cnf().free(); + return sol; + } + + /** + * Returns the result of solving an unsat formula. + * @param translation the translation + * @param stats translation / solving stats + * @return the result of solving an unsat formula. + */ + private static Solution unsat(Translation translation, Statistics stats) { + final SATSolver cnf = translation.cnf(); + final TranslationLog log = translation.log(); + if (cnf instanceof SATProver && log != null) { + return Solution.unsatisfiable(stats, new ResolutionBasedProof((SATProver) cnf, log)); + } else { // can free memory + final Solution sol = Solution.unsatisfiable(stats, null); + cnf.free(); + return sol; + } + } + + /** + * @return the number of primary variables needed to encode the unknown tuples in the given bounds. + */ + private static int trivialPrimaries(Bounds bounds) { + int prim = 0; + for(Relation r : bounds.relations()) { + prim += bounds.upperBound(r).size() - bounds.lowerBound(r).size(); + } + return prim; + } + + /** + * Returns the result of solving a trivially (un)sat formula. + * @param bounds Bounds with which solve() was called + * @param desc TrivialFormulaException thrown as the result of the formula simplifying to a constant + * @param translTime translation time + * @return the result of solving a trivially (un)sat formula. + */ + private static Solution trivial(Bounds bounds, TrivialFormulaException desc, long translTime) { + final Statistics stats = new Statistics(trivialPrimaries(desc.bounds()), 0, 0, translTime, 0); + if (desc.value().booleanValue()) { + return Solution.triviallySatisfiable(stats, padInstance(toInstance(desc.bounds()), bounds)); + } else { + return Solution.triviallyUnsatisfiable(stats, trivialProof(desc.log())); + } + } + + /** + * Returns a proof for the trivially unsatisfiable log.formula, + * provided that log is non-null. Otherwise returns null. + * @requires log != null => log.formula is trivially unsatisfiable + * @return a proof for the trivially unsatisfiable log.formula, + * provided that log is non-null. Otherwise returns null. + */ + private static Proof trivialProof(TranslationLog log) { + return log==null ? null : new TrivialProof(log); + } + + /** + * "Pads" the argument instance with the mappings that occur in bounds.lowerBound + * but not in the instance. + * @requires instance.relations in bounds.relations + * @ensures instance.relations' = bounds.relations' && + * instance.tuples' = bounds.lowerBound ++ instance.tuples + * @return instance + */ + private static Instance padInstance(Instance instance, Bounds bounds) { + for (Relation r : bounds.relations()) { + if (!instance.contains(r)) { + instance.add(r, bounds.lowerBound(r)); + } + } + for (IntIterator iter = bounds.ints().iterator(); iter.hasNext();) { + int i = iter.next(); + instance.add(i, bounds.exactBound(i)); + } + return instance; + } + + /** + * Creates an instance from the given Bounds. The instance + * is simply the mapping bounds.lowerBound. + * @return the instance corresponding to bounds.lowerBound + */ + private static Instance toInstance(Bounds bounds) { + final Instance instance = new Instance(bounds.universe()); + for (Relation r : bounds.relations()) { + instance.add(r, bounds.lowerBound(r)); + } + for (IntIterator iter = bounds.ints().iterator(); iter.hasNext();) { + int i = iter.next(); + instance.add(i, bounds.exactBound(i)); + } + return instance; + } + + /** + * An iterator over all solutions of a model. + * @author Emina Torlak + */ + private static final class SolutionIterator implements Iterator { + private final Options options; + private Formula formula; + private Bounds bounds; + private Translation translation; + private long translTime; + private int trivial; + + /** + * Constructs a solution iterator for the given formula, bounds, and options. + */ + SolutionIterator(Formula formula, Bounds bounds, Options options) { + this.formula = formula; + this.bounds = bounds; + this.options = options; + this.translation = null; + this.trivial = 0; + } + + /** + * Returns true if there is another solution. + * @see java.util.Iterator#hasNext() + */ + public boolean hasNext() { + return formula != null; + } + /** + * Solves translation.cnf and adds the negation of the + * found model to the set of clauses. + * @requires this.translation != null + * @ensures this.translation.cnf is modified to eliminate + * the current solution from the set of possible solutions + * @return current solution + */ + private Solution nonTrivialSolution() { + try { + final SATSolver cnf = translation.cnf(); + options.reporter().solvingCNF(translation.numPrimaryVariables(), cnf.numberOfVariables(), cnf.numberOfClauses()); + final long startSolve = System.currentTimeMillis(); + final boolean isSat = cnf.solve(); + final long endSolve = System.currentTimeMillis(); + + final Statistics stats = new Statistics(translation, translTime, endSolve - startSolve); + if (isSat) { + // extract the current solution; can't use the sat(..) method because it frees the sat solver + final Solution sol = Solution.satisfiable(stats, padInstance(translation.interpret(), bounds)); + // add the negation of the current model to the solver + final int primary = translation.numPrimaryVariables(); + final int[] notModel = new int[primary]; + for(int i = 1; i <= primary; i++) { + notModel[i-1] = cnf.valueOf(i) ? -i : i; + } + cnf.addClause(notModel); + return sol; + } else { + formula = null; bounds = null; // unsat, no more solutions, free up some space + return unsat(translation, stats); + } + } catch (SATAbortedException sae) { + throw new AbortedException(sae); + } + } + + /** + * Packages the information from the given trivial formula exception + * into a solution and returns it. If the formula is satisfiable, + * this.formula and this.bounds are modified to eliminate the current + * trivial solution from the set of possible solutions. + * @requires this.translation = null + * @ensures this.formula and this.bounds are modified to eliminate the current + * trivial solution from the set of possible solutions. + * @return current solution + */ + private Solution trivialSolution(TrivialFormulaException tfe) { + final Statistics stats = new Statistics(0, 0, 0, translTime, 0); + if (tfe.value().booleanValue()) { + trivial++; + final Bounds translBounds = tfe.bounds(); + final Instance trivialInstance = padInstance(toInstance(translBounds), bounds); + final Solution sol = Solution.triviallySatisfiable(stats, trivialInstance); + + final List changes = new LinkedList(); + + for(Map.Entry entry: trivialInstance.relationTuples().entrySet()) { + final Relation r = entry.getKey(); + + if (!translBounds.relations().contains(r)) { + translBounds.bound(r, bounds.lowerBound(r), bounds.upperBound(r)); + } + + if (translBounds.lowerBound(r)!=translBounds.upperBound(r)) { // r may change + if (entry.getValue().isEmpty()) { + changes.add(r.some()); + } else { + final Relation rmodel = Relation.nary(r.name()+"_"+trivial, r.arity()); + translBounds.boundExactly(rmodel, entry.getValue()); + changes.add(r.eq(rmodel).not()); + } + } + } + + bounds = translBounds; + + // no changes => there can be no more solutions (besides the current trivial one) + formula = changes.isEmpty() ? Formula.FALSE : tfe.formula().and(Formula.or(changes)); + + return sol; + } else { + formula = null; bounds = null; + return Solution.triviallyUnsatisfiable(stats, trivialProof(tfe.log())); + } + } + /** + * Returns the next solution if any. + * @see java.util.Iterator#next() + */ + public Solution next() { + if (!hasNext()) throw new NoSuchElementException(); + if (translation==null) { + try { + translTime = System.currentTimeMillis(); + translation = Translator.translate(formula, bounds, options); + translTime = System.currentTimeMillis() - translTime; + return nonTrivialSolution(); + } catch (TrivialFormulaException tfe) { + translTime = System.currentTimeMillis() - translTime; + return trivialSolution(tfe); + } + } else { + return nonTrivialSolution(); + } + } + + /** + * @see java.util.Iterator#remove() + */ + public void remove() { + throw new UnsupportedOperationException(); + } + + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/Statistics.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/Statistics.java new file mode 100644 index 00000000..2ecd6b79 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/Statistics.java @@ -0,0 +1,135 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine; + +import kodkod.engine.fol2sat.Translation; + +/** + * Stores the statistics gathered while solving + * a given formula. + * @specfield formula: Formula // the formula being solved + * @specfield bounds: Bounds // the bounds on the formula + */ +public final class Statistics { + + private static final String NEW_LINE = System.getProperty("line.separator"); + + private final int vars, pVars, clauses; + private final long translation, solving; + + /** + * Constructs a new Statistics object using the provided values. + */ + Statistics(int primaryVariables, int variables, int clauses, + long translationTime, long solvingTime) { + this.pVars = primaryVariables; + this.vars = variables; + this.clauses = clauses; + this.translation = translationTime; + this.solving = solvingTime; + } + + /** + * Constructs a new Statistics object using the provided values. + */ + Statistics(Translation translation, long translationTime, long solvingTime) { + this(translation.numPrimaryVariables(), translation.cnf().numberOfVariables(), + translation.cnf().numberOfClauses(), translationTime, solvingTime); + } + + /** + * Returns the number of variables needed + * to encode this.formula in CNF. + * @return the number of variables needed + * to encode this.formula in CNF. + */ + public int variables() { + return vars; + } + + /** + * Returns the number of primary variables + * used in the encoding of this.formula; i.e. the variables + * allocated to all the relations at the leaves + * of this.formula. + * @return the number of primary variables + * used in the encoding of this.formula + */ + public int primaryVariables() { + return pVars; + } + + /** + * Returns the number of clauses needed to + * encode this.formula in CNF. + * @return the number of variables needed + * to encode this.formula in CNF. + */ + public int clauses() { + return clauses; + } + + /** + * Returns the number of miliseconds spent + * on translation this.formula to CNF. + * @return the number of miliseconds spent + * on translation this.formula to CNF. + */ + public long translationTime() { + return translation; + } + + /** + * Returns the number of miliseconds spent + * on solving the CNF encoding of this.formula. + * @return the number of miliseconds spent + * on solving the CNF encoding of this.formula. + */ + public long solvingTime() { + return solving; + } + + /** + * Returns a string representation of this + * Statistics object. + * @return a string representation of this + * Statistics object. + */ + public String toString() { + final StringBuilder ret = new StringBuilder(); + ret.append("p cnf "); + ret.append(vars); + ret.append(" "); + ret.append(clauses); + ret.append(NEW_LINE); + ret.append("primary variables: "); + ret.append(pVars); + ret.append(NEW_LINE); + ret.append("translation time: "); + ret.append(translation); + ret.append(" ms").append(NEW_LINE); + ret.append("solving time: "); + ret.append(solving); + ret.append(" ms"); + return ret.toString(); + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/TrivialProof.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/TrivialProof.java new file mode 100644 index 00000000..b02d8bb2 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/TrivialProof.java @@ -0,0 +1,339 @@ +package kodkod.engine; + +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import kodkod.ast.BinaryFormula; +import kodkod.ast.ComparisonFormula; +import kodkod.ast.ConstantFormula; +import kodkod.ast.Decl; +import kodkod.ast.Formula; +import kodkod.ast.IntComparisonFormula; +import kodkod.ast.MultiplicityFormula; +import kodkod.ast.NaryFormula; +import kodkod.ast.Node; +import kodkod.ast.NotFormula; +import kodkod.ast.QuantifiedFormula; +import kodkod.ast.RelationPredicate; +import kodkod.ast.Variable; +import kodkod.ast.visitor.AbstractVoidVisitor; +import kodkod.engine.fol2sat.RecordFilter; +import kodkod.engine.fol2sat.TranslationLog; +import kodkod.engine.fol2sat.TranslationRecord; +import kodkod.engine.satlab.ReductionStrategy; +import kodkod.instance.TupleSet; +import kodkod.util.collections.IdentityHashSet; +import kodkod.util.ints.SparseSequence; +import kodkod.util.ints.TreeSequence; + +/** + * A proof of unsatisfiability for a trivially unsatisfiable formula. + * A formula is considered trivally unsatisfiable if its unsatisfiability + * is discovered through translation alone. + * + * @author Emina Torlak + */ +final class TrivialProof extends Proof { + private Map coreRoots; + private RecordFilter coreFilter; + + /** + * Constructs a proof of unsatisfiability for the trivially unsatisfiable + * formula whose translation is recorded in the given log. + * @requires log != null + * @ensures this.formula' = log.formula + */ + TrivialProof(TranslationLog log) { + super(log); + this.coreFilter = null; + this.coreRoots = null; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.Proof#core() + */ + public final Iterator core() { + if (coreFilter==null) { + coreFilter = new RecordFilter() { + final Set coreNodes = NodePruner.relevantNodes(log(), coreRoots==null ? log().roots() : coreRoots.keySet()); + public boolean accept(Node node, Formula translated, int literal, Map env) { + return coreNodes.contains(translated) ; + } + }; + } + return log().replay(coreFilter); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.Proof#highLevelCore() + */ + public final Map highLevelCore() { + if (coreRoots==null) { + final Iterator itr = core(); + final Set roots = log().roots(); + coreRoots = new LinkedHashMap(); + while( itr.hasNext() ) { + TranslationRecord rec = itr.next(); + if (roots.contains(rec.translated())) + coreRoots.put(rec.translated(), rec.node()); + } + coreRoots = Collections.unmodifiableMap(coreRoots); + } + return coreRoots; + } + + /** + * Minimizes the current core using the trivial strategy + * that does one of the following: (1) if there is a + * root that simplified to FALSE, sets the minimal core + * to that root; or (2) if not, there must be two + * roots that translated to x and -x, where x is a boolean + * literal, so we pick those two as the minimal core. + * The strategy argument is ignored (it can be null). + * @see Proof#minimize(ReductionStrategy) + */ + @Override + public void minimize(ReductionStrategy strategy) { + final Map rootLits = new LinkedHashMap(); + final Map rootNodes = new LinkedHashMap(); + final Set roots = log().roots(); + + for(Iterator itr = core(); itr.hasNext();) { + final TranslationRecord rec = itr.next(); + if (roots.contains(rec.translated())) { + // simply record the most recent output value for each formula: + // this is guaranteed to be the final output value for that + // formula because of the translation log guarantee that the + // log is replayed in the order of translation: i.e. a child's + // output value is always recorded before the parent's + int[] val = rootLits.get(rec.translated()); + if (val==null) { + val = new int[1]; + rootLits.put(rec.translated(), val); + } + val[0] = rec.literal(); + rootNodes.put(rec.translated(), rec.node()); + } + } + + final SparseSequence lits = new TreeSequence(); + for(Map.Entry entry : rootLits.entrySet()) { + final int lit = entry.getValue()[0]; + if (lit==-Integer.MAX_VALUE) { + coreRoots = Collections.singletonMap(entry.getKey(), rootNodes.get(entry.getKey())); + break; + } else if (lits.containsIndex(-lit)) { + final Formula f0 = lits.get(-lit); + final Formula f1 = entry.getKey(); + coreRoots = new LinkedHashMap(3); + coreRoots.put(f0, rootNodes.get(f0)); + coreRoots.put(f1, rootNodes.get(f1)); + coreRoots = Collections.unmodifiableMap(coreRoots); + break; + } else { + lits.put(lit, entry.getKey()); + } + } + + coreFilter = null; + assert coreRoots.size()==1 && rootLits.get(coreRoots.keySet().iterator().next())[0]==-Integer.MAX_VALUE || coreRoots.size()==2; + } + + /** + * Given a translation log for a trivially unsatisfiable formula, finds the nodes + * necessary for proving the formula's unsatisfiability. Instances of this + * visitor should be constructed and applied using the {@linkplain #relevantNodes(TranslationLog)} + * + * @specfield log: TranslationLog + * @author Emina Torlak + */ + private static final class NodePruner extends AbstractVoidVisitor { + private final Set visited, relevant; + private final Map constNodes; + + /** + * Constructs a proof finder for the given log. + * @ensures this.log' = log + */ + NodePruner(TranslationLog log) { + visited = new IdentityHashSet(); + relevant = new IdentityHashSet(); + + final RecordFilter filter = new RecordFilter() { + public boolean accept(Node node, Formula translated, int literal, Map env) { + return env.isEmpty(); + } + }; + + constNodes = new LinkedHashMap(); + for(Iterator itr = log.replay(filter); itr.hasNext(); ) { + TranslationRecord rec = itr.next(); + int lit = rec.literal(); + if (Math.abs(lit) != Integer.MAX_VALUE) { + constNodes.remove(rec.translated()); + } else if (lit==Integer.MAX_VALUE) { + constNodes.put(rec.translated(), Boolean.TRUE); + } else { + constNodes.put(rec.translated(), Boolean.FALSE); + } + } + } + + /** + * Returns the nodes necessary for proving the trivial unsatisfiability of log.formula. + * @requires some r: log.records | r.node = log.formula && r.literal = BooleanConstant.FALSE.label + * @requires highLevelCore in log.roots() and unsatisfiable(highLevelCore, log.bounds, log.options) + * @return nodes necessary for proving the trivial unsatisfiability of log.formula. + */ + static Set relevantNodes(TranslationLog log, Set highLevelCore) { + final NodePruner finder = new NodePruner(log); + for(Formula root : highLevelCore) { + if (!finder.isTrue(root)) { + root.accept(finder); + } + } + return finder.relevant; + } + + /** + * Returns true if the given node has been visited before. + * @ensures this.visited' = this.visited + n + * @return n in this.visited + */ + @Override + protected boolean visited(Node n) { + return !visited.add(n); + } + + /** + * Returns true if the node was simplified to TRUE during translation. + * @return some r: this.log.records | r.node = node && no r.env && r.literal = BooleanConstant.TRUE.label + */ + final boolean isTrue(Node node) { return constNodes.get(node)==Boolean.TRUE; } + + public void visit(Decl decl) { + if (visited(decl)) return; + relevant.add(decl); + } + + public void visit(QuantifiedFormula quantFormula) { + if (visited(quantFormula)) return; + relevant.add(quantFormula); + } + + public void visit(ComparisonFormula compFormula) { + if (visited(compFormula)) return; + relevant.add(compFormula); + } + public void visit(MultiplicityFormula multFormula) { + if (visited(multFormula)) return; + relevant.add(multFormula); + } + public void visit(RelationPredicate pred) { + if (visited(pred)) return; + relevant.add(pred); + } + public void visit(IntComparisonFormula intComp) { + if (visited(intComp)) return; + relevant.add(intComp); + } + + public void visit(ConstantFormula formula) { + relevant.add(formula); + } + + /** + * If the argument node has been been visited, adds it to this.relevant and visits its child. + */ + public void visit(NotFormula not) { + if (visited(not)) return; + relevant.add(not); + not.formula().accept(this); + } + + + /** + * If this formula should be visited, then we visit its children only + * if they could have contributed to the unsatisfiability of the top-level + * formula. For example, let binFormula = "p && q", binFormula simplified + * to FALSE, p simplified to FALSE and q was not simplified, then only p + * should be visited since p caused binFormula's reduction to FALSE. + */ + public void visit(BinaryFormula binFormula) { + if (visited(binFormula)) return; + relevant.add(binFormula); + + final Formula l = binFormula.left(), r = binFormula.right(); + final Boolean lval = constNodes.get(l), rval = constNodes.get(r); + final boolean lvisit, rvisit; + + switch(binFormula.op()) { + case AND : + lvisit = (lval==Boolean.FALSE || (lval==null && rval!=Boolean.FALSE)); + rvisit = (rval!=Boolean.TRUE && lval!=Boolean.FALSE); + break; + case OR : + lvisit = (lval==Boolean.TRUE || (lval==null && rval!=Boolean.TRUE)); + rvisit = (rval!=Boolean.FALSE && lval!=Boolean.TRUE); + break; + case IMPLIES: // !l || r + lvisit = (lval==Boolean.FALSE || (lval==null && rval!=Boolean.TRUE)); + rvisit = (rval!=Boolean.FALSE && lval!=Boolean.FALSE); + break; + case IFF: // (!l || r) && (l || !r) + lvisit = rvisit = true; + break; + default : + throw new IllegalArgumentException("Unknown operator: " + binFormula.op()); + } + + if (lvisit) { l.accept(this); } + if (rvisit) { r.accept(this); } + } + + /** + * If this formula should be visited, then we visit its children only + * if they could have contributed to the unsatisfiability of the top-level + * formula. For example, let binFormula = "p && q", binFormula simplified + * to FALSE, p simplified to FALSE and q was not simplified, then only p + * should be visited since p caused binFormula's reduction to FALSE. + */ + public void visit(NaryFormula formula) { + if (visited(formula)) return; + relevant.add(formula); + + final Boolean val = constNodes.get(formula); + final Boolean cancel; + + switch(formula.op()) { + case AND : cancel = Boolean.FALSE; break; + case OR : cancel = Boolean.TRUE; break; + default : throw new IllegalArgumentException("Unknown nary operator: " + formula.op()); + } + + final Boolean iden = Boolean.valueOf(!cancel); + if (val!=iden) { + for(Formula child : formula) { + if (constNodes.get(child)==cancel) { + child.accept(this); + return; + } + } + for(Formula child : formula) { + if (constNodes.get(child)!=iden) { + child.accept(this); + } + } + return; + } + + for(Formula child : formula) { child.accept(this); } + } + } + +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BinaryGate.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BinaryGate.java new file mode 100644 index 00000000..e3ff93a9 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BinaryGate.java @@ -0,0 +1,139 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.bool; + +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Set; + +/** + * A logic gate with two inputs. + * @invariant #this.inputs = 2 + * @invariant digest = sum(inputs.digest(this.op)) + */ +final class BinaryGate extends MultiGate { + private final BooleanFormula low, high; + + /** + * Constructs a new binary gate with the given operator, label, and inputs. + * @requires components.h = components.l && l.label < h.label + * @ensures this.op' = op && this.inputs' = l + h && this.label' = label + */ + BinaryGate(Operator.Nary op, int label, int hashcode, BooleanFormula l, BooleanFormula h) { + super(op, label, hashcode); + assert l.label() < h.label(); + this.low = l; + this.high = h; + } + + /** + * Returns an integer k' such that 0 < |k'| < k and |k'| is the number of flattening + * steps that need to be taken to determine that this circuit has (or does not have) + * an input with the given label. + * A positive k' indicates that f is found to be an input to this circuit in k' steps. + * A negative k' indicates that f is not an input to this circuit, when it is flattened + * using at most k steps. + * @requires k > 0 + * @return the number of flattening + * steps that need to be taken to determine that f is (not) an input to this circuit + */ + @Override + int contains(Operator op, int f, int k) { + assert k > 0; + if (f==label()) return 1; + else if (this.op != op || k < 2 || f>label() || -f>label()) return -1; + else { + final int l = low.contains(op, f, k-1); + if (l > 0) return l; + else { + final int h = high.contains(op, f, k - l); + return h > 0 ? h - l : h + l; + } + } + } + + /** + * Flattens this circuit with respect to the given operator into + * the provided set. + * Specifically, the method modifies the set so that it contains + * the elements f_0, ..., f_k' where k' <= k elements and + * [[this]] = op(f_0, ..., f_k'). + * The default implementation simply adds this to the set. + * @requires k > 0 + * @ensures 1 <= k' <= k && some f_0,..., f_k' : flat.elts' | + * [[this]] = op([[f_0]], ..., [[f_k']]) + */ + @Override + void flatten(Operator op, Set flat, int k) { + assert k > 0; + if (this.op==op && k > 1) { + final int oldsize = flat.size(); + low.flatten(op, flat, k-1); + high.flatten(op, flat, k - (flat.size()-oldsize)); + } else { + flat.add(this); + } + } + + /** + * Returns 2. + * @return 2 + */ + @Override + public int size() { return 2; } + + /** + * Returns an iterator over the inputs to this gate, in + * the increasing label order. + * @return an iterator over this.inputs. + */ + @Override + public Iterator iterator() { + return new Iterator() { + int next = 0; + public boolean hasNext() { return next < 2; } + public BooleanFormula next() { + if (!hasNext()) throw new NoSuchElementException(); + return (next++ == 0 ? low : high); + } + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + /** + * Returns the ith input to this gate. + * @return this.inputs[i] + * @requires 0 <= i < size + * @throws IndexOutOfBoundsException - i < 0 || i >= #this.inputs + */ + @Override + public BooleanFormula input(int i) { + switch(i) { + case 0 : return low; + case 1 : return high; + default: + throw new IndexOutOfBoundsException(); + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanAccumulator.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanAccumulator.java new file mode 100644 index 00000000..97b067d8 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanAccumulator.java @@ -0,0 +1,210 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.bool; + +import java.util.Iterator; + +import kodkod.util.ints.IndexedEntry; +import kodkod.util.ints.SparseSequence; +import kodkod.util.ints.TreeSequence; + + +/** + * An accumulator for easy construction of gates with multiple inputs. + * An accumulator cannot be combined with other boolean values + * using BooleanFactory methods. To use the circuit + * represented by an accumulator, one must first convert it into a gate + * by calling {@link BooleanFactory#accumulate(BooleanAccumulator)}. + * + * @specfield components: set BooleanValue + * @specfield op: Operator.Nary + * @author Emina Torlak + */ +public final class BooleanAccumulator extends BooleanValue implements Iterable{ + final Operator.Nary op; + private final SparseSequence inputs; +// private final List inputs; + + /** + * Constructs a new accumulator with the given + * operator. + * @requires op != null + * @ensures this.op' = op && this.label' = label + */ + private BooleanAccumulator(Operator.Nary op) { + this.op = op; + inputs = new TreeSequence(); +// inputs = new ArrayList(); + } + + /** + * Returns a tree based implementation of BooleanAccumulator. + * The addInput operation executes in O(lg n) time where n is the number of gate inputs. + * @return an empty tree based BooleanAccumulator with the given operator. + * @throws NullPointerException - op = null + */ + public static BooleanAccumulator treeGate(Operator.Nary op) { + if (op==null) throw new NullPointerException(); + return new BooleanAccumulator(op); + } + + /** + * Returns a tree based implementation of BooleanAccumulator, initialized with the given inputs. + * The addInput operation executes in O(lg n) time where n is the number of gate inputs. + * @return a tree based BooleanAccumulator with the given operator, initialized with the given inputs + * @throws NullPointerException - op = null || inputs = null + */ + public static BooleanAccumulator treeGate(Operator.Nary op, BooleanValue... inputs) { + if (op==null) throw new NullPointerException(); + final BooleanAccumulator ret = new BooleanAccumulator(op); + for(BooleanValue v : inputs) { + if (ret.add(v)!=ret) + break; + } + return ret; + } + + /** + * Returns the operator for this accumulator. + * @return this.op + */ + public Operator.Nary op() { + return op; + } + + /** + * Adds the given value to this.components and returns the result. Specifically, + * if the addition of the value causes the gate to evaluate to op.shortCircuit, + * then this.inputs is set to op.shortCircuit. If the given value has already + * been added or it is equal to this.op.identity, nothing changes. Otherwise, v + * is added to this.input. The method returns this.op.shortCircuit if this.inputs + * contains it after the addition, otherwise it returns the gate itself. + * @ensures v = this.op.shortCircuit || v.negation in this.components => this.components' = this.op.shortCircuit, + * v !in BooleanConstant => this.components' = this.components + v, + * this.components' = this.components + * @return this.components' = op.shortCircuit => op.shortCircuit, this + */ + public BooleanValue add(BooleanValue v) { + if (isShortCircuited()) return op.shortCircuit(); + else{ + final int lit = v.label(); + if (v==op.shortCircuit() || inputs.containsIndex(-lit)) { + inputs.clear(); + inputs.put(op.shortCircuit().label, op.shortCircuit()); + return op.shortCircuit(); + } + if (v!=op.identity() && !inputs.containsIndex(lit)) { inputs.put(lit, (BooleanValue) v); } +// if (v==op.shortCircuit()) { +// inputs.clear(); +// inputs.add(op.shortCircuit()); +// return op.shortCircuit(); +// } +// if (v!=op.identity()) { inputs.add(v); } + return this; + } + } + + /** + * Returns true if this gate is short circuited; that is, + * its inputs are reduced to this.op.shortCircuit. + * @return this.inputs = this.op.shortCircuit + */ + public boolean isShortCircuited() { + return inputs.size()==1 && inputs.first().value()==op.shortCircuit(); +// return inputs.size()==1 && inputs.get(0)==op.shortCircuit(); + } + + /** + * Throws an IllegalArgumentException if op != this.op, + * otherwise returns the sum of digests of this gate's + * inputs with respect to the given operator. + * @return op = this.op => sum(this.inputs.digest(op)) + * @throws IllegalArgumentException - op != this.op + * @throws ClassCastException - some this.inputs & BooleanConstant + */ + int digest(Operator op) { + if (this.op != op) throw new IllegalArgumentException(); + int d = 0; + for(Iterator inputs = iterator(); inputs.hasNext();) { + d += ((BooleanFormula)inputs.next()).hash(op); + } + return d; + } + + + /** + * Returns the size of this accumulator. + * @return #this.inputs + */ + public int size() { + return inputs.size(); + } + + /** + * Returns an iterator over this.components, in + * the increasing order of labels. The returned iterator + * does not support removal. + * @return an iterator over this.components, in the + * increasing order of labels. + */ + public Iterator iterator() { + return new Iterator() { + final Iterator> iter = inputs.iterator(); + public boolean hasNext() { + return iter.hasNext(); + } + + public BooleanValue next() { + return iter.next().value(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + }; +// return inputs.iterator(); + } + + + /** + * Throws an unsupported operation exception. + * @throws UnsupportedOperationException + */ + @Override + BooleanValue negation() { + throw new UnsupportedOperationException(); + } + + /** + * Returns 0. + * @return 0. + */ + @Override + public int label() { + return 0; + } + + public String toString() { + return inputs.toString(); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanConstant.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanConstant.java new file mode 100644 index 00000000..fc321342 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanConstant.java @@ -0,0 +1,99 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.bool; + +/** + * A boolean constant, true or false. The integer + * label of the true and false constants are Integer.MAX_VALUE and -Integer.MAX_VALUE, respectively. + * The two boolean constants, TRUE and FALSE, are shared among all factories. + * + * @specfield value: boolean + * @invariant this.op = Operator.CONST + * @invariant value => Integer.MAX_VALUE, -Integer.MAX_VALUE + * @author Emina Torlak + */ +public final class BooleanConstant extends BooleanValue { + final int label; + + public static final BooleanConstant TRUE = new BooleanConstant(true); + public static final BooleanConstant FALSE = new BooleanConstant(false); + + /** + * Constructs a BooleanConstant that represent the given boolean + * value. + * @ensures value => this.label' = Integer.MAX_VALUE, this.label' = -Integer.MAX_VALUE + */ + private BooleanConstant(boolean value) { + this.label = (value ? Integer.MAX_VALUE : -Integer.MAX_VALUE); + } + + /** + * Returns the negation of this value. + * @return c: BooleanConstant | [[c]] = ![[this]] + */ + @Override + BooleanValue negation() { + return this==TRUE ? FALSE : TRUE; + } + + /** + * Returns the primitive boolean representation of this label. + * @return this.label == Integer.MAX_VALUE + */ + public boolean booleanValue() { return label > 0; } + + /** + * Returns the BooleanConstant that represents the given boolean value. + * @return {c: BooleanConstant | value => c.label = Integer.MAX_VALUE, c.label = -Integer.MAX_VALUE } + */ + public static BooleanConstant constant(boolean value) { + return value ? TRUE : FALSE; + } + + /** + * Returns the label for this value. + * @return this.label + */ + @Override + public int label() { + return label; + } + + /** + * Returns a string representation of this boolean value. + * @return a string representation of this boolean value. + */ + public String toString() { + return label>0 ? "T" : "F"; + } + + /** + * Returns Operator.CONST. + * @return Operator.CONST + */ + @Override + public Operator op() { + return Operator.CONST; + } + + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanFactory.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanFactory.java new file mode 100644 index 00000000..58ec9832 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanFactory.java @@ -0,0 +1,464 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.bool; + +import static kodkod.engine.bool.Operator.AND; +import static kodkod.engine.bool.Operator.OR; + +import java.util.Collection; +import java.util.Iterator; + +import kodkod.engine.config.Options; +import kodkod.engine.config.Options.IntEncoding; +import kodkod.util.ints.IntSet; + + +/** + * A factory for creating {@link kodkod.engine.bool.BooleanValue boolean values}, + * {@link kodkod.engine.bool.BooleanMatrix matrices}, and {@link kodkod.engine.bool.Int ints}. + * + * @specfield comparisonDepth: int // the depth to which circuits should be checked for equality + * @specfield intEncoding: Options.IntEncoding // the encoding used for generating integers ({@link #integer(int)} + * @specfield bitwidth: int // the bitwidth used for integer computations + * @specfield components: set BooleanValue + * @invariant no f1, f2: BooleanFactory | f1 != f2 => f1.components & f2.components = BooleanConstant + * @author Emina Torlak + */ +public abstract class BooleanFactory { + /** + * IMPLEMENTATION NOTE: BooleanFactory is the facade and a mediator for this package. + */ + private static CBCFactory CONSTANT_FACTORY; + /** + * A circuit factory used internally to assemble circuits. + */ + private final CBCFactory circuits; + + /** The bitwidth used for integer computations */ + final int bitwidth; + + /** Whether or not it should forbid overflows */ //[AM] + final boolean noOverflow; + + /** + * Constructs a boolean factory with the given number of input variables. Gates are + * checked for semantic equality down to the given depth. Integers are represented + * using the given number of bits. The noOverflow bit tells whether or not to forbid + * overflows. + * + * @requires 0 <= numVars < Integer.MAX_VALUE + * @requires checkToDepth >= 0 && bitwidth > 0 + * @ensures #this.components' = numInputVariables && this.components' in BooleanVariable + * @ensures this.bitwidth' = bitwidth + * @ensures this.comparisonDepth' = comparisonDepth + */ + private BooleanFactory(int numVars, int comparisonDepth, int bitwidth, boolean noOverflow) { + if (numVars==0) { + if (CONSTANT_FACTORY==null) + CONSTANT_FACTORY = new CBCFactory(0, 1); + this.circuits = CONSTANT_FACTORY; + } else { + this.circuits = new CBCFactory(numVars, 1<Gates are checked for semantic equality + * down to the depth given by options.sharing when checking for cached values. In general, setting the + * comparison depth to a higher value will result in more + * subcomponents being shared. However, it will also slow down + * gate construction.

+ *

Integers are created/manipulated according to the specifications in the given Options object.

+ * @return {f: BooleanFactory | #(f.components & BooleanVariable) = numVars && + * BooleanConstant in f.components && f.components in BooleanVariable + BooleanConstant && + * f.comparisonDepth = options.sharing && + * f.bitwidth = options.bitwidth && f.intEncoding = options.intEncoding && + * (all i: [1..numVars] | one f.components.label & i }} + * @throws IllegalArgumentException - numVars < 0 || numVars = Integer.MAX_VALUE + * @throws NullPointerException - options = null + */ + public static BooleanFactory factory(int numVars, Options options) { + switch(options.intEncoding()) { + case TWOSCOMPLEMENT : + return new TwosComplementFactory(numVars, options.sharing(), options.bitwidth(), options.noOverflow()); + default : + throw new IllegalArgumentException("unknown encoding: " + options.intEncoding()); + } + } + + /** + * Returns a BooleanFactory with no variables; the returned factory + * can manipulate only constants. + * @return {f: BooleanFactory | f.components = BooleanConstant && + * f.comparisonDepth = options.sharing && + * f.bitwidth = options.bitwidth && f.intEncoding = options.intEncoding } + * @throws NullPointerException - options = null + */ + public static BooleanFactory constantFactory(Options options) { + return factory(0, options); + } + + /** + * Returns the depth (from the root) to which components are checked for + * semantic equality during gate construction. + * @return this.comparisonDepth + */ + public final int comparisonDepth() { return Integer.numberOfTrailingZeros(circuits.cmpMax()); } + + /** + * Sets the comparison depth to the given value. Setting the + * comparison depth to a high value will result in more + * subcomponents being shared. However, it will also slow down + * gate construction. + * @ensures this.comparisonDepth' = newDepth + * @throws IllegalArgumentException - newDepth < 1 + */ + public final void setComparisonDepth(int newDepth) { + if (newDepth < 1) + throw new IllegalArgumentException("newDepth < 1: " + newDepth); + circuits.setCmpMax(1< [[v1]]. + * The behavior of this method is unspecified if v0 or v1 are not components of this factory. + * @requires v0 + v1 in this.components + * @return { v: BooleanValue | [[v]] = [[v0]] => [[v1]] } + * @ensures this.components' = this.components + v + * @throws NullPointerException - any of the arguments are null + */ + public final BooleanValue implies(BooleanValue v0, BooleanValue v1) { + return circuits.assemble(OR, v0.negation(), v1); + } + + /** + * Returns a boolean value whose meaning is [[v0]] <=> [[v1]]. + * The behavior of this method is unspecified if v0 or v1 are not components of this factory. + * @requires v0 + v1 in this.components + * @return { v: BooleanValue | [[v]] = [[v0]] iff [[v1]] } + * @ensures this.components' = this.components + v + * @throws NullPointerException - any of the arguments are null + */ + public final BooleanValue iff(BooleanValue v0, BooleanValue v1) { + return circuits.assemble(v0, v1, v1.negation()); + } + + /** + * Returns a boolean value whose meaning is [[i]] ? [[t]] : [[e]]. + * The behavior of this method is unspecified if i, t, or e are not components of this factory. + * @requires i + t + e in this.components + * @return { v: BooleanValue | [[v]] = [[i]] ? [[t]] : [[e]] } + * @ensures this.components' = this.components + v + * @throws NullPointerException - any of the arguments are null + */ + public final BooleanValue ite(BooleanValue i, BooleanValue t, BooleanValue e) { + return circuits.assemble(i, t, e); + } + + /** + * Returns a boolean value whose meaning is the sum bit of a full binary adder. + * The behavior of this method is unspecified if v0, v1, or cin are not components of this factory. + * @requires v0 + v1 + cin in this.components + * @return { v: BooleanValue | [[v]] = [[cin]] xor [[v0]] xor [[v1]] } + * @ensures this.components' = this.components + v + * @throws NullPointerException - any of the arguments are null + */ + public final BooleanValue sum(BooleanValue v0, BooleanValue v1, BooleanValue cin) { + return xor(cin, xor(v0, v1)); + } + + /** + * Returns a boolean value whose meaning is the carry out bit of a full binary adder. + * The behavior of this method is unspecified if v0, v1, or cin are not components of this factory. + * @requires v0 + v1 + cin in this.components + * @return { v: BooleanValue | [[v]] = ([[v0]] and [[v1]]) or ([[cin]] and ([[v0]] xor [[v1]])) } + * @ensures this.components' = this.components + v + * @throws NullPointerException - any of the arguments are null + */ + public final BooleanValue carry(BooleanValue v0, BooleanValue v1, BooleanValue cin) { + return or(and(v0, v1), and(cin, xor(v0, v1))); + } + + /** + * Converts the given accumulator into an immutable boolean value and adds it to this.components. + * This method requires that all of g's inputs are in this.components. If g has no inputs, + * its operator's identity constant is returned. If g has one input, that input is returned. + * Otherwise, an immutable value that is semantically equivalent to g is returned. + * The behavior of this method is unspecified if the components of g are not components of this factory. + * @requires g.components in this.components + * @return no g.inputs => g.op.identity(), + * one g.inputs => g.inputs, + * {g' : BooleanValue - BooleanAccumulator | [[g']] = [[g]] } + * @ensures this.components' = this.components + g' + */ + public final BooleanValue accumulate(BooleanAccumulator g) { + return circuits.assemble(g); + } + + /** + * Returns an Int that represents the given number using this.intEncoding. + * @return { i: Int | [[i]] = number && i.encoding && this.intEncoding && i.factory = this} + * @throws IllegalArgumentException - the number cannot be represented using + * the specified encoding + */ + public abstract Int integer(int number); + + /** + * Returns an Int that represents 0 or the given number, depending on the value of the given bit. + * The behavior of this method is unspecified if the bit is not a component of this factory. + * @return { i: Int | [[bit]] => [[i]] = number, [[i]] = 0 && i.encoding = this.intEncoding && i.factory = this} + */ + public abstract Int integer(int number, BooleanValue bit); + + /** + * Returns an Int that represents the sum of the elements returned by the iterator, + * using this.intEncoding. + * @param lo the first element of the current partial sum. Initial should be 0. + * @param hi the last element of the current partial sum. Initial should be size-1, where size is the total + * number of elements returned by the iterator. + * @return an Int that represents the sum of the elements returned by the iterator, + * using this.intEncoding. + */ + private Int sum(Iterator values, int low, int high) { + if (low > high) + return integer(0); + else if (low == high) + return integer(1, values.next()); + else { + final int mid = (low + high) / 2; + final Int lsum = sum(values, low, mid); + final Int hsum = sum(values, mid+1, high); + return lsum.plus(hsum); + } + } + + /** + * Returns an Int that represents the sum of all values in the given collection. + * @return an Int that represents the sum of all values in the given collection. + */ + public final Int sum(Collection bits) { + return sum(bits.iterator(), 0, bits.size()-1); + } + + /** + * Removes all formulas with one or more inputs from this.components. + * @ensures this.componets' = + * BooleanConstant + this.components & BooleanVariable + */ + public final void clear() { + circuits.clear(); + } + + /** + * Returns a BooleanMatrix with the given dimensions and this + * as the factory for its non-FALSE components. The returned matrix + * can store any value from this.components at all + * indices between 0, inclusive, and d.capacity(), exclusive. + * @throws NullPointerException - d = null + * @return { m: BooleanMatrix | m.factory = this && m.dimensions = d && m.elements = [0..d.capacity) -> one FALSE } + */ + public final BooleanMatrix matrix(Dimensions d) { + if (d == null ) throw new NullPointerException(); + return new BooleanMatrix(d, this); + } + + /** + * @throws IllegalArgumentException - indices !in [0..d.capacity()) + */ + private static void validate(IntSet indices, Dimensions d) { + if (!indices.isEmpty()) { + if (!d.validate(indices.min()) || !d.validate(indices.max())) + throw new IllegalArgumentException(); + } + } + + /** + * Returns a BooleanMatrix m with the given dimensions, this + * as its factory, and the indices from the set trueIndices initialized + * to TRUE. An IndexOutOfBoundsException may be thrown + * if {@link BooleanMatrix#set(int, BooleanValue)} is called on m with an index + * not contained in allIndices. If allIndices.equals(trueIndices), + * m may be a constant matrix; that is, an IllegalArgumentException may be + * thrown if {@link BooleanMatrix#set(int, BooleanValue)} is called on m with + * a non-constant value. Finally, if cloning trueIndices results in an immutable + * set, then {@link BooleanMatrix#set(int, BooleanValue) m.set(int, BooleanValue)} may throw + * an UnsupportedOperationException when called with a member of trueIndices. + * @requires allIndices.containsAll(trueIndices) + * @return { m: BooleanMatrix | m.factory = this && m.dimensions = dims && + * m.elements = [0..d.capacity()-1] ->one FALSE ++ indices->TRUE } + * @throws IllegalArgumentException - allIndices !in [0..d.capacity()) + * @throws IllegalArgumentException - one of the input sets is not cloneable + * @throws NullPointerException - d = null || allIndices = null || trueIndices = null + */ + public final BooleanMatrix matrix(Dimensions d, IntSet allIndices, IntSet trueIndices) { + assert allIndices.size() >= trueIndices.size(); // sanity check + validate(allIndices, d); validate(trueIndices, d); + try { + return new BooleanMatrix(d, this, allIndices, trueIndices.clone()); + } catch (CloneNotSupportedException e) { + throw new IllegalArgumentException(); + } + + } + + /** + * BooleanFactory that produces TwosComplementInts. + * @invariant encoding = TwosComplement + * @author Emina Torlak + */ + private static final class TwosComplementFactory extends BooleanFactory { + + /** + * Constructs a boolean factory with the given number of input variables. Gates are + * checked for semantic equality down to the given depth. Integers are represented + * using the given number of bits. + * @requires 0 <= numVars < Integer.MAX_VALUE + * @requires checkToDepth >= 0 && bitwidth > 0 + * @ensures #this.components' = numInputVariables && this.components' in BooleanVariable + * @ensures this.bitwidth' = bitwidth + * @ensures this.comparisonDepth' = comparisonDepth + * @ensures this.intEncoding' = BINARY + */ + TwosComplementFactory(int numVars, int comparisonDepth, int bitwidth, boolean noOverflow) { + super(numVars, comparisonDepth, bitwidth, noOverflow); + } + /** + * Returns TWOSCOMPLEMENT. + * @return TWOSCOMPLEMENT + * @see kodkod.engine.bool.BooleanFactory#intEncoding() + */ + @Override + public IntEncoding intEncoding() { + return IntEncoding.TWOSCOMPLEMENT; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.BooleanFactory#integer(int) + */ + @Override + public Int integer(int number) { + return new TwosComplementInt(this, number, BooleanConstant.TRUE); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.BooleanFactory#integer(int, kodkod.engine.bool.BooleanValue) + */ + @Override + public Int integer(int number, BooleanValue bit) { + return new TwosComplementInt(this, number, bit); + } + + } +} + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanFormula.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanFormula.java new file mode 100644 index 00000000..9039ea07 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanFormula.java @@ -0,0 +1,139 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.bool; + +import java.util.Iterator; +import java.util.Set; + + + +/** + * A non-constant boolean value with zero or more inputs. + * @specfield op: Operator + * @specfield size: int + * @specfield inputs: [0..size) -> one BooleanFormula + * @invariant size >= 0 + * @author Emina Torlak + */ +public abstract class BooleanFormula extends BooleanValue implements Iterable { + private BooleanFormula negation; + + /** + * Constructs a boolean formula with the given negation. + */ + BooleanFormula(BooleanFormula negation) { + this.negation = negation; + } + /** + * Returns an integer hash of this formula, used + * to compute the hash of the composition of this and + * some other formula with the given operator. + * @return an integer hash of this formula when acting + * as an input to a multigate with the given operator. + */ + abstract int hash(Operator op); + + /** + * Returns an integer k' such that 0 < |k'| < k and |k'| is the number of flattening + * steps that need to be taken to determine that this circuit has (or does not have) + * an input with the given label. + * A positive k' indicates that f is found to be an input to this circuit in k' steps. + * A negative k' indicates that f is not an input to this circuit, when it is flattened + * using at most k steps. + * @requires k > 0 + * @return the number of flattening + * steps that need to be taken to determine that f is (not) an input to this circuit + */ + int contains(Operator op, int f, int k) { + return f==label() ? 1 : -1; + } + + /** + * Flattens this circuit with respect to the given operator into + * the provided set. + * Specifically, the method modifies the set so that it contains + * the elements f_0, ..., f_k' where k' <= k elements and + * [[this]] = op(f_0, ..., f_k'). + * The default implementation simply adds this to the set. + * @requires k > 0 + * @ensures 1 <= k' <= k && some f_0,..., f_k' : flat.elts' | + * [[this]] = op([[f_0]], ..., [[f_k']]) + */ + void flatten(Operator op, Set flat, int k) { + assert k > 0; + flat.add(this); + } + + + + /** + * Returns the negation of this formula if it has already been computed. + * Otherwise, computes, caches and returns the negation of this formula. + * @return !this + * @see kodkod.engine.bool.BooleanValue#negation() + */ + final BooleanFormula negation() { + if (negation==null) { + negation = new NotGate(this); + } + return negation; + } + + /** + * Returns true if the negation of this formula + * has already been computed. + * @return true if the negation of this formula has already been computed. + */ + final boolean hasNegation() { return negation != null; } + + /** + * Passes this value and the given + * argument value to the visitor, and returns the resulting value. + * @return the value produced by the visitor when visiting this node + * with the given argument. + */ + public abstract T accept(BooleanVisitor visitor, A arg); + + + + /** + * Returns an iterator over the inputs to this gate. + * @return an iterator over this.inputs. + */ + public abstract Iterator iterator(); + + + /** + * Returns the number of inputs to this gate. + * @return #this.inputs + */ + public abstract int size(); + + /** + * Returns the ith input to this gate. + * @return this.inputs[i] + * @requires 0 <= i < size + * @throws IndexOutOfBoundsException - i < 0 || i >= #this.inputs + */ + public abstract BooleanFormula input(int i); + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanMatrix.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanMatrix.java new file mode 100644 index 00000000..3ed8e65e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanMatrix.java @@ -0,0 +1,1058 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.bool; + +import static kodkod.engine.bool.BooleanConstant.FALSE; +import static kodkod.engine.bool.BooleanConstant.TRUE; +import static kodkod.engine.bool.Operator.AND; +import static kodkod.engine.bool.Operator.OR; + +import java.util.Iterator; + +import kodkod.engine.fol2sat.Environment; +import kodkod.util.collections.Containers; +import kodkod.util.ints.ArraySequence; +import kodkod.util.ints.HomogenousSequence; +import kodkod.util.ints.IndexedEntry; +import kodkod.util.ints.IntIterator; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.Ints; +import kodkod.util.ints.RangeSequence; +import kodkod.util.ints.SparseSequence; +import kodkod.util.ints.TreeSequence; + + +/** + *

An n-dimensional matrix of {@link kodkod.engine.bool.BooleanValue boolean values}. + * Boolean matrices are indexed using flat integer indeces. For example, + * let m be a the 2 x 3 matrix of boolean variables identifed by labels [0 4 1; 5 10 2]. + * Then, m[0] = 0, m[3] = 5, m[5] = 2, etc.

+ * + *

All values stored in the same matrix must be created by the same {@link kodkod.engine.bool.BooleanFactory circuit factory}. + * All methods that accept another BooleanMatrix as an input will throw an + * IllegalArgumentException if the values in the input matrix do not belong + * to the same factory as the values in the receiver matrix.

+ * + *

Some instances can store only constant values, or can only store + * values at particular indices (see {@link kodkod.engine.bool.BooleanFactory#matrix(Dimensions, IntSet, IntSet)}). + * If this is the case, an attempt to call {@link #set(int, BooleanValue) } + * with invalid parameters will cause an IllegalArgumentException or an IndexOutOfBoundsException.

+ * + * @specfield dimensions: Dimensions + * @specfield factory: BooleanFactory + * @specfield elements: [0..dimensions.capacity) -> one factory.components + * + * @author Emina Torlak + */ +public final class BooleanMatrix implements Iterable>, Cloneable { + + private DefCond defCond = new DefCond(); + + private final Dimensions dims; + private final BooleanFactory factory; + private final SparseSequence cells; + + /** + * Constructs a new matrix with the given dimensions, factory, and entries. + * + * @requires dimensions != null && factory != null && seq != null + * @requires seq.indices() in [0..dimensions.capacity) + * @ensures this.dimensions' = dimensions && this.factory' = factory && + * this.elements' = [0..dimensions.capacity)->one FALSE + */ + private BooleanMatrix(Dimensions dimensions, BooleanFactory factory, SparseSequence seq) { + this.dims = dimensions; + this.factory = factory; + this.cells = seq; + } + + /** + * Constructs a new matrix with the given dimensions and factory, + * backed by a sparse sequence which can most efficiently hold + * the elements storable in the sparse sequences s0 and s1. + * @ensures this.dimensions' = dimensions && this.factory' = factory && + * this.elements' = [0..dimensions.capacity)->one FALSE + */ + private BooleanMatrix(Dimensions d, BooleanFactory f, SparseSequence s0, SparseSequence s1) { + this.dims = d; + this.factory = f; + final Class c0 = s0.getClass(), c1 = s1.getClass(); + if (c0!=c1 || c0==RangeSequence.class) + this.cells = new RangeSequence(); + else if (c0==HomogenousSequence.class) + this.cells = new HomogenousSequence(TRUE, Ints.bestSet(d.capacity())); + else + this.cells = new TreeSequence(); + } + + /** + * Constructs a new matrix with the given dimensions and factory, + * backed by a sparse sequence which can most efficiently hold + * the elements storable in the matrices m and rest. + * @requires null !in d + m + rest[int] + * @requires m.factory = rest[int].factory + * @requires d.equals(m.dims) => d.equals(rest[int].dims) + * @ensures this.dimensions' = dimensions && this.factory' = m.factory && + * this.elements' = [0..dimensions.capacity)->one FALSE + * @throws IllegalArgumentException m.factory != rest[int].factory + * @throws IllegalArgumentException !(d.equals(m.dims) => d.equals(rest[int].dims)) + */ + private BooleanMatrix(Dimensions d, BooleanMatrix m, BooleanMatrix...rest) { + this.dims = d; + this.factory = m.factory; + + final Class h = HomogenousSequence.class, t = TreeSequence.class; + final boolean sameDim = d.equals(m); + + Class c = m.cells.getClass(); + int cId = c==h ? 1 : c==t ? 2 : 4; + + for(BooleanMatrix other : rest) { + checkFactory(factory, other.factory); + if (sameDim) checkDimensions(d, other.dims); + + c = other.cells.getClass(); + cId |= c==h ? 1 : c==t ? 2 : 4; + } + + switch(cId) { + case 1 : this.cells = new HomogenousSequence(TRUE, Ints.bestSet(d.capacity())); break; + case 2 : this.cells = new TreeSequence(); break; + default : this.cells = new RangeSequence(); + } + + mergeDefConds(m); + mergeDefConds(rest); + } + + /** + * Constructs a new matrix with the given dimensions and factory. + * The constructed matrix can store any kind of BooleanValue. + * + * @requires dimensions != null && factory != null + * @ensures this.dimensions' = dimensions && this.factory' = factory && + * this.elements' = [0..dimensions.capacity)->one FALSE + */ + BooleanMatrix(Dimensions dims, BooleanFactory factory) { + this.dims = dims; + this.factory = factory; + this.cells = new RangeSequence(); + } + + /** + * Constructs a new matrix with the given dimensions and factory, + * and initializes the indices in the given set to TRUE. + * The constructed matrix will be capable of storing only constants + * iff trueIndeces.equals(allIndices). Otherwise, it will be able to store any kind of BooleanValue + * ONLY at the indices given by allIndices. Any attempt to call {@link #set(int, BooleanValue) } on + * an index outside of allIndices may result in an IndexOutOfBoundsException. + * + * @requires allIndices.containsAll(trueIndices) + * @requires trueIndices is not modifiable using an external handle + * @requires dimensions != null && factory != null && trueIndices != null && allIndices != null + * @requires dimensions.validate(allIndices.min()) && dimensions.validate(allIndices.max()) + * @ensures this.dimensions' = dimensions && this.factory' = factory && + * this.elements' = [0..dimensions.capacity)->one FALSE ++ trueIndices -> one TRUE + */ + BooleanMatrix(Dimensions dims, BooleanFactory factory, IntSet allIndices, IntSet trueIndices) { + this.dims = dims; + this.factory = factory; + final int tsize = trueIndices.size(), asize = allIndices.size(); + if (tsize==asize) + this.cells = new HomogenousSequence(TRUE, trueIndices); + else { + this.cells = tsize==0 || asize/tsize >= 2 ? new ArraySequence(allIndices) : new RangeSequence(); + for(IntIterator iter = trueIndices.iterator(); iter.hasNext(); ) { + cells.put(iter.next(), TRUE); + } + } + } + + private void mergeDefConds(BooleanMatrix ... bms) { + mergeDefConds(FALSE, bms); + } + + private void mergeDefConds(BooleanValue of, BooleanMatrix ... bms) { + DefCond[] dcs = new DefCond[1 + bms.length]; + dcs[0] = this.defCond(); + for (int i = 0; i < bms.length; i++) { + dcs[i+1] = bms[i].defCond(); + this.defCond().addVars(bms[i].defCond().vars()); + } + this.defCond().setOverflows(of, DefCond.merge(factory, dcs)); + } + + /** + * Returns the dimensions of this matrix. + * @return this.dimensions + */ + public final Dimensions dimensions() { return dims; } + + /** + * Returns the factory used to construct all the non-constant + * entries in this matrix. + * @return this.factory + */ + public final BooleanFactory factory() { return factory; } + + /** + * Returns this.defCond + * @return this.defCond + */ + public final DefCond defCond() { return defCond; } + + public void setDefCond(DefCond dc) { + //[aaa] this.defCond = dc; + } + + /** + * Returns the number of non-FALSE entries in this matrix. + * @return #this.elements.(BooleanValue - FALSE) + */ + public final int density() { return cells.size(); } + + /** + * Returns an IndexedEntry-based view of the non-FALSE entries in this matrix. The returned + * iterator enumerates indexed entries that represent the non-FALSE entries in the matrix, in the ascending + * order of indeces. For example, suppose that the elements of this are 0->FALSE, 1->(a & b), 2->FALSE, 3->(c | d). Then, + * the Iterator will return two IndexedEntries, c1 then c2, such that c1.index=1 && c1.value = a & b and + * c2.index=3 && c.value = c | d. Calling {@link Iterator#remove()} on the returned iterator has the same effect + * as setting the entry obtained through the last call to {@link Iterator#next()} to FALSE. + * @return an iterator over IndexedEntries representing the non-FALSE entries in this matrix. + */ + public final Iterator> iterator() { + return cells.iterator(); + } + + /** + * Returns the set of all indices in this matrix that contain + * non-FALSE values. + * @return the set of all indices in this matrix that contain + * non-FALSE values. + */ + public final IntSet denseIndices() { + return cells.indices(); + } + + /** + * Return FALSE if value is null; otherwise return value itself. + * @return FALSE if value is null; otherwise return value itself. + */ + private final BooleanValue maskNull(BooleanValue value) { + return value == null ? FALSE : value; + } + + /** + * Returns the value at the given index, without checking that the index is in bounds. + * @return this.elements[index] + */ + private final BooleanValue fastGet(final int index) { + return maskNull(cells.get(index)); + } + + /** + * Returns the element at the specified index. + * @return this.elements[index] + * @throws IndexOutOfBoundsException index < 0 || index >= this.dimensions.capacity + */ + public final BooleanValue get(final int index) { + if (!dims.validate(index)) throw new IndexOutOfBoundsException(index + " is not a valid index."); + return maskNull(cells.get(index)); + } + + + /** + * Returns a new matrix each of whose entries is a negation of the + * corresponding entry in this matrix. + * + * @return { m: BooleanMatrix | m.dimensions=this.dimensions && m.factory = this.factory && + * all i: [0..m.dimensions.capacity) | m.elements[i] = !this.elements[i] } + */ + public final BooleanMatrix not() { + final BooleanMatrix negation = new BooleanMatrix(dims, factory, cells, cells); + negation.mergeDefConds(this); + + for (int i = 0, max = dims.capacity(); i < max; i++) { + BooleanValue v = cells.get(i); + if (v==null) + negation.cells.put(i, TRUE); + else if (v!=TRUE) + negation.cells.put(i, v.negation()); + } + + return negation; + } + + /** + * @throws IllegalArgumentException f != this.factory + */ + private static final void checkFactory(BooleanFactory f0, BooleanFactory f1) { + if (f0 != f1) throw new IllegalArgumentException("Incompatible factories: " + f0 + " and " + f1); + } + + /** + * @throws IllegalArgumentException !d0.equals(d1) + */ + private static final void checkDimensions(Dimensions d0, Dimensions d1) { + if (!d0.equals(d1)) throw new IllegalArgumentException("Incompatible dimensions: " + d0 + " and " + d1); + } + + /** + * Returns a new matrix such that an entry in the returned matrix represents a + * conjunction of the corresponding entries in this and other matrix. The effect + * of this method is the same as calling this.compose(ExprOperator.Binary.AND, other). + * + * @return { m: BooleanMatrix | m.dimensions = this.dimensions && m.factory = this.factory && + * all i: [0..m.dimensions.capacity) | + * m.elements[i] = this.elements[i] AND other.elements[i] } + * @throws NullPointerException other = null + * @throws IllegalArgumentException !other.dimensions.equals(this.dimensions) || this.factory != other.factory + */ + public final BooleanMatrix and(BooleanMatrix other) { + checkFactory(this.factory, other.factory); checkDimensions(this.dims, other.dims); + + final BooleanMatrix ret = new BooleanMatrix(dims, factory, cells, other.cells); + ret.mergeDefConds(this, other); + + final SparseSequence s1 = other.cells; + for(IndexedEntry e0 : cells) { + BooleanValue v1 = s1.get(e0.index()); + if (v1!=null) + ret.fastSet(e0.index(), factory.and(e0.value(), v1)); + } + return ret; + } + + /** + * Returns a new matrix such that an entry in the returned matrix represents a + * conjunction of the corresponding entries in this and other matrices. + * + * @requires all i: [0..others.length) | others[i].dimensions = this.dimensions && others[i].factory = this.factory + * @return others.length = 0 => m else + * { m: BooleanMatrix | m.dimensions = this.dimensions && m.factory = this.factory && + * all i: [0..m.dimensions.capacity) | m.elements[i] = AND(this.elements[i], others[int].elements[i]) } + * @throws NullPointerException others = null + * @throws IllegalArgumentException some m: others[int] | !m.dimensions.equals(this.dimensions) || m.factory != this.factory + */ + public final BooleanMatrix and(final BooleanMatrix...others) { + final BooleanMatrix ret = new BooleanMatrix(dims, this, others); + + for(IndexedEntry cell : cells) { + final BooleanAccumulator acc = BooleanAccumulator.treeGate(AND, cell.value()); + for(BooleanMatrix other : others) { + if (acc.add(other.fastGet(cell.index()))==BooleanConstant.FALSE) + break; + } + if (!acc.isShortCircuited()) { ret.fastSet(cell.index(), factory.accumulate(acc)); } + } + return ret; + } + + /** + * Returns a new matrix such that an entry in the returned matrix represents a + * combination of the corresponding entries in this and other matrix. The effect + * of this method is the same as calling this.compose(ExprOperator.Binary.OR, other). + * + * @return { m: BooleanMatrix | m.dimensions = this.dimensions && m.factory = this.factory && + * all i: [0..m.dimensions.capacity) | + * m.elements[i] = this.elements[i] OR other.elements[i] } + * @throws NullPointerException other = null + * @throws IllegalArgumentException !other.dimensions.equals(this.dimensions) || this.factory != other.factory + */ + public final BooleanMatrix or(BooleanMatrix other) { + checkFactory(this.factory, other.factory); checkDimensions(this.dims, other.dims); + + final BooleanMatrix ret = new BooleanMatrix(dims, factory, cells, other.cells); + ret.mergeDefConds(this, other); + + final SparseSequence retSeq = ret.cells; + for(IndexedEntry e0 : cells) { + BooleanValue v1 = other.cells.get(e0.index()); + if (v1==null) + retSeq.put(e0.index(), e0.value()); + else + retSeq.put(e0.index(), factory.or(e0.value(), v1)); + } + for(IndexedEntry e1 : other.cells) { + if (!cells.containsIndex(e1.index())) + retSeq.put(e1.index(), e1.value()); + } + return ret; + } + + /** + * Returns a new matrix such that an entry in the returned matrix represents a + * disjunction of the corresponding entries in this and other matrices. + * + * @requires all i: [0..others.length) | others[i].dimensions = this.dimensions && others[i].factory = this.factory + * @return others.length = 0 => m else + * { m: BooleanMatrix | m.dimensions = this.dimensions && m.factory = this.factory && + * all i: [0..m.dimensions.capacity) | m.elements[i] = OR(this.elements[i], others[int].elements[i]) } + * @throws NullPointerException others = null + * @throws IllegalArgumentException some m: others[int] | !m.dimensions.equals(this.dimensions) || m.factory != this.factory + */ + public final BooleanMatrix or(final BooleanMatrix... others) { + final BooleanMatrix ret = new BooleanMatrix(dims, this, others); + + for(IndexedEntry cell : cells) { + final BooleanAccumulator acc = BooleanAccumulator.treeGate(OR, cell.value()); + for(BooleanMatrix other : others) { + if (acc.add(other.fastGet(cell.index()))==BooleanConstant.TRUE) + break; + } + ret.fastSet(cell.index(), factory.accumulate(acc)); + } + + for(int i = 0, length = others.length; i < length; i++) { + for(IndexedEntry cell : others[i].cells) { + if (ret.cells.containsIndex(cell.index())) continue; + final BooleanAccumulator acc = BooleanAccumulator.treeGate(OR, cell.value()); + for(int j = i+1; j < length; j++) { + if (acc.add(others[j].fastGet(cell.index()))==BooleanConstant.TRUE) + break; + } + ret.fastSet(cell.index(), factory.accumulate(acc)); + } + } + + return ret; + } + + /** + * Returns the cross product of this and other matrix, using conjunction instead of + * multiplication. + * + * @return { m: BooleanMatrix | m = this x other } + * @throws NullPointerException other = null + * @throws IllegalArgumentException this.factory != other.factory + */ + public final BooleanMatrix cross(final BooleanMatrix other) { + checkFactory(this.factory, other.factory); + + final BooleanMatrix ret = new BooleanMatrix(dims.cross(other.dims), factory, cells, other.cells); + ret.mergeDefConds(this, other); + + if (cells.isEmpty() || other.cells.isEmpty()) return ret; + + final int ocap = other.dims.capacity(); + for(IndexedEntry e0 : cells) { + int i = ocap * e0.index(); + for(IndexedEntry e1: other.cells) { + BooleanValue conjunction = factory.and(e0.value(), e1.value()); + if (conjunction != FALSE) + ret.cells.put(i + e1.index(), conjunction); + } + } + + return ret; + } + + /** + * Updates the itrs and idxs arrays for the next step of the cross-product computation and returns a partial + * index based on the updated idxs values. + * @requires matrices.length = itrs.length = idxs.length + * @requires all m: matrices[int] | m.density() > 0 + * @requires currentIdx is a partial index based on the current value of idxs + * @ensures updates the itrs and idxs arrays for the next step cross-product computation + * @return a partial index based on the freshly updated idxs values. + */ + private static int nextCross(final BooleanMatrix[] matrices, final IntIterator[] itrs, final int[] idxs, int currentIdx) { + + int mult = 1; + for(int i = itrs.length-1; i >= 0; i--) { + if (itrs[i].hasNext()) { + final int old = idxs[i]; + idxs[i] = itrs[i].next(); + return currentIdx - mult*old + mult*idxs[i]; + } else { + itrs[i] = matrices[i].cells.indices().iterator(); + final int old = idxs[i]; + idxs[i] = itrs[i].next(); + currentIdx = currentIdx - mult*old + mult*idxs[i]; + mult *= matrices[i].dims.capacity(); + } + } + + return -1; + } + + /** + * Initializes the itrs and idxs arrays for cross-product computation and returns a partial + * index based on the freshly computed idxs values. + * @requires matrices.length = itrs.length = idxs.length + * @requires all m: matrices[int] | m.density() > 0 + * @ensures initializes the itrs and idxs arrays for cross-product computation + * @return a partial index based on the freshly computed idxs values. + */ + private static int initCross(final BooleanMatrix[] matrices, final IntIterator[] itrs, final int[] idxs) { + int mult = 1, idx = 0; + for(int i = matrices.length-1; i >= 0; i--) { + itrs[i] = matrices[i].cells.indices().iterator(); + idxs[i] = itrs[i].next(); + idx += mult*idxs[i]; + mult *= matrices[i].dims.capacity(); + } + return idx; + } + + /** + * Returns the cross product of this and other matrices, using conjunction instead of + * multiplication. + * @requires this.factory = others[int].factory + * @return others.length=0 => { m: BooleanMatrix | m.dimensions = this.dimensions && no m.elements } else + * { m: BooleanMatrix | m = this x others[0] x ... x others[others.length-1] } + * @throws NullPointerException others = null + * @throws IllegalArgumentException this.factory != others[int].factory + */ + public final BooleanMatrix cross(final BooleanMatrix...others) { + Dimensions retDims = dims; + boolean empty = cells.isEmpty(); + for(BooleanMatrix other : others) { + retDims = retDims.cross(other.dims); + empty = empty || other.cells.isEmpty(); + } + + final BooleanMatrix ret = new BooleanMatrix(retDims, this, others); + if (empty) return ret; + + final IntIterator[] itrs = new IntIterator[others.length]; + final int[] otherIdxs = new int[others.length]; + + final int ocap = retDims.capacity() / dims.capacity(); + + for(IndexedEntry cell : cells) { + final int idx = ocap * cell.index(); + for(int restIdx = initCross(others, itrs, otherIdxs); restIdx >= 0; restIdx = nextCross(others, itrs, otherIdxs, restIdx)) { + final BooleanAccumulator acc = BooleanAccumulator.treeGate(AND, cell.value()); + for(int i = others.length-1; i >= 0; i--) { + if (acc.add(others[i].fastGet(otherIdxs[i]))==BooleanConstant.FALSE) + break; + } + if (!acc.isShortCircuited()) { ret.fastSet(idx + restIdx, factory.accumulate(acc)); } + } + + } + + return ret; + } + + /** + * Sets the value at the specified index to the given value; + * returns the value previously at the specified position. + * It performs no index or null checking. + * + * @ensures this.elements'[index] = formula + */ + private final void fastSet(final int index, final BooleanValue formula) { + if (formula==FALSE) cells.remove(index); + else cells.put(index,formula); + } + + /** + * Returns the dot product of this and other matrix, using conjunction instead of + * multiplication and disjunction instead of addition. + * + * @return { m: BooleanMatrix | m = this*other } + * @throws NullPointerException other = null + * @throws IllegalArgumentException this.factory != other.factory + * @throws IllegalArgumentException dimensions incompatible for multiplication + */ + public final BooleanMatrix dot(final BooleanMatrix other) { + checkFactory(this.factory, other.factory); + + final BooleanMatrix ret = new BooleanMatrix(dims.dot(other.dims), factory, cells, other.cells); + ret.mergeDefConds(this, other); + + if (cells.isEmpty() || other.cells.isEmpty()) return ret; + + final SparseSequence mutableCells = ret.clone().cells; + final int b = other.dims.dimension(0); + final int c = other.dims.capacity() / b; + + for(IndexedEntry e0 : cells) { + int i = e0.index(); + BooleanValue iVal = e0.value(); + int rowHead = (i % b)*c, rowTail = rowHead + c - 1; + for(Iterator> iter1 = other.cells.iterator(rowHead, rowTail); iter1.hasNext();) { + IndexedEntry e1 = iter1.next(); + BooleanValue retVal = factory.and(iVal, e1.value()); + if (retVal != FALSE) { + int k = (i / b)*c + e1.index()%c; + if (retVal==TRUE) mutableCells.put(k, TRUE); + else { + BooleanValue kVal = mutableCells.get(k); + if (kVal != TRUE) { + if (kVal==null) { + kVal = BooleanAccumulator.treeGate(OR); + mutableCells.put(k, kVal); + } + ((BooleanAccumulator) kVal).add(retVal); + } + } + } + } + } + + // make mutable gates immutable + for(IndexedEntry e : mutableCells) { + if (e.value()!=TRUE) { + ret.fastSet(e.index(), factory.accumulate((BooleanAccumulator) e.value())); + } else { + ret.fastSet(e.index(), TRUE); + } + } + + return ret; + } + + /** + * Returns a formula stating that the entries in this matrix are a subset of + * the entries in the given matrix; i.e. the value of every entry in this matrix + * implies the value of the corresponding entry in the given matrix. + * @return { f: BooleanValue | f <=> (this.elements[0]=>other.elements[0]) AND ... + * AND (this.elements[this.dimensions.capacity-1]=>other.elements[this.dimensions.capacity-1])) + * @throws NullPointerException other = null + * @throws IllegalArgumentException !other.dimensions.equals(this.dimensions) || this.factory != other.factory + */ + public final BooleanValue subset(BooleanMatrix other, Environment env) { + checkFactory(this.factory, other.factory); checkDimensions(this.dims, other.dims); + final BooleanAccumulator a = BooleanAccumulator.treeGate(AND); + for(IndexedEntry e0: cells) { + if (a.add(factory.or(e0.value().negation(), other.fastGet(e0.index())))==FALSE) + return FALSE; + } + BooleanValue val = factory.accumulate(a); + return DefCond.ensureDef(factory, env, val, this.defCond(), other.defCond()); + } + + /** + * Returns a formula stating that the entries in this matrix are equivalent to + * the entries in the given matrix; i.e. the value of every entry in this matrix + * is true if and only if the value of the corresponding entry in the given matrix is true. + * The same formula can be obtained by calling factory.and(this.subset(other), other.subset(this)), + * but this method performs the operation more efficiently. + * @return { f: BooleanValue | f <=> (this.elements[0]<=>other.elements[0]) AND ... + * AND (this.elements[this.dimensions.capacity-1]<=>other.elements[this.dimensions.capacity-1])) + * @throws NullPointerException other = null + * @throws IllegalArgumentException !other.dimensions.equals(this.dimensions) || this.factory != other.factory + */ + public final BooleanValue eq(BooleanMatrix other, Environment env) { + BooleanValue val = factory.and(this.subset(other, env), other.subset(this, env)); + return DefCond.ensureDef(factory, env, val, this.defCond(), other.defCond()); + } + + /** + * Returns a matrix representing the asymmetric difference between + * the entries in this and the given matrix. The same matrix can + * be obtained by calling this.and(other.not()), but this method + * performs the operation more efficiently (intermediate + * values are not explicity created). + * @return { m: BooleanMatrix | m.dimensions = this.dimensions && m.factory = this.factory && + * all i: [0..m.dimensions.capacity) | + * m.elements[i] = this.elements[i] AND !other.elements[i] } + * @throws NullPointerException other = null + * @throws IllegalArgumentException !other.dimensions.equals(this.dimensions) || this.factory != other.factory + */ + public final BooleanMatrix difference(BooleanMatrix other) { + checkFactory(this.factory, other.factory); checkDimensions(this.dims, other.dims); + + final BooleanMatrix ret = new BooleanMatrix(dims, factory, cells, other.cells); + ret.mergeDefConds(this, other); + + for(IndexedEntry e0 : cells) { + ret.fastSet(e0.index(), factory.and(e0.value(), other.fastGet(e0.index()).negation())); + } + + return ret; + } + + /** + * Returns the transitive closure of this matrix. + * + * @return { m: BooleanMatrix | m = ^this } + * @throws UnsupportedOperationException #this.diensions != 2 || !this.dimensions.square() + */ + public final BooleanMatrix closure() { + if (dims.numDimensions() != 2 || !dims.isSquare()) { + throw new UnsupportedOperationException("#this.diensions != 2 || !this.dimensions.square()"); + } + if (cells.isEmpty()) + return clone(); + +// System.out.println("closure of " + this); + BooleanMatrix ret = this; + + // compute the number of rows in the matrix + int rowNum = 0; + final int rowFactor = dims.dimension(1); + for(IndexedEntry rowLead = cells.first(); + rowLead != null; rowLead = cells.ceil(((rowLead.index()/rowFactor) + 1) * rowFactor)) { + rowNum++; + } + + // compute closure using iterative squaring + for(int i = 1; i < rowNum; i*=2) { + ret = ret.or(ret.dot(ret)); + } +// System.out.println(ret); + return ret==this ? clone() : ret; + } + + /** + * Returns the transpose of this matrix. + * + * @return { m: BooleanMatrix | m = ~this } + * @throws UnsupportedOperationException #this.dimensions != 2 + */ + public final BooleanMatrix transpose() { + final BooleanMatrix ret = new BooleanMatrix(dims.transpose(), factory, cells, cells); + ret.mergeDefConds(this); + + final int rows = dims.dimension(0), cols = dims.dimension(1); + for (IndexedEntry e0 : cells) { + ret.cells.put((e0.index()%cols)*rows + (e0.index()/cols), e0.value()); + } + return ret; + } + + /** + * Returns a boolean matrix m such that m = this if the given condition evaluates + * to TRUE and m = other otherwise. + * + * @return { m: BooleanMatrix | m.dimensions = this.dimensions && + * all i: [0..m.dimensions.capacity) | + * m.elements[i] = condition => this.elements[i], other.elements[i] } + * @throws NullPointerException other = null || condition = null + * @throws IllegalArgumentException !other.dimensions.equals(this.dimensions) || this.factory != other.factory + */ + public final BooleanMatrix choice(BooleanValue condition, BooleanMatrix other) { + checkFactory(this.factory, other.factory); checkDimensions(this.dims, other.dims); + if (condition==TRUE) return this.clone(); + else if (condition==FALSE) return other.clone(); + + final BooleanMatrix ret = new BooleanMatrix(dims, factory); + final SparseSequence otherCells = other.cells; + for(IndexedEntry e0 : cells) { + BooleanValue v1 = otherCells.get(e0.index()); + if (v1==null) + ret.fastSet(e0.index(), factory.and(condition, e0.value())); + else + ret.fastSet(e0.index(), factory.ite(condition, e0.value(), v1)); + } + for(IndexedEntry e1 : other.cells) { + if (!cells.containsIndex(e1.index())) + ret.fastSet(e1.index(), factory.and(condition.negation(), e1.value())); + } + + BooleanValue of = factory.ite(condition, defCond().getOverflow(), other.defCond().getOverflow()); + BooleanValue accumOF = factory.ite(condition, defCond().getAccumOverflow(), other.defCond().getAccumOverflow()); + ret.defCond().setOverflows(of, accumOF); + return ret; + } + + /** + * Returns a matrix m such that the relational value of m is equal to the + * relational value of this projected on the specified columns. + * @requires column[int] in this.dimensions.dimensions[int] + * @requires this.dimensions.isSquare() + * @return { m: BooleanMatrix | [[m]] = project([[this]], columns) } + * @throws IllegalArgumentExceptions columns.length < 1 || !this.dimensions.isSquare() + * @throws NullPointerException columns = null + */ + public final BooleanMatrix project(Int[] columns) { + if (!dims.isSquare()) + throw new IllegalArgumentException("!this.dimensions.isSquare()"); + + final int rdnum = columns.length; + + if (rdnum < 1) + throw new IllegalArgumentException("columns.length < 1"); + + final Dimensions rdims = Dimensions.square(dims.dimension(0), rdnum); + final BooleanMatrix ret = new BooleanMatrix(rdims, factory, cells, cells); + ret.mergeDefConds(this); + + final int tdnum = dims.numDimensions(); + final int[] tvector = new int[tdnum]; + final int[] ivector = new int[rdnum]; + final int[] rvector = new int[rdnum]; + + int nVarCols = 1; + + // detect constant columns to avoid unnecessary looping; + for(int i = 0; i < rdnum; i++) { + if (columns[i].isConstant()) { + int value = columns[i].value(); + if (value < 0 || value >= tdnum) { + return ret; + } else { // distinguish constants by making them negative + ivector[i] = -value; + } + } else { + nVarCols *= tdnum; + } + } + + PROJECT : for(int i = 0; i < nVarCols; i++) { + BooleanValue colVal = TRUE; + for(int j = 0; j < rdnum; j++) { + // if the jth column is non-constant, check that it can take on the value ivector[j] + if (ivector[j] >= 0) { + colVal = factory.and(colVal, columns[j].eq(factory.integer(ivector[j]))); + if (colVal==FALSE) + continue PROJECT; + } + } + for(IndexedEntry e : cells) { + dims.convert(e.index(), tvector); + for(int j = 0; j < rdnum; j++) { + rvector[j] = tvector[StrictMath.abs(ivector[j])]; + } + int rindex = rdims.convert(rvector); + ret.fastSet(rindex, factory.or(factory.and(e.value(), colVal), ret.fastGet(rindex))); + } + for(int j = rdnum-1; j >= 0; j--) { // update ivector + // update ivector[j] only if the jth column is not constant + if (ivector[j]>=0) { + if (ivector[j]+1==tdnum) { + ivector[j] = 0; + } else { + ivector[j] += 1; + break; + } + } + } + } + + return ret; + } + + /** + * Returns a conjunction of the negated values between + * start, inclusive, and end, exclusive. + * @requires 0 <= start < end <= this.dimensions.capacity() + * @return !this.elements[start] && !this.elements[start+1] && ... && !this.elements[end-1] + */ + private final BooleanValue nand(int start, int end) { + final BooleanAccumulator g = BooleanAccumulator.treeGate(AND); + for(Iterator> iter = cells.iterator(start, end-1); iter.hasNext(); ) { + if (g.add(iter.next().value().negation())==FALSE) + return FALSE; + } + return factory.accumulate(g); + } + + /** + * Overrides the values in this matrix with those in other. + * Specifically, for each index i of the returned matrix m, + * m.elements[i] is true iff other.elements[i] is true or + * this.elements[i] is true and all elements of other + * that are in the same row as i are false. + * @return {m: BooleanMatrix | m.dimensions = this.dimensions && + * all i: [0..m.capacity()) | m.elements[i] = + * other.elements[i] || + * this.elements[i] && !OR(other.elements[row(i)]) } + * where other.elements[row(i)] selects all elements of other + * that are in the same row as i. + * @throws NullPointerException other = null + * @throws IllegalArgumentException other.dimensions != this.dimensions + */ + public final BooleanMatrix override(BooleanMatrix other) { + checkFactory(this.factory, other.factory); checkDimensions(this.dims, other.dims); + if (other.cells.isEmpty()) return this.clone(); + + final BooleanMatrix ret = new BooleanMatrix(dims, factory, cells, other.cells); + ret.mergeDefConds(this, other); + + ret.cells.putAll(other.cells); + final int rowLength = dims.capacity() / dims.dimension(0); + int row = -1; + BooleanValue rowVal = BooleanConstant.TRUE; + for(IndexedEntry e0 : cells) { + int e0row = e0.index() / rowLength; + if (row != e0row) { + row = e0row; + rowVal = other.nand(row*rowLength, (row+1)*rowLength); + } + ret.fastSet(e0.index(), factory.or(ret.fastGet(e0.index()), + factory.and(e0.value(), rowVal))); + } + return ret; + } + + /** + * Overrides the values in this matrix with those in other. + * @return others.length = 0 => { m: BooleanMatrix | m.dimensions = this.dimensions && m.elements = this.elements) else + * others.length = 1 => {m: BooleanMatrix | m.dimensions = this.dimensions && + * all i: [0..m.capacity()) | m.elements[i] = + * other.elements[i] || this.elements[i] && !OR(other.elements[rowOf(i)]) } else + * this.override(others[0).override(others[1..others.length)) + * @throws NullPointerException others = null + * @throws IllegalArgumentException others[int].factory != this.factory or others[int].dimensions != this.dimensions + */ + public final BooleanMatrix override(BooleanMatrix... others) { + if (others.length==0) return clone(); + final BooleanMatrix[] matrices = Containers.copy(others, 0, new BooleanMatrix[others.length+1], 1, others.length); + matrices[0] = this; + for(int part = matrices.length; part > 1; part -= part/2) { + final int max = part-1; + for(int i = 0; i < max; i += 2) { + matrices[i/2] = matrices[i].override(matrices[i+1]); + } + if (max%2==0) { // even max => odd number of entries + matrices[max/2] = matrices[max]; + } + } + return matrices[0]; + } + + /** + * Returns an Int that represents the cardinality (number of non-FALSE entries) of this + * matrix using this.factory.intEncoding. + * @return {i: Int | [[i]] = sum({v: elements[int] | if [[v]] then 1 else 0}) } + */ + public final Int cardinality() { + final Int ret = factory.sum(cells.values()); + BooleanValue accum = DefCond.merge(factory, ret.defCond(), this.defCond()); + ret.defCond().setOverflows(ret.defCond().getOverflow(), accum); + return ret; + } + + /** + * Returns a BooleanValue that constrains at least one value in this.elements to be true. The + * effect of this method is the same as calling this.orFold(). + * @return { f: BooleanValue | f <=> this.elements[0] || ... || this.elements[this.dimensions.capacity-1] } + */ + public final BooleanValue some(Environment env) { + final BooleanAccumulator g = BooleanAccumulator.treeGate(OR); + for(IndexedEntry e : cells) { + if (g.add(e.value())==TRUE) + return TRUE; + } + final BooleanValue val = factory.accumulate(g); + return DefCond.ensureDef(factory, env, val, this.defCond()); + } + + /** + * Returns a BooleanValue that constrains at most one value in this.elements to be true. + * The effect of this method is the same as calling this.factory.or(this.one(), this.none()). + * @return { f: BooleanValue | f <=> this.one() || this.none() } + */ + public final BooleanValue lone(Environment env) { + if (cells.isEmpty()) + return TRUE; + else { + final BooleanAccumulator g = BooleanAccumulator.treeGate(AND); + + BooleanValue partial = FALSE; + for(IndexedEntry e: cells) { + if (g.add(factory.or(e.value().negation(), partial.negation()))==FALSE) + return FALSE; + partial = factory.or(partial, e.value()); + } + + final BooleanValue val = factory.accumulate(g); + return DefCond.ensureDef(factory, env, val, this.defCond()); + } + } + + /** + * Returns a BooleanValue that constraints exactly one value in this.elements to be true. + * @return { f: BooleanValue | f <=> #this.elements[int] = 1 } + */ + public final BooleanValue one(Environment env) { + if (cells.isEmpty()) + return FALSE; + else { + final BooleanAccumulator g = BooleanAccumulator.treeGate(AND); + + BooleanValue partial = FALSE; + for(IndexedEntry e: cells) { + if (g.add(factory.or(e.value().negation(), partial.negation()))==FALSE) + return FALSE; + partial = factory.or(partial, e.value()); + } + g.add(partial); + + final BooleanValue val = factory.accumulate(g); + return DefCond.ensureDef(factory, env, val, this.defCond()); + } + } + + /** + * Returns a BooleanValue that constraints all values in this.elements to be false. + * The effect of this method is the same as calling this.factory.not(this.some()). + * @return { f: BooleanValue | f <=> !(this.elements[0] || ... || !this.elements[this.dimensions.capacity-1]) } + */ + public final BooleanValue none(Environment env) { + env.negate(); + BooleanValue val = some(env).negation(); + env.negate(); + return val; + } + + /** + * Sets the specified index to the given value. + * + * @requires value in this.factory.components + * @ensures this.elements'[index] = value + * @throws NullPointerException value = null + * @throws IllegalArgumentException the given is a formula, and this matrix accepts only constants + * @throws IndexOutOfBoundsException the given index does not belong to the set of indices at which + * this matrix can store non-FALSE values. + */ + public final void set(final int index, final BooleanValue value) { + if (!dims.validate(index)) throw new IndexOutOfBoundsException("index < 0 || index >= this.dimensions.capacity"); + if (value==null) throw new NullPointerException("formula=null"); + if (value==FALSE) + cells.remove(index); + else + cells.put(index,value); + } + + /** + * Returns a copy of this boolean matrix. + * @return {m: BooleanMatrix - this | m.dimensions = this.dimensions && + * m.elements = copy of this.elements } + */ + public BooleanMatrix clone() { + try { + final BooleanMatrix ret = new BooleanMatrix(dims, factory, cells.clone()); + ret.mergeDefConds(this); + return ret; + } catch (CloneNotSupportedException e) { + throw new InternalError(); // unreachable code. + } + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + final StringBuilder buff = new StringBuilder("dimensions: "); + buff.append(dims); + buff.append(", elements: "); + buff.append(cells); + return buff.toString(); + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanValue.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanValue.java new file mode 100644 index 00000000..ab5fcf6b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanValue.java @@ -0,0 +1,72 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.bool; + +/** + * Represents a boolean value, which may be a {@link kodkod.engine.bool.BooleanFormula formula} + * or a {@link kodkod.engine.bool.BooleanConstant constant}. Boolean formulas are produced by + * {@link kodkod.engine.bool.BooleanFactory circuit factories}. Each value is associated with + * an integer label; the labels are unique within a given factory. + * A boolean value with a negative label -|l| represents the negation of the value with the positive + * label |l|. Non-constant values are not shared among factories. + * + * @specfield op: Operator + * @specfield label: [-Integer.MAX_VALUE, Integer.MAX_VALUE] + * @invariant no c: BooleanValue - this | some components.c & components.this && c.label = this.label + * @author Emina Torlak + */ +public abstract class BooleanValue implements Comparable { + + BooleanValue() {} + + /** + * Returns the negation of this boolean value + * @return { f: BooleanFormula | [[f]] = ![[this]] } + */ + abstract BooleanValue negation(); + + /** + * Returns the label for this value. + * @return this.label + */ + public abstract int label(); + + /** + * Returns the operator representing the function + * computed by this gate. + * @return this.op + */ + public abstract Operator op(); + + /** + * Boolean components are ordered according to their labels. + * Note that the ordering is well defined on components produced by the same factory. + * Specifically, this comparison function is consistent with equals for the components + * produced by the same factory, but may not be for the components produced by different factories. + * @return 0 if the label of this and other are the same, a negative + * integer if the label of this is smaller than the label of other; and + * a positive integer otherwise. + */ + public final int compareTo(BooleanValue other) { + return label() - other.label(); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanVariable.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanVariable.java new file mode 100644 index 00000000..0176a21c --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanVariable.java @@ -0,0 +1,131 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.bool; + +import java.util.Iterator; + +import kodkod.util.collections.Containers; +import kodkod.util.ints.Ints; + + +/** + * Represents a boolean variable. + * + * @invariant op = Operator.VAR + * @invariant no inputs && label in [1, ..., Integer.MAX_VALUE) + * @author Emina Torlak + */ +public final class BooleanVariable extends BooleanFormula { + final int label; + private final int hashcode; + + /** + * Constructs a new BooleanVariable with the given label. + * @requires label != 0 + * @ensures this.label' = label + */ + BooleanVariable(int label) { + super(null); + assert label != 0; + this.label = label; + this.hashcode = Ints.superFastHash(label); + } + + /** + * Returns a hash of this variable's label. + * @return Ints.superFastHash(this.label) + */ + @Override + int hash(Operator op) { + return hashcode; + } + + /** + * Returns the label for this value. + * @return this.label + */ + @Override + public int label() { return label; } + + /** + * Returns a string representation of this variable. + * @return a string representation of this variable. + */ + public String toString() { + return Integer.toString(label); + } + + /** + * Passes this value and the given + * argument value to the visitor, and returns the resulting value. + * @return the value produced by the visitor when visiting this node + * with the given argument. + */ + @Override + public T accept(BooleanVisitor visitor, A arg) { + return visitor.visit(this, arg); + } + + /** + * Returns the VAR operator. + * @return Operator.VAR + */ + @Override + public Operator op() { + return Operator.VAR; + } + + /** + * Returns an empty iterator. + * @return an empty iterator + */ + @Override + public Iterator iterator() { + return Containers.emptyIterator(); + } + + /** + * Returns 0. + * @return 0 + */ + @Override + public int size() { + return 0; + } + + /** + * Throws an IndexOutOfBoundsException. + * @throws IndexOutOfBoundsException + */ + @Override + public BooleanFormula input(int i) { + throw new IndexOutOfBoundsException(); + } + + /** + * Returns a hashcode for this variable. + * @return a hashcode for this variable. + */ + public int hashCode() { + return hashcode; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanVisitor.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanVisitor.java new file mode 100644 index 00000000..df4867f0 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/BooleanVisitor.java @@ -0,0 +1,57 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.bool; + +/** + * Visits {@link kodkod.engine.bool.BooleanFormula boolean formulas}. + * In addition to passing themselves as the argument to the visitor, + * the boolean values also pass along satelite information of type A. + * + * @author Emina Torlak + */ +public interface BooleanVisitor { + + /** + * Visits the multigate and returns the result. + * @return the result of visiting the given multigate + */ + public T visit(MultiGate multigate, A arg); + + /** + * Visits the if-then-else gate and returns the result. + * @return the result of visiting the given ITEGate + */ + public T visit(ITEGate ite, A arg); + + /** + * Visits the inverter and returns the result. + * @return the result of visiting the given inverter + */ + public T visit(NotGate negation, A arg); + + /** + * Visits the variable and returns the result. + * @return the result of visiting the given variable + */ + public T visit(BooleanVariable variable, A arg); + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/CBCFactory.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/CBCFactory.java new file mode 100644 index 00000000..7b509d5a --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/CBCFactory.java @@ -0,0 +1,670 @@ + +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package kodkod.engine.bool; + +import static kodkod.engine.bool.BooleanConstant.FALSE; +import static kodkod.engine.bool.BooleanConstant.TRUE; +import static kodkod.engine.bool.Operator.AND; +import static kodkod.engine.bool.Operator.CONST; +import static kodkod.engine.bool.Operator.ITE; +import static kodkod.engine.bool.Operator.NOT; +import static kodkod.engine.bool.Operator.OR; +import static kodkod.engine.bool.Operator.VAR; + +import java.util.Iterator; +import java.util.Set; + +import kodkod.ast.operator.ExprOperator; +import kodkod.engine.bool.Operator.Nary; +import kodkod.util.collections.CacheSet; +import kodkod.util.collections.IdentityHashSet; + + +/** + * A factory for creating variables, multigates, and if-then-else gates. + * @specfield values: set (BooleanVariable + MultiGate + ITEGate) + * @specfield cmpMax: int // the maximum number of comparisons made when comparing circuits for equality + * @invariant no disj factory, factory' : CircuitFactory | some factory.values & factory'.values + * @author Emina Torlak + */ +final class CBCFactory { + + /** + * Sets used as `scrap paper' for gate comparisons. Its capacity is 2^(depth), where + * depth is the depth to which gates should be checked for equality. + */ + private final Set scrap0, scrap1; + /** + * Stores input variables. + * @invariant all i: [1..iLits.size()] | vars[i-1].positive.label = i + */ + private final BooleanVariable[] vars; + /** + * Caches the AND, OR, and ITE gates. + * @invariant all i: [0..2] | c[i].op.ordinal = i + */ + private final CacheSet[] cache; + private int label, cmpMax; + + + + /** + * Constructs a CircuitFactory using the given max comparison parameter, initialized + * to contain the given number of variables. + * @requires cmpMax > 0 && numVars >= 0 + * @ensures #this.values' = numVars && this.values in BooleanVariable + * @ensures this.cmpMax' = cmpMax + */ + @SuppressWarnings("unchecked") CBCFactory(int numVars, int cmpMax) { + assert cmpMax > 0 && numVars >= 0; + this.cmpMax = cmpMax; + this.label = numVars + 1; + vars = new BooleanVariable[numVars]; + for(int i = 0; i < numVars; i++) { + vars[i]= new BooleanVariable(i+1); + } + scrap0 = new IdentityHashSet(cmpMax); + scrap1 = new IdentityHashSet(cmpMax); + cache = new CacheSet[]{new CacheSet(), new CacheSet(), new CacheSet()}; + } + + /** + * Returns the cache for gates with the given operator. + * @requires op in AND + OR + ITE + * @return cache[op.ordinal] + */ + private CacheSet opCache(Operator op) { + return cache[op.ordinal]; + } + + /** + * Sets this.cmpMax to the given value. + * @requires cmpMax > 0 + * @ensures this.cmpMax' = cmpMax + */ + void setCmpMax(int cmpMax) { + assert cmpMax > 0; + this.cmpMax = cmpMax; + } + + /** + * Returns this.cmpMax. + * @return this.cmpMax + */ + int cmpMax() { return cmpMax; } + + /** + * Removes all MultiGates and ITEGates from this.factory. + * @ensures this.values' = this.values & BooleanVariable + */ + void clear() { + label = vars.length+1; + cache[0].clear(); + cache[1].clear(); + cache[2].clear(); + scrap0.clear(); + scrap1.clear(); + } + + /** + * Returns true if the given value + * is a valid argument to one of the assemble + * methods. Otherwise returns false. + * @return v in this.values + this.values.negation + BooleanConstant + */ + boolean canAssemble(BooleanValue v) { + if (v.op()==CONST) return true; + if (v.label() < 0) v = v.negation(); + final int absLit = v.label(); + if (absLit <= vars.length) { + return v == vars[absLit-1]; + } else { + final BooleanFormula g = (BooleanFormula) v; + for(Iterator gates = opCache(g.op()).get(g.hashCode()); gates.hasNext(); ) { + if (gates.next()==g) return true; + } + return false; + } + } + + /** + * Returns the number of variables in this factory. + * @return #(this.values & BooleanVariable) + */ + int numVars() { return vars.length; } + + /** + * Returns the boolean variable from this.values with the given label. + * @requires 0 < label <= #(this.values & BooleanVariable) + * @return (this.values & BooleanVariable).label + */ + BooleanVariable variable(int label) { + return vars[label-1]; + } + + /** + * Returns a boolean value whose meaning is (if [[i]] then [[t]] else [[e]]). + * @requires i + t + e in (this.values + this.values.negation + BooleanConstant) + * @return v: BooleanValue | [[v]] = if [[i]] then [[t]] else [[e]] + * @ensures v in BooleanFormula - NotGate => this.values' = this.values + v, this.values' = this.values + * @throws NullPointerException - any of the arguments are null + */ + BooleanValue assemble(BooleanValue i, BooleanValue t, BooleanValue e) { + if (i==TRUE || t==e) return t; + else if (i==FALSE) return e; + else if (t==TRUE || i==t) return assemble(OR, i, e); + else if (t==FALSE || i.label()==-t.label()) return assemble(AND, i.negation(), e); + else if (e==TRUE || i.label()==-e.label()) return assemble(OR, i.negation(), t); + else if (e==FALSE || i==e) return assemble(AND, i, t); + else { + final BooleanFormula f0 = (BooleanFormula) i, f1 = (BooleanFormula) t, f2 = (BooleanFormula) e; + final int hash = ITE.hash(f0, f1, f2); + + for(Iterator gates = opCache(ITE).get(hash); gates.hasNext();) { + BooleanFormula gate = gates.next(); + if (gate.input(0)==i && gate.input(1)==t && gate.input(2)==e) + return gate; + } + final BooleanFormula ret = new ITEGate(label++, hash, f0, f1, f2); + opCache(ITE).add(ret); + return ret; + } + } + + /** + * Returns a boolean value whose meaning is ([[v0]] op [[v1]]). + * @requires v0 + v1 in (this.values + this.values.negation + BooleanConstant) + * @return v: BooleanValue | [[v]] = [[v0]] op [[v1]] + * @ensures v in BooleanFormula - NotGate => this.values' = this.values + v, this.values' = this.values + * @throws NullPointerException - any of the arguments are null + */ + BooleanValue assemble(Operator.Nary op, BooleanValue v0, BooleanValue v1) { + final BooleanValue l, h; + if (v0.op().ordinal < v1.op().ordinal) { + l = v0; h = v1; + } else { + l = v1; h = v0; + } + if (h.op()==CONST) + return h==op.identity() ? l : h; + else + return assembler(l.op(), h.op()).assemble(op, (BooleanFormula)l, (BooleanFormula)h); + } + + /** + * Returns a boolean value with the same meaning as the given accumulator. + * @requires acc.components in (this.values + this.values.negation + BooleanConstant) + * @return v: BooleanValue | [[v]] = [[acc]] + * @ensures v in BooleanFormula - NotGate => this.values' = this.values + v, this.values' = this.values + * @throws NullPointerException - any of the arguments are null + */ + @SuppressWarnings("unchecked") + BooleanValue assemble(BooleanAccumulator acc) { + final int asize = acc.size(); + final Operator.Nary op = acc.op; + switch(asize) { + case 0 : return op.identity(); + case 1 : return acc.iterator().next(); + case 2 : + final Iterator inputs = acc.iterator(); + return assemble(op, inputs.next(), inputs.next()); + default : + @SuppressWarnings("rawtypes") + final int hash = op.hash((Iterator)acc.iterator()); + if (asize > cmpMax) { + for(Iterator gates = opCache(op).get(hash); gates.hasNext(); ) { + BooleanFormula g = gates.next(); + if (g.size()==asize && ((NaryGate) g).sameInputs(acc.iterator())) { + return g; + } + } + } else { + LOOKUP: for(Iterator gates = opCache(op).get(hash); gates.hasNext(); ) { + BooleanFormula g = gates.next(); + if (g.size()==asize && ((NaryGate) g).sameInputs(acc.iterator())) { + return g; + } else if (g.size() < asize) { + scrap0.clear(); + g.flatten(op, scrap0, cmpMax); + if (scrap0.size()==asize) { + for(BooleanValue v : acc) { + if (!scrap0.contains(v)) + continue LOOKUP; + } + return g; + } + } + } + } + final BooleanFormula ret = new NaryGate(acc, label++, hash); + opCache(acc.op).add(ret); + return ret; + } + } + + /** + * Given two operators, op0 and op1, returns an Assembler + * which contains the creator method for expressions of the form v0 op v1 where + * op in ExprOperator.Nary and v0.op = op0 and v1.op = op1. + * @requires op0 <= op1 && no (op0 + op1) & CONST + * @requires op0 != null && op1 != null + * @return a Assembler which contains the creator method for expressions of the form v0 op v1 where + * op in ExprOperator.Nary and v0.op = op0 and v1.op = op1. + */ + private Assembler assembler(Operator op0, Operator op1) { + return ASSEMBLERS[(op0.ordinal << 2) + op1.ordinal - ( (op0.ordinal*(op0.ordinal-1) >> 1 ))]; + } + + /** + * Returns a BooleanFormula f such that [[f]] = f0 op f1. The method + * requires that the formulas f0 and f1 be already reduced with respect to op. + * A new formula is created and cached iff the circuit with the meaning + * [[f0]] op [[f1]] has not already been created. + * @requires f0 and f1 have already been reduced with respect to op; i.e. + * f0 op f1 cannot be reduced to a constant or a simple circuit + * by applying absorption, idempotence, etc. laws to f0 and f1. + * @return f : BooleanFormula | [[f]] = [[f0]] op [[f1]] + * @ensures f !in this.values => this.values' = this.values + f, + * this.values' = this.values + */ + private BooleanFormula cache(Operator.Nary op, BooleanFormula f0, BooleanFormula f1) { + final BooleanFormula l, h; + if (f0.label() gates = opCache(op).get(hash); gates.hasNext(); ) { + BooleanFormula gate = gates.next(); + if (gate.size()==2 && gate.input(0)==l && gate.input(1)==h) + return gate; + else { + scrap1.clear(); + gate.flatten(op, scrap1, cmpMax); + if (scrap0.equals(scrap1)) + return gate; + } + } + } else { + for(Iterator gates = opCache(op).get(hash); gates.hasNext(); ) { + BooleanFormula gate = gates.next(); + if (gate.size()==2 && gate.input(0)==l && gate.input(1)==h) + return gate; + } + } + final BooleanFormula ret = new BinaryGate(op, label++, hash, l, h); + opCache(op).add(ret); + return ret; + } + + /** + * Wrapper for a method that generates boolean values + * out of existing gates, using AND and OR operators. + * @author Emina Torlak + */ + private static abstract class Assembler { + + /** + * Returns a BooleanValue whose meaning is [[f0]] op [[f1]]. A + * new circuit is created and cached iff [[f0]] op [[f1]] cannot be reduced + * to a simpler value and a circuit with equivalent meaning has not already been created. + * @requires f0.op <= f1.op && f0 + f1 in CircuitFactory.this.values + CircuitFactory.this.values.negation + * @return { v: BooleanValue | [[v]] = [[f0]] op [[f1]] } + * @ensures (no v: CircuitFactory.this.values | [[v]] = [[f0]] op [[f1]]) => + * CircuitFactory.this.values' = CircuitFactory.this.values + {v: BooleanValue | [[v]] = [[f0]] op [[f1]]} => + * CircuitFactory.this.values' = CircuitFactory.this.values + */ + abstract BooleanValue assemble(Operator.Nary op, BooleanFormula f0, BooleanFormula f1); + } + + /** + * Performs common simplifications on circuits of the form AND op X or OR op X, + * where X can be any operator other than CONST (J stands for 'junction'). + */ + private final Assembler JoX = new Assembler() { + /** + * Performs the following reductions, if possible. Note that + * these reductions will be possible only if f0 was created after f1 (i.e. |f0.label| > |f1.label|). + * (a & b) & a = a & b (a & b) & !a = F (a & b) | a = a + * (a | b) | a = a | b (a | b) | !a = T (a | b) & a = a + * @requires f0.op in (AND + OR) + */ + BooleanValue assemble(Nary op, BooleanFormula f0, BooleanFormula f1) { + assert f0.op().ordinal < 2; + final int label = f1.label(); + if (f0.contains(f0.op(), label, cmpMax) > 0) + return op==f0.op() ? f0 : f1; + else if (op==f0.op() && f0.contains(op, -label, cmpMax)>0) + return op.shortCircuit(); + else + return cache(op, f0, f1); + } + }; + + /** + * Performs common simplifications on circuits of the form AND op OR. + */ + private final Assembler AoO = new Assembler() { + /** + * Performs the following reductions, if possible, along with JoX reductions. + * (aj & ... & ak) & (a1 | ... | an) = (aj & ... & ak) where 1 <= j <= k <= n + * (a1 & ... & an) | (aj | ... | ak) = (aj | ... | ak) where 1 <= j <= k <= n + * @requires f0.op = AND && f1.op = OR + */ + BooleanValue assemble(Nary op, BooleanFormula f0, BooleanFormula f1) { + assert f0.op() == AND && f1.op() == OR; + scrap0.clear(); + scrap1.clear(); + f0.flatten(f0.op(), scrap0, cmpMax); + f1.flatten(f1.op(), scrap1, cmpMax); + for(BooleanFormula formula : scrap1) { + if (scrap0.contains(formula)) + return op==AND ? f0 : f1; + } + return (f0.label() < f1.label()) ? JoX.assemble(op, f1, f0) : JoX.assemble(op, f0, f1); + } + }; + + /** + * Performs common simplifications on circuits of the form AND op AND or OR op OR. + */ + private final Assembler JoJ = new Assembler() { + /** + * Performs the following reductions, if possible, along with the JoX reductions. + * (a1 & ... & an) & (aj & ... & ak) = (a1 & ... & an) where 1 <= j <= k <= n + * (a1 & ... & an) | (aj & ... & ak) = (aj & ... & ak) where 1 <= j <= k <= n + * (a1 | ... | an) | (aj | ... | ak) = (a1 | ... | an) where 1 <= j <= k <= n + * (a1 | ... | an) & (aj | ... | ak) = (aj | ... | ak) where 1 <= j <= k <= n + * @requires f0.op = f1.op && (f0+f1).op in (AND + OR) + */ + BooleanValue assemble(Nary op, BooleanFormula f0, BooleanFormula f1) { + assert f0.op() == f1.op(); + if (f0==f1) return f0; + final Operator fop = f0.op(); + scrap0.clear(); + scrap1.clear(); + f0.flatten(fop, scrap0, cmpMax); + f1.flatten(fop, scrap1, cmpMax); + if (scrap0.size() < scrap1.size() && scrap1.containsAll(scrap0)) + return op==fop ? f1 : f0; + else if (scrap0.size() >= scrap1.size() && scrap0.containsAll(scrap1)) + return op==fop ? f0 : f1; + else if (f0.label() |f1.label|). + * !(a | b) & a = F !(a | b) & !a = !(a | b) + * !(a & b) | a = T !(a & b) | !a = !(a & b) + * @requires f0.op = NOT + */ + BooleanValue assemble(Nary op, BooleanFormula f0, BooleanFormula f1) { + assert f0.op() == NOT ; + final int label = f1.label(); + if (f0.input(0).contains(op.complement(), label, cmpMax)>0) return op.shortCircuit(); + else if (f0.input(0).contains(op.complement(), -label, cmpMax)>0) return f0; + else return cache(op, f0, f1); + } + }; + + /** + * Performs common simplifications on circuits of the form NOT op NOT. + */ + private final Assembler NoN = new Assembler() { + /** + * Performs the following reductions, if possible, along with NoX reductions. + * !a & !a = !a !a | !a = !a + * @requires f1.op + f0.op = NOT + */ + BooleanValue assemble(Nary op, BooleanFormula f0, BooleanFormula f1) { + assert f0.op() == NOT && f1.op() == NOT; + if (f0==f1) return f0; + else if (f0.label() < f1.label()) // f0 created after f1 + return NoX.assemble(op, f0, f1); + else + return NoX.assemble(op, f1, f0); + } + }; + + /** + * Performs common simplifications on circuits of the form NOT op VAR. + */ + private final Assembler NoV = new Assembler() { + /** + * Performs the following reductions, if possible, along with NoX reductions. + * !a & a = F !a | a = T + * @requires f1.op = NOT && f1.op = VAR + */ + BooleanValue assemble(Nary op, BooleanFormula f0, BooleanFormula f1) { + assert f0.op() == NOT && f1.op() == VAR; + if (f0.label()==-f1.label()) return op.shortCircuit(); + else return NoX.assemble(op, f0, f1); + } + }; + + + /** + * Performs common simplifications on circuits of the form X op X. + */ + private final Assembler XoX = new Assembler() { + /** + * Performs the following reductions, if possible. + * a & a = a a | a = a + * @requires f0.op = f1.op + */ + @Override + BooleanValue assemble(Nary op, BooleanFormula f0, BooleanFormula f1) { + assert f0.op()==f1.op(); + return (f0==f1) ? f0 : cache(op, f0, f1); + } + }; + + + /** + * 15 Assembler entires representing all possible composition combinations of + * non-constant vertices using the operators AND and OR. Note that there + * are 15 of them rather than 25 because of the v0.op <= v1.op requirement + * of the {@link Assembler#assemble(ExprOperator.Nary, BooleanFormula, BooleanFormula)} method. + */ + private final Assembler[] ASSEMBLERS = { + JoJ, /* AND op AND */ + AoO, /* AND op OR */ + JoI, /* AND op ITE */ + JoN, /* AND op NOT */ + JoX, /* AND op VAR */ + JoJ, /* OR op OR */ + JoI, /* OR op ITE */ + JoN, /* OR op NOT */ + JoX, /* OR op VAR */ + XoX, /* ITE op ITE */ + IoN, /* ITE op NOT */ + IoV, /* ITE op VAR */ + NoN, /* NOT op NOT */ + NoV, /* NOT op VAR */ + XoX /* VAR op VAR */ + }; + +// /** +// * Returns true if for all inputs i1 in f1 there is a corresponding input i0 in +// * f0 such that i0.label = i1.label +// * @requires #f0.inputs <= f1.inputs +// */ +// private static boolean containsAll(BooleanFormula f0, BooleanFormula f1) { +// final int s0 = f0.size(), s1 = f1.size(); +// for(int i = 0, j = 0; i=0;) { +// final int l0 = f0.input(i).label(), l1 = -f1.input(j).label(); +// if (l0 < l1) { +// i++; +// } else if (l0 == l1) { +// i++; j--; +// } else { +// return false; +// } +// } +// return true; +// } +// +// /** +// * Returns true if there are inputs i0 in f0 and i1 in f1 such that i0.label = i1.label +// * @requires #f0.inputs <= f1.inputs +// */ +// private static boolean containsSome(BooleanFormula f0, BooleanFormula f1) { +// final int s0 = f0.size(), s1 = f1.size(); +// for(int i = 0, j = 0; i=0;) { +// final int l0 = f0.input(i).label(), l1 = -f1.input(j).label(); +// if (l0 < l1) { +// i++; +// } else if (l0 == l1) { +// return true; +// } else { +// j--; +// } +// } +// return false; +// } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/DefCond.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/DefCond.java new file mode 100644 index 00000000..5c75367a --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/DefCond.java @@ -0,0 +1,117 @@ +package kodkod.engine.bool; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import kodkod.ast.Variable; +import kodkod.ast.operator.Quantifier; +import kodkod.engine.fol2sat.Environment; + +public class DefCond { + + /* ------------------------------------------------------------------------------------ */ + /* used during translation */ + /* ------------------------------------------------------------------------------------ */ + + private BooleanValue overflow = BooleanConstant.FALSE; + private BooleanValue accumOverflow = BooleanConstant.FALSE; + private Set vars = new HashSet(); + + public BooleanValue getOverflow() { return overflow; } + public BooleanValue getAccumOverflow() { return accumOverflow; } + public void setOverflows(BooleanValue of, BooleanValue accumOF) { + this.overflow = of; + this.accumOverflow = accumOF; + } + + public void addVar(Variable v) { vars.add(v); } + public void addVars(Collection vars) { this.vars.addAll(vars); } + public Set vars() { return vars; } + + /** + * ORs overflow circuits of this object ( + * this.mergedOverflow), a given other object ( + * other.mergedOverflow), and a given overflow circuit ( + * of) + */ + public static BooleanValue merge(BooleanFactory factory, BooleanValue accum, DefCond ... conds) { + BooleanValue ret = accum; + for (DefCond dc : conds) { + ret = factory.or(ret, dc.accumOverflow); + } + return ret; + } + + public static BooleanValue merge(BooleanFactory factory, DefCond ... conds) { + return merge(factory, BooleanConstant.FALSE, conds); + } + + /** + * If overflow checking is disabled returns value. Otherwise, + * returns a conjunction of value, lhs.accumOverflow, + * and rhs.accumOverflow. + * + * ~~~ NOTE ~~~: Every time a BooleanValue is returned as a result of an operation + * over Ints, one of the ensureNoOverflow methods + * should be called. + */ + public static BooleanValue ensureDef(BooleanFactory factory, Environment env, + BooleanValue value, DefCond ... dcs) { + if (!factory.noOverflow) + return value; + List univQuantInts = new ArrayList(dcs.length); + List extQuantInts = new ArrayList(dcs.length); + for (DefCond e : dcs) { + if (isUnivQuant(env, e)) + univQuantInts.add(e); + else + extQuantInts.add(e); + } + BooleanValue ret = value; + if (!env.isNegated()) { + for (DefCond e : extQuantInts) ret = factory.and(ret, factory.not(e.getAccumOverflow())); + for (DefCond e : univQuantInts) ret = factory.or(ret, e.getAccumOverflow()); + } else { + for (DefCond e : extQuantInts) ret = factory.or(ret, e.getAccumOverflow()); + for (DefCond e : univQuantInts) ret = factory.and(ret, factory.not(e.getAccumOverflow())); + } + return ret; + } + + private static boolean isUnivQuant(Environment env, DefCond e) { + if (env.isEmpty()) + return false; +// if (!isInt(env.type())) +// return isUnivQuant(env.parent(), e); + if (e.vars().contains(env.variable())) { + return env.envType() == Quantifier.ALL; + } else { + return isUnivQuant(env.parent(), e); + } + } + +// /** +// * Returns if this expression represents the Int type. +// */ +// private static boolean isInt(Object expression) { +// if (expression == null) +// return false; +// if (!(expression instanceof Expression)) +// return false; +// // TODO: this is probably not complete +// return "ints".equals(expression.toString()); +// } + + /* ------------------------------------------------------------------------------------ */ + /* used by the evaluator */ + /* ------------------------------------------------------------------------------------ */ + + private boolean isOverflowFlag = false; + + public void setOverflowFlag(boolean overflow) { this.isOverflowFlag = overflow; } + public boolean isOverflowFlag() { return this.isOverflowFlag; } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/Dimensions.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/Dimensions.java new file mode 100644 index 00000000..ce300382 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/Dimensions.java @@ -0,0 +1,472 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.bool; + +import kodkod.engine.CapacityExceededException; +import kodkod.util.ints.Ints; + + + + +/** + * Stores information about the size of a matrix. Specifically, + * for an n-dimensional matrix n, a Dimensions object is abstractly + * a vector consisting of n integers; the ith integer in the vector + * represents the size of the ith dimension of a matrix. + * + * @specfield n: int + * @specfield dimensions: [0..n) -> one int + * @specfield capacity: dimensions[0] x ... x dimensions[n-1] + * @invariant n > 0 + * + * @author Emina Torlak + */ +public abstract class Dimensions { + private final int capacity; + + /** + * Constructs a Dimensions with the given capacity. + */ + private Dimensions(int capacity) { + this.capacity = capacity; + } + + /** + * Returns a new Dimensions object with n dimensions, each of + * which has the specified size. + * + * @return {d: Dimensions | d.n = n && d.dimensions[int] = size } + * @throws IllegalArgumentException - n < 1 || size < 1 + */ + public static Dimensions square(int size, int n) { + if (n < 1 || size < 1) throw new IllegalArgumentException("n < 1 || size < 1"); + return new Square(n, size); + } + + /** + * Constructs a new Dimensions object with the given dimensions. + * + * @return {d: Dimensions | d.n = dimensions.length && d.dimensions = dimensions } + * @throws NullPointerException - dimensions = null + * @throws IllegalArgumentException - dimensions.length = 0 || + * some i: [0..dimensions.n) | dimensions[i] < 1 + */ + public static Dimensions rectangular(int[] dimensions) { + if (dimensions.length==0) throw new IllegalArgumentException("n=0."); + long capacity = 1; + int size = dimensions[0]; + for (int i = 0; i < dimensions.length; i++) { + if (dimensions[i] < 1) throw new IllegalArgumentException("Invalid dimension: " + dimensions[i]); + capacity *= dimensions[i]; + if (size!=dimensions[i]) size = 0; + } + if (size>0) { + return new Square(dimensions.length, size); + } else { + final int[] dims = new int[dimensions.length]; + System.arraycopy(dimensions, 0, dims, 0, dimensions.length); + return new Rectangle(dims, capacity); + } + } + + /** + * Returns the capacity of this. + * @return this.capacity + */ + public final int capacity() { return capacity; } + + /** + * Returns the size of the ith dimensions + * @return this.dimensions[i] + * @throws ArrayIndexOutOfBoundsException - i < 0 || i >= this.capacity + */ + public abstract int dimension(int i); + + /** + * Returns the number of dimensions in this Dimensions object. + * @return this.n + */ + public abstract int numDimensions(); + + /** + * Returns true if this represents the dimensions of a square matrix; + * otherwise returns false. + * + * @return all i, j: [0..capacity) | this.dimensions[i] = this.dimensions[j] + */ + public abstract boolean isSquare(); + + /** + * Returns true if the dimensions data in this object is homogeneous + * from start, inclusive, to end, exclusive. + * @return some x: int | this.dimensions[start..end) = x + */ + abstract boolean isSquare(int start, int end); + + /** + * Fills the destination array, beginning at destPos, with the dimension data + * from this Dimensions object, beginning at srcPos. The number of components copied + * is equal to the length argument. The dimensions at positions srcPos through srcPos+length-1 + * are copied into positions destPos through destPos+length-1, respectively, of the destination + * array. + * @ensures dest[destPos..destPos+length) = this.dimensions[srcPos..srcPos+length) + */ + abstract void copy(int srcPos, int[] dest, int destPos, int length); + + /** + * Returns the dimensions of a matrix that would result from multiplying a + * matrix of dimensions given by this by a matrix whose dimensions are + * specified by dim. + * + * @return { d: Dimensions | d.n = this.n + dim.n - 2 && + * (all i: [0..this.n-1) | d.dimensions[i] = this.dimensions[i]) && + * (all i: [this.n-1..d.n) | d.dimensions[i] = dim.dimensions[i-this.n+1])} + * @throws IllegalArgumentException - this.n + dim.n < 3 || this.dimensions[n-1] != dim.dimensions[0] + */ + public final Dimensions dot(Dimensions dim) { + final int n0 = numDimensions(), n1 = dim.numDimensions(); + final int n = n0 + n1 - 2, drop = dim.dimension(0); + if (n == 0 || dimension(n0-1) != drop) { + throw new IllegalArgumentException(); + } + + if (isSquare(0,n0-1) && dim.isSquare(1,n1) && + (n0==1 || n1==1 || dimension(0)==dim.dimension(1))) { + return new Square(n, dimension(0)); + } else { + final int[] dims = new int[n]; + copy(0, dims, 0, n0-1); + dim.copy(1, dims, n0-1, n1-1); + return new Rectangle(dims, (capacity*dim.capacity) / (drop*drop)); + } + } + + /** + * Returns the dimensions of a matrix that would result from taking the cross + * product of a matrix of dimensions given by this and a matrix whose dimensions are + * specified by dim. + * + * @return { d: Dimensions | d.n = this.n + dim.n && + * (all i: [0..this.n) | d.dimensions[i] = this.dimensions[i]) && + * (all i: [this.n..d.n) | d.dimensions[i] = dim.dimensions[i-this.n])} + */ + public final Dimensions cross(Dimensions dim) { + final int n0 = numDimensions(), n1 = dim.numDimensions(); + if (isSquare() && dim.isSquare() && dimension(0)==dim.dimension(0)) + return new Square(n0+n1, dimension(0)); + else { + final int[] dims = new int[n0+n1]; + copy(0, dims, 0, n0); + dim.copy(0, dims, n0, n1); + return new Rectangle(dims, (long)capacity*(long)dim.capacity); + } + } + + + /** + * Returns the transpose of these dimensions. + * + * @return { d: Dimensions | d.n = 2 && d.dimensions[0] = this.dimensions[1] && + * d.dimensions[1] = this.dimensions[0] } + * @throws UnsupportedOperationException - this.n != 2 + */ + public abstract Dimensions transpose(); + + /** + * @return true if index is positive and less than bound. + */ + private static boolean positiveBounded(int index, int bound) { + return 0 <= index && index < bound; + } + + /** + * Returns true if index is a valid flat index for a matrix with + * these dimensions; otherwise returns false. + * + * @return 0 <= i < this.capacity + */ + public final boolean validate(int index) { + return positiveBounded(index, capacity); + } + + /** + * Returns true if index is a valid vector index for a matrix + * with these dimensions; otherwise returns false. + * + * @return index.length = n && + * (all i: [0..this.capacity) | 0 <= index[i] < this.dimensions[i]) + * @throws NullPointerException - index = null + */ + public final boolean validate(int[] index) { + final int length = numDimensions(); + if (index.length != length) return false; + for (int i = 0; i < length; i++) { + if (!positiveBounded(index[i], dimension(i))) return false; + } + return true; + } + + /** + * Converts an integer index into a matrix with these dimensions into a vector index. + * The effect of this method is the same as calling + * this.convert(index, new int[this.numDimensions()]). + * @return an array of ints that represents a vector index corresponding to the specified + * integer index into a this.dimensions[0]x...xthis.dimensions[n-1] matrix + * @throws IndexOutOfBoundsException - !validate(index) + */ + public final int[] convert(int index) { + final int[] vector = new int[numDimensions()]; + convert(index, vector); + return vector; + } + + /** + * Converts an integer index into a matrix with these dimensions into a vector index, + * and stores the result in the provided array. This method requires that + * the array argument have at least this.n cells, which are used to store the + * vector representation of the given index. The contents of the cells of vectorIndex + * beyond the first this.n cells are left unchanged. + * @requires vectorIndex.length <= this.n + * @ensures the first this.numDimensions entries of vectorIndex contain + * the vector index representation of the specified integer index into a + * this.dimensions[0]x...xthis.dimensions[n-1] matrix + * @throws NullPointerException - vectorIndex = null + * @throws IllegalArgumentException - vectorIndex.length < this.numDimensions + * @throws IndexOutOfBoundsException - !validate(index) + */ + public final void convert(int index, int[] vectorIndex) { + final int length = numDimensions(); + if (vectorIndex.length < length) + throw new IllegalArgumentException("arrayIndex.length= this.dimensions[i] + */ + public final int convert(int[] vectorIndex) { + final int length = numDimensions(); + if (vectorIndex.length < length) { + throw new IllegalArgumentException("index.length < this.n"); + } + int intIndex = 0; + int conversionFactor = capacity; + for(int i = 0; i < length; i++) { + int dim = dimension(i); + if (!positiveBounded(vectorIndex[i], dim)) throw new IndexOutOfBoundsException("index["+i+"]"); + conversionFactor = conversionFactor / dim; + intIndex += conversionFactor * vectorIndex[i]; + } + return intIndex; + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + StringBuilder buffer = new StringBuilder("[ "); + for (int i = 0; i < numDimensions(); i++) { + buffer.append(dimension(i)); + buffer.append(" "); + } + buffer.append("]"); + return buffer.toString(); + } + + /** + * Represents a Dimensions object whose dimensions are all of the + * same size. + */ + private static final class Square extends Dimensions { + private final int n, size; + /** + * Constructs a new Dimensions object with n dimensions, each of + * which has the specified size. + * + * @ensures this.n' = n && this.dimensions[int] = size + * @requires size > 0 && n > 0 + * @throws IllegalArgumentException - n < 1 || size < 1 + */ + Square(int n, int size) { + super(capacity(n, size)); + this.size = size; + this.n = n; + } + + static int capacity(int n, int size) { + final long cap = Math.round(Math.pow(size,n)); + if (cap>Integer.MAX_VALUE || cap<=0) + throw new CapacityExceededException("Matrix too large: requested capacity of " + cap, Ints.nCopies(n, size)); + return (int)cap; + } + + @Override + void copy(int srcPos, int[] dest, int destPos, int length){ + if (srcPos < 0 || length < 0 || srcPos+length > n) throw new ArrayIndexOutOfBoundsException(); + while(srcPos++ < length) { + dest[destPos++] = size; + } + } + + @Override + boolean isSquare(int start, int end) { + if (start <= end && start >= 0 && end <= n) { + return true; + } + throw new ArrayIndexOutOfBoundsException(); + } + + @Override + public int numDimensions() { return n; } + + @Override + public int dimension(int i) { + if (!positiveBounded(i,n)) throw new ArrayIndexOutOfBoundsException(); + return size; + } + + @Override + public boolean isSquare() { return true; } + + @Override + public Dimensions transpose() { + if (numDimensions() != 2) throw new UnsupportedOperationException("n!=2"); + return this; + } + + /** + * Returns true if the given object is logically equivalent to this; + * otherwise returns false. + * + * @return this.dimensions = o.dimensions + */ + public boolean equals(Object o) { + if (o instanceof Square) { + final Square s = (Square) o; + return n==s.n && size==s.size; + } + return false; + } + + public int hashCode() { + return n ^ size; + } + + } + + /** + * Represents a Dimensions object with at least two dimensions of different size. + */ + private static final class Rectangle extends Dimensions { + private final int[] dimensions; + + + /** + * Constructs a new Dimensions object with the given dimensions. + * + * @ensures this.n' = dimensions.length && this.dimensions' = dimensions + * @requires - dimensions.length > 0 && + * (all i: [0..dimensions.n) | dimensions[i] > 0) && + * (some i, j: [0..dimensions.n) | dimensions[i] != dimensions[j]) && + * capacity = dimensions[0]*dimensions[1]*...*dimensions[dimensions.length-1] + */ + Rectangle(int[] dims, long capacity) { + super((int)capacity); + if (capacity>Integer.MAX_VALUE || capacity<=0) + throw new CapacityExceededException("Matrix too large: requested capacity of " + capacity, Ints.asIntVector(dims)); + this.dimensions = dims; + } + + @Override + void copy(int srcPos, int[] dest, int destPos, int length){ + System.arraycopy(dimensions, srcPos, dest, destPos, length); + } + + @Override + boolean isSquare(int start, int end) { + for(int i = start + 1; i < end; i++) { + if (dimensions[i-1] != dimensions[i]) return false; + } + return true; + } + + @Override + public boolean isSquare() { return false; } + + @Override + public int dimension(int i) { return dimensions[i]; } + + @Override + public int numDimensions() { return dimensions.length; } + + @Override + public Dimensions transpose() { + if (numDimensions() != 2) throw new UnsupportedOperationException("n!=2"); + int[] dims = {dimensions[1], dimensions[0]}; + return new Rectangle(dims, capacity()); + } + + /** + * Returns true if the given object is logically equivalent to this; otherwise returns false. + * + * @return this.dimensions = dim.dimensions + */ + public boolean equals(Object o) { + if (o instanceof Rectangle) { + final Rectangle r = (Rectangle) o; + if (dimensions.length != r.dimensions.length || capacity() != r.capacity()) return false; + for (int i = 0; i < dimensions.length; i++) { + if (dimensions[i] != r.dimensions[i]) return false; + } + return true; + } + return false; + + } + + public int hashCode() { + return dimensions.length ^ capacity(); + } + + + } + + + + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/ITEGate.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/ITEGate.java new file mode 100644 index 00000000..121969fb --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/ITEGate.java @@ -0,0 +1,189 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.bool; + +import java.util.Iterator; +import java.util.Set; + +import kodkod.util.collections.Containers; +import kodkod.util.ints.Ints; + +/** + * An if-then-else gate. + * + * @specfield ifFormula: BooleanFormula + * @specfield thenFormula: BooleanFormula + * @specfield elseFormula: BooleanFormula + * @invariant inputs = 0->ifFormula + 1->thenFormula + 2->elseFormula + * @invariant this.label > 0 + * @invariant this.op = Operator.ITE + * @specfield all input: inputs | this.label > |input.label| + * @author Emina Torlak + */ +public final class ITEGate extends BooleanFormula { + private final BooleanFormula[] inputs; + private final int label, hashcode, labelhash; + + /** + * Constructs a new ITEGate from the given formulas and label. + * @requires label >= 0 && null !in ifFormula + thenFormula + elseFormula + * @requires hashcode = ITE.hash(ifFormula, thenFormula, elseFormula) + * @ensures this.label' = label && this.ifFormula' = ifFormula && + * this.thenFormula' = thenFormula && this.elseFormula' = elseFormula + * @throws NullPointerException - owner = null + */ + ITEGate(int label, int hashcode, BooleanFormula ifFormula, BooleanFormula thenFormula, BooleanFormula elseFormula) { + super(null); + assert label >= 0; + this.label = label; + this.labelhash = Ints.superFastHash(label); + this.hashcode = hashcode; + this.inputs = new BooleanFormula[3]; + inputs[0] = ifFormula; + inputs[1] = thenFormula; + inputs[2] = elseFormula; + } + + /** + * Returns a hash of this.label + * @return a hash of this.label + */ + @Override + int hash(Operator op) { + return labelhash; + } + + /** + * Returns an iterator over this.inputs + * @return returns an iterator over this.inputs + * @see kodkod.engine.bool.BooleanFormula#iterator() + */ + @Override + public Iterator iterator() { + return Containers.iterate(inputs); + } + + /** + * Returns 3. + * @return 2 + * @see kodkod.engine.bool.BooleanFormula#size() + */ + @Override + public int size() { + return 3; + } + + /** + * Returns this.label + * @return this.label + * @see kodkod.engine.bool.BooleanValue#label() + */ + @Override + public int label() { + return label; + } + + /** + * Passes this value and the given + * argument value to the visitor, and returns the resulting value. + * @return the value produced by the visitor when visiting this node + * with the given argument. + * @see kodkod.engine.bool.BooleanFormula#accept(kodkod.engine.bool.BooleanVisitor, Object) + */ + @Override + public T accept(BooleanVisitor visitor, A arg) { + return visitor.visit(this, arg); + } + + /** + * Returns a string representation of this ITE gate. + * @return a string representation of this ITE gate. + */ + public String toString() { + return "(" + inputs[0] + "?" + inputs[1] + ":" + inputs[2] + ")"; + } + + /** + * Returns the hashcode for this if-then-else gate. + * @return the hashcode for this gate. + */ + public int hashCode() { + return hashcode; + } + /** + * Returns Operator.ITE. + * @return Operator.ITE + */ + @Override + public kodkod.engine.bool.Operator op() { + return kodkod.engine.bool.Operator.ITE; + } + + /** + * Returns this.inputs[i]. + * @return this.inputs[i] + * @throws IndexOutOfBoundsException - 0 < i || i > 2 + */ + @Override + public BooleanFormula input(int i) { + if (i < 0 || i > 2) + throw new IndexOutOfBoundsException(); + return inputs[i]; + } + + /** + * Returns an integer k' such that 0 < |k'| < k and |k'| is the number of flattening + * steps that need to be taken to determine that this circuit has (or does not have) + * an input with the given label. + * A positive k' indicates that f is found to be an input to this circuit in k' steps. + * A negative k' indicates that f is not an input to this circuit, when it is flattened + * using at most k steps. + * @requires k > 0 + * @return this=f => 1 else op=ITE && k>2 && f in this.inputs[int].label => 3 else -3 + */ + @Override + int contains(Operator op, int f, int k) { + assert k > 0; + if (f==label) return 1; + else if (op != Operator.ITE || k < 3 || f>label || -f>label) return -1; + else return (inputs[0].label()==f || inputs[1].label()==f || inputs[2].label()==f) ? 3 : -3; + } + + /** + * Flattens this circuit with respect to the given operator into + * the provided set. + * @requires k > 0 + * @ensures op = Operator.ITE && k> 2 => flat.elts' = flat.elts + this.inputs[ints], + * flat.elts' = flat.elts + this + */ + @Override + void flatten(Operator op, Set flat, int k) { + assert k > 0; + if (op==Operator.ITE && k > 2) { + flat.add(inputs[0]); + flat.add(inputs[1]); + flat.add(inputs[2]); + } else { + flat.add(this); + } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/Int.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/Int.java new file mode 100644 index 00000000..6a3b901e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/Int.java @@ -0,0 +1,356 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.bool; + +import java.util.Collection; +import java.util.List; + +import kodkod.ast.Variable; +import kodkod.engine.fol2sat.Environment; + + +/** +* An integer represented using {@link kodkod.engine.bool.BooleanValue boolean values} +* and a given {@link kodkod.engine.config.Options.IntEncoding integer encoding}. +* +* @specfield factory: BooleanFactory +* @specfield bits: [0..factory.bitwidth) -> one factory.components +* @specfield encoding: factory.intEncoding +* @author Emina Torlak +*/ +@SuppressWarnings("rawtypes") +public abstract class Int { + final BooleanFactory factory; + final DefCond defCond = new DefCond(); + + /** + * Creates an Int with the given factory + * @ensures this.factory' = factory + */ + Int(BooleanFactory factory, Collection vars) { + this.factory = factory; + defCond.addVars(vars); + } + + /** + * Throws IllegalArgumentException if other.factory != this.factory. + * @throws IllegalArgumentException - other.factory != this.factory. + */ + final void validate(Int other) { + if (other.factory != factory) + throw new IllegalArgumentException("other.factory != this.factory"); + } + + /** + * Returns the BooleanValue at the specified index. + * @requires 0 <= i < this.factory.bitwidth + * @return this.bits[i] + */ + abstract BooleanValue bit(int i); + + /** + * Returns the most significant bit + * @return this.bits[this.width()-1] + */ + abstract BooleanValue msb(); + + /** + * Returns the little endian two's complement representation of this integer that is + * this.factory.bitwidth bits wide. Specifically, the returned list L has + * this.factory.bitwidth boolean values such that the meaning of this integer is + * 1*[[L.get(0)]] + ... + (1< twosComplementBits(); + + /** + * Returns this.factory + * @return this.factory + */ + public final BooleanFactory factory() { return factory; } + + /** + * Returns this.defCond + * @return this.defCond + */ + public final DefCond defCond() { return defCond; } + + /** + * Returns the number of bits in the representation of this Int, + * including sign bits (if any). + * @return this.width + */ + public abstract int width(); + + /** + * Returns true if all the bits representing this Int + * are BooleanConstants. + * @return this.bits[int] in BooleanConstant + */ + public abstract boolean isConstant(); + + /** + * If this Int is constant, returns its value. Otherwise + * throws an IllegalStateException. + * @return this.isConstant() => [[this.bits]] + * @throws IllegalStateException - !this.isConstant() + */ + public abstract int value(); + + /** + * Returns a BooleanValue encoding the comparator circuit + * that checks whether the integer represented by this + * Int is equal to the integer represented by the specified Int. + * @requires this.factory = other.factory + * @return BooleanValue encoding the comparator circuit + * that checks whether the integer represented by this + * Int is equal to the integer represented by the specified Int + * @throws IllegalArgumentException - this.factory != other.factory + */ + public final BooleanValue eq(Int other) { return this.eq(other, Environment.empty()); } + public abstract BooleanValue eq(Int other, Environment env); + + public final BooleanValue neq(Int other) { return this.neq(other, Environment.empty()); } + public abstract BooleanValue neq(Int other, Environment env); + + /** + * Returns a BooleanValue encoding the comparator circuit + * that checks whether the integer represented by this + * Int is less than or equal to the integer + * represented by the specified Int + * @requires this.factory = other.factory + * @return BooleanValue encoding the comparator circuit + * that checks whether the integer represented by this + * Int is less than or equal to the integer + * represented by the specified Int + * @throws IllegalArgumentException - this.factory != other.factory + */ + public BooleanValue lte(Int other) { return this.lte(other, Environment.empty()); } + public abstract BooleanValue lte(Int other, Environment env); + + /** + * Returns a BooleanValue encoding the comparator circuit + * that checks whether the integer represented by this + * Int is less than the integer + * represented by the specified Int. + * @requires this.factory = other.factory + * @return BooleanValue encoding the comparator circuit + * that checks whether the integer represented by this + * Int is less than the integer + * represented by the specified Int + * @throws IllegalArgumentException - this.factory != other.factory + */ + public final BooleanValue lt(Int other) { return this.gte(other, Environment.empty()); } + public abstract BooleanValue lt(Int other, Environment env); + + /** + * Returns a BooleanValue encoding the comparator circuit + * that checks whether the integer represented by this + * Int is greater than or equal to the integer + * represented by the specified Int. + * @requires this.factory = other.factory + * @return BooleanValue encoding the comparator circuit + * that checks whether the integer represented by this + * Int is greater than or equal to the integer + * represented by the specified Int + * @throws IllegalArgumentException - this.factory != other.factory + */ + public BooleanValue gte(Int other) { return this.gte(other, Environment.empty()); } + public BooleanValue gte(Int other, Environment env) { + return other.lte(this, env); + } + + /** + * Returns a BooleanValue encoding the comparator circuit + * that checks whether the integer represented by this + * Int is greater than the integer + * represented by the specified Int. + * @requires this.factory = other.factory + * @return BooleanValue encoding the comparator circuit + * that checks whether the integer represented by this + * Int is greater than the integer + * represented by the specified Int + * @throws IllegalArgumentException - this.factory != other.factory + */ + public BooleanValue gt(Int other) { return this.gt(other, Environment.empty()); } + public BooleanValue gt(Int other, Environment env) { + return other.lt(this, env); + } + + /** + * Returns an Int that represents the sum of this and the given Int. + * @requires this.factory = other.factory + * @return an Int that represents the sum of this and the given Int + * @throws IllegalArgumentException - this.factory != other.factory + */ + public abstract Int plus(Int other); + + /** + * Returns an Int that represents the sum of this and the given Ints. + * @requires this.factory = others[int].factory + * @return an Int that represents the sum of this and the given Ints + * @throws IllegalArgumentException - this.factory != others[int].factory + */ + public abstract Int plus(Int... others); + + /** + * Returns an Int that represents the product between this and the given Int. + * @requires this.factory = other.factory + * @return an Int that represents the product between this and the given Int + * @throws UnsupportedOperationException - this.encoding does not support multiplication + */ + public abstract Int multiply(Int other); + + /** + * Returns an Int that represents the product between this and the given Ints. + * @requires this.factory = others[int].factory + * @return an Int that represents the product between this and the given Ints + * @throws UnsupportedOperationException - this.encoding does not support multiplication + */ + public abstract Int multiply(Int... others); + + /** + * Returns an Int that represents the difference between this and the given Int. + * @requires this.factory = other.factory + * @return an Int that represents the difference between this and the given Int + * @throws UnsupportedOperationException - this.encoding does not support subtraction + */ + public abstract Int minus(Int other); + + /** + * Returns an Int that represents the quotient of the division between this and the given Int. + * @requires this.factory = other.factory + * @return an Int that represents the quotient of the division between this and the given Int + * @throws UnsupportedOperationException - this.encoding does not support division + */ + public abstract Int divide(Int other); + + /** + * Returns an Int that represents the remainder of the division between this and the given Int. + * @requires this.factory = other.factory + * @return an Int that represents the remainder of the division between this and the given Int + * @throws UnsupportedOperationException - this.encoding does not support division + */ + public abstract Int modulo(Int other); + + /** + * Returns an Int that evaluates to this if the condition is true, otherwise it + * evaluates to the given Int. + * @requires other + condition in this.factory.components + * @return an Int that evaluates to this if the condition is true, and + * to the given Int if the condition is false. + */ + public abstract Int choice(BooleanValue condition, Int other); + + /** + * Returns an Int that represents the bitwise conjunction of this and the given Int. + * @requires this.factory = other.factory + * @return an Int that represents the bitwise conjunction of this and the given Int. + */ + public abstract Int and(Int other); + + /** + * Returns an Int that represents the bitwise conjunction of this and the given Ints. + * @requires this.factory = others[int].factory + * @return an Int that represents the bitwise conjunction of this and the given Ints. + */ + public abstract Int and(Int... others); + + /** + * Returns an Int that represents the bitwise disjunction of this and the given Int. + * @requires this.factory = other.factory + * @return an Int that represents the bitwise disjunction of this and the given Int. + */ + public abstract Int or(Int other); + + /** + * Returns an Int that represents the bitwise disjunction of this and the given Ints. + * @requires this.factory = others[int].factory + * @return an Int that represents the bitwise disjunction of this and the given Ints. + */ + public abstract Int or(Int... others); + + /** + * Returns an Int that represents the bitwise XOR of this and the given Int. + * @requires this.factory = other.factory + * @return an Int that represents the bitwise XOR of this and the given Int. + * @throws UnsupportedOperationException - this.encoding does not support XOR + */ + public abstract Int xor(Int other); + + /** + * Returns an Int that represents this shifted to the left by the given Int. + * @requires this.factory = other.factory + * @return an Int that represents this shifted to the left by the given Int. + * @throws UnsupportedOperationException - this.encoding does not support SHL + */ + public abstract Int shl(Int other); + + /** + * Returns an Int that represents this shifted to the right by the given Int, + * with zero extension. + * @requires this.factory = other.factory + * @return an Int that represents this shifted to the right by the given Int, + * with zero extension. + * @throws UnsupportedOperationException - this.encoding does not support SHR + */ + public abstract Int shr(Int other); + + /** + * Returns an Int that represents this shifted to the right by the given Int, + * with sign extension. + * @requires this.factory = other.factory + * @return an Int that represents this shifted to the right by the given Int, + * with sign extension. + * @throws UnsupportedOperationException - this.encoding does not support SHA + */ + public abstract Int sha(Int other); + + /** + * Returns an Int that represents the negation of this integer. + * @return -[[this]] + * @throws UnsupportedOperationException - this.encoding does not support negation + */ + public abstract Int negate(); + + /** + * Returns an Int that represents bitwise negation of this integer. + * @return ~[[this]] + * @throws UnsupportedOperationException - this.encoding does not support bitwise negation + */ + public abstract Int not(); + + /** + * Returns an Int that represents the absolute value of this integer. + * @return abs([[this]]) + */ + public abstract Int abs(); + + /** + * Returns an Int that represents the signum of this integer. + * @return sgn([[this]]) + */ + public abstract Int sgn(); + + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/MultiGate.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/MultiGate.java new file mode 100644 index 00000000..d3545215 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/MultiGate.java @@ -0,0 +1,122 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.bool; + +import java.util.Iterator; + +import kodkod.util.ints.Ints; + + +/** + * A logic gate with two or more inputs; an AND or an OR gate. + * + * @specfield op: Operator.Binary + * @invariant #inputs > 1 + * @invariant some components.this => label in [1..Integer.MAX_VALUE), label in [0..Integer.MAX_VALUE) + * @invariant no c1, c2: inputs | c1.label = -c2.label + * @invariant this.label > 0 => all c: inputs | |c.label| < this.label + * @author Emina Torlak + */ +public abstract class MultiGate extends BooleanFormula { + final Operator.Nary op; + + private final int label, labelhash, hashcode; + + /** + * Constructs a new MultiGate gate with the given operator and label. + * @requires op != null && label >= 0 + * @ensures this.op' = op && this.label' = label + */ + MultiGate(Operator.Nary op, int label, int hashcode) { + super(null); + assert op != null; + assert label >= 0; + this.op = op; + this.label = label; + this.labelhash = Ints.superFastHash(label); + this.hashcode = hashcode; + } + + /** + * Returns the label for this value. + * @return this.label + */ + @Override + public final int label() { return label; } + + /** + * Returns the operator used to combine the input + * variables of this connective gate. + * @return this.op + */ + public final Operator.Nary op() { return op; } + + /** + * Passes this value and the given + * argument value to the visitor, and returns the resulting value. + * @return the value produced by the visitor when visiting this node + * with the given argument. + */ + @Override + public T accept(BooleanVisitor visitor, A arg) { + return visitor.visit(this, arg); + } + + /** + * Returns a string representation of this multigate. + * @return a string representation of this multigate. + */ + public String toString() { + final StringBuilder builder = new StringBuilder("("); + final Iterator children = iterator(); + builder.append(children.next()); + while(children.hasNext()) { + builder.append(op); + builder.append(children.next()); + } + builder.append(")"); + return builder.toString(); + } + + /** + * Returns a hashcode for this gate. The hashcode obeys the Object contract. + * @return a hashcode for this gate. + */ + @Override + public final int hashCode() { + return hashcode; + } + + /** + * Returns the digest of this formula that would be used + * to compute the digest of the composition of this and + * some other formula using the given operator. Specifically, + * if op = this.op, then the sum of this circuit's irreducible + * inputs' hashes (with respect to op) is returned. Otherwise, + * the superFastHash of this.label is returned. + * @return this.op = op => this.op.hash(this.inputs), Ints.superFastHash(this.label) + */ + @Override + final int hash(Operator op) { + return op==this.op ? hashcode : labelhash; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/NaryGate.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/NaryGate.java new file mode 100644 index 00000000..8a573931 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/NaryGate.java @@ -0,0 +1,157 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.bool; + +import java.util.Iterator; +import java.util.Set; + +import kodkod.util.collections.Containers; + +/** + * Represents a multi gate with more than two inputs. + * @invariant #this.inputs > 2 + * @invariant digest = sum(inputs.digest(this.op)) + */ +final class NaryGate extends MultiGate { + private final BooleanFormula[] inputs; + + /** + * Constructs a new n-ary gate with the given label, from the given mutable multi gate. + * @requires g != null && #g.inputs > 2 + * @ensures this.op' = g.op && this.inputs' = g.inputs && this.label' = label + */ + NaryGate(BooleanAccumulator g, int label, int hashcode) { + super(g.op, label, hashcode); + this.inputs = new BooleanFormula[g.size()]; + int index = 0; + for(Iterator i = g.iterator(); i.hasNext(); ) { + inputs[index] = (BooleanFormula) i.next(); + index++; + } + } + + /** + * Returns the number of inputs to this gate. + * @return #this.inputs + */ + @Override + public int size() { + return inputs.length; + } + + /** + * Returns an iterator over the inputs to this gate, in the ascending + * label order. + * @return an iterator over this.inputs + */ + @Override + public Iterator iterator() { + return Containers.iterate(inputs); + } + + /** + * Returns an integer k' such that 0 < |k'| < k and |k'| is the number of flattening + * steps that need to be taken to determine that this circuit has (or does not have) + * an input with the given label. + * A positive k' indicates that f is found to be an input to this circuit in k' steps. + * A negative k' indicates that f is not an input to this circuit, when it is flattened + * using at most k steps. + * @requires k > 0 + * @return the number of flattening + * steps that need to be taken to determine that f is (not) an input to this circuit + */ + @Override + int contains(Operator op, int f, int k) { + assert k > 0; + if (f==label()) return 1; + else if (this.op != op || f>label() || -f>label()) return -1; + else { + int low = 0, high = inputs.length-1, step = 1; + while (low <= high && step <= k) { + int mid = (low + high) >>> 1; + int midVal = inputs[mid].label(); + + if (midVal < f) + low = mid + 1; + else if (midVal > f) + high = mid - 1; + else + return step; // key found in the given number of steps + step++; + } + return 1-step; // key not found. + } + } + + /** + * Flattens this circuit with respect to the given operator into + * the provided set. + * Specifically, the method modifies the set so that it contains + * the elements f_0, ..., f_k' where k' <= k elements and + * [[this]] = op(f_0, ..., f_k'). + * The default implementation simply adds this to the set. + * @requires k > 0 + * @ensures 1 <= k' <= k && some f_0,..., f_k' : flat.elts' | + * [[this]] = op([[f_0]], ..., [[f_k']]) + */ + @Override + void flatten(Operator op, Set flat, int k) { + assert k > 0; + if (this.op == op && k >= inputs.length) { + int diff = k - inputs.length; + for(BooleanFormula f: inputs) { + int oldsize = flat.size(); + f.flatten(op, flat, StrictMath.max(1, diff)); + diff -= (flat.size() - oldsize); + } + } else { + flat.add(this); + } + } + + /** + * Returns true if the given iterator and this.iterator + * return the same elements, in the same order. + * @return true if values and this.iterator return the same elements, + * in the same order. + */ + boolean sameInputs(Iterator values) { + for(BooleanFormula f : inputs) { + if (!(values.hasNext() && f == values.next())) + return false; + } + return !values.hasNext(); + } + + /** + * Returns the ith input to this gate. + * @return this.inputs[i] + * @requires 0 <= i < size + * @throws IndexOutOfBoundsException - i < 0 || i >= #this.inputs + */ + @Override + public BooleanFormula input(int i) { + if (i < 0 || i > inputs.length) + throw new IndexOutOfBoundsException(); + return inputs[i]; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/NotGate.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/NotGate.java new file mode 100644 index 00000000..b83a7470 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/NotGate.java @@ -0,0 +1,149 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.bool; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import kodkod.util.ints.Ints; + + +/** + * A logic NOT gate. + * + * @invariant this.op = Operator.NOT + * @invariant #inputs = 1 + * @invariant this.label = -inputs.label + * @invariant label in (-Integer.MAX_VALUE..-1] + * @author Emina Torlak + */ +public final class NotGate extends BooleanFormula { + + private final int hashcode; + + /** + * Constructs a new NotGate with the given formula as its input. + * @requires input != null && input !in NotGate + * @ensures this.inputs' = 0->input && this.output'.label = -input.label + */ + NotGate(BooleanFormula input) { + super(input); + this.hashcode = Ints.superFastHash(-input.label()); + } + + /** + * Returns a hash of this inverter's label. + * @return Ints.superFastHash(this.label) + */ + @Override + int hash(Operator op) { + return hashcode; + } + + /** + * Returns an iterator that returns this gate's single input. + * @return an iterator over this.inputs. + */ + @Override + public Iterator iterator() { + return new Iterator() { + boolean hasNext = true; + public boolean hasNext() { + return hasNext; + } + + public BooleanFormula next() { + if (!hasNext) throw new NoSuchElementException(); + hasNext = false; + return negation(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + }; + } + + /** + * Returns the label for this value. + * @return this.label + */ + @Override + public final int label() { return -negation().label(); } + + /** + * Returns 1. + * @return 1. + */ + @Override + public int size() { + return 1; + } + + /** + * Passes this value and the given + * argument value to the visitor, and returns the resulting value. + * @return the value produced by the visitor when visiting this node + * with the given argument. + */ + @Override + public T accept(BooleanVisitor visitor, A arg) { + return visitor.visit(this, arg); + } + + /** + * Returns a string representation of this inverter. + * @return a string representation of this inverter. + */ + public String toString() { + return "!" + negation().toString(); + } + + /** + * Returns Operator.NOT. + * @return Operator.NOT + */ + @Override + public kodkod.engine.bool.Operator op() { + return kodkod.engine.bool.Operator.NOT; + } + + /** + * Returns this.input[i]. + * @return this.input[i] + * @throws IndexOutOfBoundsException - i != 0 + */ + @Override + public BooleanFormula input(int i) { + if (i != 0) throw new IndexOutOfBoundsException(); + return negation(); + } + + /** + * Returns a hashcode for this inverter. + * @return a hashcode for this inverter. + */ + public int hashCode() { + return hashcode; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/Operator.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/Operator.java new file mode 100644 index 00000000..5d5ebfca --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/Operator.java @@ -0,0 +1,183 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.bool; + +import java.util.Iterator; + +/** + * ExprOperator associated with a {@link kodkod.engine.bool.BooleanValue boolean value}. + * + * @specfield ordinal: [0..5] + * @invariant AND.ordinal = 0 && OR.ordinal = 1 && ITE.ordinal = 2 && + * NOT.ordinal = 2 && VAR.ordinal = 4 && CONST.ordinal = 5 + * @author Emina Torlak + */ +public abstract class Operator implements Comparable{ + final int ordinal; + + private Operator(int ordinal) { + this.ordinal = ordinal; + } + + /** + * Returns the ordinal of this operator constant. + * @return the ordinal of this operator constant. + */ + public final int ordinal() { + return ordinal; + } + + /** + * Returns an integer i such that i < 0 if this.ordinal < op.ordinal, + * i = 0 when this.ordinal = op.ordinal, and i > 0 when this.ordinal > op.ordinal. + * @return i: int | this.ordinal < op.ordinal => i < 0, + * this.ordinal = op.ordinal => i = 0, i > 0 + * @throws NullPointerException - op = null + */ + public int compareTo(Operator op) { + return ordinal() - op.ordinal(); + } + + /** + * N-ary {@link MultiGate AND} operator. + */ + public static final Nary AND = new Nary(0) { + public String toString() { return "&"; } + /** @return true */ + public BooleanConstant identity() { return BooleanConstant.TRUE; } + /** @return false */ + public BooleanConstant shortCircuit() { return BooleanConstant.FALSE; } + /** @return OR */ + public Nary complement() { return OR; } + }; + + /** + * N-ary {@link MultiGate OR} operator. + */ + public static final Nary OR = new Nary(1) { + public String toString() { return "|"; } + /** @return false */ + public BooleanConstant identity() { return BooleanConstant.FALSE; } + /** @return true */ + public BooleanConstant shortCircuit() { return BooleanConstant.TRUE; } + /** @return AND */ + public Nary complement() { return AND; } + }; + + /** + * Ternary {@link ITEGate if-then-else} operator. + */ + public static final Ternary ITE = new Ternary(2) { + public String toString() { return "?"; } + }; + + /** + * Unary {@link NotGate negation} operator. + */ + public static final Operator NOT = new Operator(3) { + public String toString() { return "!"; } + }; + + /** + * Zero-arity {@link BooleanVariable variable} operator. + */ + public static final Operator VAR = new Operator(4) { + public String toString() { return "var"; } + }; + + /** + * Zero-arity {@link BooleanConstant constant} operator. + */ + public static final Operator CONST = new Operator(5) { + public String toString() { return "const"; } + }; + + /** + * An n-ary operator, where n>=2 + */ + public static abstract class Nary extends Operator { + + private Nary(int ordinal) { + super(ordinal); + } + + /** + * Returns the hashcode for a gate v such that + * v.op = this && v.inputs[int] = f0 + f1 + * @return f0.hash(this) + f1.hash(this) + */ + int hash(BooleanFormula f0, BooleanFormula f1) { + return f0.hash(this) + f1.hash(this); + } + + /** + * Returns the hashcode for a gate v such that + * v.op = this && v.iterator() = formulas. + * @return sum(formulas.hash(this)) + */ + int hash(Iterator formulas) { + int sum = 0; + while(formulas.hasNext()) + sum += formulas.next().hash(this); + return sum; + } + + /** + * Returns the boolean constant c such that + * for all logical values x, c composed + * with x using this operator will result in x. + * @return the identity value of this binary operator + */ + public abstract BooleanConstant identity(); + /** + * Returns the boolean constant c such that + * for all logical values x, c composed + * with x using this operator will result in c. + * @return the short circuiting value of this binary operator + */ + public abstract BooleanConstant shortCircuit(); + /** + * Returns the binary operator whose identity and short circuit + * values are the negation of this operator's identity and + * short circuit. + * @return the complement of this binary operator + */ + public abstract Operator.Nary complement(); + } + + static abstract class Ternary extends Operator { + + private Ternary(int ordinal) { + super(ordinal); + } + + /** + * Returns the hashcode for a gate v such that + * v = (i ? t : e) + * @return 3*i.hash(this) + 5*t.hash(this) + 7*e.hash(this) + */ + int hash(BooleanFormula i, BooleanFormula t, BooleanFormula e) { + return 3*i.hash(this) + 5*t.hash(this) + 7*e.hash(this); + } + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/RBCFactory.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/RBCFactory.java new file mode 100644 index 00000000..ca0afbf3 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/RBCFactory.java @@ -0,0 +1,286 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.bool; + +import static kodkod.engine.bool.BooleanConstant.FALSE; +import static kodkod.engine.bool.BooleanConstant.TRUE; +import static kodkod.engine.bool.Operator.AND; +import static kodkod.engine.bool.Operator.CONST; +import static kodkod.engine.bool.Operator.ITE; +import static kodkod.engine.bool.Operator.OR; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; + +import kodkod.util.collections.CacheSet; + +/** + * A factory for creating variables, binary gates, and if-then-else gates, in RBC form. + * @specfield values: set (BooleanVariable + MultiGate + ITEGate) + * @specfield cmpMax: int // the maximum number of comparisons made when comparing circuits for equality + * @invariant no disj factory, factory' : CircuitFactory | some factory.values & factory'.values + * @author Emina Torlak + */ +final class RBCFactory { + /** + * Stores input variables. + * @invariant all i: [1..iLits.size()] | vars[i-1].positive.label = i + */ + private final BooleanVariable[] vars; + /** + * Caches the AND, OR, and ITE gates. + * @invariant all i: [0..2] | c[i].op.ordinal = i + */ + private final CacheSet[] cache; + private int label, cmpMax; + + + /** + * Constructs a CircuitFactory using the given max comparison parameter, initialized + * to contain the given number of variables. + * @requires cmpMax > 0 && numVars >= 0 + * @ensures #this.values' = numVars && this.values in BooleanVariable + * @ensures this.cmpMax' = cmpMax + */ + @SuppressWarnings("unchecked") RBCFactory(int numVars, int cmpMax) { + assert cmpMax > 0 && numVars >= 0; + this.cmpMax = cmpMax; + this.label = numVars + 1; + vars = new BooleanVariable[numVars]; + for(int i = 0; i < numVars; i++) { + vars[i]= new BooleanVariable(i+1); + } + + cache = new CacheSet[]{new CacheSet(), new CacheSet(), new CacheSet()}; + } + + /** + * Returns the cache for gates with the given operator. + * @requires op in AND + OR + ITE + * @return cache[op.ordinal] + */ + private CacheSet opCache(Operator op) { + return cache[op.ordinal]; + } + + /** + * Sets this.cmpMax to the given value. + * @requires cmpMax > 0 + * @ensures this.cmpMax' = cmpMax + */ + void setCmpMax(int cmpMax) { + assert cmpMax > 0; + this.cmpMax = cmpMax; + } + + /** + * Returns this.cmpMax. + * @return this.cmpMax + */ + int cmpMax() { return cmpMax; } + + /** + * Removes all MultiGates and ITEGates from this.factory. + * @ensures this.values' = this.values & BooleanVariable + */ + void clear() { + label = vars.length+1; + cache[0].clear(); + cache[1].clear(); + cache[2].clear(); + } + + /** + * Returns true if the given value + * is a valid argument to one of the assemble + * methods. Otherwise returns false. + * @return v in this.values + this.values.negation + BooleanConstant + */ + boolean canAssemble(BooleanValue v) { + if (v.op()==CONST) return true; + if (v.label() < 0) v = v.negation(); + final int absLit = v.label(); + if (absLit <= vars.length) { + return v == vars[absLit-1]; + } else { + final BooleanFormula g = (BooleanFormula) v; + for(Iterator gates = opCache(g.op()).get(g.hashCode()); gates.hasNext(); ) { + if (gates.next()==g) return true; + } + return false; + } + } + + /** + * Returns the number of variables in this factory. + * @return #(this.values & BooleanVariable) + */ + int numVars() { return vars.length; } + + /** + * Returns the boolean variable from this.values with the given label. + * @requires 0 < label <= #(this.values & BooleanVariable) + * @return (this.values & BooleanVariable).label + */ + BooleanVariable variable(int label) { + return vars[label-1]; + } + + /** + * Returns a boolean value whose meaning is (if [[i]] then [[t]] else [[e]]). + * @requires i + t + e in (this.values + this.values.negation + BooleanConstant) + * @return v: BooleanValue | [[v]] = if [[i]] then [[t]] else [[e]] + * @ensures v in BooleanFormula - NotGate => this.values' = this.values + v, this.values' = this.values + * @throws NullPointerException - any of the arguments are null + */ + BooleanValue assemble(BooleanValue i, BooleanValue t, BooleanValue e) { + if (i==TRUE || t==e) return t; + else if (i==FALSE) return e; + else if (t==TRUE || i==t) return assemble(OR, i, e); + else if (t==FALSE || i.negation()==t) return assemble(AND, i.negation(), e); + else if (e==TRUE || i.negation()==e) return assemble(OR, i.negation(), t); + else if (e==FALSE || i==e) return assemble(AND, i, t); + else { + final int ilabel = i.label(), tlabel = t.label(), elabel = e.label(); + boolean neg = false; + BooleanFormula f0 = (BooleanFormula) i, f1 = (BooleanFormula) t, f2 = (BooleanFormula) e; + if (Math.abs(tlabel)==Math.abs(elabel)) { + if (ilabel>0 && tlabel<0 && elabel>0) { // (a <=> !b) becomes !(a <=> b) + neg = true; + f1 = f1.negation(); + f2 = f2.negation(); + } else if (ilabel<0 && tlabel>0 && elabel<0) { // (!a <=> b) becomes !(a <=> b) + neg = true; + f0 = f0.negation(); + } else if (ilabel<0 && tlabel<0 && elabel>0) {// (!a <=> !b) becomes (a <=> b) + f0 = f0.negation(); + f1 = f1.negation(); + f2 = f2.negation(); + } + } + + final int hash = ITE.hash(f0, f1, f2); + + for(Iterator gates = opCache(ITE).get(hash); gates.hasNext();) { + BooleanFormula gate = gates.next(); + if (gate.input(0)==i && gate.input(1)==t && gate.input(2)==e) + return gate; + } + final BooleanFormula ret = new ITEGate(label++, hash, f0, f1, f2); + opCache(ITE).add(ret); + return neg ? ret.negation() : ret; + } + } + + /** + * Returns a boolean value whose meaning is ([[v0]] op [[v1]]). + * @requires v0 + v1 in (this.values + this.values.negation + BooleanConstant) + * @return v: BooleanValue | [[v]] = [[v0]] op [[v1]] + * @ensures v in BooleanFormula - NotGate => this.values' = this.values + v, this.values' = this.values + * @throws NullPointerException - any of the arguments are null + */ + BooleanValue assemble(Operator.Nary op, BooleanValue v0, BooleanValue v1) { + if (op==OR) { + return assemble(AND, v0.negation(), v1.negation()).negation(); + } + + if (v0==v1) return v0; + if (v0.label()==-v1.label()) return FALSE; + if (v0==TRUE) return v1; + if (v1==TRUE) return v0; + if (v0==FALSE) return FALSE; + if (v1==FALSE) return FALSE; + + return cache(op, (BooleanFormula)v0, (BooleanFormula)v1); + } + + /** + * Returns a boolean value with the same meaning as the given accumulator. + * @requires acc.components in (this.values + this.values.negation + BooleanConstant) + * @return v: BooleanValue | [[v]] = [[acc]] + * @ensures v in BooleanFormula - NotGate => this.values' = this.values + v, this.values' = this.values + * @throws NullPointerException - any of the arguments are null + */ + BooleanValue assemble(BooleanAccumulator acc) { + final int asize = acc.size(); + final Operator.Nary op = acc.op; + switch(asize) { + case 0 : return op.identity(); + case 1 : return acc.iterator().next(); + case 2 : + final Iterator inputs = acc.iterator(); + return assemble(op, inputs.next(), inputs.next()); + default : + final List vals = new LinkedList(); + for(BooleanValue v : acc) { + vals.add(v); + } + while(vals.size()>1) { + final ListIterator itr = vals.listIterator(); + for(int i = 0, max = vals.size()-1; i < max; i+=2) { + final BooleanValue v0 = itr.next(); + itr.remove(); + final BooleanValue v1 = itr.next(); + final BooleanValue v0opv1 = assemble(op, v0, v1); + if (v0opv1==op.shortCircuit()) return op.shortCircuit(); + else if (v0opv1==op.identity()) itr.remove(); + else itr.set(v0opv1); + } + } + return vals.get(0); + } + } + + /** + * Returns a BooleanFormula f such that [[f]] = f0 op f1. The method + * requires that the formulas f0 and f1 be already reduced with respect to op. + * A new formula is created and cached iff the circuit with the meaning + * [[f0]] op [[f1]] has not already been created. + * @requires f0 and f1 have already been reduced with respect to op; i.e. + * f0 op f1 cannot be reduced to a constant or a simple circuit + * by applying absorption, idempotence, etc. laws to f0 and f1. + * @return f : BooleanFormula | [[f]] = [[f0]] op [[f1]] + * @ensures f !in this.values => this.values' = this.values + f, + * this.values' = this.values + */ + private BooleanFormula cache(Operator.Nary op, BooleanFormula f0, BooleanFormula f1) { + final BooleanFormula l, h; + if (f0.label() gates = opCache(op).get(hash); gates.hasNext(); ) { + BooleanFormula gate = gates.next(); + if (gate.size()==2 && gate.input(0)==l && gate.input(1)==h) + return gate; + } + final BooleanFormula ret = new BinaryGate(op, label++, hash, l, h); + opCache(op).add(ret); + return ret; + } + + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/TwosComplementInt.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/TwosComplementInt.java new file mode 100644 index 00000000..053373d8 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/bool/TwosComplementInt.java @@ -0,0 +1,848 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.bool; + +import static kodkod.engine.bool.BooleanConstant.FALSE; +import static kodkod.engine.bool.BooleanConstant.TRUE; +import static kodkod.engine.bool.Operator.AND; +import static kodkod.engine.bool.Operator.OR; + +import java.util.AbstractList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import kodkod.ast.Variable; +import kodkod.engine.bool.Operator.Nary; +import kodkod.engine.fol2sat.Environment; +import kodkod.util.collections.Containers; + +/** + * Two's complement integer representation. Supports comparisons, addition and subtraction. + * Integers are represented in little-endian (least significant bit first) order. + * @author Emina Torlak + */ +@SuppressWarnings("rawtypes") +final class TwosComplementInt extends Int { + private final BooleanValue[] bits; + + /** + * Constructs a TwosComplementInt out of the given factory and bits. + * @requires bits is well formed + * @ensures this.factory' = factory && this.bits' = bits + */ + private TwosComplementInt(BooleanFactory factory, BooleanValue[] bits, + BooleanValue overflow, BooleanValue accumOverflow) { + this(factory, bits, Collections.emptySet(), overflow, accumOverflow); + } + + private TwosComplementInt(BooleanFactory factory, BooleanValue[] bits, Collection vars, + BooleanValue overflow, BooleanValue accumOverflow) { + super(factory, vars); + this.bits = bits; + defCond().setOverflows(overflow, accumOverflow); + } + + /** + * Constructs a TwosComplementInt that represents either 0 or the given number, depending on + * the value of the given bit. + * @requires factory.encoding = TWOSCOMPLEMENT && bit in factory.components + * @ensures this.factory' = factory + * @ensures bits is a two's-complement representation of the given number + * that uses the provided bit in place of 1's + */ + TwosComplementInt(BooleanFactory factory, int number, BooleanValue bit) { + super(factory, Collections.emptySet()); + final int width = bitwidth(number); + this.bits = new BooleanValue[width]; + for(int i = 0; i < width; i++) { + bits[i] = (number & (1<this.factory.bitwidth bits. + */ + private boolean checkBounds(int num) { + return num >= minInt() && num <= maxInt(); + } + + /** + * Returns the min int representable using only this.factory.bitwidth bits. + */ + private int minInt() { return -(1 << (factory.bitwidth - 1)); } + + /** + * Returns the max int representable using only this.factory.bitwidth bits. + */ + private int maxInt() { return (1 << (factory.bitwidth - 1)) - 1; } + + /** + * ORs overflow circuits of this object ( + * this.mergedOverflow), a given other object ( + * other.mergedOverflow), and a given overflow circuit ( + * of) + */ + private BooleanValue mergeOverflows(Int other, BooleanValue of) { + return DefCond.merge(factory, of, defCond(), other.defCond()); + } + + /** + * Returns the number of bits needed/allowed to represent the given number. + * @return the number of bits needed/allowed to represent the given number. + */ + private int bitwidth(int number) { + if (number > 0) + return StrictMath.min(33 - Integer.numberOfLeadingZeros(number), factory.bitwidth); + else if (number < 0) + return StrictMath.min(33 - Integer.numberOfLeadingZeros(~number), factory.bitwidth); + else // number = 0 + return 1; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#isConstant() + */ + public final boolean isConstant() { + for(int i = width()-1; i >= 0; i--) { + BooleanValue b = bit(i); + if (b!=TRUE && b!=FALSE) + return false; + } + return true; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#twosComplementBits() + */ + @Override + public final List twosComplementBits() { + return new AbstractList() { + @Override + public BooleanValue get(int i) { + if (i < 0 || i >= factory.bitwidth) + throw new IndexOutOfBoundsException(); + return bit(i); + } + @Override + public int size() { return factory.bitwidth; } + }; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#width() + */ + @Override + public int width() { + return bits.length; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#value() + */ + public final int value() { + int ret = 0; + final int max = bits.length-1; + for(int i = 0; i < max; i++) { + if (bits[i]==TRUE) ret += 1<value. Otherwise, + * returns a conjunction of value, lhs.accumOverflow, + * and rhs.accumOverflow. + * + * ~~~ NOTE ~~~: Every time a BooleanValue is returned as a result of an operation + * over Ints, one of the ensureNoOverflow methods + * should be called. + */ + private BooleanValue ensureNoOverflow(Environment env, BooleanValue value, Int... ints) { + DefCond[] dcs = new DefCond[ints.length]; + for (int i = 0; i < ints.length; i++) dcs[i] = ints[i].defCond(); + return DefCond.ensureDef(factory, env, value, dcs); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#eq(kodkod.engine.bool.Int) + */ + public final BooleanValue eq(Int other, Environment env) { + BooleanValue ret = eqWithoutOverflow(other); + return ensureNoOverflow(env, ret, this, other); + } + + public final BooleanValue neq(Int other, Environment env) { + BooleanValue ret = factory.not(eqWithoutOverflow(other)); + return ensureNoOverflow(env, ret, this, other); + } + + private BooleanValue eqWithoutOverflow(Int other) { + validate(other); + final BooleanAccumulator cmp = BooleanAccumulator.treeGate(AND); + for(int i = 0, width = StrictMath.max(width(), other.width()); i < width; i++) { + if (cmp.add(factory.iff(bit(i), other.bit(i)))==FALSE) + return FALSE; + } + BooleanValue ret = factory.accumulate(cmp); + return ret; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#lt(kodkod.engine.bool.Int) + */ + public final BooleanValue lt(Int other, Environment env) { + final BooleanValue leq = lte(other); + final BooleanAccumulator acc = BooleanAccumulator.treeGate(OR); + for(int i = 0, width = StrictMath.max(width(), other.width()); i < width; i++) { + acc.add(factory.xor(bit(i), other.bit(i))); + } + BooleanValue ret = factory.and(leq, factory.accumulate(acc)); + return ensureNoOverflow(env, ret, this, other); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#lte(kodkod.engine.bool.Int) + */ + @Override + public BooleanValue lte(Int other, Environment env) { + validate(other); + final BooleanAccumulator cmp = BooleanAccumulator.treeGate(Operator.AND); + final int last = StrictMath.max(width(), other.width())-1; + cmp.add(factory.implies(other.bit(last), bit(last))); + BooleanValue prevEquals = factory.iff(bit(last), other.bit(last)); + for(int i = last-1; i >= 0; i--) { + BooleanValue v0 = bit(i), v1 = other.bit(i); + cmp.add(factory.implies(prevEquals, factory.implies(v0, v1))); + prevEquals = factory.and(prevEquals, factory.iff(v0, v1)); + } + BooleanValue ret = factory.accumulate(cmp); + return ensureNoOverflow(env, ret, this, other); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#plus(kodkod.engine.bool.Int) + */ + @Override + public Int plus(Int other) { + validate(other); + final int width = StrictMath.min(StrictMath.max(width(), other.width()) + 1, factory.bitwidth); + final BooleanValue[] plus = new BooleanValue[width]; + BooleanValue carry = FALSE; + BooleanValue c1 = FALSE; + BooleanValue c2 = FALSE; + for(int i = 0; i < width; i++) { + BooleanValue v0 = bit(i), v1 = other.bit(i); + plus[i] = factory.sum(v0, v1, carry); + carry = factory.carry(v0, v1, carry); + if (i == width-2) c2 = carry; + else if (i == width-1) c1 = carry; + } + BooleanValue overflow = FALSE; + if (width == factory.bitwidth) { + overflow = factory.xor(c1, c2); + } + BooleanValue accumOF = mergeOverflows(other, overflow); + return new TwosComplementInt(factory, plus, unionVars(this, other), overflow, accumOF); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#minus(kodkod.engine.bool.Int) + */ + @Override + public Int minus(Int other) { + validate(other); + final int width = StrictMath.min(StrictMath.max(width(), other.width()) + 1, factory.bitwidth); + final BooleanValue[] minus = new BooleanValue[width]; + BooleanValue carry = TRUE; + BooleanValue c1 = FALSE; + BooleanValue c2 = FALSE; + for(int i = 0; i < width; i++) { + BooleanValue v0 = bit(i), v1 = other.bit(i).negation(); + minus[i] = factory.sum(v0, v1, carry); + carry = factory.carry(v0, v1, carry); + if (i == width-2) c2 = carry; + else if (i == width-1) c1 = carry; + } + BooleanValue overflow = FALSE; + if (width == factory.bitwidth) { + overflow = factory.xor(c1, c2); + } + BooleanValue accumOF = mergeOverflows(other, overflow); + return new TwosComplementInt(factory, minus, unionVars(this, other), overflow, accumOF); + } + + /** + * Adds the newBit and the given carry to this.bits[index] and returns the new carry. + * @requires 0 <= index < this.width + * @ensures this.bits'[index] = this.factory.sum(this.bits[index], newBit, cin) + * @return this.factory.carry(this.bits[index], newBit, cin) + */ + private BooleanValue addAndCarry(int index, BooleanValue newBit, BooleanValue cin) { + BooleanValue oldBit = bits[index]; + bits[index] = factory.sum(oldBit, newBit, cin); + return factory.carry(oldBit, newBit, cin); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#multiply(kodkod.engine.bool.Int) + */ + //[AM] TODO: not optimal, uses double precision (too many bits)! + @Override + public Int multiply(Int other) { + validate(other); + final int retWidth = width() + other.width(); + final BooleanValue[] mult = new BooleanValue[retWidth]; + final Set unionVars = unionVars(this, other); + final TwosComplementInt ret = new TwosComplementInt(factory, mult, unionVars, FALSE, FALSE); + + /* first partial sum */ + BooleanValue iBit = bit(0); + for(int j = 0; j < retWidth; j++) { + mult[j] = factory.and(iBit, other.bit(j)); + } + + /* intermediate partial sums */ + int last = retWidth - 1; + for(int i = 1; i < last; i++) { + iBit = this.bit(i); + BooleanValue carry = FALSE; + for (int j = 0; j < retWidth - i; j++) { + BooleanValue bit = factory.and(iBit, other.bit(j)); + carry = ret.addAndCarry(i + j, bit, carry); + } + } + + /* last partial sum is subtracted (see http://en.wikipedia.org/wiki/Multiplication_ALU) */ + iBit = this.bit(last); + BooleanValue carry = TRUE; + for (int j = 0; j < retWidth - last; j++) { + BooleanValue bit = factory.and(iBit, other.bit(j)).negation(); + carry = ret.addAndCarry(last + j, bit, carry); + } + + final int width = StrictMath.min(mult.length, factory.bitwidth); + final BooleanValue[] multTrunc = new BooleanValue[width]; + for (int i = 0; i < multTrunc.length; i++) + multTrunc[i] = mult[i]; + + BooleanAccumulator acc = BooleanAccumulator.treeGate(Nary.OR); + for (int i = multTrunc.length; i < mult.length; i++) { + acc.add(factory.xor(mult[i - 1], mult[i])); + } + BooleanValue overflow = factory.accumulate(acc); + BooleanValue accumOF = mergeOverflows(other, overflow); + return new TwosComplementInt(factory, multTrunc, unionVars, overflow, accumOF); + } + + //@Override + public Int multiply_no_overflow_detection(Int other) { + validate(other); + final int width = StrictMath.min(width()+other.width(), factory.bitwidth); + final BooleanValue[] mult = new BooleanValue[width]; + final TwosComplementInt ret = new TwosComplementInt(factory, mult, unionVars(this, other), FALSE, FALSE); + + /* first partial sum */ + BooleanValue iBit = bit(0), carry; + for(int j = 0; j < width; j++) { + mult[j] = factory.and(iBit, other.bit(j)); + } + + final int last = width-1; + /* intermediate partial sums */ + for(int i = 1; i < last; i++) { + carry = FALSE; + iBit = bit(i); + for(int j = 0, jmax = width-i; j < jmax; j++) { + carry = ret.addAndCarry(j+i, factory.and(iBit, other.bit(j)), carry); + } + } + + /* last partial sum is subtracted (see http://en.wikipedia.org/wiki/Multiplication_ALU) */ + ret.addAndCarry(last, factory.and(this.bit(last), other.bit(0)).negation(), TRUE); + return ret; + } + + /** + * Returns an array of BooleanValues that represents the same + * integer as this, but using extwidth bits. + * @requires extwidth >= this.width() + * @return an array of BooleanValues that represents the same + * integer as this, but using extwidth bits. + */ + private BooleanValue[] extend(int extwidth) { + final BooleanValue[] ext = new BooleanValue[extwidth]; + final int width = width(); + for(int i = 0; i < width; i++) { + ext[i] = bits[i]; + } + final BooleanValue sign = bits[width-1]; + for(int i = width; i < extwidth; i++) { + ext[i] = sign; + } + return ext; + } + + /** + * Performs non-restoring signed division of this and the given integer. Returns + * the this.factory.bitwidth low-order bits of the quotient if the quotient flag + * is true; otherwise returns the this.factory.bitwidth low-order bits of the remainder. + * Both the quotionent and the remainder are given in little endian format. + * @see Behrooz Parhami, Computer Arithmetic: Algorithms and Hardware Designs, + * Oxford University Press, 2000, pp. 218-221. + * @requires this.factory = d.factory && d instanceof BinaryInt + * @return an array of boolean values, as described above + */ + private BooleanValue[] nonRestoringDivision(Int d, boolean quotient) { + final int width = factory.bitwidth, extended = width*2 + 1; + + // extend the dividend to bitwidth*2 + 1 and store it in s; the quotient will have width digits + final BooleanValue[] s = this.extend(extended), q = new BooleanValue[width]; + + // detects if one of the intermediate remainders is zero + final BooleanValue[] svalues = new BooleanValue[width]; + + BooleanValue carry, sbit, qbit, dbit; + + // the sign bit of the divisor + final BooleanValue dMSB = d.bit(width); + + int sleft = 0; // the index which contains the LSB of s + for(int i = 0; i < width; i++) { + svalues[i] = factory.accumulate(BooleanAccumulator.treeGate(Operator.OR, s)); + int sright = (sleft + extended - 1) % extended; // the index which contains the MSB of s + + // q[width-i-1] is 1 if sign(s_(i)) = sign(d), otherwise it is 0 + qbit = factory.iff(s[sright], dMSB); + q[width-i-1] = qbit; + + // shift s to the left by 1 -- simulated by setting sright to FALSE and sleft to sright + s[sright] = FALSE; + sleft = sright; + + // if sign(s_(i)) = sign(d), form s_(i+1) by subtracting (2^width)d from s_(i); + // otherwise, form s_(i+1) by adding (2^width)d to s_(i). + carry = qbit; + for(int di = 0, si = (sleft+width) % extended; di <= width; di++, si = (si+1) % extended) { + dbit = factory.xor(qbit, d.bit(di)); + sbit = s[si]; + s[si] = factory.sum(sbit, dbit, carry); + carry = factory.carry(sbit, dbit, carry); + } + } + + // s[0..width] holds the width+1 high order bits of s + assert (sleft+width) % extended == 0 ; + + // correction needed if one of the intermediate remainders is zero + // or s is non-zero and its sign differs from the sign of the dividend + final BooleanValue incorrect = factory.or( + factory.not(factory.accumulate(BooleanAccumulator.treeGate(Operator.AND, svalues))), + factory.and(factory.xor(s[width], this.bit(width)), + factory.accumulate(BooleanAccumulator.treeGate(Operator.OR, s)))); + final BooleanValue corrector = factory.iff(s[width], d.bit(width)); + + if (quotient) { // convert q to 2's complement, correct it if s is nonzero, and return + + // convert q to 2's complement: shift to the left by 1 and set LSB to TRUE + System.arraycopy(q, 0, q, 1, width-1); + q[0] = TRUE; + + // correct if incorrect evaluates to true as follows: if corrector evaluates to true, + // increment q; otherwise decrement q. + final BooleanValue sign = factory.and(incorrect, factory.not(corrector)); + carry = factory.and(incorrect, corrector); + + for(int i = 0; i < width; i++) { + qbit = q[i]; + q[i] = factory.sum(qbit, sign, carry); + carry = factory.carry(qbit, sign, carry); + } + + return q; + } else { // correct s if non-zero and return + + // correct if incorrect evaluates to true as follows: if corrector evaluates to true, + // subtract (2^width)d from s; otherwise add (2^width)d to s + carry = factory.and(incorrect, corrector); + + for(int i = 0; i <= width; i++) { + dbit = factory.and(incorrect, factory.xor(corrector, d.bit(i))); + sbit = s[i]; + s[i] = factory.sum(sbit, dbit, carry); + carry = factory.carry(sbit, dbit, carry); + } + + final BooleanValue[] r = new BooleanValue[width]; + System.arraycopy(s, 0, r, 0, width); + return r; + } + + } + + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#divide(kodkod.engine.bool.Int) + */ + @Override + public Int divide(Int other) { + validate(other); + TwosComplementInt ret = new TwosComplementInt(factory, nonRestoringDivision(other, true), + unionVars(this, other), FALSE, FALSE); + BooleanValue divByZero = other.eq(factory.integer(0)); + BooleanValue singleOverflowCase = factory.and(this.eq(factory.integer(-(1 << (factory.bitwidth-1)))), other.eq(factory.integer(-1))); + BooleanValue overflow = factory.or(divByZero, singleOverflowCase); + BooleanValue accumOF = mergeOverflows(other, overflow); + ret.defCond().setOverflows(overflow, accumOF); + return ret; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#modulo(kodkod.engine.bool.Int) + */ + @Override + public Int modulo(Int other) { + validate(other); + TwosComplementInt ret = new TwosComplementInt(factory, nonRestoringDivision(other, false), + unionVars(this, other), FALSE, FALSE); + BooleanValue divByZero = other.eq(factory.integer(0)); + BooleanValue accumOF = mergeOverflows(other, divByZero); + ret.defCond().setOverflows(FALSE, accumOF); + return ret; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#choice(kodkod.engine.bool.BooleanValue, kodkod.engine.bool.Int) + */ + @Override + public Int choice(BooleanValue condition, Int other) { + validate(other); + final int width = StrictMath.max(width(), other.width()); + final BooleanValue[] choice = new BooleanValue[width]; + for(int i = 0; i < width; i++) { + choice[i] = factory.ite(condition, bit(i), other.bit(i)); + } + BooleanValue of = factory.ite(condition, defCond().getOverflow(), other.defCond().getOverflow()); + BooleanValue accumOF = factory.ite(condition, defCond().getAccumOverflow(), other.defCond().getAccumOverflow()); + return new TwosComplementInt(factory, choice, unionVars(this, other), of, accumOF); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#and(kodkod.engine.bool.Int) + */ + @Override + public Int and(Int other) { + validate(other); + final int width = StrictMath.max(width(), other.width()); + final BooleanValue[] and = new BooleanValue[width]; + for(int i = 0; i < width; i++) { + and[i] = factory.and(bit(i), other.bit(i)); + } + Set unionVars = unionVars(this, other); + return new TwosComplementInt(factory, and, unionVars, FALSE, mergeOverflows(other, FALSE)); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#or(kodkod.engine.bool.Int) + */ + @Override + public Int or(Int other) { + validate(other); + final int width = StrictMath.max(width(), other.width()); + final BooleanValue[] or = new BooleanValue[width]; + for(int i = 0; i < width; i++) { + or[i] = factory.or(bit(i), other.bit(i)); + } + return new TwosComplementInt(factory, or, unionVars(this, other), FALSE, mergeOverflows(other, FALSE)); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#xor(kodkod.engine.bool.Int) + */ + @Override + public Int xor(Int other) { + validate(other); + final int width = StrictMath.max(width(), other.width()); + final BooleanValue[] xor = new BooleanValue[width]; + for(int i = 0; i < width; i++) { + xor[i] = factory.xor(bit(i), other.bit(i)); + } + return new TwosComplementInt(factory, xor, unionVars(this, other), FALSE, mergeOverflows(other, FALSE)); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#shl(kodkod.engine.bool.Int) + */ + @Override + public Int shl(Int other) { + validate(other); + final int width = factory.bitwidth; + final TwosComplementInt shifted = new TwosComplementInt(factory, extend(width), unionVars(this, other), FALSE, FALSE); + final int max = 32 - Integer.numberOfLeadingZeros(width - 1); + BooleanAccumulator acc = BooleanAccumulator.treeGate(Nary.OR); + for(int i = 0; i < width; i++) { + int shift = 1 << i; + BooleanValue bit = other.bit(i); + // overflow: check if the bits being pushed out is different from the one immediately to the right of it + for(int x = 0; x < shift; x++) { + BooleanValue b1 = width-x-1 < 0 ? FALSE : shifted.bit(width-x-1); + BooleanValue b2 = width-x-2 < 0 ? FALSE : shifted.bit(width-x-2); + acc.add(factory.ite(bit, factory.xor(b1, b2), FALSE)); + } + if (i < max) { + for(int j = width-1; j >= 0; j--) { + shifted.bits[j] = factory.ite(bit, j < shift ? FALSE : shifted.bit(j-shift), shifted.bits[j]); + } + } + } + BooleanValue overflow = factory.accumulate(acc); + BooleanValue accumOF = mergeOverflows(other, overflow); + shifted.defCond().setOverflows(overflow, accumOF); + return shifted; + } + + /** + * Performs a right shift with the given extension. + */ + private Int shr(Int other, BooleanValue sign) { + validate(other); + final int width = factory.bitwidth; + final TwosComplementInt shifted = new TwosComplementInt(factory, extend(width), unionVars(this, other), FALSE, FALSE); + final int max = 32 - Integer.numberOfLeadingZeros(width - 1); + for(int i = 0; i < max; i++) { + int shift = 1 << i; + int fill = width - shift; + BooleanValue bit = other.bit(i); + for(int j = 0; j < width; j++) { + shifted.bits[j] = factory.ite(bit, j < fill ? shifted.bit(j+shift) : sign, shifted.bits[j]); + } + } + shifted.defCond().setOverflows(FALSE, mergeOverflows(other, FALSE)); + return shifted; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#shr(kodkod.engine.bool.Int) + */ + @Override + public Int shr(Int other) { + return shr(other, FALSE); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#sha(kodkod.engine.bool.Int) + */ + @Override + public Int sha(Int other) { + return shr(other, bits[bits.length-1]); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#negate() + */ + @Override + public Int negate() { + return (new TwosComplementInt(factory, new BooleanValue[]{FALSE}, FALSE, FALSE)).minus(this); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#not() + */ + @Override + public Int not() { + final int width = width(); + final BooleanValue[] inverse = new BooleanValue[width]; + for(int i = 0 ; i < width; i++) { + inverse[i] = factory.not(bits[i]); + } + return new TwosComplementInt(factory, inverse, defCond().vars(), FALSE, defCond().getAccumOverflow()); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#abs() + */ + @Override + public Int abs() { + Int negated = negate(); + return choice(factory.not(bits[bits.length-1]), negated); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#sgn() + */ + @Override + public Int sgn() { + final BooleanValue[] sgn = new BooleanValue[2]; + sgn[0] = factory.accumulate(BooleanAccumulator.treeGate(Operator.OR, bits)); + sgn[1] = bits[bits.length-1]; + return new TwosComplementInt(factory, sgn, defCond().vars(), FALSE, defCond().getAccumOverflow()); + } + + /** + * {@inheritDoc} + * @see java.lang.Object#toString() + */ + public String toString() { + return "b" + Arrays.toString(bits); + } + + /** + * If the plus flag is true, returns a sum of this and other ints, + * with a cascade of adders or logarithmic depth. If the plus flag + * is false, returns a product of this and other ints, with a cascade + * of multipliers of logarithmic depth. + * @return plus => PLUS(this, others) else MULTIPLY(this, others) + */ + private Int apply(boolean plus, Int...others) { + final Int[] ints = Containers.copy(others, 0, new Int[others.length+1], 1, others.length); + ints[0] = this; + for(int part = ints.length; part > 1; part -= part/2) { + final int max = part-1; + for(int i = 0; i < max; i += 2) { + ints[i/2] = plus ? ints[i].plus(ints[i+1]) : ints[i].multiply(ints[i+1]); + } + if (max%2==0) { // even max => odd number of entries + ints[max/2] = ints[max]; + } + } + return ints[0]; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#plus(kodkod.engine.bool.Int[]) + */ + @Override + public Int plus(Int... others) { return apply(true, others); } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#multiply(kodkod.engine.bool.Int[]) + */ + @Override + public Int multiply(Int... others) { return apply(false, others); } + + /** + * Applies the given nary operator to this and the given ints. + * @return op(this, others) + */ + private Int apply(Operator.Nary op, Int...others) { + int width = width(); + for(Int other : others) { + validate(other); + width = Math.max(width, other.width()); + } + final BooleanValue[] bits = new BooleanValue[width]; + final BooleanValue shortCircuit = op.shortCircuit(); + for(int i = 0; i < width; i++) { + final BooleanAccumulator acc = BooleanAccumulator.treeGate(op, bit(i)); + for(Int other : others) { + if (acc.add(other.bit(i))==shortCircuit) break; + } + bits[i] = factory.accumulate(acc); + } + + final BooleanValue[] allOverflows = new BooleanValue[others.length + 1]; + final Set allVars = new HashSet(); + allOverflows[0] = defCond().getAccumOverflow(); + allVars.addAll(defCond().vars()); + for (int i = 1; i < allOverflows.length; i++) { + allOverflows[i] = others[i-1].defCond().getAccumOverflow(); + allVars.addAll(others[i-1].defCond().vars()); + } + BooleanAccumulator overflowAcc = BooleanAccumulator.treeGate(op, allOverflows); + return new TwosComplementInt(factory, bits, allVars, FALSE, factory.accumulate(overflowAcc)); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#and(kodkod.engine.bool.Int[]) + */ + @Override + public Int and(Int... others) { return apply(AND, others); } + + /** + * {@inheritDoc} + * @see kodkod.engine.bool.Int#or(kodkod.engine.bool.Int[]) + */ + @Override + public Int or(Int... others) { return apply(OR, others); } + + private static Set unionVars(Int int1, Int int2) { + Set union = new HashSet(); + union.addAll(int1.defCond().vars()); + union.addAll(int2.defCond().vars()); + return union; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/config/AbstractReporter.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/config/AbstractReporter.java new file mode 100644 index 00000000..1d00e72d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/config/AbstractReporter.java @@ -0,0 +1,95 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.config; + + +import java.util.List; +import java.util.Set; + +import kodkod.ast.Decl; +import kodkod.ast.Formula; +import kodkod.ast.Relation; +import kodkod.engine.bool.BooleanFormula; +import kodkod.instance.Bounds; +import kodkod.util.ints.IntSet; + +/** + * A skeleton implementation of the {@link Reporter} interface. + * The default implementation for each method has an empty body.s + * @author Emina Torlak + */ +public abstract class AbstractReporter implements Reporter { + + /** + * Constructs a new abstract reporter. + */ + protected AbstractReporter() {} + + /** + * {@inheritDoc} + * @see kodkod.engine.config.Reporter#detectingSymmetries(kodkod.instance.Bounds) + */ + public void detectingSymmetries(Bounds bounds){} + + /** + * {@inheritDoc} + * @see kodkod.engine.config.Reporter#detectedSymmetries(java.util.Set) + */ + public void detectedSymmetries(Set parts) {} + + /** + * @see kodkod.engine.config.Reporter#generatingSBP() + */ + public void generatingSBP() {} + + /** + * @see kodkod.engine.config.Reporter#flattening(kodkod.engine.bool.BooleanFormula) + */ + public void flattening(BooleanFormula circuit) {} + + /** + * {@inheritDoc} + * @see kodkod.engine.config.Reporter#skolemizing(kodkod.ast.Decl, kodkod.ast.Relation, java.util.List) + */ + public void skolemizing(Decl decl, Relation skolem, List context) {} + + /** + * @see kodkod.engine.config.Reporter#solvingCNF(int, int, int) + */ + public void solvingCNF(int primaryVars, int vars, int clauses) {} + + /** + * @see kodkod.engine.config.Reporter#optimizingBoundsAndFormula() + */ + public void optimizingBoundsAndFormula() {} + + /** + * @see kodkod.engine.config.Reporter#translatingToBoolean(kodkod.ast.Formula, kodkod.instance.Bounds) + */ + public void translatingToBoolean(Formula formula, Bounds bounds) {} + + /** + * @see kodkod.engine.config.Reporter#translatingToCNF(kodkod.engine.bool.BooleanFormula) + */ + public void translatingToCNF(BooleanFormula circuit) {} + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/config/ConsoleReporter.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/config/ConsoleReporter.java new file mode 100644 index 00000000..36c1ce50 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/config/ConsoleReporter.java @@ -0,0 +1,123 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.config; + + +import java.util.List; +import java.util.Set; + +import kodkod.ast.Decl; +import kodkod.ast.Formula; +import kodkod.ast.Relation; +import kodkod.engine.bool.BooleanFormula; +import kodkod.instance.Bounds; +import kodkod.util.ints.IntSet; + +/** + * An implementation of the reporter interface that prints messages + * to the standard output stream. + * @author Emina Torlak + */ +public final class ConsoleReporter implements Reporter { + + /** + * Constructs a new instance of the ConsoleReporter. + */ + public ConsoleReporter() {} + + /** + * @see kodkod.engine.config.Reporter#generatingSBP() + */ + public void generatingSBP() { + System.out.println("generating lex-leader symmetry breaking predicate ..."); + } + + /** + * @see kodkod.engine.config.Reporter#flattening(kodkod.engine.bool.BooleanFormula) + */ + public void flattening(BooleanFormula circuit) { + System.out.println("flattening ..."); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.config.Reporter#skolemizing(kodkod.ast.Decl, kodkod.ast.Relation, java.util.List) + */ + public void skolemizing(Decl decl, Relation skolem, List context) { + System.out.println("skolemizing " + decl + ": skolem relation=" + skolem + ", arity=" + skolem.arity()); + } + + /** + * @see kodkod.engine.config.Reporter#solvingCNF(int, int, int) + */ + public void solvingCNF(int primaryVars, int vars, int clauses) { + System.out.println("solving p cnf " + vars + " " + clauses); + } + + + /** + * {@inheritDoc} + * @see kodkod.engine.config.Reporter#detectingSymmetries(kodkod.instance.Bounds) + */ + public void detectingSymmetries(Bounds bounds){ + System.out.println("detecting symmetries ..."); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.config.Reporter#detectedSymmetries(java.util.Set) + */ + public void detectedSymmetries(Set parts) { +// System.out.println("detected symmetries: " + parts); + } + + /** + * @see kodkod.engine.config.Reporter#optimizingBoundsAndFormula() + */ + public void optimizingBoundsAndFormula() { + System.out.println("optimizing bounds and formula (breaking predicate symmetries, inlining, skolemizing) ..."); + } + + /** + * @see kodkod.engine.config.Reporter#translatingToBoolean(kodkod.ast.Formula, kodkod.instance.Bounds) + */ + public void translatingToBoolean(Formula formula, Bounds bounds) { + System.out.println("translating to boolean ..."); + } + + /** + * @see kodkod.engine.config.Reporter#translatingToCNF(kodkod.engine.bool.BooleanFormula) + */ + public void translatingToCNF(BooleanFormula circuit) { + System.out.println("translating to cnf ..."); + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + return "ConsoleReporter"; + } + + + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/config/Options.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/config/Options.java new file mode 100644 index 00000000..be453f46 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/config/Options.java @@ -0,0 +1,414 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.config; + +import kodkod.engine.satlab.SATFactory; +import kodkod.util.ints.IntRange; +import kodkod.util.ints.Ints; + +/** + * Stores information about various + * user-level translation and analysis options. It can be + * used to choose the SAT solver, control symmetry breaking, etc. + * + * @specfield solver: SATFactory // SAT solver factory to use + * @specfield reporter: Reporter // reporter to use + * @specfield symmetryBreaking: int // the amount of symmetry breaking to perform + * @specfield sharing: int // the depth to which circuits should be checked for equivalence during translation + * @specfield intEncoding: IntEncoding // encoding to use for translating int expressions + * @specfield bitwidth: int // the bitwidth to use for integer representation / arithmetic + * @specfield skolemDepth: int // skolemization depth + * @specfield nof: boolean // no overflow (detect and forbid overflows) + * @specfield flatten: boolean // eliminate intermediate variables when possible? default is false. + * @specfield logTranslation: [0..2] // log translation events, default is 0 (no logging) + * @specfield coreGranularity: [0..3] // unsat core granularity, default is 0 (only top-level conjuncts are considered) + * @author Emina Torlak + */ +public final class Options { + private Reporter reporter = new AbstractReporter(){}; + private SATFactory solver = SATFactory.DefaultSAT4J; + private int symmetryBreaking = 20; + private IntEncoding intEncoding = IntEncoding.TWOSCOMPLEMENT; + private int bitwidth = 4; + private int sharing = 3; + private boolean nof = false; + private int skolemDepth = 0; + private boolean flatten = false; + private int logTranslation = 0; + private int coreGranularity = 0; + + //[AM] + public static boolean isDebug() { + return false; //TODO: read from the environment or something + } + + /** + * Constructs an Options object initalized with + * default values. + * @ensures this.solver' = SATFactory.DefaultSAT4J + * this.reporter' is silent (no messages reported) + * this.symmetryBreaking' = 20 + * this.sharing' = 3 + * this.intEncoding' = BINARY + * this.bitwidth' = 4 + * this.skolemDepth' = 0 + * this.flatten' = false + * this.logTranslation' = 0 + * this.coreGranularity' = 0 + */ + public Options() {} + + /** + * Returns the value of the solver options. + * The default is SATSolver.DefaultSAT4J. + * @return this.solver + */ + public SATFactory solver() { + return solver; + } + + /** + * Sets the solver option to the given value. + * @ensures this.solver' = solver + * @throws NullPointerException - solver = null + */ + public void setSolver(SATFactory solver) { + if (solver==null) + throw new NullPointerException(); + this.solver = solver; + } + + /** + * Returns this.reporter. + * @return this.reporter + */ + public Reporter reporter() { + return reporter; + } + + /** + * Sets this.reporter to the given reporter. + * @requires reporter != null + * @ensures this.reporter' = reporter + * @throws NullPointerException - reporter = null + */ + public void setReporter(Reporter reporter) { + if (reporter==null) + throw new NullPointerException(); + this.reporter = reporter; + } + + /** + * Returns the noOverflow flag + */ + public boolean noOverflow() { return nof; } + + /** + * Sets the noOverflow flag + */ + public void setNoOverflow(boolean noOverflow) { this.nof = noOverflow; } + + /** + * @throws IllegalArgumentException - arg !in [min..max] + */ + private void checkRange(int arg, int min, int max) { + if (arg < min || arg > max) + throw new IllegalArgumentException(arg + " !in [" + min + ".." + max + "]"); + } + + + + /** + * Returns the integer encoding that will be used for translating {@link kodkod.ast.IntExpression int nodes}. + * The default is BINARY representation, which allows negative numbers. UNARY representation is best suited to + * problems with small scopes, in which cardinalities are only compared (and possibly added to each other or + * non-negative numbers). + * @return this.intEncoding + */ + public IntEncoding intEncoding() { + return intEncoding; + } + + /** + * Sets the intEncoding option to the given value. + * @ensures this.intEncoding' = encoding + * @throws NullPointerException - encoding = null + * @throws IllegalArgumentException - this.bitwidth is not a valid bitwidth for the specified encoding + */ + public void setIntEncoding(IntEncoding encoding) { + if (encoding.maxAllowedBitwidth() 32 + */ + public void setBitwidth(int bitwidth) { + checkRange(bitwidth, 1, intEncoding.maxAllowedBitwidth()); + this.bitwidth = bitwidth; + } + + /** + * Returns the range of integers that can be encoded + * using this.intEncoding and this.bitwidth. + * @return range of integers that can be encoded + * using this.intEncoding and this.bitwidth. + */ + public IntRange integers() { + return intEncoding.range(bitwidth); + } + + /** + * Returns the value of the flattening flag, which specifies whether + * to eliminate extraneous intermediate variables. The flag is false by default. + * Flattening must be off if translation logging is enabled. + * @return this.flatten + */ + public boolean flatten() { + return flatten; + } + + /** + * Sets the flattening option to the given value. + * @ensures this.flatten' = flatten + * @throws IllegalArgumentException - this.logTranslation>0 && flatten + */ + public void setFlatten(boolean flatten) { + if (logTranslation>0 && flatten) + throw new IllegalStateException("logTranslation enabled: flattening must be off."); + this.flatten = flatten; + } + + /** + * Returns the 'amount' of symmetry breaking to perform. + * If a non-symmetric solver is chosen for this.solver, + * this value controls the maximum length of the generated + * lex-leader symmetry breaking predicate. If a symmetric + * solver is chosen, this value controls the amount of + * symmetry information to pass to the solver. (For example, + * if a formula has 10 relations on which symmetry can be broken, + * and the symmetryBreaking option is set to 5, then symmetry information + * will be computed for only 5 of the 10 relations.) In general, + * the higher this value, the more symmetries will be broken, and the + * faster the formula will be solved. But, setting the value too high + * may have the opposite effect and slow down the solving. The default + * value for this property is 20. + * @return this.symmetryBreaking + */ + public int symmetryBreaking() { + return symmetryBreaking; + } + + /** + * Sets the symmetryBreaking option to the given value. + * @ensures this.symmetryBreaking' = symmetryBreaking + * @throws IllegalArgumentException - symmetryBreaking !in [0..Integer.MAX_VALUE] + */ + public void setSymmetryBreaking(int symmetryBreaking) { + checkRange(symmetryBreaking, 0, Integer.MAX_VALUE); + this.symmetryBreaking = symmetryBreaking; + } + + /** + * Returns the depth to which circuits are checked for equivalence during translation. + * The default depth is 3, and the minimum allowed depth is 1. Increasing the sharing + * may result in a smaller CNF, but at the cost of slower translation times. + * @return this.sharing + */ + public int sharing() { + return sharing; + } + + /** + * Sets the sharing option to the given value. + * @ensures this.sharing' = sharing + * @throws IllegalArgumentException - sharing !in [1..Integer.MAX_VALUE] + */ + public void setSharing(int sharing) { + checkRange(sharing, 1, Integer.MAX_VALUE); + this.sharing = sharing; + } + + /** + * Returns the depth to which existential quantifiers are skolemized. + * A negative depth means that no skolemization is performed. + * The default depth of 0 means that only existentials that are not nested + * within a universal quantifiers are skolemized. A depth of 1 means that + * existentials nested within a single universal are also skolemized, etc. + * @return this.skolemDepth + */ + public int skolemDepth() { + return skolemDepth; + } + + /** + * Sets the skolemDepth to the given value. + * @ensures this.skolemDepth' = skolemDepth + */ + public void setSkolemDepth(int skolemDepth) { + this.skolemDepth = skolemDepth; + } + + /** + * Returns the translation logging level (0, 1, or 2), where 0 + * means logging is not performed, 1 means only the translations of + * top level formulas are logged, and 2 means all formula translations + * are logged. This is necessary for determining which formulas occur in the unsat core of an + * unsatisfiable formula. Flattening must be off whenever + * logging is enabled. Logging is off by default, since + * it incurs a non-trivial time overhead. + * @return this.logTranslation + */ + public int logTranslation() { + return logTranslation; + } + + /** + * Sets the translation logging level. If the level is above 0, + * flattening is automatically disabled. + * @requires logTranslation in [0..2] + * @ensures this.logTranslation' = logTranslation && + * logTranslation>0 => this.flatten' = false + * @throws IllegalArgumentException - logTranslation !in [0..2] + */ + public void setLogTranslation(int logTranslation) { + checkRange(logTranslation, 0, 2); + if (logTranslation>0) { + flatten = false; + } + this.logTranslation = logTranslation; + } + + /** + * Returns the core granularity level. The default is 0, which means that top-level + * conjuncts of the input formula are used as "roots" for the purposes of core minimization and extraction. Granularity + * of 1 means that the top-level conjuncts of the input formula's negation normal form (NNF) are + * used as roots; granularity of 2 means that the top-level conjuncts of the formula's skolemized + * NNF (SNNF) are used as roots; and, finally, a granularity of 3 means that the universal quantifiers of the formula's + * SNNF are broken up and that the resulting top-level conjuncts are then used as roots for core minimization and extraction. + * + *

Note that the finer granularity (that is, a larger value of this.coreGranularity) will provide better information at + * the cost of slower core extraction and, in particular, minimization.

+ * + * @return this.coreGranularity + */ + public int coreGranularity() { + return coreGranularity; + } + + /** + * Sets the core granularity level. + * @requires coreGranularity in [0..3] + * @ensures this.coreGranularity' = coreGranularity + * @throws IllegalArgumentException - coreGranularity !in [0..3] + */ + public void setCoreGranularity(int coreGranularity) { + checkRange(coreGranularity, 0, 3); + this.coreGranularity = coreGranularity; + } + + /** + * Returns a string representation of this Options object. + * @return a string representation of this Options object. + */ + public String toString() { + StringBuilder b = new StringBuilder(); + b.append("Options:"); + b.append("\n solver: "); + b.append(solver); + b.append("\n reporter: "); + b.append(reporter); + b.append("\n intEncoding: "); + b.append(intEncoding); + b.append("\n bitwidth: "); + b.append(bitwidth); + b.append("\n sharing: "); + b.append(sharing); + b.append("\n flatten: "); + b.append(flatten); + b.append("\n symmetryBreaking: "); + b.append(symmetryBreaking); + b.append("\n noOverflow: "); + b.append(nof); + b.append("\n skolemDepth: "); + b.append(skolemDepth); + b.append("\n logTranslation: "); + b.append(logTranslation); + b.append("\n coreGranularity: "); + b.append(coreGranularity); + return b.toString(); + } + + /** + * Integer encoding options for the translation of + * {@link kodkod.ast.IntExpression int expressions}. + */ + public static enum IntEncoding { + /** + * Two's-complement encoding of integers supports + * comparisons, addition, subtraction, multiplication, + * division, and all low-level bit operations + * (shifting, and, or, not, etc.). Maximum allowed + * bitwidth for this encoding is 32 bits. + */ + TWOSCOMPLEMENT { + @Override + int maxAllowedBitwidth() { return 32; } + @Override + IntRange range(int bitwidth) { + final int shift = bitwidth-1; + return Ints.range(-1< 0 + * @return range of integers representable with + * this encoding using the given number of bits. + */ + abstract IntRange range(int bitwidth) ; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/config/Reporter.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/config/Reporter.java new file mode 100644 index 00000000..219578d1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/config/Reporter.java @@ -0,0 +1,108 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.config; + + +import java.util.List; +import java.util.Set; + +import kodkod.ast.Decl; +import kodkod.ast.Formula; +import kodkod.ast.Relation; +import kodkod.engine.bool.BooleanFormula; +import kodkod.instance.Bounds; +import kodkod.util.ints.IntSet; + +/** + * Enables passing of messages between the kodkod engine + * and the client about the following stages of the analysis: + *
    + *
  1. symmetry detection + *
  2. bounds and formula optimization (breaking of predicate symmetries, predicate inlining and skolemization)
  3. + *
  4. translation to a boolean circuit
  5. + *
  6. symmetry breaking predicate (SBP) generation
  7. + *
  8. circuit flattening
  9. + *
  10. translation to cnf
  11. + *
  12. running a sat solver on the generated cnf
  13. + *
+ * Some of these stages may not be executed, depending on the + * {@link Options options} used for analysis. + * @author Emina Torlak + */ +public interface Reporter { + + /** + * Reports that symmetry detection started on the given bounds. + * The given bounds must not be mutated. + */ + public void detectingSymmetries(Bounds bounds); + + /** + * Reports the symmetry partitions that were detected. + * The given partitions must not be mutated. + */ + public void detectedSymmetries(Set parts); + + /** + * Reports that bounds optimization is in progress (stage 2). + */ + public void optimizingBoundsAndFormula(); + + /** + * Reports that the given declaration is being skolemized using the + * given skolem relation. The context list contains non-skolemizable + * quantified declarations on which the given decl depends, in the order of declaration + * (most recent decl is last in the list). + */ + public void skolemizing(Decl decl, Relation skolem, List context); + + /** + * Reports that the analysis of the given (optimized) formula + * and bounds is in stage 3. The given bounds must not be mutated. + * @ensures bounds' = bounds + */ + public void translatingToBoolean(Formula formula, Bounds bounds); + + /** + * Reports that the analysis is in stage 4. + */ + public void generatingSBP(); + + /** + * Reports that the stage 5 of the analysis is + * being performed on the given boolean formula. + */ + public void flattening(BooleanFormula circuit); + + /** + * Reports that the given (optimized) + * circuit is being translated to CNF (stage 6 of the analysis). + */ + public void translatingToCNF(BooleanFormula circuit); + + /** + * Reports that the cnf generated in stage 7, consisting of the + * given number of variables and clauses, is being analyzed by + * a sat solver (stage 8 of the analysis). + */ + public void solvingCNF(int primaryVars, int vars, int clauses); +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/Bool2CNFTranslator.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/Bool2CNFTranslator.java new file mode 100644 index 00000000..01a00543 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/Bool2CNFTranslator.java @@ -0,0 +1,302 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import static kodkod.engine.bool.Operator.AND; +import kodkod.engine.bool.BooleanFormula; +import kodkod.engine.bool.BooleanVariable; +import kodkod.engine.bool.BooleanVisitor; +import kodkod.engine.bool.ITEGate; +import kodkod.engine.bool.MultiGate; +import kodkod.engine.bool.NotGate; +import kodkod.engine.bool.Operator; +import kodkod.engine.satlab.SATFactory; +import kodkod.engine.satlab.SATSolver; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.Ints; + +/** + * Transforms a boolean circuit into a formula in conjunctive + * normal form. + * + * @author Emina Torlak + */ +final class Bool2CNFTranslator implements BooleanVisitor { + + /** + * Creates a new instance of SATSolver using the provided factory + * and uses it to translate the given circuit into conjunctive normal form + * using the definitional translation algorithm. + * The third parameter is required to contain the number of primary variables + * allocated during translation from FOL to boolean. + * @return a SATSolver instance returned by the given factory and initialized + * to contain the CNF translation of the given circuit. + */ + static SATSolver translate(BooleanFormula circuit, SATFactory factory, int numPrimaryVariables) { + final SATSolver solver = factory.instance(); + final Bool2CNFTranslator translator = new Bool2CNFTranslator(solver, numPrimaryVariables, circuit); +// System.out.println("--------------transls2-------------"); + if (circuit.op()==Operator.AND) { + for(BooleanFormula input : circuit) { +// System.out.println(input); +// solver.addClause(input.accept(translator,null)); + input.accept(translator, null); + } + for(BooleanFormula input : circuit) { + translator.unaryClause[0] = input.label(); + solver.addClause(translator.unaryClause); + } + } else { + solver.addClause(circuit.accept(translator,null)); + } + return solver; + } + + /** + * Helper visitor that performs definitional translation to cnf . + * @specfield root: BooleanFormula // the translated circuit + */ + + private final SATSolver solver; + private final IntSet visited; + private final PolarityDetector pdetector; + private final int[] unaryClause = new int[1]; + private final int[] binaryClause = new int[2]; + private final int[] ternaryClause = new int[3]; + + /** + * Constructs a translator for the given circuit. + * @ensures this.root' = circuit + */ + private Bool2CNFTranslator(SATSolver solver, int numPrimaryVars, BooleanFormula circuit) { + final int maxLiteral = StrictMath.abs(circuit.label()); + this.solver = solver; + this.solver.addVariables(StrictMath.max(numPrimaryVars, maxLiteral)); + this.pdetector = (new PolarityDetector(numPrimaryVars, maxLiteral)).apply(circuit); + this.visited = Ints.bestSet(pdetector.offset, StrictMath.max(pdetector.offset, maxLiteral)); + } + + /** @return 0->lit */ + final int[] clause(int lit) { + unaryClause[0] = lit; + return unaryClause; + } + /** @return 0->lit0 + 1->lit1 */ + final int[] clause(int lit0, int lit1) { + binaryClause[0] = lit0; binaryClause[1] = lit1; + return binaryClause; + } + /** @return 0->lit0 + 1->lit1 + 2->lit2 */ + final int[] clause(int lit0, int lit1, int lit2) { + ternaryClause[0] = lit0; ternaryClause[1] = lit1; ternaryClause[2] = lit2; + return ternaryClause; + } + + /** + * Adds translation clauses to the solver and returns an array containing the + * gate's literal. The CNF clauses are generated according to the standard SAT to CNF translation: + * o = AND(i1, i2, ... ik) ---> (i1 | !o) & (i2 | !o) & ... & (ik | !o) & (!i1 | !i2 | ... | !ik | o), + * o = OR(i1, i2, ... ik) ---> (!i1 | o) & (!i2 | o) & ... & (!ik | o) & (i1 | i2 | ... | ik | !o). + * @return o: int[] | o.length = 1 && o.[0] = multigate.literal + * @ensures if the multigate has not yet been visited, its children are visited + * and the clauses are added to the solver connecting the multigate's literal to + * its input literal, as described above. + */ + public int[] visit(MultiGate multigate, Object arg) { + final int oLit = multigate.label(); + if (visited.add(oLit)) { + final int sgn; final boolean p, n; + if (multigate.op()==AND) { + sgn = 1; p = pdetector.positive(oLit); n = pdetector.negative(oLit); + } else { // multigate.op()==OR + sgn = -1; n = pdetector.positive(oLit); p = pdetector.negative(oLit); + } + final int[] lastClause = n ? new int[multigate.size()+1] : null; + final int output = oLit * -sgn; + int i = 0; + for(BooleanFormula input : multigate) { + int iLit = input.accept(this, arg)[0]; + if (p) { + solver.addClause(clause(iLit * sgn, output)); + } + if (n) { + lastClause[i++] = iLit * -sgn; + } + } + if (n) { + lastClause[i] = oLit * sgn; + solver.addClause(lastClause); + } + } + return clause(oLit); + } + + /** + * Adds translation clauses to the solver and returns an array containing the + * gate's literal. The CNF clauses are generated according to the standard SAT to CNF translation: + * o = ITE(i, t, e) ---> (!i | !t | o) & (!i | t | !o) & (i | !e | o) & (i | e | !o) + * @return o: int[] | o.length = 1 && o.[0] = itegate.literal + * @ensures if the itegate has not yet been visited, its children are visited + * and the clauses are added to the solver connecting the multigate's literal to + * its input literal, as described above. + */ + public int[] visit(ITEGate itegate, Object arg) { + final int oLit = itegate.label(); + if (visited.add(oLit)) { + final int i = itegate.input(0).accept(this, arg)[0]; + final int t = itegate.input(1).accept(this, arg)[0]; + final int e = itegate.input(2).accept(this, arg)[0]; + final boolean p = pdetector.positive(oLit), n = pdetector.negative(oLit); + if (p) { + solver.addClause(clause(-i, t, -oLit)); + solver.addClause(clause(i, e, -oLit)); + // redundant clause that strengthens unit propagation + solver.addClause(clause(t, e, -oLit)); + } + if (n) { + solver.addClause(clause(-i, -t, oLit)); + solver.addClause(clause(i, -e, oLit)); + // redundant clause that strengthens unit propagation + solver.addClause(clause(-t, -e, oLit)); + } + } + return clause(oLit); + } + + /** + * Returns the negation of the result of visiting negation.input, wrapped in + * an array. + * @return o: int[] | o.length = 1 && o[0] = - translate(negation.inputs)[0] + * */ + public int[] visit(NotGate negation, Object arg) { + return clause(-negation.input(0).accept(this, arg)[0]); + } + + /** + * Returns the variable's literal wrapped in a an array. + * @return o: int[] | o.length = 1 && o[0] = variable.literal + */ + public int[] visit(BooleanVariable variable, Object arg) { + return clause(variable.label()); + } + + + /** + * Helper visitor that detects pdetector of subformulas. + * @specfield root: BooleanFormula // the root of the DAG for whose components we are storing pdetector information + */ + private static final class PolarityDetector implements BooleanVisitor { + final int offset; + /** + * @invariant all i : [0..polarity.length) | + * pdetector[i] = 0 <=> formula with label offset + i has not been visited, + * pdetector[i] = 1 <=> formula with label offset + i has been visited with positive pdetector only, + * pdetector[i] = 2 <=> formula with label offset + i has been visited with negative pdetector only, + * pdetector[i] = 3 <=> formula with label offset + i has been visited with both polarities + */ + private final int[] polarity; + private final Integer[] ints = { Integer.valueOf(3), Integer.valueOf(1), Integer.valueOf(2) }; + + /** + * Creates a new pdetector detector and applies it to the given circuit. + * @requires maxLiteral = |root.label()| + */ + PolarityDetector(int numPrimaryVars, int maxLiteral) { + this.offset = numPrimaryVars+1; + this.polarity = new int[StrictMath.max(0, maxLiteral-numPrimaryVars)]; + } + + /** + * Applies this detector to the given formula, and returns this. + * @requires this.root = root + * @ensures this.visit(root) + * @return this + */ + PolarityDetector apply(BooleanFormula root) { + root.accept(this, ints[1]); + return this; + } + + /** + * Returns true if the formula with the given label occurs positively in this.root. + * @requires this visitor has been applied to this.root + * @requires label in (MultiGate + ITEGate).label + * @return true if the formula with the given label occurs positively in this.root. + */ + boolean positive(int label) { + return (polarity[label-offset] & 1) > 0; + } + + /** + * Returns true if the formula with the given label occurs negatively in this.root. + * @requires this visitor has been applied to this.root + * @requires label in (MultiGate + ITEGate).label + * @return true if the formula with the given label occurs negatively in this.root. + */ + boolean negative(int label) { + return (polarity[label-offset] & 2) > 0; + } + + /** + * Returns true if the given formula has been visited with the specified + * pdetector (1 = positive, 2 = negative, 3 = both). Otherwise records the visit and returns false. + * @requires formula in (MultiGate + ITEGate) + * @requires pdetector in this.ints + * @return true if the given formula has been visited with the specified + * pdetector. Otherwise records the visit and returns false. + */ + private boolean visited(BooleanFormula formula, Integer polarity) { + final int index = formula.label() - offset; + final int value = this.polarity[index]; + return (this.polarity[index] = value | polarity) == value; + } + + public Object visit(MultiGate multigate, Integer arg) { + if (!visited(multigate, arg)) { + for(BooleanFormula input : multigate) { + input.accept(this, arg); + } + } + return null; + } + + public Object visit(ITEGate ite, Integer arg) { + if (!visited(ite, arg)) { + // the condition occurs both positively and negative in an ITE gate + ite.input(0).accept(this, ints[0]); + ite.input(1).accept(this, arg); + ite.input(2).accept(this, arg); + } + return null; + } + + public Object visit(NotGate negation, Integer arg) { + return negation.input(0).accept(this, ints[3-arg]); + } + + public Object visit(BooleanVariable variable, Integer arg) { + return null; // nothing to do + } + + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/BooleanFormulaFlattener.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/BooleanFormulaFlattener.java new file mode 100644 index 00000000..120b3e07 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/BooleanFormulaFlattener.java @@ -0,0 +1,230 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.Map; + +import kodkod.engine.bool.BooleanAccumulator; +import kodkod.engine.bool.BooleanFactory; +import kodkod.engine.bool.BooleanFormula; +import kodkod.engine.bool.BooleanValue; +import kodkod.engine.bool.BooleanVariable; +import kodkod.engine.bool.BooleanVisitor; +import kodkod.engine.bool.ITEGate; +import kodkod.engine.bool.MultiGate; +import kodkod.engine.bool.NotGate; +import kodkod.engine.bool.Operator; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.Ints; + +/** + *

Given a {@link kodkod.engine.bool.BooleanValue boolean value}, v, and a + * {@link kodkod.engine.bool.BooleanFactory factory}, F, + * a BooleanFormulaFlattener eliminates as many + * intermediate gates as possible from v, and stores the flattened tree of v in F. + * An intermediate gate's inputs are absorbed into the parent's iff the + * the gate's fanout is 1 and the gate and its parent are MultiGates with the same operator. + * For example, suppose that the root corresponds to the formula + * ((1 || 2) || 3 || !(4 || 5) || (6 & (7 & 8))), and that the components of this formula are + * assigned the following labels: (1 || 2) ---> 9, (4 || 5) ---> 10, !(4 || 5) ---> -10, (7 & 8) ---> 11, + * (6 & (7 & 8)) ---> 12, and ((1 || 2) || 3 || !(4 || 5) || (6 & 7 & 8)) ---> 13. + * Calling this.flatten(root) will flatten the root to (1 || 2 || 3 || !(4 || 5) || (6 & 7 & 8)), + * re-assigning the labels as follows: (4 || 5) ---> 9, !(4 || 5) ---> -9, (6 & 7 & 8) ---> 10, and + * (1 || 2 || 3 || !(4 || 5) || (6 & 7 & 8)) ---> 11. + * + * @author Emina Torlak + */ +final class BooleanFormulaFlattener implements BooleanVisitor { + + + + /** + * Flattens the given value using f and returns it. + * The method assumes that all variables at the leaves of + * the root are components of f. + * @requires root.*inputs in f.components + * @ensures f.components' = f.components & Variable + flatRoot.*inputs + * @return {flatRoot : BooleanValue | [[flatRoot]] = [[root]] && + * no d, p: flatRoot.*inputs & MultiGate | d in p.inputs && d.op = p.op && inputs.d != p } + */ + static final BooleanValue flatten(BooleanFormula root, BooleanFactory f) { + final int oldCompDepth = f.comparisonDepth(); + f.setComparisonDepth(1); + f.clear(); // remove everything but the variables from the factory + final BooleanFormulaFlattener flattener = new BooleanFormulaFlattener(root, f); + final BooleanValue flatRoot = root.accept(flattener, null); + f.setComparisonDepth(oldCompDepth); + return flatRoot; + } + + private final BooleanFactory factory; + private final IntSet flattenable; + private final Map cache; + + /** + * Constructs a new FlatteningVisitor. The returned visitor can only be applied to the specified + * root value. All the variables at the leaves of the given root must have been created by the + * given factory. + * @requires (root.*inputs & Variable) in factory.components + */ + private BooleanFormulaFlattener(BooleanFormula root, BooleanFactory factory) { + this.factory = factory; + final FlatteningDataGatherer dataGatherer = new FlatteningDataGatherer(root); + root.accept(dataGatherer, null); + this.flattenable = dataGatherer.flattenable; + dataGatherer.visited.removeAll(flattenable); + this.cache = new IdentityHashMap(dataGatherer.visited.size()); + } + + /** + * If p is null, returns v. Otherwise, adds v to p and + * returns the result. + */ + private final BooleanValue addToParent(BooleanValue v, BooleanAccumulator parent) { + return parent==null ? v : parent.add(v); + } + + /** + * Flattens the given multigate into its parent, if they have the multigate is not shared + * and it has the same operator as the parent. + * @return flattened gate + * @see kodkod.engine.bool.BooleanVisitor#visit(kodkod.engine.bool.MultiGate, java.lang.Object) + */ + public BooleanValue visit(MultiGate multigate, BooleanAccumulator parent) { + final Operator.Nary op = multigate.op(); + if (flattenable.contains(multigate.label())) { // multigate's inputs are absorbed into its parent's inputs +// System.out.println("Flattenable: " + multigate); + for(Iterator inputs = multigate.iterator(); inputs.hasNext();) { + if (inputs.next().accept(this, parent)==op.shortCircuit()) + return op.shortCircuit(); + } + return parent; + } else { // construct a gate that corresponds to the multigate +// System.out.println("Unflattenable: " + multigate); + BooleanValue replacement = cache.get(multigate); + + if (replacement == null) { + final BooleanAccumulator newGate = BooleanAccumulator.treeGate(op); + for(Iterator inputs = multigate.iterator(); inputs.hasNext();) { + if (inputs.next().accept(this,newGate)==op.shortCircuit()) { + return op.shortCircuit(); + } + } + replacement = factory.accumulate(newGate); + cache.put(multigate, replacement); + } + + return addToParent(replacement, parent); + } + } + + /** + * Returns the ite gate. + * @return itegate + * @see kodkod.engine.bool.BooleanVisitor#visit(kodkod.engine.bool.ITEGate, java.lang.Object) + */ + public BooleanValue visit(ITEGate itegate, BooleanAccumulator parent) { + return addToParent(factory.ite(itegate.input(0).accept(this,null), itegate.input(1).accept(this,null), + itegate.input(2).accept(this,null)), parent); + } + + /** + * Returns the not gate. + * @return negation + * @see kodkod.engine.bool.BooleanVisitor#visit(kodkod.engine.bool.NotGate, java.lang.Object) + */ + public BooleanValue visit(NotGate negation, BooleanAccumulator parent) { + return addToParent(factory.not(negation.input(0).accept(this,null)), parent); + } + + /** + * Returns the variable. + * @see kodkod.engine.bool.BooleanVisitor#visit(kodkod.engine.bool.BooleanVariable, java.lang.Object) + */ + public BooleanValue visit(BooleanVariable variable, BooleanAccumulator parent) { + return addToParent(variable, parent); + } + + + + /** + * A visitor that determins which gates can be flattened. Specifically, when + * applied to a given root, the flattenable field of the visitor contains the + * labels of all m such that m is a MultiGate descendent of the root and + * #inputs.m = 1 && (inputs.m).op = m.op => s.contains(m.label). That is, + * flattenable = {i: int | some m: root.^inputs & MultiGate | #inputs.m = 1 && (inputs.m).op = m.op && m.label = i} + */ + private static final class FlatteningDataGatherer implements BooleanVisitor { + /* contains the labels of all the flattenable multi gates */ + final IntSet flattenable; + /* contains the labels of all the visited multi gates */ + final IntSet visited; + + /** + * Constructs a new flattenning data gatherer. The returned visitor can only be + * applied to the specified root value. + */ + private FlatteningDataGatherer(BooleanFormula root) { + final int maxLit = StrictMath.abs(root.label()); + this.flattenable = Ints.bestSet(maxLit+1); + this.visited = Ints.bestSet(maxLit+1); + } + + public Object visit(MultiGate multigate, Operator parentOp) { + final int label = multigate.label(); + if (visited.contains(label)) { // we've seen this node already + flattenable.remove(label); + } else { // haven't seen it yet + visited.add(label); + if (parentOp == multigate.op()) flattenable.add(label); + // visit children + for(Iterator inputs = multigate.iterator(); inputs.hasNext();) { + inputs.next().accept(this, multigate.op()); + } + } + + return null; + } + + public Object visit(ITEGate itegate, Operator parentOp) { + if (visited.add(itegate.label())) { // not visited + itegate.input(0).accept(this,null); + itegate.input(1).accept(this,null); + itegate.input(2).accept(this,null); + } + return null; + } + + public Object visit(NotGate negation, Operator parentOp) { + negation.input(0).accept(this,null); + return null; + } + + public Object visit(BooleanVariable variable, Operator arg) { + return null; + } + + + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/Environment.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/Environment.java new file mode 100644 index 00000000..8929b00e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/Environment.java @@ -0,0 +1,190 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import kodkod.ast.Variable; + + + +/** + * Represents a variable binding environment as a + * map from a {@link kodkod.ast.Variable variable} to a + * {@link java.lang.Object value}. An environment has + * a (possibly empty) parent environment to which unsuccessful lookups + * are delegated. + * + * @specfield variable: lone Variable + * @specfield value: lone T + * @specfield type: lone E + * @specfield parent: Environment + * @invariant this = parent => no variable + * @author Emina Torlak + */ +public final class Environment { + private final Variable variable; + private final T value; + private final E type; + private final Environment parent; + private final Object envType; // may be null, but will typically contain Quantifier.ALL or Quantifier.SOME + + private boolean negated; + + /** + * Constructs the empty environment. + */ + private Environment() { + this.variable = null; + this.value = null; + this.type = null; + this.parent = this; + this.envType = null; + this.negated = false; + } + + /** + * Constructs a new environment with the specified parent + * and mapping. + * + * @ensures this.parent' = parent && this.variable' = variable && this.value' = value + */ + private Environment(Environment parent, Variable variable, E type, T value, Object quant, boolean negated) { + this.variable = variable; + this.value = value; + this.type = type; + this.parent = parent; + this.envType = quant; + this.negated = negated; + } + + /** + * Returns the empty environment. + * @return the empty environment. + */ + public static Environment empty() { + return new Environment(); + } + + /** + * Returns the parent environment of this, or null if this + * does not have a parent. + * + * @return this.parent + */ + public Environment parent() { return parent; } + + /** + * Returns a new environment that extends this environment with the specified + * mapping. + * @requires variable != null + * @return e : Environment | e.parent = this && e.variable = variable && e.value = value + */ + public Environment extend(Variable variable, E type, T value) { return extend(variable, type, value, null); } + public Environment extend(Variable variable, E type, T value, Object envType) { + return new Environment(this, variable, type, value, envType, false); + } + + public void negate() { + negated = !negated; + } + + /** + * Returns this.variable. + * @return this.variable + */ + public Variable variable() { + return this.variable; + } + + /** + * Return this.isInt. + * @return this.isInt + */ + public E type() { + return this.type; + } + + /** + * Returns this.value. + * @return this.value + */ + public T value() { + return this.value; + } + + /** + * Returns this.quant. + * @return this.quant + */ + public Object envType() { + return envType; + } + + public boolean isNegated() { + return negated; + } + + /** + * Returns true if this is the empty (root) environment; + * otherwise returns false. + * @return this.parent = this + */ + public boolean isEmpty() { + return this==this.parent; + } + + /** + * Looks up the given variable in this environment and its + * ancestors. If the variable is not bound in this + * environment or any of its ancestors, null is returned. + * If the variable is bound in multiple environments, + * the first found binding is returned. Note that null + * will also be returned if the variable is bound to null. + * @return variable = this.variable => this.value, this.parent.lookup(variable) + */ + public T lookup(Variable variable) { + Environment p = this; + // ok to use == for testing variable equality: + // see kodkod.ast.LeafExpression#equals + while(!p.isEmpty() && p.variable!=variable) { + p = p.parent; + } + return p.value; + } + + public E lookupType(Variable variable) { + Environment p = this; + // ok to use == for testing variable equality: + // see kodkod.ast.LeafExpression#equals + while(!p.isEmpty() && p.variable!=variable) { + p = p.parent; + } + return p.type; + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + return (parent.isEmpty() ? "[]" : parent.toString()) + "["+variable+"="+value+"]"; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/FOL2BoolCache.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/FOL2BoolCache.java new file mode 100644 index 00000000..5f216a3f --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/FOL2BoolCache.java @@ -0,0 +1,272 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.Set; + +import kodkod.ast.Expression; +import kodkod.ast.Node; +import kodkod.ast.Variable; +import kodkod.engine.bool.BooleanConstant; +import kodkod.engine.bool.BooleanMatrix; +import kodkod.util.nodes.AnnotatedNode; + + +/** + * Manages the caching policy for a translation from FOL to boolean. + * In particular it determines which translations + * to cache, when to throw them out of the cache, etc. + * + * @specfield node: Node // node being translated + * @specfield cached: node.*children // the nodes whose translations are cached + * @specfield cache: cached -> (Object ->lone Environment) + * @author Emina Torlak + */ +final class FOL2BoolCache { + private final Map cache; + + /** + * Constructs a new translation cache for the given annotated node. + * @ensures this.node' = annotated.node + */ + FOL2BoolCache(AnnotatedNode annotated) { + final CacheCollector collector = new CacheCollector(annotated.sharedNodes()); + annotated.node().accept(collector); + + this.cache = new IdentityHashMap(collector.cache().size()); + for(Map.Entry> e : collector.cache().entrySet()) { + Set freeVars = e.getValue(); + if (freeVars.isEmpty()) + this.cache.put(e.getKey(), new NoVarRecord()); + else + this.cache.put(e.getKey(), new MultiVarRecord(freeVars)); + } + } + + + /** + * If the translation of the given node, with its free variables + * bound as they are in the given environment, has been cached, + * the cached value is returned. Otherwise, null is returned. + * @return this.cache[node][Object] in env.map => + * this.cache[node].map, null + */ + @SuppressWarnings("unchecked") + T lookup(Node node, Environment env) { + final Record info = cache.get(node); + return info==null ? null : (T) info.get(env); + } + + /** + * Caches the given translation for the specified node, if the given node is + * in this.cached. Otherwise does nothing. + * The method returns the specified translation. + * @ensures node in this.cached => + * this.cache' = this.cache ++ node->translation->env, + * this.cache' = this.cache + * @return translation + */ + final T cache(Node node, T translation, Environment env) { + final Record info = cache.get(node); + if (info != null) { + info.set(translation, env); + } + return translation; + } + + /** + * Collects the free variables of the nodes in a given AST whose + * translations should be cached. + * @specfield root: Node + * @specfield cached: root.*children -> Set + * @invariant all c: root.*children | some cached[c] => cached[c] = freeVariables(c) + * @author Emina Torlak + */ + private static final class CacheCollector extends FreeVariableCollector { + + /** + * Constructs a new cache collector. + */ + protected CacheCollector(Set cached) { + super(cached); + } + + /** + * Returns this.cache. This method should be called *after* the + * visitor has been applied to this.root. + * @return this.cache + */ + final Map> cache() { + return cache; + } + + /** + * We record the set of free variables for the given node if the node is shared, + * or if it has free variables, none of which is the most recently declared variable. + * @ensures node in sharedNodes || + * ((node.^(~children) in (QuantifiedFormula + Comprehension)) && + * (some varsInScope.top() => !freeVars.contains(varsInScope.top()))) => + * this.cache' = this.cache ++ node->varsInScope, + * this.cache' = this.cache + * @return freeVars + */ + @Override + protected final Set cache(Node node, Set freeVars) { + if (cached.contains(node) || !varsInScope.empty() && !freeVars.contains(varsInScope.peek())) { + cache.put(node, reduce(freeVars)); + } + return freeVars; + } + + } + + /** + * A container class that stores the translation of a shared node + * (BooleanValue for formulas and BooleanMatrix for expressions) + * and bindings for the node's free variables which were used to + * generate the translation. + * Storing the bindings is necessary for proper handling of + * sharing within quantified formulas and comprehensions. + * This implementation assumes that each free variable is + * mapped to a BooleanMatrix of density one, whose sole entry + * is the BooleanConstant TRUE. + * @specfield varBinding: Variable -> lone int + * @specfield translation: lone Object + */ + private static abstract class Record { + Object translation; + /** + * Returns this.translation if the given environment + * has the same mappings for the free variables of + * the translated node as the ones used to generate + * this.translation. Otherwise returns null. + * @requires all v: varBinding.int | some e.lookup(v) + * @return all v: varBinding.int | e.lookup(v).get(varBinding[v])=TRUE => this.translation, null + * @throws NullPointerException - e = null + */ + abstract Object get(Environment e); + + /** + * Sets this.translation to the given translation + * and sets the free variable bindings to those + * given by the specified environment. + * @requires all v: varBinding.int | some env.lookup(v) + * @ensures this.translation' = translation && + * this.varBinding' = + * {v: this.varBinding.int, tupleIndex: int | + * tupleIndex = env.lookup(v).iterator().next().index() } + */ + abstract void set(Object transl, Environment env); + } + + /** + * A TranslationInfo for a node with one or more free variables. + */ + private static final class MultiVarRecord extends Record { + final Variable[] vars; + final int[] tuples; + + /** + * Constructs a translation unit for a node which + * has the given set of free variables. + * @ensures this.freeVariables' = vars && + * no this.translation' + */ + MultiVarRecord(Set freeVariables) { + this.vars = freeVariables.toArray(new Variable[freeVariables.size()]); + this.tuples = new int[freeVariables.size()]; + } + + /** + * @see kodkod.engine.fol2sat.FOL2BoolCache.Record#get(kodkod.engine.fol2sat.Environment) + */ + Object get(Environment e) { + if (translation==null) return null; + for(int i = 0; i < vars.length; i++) { + if (e.lookup(vars[i]).get(tuples[i])!=BooleanConstant.TRUE) + return null; + } + return translation; + } + + /** + * @see kodkod.engine.fol2sat.FOL2BoolCache.Record#set(java.lang.Object, kodkod.engine.fol2sat.Environment) + */ + void set(Object transl, Environment env) { + translation = transl; + for(int i = 0; i < vars.length; i++) { + final BooleanMatrix varVal = env.lookup(vars[i]); + tuples[i] = varVal.iterator().next().index(); + if (transl==varVal) { + translation = varVal.clone(); + } + } + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + final StringBuilder b = new StringBuilder("{"); + b.append(String.valueOf(translation)); + for(int i = 0; i < vars.length; i++) + { + b.append(" ("); + b.append(vars[i]); + b.append(", "); + b.append(tuples[i]); + b.append(")"); + } + b.append("}"); + return b.toString(); + } + } + + /** + * A TranslationInfo for a node with no free variables. + */ + private static final class NoVarRecord extends Record { + + /** + * @see kodkod.engine.fol2sat.FOL2BoolCache.Record#get(kodkod.engine.fol2sat.Environment) + */ + Object get(Environment e) { + return translation; + } + + /** + * @see kodkod.engine.fol2sat.FOL2BoolCache.Record#set(java.lang.Object, kodkod.engine.fol2sat.Environment) + */ + void set(Object transl, Environment env) { + translation = transl; + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + return "{" + translation+ "}"; + } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/FOL2BoolTranslator.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/FOL2BoolTranslator.java new file mode 100644 index 00000000..7d269168 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/FOL2BoolTranslator.java @@ -0,0 +1,1070 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import java.util.ArrayList; +import java.util.List; + +import kodkod.ast.BinaryExpression; +import kodkod.ast.BinaryFormula; +import kodkod.ast.BinaryIntExpression; +import kodkod.ast.ComparisonFormula; +import kodkod.ast.Comprehension; +import kodkod.ast.ConstantExpression; +import kodkod.ast.ConstantFormula; +import kodkod.ast.Decl; +import kodkod.ast.Decls; +import kodkod.ast.ExprToIntCast; +import kodkod.ast.Expression; +import kodkod.ast.Formula; +import kodkod.ast.IfExpression; +import kodkod.ast.IfIntExpression; +import kodkod.ast.IntComparisonFormula; +import kodkod.ast.IntConstant; +import kodkod.ast.IntExpression; +import kodkod.ast.IntToExprCast; +import kodkod.ast.MultiplicityFormula; +import kodkod.ast.NaryExpression; +import kodkod.ast.NaryFormula; +import kodkod.ast.NaryIntExpression; +import kodkod.ast.Node; +import kodkod.ast.NotFormula; +import kodkod.ast.ProjectExpression; +import kodkod.ast.QuantifiedFormula; +import kodkod.ast.Relation; +import kodkod.ast.RelationPredicate; +import kodkod.ast.SumExpression; +import kodkod.ast.UnaryExpression; +import kodkod.ast.UnaryIntExpression; +import kodkod.ast.Variable; +import kodkod.ast.operator.ExprCompOperator; +import kodkod.ast.operator.ExprOperator; +import kodkod.ast.operator.FormulaOperator; +import kodkod.ast.operator.Multiplicity; +import kodkod.ast.operator.Quantifier; +import kodkod.ast.visitor.ReturnVisitor; +import kodkod.engine.bool.BooleanAccumulator; +import kodkod.engine.bool.BooleanConstant; +import kodkod.engine.bool.BooleanFactory; +import kodkod.engine.bool.BooleanMatrix; +import kodkod.engine.bool.BooleanValue; +import kodkod.engine.bool.Dimensions; +import kodkod.engine.bool.Int; +import kodkod.engine.bool.Operator; +import kodkod.util.ints.IndexedEntry; +import kodkod.util.ints.IntIterator; +import kodkod.util.ints.IntSet; +import kodkod.util.nodes.AnnotatedNode; +import kodkod.util.nodes.Nodes; + +/** + * Translates an annotated node to boolean representation. + * @specfield node: AnnotatedNode // node to translate + * @specfield interpreter: LeafInterpreter // the interpreter used for translation + * @specfield env: Environment // current environment + * @author Emina Torlak + */ +abstract class FOL2BoolTranslator implements ReturnVisitor { + + /** + * Translates the given annotated formula or expression into a boolean + * formula or matrix, using the provided interpreter. + * @requires interpreter.relations = AnnotatedNode.relations(annotated) + * @return {transl: T | + * annotated.node in Formula => transl in BooleanValue, + * annotated.node in Expression => transl in BooleanMatrix, + * annotated.node in IntExpression => transl in Int} + * @throws HigherOrderDeclException - annotated.node contains a higher order declaration + * @throws UnboundLeafException - annotated.node refers to an undeclared variable + **/ + @SuppressWarnings("unchecked") + static final T translate(AnnotatedNode annotated, LeafInterpreter interpreter) { + final FOL2BoolCache cache = new FOL2BoolCache(annotated); + final FOL2BoolTranslator translator = new FOL2BoolTranslator(cache, interpreter) {}; + return (T) annotated.node().accept(translator); + } + + /** + * Translates the given annotated formula into a boolean + * accumulator with respect to the given interpreter and logs the translation events to the given logger. + * @requires interpreter.relations = AnnotatedNode.relations(annotated) + * @requires annotated.source[annotated.sourceSensitiveRoots()] = Nodes.roots(annotated.source[annotated.node]) + * @return BooleanAccumulator that is the meaning of the given annotated formula with respect to the given interpreter + * @ensures log.records' contains the translation events that occurred while generating the returned value + * @throws HigherOrderDeclException - annotated.node contains a higher order declaration + * @throws UnboundLeafException - annotated.node refers to an undeclared variable + **/ + static final BooleanAccumulator translate(final AnnotatedNode annotated, LeafInterpreter interpreter, final TranslationLogger logger) { + final FOL2BoolCache cache = new FOL2BoolCache(annotated); + final FOL2BoolTranslator translator = new FOL2BoolTranslator(cache, interpreter) { + BooleanValue cache(Formula formula, BooleanValue translation) { + logger.log(formula, translation, super.env); + return super.cache(formula, translation); + } + }; + final BooleanAccumulator acc = BooleanAccumulator.treeGate(Operator.AND); + + for(Formula root : Nodes.conjuncts(annotated.node())) { + acc.add(root.accept(translator)); + } + logger.close(); + return acc; + } + + /** + * Translates the given annotated expression into a boolean + * matrix that is a least sound upper bound on the expression's + * value, given the leaf and variable bindings in the + * the provided interpreter and environment. + * @requires interpreter.relations = AnnotatedNode.relations(annotated) + * @return a boolean matrix that is a least sound upper bound on the expression's value + * @throws HigherOrderDeclException - annotated.node contains a higher order declaration + * @throws UnboundLeafException - annotated.node refers to a variable that neither declared nor bound in env + **/ + static final BooleanMatrix approximate(AnnotatedNode annotated, LeafInterpreter interpreter, Environment env) { + final FOL2BoolTranslator approximator = new FOL2BoolTranslator(new FOL2BoolCache(annotated), interpreter, env) { + public final BooleanMatrix visit(BinaryExpression binExpr) { + final BooleanMatrix ret = lookup(binExpr); + if (ret!=null) return ret; + switch(binExpr.op()){ + case DIFFERENCE : return cache(binExpr, binExpr.left().accept(this)); + case OVERRIDE : return cache(binExpr, binExpr.left().accept(this).or(binExpr.right().accept(this))); + default : return super.visit(binExpr); + } + } + public final BooleanMatrix visit(Comprehension cexpr) { + final BooleanMatrix ret = lookup(cexpr); + return ret!=null ? ret : cache(cexpr, super.visit((Comprehension)Formula.TRUE.comprehension(cexpr.decls()))); + } + public BooleanMatrix visit(IfExpression ifExpr) { + final BooleanMatrix ret = lookup(ifExpr); + return ret!=null ? ret : cache(ifExpr, ifExpr.thenExpr().accept(this).or(ifExpr.elseExpr().accept(this))); + } + public BooleanMatrix visit(IntToExprCast castExpr) { + BooleanMatrix ret = lookup(castExpr); + if (ret!=null) return ret; + switch(castExpr.op()) { + case INTCAST : + ret = Expression.INTS.accept(this); + break; + case BITSETCAST : + final BooleanFactory factory = super.interpreter.factory(); + ret = factory.matrix(Dimensions.square(super.interpreter.universe().size(), 1)); + final IntSet ints = super.interpreter.ints(); + final int msb = factory.bitwidth()-1; + // handle all bits but the sign bit + for(int i = 0; i < msb; i++) { + int pow2 = 1< env; + + private final FOL2BoolCache cache; + + /* Holds variables discovered while visiting an expression to be cast to Int. + * (because, for the new "overflow" semantics of quantifiers, we want to know the + * variables that contribute to every Int */ + //[AM] + private NestedSet vars = NestedSet.empty(); + + /** + * Constructs a new translator that will use the given translation cache + * and interpreter to perform the translation. + * @ensures this.node' = manager.node + */ + private FOL2BoolTranslator(FOL2BoolCache cache, LeafInterpreter interpreter) { + this.cache = cache; + this.interpreter = interpreter; + this.env = Environment.empty(); + } + + /** + * Constructs a new translator that will use the given translation cache, + * interpreter and environment to perform the translation. + * @ensures this.node' = manager.node + */ + private FOL2BoolTranslator(FOL2BoolCache cache, LeafInterpreter interpreter, Environment env) { + this.interpreter = interpreter; + this.env = env; + this.cache = cache; + } + + /** + * Retrieves the cached translation for the given node, if any. + * Otherwise returns null. + * @return the cached translation for the given node, if any. + * Otherwise returns null. + */ + @SuppressWarnings("unchecked") + final T lookup(Node node) { + return (T) cache.lookup(node, env); + } + + /** + * The translation is cached, if necessary, and returned. + * @return translation + * @ensures the translation may be cached + */ + final T cache(Node node, T translation) { + return cache.cache(node, translation, env); + } + + /** + * The translation is cached, if necessary, and returned. + * @return translation + * @ensures the translation may be cached + */ + BooleanValue cache(Formula formula, BooleanValue translation) { + return cache.cache(formula, translation, env); + } + + /** + * Calls lookup(decls) and returns the cached value, if any. + * If a translation has not been cached, translates decls into a list + * of translations of its children, + * calls cache(...) on it and returns it. + * @return let t = lookup(decls) | + * some t => t, cache(decl, decls.declarations.expression.accept(this)) + */ + public final List visit(Decls decls) { + List ret = lookup(decls); + if (ret!=null) return ret; + ret = new ArrayList(decls.size()); + for(Decl decl : decls) { + ret.add(visit(decl)); + } + return cache(decls, ret); + } + + /** + * Calls lookup(decl) and returns the cached value, if any. + * If a translation has not been cached, translates decl.expression, + * calls cache(...) on it and returns it. + * @return let t = lookup(decl) | + * some t => t, cache(decl, decl.expression.accept(this)) + */ + public final BooleanMatrix visit(Decl decl) { + BooleanMatrix matrix = lookup(decl); + if (matrix!=null) return matrix; + if (decl.multiplicity()!=Multiplicity.ONE) + throw new HigherOrderDeclException(decl); + return cache(decl, decl.expression().accept(this)); + } + + /** + * Calls this.env.lookup(variable) and returns the current binding for the + * given variable and adds it to the current level of nested variables (cars). + * If no binding is found, an UnboundLeafException is thrown. + * @return this.env.lookup(variable) + * @throws UnboundLeafException - no this.env.lookup(variable) + */ + public final BooleanMatrix visit(Variable variable) { + final BooleanMatrix ret = env.lookup(variable); + if (ret == null) + throw new UnboundLeafException("Unbound variable", variable); + vars.add(variable); + return ret; + } + + /** + * Returns this.interpreter.interpret(relation). + * @return this.interpreter.interpret(relation) + */ + public final BooleanMatrix visit(Relation relation) { + return interpreter.interpret(relation); + } + + /** + * Returns this.interpreter.interpret(constExpr). + * @return this.interpreter.interpret(constExpr). + */ + public final BooleanMatrix visit(ConstantExpression constExpr) { + return interpreter.interpret(constExpr); + } + + /** + * Calls lookup(binExpr) and returns the cached value, if any. + * If a translation has not been cached, translates the expression, + * calls cache(...) on it and returns it. + * @return let t = lookup(binExpr) | some t => t, + * let op = (binExpr.op).(UNION->or + INTERSECTION->and + DIFFERENCE->difference + OVERRIDE->override + JOIN->dot + PRODUCT->cross) | + * cache(binExpr, op(binExpr.left.accept(this), binExpr.right.accept(this))) + */ + public BooleanMatrix visit(BinaryExpression binExpr) { + BooleanMatrix ret = lookup(binExpr); + if (ret!=null) return ret; + + final BooleanMatrix left = binExpr.left().accept(this); + final BooleanMatrix right = binExpr.right().accept(this); + final ExprOperator op = binExpr.op(); + + switch(op) { + case UNION : ret = left.or(right); break; + case INTERSECTION : ret = left.and(right); break; + case DIFFERENCE : ret = left.difference(right); break; + case OVERRIDE : ret = left.override(right); break; + case JOIN : ret = left.dot(right); break; + case PRODUCT : ret = left.cross(right); break; + default : + throw new IllegalArgumentException("Unknown operator: " + op); + } + + return cache(binExpr, ret); + } + + /** + * Calls lookup(expr) and returns the cached value, if any. + * If a translation has not been cached, translates the expression, + * calls cache(...) on it and returns it. + * @return let t = lookup(expr) | some t => t, + * let op = (expr.op).(UNION->or + INTERSECTION->and + DIFFERENCE->difference + OVERRIDE->override + JOIN->dot + PRODUCT->cross) | + * cache(expr, op(expr.left.accept(this), expr.right.accept(this))) + */ + public BooleanMatrix visit(NaryExpression expr) { + BooleanMatrix ret = lookup(expr); + if (ret!=null) return ret; + + final ExprOperator op = expr.op(); + final BooleanMatrix first = expr.child(0).accept(this); + final BooleanMatrix[] rest = new BooleanMatrix[expr.size()-1]; + for(int i = 0; i < rest.length; i++) { rest[i] = expr.child(i+1).accept(this); } + + switch(op) { + case UNION : ret = first.or(rest); break; + case INTERSECTION : ret = first.and(rest); break; + case OVERRIDE : ret = first.override(rest); break; + case PRODUCT : ret = first.cross(rest); break; + default : + throw new IllegalArgumentException("Unknown associative operator: " + op); + } + + return cache(expr, ret); + } + + /** + * Calls lookup(unaryExpr) and returns the cached value, if any. + * If a translation has not been cached, translates the expression, + * calls cache(...) on it and returns it. + * @return let t = lookup(unaryExpr) | some t => t, + * let op = (unaryExpr.op).(TRANSPOSE->transpose + CLOSURE->closure + REFLEXIVE_CLOSURE->(lambda(m)(m.closure().or(iden))) | + * cache(unaryExpr, op(unaryExpr.child)) + */ + public final BooleanMatrix visit(UnaryExpression unaryExpr) { + BooleanMatrix ret = lookup(unaryExpr); + if (ret!=null) return ret; + + final BooleanMatrix child = unaryExpr.expression().accept(this); + final ExprOperator op = unaryExpr.op(); + + switch(op) { + case TRANSPOSE : ret = child.transpose(); break; + case CLOSURE : ret = child.closure(); break; + case REFLEXIVE_CLOSURE : ret = child.closure().or(visit((ConstantExpression)Expression.IDEN)); break; + default : + throw new IllegalArgumentException("Unknown operator: " + op); + } + return cache(unaryExpr,ret); + } + + /** + * Translates the given comprehension as follows + * (where A_0...A_|A| stand for boolean variables that represent the + * tuples of the expression A, etc.): + * let comprehension = "{ a: A, b: B, ..., x: X | F(a, b, ..., x) }" | + * { a: A, b: B, ..., x: X | a in A && b in B && ... && x in X && F(a, b, ..., x) }. + * @param decls the declarations comprehension + * @param param formula the body of the comprehension + * @param currentDecl currently processed declaration; should be 0 initially + * @param declConstraints the constraints implied by the declarations; should be Boolean.TRUE intially + * @param partialIndex partial index into the provided matrix; should be 0 initially + * @param matrix boolean matrix that will retain the final results; should be an empty matrix of dimensions universe.size^decls.length initially + * @ensures the given matrix contains the translation of the comprehension "{ decls | formula }" + */ + private final void comprehension(Decls decls, Formula formula, int currentDecl, + BooleanValue declConstraints, int partialIndex, BooleanMatrix matrix) { + final BooleanFactory factory = interpreter.factory(); + + if (currentDecl==decls.size()) { + //TODO: what about this and overflow??? + matrix.set(partialIndex, factory.and(declConstraints, formula.accept(this))); + return; + } + + final Decl decl = decls.get(currentDecl); + final BooleanMatrix declTransl = visit(decl); + final int position = (int)StrictMath.pow(interpreter.universe().size(), decls.size()-currentDecl-1); + final BooleanMatrix groundValue = factory.matrix(declTransl.dimensions()); + env = env.extend(decl.variable(), decl.expression(), groundValue); + for(IndexedEntry entry : declTransl) { + groundValue.set(entry.index(), BooleanConstant.TRUE); + comprehension(decls, formula, currentDecl+1, factory.and(entry.value(), declConstraints), + partialIndex + entry.index()*position, matrix); + groundValue.set(entry.index(), BooleanConstant.FALSE); + } + env = env.parent(); + } + + /** + * Calls lookup(cexpr) and returns the cached value, if any. + * If a translation has not been cached, translates the expression, + * calls cache(...) on it and returns it. + * @return let t = lookup(cexpr) | some t => t, + * cache(cexpr, translate(cexpr)) + */ + public BooleanMatrix visit(Comprehension cexpr) { + BooleanMatrix ret = lookup(cexpr); + if (ret!=null) return ret; + + ret = interpreter.factory().matrix(Dimensions.square(interpreter.universe().size(), cexpr.decls().size())); + comprehension(cexpr.decls(), cexpr.formula(), 0, BooleanConstant.TRUE, 0, ret); + + return cache(cexpr,ret); + } + + /** + * Calls lookup(ifExpr) and returns the cached value, if any. + * If a translation has not been cached, translates the expression, + * calls cache(...) on it and returns it. + * @return let t = lookup(ifExpr) | some t => t, + * cache(ifExpr, ifExpr.condition.accept(this).choice(ifExpr.then.accept(this), ifExpr.else.accept(this))) + */ + public BooleanMatrix visit(IfExpression ifExpr) { + BooleanMatrix ret = lookup(ifExpr); + if (ret!=null) return ret; + + final BooleanValue condition = ifExpr.condition().accept(this); + final BooleanMatrix thenExpr = ifExpr.thenExpr().accept(this); + final BooleanMatrix elseExpr = ifExpr.elseExpr().accept(this); + ret = thenExpr.choice(condition, elseExpr); + + return cache(ifExpr,ret); + } + + /** + * Calls lookup(project) and returns the cached value, if any. + * If a translation has not been cached, translates the expression, + * calls cache(...) on it and returns it. + * @return let t = lookup(project) | some t => t, + * cache(project, project.expression.accept(this).project(translate(project.columns)) + */ + public final BooleanMatrix visit(ProjectExpression project) { + BooleanMatrix ret = lookup(project); + if (ret!=null) return ret; + + final Int[] cols = new Int[project.arity()]; + for(int i = 0, arity = project.arity(); i < arity; i++) { + cols[i] = project.column(i).accept(this); + } + + return cache(project, project.expression().accept(this).project(cols)); + } + + + /** + * @return constant = ConstantFormula.TRUE => BooleanConstant.TRUE, BooleanConstant.FALSE + */ + public final BooleanValue visit(ConstantFormula constant) { + return cache(constant, BooleanConstant.constant(constant.booleanValue())); + } + + /** + * Translates the given universally quantified formula as follows + * (where A_0...A_|A| stand for boolean variables that represent the + * tuples of the expression A, etc.): + * + * let quantFormula = "all a: A, b: B, ..., x: X | F(a, b, ..., x)" | + * (A_0 && B_0 && ... && X_0 => translate(F(A_0, B_0, ..., X_0))) && ... && + * (A_|A| && B_|B| && ... && X_|X| => translate(F(A_|A|, B_|B|, ..., X_|X|))) + * + * If the noOverflow option is specified, then the translation looks like: + * + * let quantFormula = "all a: A, b: B, ..., x: X | F(a, b, ..., x)" | + * (A_0 && B_0 && ... && X_0 => (!of(F(A_0, B_0, ..., X_0)) => translate(F(A_0, B_0, ..., X_0)))) && ... && + * (A_|A| && B_|B| && ... && X_|X| => (!of(F(A_|A|, B_|B|, ..., X_|X|)) => translate(F(A_|A|, B_|B|, ..., X_|X|)))) + * + * where of(F(A_|a|, B_|b|, ..., X_|x|)) is the portion of the overflow circuit generated by the translation of + * F(A_|a|, B_|b|, ..., X_|x|) contributed by arithmetic operations over only the integer variables of this quantifier + * + * @param decls formula declarations + * @param formula the formula body + * @param currentDecl currently processed declaration; should be 0 initially + * @param declConstraints the constraints implied by the declarations; should be Boolean.FALSE initially + * @param acc the accumulator that contains the top level conjunction; should be an empty AND accumulator initially + * @ensures the given accumulator contains the translation of the formula "all decls | formula" + */ + private void all(Decls decls, Formula formula, int currentDecl, BooleanValue declConstraints, BooleanAccumulator acc) { + if (acc.isShortCircuited()) return; + final BooleanFactory factory = interpreter.factory(); + + if (decls.size()==currentDecl) { + BooleanValue formulaCircuit = formula.accept(this); + BooleanValue finalCircuit = factory.or(declConstraints, formulaCircuit); + acc.add(finalCircuit); + return; + } + + final Decl decl = decls.get(currentDecl); + final BooleanMatrix declTransl = visit(decl); + final BooleanMatrix groundValue = factory.matrix(declTransl.dimensions()); + env = env.extend(decl.variable(), decl.expression(), groundValue, Quantifier.ALL); + for(IndexedEntry entry : declTransl) { + groundValue.set(entry.index(), BooleanConstant.TRUE); + all(decls, formula, currentDecl+1, factory.or(factory.not(entry.value()), declConstraints), acc); + groundValue.set(entry.index(), BooleanConstant.FALSE); + } + env = env.parent(); + } + + /** + * Translates the given existentially quantified formula as follows + * (where A_0...A_|A| stand for boolean variables that represent the + * tuples of the expression A, etc.): + * + * let quantFormula = "some a: A, b: B, ..., x: X | F(a, b, ..., x)" | + * (A_0 && B_0 && ... && X_0 && translate(F(A_0, B_0, ..., X_0))) || ... || + * (A_|A| && B_|B| && ... && X_|X| && translate(F(A_|A|, B_|B|, ..., X_|X|)) + * + * If the noOverflow option is specified, then the translation looks like: + * + * let quantFormula = "some a: A, b: B, ..., x: X | F(a, b, ..., x)" | + * (A_0 && B_0 && ... && X_0 && !of(F(A_0, B_0, ..., X_0)) && translate(F(A_0, B_0, ..., X_0))) || ... || + * (A_|A| && B_|B| && ... && X_|X| && !of(F(A_|A|, B_|B|, ..., X_|X|)) && translate(F(A_|A|, B_|B|, ..., X_|X|)) + * + * where of(F(A_|a|, B_|b|, ..., X_|x|)) is the portion of the overflow circuit generated by the translation of + * F(A_|a|, B_|b|, ..., X_|x|) contributed by arithmetic operations over only the integer variables of this quantifier + * + * @param decls formula declarations + * @param formula the formula body + * @param currentDecl currently processed declaration; should be 0 initially + * @param declConstraints the constraints implied by the declarations; should be Boolean.TRUE intially + * @param acc the accumulator that contains the top level conjunction; should be an empty OR accumulator initially + * @ensures the given accumulator contains the translation of the formula "some decls | formula" + */ + private void some(Decls decls, Formula formula, int currentDecl, BooleanValue declConstraints, BooleanAccumulator acc) { + if (acc.isShortCircuited()) return; + final BooleanFactory factory = interpreter.factory(); + + if (decls.size()==currentDecl) { + BooleanValue formulaCircuit = formula.accept(this); + BooleanValue finalCircuit = factory.and(declConstraints, formulaCircuit); + acc.add(finalCircuit); + return; + } + + final Decl decl = decls.get(currentDecl); + final BooleanMatrix declTransl = visit(decl); + final BooleanMatrix groundValue = factory.matrix(declTransl.dimensions()); + env = env.extend(decl.variable(), decl.expression(), groundValue, Quantifier.SOME); + for(IndexedEntry entry : declTransl) { + groundValue.set(entry.index(), BooleanConstant.TRUE); + some(decls, formula, currentDecl+1, factory.and(entry.value(), declConstraints), acc); + groundValue.set(entry.index(), BooleanConstant.FALSE); + } + env = env.parent(); + } + + /** + * Calls lookup(quantFormula) and returns the cached value, if any. + * If a translation has not been cached, translates the formula, + * calls cache(...) on it and returns it. + * @return let t = lookup(quantFormula) | some t => t, + * cache(quantFormula, translate(quantFormula)) + */ + public final BooleanValue visit(QuantifiedFormula quantFormula) { + BooleanValue ret = lookup(quantFormula); + if (ret!=null) return ret; + + final Quantifier quantifier = quantFormula.quantifier(); + switch(quantifier) { + case ALL : + final BooleanAccumulator and = BooleanAccumulator.treeGate(Operator.AND); + all(quantFormula.decls(), quantFormula.formula(), 0, BooleanConstant.FALSE, and); + ret = interpreter.factory().accumulate(and); + break; + case SOME : + final BooleanAccumulator or = BooleanAccumulator.treeGate(Operator.OR); + some(quantFormula.decls(), quantFormula.formula(), 0, BooleanConstant.TRUE, or); + ret = interpreter.factory().accumulate(or); + break; + default : + throw new IllegalArgumentException("Unknown quantifier: " + quantifier); + } + return cache(quantFormula,ret); + } + + /** + * Calls lookup(formula) and returns the cached value, if any. + * If a translation has not been cached, translates the formula, + * calls cache(...) on it and returns it. + * @return let t = lookup(formula) | some t => t, + * cache(formula, formula.op(formula.left.accept(this), formula.right.accept(this)) + */ + public final BooleanValue visit(NaryFormula formula) { + final BooleanValue ret = lookup(formula); + if (ret!=null) return ret; + + final FormulaOperator op = formula.op(); + final Operator.Nary boolOp; + + switch(op) { + case AND : boolOp = Operator.AND; break; + case OR : boolOp = Operator.OR; break; + default : throw new IllegalArgumentException("Unknown nary operator: " + op); + } + + final BooleanAccumulator acc = BooleanAccumulator.treeGate(boolOp); + final BooleanValue shortCircuit = boolOp.shortCircuit(); + for(Formula child : formula) { + if (acc.add(child.accept(this))==shortCircuit) + break; + } + + return cache(formula, interpreter.factory().accumulate(acc)); + } + + + + /** + * Calls lookup(binFormula) and returns the cached value, if any. + * If a translation has not been cached, translates the formula, + * calls cache(...) on it and returns it. + * @return let t = lookup(binFormula) | some t => t, + * cache(binFormula, binFormula.op(binFormula.left.accept(this), binFormula.right.accept(this)) + */ + public final BooleanValue visit(BinaryFormula binFormula) { + BooleanValue ret = lookup(binFormula); + if (ret!=null) return ret; + + final BooleanValue left = binFormula.left().accept(this); + final BooleanValue right = binFormula.right().accept(this); + final FormulaOperator op = binFormula.op(); + final BooleanFactory f = interpreter.factory(); + + switch(op) { + case AND : ret = f.and(left, right); break; + case OR : ret = f.or(left, right); break; + case IMPLIES : ret = f.implies(left, right); break; + case IFF : ret = f.iff(left, right); break; + default : + throw new IllegalArgumentException("Unknown operator: " + op); + } + return cache(binFormula, ret); + } + + /** + * Calls lookup(not) and returns the cached value, if any. + * If a translation has not been cached, translates the formula, + * calls cache(...) on it and returns it. + * @return let t = lookup(not) | some t => t, + * cache(not, !not.formula.accept(this)) + */ + public final BooleanValue visit(NotFormula not) { + BooleanValue ret = lookup(not); + if (ret != null) + return ret; + env.negate(); + ret = cache(not, interpreter.factory().not(not.formula().accept(this))); + env.negate(); + return ret; + } + + /** + * Calls lookup(compFormula) and returns the cached value, if any. + * If a translation has not been cached, translates the formula, + * calls cache(...) on it and returns it. + * @return let t = lookup(compFormula) | some t => t, + * let op = (binExpr.op).(SUBSET->subset + EQUALS->eq) | + * cache(compFormula, op(compFormula.left.accept(this), compFormula.right.accept(this))) + */ + public final BooleanValue visit(ComparisonFormula compFormula) { + BooleanValue ret = lookup(compFormula); + if (ret!=null) return ret; + + final BooleanMatrix left = compFormula.left().accept(this); + final BooleanMatrix right = compFormula.right().accept(this); + final ExprCompOperator op = compFormula.op(); + + switch(op) { + case SUBSET : ret = left.subset(right, env); break; + case EQUALS : ret = left.eq(right, env); break; + default : + throw new IllegalArgumentException("Unknown operator: " + compFormula.op()); + } + return cache(compFormula,ret); + } + + /** + * Calls lookup(multFormula) and returns the cached value, if any. + * If a translation has not been cached, translates the formula, + * calls cache(...) on it and returns it. + * @return let t = lookup(multFormula) | some t => t, + * let op = (multFormula.mult).(NO->none + SOME->some + ONE->one + LONE->lone) | + * cache(multFormula, op(multFormula.expression.accept(this))) + */ + public final BooleanValue visit(MultiplicityFormula multFormula) { + BooleanValue ret = lookup(multFormula); + if (ret!=null) return ret; + + final BooleanMatrix child = multFormula.expression().accept(this); + final Multiplicity mult = multFormula.multiplicity(); + + switch(mult) { + case NO : ret = child.none(env); break; + case SOME : ret = child.some(env); break; + case ONE : ret = child.one(env); break; + case LONE : ret = child.lone(env); break; + default : + throw new IllegalArgumentException("Unknown multiplicity: " + mult); + } + + return cache(multFormula, ret); + } + + /** + * Calls lookup(pred) and returns the cached value, if any. + * If a translation has not been cached, translates the expression, + * calls cache(...) on it and returns it. + * @return let t = lookup(pred) | some t => t, + * cache(pred, pred.toConstraints().accept(this)) + */ + public final BooleanValue visit(RelationPredicate pred) { + BooleanValue ret = lookup(pred); + return ret != null ? ret : cache(pred, pred.toConstraints().accept(this)); + } + + /** + * Calls lookup(castExpr) and returns the cached value, if any. + * If a translation has not been cached, translates the expression, + * calls cache(...) on it and returns it. + * @return let t = lookup(castExpr) | some t => t, + * cache(castExpr, translate(castExpr)) + */ + public BooleanMatrix visit(IntToExprCast castExpr) { + BooleanMatrix ret = lookup(castExpr); + if (ret!=null) return ret; + + final Int child = castExpr.intExpr().accept(this); + final BooleanFactory factory = interpreter.factory(); + final IntSet ints = interpreter.ints(); + + ret = factory.matrix(Dimensions.square(interpreter.universe().size(), 1)); + + switch(castExpr.op()) { + case INTCAST : + for(IntIterator iter = ints.iterator(); iter.hasNext(); ) { + int i = iter.next(); + int atomIndex = interpreter.interpret(i); + ret.set(atomIndex, factory.or(ret.get(atomIndex), child.eq(factory.integer(i)))); + } + ret.setDefCond(child.defCond()); + break; + case BITSETCAST : + final List twosComplement = child.twosComplementBits(); + final int msb = twosComplement.size()-1; + // handle all bits but the sign bit + for(int i = 0; i < msb; i++) { + int pow2 = 1< t, + * cache(intExpr, intExpr.condition.accept(this).choice(intExpr.then.accept(this), intExpr.else.accept(this))) + */ + public final Int visit(IfIntExpression intExpr) { + Int ret = lookup(intExpr); + if (ret!=null) return ret; + + final BooleanValue condition = intExpr.condition().accept(this); + final Int thenExpr = intExpr.thenExpr().accept(this); + final Int elseExpr = intExpr.elseExpr().accept(this); + ret = thenExpr.choice(condition, elseExpr); + return cache(intExpr, ret); + } + + /** + * Returns an Int that represents the sum of all the integers that + * correspond to non-FALSE entries in the given matrix. + * @param iter an iterator over all the bound integers. Initial should be this.manager.ints().iterator(). + * @param lo the first element of the current partial sum. Initial should be 0. + * @param hi the last element of the current partial sum. Initial should be size-1, where size is the total + * number of elements returned by the iterator. + * @return an Int that represents the sum of all the integers that + * correspond to non-FALSE entries in the given matrix. + */ + private final Int sum(BooleanMatrix m, IntIterator iter, int low, int high) { + if (low > high) + return interpreter.factory().integer(0); + else if (low==high) { + int i = iter.next(); + return interpreter.factory().integer(i, m.get(interpreter.interpret(i))); + } else { + final int mid = (low + high) / 2; + final Int lsum = sum(m, iter, low, mid); + final Int hsum = sum(m, iter, mid+1, high); + return lsum.plus(hsum); + } + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If a translation has not been cached, translates the expression, + * calls cache(...) on it and returns it. + * @return let t = lookup(intExpr) | some t => t, + * cache(intExpr, translate(intExpr)) + */ + public final Int visit(ExprToIntCast intExpr) { + Int ret = lookup(intExpr); + if (ret!=null) return ret; + vars = vars.createNested(); + BooleanMatrix expr = intExpr.expression().accept(this); + switch(intExpr.op()) { + case CARDINALITY : + ret = expr.cardinality(); break; + case SUM : + final IntSet ints = interpreter.ints(); + ret = sum(expr, ints.iterator(), 0, ints.size()-1); break; + default: + throw new IllegalArgumentException("unknown operator: " + intExpr.op()); + } + for (Variable v : vars) ret.defCond().addVar(v); + vars = vars.parent(); + return cache(intExpr, ret); + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If a translation has not been cached, translates the expression, + * calls cache(...) on it and returns it. + * @return let t = lookup(intExpr) | some t => t, + * cache(intExpr, intExpr.left.accept(this) intExpr.op intExpr.right.accept(this)) + */ + public final Int visit(BinaryIntExpression intExpr) { + Int ret = lookup(intExpr); + if (ret!=null) return ret; + final Int left = intExpr.left().accept(this); + final Int right = intExpr.right().accept(this); + switch(intExpr.op()) { + case PLUS : ret = left.plus(right); break; + case MINUS : ret = left.minus(right); break; + case MULTIPLY : ret = left.multiply(right); break; + case DIVIDE : ret = left.divide(right); break; + case MODULO : ret = left.modulo(right); break; + case AND : ret = left.and(right); break; + case OR : ret = left.or(right); break; + case XOR : ret = left.xor(right); break; + case SHL : ret = left.shl(right); break; + case SHR : ret = left.shr(right); break; + case SHA : ret = left.sha(right); break; + default : + throw new IllegalArgumentException("Unknown operator: " + intExpr.op()); + } + return cache(intExpr, ret); + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If a translation has not been cached, translates the expression, + * calls cache(...) on it and returns it. + * @return let t = lookup(intExpr) | some t => t, + * cache(intExpr, intExpr.left.accept(this) intExpr.op intExpr.right.accept(this)) + */ + public final Int visit(NaryIntExpression intExpr) { + Int ret = lookup(intExpr); + if (ret!=null) return ret; + final Int first = intExpr.child(0).accept(this); + final Int[] rest = new Int[intExpr.size()-1]; + for(int i = 0; i < rest.length; i++) { rest[i] = intExpr.child(i+1).accept(this); } + switch(intExpr.op()) { + case PLUS : ret = first.plus(rest); break; + case MULTIPLY : ret = first.multiply(rest); break; + case AND : ret = first.and(rest); break; + case OR : ret = first.or(rest); break; + default : + throw new IllegalArgumentException("Unknown nary operator: " + intExpr.op()); + } + return cache(intExpr, ret); + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If a translation has not been cached, translates the expression, + * calls cache(...) on it and returns it. + * @return let t = lookup(intExpr) | some t => t, + * cache(intExpr, intExpr.op(intExpr.expression.accept(this))) + */ + public final Int visit(UnaryIntExpression intExpr) { + Int ret = lookup(intExpr); + if (ret!=null) return ret; + final Int child = intExpr.intExpr().accept(this); + switch(intExpr.op()) { + case NEG : ret = child.negate(); break; + case NOT : ret = child.not(); break; + case ABS : ret = child.abs(); break; + case SGN : ret = child.sgn(); break; + default : + throw new IllegalArgumentException("Unknown operator: " + intExpr.op()); + } + return cache(intExpr, ret); + } + + /** + * Translates the given sum expression as follows + * (where A_0...A_|A| stand for boolean variables that represent the + * tuples of the expression A, etc.): + * let sum = "sum a: A, b: B, ..., x: X | IE(a, b, ..., x) " | + * sum a: A, b: B, ..., x: X | if (a in A && b in B && ... && x in X) then IE(a, b, ..., x) else 0 }. + * @param decls intexpr declarations + * @param formula the formula body + * @param currentDecl currently processed declaration; should be 0 initially + * @param declConstraints the constraints implied by the declarations; should be Boolean.TRUE intially + * @param values integer values computed so far + */ + private final void sum(Decls decls, IntExpression expr, int currentDecl, BooleanValue declConstraints, + List values) { + final BooleanFactory factory = interpreter.factory(); + if (decls.size()==currentDecl) { + Int intExpr = expr.accept(this); + Int newInt = intExpr.choice(declConstraints, factory.integer(0)); + values.add(newInt); + return; + } + + final Decl decl = decls.get(currentDecl); + final BooleanMatrix declTransl = visit(decl); + final BooleanMatrix groundValue = factory.matrix(declTransl.dimensions()); + env = env.extend(decl.variable(), decl.expression(), groundValue); + for(IndexedEntry entry : declTransl) { + groundValue.set(entry.index(), BooleanConstant.TRUE); + sum(decls, expr, currentDecl+1, factory.and(entry.value(), declConstraints), values); + groundValue.set(entry.index(), BooleanConstant.FALSE); + } + env = env.parent(); + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If a translation has not been cached, translates the expression, + * calls cache(...) on it and returns it. + * @return let t = lookup(intExpr) | some t => t, + * cache(intExpr, translate(intExpr)) + */ + public final Int visit(SumExpression intExpr) { + final Int ret = lookup(intExpr); + if (ret!=null) return ret; + final List values = new ArrayList(); + sum(intExpr.decls(), intExpr.intExpr(), 0, BooleanConstant.TRUE, values); + for(int sums = values.size(); sums > 1; sums -= sums/2) { + final int max = sums-1; + for(int i = 0; i < max; i += 2) { + values.set(i/2, values.get(i).plus(values.get(i+1))); + } + if (max%2==0) { // even max => odd number of entries + values.set(max/2, values.get(max)); + } + } + if (values.isEmpty()) { + return cache(intExpr, interpreter.factory().integer(0)); + } else { + Int sumValue = values.get(0); + return cache(intExpr, sumValue); + } + } + + /** + * Calls lookup(intComp) and returns the cached value, if any. + * If a translation has not been cached, translates the formula, + * calls cache(...) on it and returns it. + * + * This is the only place where Ints are turned into + * formulas, so that's where the overflow circuits of individual + * Ints are built into the translated formula. + * + * @return let t = lookup(intComp) | some t => t, + * cache(intComp, intComp.left.accept(this) intComp.op intComp.right.accept(this)) + */ + public final BooleanValue visit(IntComparisonFormula intComp) { + BooleanValue ret = lookup(intComp); + if (ret!=null) return ret; + final Int left = intComp.left().accept(this); + final Int right = intComp.right().accept(this); + switch(intComp.op()) { + case EQ : ret = left.eq(right, env); break; + case NEQ : ret = left.neq(right, env); break; + case LT : ret = left.lt(right, env); break; + case LTE : ret = left.lte(right, env); break; + case GT : ret = left.gt(right, env); break; + case GTE : ret = left.gte(right, env); break; + default: + throw new IllegalArgumentException("Unknown operator: " + intComp.op()); + } + return cache(intComp, ret); + } +} + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/FileLogger.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/FileLogger.java new file mode 100644 index 00000000..c592443d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/FileLogger.java @@ -0,0 +1,337 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; + +import kodkod.ast.ConstantFormula; +import kodkod.ast.Expression; +import kodkod.ast.Formula; +import kodkod.ast.Node; +import kodkod.ast.Variable; +import kodkod.engine.Solver; +import kodkod.engine.bool.BooleanMatrix; +import kodkod.engine.bool.BooleanValue; +import kodkod.instance.Bounds; +import kodkod.instance.TupleFactory; +import kodkod.instance.TupleSet; +import kodkod.util.collections.Containers; +import kodkod.util.collections.FixedMap; +import kodkod.util.ints.Ints; +import kodkod.util.nodes.AnnotatedNode; +import kodkod.util.nodes.Nodes; + +/** + * A file-based translation logger that logs translation events + * to a temporary file. + * @specfield originalFormula: Formula // the {@linkplain Solver#solve(Formula, kodkod.instance.Bounds) original} formula, provided by the user + * @specfield originalBounds: Bounds // the {@linkplain Solver#solve(Formula, kodkod.instance.Bounds) original} bounds, provided by the user + * @specfield formula: Formula // desugaring of this.formula that was translated + * @specfield bounds: Bounds // translation bounds + * @specfield records: (formula.*children & Formula) -> BooleanValue -> Environment + * @invariant Solver.solve(formula, bounds).instance() == null iff Solver.solve(originalFormula, originalBounds).instance() == null + * @author Emina Torlak + */ +final class FileLogger extends TranslationLogger { + + private final FixedMap logMap; + private final AnnotatedNode annotated; + private final File file; + private DataOutputStream out; + private final Bounds bounds; + /** + * Constructs a new file logger from the given annotated formula. + * @ensures this.formula' = annotated.node + * @ensures this.originalFormula' = annotated.source[annotated.node] + * @ensures this.bounds' = bounds + * @ensures this.log().roots() = Nodes.conjuncts(annotated) + * @ensures no this.records' + */ + FileLogger(final AnnotatedNode annotated, Bounds bounds) { + this.annotated = annotated; + try { + this.file = File.createTempFile("kodkod", ".log"); + this.out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file))); + } catch (IOException e1) { + throw new RuntimeException(e1); + } + + final Map> freeVarMap = freeVars(annotated); + final Variable[] empty = new Variable[0]; + + this.logMap = new FixedMap(freeVarMap.keySet()); + + for(Map.Entry e : logMap.entrySet()) { + Set vars = freeVarMap.get(e.getKey()); + int size = vars.size(); + if (size==0) { + e.setValue(empty); + } else { + e.setValue(Containers.identitySort(vars.toArray(new Variable[size]))); + } + } + this.bounds = bounds.unmodifiableView(); + } + + /** + * Returns a map from all formulas in the given annotated node to their free variables. + * @return a map from all formulas in the given annotated node to their free variables. + */ + @SuppressWarnings("unchecked") + private static Map> freeVars(final AnnotatedNode annotated) { + final Map> freeVarMap = new IdentityHashMap>(); + final FreeVariableCollector collector = new FreeVariableCollector(annotated.sharedNodes()) { + protected Set cache(Node node, Set freeVars) { + if (node instanceof Formula) { + freeVarMap.put((Formula)node, freeVars); + } + return super.cache(node, freeVars); + } + public Set visit(ConstantFormula constant) { + return cache(constant, Collections.EMPTY_SET); + } + + }; + annotated.node().accept(collector); + return freeVarMap; + } + + /** + * @see kodkod.engine.fol2sat.TranslationLogger#close() + */ + @Override + void close() { + try { + if (out!=null) { out.close(); } + } catch (IOException e1) { + /* unused */ + } finally { out = null; } + } + + /** + * Records the translation of the source of the + * given transformed formula to the given boolean value + * in the specified environment. + * @requires some this.transforms.f + * @ensures this.records' = this.records + this.transforms.f -> translation -> freeVariables(f)<:env + * @throws IllegalArgumentException - no this.transforms.f + * @throws IllegalStateException - this log has been closed + */ + @Override + void log(Formula f, BooleanValue v, Environment env) { + if (out==null) throw new IllegalStateException(); + + final int index = logMap.indexOf(f); + if (index < 0) throw new IllegalArgumentException(); + + final Variable[] vars = logMap.get(index); + + try { + out.writeInt(index); + out.writeInt(v.label()); + for(Variable var : vars) { + out.writeInt(env.lookup(var).denseIndices().min()); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * @see kodkod.engine.fol2sat.TranslationLogger#log() + */ + @Override + TranslationLog log() { + return new FileLog(annotated, logMap, file, bounds); + } + + /** + * @see java.lang.Object#finalize() + */ + protected final void finalize() { + close(); + } + + /** + * A file-based translation log, written by a FileLogger. + * @author Emina Torlak + */ + private static final class FileLog extends TranslationLog { + private final Set roots; + private final Node[] original; + private final Formula[] translated; + private final Variable[][] freeVars; + private final File file; + private final Bounds bounds; + + /** + * Constructs a new file log for the sources of the given annotated formula, + * using the provided fixed map, file, and tuplefactory. + * @requires all f: annotated.node.*children & Formula | logMap.get(f) = freeVariables(f) + * @requires the file was written by a FileLogger using the given map + */ + FileLog(AnnotatedNode annotated, FixedMap logMap, File file, Bounds bounds) { + this.file = file; + this.bounds = bounds; + this.roots = Nodes.conjuncts(annotated.node()); + + final int size = logMap.entrySet().size(); + this.original = new Node[size]; + this.translated = new Formula[size]; + this.freeVars = new Variable[size][]; + int index = 0; + for(Map.Entry e : logMap.entrySet()) { + translated[index] = e.getKey(); + original[index] = annotated.sourceOf(e.getKey()); + freeVars[index] = e.getValue(); + index++; + } + } + + /** + * Deletes the log file. + * @see java.lang.Object#finalize() + */ + protected final void finalize() { + file.delete(); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.fol2sat.TranslationLog#roots() + */ + public Set roots() { return roots; } + + /** + * {@inheritDoc} + * @see kodkod.engine.fol2sat.TranslationLog#bounds() + */ + public Bounds bounds() { return bounds; } + + /** + * {@inheritDoc} + * @see kodkod.engine.fol2sat.TranslationLog#replay(kodkod.engine.fol2sat.RecordFilter) + */ + public Iterator replay(final RecordFilter filter) { + try { + return new Iterator() { + final TupleFactory factory = bounds.universe().factory(); + final DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(file))); + final MutableRecord current = new MutableRecord(), next = new MutableRecord(); + long remaining = file.length(); + + public boolean hasNext() { + while(remaining > 0 && next.node == null) { + try { + final long indexLiteral = in.readLong(); + final int literal = (int) (indexLiteral); + final int index = (int) (indexLiteral>>>32); + final Variable[] freeVars = FileLog.this.freeVars[index]; + final Map env; + if (freeVars.length==0) { + env = Collections.emptyMap(); + } else { + env = new FixedMap(freeVars); + for(int i = 0; i < freeVars.length; i++) { + env.put(freeVars[i], factory.setOf(1, Ints.singleton(in.readInt()))); + } + } + if (filter.accept(original[index], translated[index], literal, env)) { + next.setAll(original[index], translated[index], literal, env); + } + remaining -= (8 + (freeVars.length << 2)); + + } catch (IOException e) { + throw new RuntimeException(e); + } + } + if (next.node==null) { + try { + in.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return false; + } else { + return true; + } + } + + public TranslationRecord next() { + if (!hasNext()) throw new NoSuchElementException(); + return current.setAll(next); + } + + public void remove() { throw new UnsupportedOperationException(); } + + protected final void finalize() { + try { in.close(); } catch (IOException e) { /* unused */ } + } + }; + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } + } + + /** + * A mutable translation record. + * @author Emina Torlak + */ + private static final class MutableRecord extends TranslationRecord { + Node node = null; + Formula translated = null; + int literal = 0; + Map env = null; + + public Map env() { return env; } + public int literal() { return literal; } + public Node node() { return node; } + void setAll(Node node, Formula translated, int literal, Map env) { + this.node = node; + this.translated = translated; + this.literal = literal; + this.env = env; + } + TranslationRecord setAll(MutableRecord other) { + setAll(other.node, other.translated, other.literal, other.env); + other.setAll(null,null,0,null); + return this; + } + public Formula translated() { return translated;} + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/FormulaFlattener.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/FormulaFlattener.java new file mode 100644 index 00000000..9bdab9b1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/FormulaFlattener.java @@ -0,0 +1,275 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import static kodkod.ast.operator.FormulaOperator.AND; +import static kodkod.ast.operator.FormulaOperator.IFF; +import static kodkod.ast.operator.FormulaOperator.IMPLIES; +import static kodkod.ast.operator.FormulaOperator.OR; +import static kodkod.ast.operator.Quantifier.ALL; +import static kodkod.ast.operator.Quantifier.SOME; + +import java.util.ArrayList; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import kodkod.ast.BinaryFormula; +import kodkod.ast.ComparisonFormula; +import kodkod.ast.ConstantFormula; +import kodkod.ast.Decls; +import kodkod.ast.Formula; +import kodkod.ast.IntComparisonFormula; +import kodkod.ast.MultiplicityFormula; +import kodkod.ast.NaryFormula; +import kodkod.ast.Node; +import kodkod.ast.NotFormula; +import kodkod.ast.QuantifiedFormula; +import kodkod.ast.RelationPredicate; +import kodkod.ast.operator.FormulaOperator; +import kodkod.ast.operator.Quantifier; +import kodkod.ast.visitor.AbstractVoidVisitor; +import kodkod.util.nodes.AnnotatedNode; + +/** + * Flattens a given formula by putting into negation normal form and, optionally, + * by breaking up universally quantifier formulas whenever possible. + * + * @author Emina Torlak + */ +final class FormulaFlattener extends AbstractVoidVisitor { + + /** + * Flattens the given formula into a set of conjuncts + * by pushing negations through quantifier-free formulas, if breakupQuantifiers is false. + * Otherwise, pushes the negations through all formulas, breaking up universal quantifiers + * whenever possible. The source map of the returned annotated node reflects the source relationships + * from the descendants of the returned formula to the sources of the corresponding descendants of annotated.node. + * @return a map that binds each flattened conjuncts to the corresponding + * subformula of annotated.node + */ + public static AnnotatedNode flatten(AnnotatedNode annotated, boolean breakupQuantifiers) { + final FormulaFlattener flat = new FormulaFlattener(annotated.sharedNodes(), breakupQuantifiers); + annotated.node().accept(flat); + final List roots = new ArrayList(flat.conjuncts.size()); + roots.addAll(flat.conjuncts.keySet()); + for(Iterator> itr = flat.conjuncts.entrySet().iterator(); itr.hasNext(); ) { + final Map.Entry entry = itr.next(); + final Node source = annotated.sourceOf(entry.getValue()); + if (entry.getKey()==source) { itr.remove(); } + else { entry.setValue(source); } + } + return AnnotatedNode.annotate(Formula.and(roots), flat.conjuncts); + } + + + + private Map conjuncts; + private final Map visited; + private final Set shared; + private boolean negated; + private final boolean breakupQuantifiers; + /** + * Constructs a flattener for a formula in which the given nodes are shared. + */ + private FormulaFlattener(Set shared, boolean breakupQuantifiers) { + this.conjuncts = new LinkedHashMap(); + this.shared = shared; + this.visited = new IdentityHashMap(); + this.negated = false; + this.breakupQuantifiers = breakupQuantifiers; + } + + /** + * Returns the result of applying this visitor to the given annotated formula. + * @return the result of applying this visitor to the given annotated formula. + */ + final AnnotatedNode apply(AnnotatedNode annotated) { + annotated.node().accept(this); + final List roots = new ArrayList(conjuncts.size()); + roots.addAll(conjuncts.keySet()); + for(Iterator> itr = conjuncts.entrySet().iterator(); itr.hasNext(); ) { + final Map.Entry entry = itr.next(); + final Node source = annotated.sourceOf(entry.getValue()); + if (entry.getKey()==source) { itr.remove(); } + else { entry.setValue(source); } + } + return AnnotatedNode.annotate(Formula.and(roots), conjuncts); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.visitor.AbstractVoidVisitor#visited(kodkod.ast.Node) + */ + @Override + protected boolean visited(Node n) { + if (shared.contains(n)) { + if (visited.containsKey(n)) { + final Boolean val = visited.get(n); + if (val==null || val.booleanValue()==negated) { + return true; + } else { + visited.put(n, null); + return false; + } + } else { + visited.put(n, Boolean.valueOf(negated)); + return false; + } + } + return false; + } + + + + /** + * Calls nf.formula.accept(this) after flipping the negation flag. + * @see kodkod.ast.visitor.AbstractVoidVisitor#visit(kodkod.ast.NotFormula) + */ + public final void visit(NotFormula nf) { + if (visited(nf)) return; + + final Map oldConjuncts = conjuncts; + conjuncts = new LinkedHashMap(); + negated = !negated; + nf.formula().accept(this); + negated = !negated; + if (conjuncts.size()>1) { // was broken down further + oldConjuncts.putAll(conjuncts); + conjuncts = oldConjuncts; + } else { // wasn't broken down further + conjuncts = oldConjuncts; + conjuncts.put(negated ? nf.formula() : nf, nf); + } + } + + /** + * Adds the given formula (or its negation, depending on the value of the negated flag) + * to this.conjuncts. + */ + private final void addConjunct(Formula conjunct) { + conjuncts.put(negated ? conjunct.not() : conjunct, conjunct); + } + + /** + * Visits the formula's children with appropriate settings + * for the negated flag if bf has not been visited before. + * @see kodkod.ast.visitor.AbstractVoidVisitor#visit(kodkod.ast.BinaryFormula) + */ + public final void visit(BinaryFormula bf) { + if (visited(bf)) return; + final FormulaOperator op = bf.op(); + if (op==IFF || (negated && op==AND) || (!negated && (op==OR || op==IMPLIES))) { // can't break down further in these cases + addConjunct(bf); + } else { // will break down further + if (negated && op==IMPLIES) { // !(a => b) = !(!a || b) = a && !b + negated = !negated; + bf.left().accept(this); + negated = !negated; + bf.right().accept(this); + } else { + bf.left().accept(this); + bf.right().accept(this); + } + } + } + + /** + * Visits the formula's children with appropriate settings + * for the negated flag if bf has not been visited before. + * @see kodkod.ast.visitor.AbstractVoidVisitor#visit(kodkod.ast.NaryFormula) + */ + public final void visit(NaryFormula nf) { + if (visited(nf)) return; + final FormulaOperator op = nf.op(); + if ((negated && op==AND) || (!negated && op==OR)) { // can't break down further in these cases + addConjunct(nf); + } else { // will break down further + for(Formula f : nf) { + f.accept(this); + } + } + } + + /** + * {@inheritDoc} + * @see kodkod.ast.visitor.AbstractVoidVisitor#visit(kodkod.ast.QuantifiedFormula) + */ + public final void visit(QuantifiedFormula qf) { + if (visited(qf)) return; + + if (breakupQuantifiers) { + + final Quantifier quant = qf.quantifier(); + + if ((!negated && quant==ALL) || (negated && quant==SOME)) { // may break down further + final Map oldConjuncts = conjuncts; + conjuncts = new LinkedHashMap(); + qf.formula().accept(this); + if (conjuncts.size()>1) { // was broken down further + final Decls decls = qf.decls(); + for(Map.Entry entry : conjuncts.entrySet()) { + oldConjuncts.put(entry.getKey().forAll(decls), entry.getValue()); + } + conjuncts = oldConjuncts; + return; + } else { // wasn't broken down further + conjuncts = oldConjuncts; + } + } // won't break down further + } + + addConjunct(qf); + + } + + /** + * Adds f (resp. f.not()) to this.conjuncts if the negated flag is false (resp. true) and + * the given node has not been visited; otherwise does nothing. + * @ensures !this.visited(f) => + * (this.conjuncts' = conjuncts + (negated => f.not() else f)) else + * (this.conjuncts' = this.conjuncts) + */ + final void visitFormula(Formula f) { + if (visited(f)) return; + addConjunct(f); + } + + /** @see #visitFormula(Formula) */ + public final void visit(ComparisonFormula cf) { visitFormula(cf); } + + /** @see #visitFormula(Formula) */ + public final void visit(IntComparisonFormula cf) { visitFormula(cf); } + + /** @see #visitFormula(Formula) */ + public final void visit(MultiplicityFormula mf) { visitFormula(mf); } + + /** @see #visitFormula(Formula) */ + public final void visit(ConstantFormula constant) { visitFormula(constant); } + + /** @see #visitFormula(Formula) */ + public final void visit(RelationPredicate pred) { visitFormula(pred); } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/FreeVariableCollector.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/FreeVariableCollector.java new file mode 100644 index 00000000..3322a485 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/FreeVariableCollector.java @@ -0,0 +1,180 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; + +import kodkod.ast.Comprehension; +import kodkod.ast.Decl; +import kodkod.ast.Decls; +import kodkod.ast.Node; +import kodkod.ast.QuantifiedFormula; +import kodkod.ast.SumExpression; +import kodkod.ast.Variable; +import kodkod.ast.visitor.AbstractCollector; +import kodkod.util.collections.ArrayStack; +import kodkod.util.collections.Stack; + +/** + * Collects free variables in a given Node. Subclasses + * can customize the collection policy by overriding the + * cache method. By default, the cache + * will contain only the free variables of the shared nodes. The + * default implementation of {@link #newSet()} ensures that + * the collected free variables will be returned in the order + * in which they were encountered during traversal. + * @specfield cached: set Node + * @specfield cache: Node -> lone Set + * @specfield varsInScope: Stack // variables currently in scope + * @author Emina Torlak + */ +abstract class FreeVariableCollector extends AbstractCollector { + /* Holds the variables that are currently in scope, with the + * variable at the top of the stack being the last declared variable. */ + protected final Stack varsInScope; + + /** + * Constructs a new collector using the given structural information. + * The given set is required to contain the syntactically shared subtrees of the + * node for which we are computing caching information. + */ + protected FreeVariableCollector(Set cached) { + super(cached); + this.varsInScope = new ArrayStack(); + } + + /** + * @see kodkod.ast.visitor.AbstractCollector#newSet() + */ + @Override + protected Set newSet() { + return new LinkedHashSet(2); + } + + /** + * Visits the given comprehension, quantified formula, or sum expression. + * The method returns a set that contains all + * the free variables in the declarations and the body, minus the variables that are + * actually bound in the declarations. + */ + @SuppressWarnings("unchecked") + private Set visit(Node creator, Decls decls, Node body) { + Set ret = lookup(creator); + if (ret!=null) return ret; + + ret = newSet(); + final Set boundVars = newSet(); + + // add the declared variables to the scoped variables stack; + // compute free vars for each decl, and the difference of the + // computed set and previously bound variables to ret + for(Decl decl : decls) { + for(Variable v : visit(decl)) { + if (!boundVars.contains(v)) + ret.add(v); + } + varsInScope.push(decl.variable()); + boundVars.add(decl.variable()); + } + + // add to ret the free variables in the body, minus the bound variables + for(Variable v: (Set) body.accept(this)) { + if (!boundVars.contains(v)) + ret.add(v); + } + + // remove the declared variables from the in-scope stack + for(int i = decls.size(); i > 0; i--) { + varsInScope.pop(); + } + + return cache(creator, ret); + } + + /** + * Returns the free variables in the given declaration. + * @return freeVars(decl.expression) + */ + public Set visit(Decl decl) { + final Set ret = lookup(decl); + return ret != null ? ret : cache(decl, decl.expression().accept(this)); + } + + /** + * Returns the singleton set containing the given variable. + * @return {variable} + */ + @Override + public Set visit(Variable variable) { + return cache(variable, Collections.singleton(variable)); + } + + /** + * Calls lookup(comprehension) and returns the cached value, if any. + * If no cached value exists, computes, caches and returns the set + * of free variables in comprehension. + * @return let x = lookup(comprehension), d = comprehension.declarations, f = comprehension.formula | + * x != null => x, + * cache(comprehension, + * (f.accept(this) - d.children.variable) + + * {v: Variable | some i: [0..d.size) | + * v in d.declarations[i].accept(this) - d.declarations[0..i).variable } ) + */ + @Override + public Set visit(Comprehension comprehension) { + return visit(comprehension, comprehension.decls(), comprehension.formula()); + } + + /** + * Calls lookup(intExpr) and returns the cached value, if any. + * If no cached value exists, computes, caches and returns the set + * of free variables in intExpr. + * @return let x = lookup(intExpr), d = intExpr.declarations, e = intExpr.intExpr | + * x != null => x, + * cache(intExpr, + * (e.accept(this) - d.children.variable) + + * {v: Variable | some i: [0..d.size) | + * v in d.declarations[i].accept(this) - d.declarations[0..i).variable } ) + */ + @Override + public Set visit(SumExpression intExpr) { + return visit(intExpr, intExpr.decls(), intExpr.intExpr()); + } + + /** + * Calls lookup(quantFormula) and returns the cached value, if any. + * If no cached value exists, computes, caches and returns the set + * of free variables in quantFormula. + * @return let x = lookup(quantFormula), d = quantFormula.declarations, f = quantFormula.formula | + * x != null => x, + * cache(quantFormula, + * (f.accept(this) - d.children.variable) + + * {v: Variable | some i: [0..d.size) | + * v in d.declarations[i].accept(this) - d.declarations[0..i).variable } ) + */ + @Override + public Set visit(QuantifiedFormula quantFormula) { + return visit(quantFormula, quantFormula.decls(), quantFormula.formula()); + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/FullNegationPropagator.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/FullNegationPropagator.java new file mode 100644 index 00000000..f340aea1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/FullNegationPropagator.java @@ -0,0 +1,360 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import static kodkod.ast.operator.FormulaOperator.AND; +import static kodkod.ast.operator.FormulaOperator.OR; + +import java.util.ArrayList; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import kodkod.ast.BinaryFormula; +import kodkod.ast.ComparisonFormula; +import kodkod.ast.ConstantFormula; +import kodkod.ast.Formula; +import kodkod.ast.IntComparisonFormula; +import kodkod.ast.MultiplicityFormula; +import kodkod.ast.NaryFormula; +import kodkod.ast.Node; +import kodkod.ast.NotFormula; +import kodkod.ast.QuantifiedFormula; +import kodkod.ast.RelationPredicate; +import kodkod.ast.operator.FormulaOperator; +import kodkod.ast.visitor.AbstractVoidVisitor; +import kodkod.util.nodes.AnnotatedNode; + +/** + * Propagates negations all the way down to the leafs, but without crossing + * quantification boundaries. It also eliminates negations wherever possible + * (e.g. double negation, !(a>b) --> a<=b, etc.) + * + * Breaks up all implications (=>) and two-way implications (<=>), so that + * the resulting formula only contains the following boolean operators: + * AND (&&), OR (||), and NOT (!) at the leaf positions. + */ +final class FullNegationPropagator extends AbstractVoidVisitor { + + /** + * + */ + public static AnnotatedNode flatten(AnnotatedNode annotated) { + final FullNegationPropagator flat = new FullNegationPropagator(annotated.sharedNodes()); + annotated.node().accept(flat); + final List roots = new ArrayList(flat.annotations.size()); + roots.addAll(flat.annotations.keySet()); + for(Iterator> itr = flat.annotations.entrySet().iterator(); itr.hasNext(); ) { + final Map.Entry entry = itr.next(); + final Node source = annotated.sourceOf(entry.getValue()); + if (entry.getKey()==source) { itr.remove(); /* TODO: what is this for? */ } + else { entry.setValue(source); } + } + return AnnotatedNode.annotate(Formula.and(flat.conjuncts), flat.annotations); + } + + private List conjuncts; + private Map annotations; + private final Map visited; + private final Set shared; + private boolean negated; + private boolean hasChanged; + + /** + * Constructs a flattener for a formula in which the given nodes are shared. + */ + private FullNegationPropagator(Set shared) { + this(shared, new LinkedHashMap(), new IdentityHashMap()); + } + + private FullNegationPropagator(Set shared, Map annotations, Map visited) { + this.conjuncts = new LinkedList(); + this.annotations = annotations; + this.shared = shared; + this.visited = visited; + this.negated = false; + } + + /** + * {@inheritDoc} + * @see kodkod.ast.visitor.AbstractVoidVisitor#visited(kodkod.ast.Node) + */ + @Override + protected boolean visited(Node n) { + if (shared.contains(n)) { + if (visited.containsKey(n)) { + final Boolean val = visited.get(n); + if (val==null || val.booleanValue()==negated) { + return true; + } else { + visited.put(n, null); + return false; + } + } else { + visited.put(n, Boolean.valueOf(negated)); + return false; + } + } + return false; + } + + /** + * Calls nf.formula.accept(this) after flipping the negation flag. + * @see kodkod.ast.visitor.AbstractVoidVisitor#visit(kodkod.ast.NotFormula) + */ + public final void visit(NotFormula nf) { + if (visited(nf)) return; + + FullNegationPropagator fne = new FullNegationPropagator(shared, annotations, visited); + fne.negated = !negated; + nf.formula().accept(fne); + if (fne.hasChanged) { + addConjunct(Formula.and(fne.conjuncts), false, nf); + hasChanged = true; + } else { + addConjunct(nf); + } + } + + /** + * Adds the given formula (or its negation, depending on the value of the negated flag) + * to this.conjuncts. + */ + private final void addConjunct(Formula conjunct) { + Formula f = negated ? conjunct.not() : conjunct; + conjuncts.add(f); + annotations.put(f, conjunct); + } + private final void addConjunct(Formula conjunct, boolean neg, Node source) { + Formula f = neg ? conjunct.not() : conjunct; + conjuncts.add(f); + annotations.put(f, source); + } + + /** + * Visits the formula's children with appropriate settings + * for the negated flag if bf has not been visited before. + * @see kodkod.ast.visitor.AbstractVoidVisitor#visit(kodkod.ast.BinaryFormula) + */ + public final void visit(BinaryFormula bf) { + if (visited(bf)) return; + final FormulaOperator op = bf.op(); + switch (op) { + case AND: + if (!negated) { + // left && right + bf.left().accept(this); + bf.right().accept(this); + } else { + // !(left && right) --> !left || !right + FullNegationPropagator fne1 = new FullNegationPropagator(shared, annotations, visited); + bf.left().not().accept(fne1); + + FullNegationPropagator fne2 = new FullNegationPropagator(shared, annotations, visited); + bf.right().not().accept(fne2); + + addConjunct(Formula.and(fne1.conjuncts).or(Formula.and(fne2.conjuncts)), false, bf); + hasChanged = true; + } + break; + case OR: + if (!negated) { + // left || right + FullNegationPropagator fne1 = new FullNegationPropagator(shared, annotations, visited); + bf.left().accept(fne1); + + FullNegationPropagator fne2 = new FullNegationPropagator(shared, annotations, visited); + bf.right().accept(fne2); + + if (!fne1.hasChanged && !fne2.hasChanged) { + addConjunct(bf); + } else { + addConjunct(Formula.and(fne1.conjuncts).or(Formula.and(fne2.conjuncts)), false, bf); + hasChanged = true; + } + } else { + // !(left || right) --> !left && !right + bf.left().accept(this); + bf.right().accept(this); + hasChanged = true; + } + break; + case IMPLIES: + if (!negated) { + // left => right --> !left || right + FullNegationPropagator fne1 = new FullNegationPropagator(shared, annotations, visited); + bf.left().not().accept(fne1); + + FullNegationPropagator fne2 = new FullNegationPropagator(shared, annotations, visited); + bf.right().accept(fne2); + + addConjunct(Formula.and(fne1.conjuncts).or(Formula.and(fne2.conjuncts)), false, bf); + } else { + // !(left => right) --> left && !right + negated = false; + bf.left().accept(this); + negated = true; + bf.right().accept(this); + } + hasChanged = true; + break; + case IFF: + FullNegationPropagator fne1 = new FullNegationPropagator(shared, annotations, visited); + FullNegationPropagator fne2 = new FullNegationPropagator(shared, annotations, visited); + if (!negated) { + // a = b --> (a && b) || (!a && !b) + bf.left().and(bf.right()).accept(fne1); + bf.left().not().and(bf.right().not()).accept(fne2); + } else { + // !(a = b) --> (a && !b) || (!a && b) + bf.left().and(bf.right().not()).accept(fne1); + bf.left().not().and(bf.right()).accept(fne2); + } + addConjunct(Formula.and(fne1.conjuncts).or(Formula.and(fne2.conjuncts)), false, bf); + hasChanged = true; + break; + default: + addConjunct(bf); + } + } + + /** + * Visits the formula's children with appropriate settings + * for the negated flag if bf has not been visited before. + * @see kodkod.ast.visitor.AbstractVoidVisitor#visit(kodkod.ast.NaryFormula) + */ + public final void visit(NaryFormula nf) { + if (visited(nf)) return; + final FormulaOperator op = nf.op(); + if (negated && op==AND) { + List formulas = new LinkedList(); + for (Formula f : nf) { + FullNegationPropagator fne = new FullNegationPropagator(shared, annotations, visited); + f.not().accept(fne); + formulas.add(Formula.and(fne.conjuncts)); + } + addConjunct(Formula.or(formulas), false, nf); + } else if (!negated && op==OR) { + List formulas = new LinkedList(); + boolean changed = false; + for (Formula f : nf) { + FullNegationPropagator fne = new FullNegationPropagator(shared, annotations, visited); + f.accept(fne); + changed = changed || fne.hasChanged; + formulas.add(Formula.and(fne.conjuncts)); + } + if (changed) { + addConjunct(Formula.or(formulas), false, nf); + hasChanged = true; + } else { + addConjunct(nf); + } + } else { + for(Formula f : nf) { + f.accept(this); + } + } + } + + /** + * Adds f (resp. f.not()) to this.conjuncts if the negated flag is false (resp. true) and + * the given node has not been visited; otherwise does nothing. + * @ensures !this.visited(f) => + * (this.conjuncts' = conjuncts + (negated => f.not() else f)) else + * (this.conjuncts' = this.conjuncts) + */ + final void visitFormula(Formula f) { + if (visited(f)) return; + addConjunct(f); + } + + /** + * {@inheritDoc} + * @see kodkod.ast.visitor.AbstractVoidVisitor#visit(kodkod.ast.QuantifiedFormula) + */ + public final void visit(QuantifiedFormula qf) { + if (visited(qf)) return; + FullNegationPropagator fne = new FullNegationPropagator(shared, annotations, visited); + qf.formula().accept(fne); + if (fne.hasChanged) { + Formula f = Formula.and(fne.conjuncts); + addConjunct(f.quantify(qf.quantifier(), qf.decls()), negated, qf); + hasChanged = true; + } else { + addConjunct(qf); + } + } + + /** @see #visitFormula(Formula) */ + public final void visit(ComparisonFormula cf) { visitFormula(cf); } + + /** @see #visitFormula(Formula) */ + public final void visit(IntComparisonFormula cf) { + if (visited(cf)) return; + if (!negated) { + addConjunct(cf); + } else { + switch (cf.op()) { + case GT: + addConjunct(cf.left().lte(cf.right()), false, cf); + hasChanged = true; + break; + case GTE: + addConjunct(cf.left().lt(cf.right()), false, cf); + hasChanged = true; + break; + case LT: + addConjunct(cf.left().gte(cf.right()), false, cf); + hasChanged = true; + break; + case LTE: + addConjunct(cf.left().gt(cf.right()), false, cf); + hasChanged = true; + break; + case EQ: + addConjunct(cf.left().neq(cf.right()), false, cf); + hasChanged = true; + break; + case NEQ: + addConjunct(cf.left().eq(cf.right()), false, cf); + hasChanged = true; + break; + default: + addConjunct(cf); + } + } + } + + /** @see #visitFormula(Formula) */ + public final void visit(MultiplicityFormula mf) { visitFormula(mf); } + + /** @see #visitFormula(Formula) */ + public final void visit(ConstantFormula constant) { visitFormula(constant); } + + /** @see #visitFormula(Formula) */ + public final void visit(RelationPredicate pred) { visitFormula(pred); } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/HigherOrderDeclException.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/HigherOrderDeclException.java new file mode 100644 index 00000000..eabc7051 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/HigherOrderDeclException.java @@ -0,0 +1,57 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import kodkod.ast.Decl; +import kodkod.ast.operator.Multiplicity; + +/** + * Thrown when a node contains a higher order declaration that cannot + * be skolemized, or it can be skolemized but skolemization is disabled. + * + * @specfield decl: Decl // higher order decl that caused the exception to be thrown + * @author Emina Torlak + */ +public final class HigherOrderDeclException extends RuntimeException { + private final Decl decl; + private static final long serialVersionUID = 1892780864484615171L; + + /** + * Constructs a HigherOrderDeclException for the given decl. + * @requires decl.multiplicity != ONE + * @ensures this.decl' = decl + */ + HigherOrderDeclException(Decl decl) { + super("Higher order declaration: " + decl); + assert decl.multiplicity() != Multiplicity.ONE; + this.decl = decl; + } + + /** + * Returns this.decl + * @return this.decl + */ + public Decl decl() { + return decl; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/LeafInterpreter.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/LeafInterpreter.java new file mode 100644 index 00000000..0e041b7f --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/LeafInterpreter.java @@ -0,0 +1,260 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +import kodkod.ast.ConstantExpression; +import kodkod.ast.Expression; +import kodkod.ast.Relation; +import kodkod.engine.bool.BooleanFactory; +import kodkod.engine.bool.BooleanMatrix; +import kodkod.engine.bool.Dimensions; +import kodkod.engine.config.Options; +import kodkod.instance.Bounds; +import kodkod.instance.Instance; +import kodkod.instance.TupleSet; +import kodkod.instance.Universe; +import kodkod.util.ints.IntIterator; +import kodkod.util.ints.IntRange; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.Ints; +import kodkod.util.ints.SparseSequence; + +/** + *

Interprets the unquantified leaf expressions of a kodkod ast, {@link kodkod.ast.Relation relations} and + * {@link kodkod.ast.ConstantExpression constant expressions}, as {@link kodkod.engine.bool.BooleanMatrix matrices} of {@link kodkod.engine.bool.BooleanValue + * boolean values}, and primitive integers as corresponding to particular atoms in the {@link kodkod.instance.Universe universe + * of discourse}

+ * + * @specfield universe: Universe + * @specfield relations: set Relation + * @specfield ints: set int + * @specfield lbounds: relations ->one TupleSet + * @specfield ubounds: relations ->one TupleSet + * @specfield ibounds: ints -> one TupleSet + * @specfield factory: BooleanFactory + * @specfield vars: relations -> set BooleanVariable + * @invariant all r: relations | r.arity = lbounds[r].arity = ubounds[r].arity && ubounds[r].containsAll(lbounds[r]) + * @invariant all r: relations | lbounds[r].atoms + ubounds[r] in universe + * @invariant all r: relations | #vars[r] = ubounds[r].size() - lbounds[r].size() + * @invariant all i: ints | ibounds[i].arity = ibounds[i].size() = 1 + * @invariant vars[relations] in factory.components + * + * @author Emina Torlak + */ +final class LeafInterpreter { + private final BooleanFactory factory; + private final Universe universe; + private final Map vars; + private final Map lowers, uppers; + private final SparseSequence ints; + + /** + * Constructs a new LeafInterpreter using the given values. + * @requires lowers.keySet() = uppers.keySet() + * @ensures this.universe' = universe && this.relations' = lowers.keySet() && + * this.ints' = ints.indices && this.factory' = factory && + * this.ubounds' = uppers && this.lbounds' = lowers && + * this.ibounds' = ints + */ + private LeafInterpreter(Universe universe, Map lowers, Map uppers, + SparseSequence ints, BooleanFactory factory, Map vars) { + this.universe = universe; + this.lowers = lowers; + this.uppers = uppers; + this.ints = ints; + this.factory = factory; + this.vars = vars; + } + + + /** + * Constructs a new LeafInterpreter using the given values. + * @requires lowers.keySet() = uppers.keySet() + * @ensures this.universe' = universe && this.relations' = lowers.keySet() && + * this.ints' = ints.indices && this.factory' = factory && + * this.ubounds' = uppers && this.lbounds' = lowers && + * this.ibounds' = ints + */ + @SuppressWarnings("unchecked") + private LeafInterpreter(Universe universe, Map rbound, SparseSequence ints, Options options) { + this(universe, rbound, rbound, ints, BooleanFactory.constantFactory(options), Collections.EMPTY_MAP); + } + + /** + * Returns an exact leaf interpreter based on the given instance and options. + * @return { l: LeafInterpreter | l.universe = instance.universe && l.relations = instance.relations() && + * l.ints = instance.ints() && l.lbounds = l.ubounds = instance.relationTuples() && + * l.ibounds = instance.intTuples && l.factory = BooleanFactory.constantFactory(options) && no l.vars } + */ + static final LeafInterpreter exact(Instance instance, Options options) { + return new LeafInterpreter(instance.universe(), instance.relationTuples(), instance.intTuples(), options); + } + + /** + * Returns an exact interpreter for the given bounds and options. + * @return { l: LeafInterpreter | l.universe = bounds.universe && l.relations = bounds.relations() && + * l.ints = bounds.ints() && l.lbounds = bounds.lowerBound && l.ubounds = bounds.upperBound && + * l.ibounds = bounds.intBound && + * l.factory = BooleanFactory.factory(sum(r: l.relations | #(l.ubounds[r]-l.lbounds[r]))-1, options) && + * l.vars[relations] = l.factory & BooleanVariable} + */ + static final LeafInterpreter exact(Bounds bounds, Options options) { + final Map vars = new LinkedHashMap(); + int maxLit = 1; + for(Relation r : bounds.relations()) { + int rLits = bounds.upperBound(r).size() - bounds.lowerBound(r).size(); + if (rLits > 0) { + vars.put(r, Ints.range(maxLit, maxLit + rLits - 1)); + maxLit += rLits; + } + } + return new LeafInterpreter(bounds.universe(), bounds.lowerBounds(), bounds.upperBounds(), + bounds.intBounds(), BooleanFactory.factory(maxLit-1, options), vars); + } + + /** + * Returns an overapproximating interpreter for the given bounds and options. + * @return { l: LeafInterpreter | l.universe = bounds.universe && l.relations = bounds.relations() && + * l.ints = bounds.ints() && l.lbounds = l.ubounds = bounds.upperBound && + * l.ibounds = bounds.intBound && l.factory = BooleanFactory.constantFactory(options) && no l.vars } + */ + static final LeafInterpreter overapproximating(Bounds bounds, Options options) { + return new LeafInterpreter(bounds.universe(), bounds.upperBounds(), bounds.intBounds(), options); + } + + /** + * Returns this.factory. + * @return this.factory. + */ + public final BooleanFactory factory() { + return this.factory; + } + + /** + * Returns the universe of discourse. + * @return this.universe + */ + public final Universe universe() { + return universe; + } + + /** + * Returns this.vars. + * @return this.vars. + */ + public final Map vars() { + final Map ret = new LinkedHashMap((vars.size() * 4)/3); + for(Map.Entry e: vars.entrySet()) { + ret.put(e.getKey(), Ints.rangeSet(e.getValue())); + } + return ret; + } + + /** + * Returns a {@link kodkod.engine.bool.BooleanMatrix matrix} m of + * {@link kodkod.engine.bool.BooleanValue boolean formulas} representing + * the specified relation. + * @requires r in this.relations + * @return { m: BooleanMatrix | let lset = (this.rBounds[r].TupleSet).tuples.index, + * hset = (this.rBounds[r][TupleSet]).tuples.index, dset = [0..this.universe.size()^r.arity) | + * m.dimensions.dimensions = [0..r.arity) ->one this.universe.size() && + * m.elements[lset] = TRUE && m.elements[dset-hset] = FALSE && + * all disj i, j: hset-lset | m.elements[i]+m.elements[j] in this.vars[r] && + * m.elements[i].label < m.elements[j].label <=> i < j } + * @throws UnboundLeafException - r !in this.relations + */ + public final BooleanMatrix interpret(Relation r) { + if (!lowers.containsKey(r)) + throw new UnboundLeafException("Unbound relation: ", r); + final IntSet lowerBound = lowers.get(r).indexView(); + final IntSet upperBound = uppers.get(r).indexView(); + + final BooleanMatrix m = factory.matrix(Dimensions.square(universe().size(), r.arity()), upperBound, lowerBound); + + if (upperBound.size() > lowerBound.size()) { + int varId = vars.get(r).min(); + for (IntIterator indeces = upperBound.iterator(); indeces.hasNext();) { + int tupleIndex = indeces.next(); + if (!lowerBound.contains(tupleIndex)) + m.set(tupleIndex, factory.variable(varId++)); + } + } + return m; + } + + /** + * Returns a {@link kodkod.engine.bool.BooleanMatrix matrix} m of + * {@link kodkod.engine.bool.BooleanValue boolean formulas} representing + * the specified constant expression. + * @return { m: BooleanMatrix | let dset = [0..this.universe.size()^c.arity) | + * m.dimensions.dimensions = [0..c.arity) ->one this.universe.size() && + * c = UNIV => m.elements[dset] = TRUE, c = NONE => m.elements[dset] = FALSE, + * c = IDEN => (all i: dset | (some j: int | i = j*(1+this.universe.size())) => m.elements[i] = TRUE, m.elements[i] = FALSE), + * c = INT => (all i: dset | (some j: int | this.interpret(j)=i) => m.elements[i] = TRUE, m.elements[i] = FALSE } + */ + public final BooleanMatrix interpret(ConstantExpression c) { + final int univSize = universe().size(); + if (c==Expression.UNIV) { + final IntSet all = Ints.rangeSet(Ints.range(0, univSize-1)); + return factory().matrix(Dimensions.square(univSize, 1), all, all); + } else if (c==Expression.IDEN) { + final Dimensions dim2 = Dimensions.square(univSize, 2); + final IntSet iden = Ints.bestSet(dim2.capacity()); + for(int i = 0; i < univSize; i++) { + iden.add(i*univSize + i); + } + return factory().matrix(dim2, iden, iden); + } else if (c==Expression.NONE) { + return factory().matrix(Dimensions.square(univSize, 1), Ints.EMPTY_SET, Ints.EMPTY_SET); + } else if (c==Expression.INTS) { + final IntSet ints = Ints.bestSet(univSize); + for(IntIterator iter = ints().iterator(); iter.hasNext(); ) { + ints.add(interpret(iter.next())); + } + return factory().matrix(Dimensions.square(univSize, 1), ints, ints); + } else { + throw new IllegalArgumentException("unknown constant expression: " + c); + } + } + + /** + * Returns the set of all integers corresponding to some + * atom in this.universe. + * @return this.ints + */ + public final IntSet ints() { + return ints.indices(); + } + + /** + * Returns the index of the atom from this.universe which represents the given integer. + * @requires i in this.ints + * @return this.ibounds[i].indexView().min() + */ + public final int interpret(int i) { + return ints.get(i).indexView().min(); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/MemoryLogger.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/MemoryLogger.java new file mode 100644 index 00000000..99f472b7 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/MemoryLogger.java @@ -0,0 +1,192 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; + +import kodkod.ast.Expression; +import kodkod.ast.Formula; +import kodkod.ast.Node; +import kodkod.ast.Variable; +import kodkod.engine.Solver; +import kodkod.engine.bool.BooleanMatrix; +import kodkod.engine.bool.BooleanValue; +import kodkod.instance.Bounds; +import kodkod.instance.TupleSet; +import kodkod.util.collections.FixedMap; +import kodkod.util.nodes.AnnotatedNode; +import kodkod.util.nodes.Nodes; + +/** + * A translation logger that logs translation events for the {@linkplain Nodes#conjuncts(Formula) conjuncts} of a given formula to memory. + * In other words, this logger only logs the translations for the children of the given formula, if the formula is a conjunction. Otherwise, + * it simply logs the translation for the formula itself. The translation events for the conjuncts' descendants are ignored. + * @specfield originalFormula: Formula // the {@linkplain Solver#solve(Formula, kodkod.instance.Bounds) original} formula, provided by the user + * @specfield originalBounds: Bounds // the {@linkplain Solver#solve(Formula, kodkod.instance.Bounds) original} bounds, provided by the user + * @specfield formula: Formula // desugaring of this.formula that was translated + * @specfield bounds: Bounds // translation bounds + * @specfield records: (formula.*children & Formula) -> BooleanValue -> Environment + * @invariant Solver.solve(formula, bounds).instance() == null iff Solver.solve(originalFormula, originalBounds).instance() == null + * @author Emina Torlak + */ +final class MemoryLogger extends TranslationLogger { + private final FixedMap logMap; + private final AnnotatedNode annotated; + private final Bounds bounds; + + /** + * Constructs a new memory logger from the given annotated formula. + * @ensures this.formula' = annotated.node + * @ensures this.bounds' = bounds + * @ensures no this.records' + * @ensures this.log().roots() = Nodes.conjuncts(annotated) + */ + MemoryLogger(final AnnotatedNode annotated, Bounds bounds) { + this.annotated = annotated; + this.bounds = bounds; + this.logMap = new FixedMap(Nodes.conjuncts(annotated.node())); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.fol2sat.TranslationLogger#close() + */ + @Override + void close() {} + + /** + * Logs the translation of the given formula if and only if f is a root of this.formula. + * @ensures f in Nodes.conjuncts(this.formula) and no this.records[f] => + * this.records' = this.records ++ f -> translation -> env + * @throws IllegalArgumentException - some this.records[f] and this.records[f] != translation -> env + * @see kodkod.engine.fol2sat.TranslationLogger#log(kodkod.ast.Formula, kodkod.engine.bool.BooleanValue, kodkod.engine.fol2sat.Environment) + */ + @Override + void log(Formula f, BooleanValue translation, Environment env) { + if (logMap.containsKey(f)) { + //assert env.isEmpty(); + final BooleanValue old = logMap.put(f, translation); + if (old!=null && old!=translation) + throw new IllegalArgumentException("translation of root corresponding to the formula has already been logged: " + f); + } + } + + /** + * {@inheritDoc} + * @see kodkod.engine.fol2sat.TranslationLogger#log() + */ + @Override + TranslationLog log() { return new MemoryLog(annotated,logMap,bounds); } + + /** + * A memory-based translation log, written by a MemoryLogger. + * @author Emina Torlak + */ + private static class MemoryLog extends TranslationLog { + private final Set roots; + private final Bounds bounds; + private final Node[] original; + private final int[] transl; + + /** + * Constructs a new memory log out of the given node and its corresponding log map. + */ + MemoryLog(AnnotatedNode annotated, FixedMap logMap, Bounds bounds) { + this.bounds = bounds; + this.roots = Nodes.conjuncts(annotated.node()); + assert roots.size() == logMap.size(); + this.transl = new int[roots.size()]; + this.original = new Node[roots.size()]; + final Iterator itr = roots.iterator(); + for(int i = 0; i < transl.length; i++) { + final Formula root = itr.next(); + transl[i] = logMap.get(root).label(); + original[i] = annotated.sourceOf(root); + } + } + + /** + * {@inheritDoc} + * @see kodkod.engine.fol2sat.TranslationLog#bounds() + */ + public Bounds bounds() { return bounds; } + + /** + * {@inheritDoc} + * @see kodkod.engine.fol2sat.TranslationLog#replay(kodkod.engine.fol2sat.RecordFilter) + */ + @Override + public Iterator replay(final RecordFilter filter) { + return new Iterator() { + final Iterator itr = roots.iterator(); + boolean ready = false; + int index = -1; + Formula root = null; + final TranslationRecord current = new TranslationRecord() { + @Override + public Map env() { return Collections.emptyMap(); } + @Override + public int literal() { return transl[index]; } + @Override + public Node node() { return original[index]; } + @Override + public Formula translated() { return root; } + + }; + + @SuppressWarnings("unchecked") + public boolean hasNext() { + while(!ready && itr.hasNext()) { + root = itr.next(); + index++; + if (filter.accept(original[index], root, transl[index], Collections.EMPTY_MAP)) { + ready = true; + break; + } + } + return ready; + } + + public TranslationRecord next() { + if (!hasNext()) throw new NoSuchElementException(); + ready = false; + return current; + } + + public void remove() { throw new UnsupportedOperationException(); } + }; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.fol2sat.TranslationLog#roots() + */ + @Override + public Set roots() { return roots; } + + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/NNFConverter.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/NNFConverter.java new file mode 100644 index 00000000..3d1ec809 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/NNFConverter.java @@ -0,0 +1,271 @@ +package kodkod.engine.fol2sat; + +import static kodkod.ast.operator.FormulaOperator.AND; +import static kodkod.ast.operator.FormulaOperator.OR; + +import java.util.ArrayList; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import kodkod.ast.BinaryFormula; +import kodkod.ast.ComparisonFormula; +import kodkod.ast.ConstantFormula; +import kodkod.ast.Formula; +import kodkod.ast.IntComparisonFormula; +import kodkod.ast.IntExpression; +import kodkod.ast.MultiplicityFormula; +import kodkod.ast.NaryFormula; +import kodkod.ast.Node; +import kodkod.ast.NotFormula; +import kodkod.ast.QuantifiedFormula; +import kodkod.ast.RelationPredicate; +import kodkod.ast.operator.FormulaOperator; +import kodkod.ast.visitor.AbstractReplacer; +import kodkod.util.nodes.AnnotatedNode; + +public class NNFConverter extends AbstractReplacer { + + public static AnnotatedNode flatten(AnnotatedNode annotated) { + final NNFConverter flat = new NNFConverter(annotated.sharedNodes()); + Formula f = annotated.node().accept(flat); + final List roots = new ArrayList(flat.annotations.size()); + roots.addAll(flat.annotations.keySet()); + for(Iterator> itr = flat.annotations.entrySet().iterator(); itr.hasNext(); ) { + final Map.Entry entry = itr.next(); + final Node source = annotated.sourceOf(entry.getValue()); + if (entry.getKey()==source) { itr.remove(); /* TODO: what is this for? */ } + else { entry.setValue(source); } + } + return AnnotatedNode.annotate(f, flat.annotations); + } + + private Map annotations; + private boolean negated; + + protected NNFConverter(Set shared) { + this(shared, new LinkedHashMap(), new IdentityHashMap()); + } + + protected NNFConverter(Set shared, Map annotations, Map visited) { + super(shared); + this.annotations = annotations; + this.negated = false; + } + + protected Formula addMapping(Formula f, Node source) { + annotations.put(f, source); + return f; + } + + /** + * Calls nf.formula.accept(this) after flipping the negation flag. + * @see kodkod.ast.visitor.AbstractVoidVisitor#visit(kodkod.ast.NotFormula) + */ + public final Formula visit(NotFormula nf) { + //if (visited(bf)) return; + negated = !negated; + Formula f = nf.formula().accept(this); + negated = !negated; + if (f instanceof NotFormula) { + if (((NotFormula) f).formula() == nf.formula()) { + return addMapping(nf, nf); + } + } + return addMapping(f, nf); + } + + /** + * Visits the formula's children with appropriate settings + * for the negated flag if bf has not been visited before. + * @see kodkod.ast.visitor.AbstractVoidVisitor#visit(kodkod.ast.BinaryFormula) + */ + public final Formula visit(BinaryFormula bf) { + //if (visited(bf)) return; + final FormulaOperator op = bf.op(); + switch (op) { + case AND: + if (!negated) { + // left && right + Formula lf = bf.left().accept(this); + Formula rf = bf.right().accept(this); + if (lf == bf.left() && rf == bf.right()) { + return addMapping(bf, bf); + } else { + return addMapping(lf.and(rf), bf); + } + } else { + // !(left && right) --> !left || !right + Formula lf = bf.left().accept(this); + Formula rf = bf.right().accept(this); + return addMapping(lf.or(rf), bf); + } + case OR: + if (!negated) { + // left || right + Formula lf = bf.left().accept(this); + Formula rf = bf.right().accept(this); + if (lf == bf.left() && rf == bf.right()) { + return addMapping(bf, bf); + } else { + return addMapping(lf.or(rf), bf); + } + } else { + // !(left || right) --> !left && !right + Formula lf = bf.left().accept(this); + Formula rf = bf.right().accept(this); + return addMapping(lf.or(rf), bf); + } + case IMPLIES: + if (!negated) { + // left => right --> !left || right + Formula lf = bf.left().not().accept(this); + Formula rf = bf.right().accept(this); + return addMapping(lf.or(rf), bf); + } else { + // !(left => right) --> left && !right + negated = false; + Formula lf = bf.left().accept(this); + negated = true; + Formula rf = bf.right().accept(this); + return addMapping(lf.and(rf), bf); + } + case IFF: + if (!negated) { + // a = b --> (a && b) || (!a && !b) + Formula lf = bf.left().and(bf.right()).accept(this); + Formula rf = bf.left().not().and(bf.right().not()).accept(this); + return addMapping(lf.or(rf), bf); + } else { + // !(a = b) --> (a && !b) || (!a && b) + negated = false; + Formula lf = bf.left().and(bf.right().not()).accept(this); + Formula rf = bf.left().not().and(bf.right()).accept(this); + negated = true; + return addMapping(lf.or(rf), bf); + } + default: + return addMapping(bf, bf); + } + } + + /** + * Visits the formula's children with appropriate settings + * for the negated flag if bf has not been visited before. + * @see kodkod.ast.visitor.AbstractVoidVisitor#visit(kodkod.ast.NaryFormula) + */ + //TODO: probably don't needed + public final Formula visit(NaryFormula nf) { + //if (visited(nf)) return; + final FormulaOperator op = nf.op(); + if (negated && op==AND) { + List formulas = new LinkedList(); + for (Formula f : nf) { + formulas.add(f.accept(this)); + } + return addMapping(Formula.or(formulas), nf); + } else if (negated && op==OR) { + List formulas = new LinkedList(); + for (Formula f : nf) { + formulas.add(f.accept(this)); + } + return addMapping(Formula.and(formulas), nf); + } else { + List formulas = new LinkedList(); + boolean changed = false; + for (Formula f : nf) { + Formula ff = f.accept(this); + changed = changed || ff != f; + formulas.add(ff); + } + if (changed) { + if (op==AND) + return addMapping(Formula.and(formulas), nf); + else + return addMapping(Formula.or(formulas), nf); + } else { + return addMapping(nf, nf); + } + } + } + + /** @see #visitFormula(Formula) */ + public final Formula visit(IntComparisonFormula cf) { + //if (visited(cf)) return; + IntExpression lh = cf.left().accept(this); + IntExpression rh = cf.right().accept(this); + if (!negated) { + if (lh == cf.left() && rh == cf.right()) { + return addMapping(cf, cf); + } else { + return addMapping(lh.compare(cf.op(), rh), cf); + } + } else { + switch (cf.op()) { + case GT: + return addMapping(lh.lte(rh), cf); + case GTE: + return addMapping(lh.lt(rh), cf); + case LT: + return addMapping(lh.gte(rh), cf); + case LTE: + return addMapping(lh.gt(rh), cf); + case EQ: + return addMapping(lh.neq(rh), cf); + case NEQ: + return addMapping(lh.eq(rh), cf); + default: + return addMapping(cf, cf); + } + } + } + + protected Formula addFormula(Formula f, Node src, boolean negOld) { + negated = negOld; + if (negated) { + return addMapping(f.not(), src); + } else { + return addMapping(f, src); + } + } + + @Override + public Formula visit(ConstantFormula constant) { + boolean negOld = negated; + negated = false; + return addFormula(super.visit(constant), constant, negOld); + } + + @Override + public Formula visit(QuantifiedFormula quantFormula) { + boolean negOld = negated; + negated = false; + return addFormula(super.visit(quantFormula), quantFormula, negOld); + } + + @Override + public Formula visit(ComparisonFormula compFormula) { + boolean negOld = negated; + negated = false; + return addFormula(super.visit(compFormula), compFormula, negOld); + } + + @Override + public Formula visit(MultiplicityFormula multFormula) { + boolean negOld = negated; + negated = false; + return addFormula(super.visit(multFormula), multFormula, negOld); + } + + @Override + public Formula visit(RelationPredicate pred) { + boolean negOld = negated; + negated = false; + return addFormula(super.visit(pred), pred, negOld); + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/NestedSet.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/NestedSet.java new file mode 100644 index 00000000..b6ce065b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/NestedSet.java @@ -0,0 +1,41 @@ +package kodkod.engine.fol2sat; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +/** + * Implements a data structure that contains sets of values at different nesting levels. + * + * @author aleks + */ +@SuppressWarnings("unchecked") +public class NestedSet implements Iterable { + + private final NestedSet parent; + private final Set elems; + + private NestedSet(NestedSet parent) { + this(parent, new HashSet()); + } + + private NestedSet(NestedSet parent, Set elems) { + this.parent = parent; + this.elems = elems; + } + + public NestedSet createNested() { + return new NestedSet(this); + } + + public void add(T elem) { this.elems.add(elem); } + public void addAll(Collectionelems) { this.elems.addAll(elems); } + public NestedSet parent() { return parent; } + @Override public Iterator iterator() { return elems.iterator(); } + + @SuppressWarnings("rawtypes") + private static final NestedSet EMPTY = new NestedSet(null); + public static NestedSet empty() { return (NestedSet) EMPTY; } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/RecordFilter.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/RecordFilter.java new file mode 100644 index 00000000..81969fb4 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/RecordFilter.java @@ -0,0 +1,35 @@ +package kodkod.engine.fol2sat; + +import java.util.Map; + +import kodkod.ast.Formula; +import kodkod.ast.Node; +import kodkod.ast.Variable; +import kodkod.instance.TupleSet; + +/** + * A filter for TranslationRecords, based on the value of a record's node and literal fields. + **/ +public interface RecordFilter { + /** + * Returns true if the records with the given node, formula derived from the node, literal, and environment + * should be returned by iterators produced by the {@linkplain TranslationLog#replay()} method. + * @return true if the records with the given node, formula derived from the node, literal, and environment + * should be returned by iterators produced by {@linkplain TranslationLog#replay()}. + */ + public abstract boolean accept(Node node, Formula translated, int literal, Map env); + + /** + * A record filter that accepts all records. + */ + public static RecordFilter ALL = new RecordFilter() { + /** + * Returns true. + * @return true + */ + public boolean accept(Node node, Formula translated, int literal, Map env) { + return true; + } + }; + +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/Skolemizer.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/Skolemizer.java new file mode 100644 index 00000000..7e3c736e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/Skolemizer.java @@ -0,0 +1,563 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import static kodkod.ast.operator.FormulaOperator.AND; +import static kodkod.ast.operator.FormulaOperator.IFF; +import static kodkod.ast.operator.FormulaOperator.IMPLIES; +import static kodkod.ast.operator.FormulaOperator.OR; +import static kodkod.ast.operator.Quantifier.ALL; +import static kodkod.ast.operator.Quantifier.SOME; +import static kodkod.util.nodes.AnnotatedNode.annotate; + +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import kodkod.ast.BinaryFormula; +import kodkod.ast.ComparisonFormula; +import kodkod.ast.Comprehension; +import kodkod.ast.Decl; +import kodkod.ast.Decls; +import kodkod.ast.Expression; +import kodkod.ast.Formula; +import kodkod.ast.IntComparisonFormula; +import kodkod.ast.IntExpression; +import kodkod.ast.MultiplicityFormula; +import kodkod.ast.NaryFormula; +import kodkod.ast.Node; +import kodkod.ast.NotFormula; +import kodkod.ast.QuantifiedFormula; +import kodkod.ast.Relation; +import kodkod.ast.RelationPredicate; +import kodkod.ast.SumExpression; +import kodkod.ast.Variable; +import kodkod.ast.operator.FormulaOperator; +import kodkod.ast.operator.Multiplicity; +import kodkod.ast.operator.Quantifier; +import kodkod.ast.visitor.AbstractDetector; +import kodkod.ast.visitor.AbstractReplacer; +import kodkod.engine.bool.BooleanMatrix; +import kodkod.engine.config.Options; +import kodkod.engine.config.Reporter; +import kodkod.instance.Bounds; +import kodkod.instance.TupleSet; +import kodkod.util.nodes.AnnotatedNode; + +/** + * Skolemizes existential quantifiers, up to a given + * number of nestings (within universal quantifiers). + * @author Emina Torlak + */ +abstract class Skolemizer extends AbstractReplacer { + + /** + * Skolemizes the given annotated formula using the given bounds and options. If + * Options.trackFormulas is set and the formula is skolemizable, the resulting annotated + * formula will contain transitive source information for each of its subformulas. + * Specifically, let f be the returned annotated formula, t be a descendeant of f.node, and + * s a descendant of annotated.node from which t was derived. Then, + * f.source[t] = annotated.source[s]. If options.trackFormulas is false, no source + * information will be recorded (i.e. f.source[t] = t for all descendants t of f). + * @ensures upper bound mappings for skolem constants, if any, are added to the bounds + * @return the skolemized version of the given formula + * @throws NullPointerException - any of the arguments are null + * @throws IllegalArgumentException - some Relation & annotated.node.^children - bounds.relations + * @throws UnsupportedOperationException - bounds is unmodifiable + */ + static AnnotatedNode skolemize(final AnnotatedNode annotated, Bounds bounds, Options options) { + if (options.logTranslation()>0) { + final Map source = new IdentityHashMap(); + final Skolemizer r = new Skolemizer(annotated, bounds, options) { + protected Formula source(Formula f, Node n) { + //System.out.println("logging " + f + " <-- " + n); + final Node nsource = annotated.sourceOf(n); + if (f!=nsource) source.put(f, nsource); + return f; + } + }; + final Formula f = annotated.node().accept(r); + return f==annotated.node() ? annotated : annotate(f, source); + } else { + final Skolemizer r = new Skolemizer(annotated, bounds, options) {}; + final Formula f = annotated.node().accept(r); + return f==annotated.node() ? annotated : annotate(f); + } + } + + /** + * Contains info about an approximate bound for a + * non-skolemizable decl. + * @specfield decl: Decl + * @specfield upperBound: lone BooleanMatrix + * @invariant decl.expression in upperBound + * @author Emina Torlak + */ + private static final class DeclInfo { + final Decl decl; + BooleanMatrix upperBound; + /** + * Constructs a DeclInfo for the given decl. + * @ensures this.decl' = decl && this.upperBound' = null + */ + DeclInfo(Decl decl) { + this.decl = decl; + this.upperBound = null; + } + } + + /* replacement environment; maps skolemized variables to their skolem expressions, + * and non-skolemized variables to themselves */ + private Environment repEnv; + /* the interpreter used to determine the upper bounds for skolem constants; + * the upper bounds for skolem constants will be added to interpreter.bounds */ + private final LeafInterpreter interpreter; + /* bounds on which the interpreter is based */ + private final Bounds bounds; + /* reporter */ + private final Reporter reporter; + /* non-skolemizable quantified declarations in the current scope, in the order of declaration + * (most recent decl is last in the list) */ + private final List nonSkolems; + /* a Decl-only view of the nonSkolems list */ + private final List nonSkolemsView; + private final List topSkolemConstraints; + /* true if the polarity of the currently visited node is negative, otherwise false */ + private boolean negated; + /* depth to which to skolemize; negative depth indicates that no skolemization can be done at that point */ + private int skolemDepth; + + /** + * Constructs a skolem replacer from the given arguments. + */ + private Skolemizer(AnnotatedNode annotated, Bounds bounds, Options options) { + super(annotated.sharedNodes()); + + // only cache intermediate computations for expressions with no free variables + // and formulas with no free variables and no quantified descendents + final AbstractDetector fvdetect = annotated.freeVariableDetector(); + final AbstractDetector qdetect = annotated.quantifiedFormulaDetector(); + for(Node n: annotated.sharedNodes()) { + if (!(Boolean)n.accept(fvdetect)) { + if (!(n instanceof Formula) || !((Boolean)n.accept(qdetect))) + this.cache.put(n, null); + } + } + this.reporter = options.reporter(); + this.bounds = bounds; + this.interpreter = LeafInterpreter.overapproximating(bounds, options); + this.repEnv = Environment.empty(); + this.nonSkolems = new ArrayList(); + this.nonSkolemsView = new AbstractList() { + public Decl get(int index) { return nonSkolems.get(index).decl; } + public int size() { return nonSkolems.size(); } + }; + this.topSkolemConstraints = new ArrayList(); + this.negated = false; + this.skolemDepth = options.skolemDepth(); + } + + /** + * Caches the given replacement for the specified node, if + * the node is a syntactically shared expression, int expression or declaration with + * no free variables. Otherwise does nothing. The method returns + * the replacement node. + * @return replacement + */ + @Override + protected final N cache(N node, N replacement) { + if (cache.containsKey(node)) { + cache.put(node, replacement); + } + return replacement; + } + + /** + * Records that the given node is the source of the + * specified formula, if this is a tracking skolemizer. Otherwise does nothing. + * This method is always called when the result of visiting a node n will result + * in the creation of a formula f such that f != n. + * @return f + * @ensures Records that the given node is the source of the + * specified formula, if this is a tracking skolemizer. Otherwise does nothing. + */ + protected Formula source(Formula f, Node n) { + return f; + } + + /*-------declarations---------*/ + /** + * Visits the given decl's expression. Note that we must not visit variables + * in case they are re-used. For example, consider the formula + * some x: X | all x: Y | F(x). Since x bound by the existential quantifier + * is going to be skolemized, if we visited the variable in the enclosed + * declaration, we would get the skolem constant as a return value and + * a ClassCastException would be thrown. + * + * @return { d: Declaration | d.variable = decl.variable && d.multiplicity = decl.multiplicity && + * d.expression = decl.expression.accept(this) } + */ + @Override + public final Decl visit(Decl decl) { + Decl ret = lookup(decl); + if (ret!=null) return ret; + final int oldDepth = skolemDepth; + skolemDepth = -1; // can't skolemize inside a decl + final Expression expression = decl.expression().accept(this); + skolemDepth = oldDepth; + ret = (expression==decl.expression()) ? decl : decl.variable().declare(decl.multiplicity(), expression); + return cache(decl,ret); + } + + /** + * This method should be accessed only from the context of a non-skolemizable + * node, because it extends the replacement environment + * with identity mappings for the variables declared in the given decls. To ensure + * that the environment is always extended, the method should be called using the + * visit((Decls) node.declarations()) syntax, since the accept syntax may dynamically + * dispatch the call to the {@link #visit(Decl)} method, producing UnboundLeafExceptions. + * @ensures this.repEnv in this.repEnv'.^parent && + * #(this.repEnv'.*parent - this.repEnv.*parent) = decls.size() && + * all v: decls.variable | this.repEnv'.lookup(v) = v + * @requires this.skolemDepth < 0 + * @return { d: Decls | d.size = decls.size && + * all i: [0..d.size) | d.declarations[i] = decls.declarations[i].accept(this) } + */ + public final Decls visit(Decls decls) { + Decls ret = lookup(decls); + if (ret==null) { + Decls visitedDecls = null; + boolean allSame = true; + for(Decl decl : decls) { + Decls newDecl = visit(decl); + if (newDecl != decl) + allSame = false; + visitedDecls = (visitedDecls==null) ? newDecl : visitedDecls.and(newDecl); + repEnv = repEnv.extend(decl.variable(), decl.expression(), decl.variable()); + } + ret = allSame ? decls : visitedDecls; + return cache(decls, ret); + } else { // just extend the replacement environment + for(Decl decl: decls) { + repEnv = repEnv.extend(decl.variable(), decl.expression(), decl.variable()); + } + return ret; + } + } + + /*-------expressions and intexpressions---------*/ + /* INVARIANT: whenever an expression or intexpression is visited, skolemDepth < 0 */ + /** + * Returns the binding for the given variable in the current replacement environment. + * @return the binding for the given variable in the current replacement environment. + * @throws UnboundLeafException - variable not bound in teh replacement environment. + */ + @Override + public final Expression visit(Variable variable) { + final Expression ret = repEnv.lookup(variable); + if (ret==null) + throw new UnboundLeafException("Unbound variable", variable); + return ret; + } + + /** + * @see kodkod.ast.visitor.AbstractReplacer#visit(kodkod.ast.Comprehension) + */ + @Override + public final Expression visit(Comprehension expr) { + Expression ret = lookup(expr); + if (ret!=null) return ret; + final Environment oldRepEnv = repEnv; // skolemDepth < 0 at this point + final Decls decls = visit((Decls)expr.decls()); + final Formula formula = expr.formula().accept(this); + ret = (decls==expr.decls() && formula==expr.formula()) ? expr : formula.comprehension(decls); + repEnv = oldRepEnv; + return cache(expr,ret); + } + /** + * @see kodkod.ast.visitor.AbstractReplacer#visit(kodkod.ast.SumExpression) + */ + @Override + public final IntExpression visit(SumExpression intExpr) { + IntExpression ret = lookup(intExpr); + if (ret!=null) return ret; + final Environment oldRepEnv = repEnv; // skolemDepth < 0 at this point + final Decls decls = visit((Decls)intExpr.decls()); + final IntExpression expr = intExpr.intExpr().accept(this); + ret = (decls==intExpr.decls() && expr==intExpr.intExpr()) ? intExpr : expr.sum(decls); + repEnv = oldRepEnv; + return cache(intExpr,ret); + } + + /*-------formulas---------*/ + /** + * Returns the least sound upper bound on the value of expr + * @return the least sound upper bound on the value of expr + */ + private final BooleanMatrix upperBound(Expression expr, Environment env) { + return FOL2BoolTranslator.approximate(annotate(expr), interpreter, env); + } + + /** + * Adds a bound for the given skolem relation to + * this.bounds, and returns the expression that should replace skolemDecl.variable in the final formula. + * @requires skolem !in this.bounds.relations + * @requires skolem.arity = nonSkolems.size() + skolemDecl.variable().arity() + * @ensures adds a sound upper bound for the given skolem relation to this.bounds + * @return the expression that should replace skolemDecl.variable in the final formula + */ + private Expression skolemExpr(Decl skolemDecl, Relation skolem) { + final int depth = nonSkolems.size(); + final int arity = depth + skolemDecl.variable().arity(); + + Expression skolemExpr = skolem; + Environment skolemEnv = Environment.empty(); + + for(DeclInfo info : nonSkolems) { + if (info.upperBound==null) { + info.upperBound = upperBound(info.decl.expression(), skolemEnv); + } + skolemEnv = skolemEnv.extend(info.decl.variable(), info.decl.expression(), info.upperBound); + skolemExpr = info.decl.variable().join(skolemExpr); + } + + BooleanMatrix matrixBound = upperBound(skolemDecl.expression(), skolemEnv); + for(int i = depth-1; i >= 0; i--) { + matrixBound = nonSkolems.get(i).upperBound.cross(matrixBound); + } + + final TupleSet skolemBound = bounds.universe().factory().setOf(arity, matrixBound.denseIndices()); + bounds.bound(skolem, skolemBound); + + return skolemExpr; + } + + /** + * Returns a formula that properly constrains the given skolem's domain. + * @requires !nonSkolems.isEmpty() + * @return a formula that properly constrains the given skolem's domain. + */ + private Formula domainConstraint(Decl skolemDecl, Relation skolem) { + final Iterator itr = nonSkolems.iterator(); + Decls rangeDecls = itr.next().decl; + while(itr.hasNext()) { + rangeDecls = rangeDecls.and(itr.next().decl); + } +// System.out.println(skolemDecl.expression()); + Expression skolemDomain = skolem; + for(int i = 0, max = skolemDecl.variable().arity(); i < max; i++) { + skolemDomain = skolemDomain.join(Expression.UNIV); + } + return skolemDomain.in(Formula.TRUE.comprehension(rangeDecls)); + } + + /** + * Skolemizes the given formula, if possible, otherwise returns the result + * of replacing its free variables according to the current replacement environment. + * @see kodkod.ast.visitor.AbstractReplacer#visit(kodkod.ast.QuantifiedFormula) + */ + public final Formula visit(QuantifiedFormula qf) { + Formula ret = lookup(qf); + if (ret!=null) return ret; + + final Environment oldRepEnv = repEnv; + final Quantifier quant = qf.quantifier(); + final Decls decls = qf.decls(); + + if (skolemDepth>=0 && (negated && quant==ALL || !negated && quant==SOME)) { // skolemizable formula + final List rangeConstraints = new LinkedList(); + final List domConstraints = new LinkedList(); + + for(Decl decl : decls) { + final Decl skolemDecl = visit(decl); + + final Relation skolem = Relation.nary("$"+ skolemDecl.variable().name(), nonSkolems.size() + skolemDecl.variable().arity()); + reporter.skolemizing(decl, skolem, nonSkolemsView); + + final Expression skolemExpr = skolemExpr(skolemDecl, skolem); + + final Multiplicity mult = decl.multiplicity(); + rangeConstraints.add(source(skolemExpr.in(skolemDecl.expression()), decl)); + if (mult!=Multiplicity.SET) { + rangeConstraints.add(source(skolemExpr.apply(mult), decl)); + } + + if (!nonSkolems.isEmpty()) + domConstraints.add(source(domainConstraint(skolemDecl, skolem), decl)); + + repEnv = repEnv.extend(decl.variable(), decl.expression(), skolemExpr); + } + + ret = source(Formula.and(rangeConstraints), decls).compose(negated ? IMPLIES : AND, qf.formula().accept(this)); + + if (!domConstraints.isEmpty()) + topSkolemConstraints.add(source(Formula.and(domConstraints), decls)); + + } else { // non-skolemizable formula + + final Decls newDecls = visit((Decls)qf.decls()); + if (skolemDepth>=nonSkolems.size()+newDecls.size()) { // could skolemize below + for(Decl d: newDecls) { nonSkolems.add(new DeclInfo(d)); } + final Formula formula = qf.formula().accept(this); + ret = ((newDecls==decls && formula==qf.formula()) ? qf : formula.quantify(quant, newDecls)); + for(int i = newDecls.size(); i > 0; i--) { nonSkolems.remove(nonSkolems.size()-1); } + } else { // can't skolemize below + final int oldDepth = skolemDepth; + skolemDepth = -1; + final Formula formula = qf.formula().accept(this); + ret = ((newDecls==decls && formula==qf.formula()) ? qf : formula.quantify(quant, newDecls)); + skolemDepth = oldDepth; + } + } + + repEnv = oldRepEnv; + if (repEnv.isEmpty() && !topSkolemConstraints.isEmpty()) { + ret = source(Formula.and(topSkolemConstraints), qf).compose(negated ? IMPLIES : AND, ret); + } + return source(cache(qf,ret), qf); + } + + /** + * Calls not.formula.accept(this) after flipping the negation flag and returns the result. + * @see kodkod.ast.visitor.AbstractReplacer#visit(kodkod.ast.NotFormula) + **/ + public final Formula visit(NotFormula not) { + Formula ret = lookup(not); + if (ret!=null) return ret; + negated = !negated; // flip the negation flag + final Formula retChild = not.formula().accept(this); + negated = !negated; + return retChild==not.formula() ? cache(not,not) : source(cache(not, retChild.not()), not); + } + + /** + * If not cached, visits the formula's children with appropriate settings + * for the negated flag and the skolemDepth parameter. + * @see kodkod.ast.visitor.AbstractReplacer#visit(kodkod.ast.BinaryFormula) + */ + public final Formula visit(BinaryFormula bf) { + Formula ret = lookup(bf); + if (ret!=null) return ret; + final FormulaOperator op = bf.op(); + final int oldDepth = skolemDepth; + if (op==IFF || (negated && op==AND) || (!negated && (op==OR || op==IMPLIES))) { // cannot skolemize in these cases + skolemDepth = -1; + } + final Formula left, right; + if (negated && op==IMPLIES) { // !(a => b) = !(!a || b) = a && !b + negated = !negated; + left = bf.left().accept(this); + negated = !negated; + right = bf.right().accept(this); + } else { + left = bf.left().accept(this); + right = bf.right().accept(this); + } + skolemDepth = oldDepth; + ret = (left==bf.left()&&right==bf.right()) ? bf : left.compose(op, right); + return source(cache(bf,ret),bf); + } + + /** + * If not cached, visits the formula's children with appropriate settings + * for the negated flag and the skolemDepth parameter. + * @see kodkod.ast.visitor.AbstractReplacer#visit(kodkod.ast.NaryFormula) + */ + public final Formula visit(NaryFormula bf) { + Formula ret = lookup(bf); + if (ret!=null) return ret; + + final int oldDepth = skolemDepth; + final FormulaOperator op = bf.op(); + + switch(op) { + case AND : if (negated) skolemDepth = -1; break; + case OR : if (!negated) skolemDepth = -1; break; + default : throw new IllegalArgumentException("Unknown nary operator: " + op); + } + + final Formula[] visited = new Formula[bf.size()]; + boolean allSame = true; + for(int i = 0; i < visited.length; i++) { + final Formula child = bf.child(i); + visited[i] = child.accept(this); + allSame = allSame && (child==visited[i]); + } + ret = allSame ? bf : Formula.compose(op, visited); + + skolemDepth = oldDepth; + + return source(cache(bf,ret),bf); + } + + /** + * Calls super.visit(icf) after disabling skolemization and returns the result. + * @return super.visit(icf) + **/ + public final Formula visit(IntComparisonFormula icf) { + final int oldDepth = skolemDepth; + skolemDepth = -1; // cannot skolemize inside an int comparison formula + final Formula ret = super.visit(icf); + skolemDepth = oldDepth; + return source(ret,icf); + } + + /** + * Calls super.visit(cf) after disabling skolemization and returns the result. + * @return super.visit(cf) + **/ + public final Formula visit(ComparisonFormula cf) { + final int oldDepth = skolemDepth; + skolemDepth = -1; // cannot skolemize inside a comparison formula + final Formula ret = super.visit(cf); + skolemDepth = oldDepth; + return source(ret,cf); + } + + /** + * Calls super.visit(mf) after disabling skolemization and returns the result. + * @return super.visit(mf) + **/ + public final Formula visit(MultiplicityFormula mf) { + final int oldDepth = skolemDepth; + skolemDepth = -1; // cannot skolemize inside a multiplicity formula + final Formula ret = super.visit(mf); + skolemDepth = oldDepth; + return source(ret,mf); + } + + /** + * Calls super.visit(pred) after disabling skolemization and returns the result. + * @return super.visit(pred) + **/ + public final Formula visit(RelationPredicate pred) { + final int oldDepth = skolemDepth; + skolemDepth = -1; // cannot skolemize inside a relation predicate + final Formula ret = super.visit(pred); + skolemDepth = oldDepth; + return source(ret,pred); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/SymmetryBreaker.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/SymmetryBreaker.java new file mode 100644 index 00000000..c5ac60dd --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/SymmetryBreaker.java @@ -0,0 +1,489 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import static kodkod.ast.RelationPredicate.Name.ACYCLIC; +import static kodkod.ast.RelationPredicate.Name.TOTAL_ORDERING; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import kodkod.ast.Formula; +import kodkod.ast.Relation; +import kodkod.ast.RelationPredicate; +import kodkod.ast.RelationPredicate.Name; +import kodkod.engine.bool.BooleanAccumulator; +import kodkod.engine.bool.BooleanConstant; +import kodkod.engine.bool.BooleanFactory; +import kodkod.engine.bool.BooleanMatrix; +import kodkod.engine.bool.BooleanValue; +import kodkod.engine.bool.Operator; +import kodkod.engine.config.Reporter; +import kodkod.instance.Bounds; +import kodkod.instance.TupleFactory; +import kodkod.util.ints.IndexedEntry; +import kodkod.util.ints.IntIterator; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.Ints; + +/** + * Breaks symmetries for a given problem. Symmetries + * are broken for total orders, acyclic relations, and + * via a generic lex-leader predicate. + * + * @specfield bounds: Bounds // problem bounds + * @specfield symmetries: set IntSet + * @specfield broken: set RelationPredicate + * @author Emina Torlak + */ +final class SymmetryBreaker { + private final Bounds bounds; + private final Set symmetries; + private final int usize; + + /** + * Constructs a new symmetry breaker for the given Bounds. + * Note that the constructor does not make a local copy of the given + * bounds, so the caller must ensure that all modifications of the + * given bounds are symmetry preserving. + * @ensures this.bounds' = bounds && this.symmetries' = SymmetryDetector.partition(bounds) && + * no this.broken' + **/ + SymmetryBreaker(Bounds bounds, Reporter reporter) { + this.bounds = bounds; + this.usize = bounds.universe().size(); + reporter.detectingSymmetries(bounds); + this.symmetries = SymmetryDetector.partition(bounds); + reporter.detectedSymmetries(symmetries); +// System.out.println(symmetries); + } + + /** + * Breaks matrix symmetries on the relations in this.bounds that are constrained by + * the total ordering and acyclic predicates, drawn from preds.values(), that make up the + * keyset of the returned map. After this method returns, the following constraint holds. + * Let m be the map returned by the method, and m.keySet() be the subset of preds.values() + * used for symmetry breaking. Then, if we let [[b]] denote the set of constraints + * specified by a Bounds object b, the formulas "p and [[this.bounds]]" and "m.get(p) and [[this.bounds']]" + * are equisatisfiable for all p in m.keySet(). + * + *

The value of the "aggressive" flag determines how the symmetries are broken. In particular, if + * the aggressive flag is true, then the symmetries are broken efficiently, at the cost of + * losing the information needed to determine whether a predicate in m.keySet() belongs to an unsatisfiable + * core or not. If the aggressive flag is false, then a less efficient algorithm is applied, which preserves + * the information necessary for unsatisfiable core extraction.

+ * + *

The aggressive symmetry breaking algorithm works as follows. Let t1...tn and c1...ck + * be the total ordering and acyclic predicates in m.keySet(). For each t in {t1...tn}, this.bounds + * is modified so that the bounds for t.first, t.last, t.ordered and t.relation are the following constants: + * t.first is the first atom in the upper bound of t.ordered, t.last is the last atom in the upper bound of t.ordered, t.ordered's + * lower bound is changed to be equal to its upper bound, and t.relation imposes a total ordering on t.ordered + * that corresponds to the ordering of the atoms in this.bounds.universe. Then, m is updated with a binding + * from t to the constant formula TRUE. For each c in {c1...ck}, + * this.bounds is modified so that the upper bound for c.relation is a tupleset whose equivalent matrix + * has FALSE in the entries on or below the main diagonal. Then, m is updated with a binding from c to the + * constant formula TRUE.

+ * + *

The lossless symmetry breaking algorithm works as follows. Let t1...tn and c1...ck be the total ordering + * and acyclic predicates in m.keySet(). For each t in {t1...tn}, three fresh relations are added to this.bounds-- + * t_first, t_last, t_ordered, and t_order--and constrained as follows: t_first is the first atom + * in the upper bound of t.ordered, t_last is the last atom in the upper bound of t.ordered, t_ordered is + * the upper bound of t.ordered, and t_order imposes a total ordering on t.ordered that corresponds to the + * ordering of the atoms in this.bounds.universe. Then, m is updated with a binding from t to the formula + * "t.first = t_first and t.last = t_last and t.ordered = t_ordered and t.relation = t.order." + * For each c in {c1...ck}, a fresh relation c_acyclic is added to this.bounds and constrained to be a constant + * whose equivalent matrix has no entries on or below the main diagonal. The map m is then + * updated with a binding from c to the constraint "c in c_acyclic".

+ * + * @ensures this.bounds' is modified as described above + * @ensures this.symmetries' is modified to no longer contain the partitions that made up the bounds of + * the relations on which symmetries have been broken + * @return a map m such that m.keySet() in preds.values(), and for all predicates p in m.keySet(), the formulas + * "p and [[this.bounds]]" and "m.get(p) and [[this.bounds']]" are equisatisfiable + */ + Map breakMatrixSymmetries(Map> preds, boolean aggressive) { + final Set totals = preds.get(TOTAL_ORDERING); + final Set acyclics = preds.get(ACYCLIC); + final Map broken = new IdentityHashMap(); + + for(RelationPredicate.TotalOrdering pred : sort(totals.toArray(new RelationPredicate.TotalOrdering[totals.size()]))) { + Formula replacement = breakTotalOrder(pred,aggressive); + if (replacement!=null) + broken.put(pred, replacement); + } + + for(RelationPredicate.Acyclic pred : sort(acyclics.toArray(new RelationPredicate.Acyclic[acyclics.size()]))) { + Formula replacement = breakAcyclic(pred,aggressive); + if (replacement!=null) + broken.put(pred, replacement); + } + + return broken; + } + + /** + * Generates a lex leader symmetry breaking predicate for this.symmetries + * (if any), using the specified leaf interpreter and the specified predicate length. + * @requires interpreter.relations in this.bounds.relations + * @return a symmetry breaking predicate for this.symmetries + */ + final BooleanValue generateSBP(LeafInterpreter interpreter, int predLength) { + if (symmetries.isEmpty() || predLength==0) return BooleanConstant.TRUE; + + final List relParts = relParts(); + final BooleanFactory factory = interpreter.factory(); + final BooleanAccumulator sbp = BooleanAccumulator.treeGate(Operator.AND); + final List original = new ArrayList(predLength); + final List permuted = new ArrayList(predLength); + + for(IntSet sym : symmetries) { + + IntIterator indeces = sym.iterator(); + for(int prevIndex = indeces.next(); indeces.hasNext(); ) { + int curIndex = indeces.next(); + for(Iterator rIter = relParts.iterator(); rIter.hasNext() && original.size() < predLength;) { + + RelationParts rparts = rIter.next(); + Relation r = rparts.relation; + + if (!rparts.representatives.contains(sym.min())) continue; // r does not range over sym + + BooleanMatrix m = interpreter.interpret(r); + for(IndexedEntry entry : m) { + int permIndex = permutation(r.arity(), entry.index(), prevIndex, curIndex); + BooleanValue permValue = m.get(permIndex); + if (permIndex==entry.index() || atSameIndex(original, permValue, permuted, entry.value())) + continue; + + original.add(entry.value()); + permuted.add(permValue); + } + } + + sbp.add(leq(factory, original, permuted)); + original.clear(); + permuted.clear(); + prevIndex = curIndex; + } + } + + return factory.accumulate(sbp); + } + + /** + * Returns a list of RelationParts that map each non-constant r in this.bounds.relations to + * the representatives of the sets from this.symmetries contained in the upper bound of r. + * The entries are sorted by relations' arities and names. + * @return a list of RelationParts that contains an entry for each non-constant r in this.bounds.relations and + * the representatives of sets from this.symmetries contained in the upper bound of r. + */ + private List relParts() { + final List relParts = new ArrayList(bounds.relations().size()); + for(Relation r: bounds.relations()) { + IntSet upper = bounds.upperBound(r).indexView(); + if (upper.size()==bounds.lowerBound(r).size()) continue; // skip constant relation + IntSet reps = Ints.bestSet(usize); + for(IntIterator tuples = upper.iterator(); tuples.hasNext(); ) { + for(int tIndex = tuples.next(), i = r.arity(); i > 0; i--, tIndex /= usize) { + for(IntSet symm : symmetries) { + if (symm.contains(tIndex%usize)) { + reps.add(symm.min()); + break; + } + } + } + } + relParts.add(new RelationParts(r, reps)); + } + final Comparator cmp = new Comparator() { + public int compare(RelationParts o1, RelationParts o2) { + final int acmp = o1.relation.arity() - o2.relation.arity(); + return acmp!=0 ? acmp : String.valueOf(o1.relation.name()).compareTo(String.valueOf(o2.relation.name())); + } + }; + Collections.sort(relParts, cmp); + return relParts; + } + + /** + * Returns a BooleanValue that is true iff the string of bits + * represented by l0 is lexicographically less than or equal + * to the string of bits reprented by l1. + * @requires l0.size()==l1.size() + * @return a circuit that compares l0 and l1 + */ + private static final BooleanValue leq(BooleanFactory f, List l0, List l1) { + final BooleanAccumulator cmp = BooleanAccumulator.treeGate(Operator.AND); + BooleanValue prevEquals = BooleanConstant.TRUE; + for(int i = 0; i < l0.size(); i++) { + cmp.add(f.implies(prevEquals, f.implies(l0.get(i), l1.get(i)))); + prevEquals = f.and(prevEquals, f.iff(l0.get(i), l1.get(i))); + } + return f.accumulate(cmp); + } + + /** + * Let t be the tuple represent by the given arity and tupleIndex. + * This method returns the tuple index of the tuple t' such t' + * is equal to t with each occurence of atomIndex0 + * replaced by atomIndex1 and vice versa. + * @return the index of the tuple to which the given symmetry + * maps the tuple specified by arith and tupleIndex + */ + private final int permutation(int arity, int tupleIndex, int atomIndex0, int atomIndex1) { + int permIndex = 0; + for(int u = 1; arity > 0; arity--, tupleIndex /= usize, u *= usize ) { + int atomIndex = tupleIndex%usize; + if (atomIndex==atomIndex0) + permIndex += atomIndex1 * u; + else if (atomIndex==atomIndex1) { + permIndex += atomIndex0 * u; + } else { + permIndex += atomIndex * u; + } + } + return permIndex; + } + + /** + * Returns true if there is some index i such that l0[i] = v0 and l1[i] = v1. + * @requires l0.size()=l1.size() + * @return some i: int | l0[i] = v0 && l1[i] = v1 + */ + private static boolean atSameIndex(List l0, BooleanValue v0, List l1, BooleanValue v1) { + for(int i = 0; i < l0.size(); i++) { + if (l0.get(i).equals(v0) && l1.get(i).equals(v1)) + return true; + } + return false; + } + + /** + * Sorts the predicates in the given array in the ascending order of + * the names of the predicates' relations, and returns it. + * @return broken' + * @ensures all i: [0..preds.size()) | all j: [0..i) | + * broken[j].relation.name <= broken[i].relation.name + */ + private static final

P[] sort(final P[] preds) { + final Comparator cmp = new Comparator() { + public int compare(RelationPredicate o1, RelationPredicate o2) { + return String.valueOf(o1.relation().name()).compareTo(String.valueOf(o2.relation().name())); + } + }; + Arrays.sort(preds, cmp); + return preds; + } + + /** + * If possible, breaks symmetry on the given acyclic predicate and returns a formula + * f such that the meaning of acyclic with respect to this.bounds is equivalent to the + * meaning of f with respect to this.bounds'. If symmetry cannot be broken on the given predicate, returns null. + * + *

We break symmetry on the relation constrained by the given predicate iff + * this.bounds.upperBound[acyclic.relation] is the cross product of some partition in this.symmetries with + * itself. Assuming that this is the case, we then break symmetry on acyclic.relation using one of the methods + * described in {@linkplain #breakMatrixSymmetries(Map, boolean)}; the method used depends + * on the value of the "agressive" flag. + * The partition that formed the upper bound of acylic.relation is removed from this.symmetries.

+ * + * @return null if symmetry cannot be broken on acyclic; otherwise returns a formula + * f such that the meaning of acyclic with respect to this.bounds is equivalent to the + * meaning of f with respect to this.bounds' + * @ensures this.symmetries and this.bounds are modified as described in {@linkplain #breakMatrixSymmetries(Map, boolean)} iff this.bounds.upperBound[acyclic.relation] is the + * cross product of some partition in this.symmetries with itself + * + * @see #breakMatrixSymmetries(Map,boolean) + */ + private final Formula breakAcyclic(RelationPredicate.Acyclic acyclic, boolean aggressive) { + final IntSet[] colParts = symmetricColumnPartitions(acyclic.relation()); + if (colParts!=null) { + final Relation relation = acyclic.relation(); + final IntSet upper = bounds.upperBound(relation).indexView(); + final IntSet reduced = Ints.bestSet(usize*usize); + for(IntIterator tuples = upper.iterator(); tuples.hasNext(); ) { + int tuple = tuples.next(); + int mirror = (tuple / usize) + (tuple % usize)*usize; + if (tuple != mirror) { + if (!upper.contains(mirror)) return null; + if (!reduced.contains(mirror)) + reduced.add(tuple); + } + } + + // remove the partition from the set of symmetric partitions + removePartition(colParts[0].min()); + + if (aggressive) { + bounds.bound(relation, bounds.universe().factory().setOf(2, reduced)); + return Formula.TRUE; + } else { + final Relation acyclicConst = Relation.binary("SYM_BREAK_CONST_"+acyclic.relation().name()); + bounds.boundExactly(acyclicConst, bounds.universe().factory().setOf(2, reduced)); + return relation.in(acyclicConst); + } + } + return null; + } + + /** + * If possible, breaks symmetry on the given total ordering predicate and returns a formula + * f such that the meaning of total with respect to this.bounds is equivalent to the + * meaning of f with respect to this.bounds'. If symmetry cannot be broken on the given predicate, returns null. + * + *

We break symmetry on the relation constrained by the given predicate iff + * total.first, total.last, and total.ordered have the same upper bound, which, when + * cross-multiplied with itself gives the upper bound of total.relation. Assuming that this is the case, + * we then break symmetry on total.relation, total.first, total.last, and total.ordered using one of the methods + * described in {@linkplain #breakMatrixSymmetries(Map, boolean)}; the method used depends + * on the value of the "agressive" flag. + * The partition that formed the upper bound of total.ordered is removed from this.symmetries.

+ * + * @return null if symmetry cannot be broken on total; otherwise returns a formula + * f such that the meaning of total with respect to this.bounds is equivalent to the + * meaning of f with respect to this.bounds' + * @ensures this.symmetries and this.bounds are modified as desribed in {@linkplain #breakMatrixSymmetries(Map, boolean)} + * iff total.first, total.last, and total.ordered have the same upper bound, which, when + * cross-multiplied with itself gives the upper bound of total.relation + * + * @see #breakMatrixSymmetries(Map,boolean) + */ + private final Formula breakTotalOrder(RelationPredicate.TotalOrdering total, boolean aggressive) { + final Relation first = total.first(), last = total.last(), ordered = total.ordered(), relation = total.relation(); + final IntSet domain = bounds.upperBound(ordered).indexView(); + + if (symmetricColumnPartitions(ordered)!=null && + bounds.upperBound(first).indexView().contains(domain.min()) && + bounds.upperBound(last).indexView().contains(domain.max())) { + + // construct the natural ordering that corresponds to the ordering of the atoms in the universe + final IntSet ordering = Ints.bestSet(usize*usize); + int prev = domain.min(); + for(IntIterator atoms = domain.iterator(prev+1, usize); atoms.hasNext(); ) { + int next = atoms.next(); + ordering.add(prev*usize + next); + prev = next; + } + + if (ordering.containsAll(bounds.lowerBound(relation).indexView()) && + bounds.upperBound(relation).indexView().containsAll(ordering)) { + + // remove the ordered partition from the set of symmetric partitions + removePartition(domain.min()); + + final TupleFactory f = bounds.universe().factory(); + + if (aggressive) { + bounds.boundExactly(first, f.setOf(f.tuple(1, domain.min()))); + bounds.boundExactly(last, f.setOf(f.tuple(1, domain.max()))); + bounds.boundExactly(ordered, bounds.upperBound(total.ordered())); + bounds.boundExactly(relation, f.setOf(2, ordering)); + + return Formula.TRUE; + + } else { + final Relation firstConst = Relation.unary("SYM_BREAK_CONST_"+first.name()); + final Relation lastConst = Relation.unary("SYM_BREAK_CONST_"+last.name()); + final Relation ordConst = Relation.unary("SYM_BREAK_CONST_"+ordered.name()); + final Relation relConst = Relation.binary("SYM_BREAK_CONST_"+relation.name()); + bounds.boundExactly(firstConst, f.setOf(f.tuple(1, domain.min()))); + bounds.boundExactly(lastConst, f.setOf(f.tuple(1, domain.max()))); + bounds.boundExactly(ordConst, bounds.upperBound(total.ordered())); + bounds.boundExactly(relConst, f.setOf(2, ordering)); + + return Formula.and(first.eq(firstConst), last.eq(lastConst), ordered.eq(ordConst), relation.eq(relConst)); +// return first.eq(firstConst).and(last.eq(lastConst)).and( ordered.eq(ordConst)).and( relation.eq(relConst)); + } + + } + } + + return null; + } + + /** + * Removes from this.symmetries the partition that contains the specified atom. + * @ensures this.symmetries' = { s: this.symmetries | !s.contains(atom) } + */ + private final void removePartition(int atom) { + for(Iterator symIter = symmetries.iterator(); symIter.hasNext(); ) { + if (symIter.next().contains(atom)) { + symIter.remove(); + break; + } + } + } + + /** + * If all columns of the upper bound of r are symmetric partitions, + * those partitions are returned. Otherwise null is returned. + * @return (all i: [0..r.arity) | some s: symmetries[int] | + * bounds.upperBound[r].project(i).indexView() = s) => + * {colParts: [0..r.arity)->IntSet | + * all i: [0..r.arity()) | colParts[i] = bounds.upperBound[r].project(i).indexView() }, + * null + */ + private final IntSet[] symmetricColumnPartitions(Relation r) { + final IntSet upper = bounds.upperBound(r).indexView(); + if (upper.isEmpty()) return null; + + final IntSet[] colParts = new IntSet[r.arity()]; + for(int i = r.arity()-1, min = upper.min(); i >= 0; i--, min /= usize) { + for(IntSet part : symmetries) { + if (part.contains(min%usize)) { + colParts[i] = part; + break; + } + } + if (colParts[i]==null) + return null; + } + for(IntIterator tuples = upper.iterator(); tuples.hasNext(); ) { + for(int i = r.arity()-1, tuple = tuples.next(); i >= 0; i--, tuple /= usize) { + if (!colParts[i].contains(tuple%usize)) + return null; + } + } + return colParts; + } + + /** + * An entry for a relation and the representative (least atom) for each + * symmetry class in the relation's upper bound. + */ + private static final class RelationParts { + final Relation relation; + final IntSet representatives; + + RelationParts(Relation relation, IntSet representatives) { + this.relation = relation; + this.representatives = representatives; + } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/SymmetryDetector.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/SymmetryDetector.java new file mode 100644 index 00000000..5658d650 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/SymmetryDetector.java @@ -0,0 +1,244 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Set; + +import kodkod.ast.Relation; +import kodkod.instance.Bounds; +import kodkod.instance.TupleSet; +import kodkod.util.ints.IntIterator; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.Ints; + +/** + * Partitions a universe into equivalence classes based + * on the bounding constraints given by a Bounds object. + * @specfield bounds: Bounds // bounds on which the partitioning is based + * @author Emina Torlak + */ +final class SymmetryDetector { + private final Bounds bounds; + /* invariant: representatives always holds a sequence of IntSets that partition bounds.universe */ + private final List parts; + private final int usize; + + /** + * Constructs a new SymmetryDetector for the given bounds. + * @ensures this.bounds' = bounds + */ + private SymmetryDetector(Bounds bounds) { + this.bounds = bounds; + this.usize = bounds.universe().size(); + + // start with the maximum partition -- the whole universe. + this.parts = new LinkedList(); + final IntSet set = Ints.bestSet(usize); + for(int i = 0; i < usize; i++) { set.add(i); } + this.parts.add(set); + } + + /** + * Returns a sound partitioning of bounds.universe + * into symmetry classes. Each intset in the returned + * collection represents the indices of the atoms in + * this.bounds.universe that belong to the same equivalence class. + * @return a sound partitioning of bounds.universe + * into symmetry classes + */ + static Set partition(Bounds bounds) { + final SymmetryDetector detector = new SymmetryDetector(bounds); + detector.computePartitions(); + final Set parts = new LinkedHashSet(detector.parts); + assert parts.size()==detector.parts.size(); // sanity check + return parts; + } + + + /** + * Partitions this.bounds.universe into sets of equivalent atoms. + * @ensures all disj s, q: this.parts'[int] | + * some s.ints && some q.ints && (no s.ints & q.ints) && + * this.parts'[int].ints = [0..this.bounds.universe.size()) && + * (all ts: this.bounds.lowerBound[Relation] + this.bounds.upperBound[Relation] | + * all s: this.parts'[int] | all a1, a2: this.bounds.universe.atoms[s.ints] | + * all t1, t2: ts.tuples | t1.atoms[0] = a1 && t2.atoms[0] = a2 => + * t1.atoms[1..ts.arity) = t1.atoms[1..ts.arity) || + * t1.atoms[1..ts.arity) = a1 && t1.atoms[1..ts.arity) = a2) + */ + private final void computePartitions() { + if (usize==1) return; // nothing more to do + + final Map range2domain = new HashMap((usize*2) / 3); + + // refine the partitions based on the bounds for each integer + for(IntIterator iter = bounds.ints().iterator(); iter.hasNext();) { + TupleSet exact = bounds.exactBound(iter.next()); + refinePartitions(exact.indexView(), 1, range2domain); + } + + // refine the partitions based on the upper/lower bounds for each relation + for(TupleSet s : sort(bounds)) { + if (parts.size()==usize) return; + refinePartitions(s.indexView(), s.arity(), range2domain); + } + + } + + /** + * Returns an array that contains unique non-empty tuplesets in the given bounds, + * sorted in the order of increasing size. + * @return unique non-empty tuplesets in the given bounds, + * sorted in the order of increasing size. + */ + private static TupleSet[] sort(Bounds bounds) { + final List sets = new ArrayList(bounds.relations().size()); + for(Relation r : bounds.relations()) { + final TupleSet lower = bounds.lowerBound(r); + final TupleSet upper = bounds.upperBound(r); + if (!lower.isEmpty() && lower.size()(){ + public int compare(TupleSet o1, TupleSet o2) { + return o1.size() - o2.size(); + } + }); + return sorted; + } + + /** + * Refines the atomic partitions in this.parts based on the contents of the given tupleset, + * decomposed into its constituent IntSet and arity. The range2domain map is used for + * intermediate computations for efficiency (to avoid allocating it in each recursive call). + * @requires all disj s, q: this.parts[int] | + * some s.ints && some q.ints && (no s.ints & q.ints) && + * this.parts[int].ints = [0..this.bounds.universe.size()) + * @ensures let usize = this.bounds.universe.size(), firstColFactor = usize^(arit-1) | + * all disj s, q: this.parts'[int] | + * some s.ints && some q.ints && (no s.ints & q.ints) && + * this.parts'[int].ints = [0..usize) && + * all s: this.parts'[int] | all a1, a2: this.bounds.universe.atoms[s.ints] | + * all t1, t2: set.ints | t1 / firstColFactor = a1 && t2 / firstColFactor = a2 => + * t1 % firstColFactor = t2 % firstColFactor || + * t1 = a1*((1 - firstColFactor) / (1 - usize)) && + * t2 = a2*((1 - firstColFactor) / (1 - usize))) + */ + private void refinePartitions(IntSet set, int arity, Map range2domain) { + if (arity==1) { + refinePartitions(set); + return; + } + + final List otherColumns = new LinkedList(); + int firstColFactor = (int) StrictMath.pow(usize, arity-1); + IntSet firstCol = Ints.bestSet(usize); + for(IntIterator rbIter = set.iterator(); rbIter.hasNext(); ) { + firstCol.add(rbIter.next() / firstColFactor); + } + refinePartitions(firstCol); + + int idenFactor = (1 - firstColFactor) / (1 - usize); + for(ListIterator partsIter = parts.listIterator(); partsIter.hasNext(); ) { + IntSet part = partsIter.next(); + if (firstCol.contains(part.min())) { // contains one, contains them all + range2domain.clear(); + for(IntIterator atoms = part.iterator(); atoms.hasNext(); ) { + int atom = atoms.next(); + IntSet atomRange = Ints.bestSet(firstColFactor); + for(IntIterator rbIter = set.iterator(atom*firstColFactor, (atom+1)*firstColFactor - 1); + rbIter.hasNext(); ) { + atomRange.add(rbIter.next() % firstColFactor); + } + IntSet atomDomain = range2domain.get(atomRange); + if (atomDomain != null) atomDomain.add(atom); + else range2domain.put(atomRange, oneOf(usize, atom)); + } + partsIter.remove(); + IntSet idenPartition = Ints.bestSet(usize); + for(Map.Entry entry : range2domain.entrySet()) { + if (entry.getValue().size()==1 && entry.getKey().size()==1 && + entry.getKey().min() == entry.getValue().min() * idenFactor) { + idenPartition.add(entry.getValue().min()); + } else { + partsIter.add(entry.getValue()); + otherColumns.add(entry.getKey()); + } + } + if (!idenPartition.isEmpty()) + partsIter.add(idenPartition); + } + } + + // refine based on the remaining columns + for(IntSet otherCol : otherColumns) { + refinePartitions(otherCol, arity-1, range2domain); + } + } + + /** + * Refines the atomic partitions this.parts based on the contents of the given set. + * @requires all disj s, q: this.parts[int] | + * some s.ints && some q.ints && (no s.ints & q.ints) && + * this.parts[int].ints = [0..this.bounds.universe.size()) + * @ensures all disj s, q: this.parts'[int] | + * some s.ints && some q.ints && (no s.ints & q.ints) && + * this.parts'[int].ints = [0..this.bounds.universe.size()) && + * (all i: [0..this.parts'.size()) | + * this.parts'[i].ints in set.ints || no this.parts'[i].ints & set.ints) + */ + private void refinePartitions(IntSet set) { + for(ListIterator partsIter = parts.listIterator(); partsIter.hasNext(); ) { + IntSet part = partsIter.next(); + IntSet intersection = Ints.bestSet(part.min(), part.max()); + intersection.addAll(part); + intersection.retainAll(set); + if (!intersection.isEmpty() && intersection.size() < part.size()) { + part.removeAll(intersection); + partsIter.add(intersection); + } + } + } + + /** + * Returns an IntSet that can store elements + * in the range [0..size), and that holds + * the given number. + * @requries 0 <= num < size + * @return {s: IntSet | s.ints = num } + */ + private static final IntSet oneOf(int size, int num) { + final IntSet set = Ints.bestSet(size); + set.add(num); + return set; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/Translation.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/Translation.java new file mode 100644 index 00000000..e59cb1e3 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/Translation.java @@ -0,0 +1,152 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import java.util.Map; + +import kodkod.ast.Relation; +import kodkod.engine.satlab.SATSolver; +import kodkod.instance.Bounds; +import kodkod.instance.Instance; +import kodkod.instance.TupleFactory; +import kodkod.instance.TupleSet; +import kodkod.util.ints.IntIterator; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.Ints; + +/** + * Stores the translation of a {@link kodkod.ast.Formula kodkod formula} + * to CNF. + * + * @specfield formula: Formula // the formula that was translated + * @specfield bounds: Bounds // the bounds used to obtain the CNF from the formula + * @specfield solver: SATSolver // a SATSolver containing the CNF representation of the formula + * @specfield options: Options // the options object used to control translation parameters + * @author Emina Torlak + */ +public final class Translation { + private final Bounds bounds; + private final SATSolver solver; + /* maps relations to the literals that comprise their translations */ + private final Map primaryVarUsage; + private final TranslationLog log; + private final int maxPrimaryLit; + + /** + * Constructs a new Translation object for the given solver, bounds, mapping + * from Relations to literals, and TranslationLog. + * @requires maxPrimaryLit = max(varUsage[Relation].max) + * @requires bounds.relations = varUsage.IntSet + * @ensures this.solver' = solver && this.bounds' = bounds + */ + Translation(SATSolver solver, Bounds bounds, Map varUsage, int maxPrimaryLit, TranslationLog log) { + this.solver = solver; + this.bounds = bounds; + this.primaryVarUsage = varUsage; + this.maxPrimaryLit = maxPrimaryLit; + this.log = log; + } + + /** + * Returns a SATSolver object initialized with the CNF encoding of this.formula + * and the timeout and random seed values specified by this.options. Satisfiability + * of the formula can be checked by calling {@link kodkod.engine.satlab.SATSolver#solve()}. + * @return {s: SATSolver | [[s.clauses]] = [[this.formula]] && s.timeout() = this.options.timeout() && + * s.seed() = this.options.seed() } + */ + public SATSolver cnf() { + return solver; + } + + /** + * If this.solver.solve() is true, returns + * an interpretation of the cnf solution as a + * mapping from Relations to sets of Tuples. The Relations + * mapped by the returned instance are either leaves + * of this.formula with different lower and upper + * bounds (i.e. {r: this.formula.*children & Relation | + * this.bounds.upperBound[r] != this.bounds.lowerBound[r]}), + * or skolem constants. + * @return an interpretation of the cnf solution as + * a mapping from (this.variableUsage().keySet() & Relation) to sets of Tuples. + * @throws IllegalStateException - this.solver.solve() has not been called or the + * outcome of the last call was not true. + */ + public Instance interpret() { + final TupleFactory f = bounds.universe().factory(); + final Instance instance = new Instance(bounds.universe()); +// System.out.println(varUsage); + for(Relation r : bounds.relations()) { + TupleSet lower = bounds.lowerBound(r); + IntSet indeces = Ints.bestSet(lower.capacity()); + indeces.addAll(lower.indexView()); + IntSet vars = primaryVarUsage.get(r); + if (vars!=null) { + int lit = vars.min(); + for(IntIterator iter = bounds.upperBound(r).indexView().iterator(); iter.hasNext();) { + final int index = iter.next(); + if (!indeces.contains(index) && solver.valueOf(lit++)) + indeces.add(index); + } + } + instance.add(r, f.setOf(r.arity(), indeces)); + } + return instance; + } + + /** + * Returns the set of primary variable literals that represent + * the tuples in the given relation. If no literals were allocated + * to the given relation, null is returned. + * @return the set of primary variable literals that represent + * the tuples in the given relation. + */ + public IntSet primaryVariables(Relation relation) { + return primaryVarUsage.get(relation); + } + + /** + * Returns the number of primary variables allocated + * during translation. Primary variables represent + * the tuples of Relations that are either leaves + * of this.formula with different lower and upper + * bounds (i.e. {r: this.formula.*children & Relation | + * this.bounds.upperBound[r] != this.bounds.lowerBound[r]}), + * or skolem constants. + * @return the number of primary variables allocated + * during translation. + */ + public int numPrimaryVariables() { + return maxPrimaryLit; + } + + /** + * If this.options.logTranslation was set to true, returns the log of the + * translation that produced this Translation object. Otherwise returns null. + * @return the log of the translation that produced this Translation + * object, if this.options.logTranslation was enabled during translation, or null if not. + */ + public TranslationLog log() { + return log; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/TranslationLog.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/TranslationLog.java new file mode 100644 index 00000000..69f1cd49 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/TranslationLog.java @@ -0,0 +1,114 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import java.util.Iterator; +import java.util.Set; + +import kodkod.ast.Formula; +import kodkod.engine.Solver; +import kodkod.engine.config.Options; +import kodkod.instance.Bounds; + +/** + * A log of the translations of the descendants of a given formula that + * are either formulas or that desugar to formulas. + * @specfield originalFormula: Formula // the {@linkplain Solver#solve(Formula, kodkod.instance.Bounds) original} formula, provided by the user + * @specfield originalBounds: Bounds // the {@linkplain Solver#solve(Formula, kodkod.instance.Bounds) original} bounds, provided by the user + * @specfield formula: Formula // desugaring of this.formula that was translated + * @specfield bounds: Bounds // translation bounds + * @specfield records: set TranslationRecord + * @specfield replay: [0..#records) one->one records // replay order -- i.e. the order in the which records were added to the log + * @invariant all r: records | r.node in formula.*children + * @invariant Solver.solve(formula, bounds).instance() == null iff Solver.solve(originalFormula, originalBounds).instance() == null + * @author Emina Torlak + */ +public abstract class TranslationLog { + TranslationLog() {} + + /** + * Returns the roots of this.formula. In other words, returns the subformulas, {f0, ..., fk}, + * of this.formula such that, for all 0<=i<=k, fi [[f0 && ... && fk]] <=> [[formula]]. + * The granularity of the subdivision of this.formula into roots depends on the core granularity + * specified in the {@linkplain Options} that were used when translating this.formula. + * + *

Unless a given root translates to a constant, the highest magnitude literal corresponding to + * each root (as given by this.records) is guaranteed to be present in the translation of this.formula + * as a unit clause. All the remaining clauses (except those comprising the symmetry + * breaking predicate, encoded with its own unit clause containing the maximum literal) + * that are reachable from such a unit clause represent the translations + * of the given root's descendants. We define reachability over the clauses in a translation + * as follows: let l1 be the highest magnitude literal in the clause c1, and let l2 be the + * highest magnitude literal in c2. If l2 occurs in c1 (in any polarity), then there is + * an edge from c1 and c2. The unit clauses are always the last clauses to be added to a SAT solver + * during translation.

+ * + * @return roots of this.formula + */ + public abstract Set roots(); + + /** + * Returns this.bounds. + * @return this.bounds. + */ + public abstract Bounds bounds(); + + /** + * Returns an iterator over the translation records in this log that are accepted + * by the given filter. The iterator returns the records in the order in which + * they were generated. This guarantees that records for the descendants of a + * node are always returned before the record for the node itself. + * + *

Note:The record objects returned by the iterator are not + * required to be immutable. In particular, the state of a record object + * returned by next() is guaranteed to remain the same only until the + * subsequent call to next().

+ * @return an iterator, in the proper replay sequence, over the translation records + * in this log that are accepted by the given filter. + */ + public abstract Iterator replay(RecordFilter filter); + + /** + * Returns an iterator over all translation records in this log. The iterator returns + * the records in the order in which they were generated. This guarantees that records for + * the descendants of a node are always returned before the record for the node itself. + * The effect of this method is the same as calling {@linkplain #replay(RecordFilter) replay(RecordFilter.ALL)}. + * + *

Note:The record objects returned by the iterator are not + * required to be immutable. In particular, the state of a record object + * returned by next() is guaranteed to remain the same only until the + * subsequent call to next().

+ * @return an iterator over all translation records in this.log, in the proper replay sequence. + * @see #replay(RecordFilter) + */ + public final Iterator replay() { + return replay(RecordFilter.ALL); + } + +// /** +// * Compresses this translation log (optional operation) by eliminating +// * redundant records. +// * @ensures all r: this.records | one r': this.records' | r.node = r'.node && r.literal = r'.literal && r.env.equals(r'.env) +// * @throws UnsupportedOperationException - this log does not support compression +// */ +// public abstract void compress(); +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/TranslationLogger.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/TranslationLogger.java new file mode 100644 index 00000000..2b239637 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/TranslationLogger.java @@ -0,0 +1,66 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import kodkod.ast.Expression; +import kodkod.ast.Formula; +import kodkod.engine.Solver; +import kodkod.engine.bool.BooleanMatrix; +import kodkod.engine.bool.BooleanValue; + +/** + * Logs the translations of all descendants of a user-provided formula that + * are either formulas or that desugar to formulas. + * @specfield originalFormula: Formula // the {@linkplain Solver#solve(Formula, kodkod.instance.Bounds) original} formula, provided by the user + * @specfield originalBounds: Bounds // the {@linkplain Solver#solve(Formula, kodkod.instance.Bounds) original} bounds, provided by the user + * @specfield formula: Formula // desugaring of this.formula that was translated + * @specfield bounds: Bounds // translation bounds + * @specfield records: (formula.*children & Formula) -> BooleanValue -> Environment + * @invariant Solver.solve(formula, bounds).instance() == null iff Solver.solve(originalFormula, originalBounds).instance() == null + * @author Emina Torlak + */ +abstract class TranslationLogger { + + /** + * Optionally records the translation of the source of the + * given transformed formula to the given boolean value + * in the specified environment. + * @requires f in this.formula.*children + * @ensures this.records' = this.records or this.records' = this.records + f -> translation -> freeVariables(f)<:env + * @throws IllegalArgumentException - some aspect of the given translation event prevents it from being logged + * @throws IllegalStateException - this log has been closed + */ + abstract void log(Formula f, BooleanValue translation, Environment env); + + /** + * Closes this logger and releases associated resources. Attempts to call {@link #log(Formula, BooleanValue, Environment)} + * after the log has been closed may result in an IllegalStateException. + * @ensures closes this logger and releases associated resources. + */ + abstract void close(); + + /** + * Returns a TranslationLog view of this.records. + * @return a TranslationLog view of this.records. + */ + abstract TranslationLog log(); +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/TranslationRecord.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/TranslationRecord.java new file mode 100644 index 00000000..ef8c184b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/TranslationRecord.java @@ -0,0 +1,87 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import java.util.Map; + +import kodkod.ast.Formula; +import kodkod.ast.Node; +import kodkod.ast.Variable; +import kodkod.instance.TupleSet; + +/** + * Record of a translation event. Each translation event is described by four pieces of information: + *
    + *
  1. the {@linkplain Formula formula} that was translated;
  2. + *
  3. the {@linkplain Node node} from which the translated formula was derived by skolemization or through some other optimization;
  4. + *
  5. the environment in which the given formula is translated, given as a binding of free variables to scalars (singleton, unary tuplesets);
  6. + *
  7. the CNF literal, expressed as an integer, that represents the meaning of the given formula in the given environment.
  8. + *
+ * + * @specfield node: Node // node that was transformed to this.translated + * @specfield translated: Formula // the translated formula obtain from this.node + * @specfield literal: int // cnf literal representing the meaning of this.node in this.env + * @specfield env: Variable ->one TupleSet // bindings for free, non-skolemized variables + * // for which this.node (or its desugared form) evaluates to this.literal + * @author Emina Torlak + */ +public abstract class TranslationRecord { + + /** + * Returns this.node. + * @return this.node. + */ + public abstract Node node(); + + /** + * Returns this.translated. + * @return this.translated + */ + public abstract Formula translated(); + + /** + * Returns this.literal. + * @return this.literal + */ + public abstract int literal(); + + /** + * Returns a map view of this.env. + * @return this.env + */ + public abstract Map env(); + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + final StringBuilder ret = new StringBuilder(); + ret.append("< node: "); + ret.append(node()); + ret.append(", literal: "); + ret.append(literal()); + ret.append(", env: "); + ret.append(env()); + ret.append(">"); + return ret.toString(); + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/Translator.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/Translator.java new file mode 100644 index 00000000..ecdd391d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/Translator.java @@ -0,0 +1,430 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import static kodkod.util.nodes.AnnotatedNode.annotate; +import static kodkod.util.nodes.AnnotatedNode.annotateRoots; + +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.Set; + +import kodkod.ast.Expression; +import kodkod.ast.Formula; +import kodkod.ast.IntExpression; +import kodkod.ast.Node; +import kodkod.ast.Relation; +import kodkod.ast.RelationPredicate; +import kodkod.ast.visitor.AbstractReplacer; +import kodkod.engine.bool.BooleanAccumulator; +import kodkod.engine.bool.BooleanConstant; +import kodkod.engine.bool.BooleanFactory; +import kodkod.engine.bool.BooleanFormula; +import kodkod.engine.bool.BooleanMatrix; +import kodkod.engine.bool.BooleanValue; +import kodkod.engine.bool.Int; +import kodkod.engine.bool.Operator; +import kodkod.engine.config.Options; +import kodkod.engine.satlab.SATSolver; +import kodkod.instance.Bounds; +import kodkod.instance.Instance; +import kodkod.util.ints.IntSet; +import kodkod.util.nodes.AnnotatedNode; + +/** + * Translates, evaluates, and approximates {@link Node nodes} with + * respect to given {@link Bounds bounds} (or {@link Instance instances}) and {@link Options}. + * + * @author Emina Torlak + */ +public final class Translator { + + /*---------------------- public methods ----------------------*/ + /** + * Overapproximates the value of the given expression using the provided bounds and options. + * @return a BooleanMatrix whose TRUE entries represent the tuples contained in a sound overapproximation + * of the expression. + * @throws expression = null || instance = null || options = null + * @throws UnboundLeafException - the expression refers to an undeclared variable or a relation not mapped by the instance + * @throws HigherOrderDeclException - the expression contains a higher order declaration + */ + public static BooleanMatrix approximate(Expression expression, Bounds bounds, Options options) { + Environment emptyEnv = Environment.empty(); + return FOL2BoolTranslator.approximate(annotate(expression), LeafInterpreter.overapproximating(bounds, options), emptyEnv); + } + + /** + * Evaluates the given formula to a BooleanConstant using the provided instance and options. + * + * @return a BooleanConstant that represents the value of the formula. + * @throws NullPointerException - formula = null || instance = null || options = null + * @throws UnboundLeafException - the formula refers to an undeclared variable or a relation not mapped by the instance + * @throws HigherOrderDeclException - the formula contains a higher order declaration + */ + public static BooleanConstant evaluate(Formula formula, Instance instance, Options options) { + final LeafInterpreter interpreter = LeafInterpreter.exact(instance, options); + final BooleanConstant eval = (BooleanConstant) FOL2BoolTranslator.translate(annotate(formula), interpreter); + //TODO: check OF +// final BooleanFactory factory = interpreter.factory(); +// BooleanConstant overflow = (BooleanConstant) factory.of(); +// if (options.noOverflow() && overflow.booleanValue()) { //[AM] +// eval = BooleanConstant.FALSE; +// } + return eval; + } + + /** + * Evaluates the given expression to a BooleanMatrix using the provided instance and options. + * + * @return a BooleanMatrix whose TRUE entries represent the tuples contained by the expression. + * @throws NullPointerException - expression = null || instance = null || options = null + * @throws UnboundLeafException - the expression refers to an undeclared variable or a relation not mapped by the instance + * @throws HigherOrderDeclException - the expression contains a higher order declaration + */ + public static BooleanMatrix evaluate(Expression expression,Instance instance, Options options) { + return (BooleanMatrix) FOL2BoolTranslator.translate(annotate(expression), LeafInterpreter.exact(instance, options)); + } + + /** + * Evalutes the given intexpression to an {@link kodkod.engine.bool.Int} using the provided instance and options. + * @return an {@link kodkod.engine.bool.Int} representing the value of the intExpr with respect + * to the specified instance and options. + * @throws NullPointerException - formula = null || instance = null || options = null + * @throws UnboundLeafException - the expression refers to an undeclared variable or a relation not mapped by the instance + * @throws HigherOrderDeclException - the expression contains a higher order declaration + */ + public static Int evaluate(IntExpression intExpr, Instance instance, Options options) { + LeafInterpreter interpreter = LeafInterpreter.exact(instance, options); + Int ret = (Int) FOL2BoolTranslator.translate(annotate(intExpr), interpreter); + //TODO: check OF +// BooleanFactory factory = interpreter.factory(); +// BooleanConstant bc = (BooleanConstant) factory.of(); +// boolean overflow = false; +// if (options.noOverflow() && bc.booleanValue()) //[AM] +// overflow = true; +// ret.setOverflowFlag(overflow); + return ret; + } + + /** + * Translates the given formula using the specified bounds and options. + * @return a Translation whose solver is a SATSolver instance initialized with the + * CNF representation of the given formula, with respect to the given bounds. The CNF + * is generated in such a way that the magnitude of the literal representing the truth + * value of a given formula is strictly larger than the magnitudes of the literals representing + * the truth values of the formula's descendants. + * @throws TrivialFormulaException - the given formula is reduced to a constant during translation + * (i.e. the formula is trivially (un)satisfiable). + * @throws NullPointerException - any of the arguments are null + * @throws UnboundLeafException - the formula refers to an undeclared variable or a relation not mapped by the given bounds. + * @throws HigherOrderDeclException - the formula contains a higher order declaration that cannot + * be skolemized, or it can be skolemized but options.skolemize is false. + */ + public static Translation translate(Formula formula, Bounds bounds, Options options) throws TrivialFormulaException { + return (new Translator(formula,bounds,options)).translate(); + } + + /*---------------------- private translation state and methods ----------------------*/ + /** + * @specfield formula: Formula + * @specfield bounds: Bounds + * @specfield options: Options + * @specfield log: TranslationLog + */ + private final Formula formula; + private final Bounds bounds; + private final Options options; + + private TranslationLog log; + + /** + * Constructs a Translator for the given formula, bounds and options. + * @ensures this.formula' = formula and + * this.options' = options and + * this.bounds' = bounds.clone() and + * no this.log' + */ + private Translator(Formula formula, Bounds bounds, Options options) { + this.formula = formula; + this.bounds = bounds.clone(); + this.options = options; + this.log = null; + } + + /** + * Translates this.formula with respect to this.bounds and this.options. + * @return a Translation whose solver is a SATSolver instance initialized with the + * CNF representation of the given formula, with respect to the given bounds. The CNF + * is generated in such a way that the magnitude of a literal representing the truth + * value of a given formula is strictly larger than the magnitudes of the literals representing + * the truth values of the formula's descendants. + * @throws TrivialFormulaException - this.formula is reduced to a constant during translation + * (i.e. the formula is trivially (un)satisfiable). + * @throws UnboundLeafException - this.formula refers to an undeclared variable or a relation not mapped by this.bounds. + * @throws HigherOrderDeclException - this.formula contains a higher order declaration that cannot + * be skolemized, or it can be skolemized but this.options.skolemDepth < 0 + */ + private Translation translate() throws TrivialFormulaException { + final AnnotatedNode annotated = options.logTranslation()>0 ? annotateRoots(formula) : annotate(formula); + final SymmetryBreaker breaker = optimizeBounds(annotated); + return toBoolean(optimizeFormula(annotated, breaker), breaker); + } + + /** + * Removes bindings for unused relations/ints from this.bounds and + * returns a SymmetryBreaker for the reduced bounds. + * @requires annotated.node = this.formula + * @ensures this.bounds'.relations = this.formula.*children & Relations + * @ensures !annotated.usesInts() => no this.bounds'.int + * @return { b: SymmetryBreaker | b.bounds = this.bounds' } + */ + private SymmetryBreaker optimizeBounds(AnnotatedNode annotated) { + // remove bindings for unused relations/ints + bounds.relations().retainAll(annotated.relations()); + if (!annotated.usesInts()) bounds.ints().clear(); + + // detect symmetries + return new SymmetryBreaker(bounds, options.reporter()); + } + + /** + * Optimizes annotated.node by first breaking symmetries on its top-level predicates, + * replacing them with the simpler formulas generated by {@linkplain SymmetryBreaker#breakMatrixSymmetries(Map, boolean) breaker.breakMatrixSymmetries(...)}, + * and skolemizing the result. + * @requires annotated.node = this.formula + * @requires breaker.bounds = this.bounds + * @return the skolemization, up to depth this.options.skolemDepth, of annotated.node with + * the broken predicates replaced with simpler constraints and the remaining predicates inlined. + */ + private AnnotatedNode optimizeFormula(AnnotatedNode annotated, SymmetryBreaker breaker) { + options.reporter().optimizingBoundsAndFormula(); + if (options.logTranslation()==0) { // no logging + annotated = inlinePredicates(annotated, breaker.breakMatrixSymmetries(annotated.predicates(), true).keySet()); + annotated = options.skolemDepth()>=0 ? Skolemizer.skolemize(annotated, bounds, options) : annotated; +// if (options.noOverflow()) { +// annotated = NNFConverter.flatten(annotated); // FullNegationPropagator.flatten(annotated); +// } + return annotated; + } else { + // logging; inlining of predicates *must* happen last when logging is enabled + if (options.coreGranularity()==1) { + annotated = FormulaFlattener.flatten(annotated, false); + } + if (options.skolemDepth()>=0) { + annotated = Skolemizer.skolemize(annotated, bounds, options); + } + if (options.coreGranularity()>1) { + annotated = FormulaFlattener.flatten(annotated, options.coreGranularity()==3); + } +// if (options.noOverflow()) { +// annotated = NNFConverter.flatten(annotated); //FullNegationPropagator.flatten(annotated); +// } + return inlinePredicates(annotated, breaker.breakMatrixSymmetries(annotated.predicates(), false)); + } + } + + /** + * Returns an annotated formula f such that f.node is equivalent to annotated.node + * with its truePreds replaced with the constant formula TRUE and the remaining + * predicates replaced with equivalent constraints. + * @requires this.options.logTranslation = false + * @requires truePreds in annotated.predicates()[RelationnPredicate.NAME] + * @requires truePreds are trivially true with respect to this.bounds + * @return an annotated formula f such that f.node is equivalent to annotated.node + * with its truePreds replaced with the constant formula TRUE and the remaining + * predicates replaced with equivalent constraints. + */ + private AnnotatedNode inlinePredicates(final AnnotatedNode annotated, final Set truePreds) { + final AbstractReplacer inliner = new AbstractReplacer(annotated.sharedNodes()) { + public Formula visit(RelationPredicate pred) { + Formula ret = lookup(pred); + if (ret!=null) return ret; + return truePreds.contains(pred) ? cache(pred, Formula.TRUE) : cache(pred, pred.toConstraints()); + } + }; + return annotate(annotated.node().accept(inliner)); + } + + /** + * Returns an annotated formula f such that f.node is equivalent to annotated.node + * with its simplified predicates replaced with their corresponding Formulas and the remaining + * predicates replaced with equivalent constraints. The annotated formula f will contain transitive source + * information for each of the subformulas of f.node. Specifically, let t be a subformula of f.node, and + * s be a descdendent of annotated.node from which t was derived. Then, f.source[t] = annotated.source[s].

+ * @requires this.options.logTranslation = true + * @requires simplified.keySet() in annotated.predicates()[RelationPredicate.NAME] + * @requires no disj p, p': simplified.keySet() | simplified.get(p) = simplifed.get(p') // this must hold in order + * to maintain the invariant that each subformula of the returned formula has exactly one source + * @requires for each p in simplified.keySet(), the formulas "p and [[this.bounds]]" and + * "simplified.get(p) and [[this.bounds]]" are equisatisfiable + * @return an annotated formula f such that f.node is equivalent to annotated.node + * with its simplified predicates replaced with their corresponding Formulas and the remaining + * predicates replaced with equivalent constraints. + */ + private AnnotatedNode inlinePredicates(final AnnotatedNode annotated, final Map simplified) { + final Map sources = new IdentityHashMap(); + final AbstractReplacer inliner = new AbstractReplacer(annotated.sharedNodes()) { + private RelationPredicate source = null; + protected N cache(N node, N replacement) { + if (replacement instanceof Formula) { + if (source==null) { + final Node nsource = annotated.sourceOf(node); + if (replacement!=nsource) + sources.put(replacement, nsource); + } else { + sources.put(replacement, source); + } + } + return super.cache(node, replacement); + } + public Formula visit(RelationPredicate pred) { + Formula ret = lookup(pred); + if (ret!=null) return ret; + source = pred; + if (simplified.containsKey(pred)) { + ret = simplified.get(pred).accept(this); + } else { + ret = pred.toConstraints().accept(this); + } + source = null; + return cache(pred, ret); + } + }; + + return annotate(annotated.node().accept(inliner), sources); + } + + /** + * Translates the given annotated formula to a circuit, conjoins the circuit with an + * SBP generated by the given symmetry breaker, flattens the result if so specified by this.options, + * and returns its Translation to CNF. + * @requires [[annotated.node]] <=> ([[this.formula]] and [[breaker.broken]]) + * @ensures this.options.logTranslation => some this.log' + * @return the result of calling {@link #generateSBP(BooleanFormula, LeafInterpreter, SymmetryBreaker)} + * on the translation of annotated.node with respect to this.bounds + * @throws TrivialFormulaException - the translation of annotated is a constant or can be made into + * a constant by flattening + */ + private Translation toBoolean(AnnotatedNode annotated, SymmetryBreaker breaker) throws TrivialFormulaException { + + options.reporter().translatingToBoolean(annotated.node(), bounds); + + final LeafInterpreter interpreter = LeafInterpreter.exact(bounds, options); + //final BooleanFactory factory = interpreter.factory(); + + if (options.logTranslation()>0) { + final TranslationLogger logger = options.logTranslation()==1 ? new MemoryLogger(annotated, bounds) : new FileLogger(annotated, bounds); + BooleanAccumulator circuit = FOL2BoolTranslator.translate(annotated, interpreter, logger); + log = logger.log(); + if (circuit.isShortCircuited()) { + throw new TrivialFormulaException(annotated.node(), bounds, circuit.op().shortCircuit(), log); + } else if (circuit.size()==0) { + throw new TrivialFormulaException(annotated.node(), bounds, circuit.op().identity(), log); + } + return generateSBP(circuit, interpreter, breaker); + } else { + BooleanValue circuit = (BooleanValue)FOL2BoolTranslator.translate(annotated, interpreter); + if (circuit.op()==Operator.CONST) { + throw new TrivialFormulaException(annotated.node(), bounds, (BooleanConstant)circuit, null); + } + return generateSBP(annotated, (BooleanFormula)circuit, interpreter, breaker); + } + } + + /** + * Adds to given accumulator an SBP generated using the given symmetry breaker and interpreter, + * and returns the resulting circuit's translation to CNF. + * @requires circuit is a translation of this.formula with respect to this.bounds + * @requires interpreter is the leaf interpreter used in generating the given circuit + * @requires breaker.bounds = this.bounds + * @return toCNF(circuit && breaker.generateSBP(interpreter)) + */ + private Translation generateSBP(BooleanAccumulator circuit, LeafInterpreter interpreter, SymmetryBreaker breaker) { + options.reporter().generatingSBP(); + final BooleanFactory factory = interpreter.factory(); + circuit.add(breaker.generateSBP(interpreter, options.symmetryBreaking())); + return toCNF((BooleanFormula)factory.accumulate(circuit), factory.numberOfVariables(), interpreter.vars()); + } + + /** + * Conjoins the given circuit with an SBP generated using the given symmetry breaker and interpreter, + * and returns the resulting circuit's translation to CNF. + * @requires [[annotated.node]] <=> ([[this.formula]] and [[breaker.broken]]) + * @requires circuit is a translation of annotated.node with respect to this.bounds + * @requires interpreter is the leaf interpreter used in generating the given circuit + * @requires breaker.bounds = this.bounds + * @return flatten(circuit && breaker.generateSBP(interpreter), interpreter) + * @throws TrivialFormulaException - flattening the circuit and the predicate yields a constant + */ + private Translation generateSBP(AnnotatedNode annotated, BooleanFormula circuit, LeafInterpreter interpreter, SymmetryBreaker breaker) + throws TrivialFormulaException { + options.reporter().generatingSBP(); + final BooleanFactory factory = interpreter.factory(); + final BooleanValue sbp = breaker.generateSBP(interpreter, options.symmetryBreaking()); + return flatten(annotated, (BooleanFormula)factory.and(circuit, sbp), interpreter); + } + + /** + * If this.options.flatten is true, flattens the given circuit and returns its translation to CNF. + * Otherwise, simply returns the given circuit's translation to CNF. + * @requires [[annotated.node]] <=> ([[this.formula]] and [[breaker.broken]]) + * @requires circuit is a translation of annotated.node with respect to this.bounds + * @requires interpreter is the leaf interpreter used in generating the given circuit + * @return if this.options.flatten then + * toCNF(flatten(circuit), interpreter.factory().numberOfVariables(), interpreter.vars()) else + * toCNF(circuit, interpreter.factory().numberOfVariables(), interpreter.vars()) + * @throws TrivialFormulaException - flattening the circuit yields a constant + */ + private Translation flatten(AnnotatedNode annotated, BooleanFormula circuit, LeafInterpreter interpreter) throws TrivialFormulaException { + final BooleanFactory factory = interpreter.factory(); + if (options.flatten()) { + options.reporter().flattening(circuit); + final BooleanValue flatCircuit = BooleanFormulaFlattener.flatten(circuit, factory); + if (flatCircuit.op()==Operator.CONST) { + throw new TrivialFormulaException(annotated.node(), bounds, (BooleanConstant)flatCircuit, null); + } else { + return toCNF((BooleanFormula)flatCircuit, factory.numberOfVariables(), interpreter.vars()); + } + } else { + return toCNF(circuit, factory.numberOfVariables(), interpreter.vars()); + } + } + + /** + * Translates the given circuit to CNF, adds the clauses to a SATSolver returned + * by options.solver(), and returns a Translation object constructed from the solver + * and the provided arguments. + * @requires circuit is a translation of this.formula with respect to this.bounds + * @requires primaryVars is the number of primary variables generated by translating + * this.formula and this.bounds into the given circuit + * @requires varUsage maps each non-constant relation in this.bounds to the labels of + * the primary variables used to represent that relation in the given circuit + * @return Translation constructed from a SAT solver initialized with the CNF translation + * of the given circuit, the provided arguments, this.bounds, and this.log + */ + private Translation toCNF(BooleanFormula circuit, int primaryVars, Map varUsage) { + options.reporter().translatingToCNF(circuit); + final SATSolver cnf = Bool2CNFTranslator.translate((BooleanFormula)circuit, options.solver(), primaryVars); + return new Translation(cnf, bounds, varUsage, primaryVars, log); + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/TrivialFormulaException.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/TrivialFormulaException.java new file mode 100644 index 00000000..e99b27d2 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/TrivialFormulaException.java @@ -0,0 +1,93 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import kodkod.ast.Formula; +import kodkod.engine.bool.BooleanConstant; +import kodkod.instance.Bounds; + +/** + * Thrown when a formula is found to be trivially (un)satisfiable + * with respect to given Bounds. + * + * @specfield formula: Formula // possibly de-sugared (skolemized) formula + * @specfield bounds: Bounds // bounds (possibly a subset of the original bounds) with respect to which the formula reduces to a constant + * @specfield log: lone TranslationLog // log is null if translation logging was not enabled + * @specfield value: BooleanConstant // the value to which the reduction simplified + * @author Emina Torlak + */ +public final class TrivialFormulaException extends Exception { + private final BooleanConstant value; + private final TranslationLog log; + private final Formula formula; + private final Bounds bounds; + + private static final long serialVersionUID = 6251577831781586067L; + + /** + * Constructs a new TrivialFormulaException using the given arguments. + * @requires log != null && bounds != null && value != null + * @ensures this.log' = log && this.formula' = log.formula && + * this.bounds' = bounds && this.value' = value + */ + TrivialFormulaException(Formula formula, Bounds bounds, BooleanConstant formulaValue, TranslationLog log) { + super("Trivially " + ((formulaValue==BooleanConstant.FALSE) ? "un" : "" ) + "satisfiable formula."); + assert formulaValue != null && bounds != null; + this.log = log; + this.formula = formula; + this.bounds = bounds; + this.value = formulaValue; + } + + /** + * Returns this.log. + * @return this.log + */ + public TranslationLog log() { + return log; + } + + /** + * Returns this.formula. + * @return this.formula + */ + public Formula formula() { + return formula; + } + + /** + * Return this.bounds. + * @return this.bounds + */ + public Bounds bounds() { + return bounds; + } + + /** + * Returns the value to which this.formula is trivially reducible. + * @return this.value + */ + public BooleanConstant value() { + return value; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/UnboundLeafException.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/UnboundLeafException.java new file mode 100644 index 00000000..fd616bad --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/fol2sat/UnboundLeafException.java @@ -0,0 +1,52 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.fol2sat; + +import kodkod.ast.LeafExpression; + +/** + * Thrown when a node contains an undeclared variable or a relation with no bounds. + * @specfield leaf: LeafExpression // the unbound leaf that caused the exception to be thrown + * @author Emina Torlak + */ +public final class UnboundLeafException extends RuntimeException { + private final LeafExpression leaf; + private static final long serialVersionUID = 2472395272061454465L; + + /** + * Constructs an UnboundLeafException for the given leaf. + * @ensures this.leaf' = leaf + */ + UnboundLeafException(String msg, LeafExpression leaf) { + super(msg + ": " +leaf); + this.leaf = leaf; + } + + /** + * Returns this.leaf. + * @return this.leaf + */ + public LeafExpression leaf() { + return leaf; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/ArrayTrace.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/ArrayTrace.java new file mode 100644 index 00000000..a2aec07d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/ArrayTrace.java @@ -0,0 +1,566 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.satlab; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import kodkod.util.collections.Containers; +import kodkod.util.ints.IntBitSet; +import kodkod.util.ints.IntIterator; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.Ints; + +/** + * An array-backed implementation of the {@linkplain ResolutionTrace} interface. + * @author Emina Torlak + */ +final class ArrayTrace implements ResolutionTrace { + /* The trace array encodes the resolution trace as follows. + * The first axioms entries in the trace array contain + * the literals of the clauses added to the prover, in the order + * in which they were added. The remaining entries encode the + * resolvents as follows. Let i >= axioms + * represent the ith resolvent. Then trace[i][0] contains the number of the resolvent's + * antecedents; trace[i][1..trace[i][0]] contains the indices of + * the resolvent's antecedents in the trace; and trace[i][trace[i][0]+1..trace[i].length-1] + * contains the literals of the ith resolvent. All literals are sorted in the + * increasing order of absolute values. All antecedents of a given resolvent precede it in the trace, + * and the conflict clause should be the last trace element. + */ + private final int[][] trace; + private final int axioms; + private final IntSet core; + + /** + * Constructs a resolution trace view for the given raw trace. + * The first axioms entries in the trace array should + * contain the literals of the clauses added to the prover, in + * the order in which they were added. The literals should be + * sorted in the increasing order of absolute values. The remaining entries + * should encode the resolvents as follows. Let i be the index + * of a resolvent in the raw trace. Then, for all 0 <= j < trace[i].length, + * trace[i][j] is the index of the resolvent's jth antecedents in the trace array. + * All antecedents of a given resolvent should precede it in the trace, + * and the conflict clause should be the last trace element. + * + *

Note: the given array's contents must not be modified while + * in use by this resolution trace object.

+ */ + ArrayTrace(int[][] trace, int axioms) { + this.axioms = axioms; + this.trace = computeResolventLiterals(trace, axioms, axioms); + this.core = Ints.unmodifiableIntSet(core(trace,axioms)); + } + + /** + * Constructs a resolution trace from the given subtrace and partial + * trace. This constructor assumes that partial is the result + * of solving the subtrace of the original trace that is given by the + * specified set of indices. The first indices.size() of the partial + * trace are assumed to represent the clauses given by original.trace[indices], + * in the increasing order of indices; the remaining entries should encode + * the resolvents computed from original.trace[indices], as specified by + * {@linkplain #ArrayTrace(int[][], int)}. The given subtrace of the original + * trace must be self-contained, i.e. original.reachable(indices).equals(indices). + * + *

Note: the given array's contents must not be modified while + * in use by this resolution trace object.

+ */ + ArrayTrace(ArrayTrace original, IntSet indices, int[][] partial) { + + int axiomCount = indices.size(); + { // fill the partial[0..indices.size()-1] with the corresponding clauses from original.trace[indices] + final int[][] originalTrace = original.trace; + final int[] position = new int[originalTrace.length]; + + IntIterator itr = indices.iterator(); + for(int i = 0, length = indices.size(); i < length; i++) { + int index = itr.next(); + position[index] = i; + if (original.axiom(index)) { // just set the ith pointer to original literals + partial[i] = originalTrace[index]; + } else { // copy the resolvent and adjust copy's antecedent indices + int resLength = originalTrace[index].length; + int[] resolvent = new int[resLength]; + System.arraycopy(originalTrace[index], 0, resolvent, 0, resLength); + for(int j = 1, lastAnte = resolvent[0]; j <= lastAnte; j++) { + resolvent[j] = position[resolvent[j]]; + } + partial[i] = resolvent; + axiomCount--; + } + } + } + this.axioms = axiomCount; + this.trace = computeResolventLiterals(partial, axioms, indices.size()); + this.core = Ints.unmodifiableIntSet(core(trace,axioms)); + } + + + /** + * Computes literals for the resolvents at indices [computeFrom..trace.length) in the given trace. + * Arrays at indices [0..computeFrom) are assumed to encode clauses as specified by {@linkplain #trace}. + * The resolvents at indices [computeFrom..trace.length) are assumed to encode the remaining resolvents, + * as specified by the {@linkplain #ArrayTrace(int[][], int)} constructor. + * @requires axioms <= computeFrom < trace.length + * @ensures modifies trace to conform to the specification of {@linkplain #trace} + * @return modified trace + */ + private static int[][] computeResolventLiterals(int[][] trace, int axioms, int computeFrom) { + for(int i = computeFrom, length = trace.length; i < length; i++) { + int[] ante = trace[i]; + int[] lits = resolve(trace[ante[0]], ante[0] abs(c1[i]) < abs(c1[j])) and + * (all i: [off2..c2.length), j: [off2..c2.length) | i < j => abs(c2[i]) < abs(c2[j])) and + * (one i: [off1..c1.length), j: [off2..c2.length) | c1[i] = -c2[j]) + * @return an array of integers representing the result of + * resolving the clauses c1 and c2, sorted in the increasing order of absolute values + */ + private static int[] resolve(int[] c1, boolean axiom1, int[] c2, boolean axiom2) { + final int len1 = c1.length, len2 = c2.length; + int i = axiom1 ? 0 : c1[0] + 1; + int j = axiom2 ? 0 : c2[0] + 1; + int k = 0; + + final int[] tmp = new int[(len1-i + len2-j) - 2]; + + while(i < len1 && j < len2) { + int lit1 = c1[i], lit2 = c2[j]; + int var1 = StrictMath.abs(lit1), var2 = StrictMath.abs(lit2); + if (var1==var2) { + if (lit1==lit2) { + tmp[k++] = lit1; + } + i++; + j++; + } else if (var1 < var2) { + tmp[k++] = lit1; + i++; + } else { // var1 > var2 + tmp[k++] = lit2; + j++; + } + } + if (i= axioms; i--) { + if (reachable.contains(i)) { + int[] resolvent = trace[i]; + for(int j = 1, antes = resolvent[0]; j <= antes; j++) { + reachable.add(resolvent[j]); + } + } + } + + for(IntIterator itr = reachable.iterator(0, axioms-1); itr.hasNext(); ) { + core.add(itr.next()); + } + + return core; + } + + /** + * Returns true if the clause at the given index is an axiom. + * @return index < this.axioms + */ + private boolean axiom(int index) { + return index < axioms; + } + + /** + * Returns the offset in this.trace[index] array where literal + * data is stored. + * @return axiom(index) ? 0 : this.trace[index][0] + 1 + */ + private int litOffset(int index) { + return axiom(index) ? 0 : trace[index][0] + 1; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ResolutionTrace#size() + */ + public int size() { return trace.length; } + + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ResolutionTrace#core() + */ + public IntSet core() { return core; } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ResolutionTrace#axioms() + */ + public IntSet axioms() { return Ints.rangeSet(Ints.range(0, axioms-1)); } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ResolutionTrace#resolvents() + */ + public IntSet resolvents() { return Ints.rangeSet(Ints.range(axioms, trace.length-1)); } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ResolutionTrace#get(int) + */ + public Clause get(final int index) { + if (index>=0 && index antecedents() { return Containers.emptyIterator(); } + public IntIterator literals() { return new IntArrayIterator(literals,0,literals.length); } + public int maxVariable() { return StrictMath.abs(literals[literals.length-1]); } + public int numberOfAntecedents() { return 0; } + public int size() { return literals.length; } + public int[] toArray(int[] array) { + if (array.length iterator() { + return new ClauseIterator(new IntIterator() { + int index = 0; + public boolean hasNext() { return index>=0 && index < trace.length; } + public int next() { + if (!hasNext()) throw new NoSuchElementException(); + return index++; + } + public void remove() { throw new UnsupportedOperationException(); } + }); + } + + /** + * Returns true if indices.min() >= 0 && indices.max() < this.size() + * @requires !indices.isEmpty() + * @return indices.min() >= 0 && indices.max() < this.size() + */ + private boolean valid(IntSet indices) { + return indices.min()>=0 && indices.max() iterator(IntSet indices) { + if (indices.isEmpty() || valid(indices)) { + return new ClauseIterator(indices.iterator()); + } + throw new IndexOutOfBoundsException("invalid indices: " + indices); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ResolutionTrace#reverseIterator(kodkod.util.ints.IntSet) + */ + public Iterator reverseIterator(IntSet indices) { + if (indices.isEmpty() || valid(indices)) { + return new ClauseIterator(indices.iterator(Integer.MAX_VALUE, Integer.MIN_VALUE)); + } + throw new IndexOutOfBoundsException("invalid indices: " + indices); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ResolutionTrace#implicants(kodkod.util.ints.IntSet) + */ + public IntSet reachable(IntSet indices) { + if (indices.isEmpty()) return Ints.EMPTY_SET; + else if (valid(indices)) { + final IntSet ret = new IntBitSet(trace.length); + ret.addAll(indices); + for(int i = indices.max(); i >= axioms; i--) { + if (ret.contains(i)) { + int[] resolvent = trace[i]; + for(int j = 1, antes = resolvent[0]; j <= antes; j++) { + ret.add(resolvent[j]); + } + } + } + return ret; + } + else throw new IndexOutOfBoundsException("invalid indices: " + indices); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ResolutionTrace#backwardReachable(kodkod.util.ints.IntSet) + */ + public IntSet backwardReachable(IntSet indices) { + if (indices.isEmpty()) return Ints.EMPTY_SET; + else if (valid(indices)) { + final IntSet ret = new IntBitSet(trace.length); + ret.addAll(indices); + for(int i = axioms, length = trace.length; i < length; i++) { + int[] resolvent = trace[i]; + for(int j = 1, antes = resolvent[0]; j <= antes; j++) { + if (ret.contains(resolvent[j])) { + ret.add(i); + break; + } + } + } + return ret; + } + else throw new IndexOutOfBoundsException("invalid indices: " + indices); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ResolutionTrace#learnable(kodkod.util.ints.IntSet) + */ + public IntSet learnable(IntSet indices) { + if (indices.isEmpty()) return Ints.EMPTY_SET; + else if (valid(indices)) { + final IntSet ret = new IntBitSet(trace.length); + ret.addAll(indices); + TOP: for(int i = axioms, length = trace.length; i < length; i++) { + int[] resolvent = trace[i]; + for(int j = 1, antes = resolvent[0]; j <= antes; j++) { + if (!ret.contains(resolvent[j])) { + continue TOP; + } + } + ret.add(i); + } + return ret; + } + else throw new IndexOutOfBoundsException("invalid indices: " + indices); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ResolutionTrace#directlyLearnable(kodkod.util.ints.IntSet) + */ + public IntSet directlyLearnable(IntSet indices) { + if (indices.isEmpty()) return Ints.EMPTY_SET; + else if (valid(indices)) { + final IntSet ret = new IntBitSet(trace.length); + ret.addAll(indices); + TOP: for(int i = axioms, length = trace.length; i < length; i++) { + int[] resolvent = trace[i]; + for(int j = 1, antes = resolvent[0]; j <= antes; j++) { + if (!indices.contains(resolvent[j])) { + continue TOP; + } + } + ret.add(i); + } + return ret; + } + + else throw new IndexOutOfBoundsException("invalid indices: " + indices); + } + + /** + * {@inheritDoc} + * @see java.lang.Object#toString() + */ + public String toString() { + final StringBuilder ret = new StringBuilder(); + for(int i = 0; i < axioms; i++) { + ret.append("AXIOM. Literals: "); + int[] clause = trace[i]; + for(int j = 0, c = clause.length; j < c; j++) { + ret.append(clause[j]); + ret.append(" "); + } + ret.append("\n"); + } + for(int i = axioms, max = trace.length; i < max; i++) { + ret.append("RESOLVENT. Antecedents: "); + int[] clause = trace[i]; + for(int j = 1, c = clause[0]; j <= c; j++) { + ret.append(clause[j]); + ret.append(" "); + } + ret.append("\n"); + } + return ret.toString(); + } + + /** + * A mutable implementation of the Clause interface. + * @author Emina Torlak + */ + private class ClauseView extends Clause { + private int[] clause; + private int litOffset; + + /** + * Constructs a clause view for the ith clause. + * @requires 0 <= index < trace.length + */ + ClauseView(int index) { + this.clause = trace[index]; + this.litOffset = litOffset(index); + } + + /** + * Constructs a clause view for the 0th clause. + */ + ClauseView() { this(0); } + + /** + * Sets the state of this clause view to represent + * the ith clause in the trace and returns this. + * @ensures sets the state of this clause view to represent + * the ith clause in the trace + * @return this + */ + ClauseView set(int index) { + this.clause = trace[index]; + this.litOffset = litOffset(index); + return this; + } + + public int maxVariable() { return StrictMath.abs(clause[clause.length-1]); } + public int numberOfAntecedents() { return StrictMath.max(0, litOffset-1); } + public int size() { return clause.length - litOffset; } + public Iterator antecedents() { return new ClauseIterator(new IntArrayIterator(clause, 1, litOffset)); } + public IntIterator literals() { return new IntArrayIterator(clause, litOffset, clause.length); } + + public int[] toArray(int[] array) { + final int size = size(); + if (array.length < size) { + array = new int[size]; + } + System.arraycopy(clause, litOffset, array, 0, size); + return array; + } + } + + /** + * A clause iterator wrapper for an int iterator. + * @author Emina Torlak + */ + private final class ClauseIterator extends ClauseView implements Iterator { + private final IntIterator itr; + /** + * Constructs a clause iterator that will iterate over the clauses in this.trace + * located at the indices given by itr. The given iterator must return valid indices. + */ + ClauseIterator(IntIterator itr) { + this.itr = itr; + } + public boolean hasNext() { return itr.hasNext(); } + public Clause next() { return set(itr.next()); } + public void remove() { throw new UnsupportedOperationException(); } + } + + /** + * An int iterator that iterates over the portion of an integer array + * in the increasing order of indices. + * @author Emina Torlak + */ + private static final class IntArrayIterator implements IntIterator { + private final int[] array; + private int from; + private final int to; + /** + * Constructs an int iterator that iterates over the given array, + * returning the elements between from, inclusive, and to, exclusive. + * @requires 0 <= from < array.length < Integer.MAX_VALUE + */ + IntArrayIterator(int[] array, int from, int to) { + this.array = array; + this.from = from; + this.to = to; + } + public boolean hasNext() { return from >= 0 && from < to; } + public int next() { + if (!hasNext()) throw new NoSuchElementException(); + return array[from++]; + } + public void remove() { throw new UnsupportedOperationException(); } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/Clause.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/Clause.java new file mode 100644 index 00000000..f774c310 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/Clause.java @@ -0,0 +1,155 @@ +package kodkod.engine.satlab; + +import java.util.Iterator; + +import kodkod.util.ints.IntIterator; +import kodkod.util.ints.Ints; + +/** + * A propositional clause. + * + * @specfield literals: set int + * @specfield antecedents: Clause[] + * @invariant 0 !in literals + * @invariant no lit: literals | -lit in literals + * @invariant some antecedents => #antecedents > 1 + * @invariant some antecedents => + * literals = { lit: antecedents[int].literals | + * no i: [0..#antecedents-1) | lit in antecedents[i].literals && -lit in antecedents[i+1].literals } + * @author Emina Torlak + */ +public abstract class Clause { + /** + * Constructs a new clause. + */ + Clause() {} + + /** + * Returns the size of this clause, measured in the + * number of literals. + * @return #this.literals + */ + public abstract int size(); + + /** + * Returns an iterator over the literals in this clause, + * in the ascending order of absolute values. + * @return an iterator over this.literals + */ + public abstract IntIterator literals(); + + /** + * Returns the largest variable identifier occurring in this.literals. + * @return max(abs(this.literals)) + */ + public abstract int maxVariable(); + + /** + * Copies this.literals into the specified array, provided + * that it is large enough, and returns it. If the array is not large enough, + * a new array is allocated, populated with this.literals, and returned. + * @return the given array, filled with this.literals, if + * the it is large enough; otherwise a new array containing this.literals + * @throws NullPointerException - array = null + */ + public abstract int[] toArray(int[] array); + + /** + * Returns a new array of length this.size(), initialized with this.literals. + * @return a new array of length this.size(), initialized with this.literals. + */ + public int[] toArray() { + return toArray(new int[size()]); + } + + /** + * Returns the number of antecedents of this clause. + * @return #this.antecedents + */ + public abstract int numberOfAntecedents(); + + /** + * Returns an iterator that traverses this.antecedents in proper sequence. + *

Note:The clause objects returned by the iterator are not + * required to be immutable. In particular, the state of a clause object + * returned by next() (as well as the state of any object obtained + * through that clause's {@linkplain Clause#antecedents()} methods) is guaranteed + * to remain the same only until the subsequent call to next().

+ * @return an iterator that traverses this.antecedents in proper sequence. + */ + public abstract Iterator antecedents(); + + /** +// * Returns the antecedent at the given index. +// * @requires 0 <= index < this.numberOfAntecedents() +// * @return this.antecedents[index] +// * @throws IndexOutOfBoundsException - index < 0 || index >= this.numberOfAntecedents() +// */ +// public abstract Clause antecedent(int index); + + /** + * Returns true if o is a Clause whose literals and antecedents + * are equal to those of this clause. + * @return o in Clause && o.literals.equals(this.literals) && o.antecedents.equals(this.antecedents) + */ + public boolean equals(Object o) { + if (o==this) return true; + if (o instanceof Clause) { + final Clause c = (Clause) o; + if (size()==c.size()) { + final IntIterator itr1 = literals(), itr2 = literals(); + while(itr1.hasNext()) { + if (itr1.next()!=itr2.next()) return false; + } + } + final int ante = numberOfAntecedents(); + if (ante > 0 && ante==c.numberOfAntecedents()) { + final Iterator itr1 = antecedents(), itr2 = c.antecedents(); + while(itr1.hasNext()) { + if (!itr1.next().equals(itr2.next())) return false; + } + } + return ante==0; + } + return false; + } + + /** + * Returns the hashcode for this clause. The hashcode for a clause is equivalent + * to Ints.superFastHash(x) where x is an array such that its first this.size() + * elements are the literals of this clause (as returned by this.literals()) + * and its remaining this.numberOfAntecedents() elements are the hashCodes of + * this.antecedents (as returned by this.antecedents()). + * @return hashcode for this clause + */ + public int hashCode() { + int hash = size() + numberOfAntecedents(); + for(IntIterator iter = literals(); iter.hasNext(); ) { + hash = Ints.superFastHashIncremental(iter.next(), hash); + } + for(Iterator iter = antecedents(); iter.hasNext(); ) { + hash = Ints.superFastHash(new int[] { iter.next().hashCode(), hash }); + } + return Ints.superFastHashAvalanche(hash); + } + + /** + * Returns a string representation of this clause. + * @return a string representation of this clause. + */ + public String toString() { + final StringBuilder ret = new StringBuilder(); + if (numberOfAntecedents()==0) { + ret.append("AXIOM"); + } else { + ret.append("RESOLVENT"); + } + ret.append(". Literals: {"); + for(IntIterator iter = literals(); iter.hasNext();) { + ret.append(" "); + ret.append(iter.next()); + } + ret.append(" }"); + return ret.toString(); + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/ExternalSolver.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/ExternalSolver.java new file mode 100644 index 00000000..566e2e14 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/ExternalSolver.java @@ -0,0 +1,280 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.satlab; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.RandomAccessFile; +import java.util.BitSet; + +/** + * An implementation of a wrapper for an external SAT solver, + * executed in a separate process. + * @author Emina Torlak + */ +final class ExternalSolver implements SATSolver { + private final StringBuilder buffer; + private final int capacity = 8192; + private final String executable, inTemp, outTemp; + private final String[] options; + private final RandomAccessFile cnf; + private final BitSet solution; + private volatile Boolean sat; + private volatile int vars, clauses; + + /** + * Constructs an ExternalSolver that will execute the specified binary + * with the given options on the inTemp file with the specified name. inTemp + * will be initialized to contain all clauses added to this solver via the + * {@link #addClause(int[])} method. If outTemp is the empty string, + * the solver is assumed to write its output to standard out. Otherwise, + * it is assumed to write its output to the outTemp file. + */ + ExternalSolver(String executable, String inTemp, String outTemp, String... options) { + try { + this.cnf = new RandomAccessFile(inTemp,"rw"); + this.cnf.setLength(0); + // get enough space into the buffer for the cnf header, which will be written last + this.buffer = new StringBuilder(); + for(int i = headerLength(); i > 0; i--) { + buffer.append(" "); + } + buffer.append("\n"); + this.sat = null; + this.solution = new BitSet(); + this.vars = 0; + this.clauses = 0; + this.executable = executable; + this.options = options; + this.inTemp = inTemp; + this.outTemp = outTemp; + } catch (FileNotFoundException e) { + throw new SATAbortedException(e); + } catch (IOException e) { + throw new SATAbortedException(e); + } + + } + + /** + * Returns the length, in characters, of the longest possible header + * for a cnf file: p cnf Integer.MAX_VALUE Integer.MAX_VALUE + * @return the length, in characters, of the longest possible header + * for a cnf file: p cnf Integer.MAX_VALUE Integer.MAX_VALUE + */ + private static final int headerLength() { + return String.valueOf(Integer.MAX_VALUE).length()*2 + 8; + } + + /** + * Flushes the contents of the string buffer to the cnf file. + */ + private final void flush(){ + try { + cnf.writeBytes(buffer.toString()); + } catch (IOException e) { + throw new SATAbortedException(e); + } + buffer.setLength(0); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.SATSolver#addClause(int[]) + */ + public boolean addClause(int[] lits) { + if (lits.length>0) { + clauses++; + if (buffer.length()>capacity) flush(); + for(int lit: lits) { + buffer.append(lit); + buffer.append(" "); + } + buffer.append("0\n"); + return true; + } + return false; + } + + /** + * @see kodkod.engine.satlab.SATSolver#addVariables(int) + */ + public void addVariables(int numVars) { + if (numVars < 0) + throw new IllegalArgumentException("vars < 0: " + numVars); + vars += numVars; + } + + /** + * @see kodkod.engine.satlab.SATSolver#free() + */ + public synchronized void free() { + try { + cnf.close(); + } catch (IOException e) { + // do nothing + } + } + + + /** + * Releases the resources used by this external solver. + */ + protected final void finalize() throws Throwable { + super.finalize(); + free(); + } + + /** + * @see kodkod.engine.satlab.SATSolver#numberOfClauses() + */ + public int numberOfClauses() { + return clauses; + } + + /** + * @see kodkod.engine.satlab.SATSolver#numberOfVariables() + */ + public int numberOfVariables() { + return vars; + } + + /** + * @ensures |lit| <= this.vars && lit != 0 => this.solution'.set(|lit|, lit>0) + * @throws RuntimeException - lit=0 || |lit|>this.vars + */ + private final void updateSolution(int lit) { + int abs = StrictMath.abs(lit); + if (abs<=vars && abs>0) + solution.set(abs-1, lit>0); + else + throw new RuntimeException("invalid variable value: |" + lit + "| !in [1.."+vars+"]"); + } + + /** Helper class that drains the stderr. */ + private final class Drainer implements Runnable { + /** The stream to drain. */ + private final InputStream input; + /** Constructor that constructs a new Drainer. */ + public Drainer(InputStream input) { + this.input=input; + } + /** The run method that keeps reading from the InputStream until end-of-file. */ + public void run() { + try { + byte[] buffer=new byte[8192]; + while(true) { + int n=input.read(buffer); + if (n<0) break; + } + } catch (IOException ex) { + } + try { input.close(); } catch(IOException ex) { } + } + } + + /** + * @see kodkod.engine.satlab.SATSolver#solve() + */ + public boolean solve() throws SATAbortedException { + if (sat==null) { + flush(); + Process p = null; + try { + cnf.seek(0); + cnf.writeBytes("p cnf " + vars + " " + clauses); + cnf.close(); + + final String[] command = new String[options.length+2]; + command[0] = executable; + System.arraycopy(options, 0, command, 1, options.length); + command[command.length-1] = inTemp; + p = Runtime.getRuntime().exec(command); + new Thread(new Drainer(p.getErrorStream())).start(); + final BufferedReader out; + if (outTemp.length()==0) { + out = new BufferedReader(new InputStreamReader(p.getInputStream(), "ISO-8859-1")); + } else { + out = new BufferedReader(new FileReader(outTemp)); + } + String line = null; + while((line = out.readLine()) != null) { + String[] tokens = line.split("\\s"); + int tlength = tokens.length; + if (tlength>0) { + if (tokens[0].compareToIgnoreCase("s")==0) { + if (tlength==2) { + if (tokens[1].compareToIgnoreCase("SATISFIABLE")==0) { + sat = Boolean.TRUE; + continue; + } else if (tokens[1].compareToIgnoreCase("UNSATISFIABLE")==0) { + sat = Boolean.FALSE; + continue; + } + } + throw new RuntimeException("invalid " + executable + " output line: " + line); + } else if (tokens[0].compareToIgnoreCase("v")==0) { + int last = tlength-1; + for(int i = 1; i < last; i++) { + updateSolution(Integer.parseInt(tokens[i])); + } + int lit = Integer.parseInt(tokens[last]); + if (lit!=0) updateSolution(lit); + else if (sat!=null) break; + } // not a solution line or a variable line, so ignore it. + } + } + try { out.close(); } catch (IOException e) { } // do nothing, we are done + if (sat==null) { + throw new RuntimeException("invalid " + executable + " output"); + } + } catch (IOException e) { + throw new SATAbortedException(e); + } catch (NumberFormatException e) { + throw new RuntimeException("invalid "+ executable +" output", e); + } + } + return sat; + } + + /** + * @see kodkod.engine.satlab.SATSolver#valueOf(int) + */ + public boolean valueOf(int variable) { + if (!Boolean.TRUE.equals(sat)) + throw new IllegalStateException(); + if (variable < 1 || variable > vars) + throw new IllegalArgumentException(variable + " !in [1.." + vars+"]"); + return solution.get(variable-1); + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + return executable + " " + options; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/LazyTrace.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/LazyTrace.java new file mode 100644 index 00000000..771723f6 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/LazyTrace.java @@ -0,0 +1,704 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.satlab; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import kodkod.util.collections.Containers; +import kodkod.util.ints.IntBitSet; +import kodkod.util.ints.IntIterator; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.Ints; + +/** + * An array-backed implementation of the {@linkplain ResolutionTrace} interface. + * Resolvent literals are computed on-demand, and only the resolvents reachable + * from the conflict clause are stored. + * + * @author Emina Torlak + */ +final class LazyTrace implements ResolutionTrace { + /* The trace array encodes the resolution trace as follows. + * The first axioms entries in the trace array contain + * the literals of the clauses added to the prover, in the order + * in which they were added. The remaining entries encode the + * resolvents as follows. Let i >= axioms + * represent the ith resolvent. If resolved.contains(i-axioms), then trace[i][0] + * contains the number of the resolvent's antecedents; trace[i][1..trace[i][0]] + * contains the indices of the resolvent's antecedents in the trace; + * and trace[i][trace[i][0]+1..trace[i].length-1] contains the literals of the ith resolvent. + * Otherwise, the literals for the given resolvent have not yet been computed so + * trace[i][0..trace[i].length-1] contains the indices of the resolvent's antecedents. + * + * All computed and axiom literals are sorted in the increasing order of absolute values. + * All antecedents of a given resolvent precede it in the trace, + * and the conflict clause should be the last trace element. + */ + private final int[][] trace; + private final int axioms; + private final IntSet core, resolved; + + /** + * Constructs a resolution trace view for the given raw trace. + * The first axioms entries in the trace array should + * contain the literals of the clauses added to the prover, in + * the order in which they were added. The literals should be + * sorted in the increasing order of absolute values. The remaining entries + * should encode the resolvents as follows. Let i be the index + * of a resolvent in the raw trace. Then, for all 0 <= j < trace[i].length, + * trace[i][j] is the index of the resolvent's jth antecedents in the trace array. + * All antecedents of a given resolvent should precede it in the trace, + * and the conflict clause should be the last trace element. + * + *

Note: the given array's contents must not be modified while + * in use by this resolution trace object.

+ */ + LazyTrace(int[][] trace, int axioms) { + this.axioms = axioms; + + // find all the clauses that are reachable from the conflict + final IntSet reachable = reachable(trace, axioms); + + // get the core clauses + this.core = core(reachable, axioms); + + // trim the trace so that it contains all axioms but only those resolvents that are reachable from the conflict + this.trace = compress(trace, axioms, reachable, core); + + // we haven't computed any resolvent literals yet ... + this.resolved = new IntBitSet(this.trace.length-axioms); + } + + + /** + * Constructs a resolution trace from the given subtrace and partial + * trace. This constructor assumes that partial is the result + * of solving the subtrace of the original trace that is given by the + * specified set of indices. The first indices.size() of the partial + * trace are assumed to represent the clauses given by original.trace[indices], + * in the increasing order of indices; the remaining entries should encode + * the resolvents computed from original.trace[indices], as specified by + * {@linkplain #LazyTrace(int[][], int)}. The given subtrace of the original + * trace must be self-contained, i.e. original.reachable(indices).equals(indices). + * + *

Note: the given array's contents must not be modified while + * in use by this resolution trace object.

+ */ + LazyTrace(LazyTrace original, IntSet indices, int[][] partial) { + this.axioms = reconstruct(original, indices, partial); + + // find all the clauses that are reachable from the conflict + final IntSet reachable = reachable(partial, axioms); + + // get the core clauses + this.core = core(reachable, axioms); + + // trim the trace so that it contains all axioms but only those resolvents that are reachable from the conflict + this.trace = compress(partial, axioms, reachable, core); + + // we haven't computed any resolvent literals yet ... + this.resolved = new IntBitSet(this.trace.length-axioms); + } + + /** + * Fills the first indices.size() empty positions of the partial trace with the + * corresponding clauses from the original trace and returns the number of axioms + * in the reconstructed trace. + * @requires original, indices, and partial are as specified by {@linkplain #LazyTrace(LazyTrace, IntSet, int[][])} constructor + * @ensures modifies partial so that it conforms to the {@linkplain #trace LazyTrace.trace} spec + * using the provided original trace and indices. + * @return number of axioms in the modified partial trace + */ + private static int reconstruct(LazyTrace original, IntSet indices, int[][] partial) { + int axiomCount = indices.size(); + // fill the partial[0..indices.size()-1] with the corresponding clauses from original.trace[indices] + final int[][] originalTrace = original.trace; + final int[] position = new int[indices.max()+1]; + + IntIterator itr = indices.iterator(); + for(int i = 0, length = indices.size(); i < length; i++) { + int index = itr.next(); + position[index] = i; + if (original.axiom(index)) { // just set the ith pointer to original literals + partial[i] = originalTrace[index]; + } else { // copy the resolvent and adjust copy's antecedent indices + int antes = originalTrace[index][0]; + int[] resolvent = new int[antes]; + for(int j = 0; j < antes; j++) { + resolvent[j] = position[originalTrace[index][j+1]]; + } + partial[i] = resolvent; + axiomCount--; + } + } + + return axiomCount; + } + + /** + * Returns the indices of all clauses in the given trace that are + * reachable from the conflict clause through the resolvents + * in trace[roots..trace.length-1]. This method assumes that + * that the last trace[roots..trace.length-1] clauses encode + * resolvents as specified by the + * {@linkplain #LazyTrace(int[][], int)} constructor. + * @return indices of all clauses in the given trace that are + * reachable from the conflict clause through the resolvents in + * trace[roots..trace.length-1] + */ + private static IntSet reachable(int[][] trace, int roots) { + final IntSet reachable = new IntBitSet(trace.length); + reachable.add(trace.length-1); + for(int i = trace.length-1; i >= roots; i--) { + if (reachable.contains(i)) { + int[] resolvent = trace[i]; + for(int j = 0; j < resolvent.length; j++) { + reachable.add(resolvent[j]); + } + } + } + return reachable; + } + + /** + * Returns a set that contains the elements from the given + * reachable between 0, inclusive, and axioms, exclusive. + * @return a set that contains the elements from the given + * reachable between 0, inclusive, and axioms, exclusive. + */ + private static IntSet core(IntSet reachable, int axioms) { + final IntSet core = new IntBitSet(axioms); + for(IntIterator itr = reachable.iterator(0, axioms-1); itr.hasNext(); ) { + core.add(itr.next()); + } + return Ints.unmodifiableIntSet(core); + } + + /** + * Compresses the given src trace into a destination trace that contains the same axioms as the + * source but only the resolvents that are reachable from the conflict clause. + * @requires src and axioms are as specified by the {@linkplain #LazyTrace(int[][], int)} constructor + * @requires reachable.elts = reachable(src, axioms).elts + * @requires core.elts = core(reachable, axioms).elts + * @ensures invalidates the contents of src; src should not be used after this method returns + * @return a new trace that contains the same axioms as the + * source but only the resolvents that are reachable from the conflict clause. + */ + private static int[][] compress(int[][] src, int axioms, IntSet reachable, IntSet core) { + final int[][] dest = new int[reachable.size()-core.size()+axioms][]; + System.arraycopy(src, 0, dest, 0, axioms); + + final int[] pos = new int[src.length-axioms]; + final IntIterator srcIdxs = reachable.iterator(axioms, src.length); + for(int i = axioms; srcIdxs.hasNext(); i++) { + int srcIdx = srcIdxs.next(); + pos[srcIdx-axioms] = i; + // move the resolvent and adjust its antecedent indices + int[] resolvent = src[srcIdx]; + dest[i] = resolvent; + for(int j = 0, lastAnte = resolvent.length; j < lastAnte; j++) { + int ante = resolvent[j]; + resolvent[j] = ante < axioms ? ante : pos[ante-axioms]; + } + } + return dest; + } + + /** + * Returns an array of integers representing the result of + * resolving the clauses c1 and c2, sorted in the increasing order + * of absolute values. The parameters axiom1 and axiom2 specify + * whether c1 and c2 encode axioms or resolvents. In particular, + * if axiom1 (resp. axiom2) is true, then all integers in c1 (resp. c2) + * are assumed to be literals, sorted in the increasing order of absolute + * values. If axiom1 (resp. axiom2) is false, then the integers starting + * at c1[0]+1 (resp. c2[0]+1) are assumed to be literals, sorted in the increasing + * order of absolute values. + * @requires let off1 = axiom1 ? 0 : c1[0] + 1, off2 = axiom2 ? 0 : c2[0]+1 | + * (all i: [off1..c1.length), j: [off1..c1.length) | i < j => abs(c1[i]) < abs(c1[j])) and + * (all i: [off2..c2.length), j: [off2..c2.length) | i < j => abs(c2[i]) < abs(c2[j])) and + * (one i: [off1..c1.length), j: [off2..c2.length) | c1[i] = -c2[j]) + * @return an array of integers representing the result of + * resolving the clauses c1 and c2, sorted in the increasing order of absolute values + */ + private static int[] resolve(int[] c1, boolean axiom1, int[] c2, boolean axiom2) { + final int len1 = c1.length, len2 = c2.length; + int i = axiom1 ? 0 : c1[0] + 1; + int j = axiom2 ? 0 : c2[0] + 1; + int k = 0; + + final int[] tmp = new int[(len1-i + len2-j) - 2]; + + while(i < len1 && j < len2) { + int lit1 = c1[i], lit2 = c2[j]; + int var1 = StrictMath.abs(lit1), var2 = StrictMath.abs(lit2); + if (var1==var2) { + if (lit1==lit2) { + tmp[k++] = lit1; + } + i++; + j++; + } else if (var1 < var2) { + tmp[k++] = lit1; + i++; + } else { // var1 > var2 + tmp[k++] = lit2; + j++; + } + } + if (i=0 && index antecedents() { return Containers.emptyIterator(); } + public IntIterator literals() { return new IntArrayIterator(literals,0,literals.length); } + public int maxVariable() { return StrictMath.abs(literals[literals.length-1]); } + public int numberOfAntecedents() { return 0; } + public int size() { return literals.length; } + public int[] toArray(int[] array) { + if (array.length iterator() { + return new ClauseIterator(new IntIterator() { + int index = 0; + public boolean hasNext() { return index>=0 && index < trace.length; } + public int next() { + if (!hasNext()) throw new NoSuchElementException(); + return index++; + } + public void remove() { throw new UnsupportedOperationException(); } + }); + } + + /** + * Returns true if indices.min() >= 0 && indices.max() < this.size() + * @requires !indices.isEmpty() + * @return indices.min() >= 0 && indices.max() < this.size() + */ + private boolean valid(IntSet indices) { + return indices.min()>=0 && indices.max() iterator(IntSet indices) { + if (indices.isEmpty() || valid(indices)) { + return new ClauseIterator(indices.iterator()); + } + throw new IndexOutOfBoundsException("invalid indices: " + indices); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ResolutionTrace#reverseIterator(kodkod.util.ints.IntSet) + */ + public Iterator reverseIterator(IntSet indices) { + if (indices.isEmpty() || valid(indices)) { + return new ClauseIterator(indices.iterator(Integer.MAX_VALUE, Integer.MIN_VALUE)); + } + throw new IndexOutOfBoundsException("invalid indices: " + indices); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ResolutionTrace#implicants(kodkod.util.ints.IntSet) + */ + public IntSet reachable(IntSet indices) { + if (indices.isEmpty()) return Ints.EMPTY_SET; + else if (valid(indices)) { + final IntSet ret = new IntBitSet(trace.length); + ret.addAll(indices); + for(int i = indices.max(); i >= axioms; i--) { + if (ret.contains(i)) { + int[] resolvent = trace[i]; + if (resolved(i)) { + for(int j = 1, antes = resolvent[0]; j <= antes; j++) { + ret.add(resolvent[j]); + } + } else { + for(int j = 0; j < resolvent.length; j++) { + ret.add(resolvent[j]); + } + } + } + } + return ret; + } + else throw new IndexOutOfBoundsException("invalid indices: " + indices); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ResolutionTrace#backwardReachable(kodkod.util.ints.IntSet) + */ + public IntSet backwardReachable(IntSet indices) { + if (indices.isEmpty()) return Ints.EMPTY_SET; + else if (valid(indices)) { + final IntSet ret = new IntBitSet(trace.length); + ret.addAll(indices); + for(int i = axioms, length = trace.length; i < length; i++) { + int[] resolvent = trace[i]; + if (resolved(i)) { + for(int j = 1, antes = resolvent[0]; j <= antes; j++) { + if (ret.contains(resolvent[j])) { + ret.add(i); + break; + } + } + } else { + for(int j = 0; j < resolvent.length; j++) { + if (ret.contains(resolvent[j])) { + ret.add(i); + break; + } + } + } + } + return ret; + } + else throw new IndexOutOfBoundsException("invalid indices: " + indices); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ResolutionTrace#learnable(kodkod.util.ints.IntSet) + */ + public IntSet learnable(IntSet indices) { + if (indices.isEmpty()) return Ints.EMPTY_SET; + else if (valid(indices)) { + final IntSet ret = new IntBitSet(trace.length); + ret.addAll(indices); + TOP: for(int i = axioms, length = trace.length; i < length; i++) { + int[] resolvent = trace[i]; + if (resolved(i)) { + for(int j = 1, antes = resolvent[0]; j <= antes; j++) { + if (!ret.contains(resolvent[j])) { + continue TOP; + } + } + } else { + for(int j = 0; j < resolvent.length; j++) { + if (!ret.contains(resolvent[j])) { + continue TOP; + } + } + } + ret.add(i); + } + return ret; + } + else throw new IndexOutOfBoundsException("invalid indices: " + indices); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ResolutionTrace#directlyLearnable(kodkod.util.ints.IntSet) + */ + public IntSet directlyLearnable(IntSet indices) { + if (indices.isEmpty()) return Ints.EMPTY_SET; + else if (valid(indices)) { + final IntSet ret = new IntBitSet(trace.length); + ret.addAll(indices); + TOP: for(int i = axioms, length = trace.length; i < length; i++) { + int[] resolvent = trace[i]; + if (resolved(i)) { + for(int j = 1, antes = resolvent[0]; j <= antes; j++) { + if (!indices.contains(resolvent[j])) { + continue TOP; + } + } + } else { + for(int j = 0; j < resolvent.length; j++) { + if (!indices.contains(resolvent[j])) { + continue TOP; + } + } + } + ret.add(i); + } + return ret; + } + + else throw new IndexOutOfBoundsException("invalid indices: " + indices); + } + + /** + * {@inheritDoc} + * @see java.lang.Object#toString() + */ + public String toString() { + final StringBuilder ret = new StringBuilder(); + for(int i = 0; i < axioms; i++) { + ret.append("AXIOM. Literals: "); + int[] clause = trace[i]; + for(int j = 0, c = clause.length; j < c; j++) { + ret.append(clause[j]); + ret.append(" "); + } + ret.append("\n"); + } + for(int i = axioms, max = trace.length; i < max; i++) { + ret.append("RESOLVENT. Antecedents: "); + int[] clause = trace[i]; + if (resolved(i)) { + for(int j = 1, c = clause[0]; j <= c; j++) { + ret.append(clause[j]); + ret.append(" "); + } + } else { + for(int j = 0; j < clause.length; j++) { + ret.append(clause[j]); + ret.append(" "); + } + } + ret.append("\n"); + } + return ret.toString(); + } + + /** + * A mutable implementation of the Clause interface. + * @author Emina Torlak + */ + private class ClauseView extends Clause { + private int[] clause; + private int litOffset, index; + + /** + * Constructs a clause view for the ith clause. + * @requires 0 <= index < trace.length + */ + ClauseView(int index) { + this.index = index; + this.clause = trace[index]; + this.litOffset = litOffset(index); + } + + /** + * Constructs a clause view for the 0th clause. + */ + ClauseView() { this(0); } + + /** + * Sets the state of this clause view to represent + * the ith clause in the trace and returns this. + * @ensures sets the state of this clause view to represent + * the ith clause in the trace + * @return this + */ + ClauseView set(int index) { + this.index = index; + this.clause = trace[index]; + this.litOffset = litOffset(index); + return this; + } + void ensureLiterals() { + if (litOffset<0) { + resolve(index); + this.clause = trace[index]; + this.litOffset = litOffset(index); + } + } + public int maxVariable() { + ensureLiterals(); + return StrictMath.abs(clause[clause.length-1]); + } + public int numberOfAntecedents() { + return litOffset<0 ? clause.length : StrictMath.max(0, litOffset-1); + } + public int size() { + ensureLiterals(); + return clause.length - litOffset; + } + public Iterator antecedents() { + return new ClauseIterator(new IntArrayIterator(clause, 1, litOffset)); + } + public IntIterator literals() { + ensureLiterals(); + return new IntArrayIterator(clause, litOffset, clause.length); + } + public int[] toArray(int[] array) { + final int size = size(); + if (array.length < size) { + array = new int[size]; + } + System.arraycopy(clause, litOffset, array, 0, size); + return array; + } + } + + /** + * A clause iterator wrapper for an int iterator. + * @author Emina Torlak + */ + private final class ClauseIterator extends ClauseView implements Iterator { + private final IntIterator itr; + /** + * Constructs a clause iterator that will iterate over the clauses in this.trace + * located at the indices given by itr. The given iterator must return valid indices. + */ + ClauseIterator(IntIterator itr) { + this.itr = itr; + } + public boolean hasNext() { return itr.hasNext(); } + public Clause next() { return set(itr.next()); } + public void remove() { throw new UnsupportedOperationException(); } + } + + /** + * An int iterator that iterates over the portion of an integer array + * in the increasing order of indices. + * @author Emina Torlak + */ + private static final class IntArrayIterator implements IntIterator { + private final int[] array; + private int from; + private final int to; + /** + * Constructs an int iterator that iterates over the given array, + * returning the elements between from, inclusive, and to, exclusive. + * @requires 0 <= from < array.length < Integer.MAX_VALUE + */ + IntArrayIterator(int[] array, int from, int to) { + this.array = array; + this.from = from; + this.to = to; + } + public boolean hasNext() { return from >= 0 && from < to; } + public int next() { + if (!hasNext()) throw new NoSuchElementException(); + return array[from++]; + } + public void remove() { throw new UnsupportedOperationException(); } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/MiniSat.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/MiniSat.java new file mode 100644 index 00000000..5fc65c50 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/MiniSat.java @@ -0,0 +1,86 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.satlab; + + +/** + * Java wrapper for Niklas En and Niklas Srensson MiniSAT solver. + * @author Emina Torlak + */ +final class MiniSat extends NativeSolver { + + /** + * Constructs a new MiniSAT wrapper. + */ + public MiniSat() { + super(make()); + } + + static { + loadLibrary("minisat"); + } + + + /** + * {@inheritDoc} + * @see java.lang.Object#toString() + */ + public String toString() { + return "MiniSat"; + } + + /** + * Returns a pointer to an instance of MiniSAT. + * @return a pointer to an instance of minisat. + */ + private static native long make(); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#free(long) + */ + native void free(long peer); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#addVariables(long, int) + */ + native void addVariables(long peer, int numVariables); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#addClause(long, int[]) + */ + native boolean addClause(long peer, int[] lits); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#solve(long) + */ + native boolean solve(long peer); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#valueOf(long, int) + */ + native boolean valueOf(long peer, int literal); +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/MiniSatExternal.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/MiniSatExternal.java new file mode 100644 index 00000000..81b32a36 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/MiniSatExternal.java @@ -0,0 +1,223 @@ +package kodkod.engine.satlab; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; + +/** + * Runs an external version of minisat (whichever "minisat" is found in the PATH) + * + * @author aleks + */ +public class MiniSatExternal implements SATSolver { + + private File cnfFile; + private OutputStream cnfOut; + + private int vars = 0; + private int clauses = 0; + private boolean freed = false; + + private boolean sat = false; + private boolean[] model; + + public MiniSatExternal() { + init(); + } + + private void init() { + try { + cnfFile = File.createTempFile("kk_minisat", ".cnf"); + cnfOut = new BufferedOutputStream(new FileOutputStream(cnfFile)); + } catch (IOException e) { + throw new RuntimeException("Could not create cnf file: " + cnfFile.getAbsolutePath(), e); + } + } + + @Override + public boolean addClause(int[] lits) { + try { + clauses++; + StringBuilder sb = new StringBuilder(); + for (int l : lits) sb.append(l + " "); + sb.append("0\n"); + cnfOut.write(sb.toString().getBytes()); + return false; + } catch (IOException e) { + throw new RuntimeException("Could not write to cnf file " + cnfFile.getAbsolutePath(), e); + } + } + + @Override + public void addVariables(int numVars) { + assert numVars >= 0; + vars += numVars; + } + + @Override + public void free() { + try { + if (!freed) { + cnfOut.flush(); + cnfOut.close(); + cnfFile.deleteOnExit(); + freed = true; + } + } catch (IOException e) { + throw new RuntimeException("Could not close cnf output stream"); + } + } + + @Override + public int numberOfClauses() { + return clauses; + } + + @Override + public int numberOfVariables() { + return vars; + } + + @Override + public boolean solve() throws SATAbortedException { + finalizeCnf(); + File modelFile = runMinisat(); + readModel(modelFile); + if (sat) + assert checkModel(); + return sat; + } + + private boolean checkModel() { + BufferedReader br = null; + try { + br = new BufferedReader(new InputStreamReader(new FileInputStream(cnfFile))); + String line = br.readLine(); //header + line = br.readLine(); + while (line != null) { + String[] clause = line.trim().split("\\ "); + int i; + for (i = 0; i < clause.length - 1; i++) { + int lit = Integer.parseInt(clause[i]); + if ((lit > 0 ? valueOf(lit) : !valueOf(Math.abs(lit)))) + break; + } + if (i == clause.length - 1) + return false; + line = br.readLine(); + } + return true; + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + try { + if (br != null) br.close(); + } catch (IOException e) { + } + } + } + + @Override + public boolean valueOf(int variable) { + if (!sat) + throw new RuntimeException("UNSAT"); + return model[variable-1]; + } + + private void finalizeCnf() { + try { + free(); + BufferedInputStream in = new BufferedInputStream(new FileInputStream(cnfFile)); + File tmp = new File(cnfFile + ".tmp"); + BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(tmp)); + byte[] header = String.format("p cnf %s %s\n", vars, clauses).getBytes(); + out.write(header); + int ch; + while ((ch = in.read()) != -1) { + out.write(ch); + } + in.close(); + out.close(); + tmp.renameTo(cnfFile); + } catch (IOException e) { + throw new RuntimeException("could not preprend header to cnf file: " + cnfFile.getAbsolutePath(), e); + } + } + + private File runMinisat() { + try { + File modelFile = File.createTempFile("minisat_model", ".txt"); + modelFile.deleteOnExit(); + String cmd = String.format("minisat -verb=0 %s %s", cnfFile.getAbsolutePath(), modelFile.getAbsolutePath()); + Process p = Runtime.getRuntime().exec(cmd); + int retVal = p.waitFor(); + if (retVal == 0) + throw new RuntimeException("couldn't run shell command: " + cmd); + return modelFile; + } catch (Exception e) { + throw new RuntimeException("error during solving", e); + } + } + + private void readModel(File modelFile) { + try { + BufferedInputStream in = new BufferedInputStream(new FileInputStream(modelFile)); + String line = readLine(in).trim(); + if (!"SAT".equals(line)) { + sat = false; + model = null; + return; + } + sat = true; + model = new boolean[vars]; + int chCode; + int cnt = 0; + int curr = 0; + boolean sign = true; + while ((chCode = in.read()) != -1) { + char ch = (char)chCode; + switch (ch) { + case '-': + sign = false; + break; + case ' ': case '\n': + if (curr == 0) + break; + assert curr == cnt + 1; + model[cnt] = sign; + cnt++; + curr = 0; + sign = true; + break; + default: + int x = ch - '0'; + assert x >= 0 && x <= 9; + curr = 10*curr + x; + break; + } + } + in.close(); + } catch (IOException e) { + throw new RuntimeException("couldn't read model file: " + model); + } + } + + private String readLine(InputStream in) throws IOException { + StringBuilder sb = new StringBuilder(); + while (true) { + int ch = in.read(); + if (ch == -1) break; + if (ch == '\n') break; + sb.append((char)ch); + } + return sb.toString(); + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/MiniSatProver.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/MiniSatProver.java new file mode 100644 index 00000000..822533bf --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/MiniSatProver.java @@ -0,0 +1,201 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.satlab; + +import java.util.Iterator; + +import kodkod.util.ints.IntBitSet; +import kodkod.util.ints.IntIterator; +import kodkod.util.ints.IntSet; + +/** + * Java wrapper for Niklas En and Niklas Srensson MiniSAT solver + * with proof logging. + * @author Emina Torlak + */ +final class MiniSatProver extends NativeSolver implements SATProver { + private LazyTrace proof; + /** + * Constructs a new MiniSat prover wrapper. + */ + MiniSatProver() { + super(make()); + proof = null; + } + + /** + * Modifies the given raw trace so that it conforms to the + * specification of {@linkplain ArrayTrace#ArrayTrace(int[][], int)}, + * if the array contains no null entries, and to the specfication of + * {@linkplain ArrayTrace#ArrayTrace(ArrayTrace, IntSet, int[][])} + * otherwise. + * @ensures modifies the trace so that it conforms to the specification + * of one of the ArrayTrace constructors. + * @return trace + */ + private int[][] format(int[][] trace) { + final int length = trace.length; + final IntSet resolvents = new IntBitSet(length); + final int offset = numberOfVariables() + 1; + for(int i = 0; i < length; i++) { + int[] clause = trace[i]; + if (clause!=null && clause[0]>=offset) { + clause[0] -= offset; + resolvents.add(i); + } + } + + final int axioms = length - resolvents.size(); + if (resolvents.min() itr = proof.iterator(next); itr.hasNext();) { + Clause c = itr.next(); + if (!addClause(prover, c.toArray())) { + throw new AssertionError("could not add non-redundant clause: " + c); + } + } + + if (!solve(prover)) { + adjustClauseCount(next.size()); + int[][] trace = trace(prover, false); + free(prover); + proof = new LazyTrace(proof, next, format(trace)); + } else { + free(prover); + } + } + } + + /** + * {@inheritDoc} + * @see java.lang.Object#toString() + */ + public String toString() { + return "MiniSatProver"; + } + + + static { + loadLibrary("minisatprover"); + } + + /** + * Returns a pointer to an instance of MiniSAT. + * @return a pointer to an instance of minisat. + */ + private static native long make(); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#free(long) + */ + native void free(long peer); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#addVariables(long, int) + */ + native void addVariables(long peer, int numVariables); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#addClause(long, int[]) + */ + native boolean addClause(long peer, int[] lits); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#solve(long) + */ + native boolean solve(long peer); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#valueOf(long, int) + */ + native boolean valueOf(long peer, int literal); + + /** + * Returns an array of arrays that encodes the most recently generated + * resolution trace. The resolution trace is encoded as follows. Let + * R be the returned array. For all 0 <= i < trace.length such that + * R[i][0] > this.numberOfVariables(), the array R[i] encodes a + * resolvent clause. In particular, (R[i][0] - this.numberOfVariables() - 1) < i + * is the index of the 0th antecedent of R[i] in R; for each 0 < j < R[i].length, + * R[i][j] < i and R[i][j] is the index of the jth antecedent of R[i] in R. + * For all 0 <= i < trace.length-1 such that + * R[i][0] <= this.numberOfVariables(), R[i] contains the literals of the ith axiom, + * sorted in the increasing order of absolute values, if recordAxioms is true; otherwise R[i] is null. + * @return an array of arrays that encodes the most recently generated resolution trace + */ + native int[][] trace(long peer, boolean recordAxioms); +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/NativeSolver.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/NativeSolver.java new file mode 100644 index 00000000..f48454b3 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/NativeSolver.java @@ -0,0 +1,255 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.satlab; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Arrays; + +import kodkod.engine.config.Options; + +/** + * A skeleton implementation of a wrapper for a sat solver + * accessed through JNI. + * + * @author Emina Torlak + */ +abstract class NativeSolver implements SATSolver { + /** + * The memory address of the native instance wrapped by this wrapper. + */ + private long peer; + private Boolean sat; + private int clauses, vars; + + private OutputStream cnfFile; + + /** + * Constructs a new wrapper for the given + * instance of the native solver. + */ + NativeSolver(long peer) { + this.peer = peer; + this.clauses = this.vars = 0; + this.sat = null; + try { + if (Options.isDebug()) + cnfFile = new BufferedOutputStream(new FileOutputStream(new File(System.getProperty("java.io.tmpdir"), "cnf_kk.cnf"))); + } catch (IOException e) { + } + } + + /** + * Loads the JNI library with the given name. + */ + static void loadLibrary(String library) { + try { System.loadLibrary(library); return; } catch(UnsatisfiedLinkError ex) { } + try { System.loadLibrary(library+"x1"); return; } catch(UnsatisfiedLinkError ex) { } + try { System.loadLibrary(library+"x2"); return; } catch(UnsatisfiedLinkError ex) { } + try { System.loadLibrary(library+"x3"); return; } catch(UnsatisfiedLinkError ex) { } + try { System.loadLibrary(library+"x4"); return; } catch(UnsatisfiedLinkError ex) { } + System.loadLibrary(library+"x5"); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.SATSolver#numberOfVariables() + */ + public final int numberOfVariables() { + return vars; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.SATSolver#numberOfClauses() + */ + public final int numberOfClauses() { + return clauses; + } + + /** + * Adjusts the internal clause count so that the next call to {@linkplain #numberOfClauses()} + * will return the given value. + * @requires clauseCount >= 0 + * @ensures adjusts the internal clause so that the next call to {@linkplain #numberOfClauses()} + * will return the given value. + */ + void adjustClauseCount(int clauseCount) { + assert clauseCount >= 0; + clauses = clauseCount; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.SATSolver#addVariables(int) + * @see #addVariables(long, int) + */ + public final void addVariables(int numVars) { + if (numVars < 0) + throw new IllegalArgumentException("vars < 0: " + numVars); + else if (numVars > 0) { + vars += numVars; + addVariables(peer, numVars); + } + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.SATSolver#addClause(int[]) + * @see #addClause(long, int[]) + */ + public final boolean addClause(int[] lits) { + if (lits.length > 0) { + if (addClause(peer, lits)) { + clauses++; + try { + if (Options.isDebug()) cnfFile.write((Arrays.toString(lits) + " 0\n").getBytes()); + } catch (IOException e) {} + return true; + } + } + return false; + } + + + /** + * Returns a pointer to the C++ peer class (the native instance wrapped by this object). + * @return a pointer to the C++ peer class (the native instance wrapped by this object). + */ + final long peer() { return peer; } + + /** + * Returns the current sat of the solver. + * @return null if the sat is unknown, TRUE if the last + * call to solve() yielded SAT, and FALSE if the last call to + * solve() yielded UNSAT. + */ + final Boolean status() { return sat; } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.SATSolver#solve() + * @see #solve(long) + */ + public final boolean solve() { + try { + if (Options.isDebug()) { + cnfFile.write(String.format("p cnf %s %s\n", vars, clauses).getBytes()); + cnfFile.flush(); + cnfFile.close(); + } + } catch (IOException e) { + } + return (sat = solve(peer)); + } + + + /** + * Throws an IllegalArgumentException if variable !in this.variables. + * Otherwise does nothing. + * @throws IllegalArgumentException - variable !in this.variables + */ + final void validateVariable(int variable) { + if (variable < 1 || variable > vars) + throw new IllegalArgumentException(variable + " !in [1.." + vars+"]"); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.SATSolver#valueOf(int) + */ + public final boolean valueOf(int variable) { + if (!Boolean.TRUE.equals(sat)) + throw new IllegalStateException(); + validateVariable(variable); + return valueOf(peer, variable); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.SATSolver#free() + */ + public synchronized final void free() { + if (peer!=0) { +// System.out.println("freeing " + peer + " " + getClass()); + free(peer); + peer = 0; + } // already freed + } + + + /** + * Releases the resources used by this native solver. + */ + protected final void finalize() throws Throwable { + super.finalize(); + free(); + } + + /** + * Releases the resources associated with + * the native solver at the given memory address. + * This method must be called when the object holding the + * given reference goes out of scope to avoid + * memory leaks. + * @ensures releases the resources associated + * with the given native peer + */ + abstract void free(long peer); + + /** + * Adds the specified number of variables to the given native peer. + * @ensures increases the vocabulary of the given native peer by + * the specified number of variables + */ + abstract void addVariables(long peer, int numVariables); + + /** + * Ensures that the given native peer logically contains the + * specified clause and returns true if the solver's clause database + * changed as a result of the call. + * @requires all i: [0..lits.length) | abs(lits[i]) in this.variables + * @requires all disj i,j: [0..lits.length) | abs(lits[i]) != abs(lits[j]) + * @ensures ensures that the given native peer logically contains the specified clause + * @return true if the peer's clause database changed as a result of the call; a negative integer if not. + */ + abstract boolean addClause(long peer, int[] lits); + + /** + * Calls the solve method on the given native peer. + * @return true if the clauses in the solver are SAT; + * otherwise returns false. + */ + abstract boolean solve(long peer); + + /** + * Returns the assignment for the given literal + * by the specified native peer + * @requires the last call to {@link #solve(long) solve(peer)} returned SATISFIABLE + * @return the assignment for the given literal + */ + abstract boolean valueOf(long peer, int literal); + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/ReductionStrategy.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/ReductionStrategy.java new file mode 100644 index 00000000..efed092d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/ReductionStrategy.java @@ -0,0 +1,65 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.satlab; + +import kodkod.util.ints.IntSet; + + +/** + * Strategy for reducing the unsatisfiable core of + * a {@link SATProver}. + * @specfield traces: ResolutionTrace[] + * @specfield nexts: IntSet[] + * @invariant #traces = #nexts + * @invariant no disj i,j: [0..#nexts) | traces[i] = traces[j] && nexts[i] = nexts[j] + * @see SATProver#reduce(ReductionStrategy) + * @author Emina Torlak + */ +public interface ReductionStrategy { + + /** + * Returns the next subtrace of the specified trace to be analyzed, given + * as a set of indices into the trace. + * If there are no more subtraces to be analyzed (i.e. the given trace is + * minimal according to the minimality measure used by this strategy), + * returns the empty set. + * @requires + *
+	 * let t = this.traces[#this.traces-1], n = this.nexts[#this.nexts-1] | 
+	 *  unsat(t.elts[n].literals) => 
+	 *   (all i: n.ints | let j = #{k: n.ints | k < i} | t.elts[i].equals(trace.elts[j])) 
+	 *  else
+	 *   trace = t
+	 * 
+ * @ensures + *
 
+	 *  let next = { i: int | 0 <= i < trace.size()-1 } |
+	 *   trace.elts[next].antecedents in trace.elts[next] and 
+	 *   (some i: [0..#trace) | i !in next and no trace[i].antecedents) and  
+	 *   this.nexts' = this.nexts + #this.nexts->next and
+	 *   this.traces' = this.traces + #this.traces->trace 
+	 * 
+ * @return this.nexts'[#this.nexts-1] + */ + public IntSet next(ResolutionTrace trace); + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/ResolutionTrace.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/ResolutionTrace.java new file mode 100644 index 00000000..abfeeeb8 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/ResolutionTrace.java @@ -0,0 +1,178 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.satlab; + +import java.util.Iterator; + +import kodkod.util.ints.IntSet; + + +/** + *

A proof of unsatisfiability generated by a {@linkplain SATProver}. + * Formally, a resolution trace is a sequence of inferences made by a + * prover that ends in a conflict (empty clause). An element in a resolution + * trace is called a clause. There are two kinds of clauses in the trace: + * axioms and resolvents. Axioms are the clauses given to the + * prover via the {@linkplain SATSolver#addClause(int[])} method, and resolvents are + * the clauses derived by the prover from axioms or previously learned resolvents through + * resolution.

+ * + *

Clauses in a resolution trace are ordered as follows. The first |A| elements + * in the trace correspond to the axioms given to the prover (i.e. prover.clauses). + * An axiom a1 precedes an axiom a2 in the trace if and only if + * a1 was added to the prover before a2. (An axiom is "added" to the + * prover, and appears in the trace, if and only if the corresponding call to {@linkplain SATSolver#addClause(int[])}) + * returned true.) The remaining elements in the trace + * are the resolvents. A resolvent r succeeds all of the resolvents needed for its derivation + * (i.e. all resolvents reachable from r via the {@linkplain Clause#antecedents()} relation). + * The last element in the trace is the conflict resolvent. The axioms that are reachable from the conflict + * form the unsatisfiable core of the trace.

+ * + * @specfield prover: SATProver + * @specfield elts: Clause[] + * @specfield conflict: elts[#elts-1] + * @invariant #elts = #(prover.clauses + prover.resolvents) + * @invariant elts[[0..#prover.clauses)].literals = prover.clauses + * @invariant elts[[#prover.clauses..#elts)].literals = prover.resolvents + * @invariant all i: [0..#prover.clauses) | no elts[i].antecedents + * @invariant all i: [#prover.clauses..#elts) | all ante: elts[i].antecedents[int] | elts.ante < i + * @invariant no conflict.literals + * + * @author Emina Torlak + */ +public interface ResolutionTrace extends Iterable { + + /** + * Returns the length of this trace. + * @return #this.elts + */ + public int size(); + + /** + * Returns an iterator over the elements in this trace in proper sequence. + *

Note:The clause objects returned by the iterator are not + * required to be immutable. In particular, the state of a clause object + * returned by next() (as well as the state of any object obtained + * through that clause's {@linkplain Clause#antecedents()} method) is guaranteed + * to remain the same only until the subsequent call to the next() method + * of the iterator instance.

+ * @return an iterator over the elements in this trace in proper sequence. + */ + public abstract Iterator iterator(); + + /** + * Returns an iterator over the elements at the given indices in this trace, in proper sequence. + *

Note:The clause objects returned by the iterator are not + * required to be immutable. In particular, the state of a clause object + * returned by next() (as well as the state of any object obtained + * through that clause's {@linkplain Clause#antecedents()} method) is guaranteed + * to remain the same only until the subsequent call to the next() method + * of the iterator instance.

+ * @requires indices.min() >= 0 && indices.max() < this.size() + * @return an iterator over the elements at the given indices in this trace, in proper sequence. + * @throws IndexOutOfBoundsException - indices.min() < 0 || indices.max() >= this.size() + */ + public abstract Iterator iterator(IntSet indices); + + /** + * Returns an iterator over the elements at the given indices in this trace, in the + * reverse order of indices. + *

Note:The clause objects returned by the iterator are not + * required to be immutable. In particular, the state of a clause object + * returned by next() (as well as the state of any object obtained + * through that clause's {@linkplain Clause#antecedents()} method) is guaranteed + * to remain the same only until the subsequent call to the next() method + * of the iterator instance.

+ * @requires indices.min() >= 0 && indices.max() < this.size() + * @return an iterator over the elements at the given indices in this trace, in the + * reverse order of indices. + * @throws IndexOutOfBoundsException - indices.min() < 0 || indices.max() >= this.size() + */ + public abstract Iterator reverseIterator(IntSet indices); + + /** + * Returns the indices of the axioms that form the unsatisfiable core of this trace. + * @return { i: int | no this.elts[i].antecedents and this.elts[i] in this.conflict.^antecedents } + */ + public abstract IntSet core(); + + /** + * Returns the indices of the axioms in this trace. + * @return { i: int | this.elts[i] in this.prover.clauses } + */ + public abstract IntSet axioms(); + + /** + * Returns the indices of the resolvents in this trace. + * @return { i: int | this.elts[i] in this.prover.resolvents } + */ + public abstract IntSet resolvents(); + + /** + * Returns the indices of all clauses reachable from the clauses at the given indices + * by following the antecedent relation zero or more times. + * @requires indices.min() >= 0 && indices.max() < this.size() + * @return { i: int | this.elts[i] in this.elts[indices].*antecedents } + * @throws IllegalArgumentException - indices.min() < 0 || indices.max() >= this.size() + */ + public abstract IntSet reachable(IntSet indices); + + /** + * Returns the indices of all clauses reachable from the clauses at the given indices + * by following the transpose of the antecedent relation zero or more times. + * @requires indices.min() >= 0 && indices.max() < this.size() + * @return { i: int | this.elts[i] in this.elts[indices].*~antecedents } + * @throws IllegalArgumentException - indices.min() < 0 || indices.max() >= this.size() + */ + public abstract IntSet backwardReachable(IntSet indices); + + /** + * Returns the indices of all clauses in this trace that can be learned solely from the + * clauses with the given indices. + * @requires indices.min() >= 0 && indices.max() < this.size() + * @return { i: int | this.elts[i].*antecedents = this.elts[indices].*antecedents + this.elts[i].*antecedents & this.elts[indices].*~antecedents } + * @throws IllegalArgumentException - indices.min() < 0 || indices.max() >= this.size() + */ + public abstract IntSet learnable(IntSet indices); + + /** + * Returns the indices of all clauses in this trace that can be learned solely and directly from the + * clauses with the given indices. + * @requires indices.min() >= 0 && indices.max() < this.size() + * @return { i: int | this.elts[i].antecedents in this.elts[indices] } + * @throws IllegalArgumentException - indices.min() < 0 || indices.max() >= this.size() + */ + public abstract IntSet directlyLearnable(IntSet indices); + + + /** + * Returns the clause at the given index. Note that this method is not required + * to always return the same Clause object; it is only required to return Clause + * objects that are equal according to their equals methods. The Clause + * objects returned by this method are guaranteed to be immutable. + * @requires 0 <= index < this.size() + * @return this.elts[index] + * @throws IndexOutOfBoundsException - 0 < index || index >= this.size() + */ + public abstract Clause get(int index); + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/SAT4J.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/SAT4J.java new file mode 100644 index 00000000..dc07ccd6 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/SAT4J.java @@ -0,0 +1,356 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.satlab; + +import java.util.NoSuchElementException; +import org.sat4j.specs.ContradictionException; +import org.sat4j.specs.ISolver; +import org.sat4j.specs.IVecInt; +import org.sat4j.specs.IteratorInt; + +/** + * A wrapper class that provides + * access to the basic funcionality of the MiniSAT solvers + * (org.sat4j.specs.ISolver) from CRIL. + * + * @author Emina Torlak + */ +final class SAT4J implements SATSolver { + private ISolver solver; + private final ReadOnlyIVecInt wrapper; + private Boolean sat; + private int vars, clauses; + + /** + * Constructs a wrapper for the given instance + * of ISolver. + * @throws NullPointerException - solver = null + */ + SAT4J(ISolver solver) { + if (solver==null) + throw new NullPointerException("solver"); + this.solver = solver; + this.wrapper = new ReadOnlyIVecInt(); + this.sat = null; + this.vars = this.clauses = 0; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.SATSolver#numberOfVariables() + */ + public int numberOfVariables() { + return vars; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.SATSolver#numberOfClauses() + */ + public int numberOfClauses() { + return clauses; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.SATSolver#addVariables(int) + */ + public void addVariables(int numVars) { + if (numVars < 0) + throw new IllegalArgumentException("numVars < 0: " + numVars); + else if (numVars > 0) { + vars += numVars; + solver.newVar(vars); + } + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.SATSolver#addClause(int[]) + */ + public boolean addClause(int[] lits) { + try { + if (!Boolean.FALSE.equals(sat)) { + clauses++; + solver.addClause(wrapper.wrap(lits)); +// for(int lit : lits) { +// System.out.print(lit + " "); +// } +// System.out.println(0); + return true; + } + + } catch (ContradictionException e) { + sat = Boolean.FALSE; + } + return false; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.SATSolver#solve() + */ + public boolean solve() { + try { + if (!Boolean.FALSE.equals(sat)) + sat = Boolean.valueOf(solver.isSatisfiable()); + return sat; + } catch (org.sat4j.specs.TimeoutException e) { + throw new RuntimeException("timed out"); + } + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.SATSolver#valueOf(int) + */ + public final boolean valueOf(int variable) { + if (!Boolean.TRUE.equals(sat)) + throw new IllegalStateException(); + if (variable < 1 || variable > vars) + throw new IllegalArgumentException(variable + " !in [1.." + vars+"]"); + return solver.model(variable); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.SATSolver#free() + */ + public synchronized final void free() { + solver = null; + } + + /** + * A wrapper for an int array that provides + * read-only access to the array via the IVecInt interface. + * + * @author Emina Torlak + */ + private static final class ReadOnlyIVecInt implements IVecInt { + private static final long serialVersionUID = 1451465675531453944L; + + private int[] vec; + + /** + * Sets this.vec to the given vector + * and returns this. + */ + IVecInt wrap(int[] vec) { + this.vec = vec; + return this; + } + + public int size() { + return vec.length; + } + + public boolean isEmpty() { + return size() == 0; + } + + public void shrink(int arg0) { + throw new UnsupportedOperationException(); + } + + public void shrinkTo(int arg0) { + throw new UnsupportedOperationException(); + } + + public IVecInt pop() { + throw new UnsupportedOperationException(); + } + + public void growTo(int arg0, int arg1) { + throw new UnsupportedOperationException(); + } + + public void ensure(int arg0) { + throw new UnsupportedOperationException(); + } + + public IVecInt push(int arg0) { + throw new UnsupportedOperationException(); + } + + public void unsafePush(int arg0) { + throw new UnsupportedOperationException(); + } + + public int unsafeGet(int arg0) { + return vec[arg0]; + } + + public void clear() { + throw new UnsupportedOperationException(); + } + + public int last() { + return vec[vec.length - 1]; + } + + public int get(int arg0) { + if (arg0 < 0 || arg0 >= vec.length) + throw new IndexOutOfBoundsException("arg0: " + arg0); + return vec[arg0]; + } + + public void set(int arg0, int arg1) { + throw new UnsupportedOperationException(); + } + + public boolean contains(int arg0) { + for(int i : vec) { + if (i==arg0) return true; + } + return false; + } + + public void copyTo(IVecInt arg0) { + int argLength = arg0.size(); + arg0.ensure(argLength + vec.length); + for(int i : vec) { + arg0.set(argLength++, i); + } + } + + public void copyTo(int[] arg0) { + assert arg0.length >= vec.length; + System.arraycopy(vec,0, arg0, 0, vec.length); + } + + public void moveTo(IVecInt arg0) { + throw new UnsupportedOperationException(); + } + + public void moveTo2(IVecInt arg0) { + throw new UnsupportedOperationException(); + } + + public void moveTo(int[] arg0) { + throw new UnsupportedOperationException(); + } + + public void moveTo(int arg0, int arg1) { + throw new UnsupportedOperationException(); + } + + public void insertFirst(int arg0) { + throw new UnsupportedOperationException(); + } + + public void remove(int arg0) { + throw new UnsupportedOperationException(); + } + + public int delete(int arg0) { + throw new UnsupportedOperationException(); + } + + public void sort() { + throw new UnsupportedOperationException(); + } + + public void sortUnique() { + throw new UnsupportedOperationException(); + } + + public IteratorInt iterator() { + return new IteratorInt() { + int cursor = 0; + public boolean hasNext() { + return cursor < vec.length; + } + public int next() { + if (!hasNext()) + throw new NoSuchElementException(); + return vec[cursor++]; + } + }; + } + + public int containsAt(int e) { + for(int n=vec.length, i=0; iSAT4J solvers, + * the zchaff solver from Princeton, + * and the MiniSat solver by + * Niklas Eén and Niklas Sörensson. + * @author Emina Torlak + */ +public abstract class SATFactory { + + /** + * Constructs a new instance of SATFactory. + */ + protected SATFactory() {} + + /** + * The factory that produces instances of the default sat4j solver. + * @see org.sat4j.core.ASolverFactory#defaultSolver() + */ + public static final SATFactory DefaultSAT4J = new SATFactory() { + public SATSolver instance() { + return new SAT4J(SolverFactory.instance().defaultSolver()); + } + public String toString() { return "DefaultSAT4J"; } + }; + + /** + * The factory that produces instances of the "light" sat4j solver. The + * light solver is suitable for solving many small instances of SAT problems. + * @see org.sat4j.core.ASolverFactory#lightSolver() + */ + public static final SATFactory LightSAT4J = new SATFactory() { + public SATSolver instance() { + return new SAT4J(SolverFactory.instance().lightSolver()); + } + public String toString() { return "LightSAT4J"; } + }; + + /** + * The factory that produces instances of the zchaff solver from Princeton; + * the returned instances + * support only basic sat solver operations (adding variables/clauses, + * solving, and obtaining a satisfying solution, if any). ZChaff is not incremental. + */ + public static final SATFactory ZChaff = new SATFactory() { + public SATSolver instance() { + return new ZChaff(); + } + public boolean incremental() { return false; } + public String toString() { return "ZChaff"; } + }; + + + + /** + * The factory the produces {@link SATMinSolver cost-minimizing} + * instances of the zchaff solver from Princeton. Note that cost minimization + * can incur a time and/or memory overhead during solving, + * so if you do not need this functionality, use the {@link #ZChaff} factory + * instead. ZChaffMincost is not incremental. + */ + public static final SATFactory ZChaffMincost = new SATFactory() { + public SATSolver instance() { + return new ZChaffMincost(); + } + @Override + public boolean minimizer() { return true; } + public boolean incremental() { return false; } + public String toString() { return "ZChaffMincost"; } + }; + + /** + * The factory the produces {@link SATProver proof logging} + * instances of the MiniSat solver. Note that core + * extraction can incur a significant time overhead during solving, + * so if you do not need this functionality, use the {@link #MiniSat} factory + * instead. + */ + public static final SATFactory MiniSatProver = new SATFactory() { + public SATSolver instance() { + return new MiniSatProver(); + } + @Override + public boolean prover() { return true; } + public String toString() { return "MiniSatProver"; } + }; + + /** + * The factory that produces instances of Niklas Eén and Niklas Sörensson's + * MiniSat solver. + */ + public static final SATFactory MiniSat = new SATFactory() { + public SATSolver instance() { + return new MiniSat(); + } + public String toString() { return "MiniSat"; } + }; + + public static final SATFactory MiniSatExternal = new SATFactory() { + public SATSolver instance() { + return new MiniSatExternal(); + } + public String toString() { return "MiniSatExternal"; } + }; + + + /** + * Returns a SATFactory that produces instances of the specified + * SAT4J solver. For the list of available SAT4J solvers see + * {@link org.sat4j.core.ASolverFactory#solverNames() org.sat4j.core.ASolverFactory#solverNames()}. + * @requires solverName is a valid solver name + * @return a SATFactory that returns the instances of the specified + * SAT4J solver + * @see org.sat4j.core.ASolverFactory#solverNames() + */ + public static final SATFactory sat4jFactory(final String solverName) { + return new SATFactory() { + @Override + public SATSolver instance() { + return new SAT4J(SolverFactory.instance().createSolverByName(solverName)); + } + public String toString() { return solverName; } + }; + } + + /** + * Returns a SATFactory that produces SATSolver wrappers for the external + * SAT solver specified by the executable parameter. The solver's input + * and output formats must conform to the SAT competition standards + * (http://www.satcompetition.org/2004/format-solvers2004.html). The solver + * will be called with the specified options, and the given tempInput file name will + * be used to store the generated CNF files. If the tempOutput string is empty, + * the solver specified by the executable string is assumed to write its output + * to standard out; otherwise, the + * solver is assumed to write its output to the tempOutput file. It is the caller's responsibility to + * delete the temporary file(s) when no longer needed. External solvers are never incremental. + * @return SATFactory that produces interruptible SATSolver wrappers for the specified external + * SAT solver + */ + public static final SATFactory externalFactory(final String executable, final String tempInput, final String tempOutput, final String... options) { + return new SATFactory() { + + @Override + public SATSolver instance() { + return new ExternalSolver(executable, tempInput, tempOutput, options); + } + + @Override + public boolean incremental() { + return false; + } + }; + } + + + /** + * Returns an instance of a SATSolver produced by this factory. + * @return a SATSolver instance + */ + public abstract SATSolver instance(); + + /** + * Returns true if the solvers returned by this.instance() are + * {@link SATProver SATProvers}. Otherwise returns false. + * @return true if the solvers returned by this.instance() are + * {@link SATProver SATProvers}. Otherwise returns false. + */ + public boolean prover() { + return false; + } + + /** + * Returns true if the solvers returned by this.instance() are + * {@link SATMinSolver SATMinSolvers}. Otherwise returns false. + * @return true if the solvers returned by this.instance() are + * {@link SATMinSolver SATMinSolvers}. Otherwise returns false. + */ + public boolean minimizer() { + return false; + } + + /** + * Returns true if the solvers returned by this.instance() are incremental; + * i.e. if clauses/variables can be added to the solver between multiple + * calls to solve(). + * @return true if the solvers returned by this.instance() are incremental + */ + public boolean incremental() { + return true; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/SATMinSolver.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/SATMinSolver.java new file mode 100644 index 00000000..d003cdae --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/SATMinSolver.java @@ -0,0 +1,58 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.satlab; + +/** + * Provides an interface to a SAT solver that produces + * minimal cost solutions. That is, given a CNF formula + * and a function f from the variables to non-negative integer, + * the solver produces the solution that minimizes the expression + * sum(f(v)*valueOf(v)) for all variables v, where valueOf(v) is + * 1 if the variable is set to TRUE and 0 otherwise. + * + * @specfield variables: set [1..) + * @specfield cost: variables -> one [0..) + * @specfield clauses: set Clause + * @invariant all i: [2..) | i in variables => i-1 in variables + * @invariant all c: clauses | all lit: c.literals | lit in variables || -lit in variables + * @invariant all c: clauses | all disj i,j: c.literals | abs(i) != abs(j) + * @author Emina Torlak + */ +public interface SATMinSolver extends SATSolver { + + /** + * Sets the cost of the given variable to the specified value. + * @requires variable in this.variables && cost >= 0 + * @ensures this.cost' = this.cost ++ variable -> cost + * @throws IllegalArgumentException - variable !in this.variables || cost < 0 + */ + public abstract void setCost(int variable, int cost); + + /** + * Returns the cost of setting the given variable to TRUE. + * @requires variable in this.variables + * @return this.cost[variable] + * @throws IllegalArgumentException - variable !in this.variables + */ + public abstract int costOf(int variable); + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/SATProver.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/SATProver.java new file mode 100644 index 00000000..f29daaf4 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/SATProver.java @@ -0,0 +1,77 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.satlab; + +/** + * Provides an interface to a SAT solver that can generate + * proofs of unsatisfiability. + * + * @specfield variables: set [1..) + * @specfield clauses: set Clause + * @specfield resolvents: set Clause + * @invariant all i: [2..) | i in variables => i-1 in variables + * @invariant all c: clauses + resolvents | all lit: c.lits | lit in variables || -lit in variables + * @invariant all c: clauses + resolvents | all disj i,j: c.lits | abs(i) != abs(j) + * @author Emina Torlak + */ +public interface SATProver extends SATSolver { + + /** + * Returns a resolution-based proof of unsatisfiability of this.clauses. + * @requires {@link SATSolver#solve()} has been called, and it returned false + * @return { t: ResolutionTrace | t.prover = this } + * @throws IllegalStateException - {@link SATSolver#solve()} has not been called, + * or the last call to {@link SATSolver#solve()} returned true + */ + public ResolutionTrace proof(); + + /** + * Uses the given reduction strategy to remove irrelevant clauses from + * the set of unsatisfiable clauses stored in this prover. + * A clause c is irrelevant iff this.clauses - c is unsatisfiable. + * The removal algorithm works as follows: + *
+	 * for (IntSet next = strategy.next(this.proof()); !next.isEmpty(); next = strategy.next(this.proof())) {
+	 *  let oldClauses = this.clauses, oldResolvents = this.resolvents
+	 *  clear this.clauses
+	 *  clear this.resolvents
+	 *  for(Clause c : this.proof().elts[next]) {
+	 *    if (no c.antecedents)
+	 *      add c to this.clauses
+	 *    else
+	 *      add c to this.resolvents
+	 *  }
+	 *  if (this.solve()) {
+	 *   this.clauses = oldClauses 
+	 *   this.resolvents = oldResolvents
+	 *  }
+	 * }
+	 * 
+ * @requires {@link SATSolver#solve()} has been called, and it returned false + * @ensures modifies this.clauses and this.resolvents according to the algorithm described above + * @throws IllegalStateException - {@link SATSolver#solve()} has not been called, + * or the last call to {@link SATSolver#solve()} returned true + * @see ReductionStrategy + */ + public void reduce(ReductionStrategy strategy); + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/SATSolver.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/SATSolver.java new file mode 100644 index 00000000..dd8a6ff2 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/SATSolver.java @@ -0,0 +1,111 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.satlab; + + +/** + * Provides an interface to a SAT solver. + * + * @specfield variables: set [1..) + * @specfield clauses: set Clause + * @invariant all i: [2..) | i in variables => i-1 in variables + * @invariant all c: clauses | all lit: c.literals | lit in variables || -lit in variables + * @invariant all c: clauses | all disj i,j: c.literals | abs(i) != abs(j) + * @author Emina Torlak + */ +public interface SATSolver { + + /** + * Returns the size of this solver's vocabulary. + * @return #this.variables + */ + public abstract int numberOfVariables(); + + /** + * Returns the number of clauses in this solver. + * @return #this.clauses + */ + public abstract int numberOfClauses(); + + /** + * Adds the specified number of new variables + * to the solver's vocabulary. The behavior of this + * method is undefined if it is called after this.solve() + * has returned false. + * @requires numVars >= 0 + * @ensures this.variables' = [1..#this.variables + numVars] + * @throws IllegalArgumentException - numVars < 0 + */ + public abstract void addVariables(int numVars); + + /** + * Ensures that this solver logically contains the given + * clause, and returns true if this.clauses changed as a + * result of the call. No reference to the specified array + * is kept, so it can be reused. The contents of the array may, + * however, be modified. It is the client's responsibility to + * ensure that no literals in the given array are repeated, or that + * both a literal and its negation are present. The behavior of this + * method is undefined if it is called after this.solve() + * has returned false. + * @requires all i: [0..lits.length) | abs(lits[i]) in this.variables + * @requires all disj i,j: [0..lits.length) | abs(lits[i]) != abs(lits[j]) + * @ensures [[this.clauses']] = ([[this.clauses]] and [[lits]]) + * @return #this.clauses' > #this.clauses + * @throws NullPointerException - lits = null + */ + public abstract boolean addClause(int[] lits); + + /** + * Returns true if there is a satisfying assignment for this.clauses. + * Otherwise returns false. If this.clauses are satisfiable, the + * satisfying assignment for a given variable + * can be obtained by calling {@link #valueOf(int)}. + * If the satisfiability of this.clauses cannot be determined within + * the given number of seconds, a TimeoutException is thrown. + * @return true if this.clauses are satisfiable; otherwise false. + * @throws SATAbortedException -- the call to solve was cancelled or + * could not terminate normally. + */ + public abstract boolean solve() throws SATAbortedException; + + /** + * Returns the boolean value assigned to the given variable by the + * last successful call to {@link #solve()}. + * @requires {@link #solve() } has been called and the + * outcome of the last call was true. + * @return the boolean value assigned to the given variable by the + * last successful call to {@link #solve()}. + * @throws IllegalArgumentException - variable !in this.variables + * @throws IllegalStateException - {@link #solve() } has not been called or the + * outcome of the last call was not true. + */ + public abstract boolean valueOf(int variable); + + /** + * Frees the memory used by this solver. Once free() is called, + * all subsequent calls to methods other than free() may fail. + * @ensures frees the memory used by this solver + */ + public abstract void free(); + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/ZChaff.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/ZChaff.java new file mode 100644 index 00000000..7f55cfd9 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/ZChaff.java @@ -0,0 +1,86 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.satlab; + +/** + * Wrapper for an instance of zchaff that provides + * access to basic functionality. + */ +final class ZChaff extends NativeSolver { + /** + * Constructs an instance of ZChaffBasic. + */ + ZChaff() { + super(make()); + } + + /** + * {@inheritDoc} + * @see java.lang.Object#toString() + */ + public String toString() { + return "ZChaff"; + } + + static { + loadLibrary("zchaff"); + } + + /** + * Creates an instance of zchaff and returns + * its address in memory. + * @return the memory address of an instance + * of the zchaff solver + */ + private static native long make(); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#free(long) + */ + native void free(long peer); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#addVariables(long, int) + */ + native void addVariables(long peer, int numVariables); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#addClause(long, int[]) + */ + native boolean addClause(long peer, int[] lits); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#solve(long) + */ + native boolean solve(long peer); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#valueOf(long, int) + */ + native boolean valueOf(long peer, int literal); + +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/ZChaffMincost.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/ZChaffMincost.java new file mode 100644 index 00000000..10c6cdb5 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/satlab/ZChaffMincost.java @@ -0,0 +1,126 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.satlab; + +/** + * Wrapper for an instance of MinCostZChaff. + * + * @author Emina Torlak + */ +final class ZChaffMincost extends NativeSolver implements SATMinSolver { + + /** + * Constructs an instance of ZChaffMincost. + */ + ZChaffMincost() { + super(make()); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.SATMinSolver#setCost(int, int) + */ + public void setCost(int variable, int cost) { + validateVariable(variable); + if (cost < 0) + throw new IllegalArgumentException("invalid cost: " + cost); + setCost(peer(), variable, cost); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.SATMinSolver#costOf(int) + */ + public int costOf(int variable) { + validateVariable(variable); + return costOf(peer(), variable); + } + + /** + * {@inheritDoc} + * @see java.lang.Object#toString() + */ + public String toString() { + return "ZChaffMincost"; + } + + static { + loadLibrary("zchaffmincost"); + } + + /** + * Creates an instance of zchaff and returns + * its address in memory. + * @return the memory address of an instance + * of the zchaff solver + */ + private static native long make(); + + /** + * Sets the cost of the given variable to the specified value in the + * native zchaff instance at the given address. + * @requires variable is a valid variable identifier && cost >= 0 + * @ensures sets the cost of the given variable to the specified value in the + * native zchaff instance at the given address. + */ + private native void setCost(long peer, int variable, int cost); + + /** + * Retrieves the cost of the given variable in the native zchaff instance at the + * given address. + * @requires variable is a valid variable identifier + * @return the cost of the given variable in the native zchaff instance at the + * given address. + */ + private native int costOf(long peer, int variable); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#free(long) + */ + native void free(long peer); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#addVariables(long, int) + */ + native void addVariables(long peer, int numVariables); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#addClause(long, int[]) + */ + native boolean addClause(long peer, int[] lits); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#solve(long) + */ + native boolean solve(long peer); + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.NativeSolver#valueOf(long, int) + */ + native boolean valueOf(long peer, int literal); + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/AdaptiveRCEStrategy.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/AdaptiveRCEStrategy.java new file mode 100644 index 00000000..0f51a158 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/AdaptiveRCEStrategy.java @@ -0,0 +1,172 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.ucore; + +import kodkod.engine.fol2sat.TranslationLog; +import kodkod.engine.fol2sat.Translator; +import kodkod.engine.satlab.ReductionStrategy; +import kodkod.engine.satlab.ResolutionTrace; +import kodkod.util.ints.IntCollection; +import kodkod.util.ints.IntIterator; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.Ints; +/** + * Adaptive Recycling Core Extraction is a strategy for generating unsat cores that are minimal at the logic level. + * Specifically, let C be a core that is minimal according to this strategy, + * and let F(C) be the top-level logic constraints + * corresponding to C. Then, this strategy guarantees that there is no clause + * c in C such that F(C - c) is a strict subset of F(C). Furthermore, it also + * guarantees that for all f in F(C), F(C) - f is satisfiable. This is a stronger + * guarantee than that of {@linkplain HybridStrategy}. In general, using this strategy + * is more expensive, timewise, than using {@linkplain HybridStrategy}. + * + *

Unlike RCE, ARCE is parameterized with 3 values that control the amount of recycling. The + * first is the noRecycleRatio, which completely disables recycling if it is greater than + * the ratio of the size of the core passed to {@linkplain #next(ResolutionTrace)} and the number of axioms in the + * trace. The default value is .03; if the core makes up only 3 percent of the axioms, no recycling + * will happen. The remaining two parameters are the recycleLimit and the hardnessCutOff. + * If the hardness of the proof passed to {@linkplain #next(ResolutionTrace)} is greater than hardnessCutOff, + * then the number of relevant axioms, |A_r|, plus the number of recycled resolvents is no greater than + * |A_r|*recycleLimit. Otherwise, all valid + * resolvents are recycled (i.e. added to the relevant axioms). + * Proof hardness is the ratio of the trace size to the number of axioms in the trace. + * Default value for hardnessCutOff is 2.0, and default value for recycleLimit is 1.2. + * + *

This implementation of ARCE will work properly only on CNFs generated by the kodkod {@linkplain Translator}.

+ * + * @specfield noRecycleRatio: double + * @specfield hardnessCutOff: double + * @specfield recycleLimit: double + * @invariant noRecycleRatio in [0..1] + * @invariant recycleLimit >= 1 + * @invariant hardnessCutOff >= 1 + * @author Emina Torlak + * @see HybridStrategy + */ +public final class AdaptiveRCEStrategy implements ReductionStrategy { + private final IntCollection varsToTry; + private final double noRecycleRatio, recycleLimit, hardnessCutOff; + private static final boolean DBG = true; + + /** + * Constructs an ARCE strategy that will use the given translation + * log to relate the cnf clauses back to the logic constraints from + * which they were generated. + * @ensures this.hardnessCutOff' = 2 and this.recycleLimit' = 1.2 and this.noRecycleRatio' = .03 + */ + public AdaptiveRCEStrategy(final TranslationLog log) { + this(log, .03, 2.0, 1.2); + } + + /** + * Constructs an ARCE strategy that will use the given translation + * log to relate the cnf clauses back to the logic constraints from + * which they were generated. + * @ensures this.hardnessCutOff' = hardnessCutOff and this.recycleLimit' = recycleLimit and + * this.noRecycleRatio' = noRecycleRatio + */ + public AdaptiveRCEStrategy(final TranslationLog log, double noRecycleRatio, double hardnessCutOff, double recycleLimit) { + varsToTry = StrategyUtils.rootVars(log); + if (noRecycleRatio<0 || noRecycleRatio>1) + throw new IllegalArgumentException("noRecycleRatio must be in [0..1]: " + noRecycleRatio); + if (hardnessCutOff < 1) + throw new IllegalArgumentException("hardnessCutOff must be >=1: " + hardnessCutOff); + if (recycleLimit < 1) + throw new IllegalArgumentException("recycleLimit must be >=1: " + recycleLimit); + this.noRecycleRatio = noRecycleRatio; + this.hardnessCutOff = hardnessCutOff; + this.recycleLimit = recycleLimit; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ReductionStrategy#next(kodkod.engine.satlab.ResolutionTrace) + */ + public IntSet next(ResolutionTrace trace) { + if (varsToTry.isEmpty()) return Ints.EMPTY_SET; // tried everything + + final IntSet relevantVars = StrategyUtils.coreTailUnits(trace); + + + for(IntIterator varItr = varsToTry.iterator( ); varItr.hasNext();) { + final int var = varItr.next(); + varItr.remove(); + if (relevantVars.remove(var)) { // remove maxVar from the set of relevant variables + if (relevantVars.isEmpty()) break; // there was only one root formula left + // get all axioms and resolvents corresponding to the clauses that + // form the translations of formulas identified by relevant vars + final IntSet relevantClauses = clausesFor(trace, relevantVars); + assert !relevantClauses.isEmpty() && !relevantClauses.contains(trace.size()-1); + + if (DBG) System.out.println("relevant clauses: " + relevantClauses.size() + ", removed " + var); + + return relevantClauses; + } + } + + varsToTry.clear(); + return Ints.EMPTY_SET; + } + + + /** + * Returns the indices of all axioms and resolvents + * in the given trace that form the translations of the formulas + * identified by the given variables. This method assumes that + * the axioms in the given trace were generated by the Kodkod + * {@linkplain Translator}. + * @return + * let C = { c: trace.prover.clauses | c.maxVariable() in relevantVars }, + * T = { c1, c2: C | c2.maxVariable() in abs(c1.literals) }, + * A = C.*T | + * trace.backwardReachable(A) - trace.backwardReachable(trace.axioms() - A) + */ + private IntSet clausesFor(ResolutionTrace trace, IntSet relevantVars) { + final double hardness = (double) trace.size() / (double) trace.axioms().size(); + final double coreRatio = ((double) trace.core().size() / (double) trace.axioms().size()); + + if (DBG) System.out.println("\ntrace size: " + trace.size() + ", axioms: " + trace.axioms().size() + ", core: " + trace.core().size() + ", resolvents: " + trace.resolvents().size()); + if (DBG) System.out.println("hardness: " + hardness + ", coreRatio: " + coreRatio); + + final IntSet relevantAxioms = StrategyUtils.clausesFor(trace, relevantVars); + if (DBG) System.out.println("relevant axioms: " + relevantAxioms.size()); + + if (coreRatio < noRecycleRatio) { + return relevantAxioms; + } else if (hardness < hardnessCutOff) { + return trace.learnable(relevantAxioms); + } else { + IntSet current = relevantAxioms, last; + final int maxRelevant = (int) Math.rint(relevantAxioms.size()*recycleLimit); + do { + last = current; + current = trace.directlyLearnable(current); + } while (last.size() < current.size() && current.size() < maxRelevant); + + if (DBG) System.out.println("last: " + last.size() +", current: " + current.size() + ", maxRelevant: " + maxRelevant); + + return current.size() < maxRelevant ? current : last; + } + + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/CRRStrategy.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/CRRStrategy.java new file mode 100644 index 00000000..ea8e3e87 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/CRRStrategy.java @@ -0,0 +1,88 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.ucore; + +import java.util.HashSet; +import java.util.Set; + +import kodkod.engine.satlab.Clause; +import kodkod.engine.satlab.ReductionStrategy; +import kodkod.engine.satlab.ResolutionTrace; +import kodkod.util.ints.IntIterator; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.Ints; + + +/** + * A basic implementation of the Complete ResolutionTrace Refutation algorithm + * for for producing locally minimal cores. + * An unsatisfiable core is locally minimal iff removing any single clause from + * the core will make the resulting formula satisfiable. No heuristic is used + * to pick the clauses to be excluded from the core. + * @specfield traces: [0..)->ResolutionTrace + * @specfield nexts: [0..)->Set + * @invariant traces.ResolutionTrace = nexts.Set + * @invariant all i: [1..) | some traces[i] => some traces[i-1] + * @invariant all i: [0..#nexts) | nexts[i] in traces[i].conflict.^antecedents + * @invariant no disj i,j: [0..#nexts) | traces[i] = traces[j] && nexts[i] = nexts[j] + * @author Emina Torlak + * @see N. Dershowitz, Z. Hanna, and A. Nadel. A scalable algorithm for minimal unsatisfiable core + * extraction. In Proceedings of Ninth International Conference on Theory and Applications of + * Satisfiability Testing (SAT '06). 2006. + */ +public final class CRRStrategy implements ReductionStrategy { + private Set excluded; + + /** + * Constructs a new instance of CRRStrategy. + * @ensures no this.traces' and no this.nexts' + **/ + public CRRStrategy() { + excluded = null; + } + + /** + * Returns the next subset of clauses in the given trace to be analyzed. + * @requires {@inheritDoc} + * @ensures {@inheritDoc} + * @return last(this.nexts') + */ + public final IntSet next(final ResolutionTrace trace) { + final IntSet core = trace.core(); + if (excluded==null) { // the first time this method is called + excluded = new HashSet((int)(StrictMath.round(core.size()*.75))); + } + + for(IntIterator iter = core.iterator(Integer.MAX_VALUE, Integer.MIN_VALUE); iter.hasNext();) { + int index = iter.next(); + if (excluded.add(trace.get(index))) { // haven't tried excluding this one + // get all clauses reachable from the conflict clause + IntSet next = trace.reachable(Ints.singleton(trace.size()-1)); + // remove all clauses backward reachable from the excluded clause + next.removeAll(trace.backwardReachable(Ints.singleton(index))); + return next; + } + } + + return Ints.EMPTY_SET; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/DynamicRCEStrategy.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/DynamicRCEStrategy.java new file mode 100644 index 00000000..a529865e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/DynamicRCEStrategy.java @@ -0,0 +1,248 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.ucore; + +import java.util.Arrays; +import java.util.Iterator; + +import kodkod.engine.fol2sat.TranslationLog; +import kodkod.engine.fol2sat.Translator; +import kodkod.engine.satlab.Clause; +import kodkod.engine.satlab.ReductionStrategy; +import kodkod.engine.satlab.ResolutionTrace; +import kodkod.util.ints.IntBitSet; +import kodkod.util.ints.IntIterator; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.Ints; +import kodkod.util.ints.SparseSequence; +import kodkod.util.ints.TreeSequence; + +/** + * Dynamic Recycling Core Extraction is a strategy for generating unsat cores that are minimal at the logic level. + * Specifically, let C be a core that is minimal according to this strategy, + * and let F(C) be the top-level logic constraints + * corresponding to C. Then, this strategy guarantees that there is no clause + * c in C such that F(C - c) is a strict subset of F(C). Furthermore, it also + * guarantees that for all f in F(C), F(C) - f is satisfiable. This is a stronger + * guarantee than that of {@linkplain HybridStrategy}. In general, using this strategy + * is more expensive, timewise, than using {@linkplain HybridStrategy}. + * + *

Like Adaptive RCE, DRCE is parameterized with 3 values that control the amount of recycling. The + * first is the noRecycleRatio, which completely disables recycling if it is greater than + * the ratio of the size of the core passed to {@linkplain #next(ResolutionTrace)} and the number of axioms in the + * trace. The default value is .03; if the core makes up only 3 percent of the axioms, no recycling + * will happen. The remaining two parameters are the recycleLimit and the hardnessCutOff. + * If the hardness of the proof passed to {@linkplain #next(ResolutionTrace)} is greater than hardnessCutOff, + * then the number of relevant axioms, |A_r|, plus the number of recycled resolvents is no greater than + * |A_r|*recycleLimit. Otherwise, all valid + * resolvents are recycled (i.e. added to the relevant axioms). + * Proof hardness is the ratio of the trace size to the number of axioms in the trace. + * Default value for hardnessCutOff is 2.0, and default value for recycleLimit is 1.2. + * + *

Unlike ARCE, DRCE uses proof information to determine the order in which the constraints are tested for + * membership in a minimal core. ARCE, RCE, SCE and NCE all use the same (arbitrary but deterministic) ordering.

+ * + *

This implementation of DRCE will work properly only on CNFs generated by the kodkod {@linkplain Translator}.

+ * + * @specfield noRecycleRatio: double + * @specfield hardnessCutOff: double + * @specfield recycleLimit: double + * @invariant noRecycleRatio in [0..1] + * @invariant recycleLimit >= 1 + * @invariant hardnessCutOff >= 1 + * @author Emina Torlak + * @see HybridStrategy + */ +public final class DynamicRCEStrategy implements ReductionStrategy { + private final double noRecycleRatio, recycleLimit, hardnessCutOff; + private static final boolean DBG = true; + private final SparseSequence hits; + /** + * Constructs an ARCE strategy that will use the given translation + * log to relate the cnf clauses back to the logic constraints from + * which they were generated. + * @ensures this.hardnessCutOff' = 2 and this.recycleLimit' = 1.2 and this.noRecycleRatio' = .03 + */ + public DynamicRCEStrategy(final TranslationLog log) { + this(log, .03, 2.0, 1.2); + } + + /** + * Constructs an ARCE strategy that will use the given translation + * log to relate the cnf clauses back to the logic constraints from + * which they were generated. + * @ensures this.hardnessCutOff' = hardnessCutOff and this.recycleLimit' = recycleLimit and + * this.noRecycleRatio' = noRecycleRatio + */ + public DynamicRCEStrategy(final TranslationLog log, double noRecycleRatio, double hardnessCutOff, double recycleLimit) { + if (noRecycleRatio<0 || noRecycleRatio>1) + throw new IllegalArgumentException("noRecycleRatio must be in [0..1]: " + noRecycleRatio); + if (hardnessCutOff < 1) + throw new IllegalArgumentException("hardnessCutOff must be >=1: " + hardnessCutOff); + if (recycleLimit < 1) + throw new IllegalArgumentException("recycleLimit must be >=1: " + recycleLimit); + this.noRecycleRatio = noRecycleRatio; + this.hardnessCutOff = hardnessCutOff; + this.recycleLimit = recycleLimit; + this.hits = new TreeSequence(); + for(IntIterator itr = StrategyUtils.rootVars(log).iterator(); itr.hasNext(); ) { + hits.put(itr.next(), null); + } + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ReductionStrategy#next(kodkod.engine.satlab.ResolutionTrace) + */ + public IntSet next(ResolutionTrace trace) { + if (hits.isEmpty()) return Ints.EMPTY_SET; // tried everything + final IntSet relevantVars = StrategyUtils.coreTailUnits(trace); + + final long[] byRelevance = sortByRelevance(trace, relevantVars); + if (DBG) printRelevant(byRelevance); + for(int i = byRelevance.length-1; i>=0; i--) { + final int var = (int)byRelevance[i]; + if (hits.remove(var)!=null) { + // remove maxVar from the set of relevant variables + relevantVars.remove(var); + if (relevantVars.isEmpty()) break; // there was only one root formula left + // get all axioms and resolvents corresponding to the clauses that + // form the translations of formulas identified by relevant vars + final IntSet relevantClauses = clausesFor(trace, relevantVars); + assert !relevantClauses.isEmpty() && !relevantClauses.contains(trace.size()-1); + + if (DBG) System.out.println("relevant clauses: " + relevantClauses.size() + ", removed " + var); + + return relevantClauses; + } + } + + hits.clear(); + return Ints.EMPTY_SET; + } + + private final void printRelevant(long[] byRelevance) { + System.out.print("\nsorted by relevance: "); + for(long r : byRelevance) { + System.out.print((int)(r>>>32) + ":" + (int)r + " "); + } + System.out.println(); + } + + /** + * Returns an array R of longs such that for each i, j in [0..R.length) i < j implies + * that the formula identified by (int)R[i] in this.hits contributes fewer clauses to + * the core of the given trace than the formula identified by (int)R[j]. + * @return an array as described above + */ + private long[] sortByRelevance(ResolutionTrace trace, IntSet relevantVars) { + hits.indices().retainAll(relevantVars); + + if (hits.get(hits.indices().min())==null) { // first call, initialize the hits + for(IntIterator varItr = relevantVars.iterator(); varItr.hasNext(); ) { + final int var = varItr.next(); + final IntSet varReachable = new IntBitSet(var+1); + varReachable.add(var); + hits.put(var, varReachable); + } + for(Iterator clauseItr = trace.reverseIterator(trace.axioms()); clauseItr.hasNext();) { + final Clause clause = clauseItr.next(); + final int maxVar = clause.maxVariable(); + for(IntSet reachableVars : hits.values()) { + if (reachableVars.contains(maxVar)) { + for(IntIterator lits = clause.literals(); lits.hasNext(); ) { + reachableVars.add(StrictMath.abs(lits.next())); + } + } + } + } + } + + final long[] counts = new long[hits.size()]; + + for(Iterator clauseItr = trace.iterator(trace.core()); clauseItr.hasNext(); ) { + final Clause clause = clauseItr.next(); + final int maxVar = clause.maxVariable(); + int i = 0; + for(IntSet reachableVars : hits.values()) { + if (reachableVars.contains(maxVar)) { + counts[i]++; + } + i++; + } + } + + + int i = 0; + for(IntIterator varItr = hits.indices().iterator(); varItr.hasNext();) { + final int var = varItr.next(); + counts[i] = (counts[i]<<32) | var; + i++; + } + + Arrays.sort(counts); + + return counts; + } + + /** + * Returns the indices of all axioms and resolvents + * in the given trace that form the translations of the formulas + * identified by the given variables. This method assumes that + * the axioms in the given trace were generated by the Kodkod + * {@linkplain Translator}. + * @return + * let C = { c: trace.prover.clauses | c.maxVariable() in relevantVars }, + * T = { c1, c2: C | c2.maxVariable() in abs(c1.literals) }, + * A = C.*T | + * trace.backwardReachable(A) - trace.backwardReachable(trace.axioms() - A) + */ + private IntSet clausesFor(ResolutionTrace trace, IntSet relevantVars) { + final double hardness = (double) trace.size() / (double) trace.axioms().size(); + final double coreRatio = ((double) trace.core().size() / (double) trace.axioms().size()); + + if (DBG) System.out.println("trace size: " + trace.size() + ", axioms: " + trace.axioms().size() + ", core: " + trace.core().size() + ", resolvents: " + trace.resolvents().size()); + if (DBG) System.out.println("hardness: " + hardness + ", coreRatio: " + coreRatio); + + final IntSet relevantAxioms = StrategyUtils.clausesFor(trace, relevantVars); + if (DBG) System.out.println("relevant axioms: " + relevantAxioms.size()); + + if (coreRatio < noRecycleRatio) { + return relevantAxioms; + } else if (hardness < hardnessCutOff) { + return trace.learnable(relevantAxioms); + } else { + IntSet current = relevantAxioms, last; + final int maxRelevant = (int) Math.rint(relevantAxioms.size()*recycleLimit); + do { + last = current; + current = trace.directlyLearnable(current); + } while (last.size() < current.size() && current.size() < maxRelevant); + + if (DBG) System.out.println("last: " + last.size() +", current: " + current.size() + ", maxRelevant: " + maxRelevant); + + return current.size() < maxRelevant ? current : last; + } + + } + +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/ECFPStrategy.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/ECFPStrategy.java new file mode 100644 index 00000000..8b993c3b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/ECFPStrategy.java @@ -0,0 +1,61 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.ucore; + +import kodkod.engine.satlab.ReductionStrategy; +import kodkod.engine.satlab.ResolutionTrace; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.Ints; + +/** + * A non-optimal minimization strategy based on the Empty Clause Cone algorithm. + * @author Emina Torlak + * @see L. Zhang and S. Malik. Extracting small unsatisfiable cores from unsatisfiable + * Boolean formula. In Proceedings of Sixth International Conference on Theory and Applications of + * Satisfiability Testing (SAT '03). 2003. + */ +public final class ECFPStrategy implements ReductionStrategy { + private int lastCore; + /** + * Constructs a new instance of the empty clause cone strategy for + * minimizing unsatisfiable cores. + */ + public ECFPStrategy() { + lastCore = Integer.MAX_VALUE; + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ReductionStrategy#next(kodkod.engine.satlab.ResolutionTrace) + */ + public IntSet next(final ResolutionTrace trace) { + final IntSet core = trace.core(); + if (lastCore > core.size()) { + lastCore = core.size(); + return core; + } else { + lastCore = Integer.MIN_VALUE; + return Ints.EMPTY_SET; + } + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/HybridStrategy.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/HybridStrategy.java new file mode 100644 index 00000000..1c1932e1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/HybridStrategy.java @@ -0,0 +1,110 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.ucore; + +import java.util.Iterator; + +import kodkod.engine.fol2sat.TranslationLog; +import kodkod.engine.fol2sat.Translator; +import kodkod.engine.satlab.Clause; +import kodkod.engine.satlab.ReductionStrategy; +import kodkod.engine.satlab.ResolutionTrace; +import kodkod.util.ints.IntBitSet; +import kodkod.util.ints.IntIterator; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.Ints; + +/** + * A hybrid strategy for generating unsat cores that are minimal when mapped + * back onto the logic level. Specifically, let C be a core that is minimal + * according to this strategy, and let F(C) be the top-level logic constraints + * corresponding to C. Then, this strategy guarantees that there is no clause + * c in C such that F(C - c) is a strict subset of F(C). Note that this does + * not guarantee that F(C) itself is minimal. In other words, there could be + * an f in F(C) such that F(C) - f is unsatisfiable. To get a minimal logic core, + * use {@linkplain RCEStrategy}. + * + *

This strategy will work properly only on CNFs generated by the kodkod {@linkplain Translator}.

+ * @author Emina Torlak + * @see RCEStrategy + */ +public final class HybridStrategy implements ReductionStrategy { + private final IntSet topVars; + + /** + * Constructs a hybrid strategy that will use the given translation + * log to relate the cnf clauses back to the logic constraints from + * which they were generated. + */ + public HybridStrategy(TranslationLog log) { + topVars = StrategyUtils.rootVars(log); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ReductionStrategy#next(kodkod.engine.satlab.ResolutionTrace) + */ + public IntSet next(ResolutionTrace trace) { + if (topVars.isEmpty()) return Ints.EMPTY_SET; // tried everything + final IntSet core = trace.core(); + + for(Iterator iter = trace.iterator(core); iter.hasNext();) { + Clause clause = iter.next(); + int maxVar = clause.maxVariable(); + if (topVars.remove(maxVar)) { + // get all core clauses with the given maximum variable + IntSet exclude = coreClausesWithMaxVar(trace, maxVar); + assert !exclude.isEmpty(); + // get all clauses reachable from the conflict clause + IntSet next = trace.reachable(Ints.singleton(trace.size()-1)); + // remove all clauses backward reachable from the clauses with the given maxVar + next.removeAll(trace.backwardReachable(exclude)); + if (!next.isEmpty()) { + return next; + } + } + } + + topVars.clear(); + return Ints.EMPTY_SET; + } + + /** + * Returns the indices of the clauses in the unsatisfiable core of the + * given trace that have the specified maximum variable. + * @return { i: trace.core() | trace[i].maxVariable() = maxVariable } + */ + private static IntSet coreClausesWithMaxVar(ResolutionTrace trace, int maxVariable) { + final IntSet core = trace.core(); + final IntSet restricted = new IntBitSet(core.max()+1); + final Iterator clauses = trace.iterator(core); + final IntIterator indices = core.iterator(); + while(clauses.hasNext()) { + Clause clause = clauses.next(); + int index = indices.next(); + if (clause.maxVariable()==maxVariable) + restricted.add(index); + } + return restricted; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/NCEStrategy.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/NCEStrategy.java new file mode 100644 index 00000000..ea603c93 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/NCEStrategy.java @@ -0,0 +1,81 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.ucore; + +import kodkod.engine.fol2sat.TranslationLog; +import kodkod.engine.fol2sat.Translator; +import kodkod.engine.satlab.ReductionStrategy; +import kodkod.engine.satlab.ResolutionTrace; +import kodkod.util.ints.IntCollection; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.IntTreeSet; +import kodkod.util.ints.Ints; + +/** +* Naive Core Extraction is a strategy for generating unsat cores that are minimal at the logic level. + * Specifically, let C be a core that is minimal according to this strategy, + * and let F(C) be the top-level logic constraints + * corresponding to C. Then, this strategy guarantees that there is no clause + * c in C such that F(C - c) is a strict subset of F(C). Furthermore, it also + * guarantees that for all f in F(C), F(C) - f is satisfiable. This is a stronger + * guarantee than that of {@linkplain HybridStrategy}. In general, using this strategy + * is more expensive, timewise, than using {@linkplain HybridStrategy}. + * + *

This implementation of NCE will work properly only on CNFs generated by the kodkod {@linkplain Translator}.

+* @author Emina Torlak +* @see HybridStrategy +*/ +public final class NCEStrategy implements ReductionStrategy { + private final IntCollection varsToTry; + private final IntSet coreVars; + + /** + * Constructs an NCE strategy that will use the given translation + * log to relate the cnf clauses back to the logic constraints from + * which they were generated. + */ + public NCEStrategy(final TranslationLog log) { + varsToTry = StrategyUtils.rootVars(log); + coreVars = new IntTreeSet();//new IntTreeSet(varsToTry); + coreVars.addAll(varsToTry); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ReductionStrategy#next(kodkod.engine.satlab.ResolutionTrace) + */ + public IntSet next(ResolutionTrace trace) { + if (varsToTry.isEmpty()) return Ints.EMPTY_SET; + // if the last attempt at reduction was unsuccessful, + // add the unit clauses that we tried to discard back to coreVars + coreVars.addAll(StrategyUtils.coreTailUnits(trace)); + final int first = varsToTry.iterator().next();//varsToTry.min(); + varsToTry.remove(first); + coreVars.remove(first); + // get all axioms corresponding to the clauses that + // form the translations of formulas identified by coreVars + final IntSet relevantClauses = StrategyUtils.clausesFor(trace, coreVars); + assert !relevantClauses.isEmpty() && !relevantClauses.contains(trace.size()-1); + return relevantClauses; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/RCEStrategy.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/RCEStrategy.java new file mode 100644 index 00000000..e1534891 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/RCEStrategy.java @@ -0,0 +1,134 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.ucore; + +import kodkod.engine.fol2sat.TranslationLog; +import kodkod.engine.fol2sat.Translator; +import kodkod.engine.satlab.ReductionStrategy; +import kodkod.engine.satlab.ResolutionTrace; +import kodkod.util.ints.IntCollection; +import kodkod.util.ints.IntIterator; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.Ints; + +/** + * Recycling Core Extraction is a strategy for generating unsat cores that are minimal at the logic level. + * Specifically, let C be a core that is minimal according to this strategy, + * and let F(C) be the top-level logic constraints + * corresponding to C. Then, this strategy guarantees that there is no clause + * c in C such that F(C - c) is a strict subset of F(C). Furthermore, it also + * guarantees that for all f in F(C), F(C) - f is satisfiable. This is a stronger + * guarantee than that of {@linkplain HybridStrategy}. In general, using this strategy + * is more expensive, timewise, than using {@linkplain HybridStrategy}. + * + *

This implementation of RCE will work properly only on CNFs generated by the kodkod {@linkplain Translator}.

+ * @author Emina Torlak + * @see HybridStrategy + */ +public class RCEStrategy implements ReductionStrategy { + private final IntCollection varsToTry; + private final int dist; + + /** + * Constructs an RCE strategy that will use the given translation + * log to relate the cnf clauses back to the logic constraints from + * which they were generated. By default, all relevant resolvents + * are used in each iteration. + */ + public RCEStrategy(final TranslationLog log) { + this(log, Integer.MAX_VALUE); + } + + + /** + * Constructs an RCE strategy that will use the given translation + * log to relate the cnf clauses back to the logic constraints from + * which they were generated. The relevant resolvents + * used in each iteration are reachable from the relevant axioms + * in at most dist steps. + * @requires dist >= 0 + */ + public RCEStrategy(final TranslationLog log, int dist) { + if (dist<0) throw new IllegalArgumentException("Resolution distance must be non-negative: " + dist); + varsToTry = StrategyUtils.rootVars(log); + this.dist = dist; + } + + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ReductionStrategy#next(kodkod.engine.satlab.ResolutionTrace) + */ + public IntSet next(ResolutionTrace trace) { + if (varsToTry.isEmpty()) return Ints.EMPTY_SET; // tried everything + final IntSet relevantVars = StrategyUtils.coreTailUnits(trace); + + for(IntIterator varItr = varsToTry.iterator(); varItr.hasNext();) { + final int var = varItr.next(); + varItr.remove(); + if (relevantVars.remove(var)) { // remove maxVar from the set of relevant variables + if (relevantVars.isEmpty()) break; // there was only root formula left + // get all axioms and resolvents corresponding to the clauses that + // form the translations of formulas identified by relevant vars + final IntSet relevantClauses = clausesFor(trace, relevantVars); + assert !relevantClauses.isEmpty() && !relevantClauses.contains(trace.size()-1); + return relevantClauses; + } + } + + varsToTry.clear(); + return Ints.EMPTY_SET; + } + + + /** + * Returns the indices of all axioms and resolvents + * in the given trace that form the translations of the formulas + * identified by the given variables. This method assumes that + * the axioms in the given trace were generated by the Kodkod + * {@linkplain Translator}. + * @return + * let C = { c: trace.prover.clauses | c.maxVariable() in relevantVars }, + * T = { c1, c2: C | c2.maxVariable() in abs(c1.literals) }, + * A = C.*T | + * trace.backwardReachable(A) - trace.backwardReachable(trace.axioms() - A) + */ + private IntSet clausesFor(ResolutionTrace trace, IntSet relevantVars) { + + final IntSet relevantAxioms = StrategyUtils.clausesFor(trace, relevantVars); + + if (distThis implementation of SCE will work properly only on CNFs generated by the kodkod {@linkplain Translator}.

+ * @author Emina Torlak + * @see HybridStrategy + */ +public final class SCEStrategy implements ReductionStrategy { + private final IntCollection varsToTry; + + /** + * Constructs an SCE strategy that will use the given translation + * log to relate the cnf clauses back to the logic constraints from + * which they were generated. + */ + public SCEStrategy(final TranslationLog log) { + varsToTry = StrategyUtils.rootVars(log); + } + + /** + * {@inheritDoc} + * @see kodkod.engine.satlab.ReductionStrategy#next(kodkod.engine.satlab.ResolutionTrace) + */ + public IntSet next(ResolutionTrace trace) { + if (varsToTry.isEmpty()) return Ints.EMPTY_SET; // tried everything + final IntSet relevantVars = StrategyUtils.coreTailUnits(trace); + + for(IntIterator varItr = varsToTry.iterator(); varItr.hasNext();) { + final int var = varItr.next(); + varItr.remove(); + if (relevantVars.remove(var)) { // remove maxVar from the set of relevant variables + if (relevantVars.isEmpty()) break; // there was only root formula left + // get all axioms corresponding to the clauses that + // form the translations of formulas identified by relevant vars + final IntSet relevantClauses = StrategyUtils.clausesFor(trace, relevantVars); + assert !relevantClauses.isEmpty() && !relevantClauses.contains(trace.size()-1); + return relevantClauses; + } + } + varsToTry.clear(); + return Ints.EMPTY_SET; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/StrategyUtils.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/StrategyUtils.java new file mode 100644 index 00000000..0f5e8e46 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/engine/ucore/StrategyUtils.java @@ -0,0 +1,285 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.engine.ucore; + +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import kodkod.ast.Formula; +import kodkod.ast.Node; +import kodkod.ast.Variable; +import kodkod.engine.fol2sat.RecordFilter; +import kodkod.engine.fol2sat.TranslationLog; +import kodkod.engine.fol2sat.TranslationRecord; +import kodkod.engine.fol2sat.Translator; +import kodkod.engine.satlab.Clause; +import kodkod.engine.satlab.ResolutionTrace; +import kodkod.instance.TupleSet; +import kodkod.util.ints.IntBitSet; +import kodkod.util.ints.IntIterator; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.IntTreeSet; +import kodkod.util.ints.Ints; +import kodkod.util.ints.SparseSequence; +import kodkod.util.ints.TreeSequence; + +/** + * A collection of utility methods for implementing + * logic-level reduction strategies. + * + * @author Emina Torlak + */ +public final class StrategyUtils { + private StrategyUtils() {} + + + /** + * Returns the variables that correspond to the roots of log.formula. + * @return + *
 
+	 * { v: int | some r: log.records | 
+	 *   r.node in log.roots() and 
+	 *   r.env.isEmpty() and
+	 *   abs(r.literal) != Integer.MAX_VALUE and
+	 *   v = abs(r.literal) and
+	 *   no r': log.records | r'.node = r.node && log.replay.r' > log.replay.r }
+	 * 
+ */ + public static IntSet rootVars(TranslationLog log) { + final IntSet rootVars = new IntTreeSet(); + final Set roots = log.roots(); + final Map maxRootVar = new LinkedHashMap(roots.size()); + final RecordFilter filter = new RecordFilter() { + public boolean accept(Node node, Formula translated, int literal, Map env) { + return roots.contains(translated) && env.isEmpty(); + } + }; + for(Iterator itr = log.replay(filter); itr.hasNext();) { + TranslationRecord record = itr.next(); + int[] var = maxRootVar.get(record.translated()); + if (var==null) { + var = new int[1]; + maxRootVar.put(record.translated(), var); + } + var[0] = StrictMath.abs(record.literal()); + } + + for(int[] var : maxRootVar.values()) { + int topVar = var[0]; + if (topVar != Integer.MAX_VALUE) // formula simplified to TRUE + rootVars.add(var[0]); + } + +// for(Map.Entry entry : maxRootVar.entrySet()) { +// final int topVar = entry.getValue()[0]; +// if (topVar != Integer.MAX_VALUE) // formula simplified to TRUE +// rootVars.add(topVar); +// System.out.println(topVar + " ==>" + entry.getKey()); +// } + + return rootVars; + } + + /** + * Returns a map from variables to the corresponding roots of log.formula. + * @return + *
 
+	 * { v: int, f: Formula | some r: log.records | 
+	 *   r.translated in log.roots() and 
+	 *   r.translated = f and
+	 *   r.env.isEmpty() and
+	 *   abs(r.literal) != Integer.MAX_VALUE and
+	 *   v = abs(r.literal) and
+	 *   no r': log.records | r'.node = r.node && log.replay.r' > log.replay.r }
+	 * 
+ */ + static SparseSequence roots(TranslationLog log) { + final SparseSequence rootVars = new TreeSequence(); + final Set roots = log.roots(); + final Map maxRootVar = new IdentityHashMap(roots.size()); + final RecordFilter filter = new RecordFilter() { + public boolean accept(Node node, Formula translated, int literal, Map env) { + return roots.contains(translated) && env.isEmpty(); + } + }; + for(Iterator itr = log.replay(filter); itr.hasNext();) { + TranslationRecord record = itr.next(); + int[] var = maxRootVar.get(record.translated()); + if (var==null) { + var = new int[1]; + maxRootVar.put(record.translated(), var); + } + var[0] = StrictMath.abs(record.literal()); + } + + for(Map.Entry entry : maxRootVar.entrySet()) { + final int topVar = entry.getValue()[0]; + if (topVar != Integer.MAX_VALUE) // formula simplified to TRUE + rootVars.put(topVar, entry.getKey()); + } + return rootVars; + } + + /** + * Returns the variables that correspond to the roots of log.formula, in the order + * in which they were specified in log.formula. + * @return variables that correspond to the roots of log.formula, in the order + * in which they were specified in log.formula. + */ +// static IntVector orderedRootVars(TranslationLog log) { +// final Set roots = log.roots(); +// final Map maxRootVar = new LinkedHashMap(roots.size()); +// final RecordFilter filter = new RecordFilter() { +// public boolean accept(Node node, int literal, Map env) { +// return roots.contains(node) && env.isEmpty(); +// } +// }; +// for(Iterator itr = log.replay(filter); itr.hasNext();) { +// TranslationRecord record = itr.next(); +// int[] var = maxRootVar.get(record.node()); +// if (var==null) { +// var = new int[1]; +// maxRootVar.put((Formula)record.node(), var); +// } +// var[0] = StrictMath.abs(record.literal()); +// } +// final IntSet uniqueRoots = new IntTreeSet(); +// final IntVector orderedRoots = new ArrayIntVector(roots.size()); +// for(int[] var : maxRootVar.values()) { +// int topVar = var[0]; +// if (topVar != Integer.MAX_VALUE) // formula simplified to TRUE +// if (uniqueRoots.add(var[0])) { +// orderedRoots.add(var[0]); +// }; +// } +// return orderedRoots; +// } + + /** + * Returns relevant core variables; that is, all variables that occur both in the positive and + * negative phase in trace.core. + * @return { v: [1..) | (some p, n: trace.core | v in trace.elts[p].literals and -v in trace.elts[n].literals) } + */ + public static IntSet coreVars(ResolutionTrace trace) { + + final IntSet posVars = new IntTreeSet(), negVars = new IntTreeSet(); + + for(Iterator iter = trace.iterator(trace.core()); iter.hasNext();) { + Clause clause = iter.next(); + for(IntIterator lits = clause.literals(); lits.hasNext(); ) { + int lit = lits.next(); + if (lit > 0) posVars.add(lit); + else negVars.add(-lit); + } + } + + posVars.retainAll(negVars); + + assert !posVars.isEmpty(); + final IntSet ret = new IntBitSet(posVars.max()+1); + ret.addAll(posVars); + + return ret; + } + + /** + * Returns the set of all variables in the core of the given trace + * that form unit clauses. + * @return { v: [1..) | some c: trace.core | c.size() = 1 and c.maxVariable() = v } + */ + public static IntSet coreUnits(ResolutionTrace trace) { + final IntSet units = new IntTreeSet(); + + for(Iterator itr = trace.reverseIterator(trace.core()); itr.hasNext(); ) { + Clause c = itr.next(); + if (c.size()==1) { + units.add(c.maxVariable()); + } + } + + if (units.isEmpty()) return Ints.EMPTY_SET; + + return Ints.asSet(units.toArray()); + } + + /** + * Returns the consecutive variables at the tail of the core of the given trace + * that form unit clauses. + * @return the consecutive variables at the tail of the core of the given trace + * that form unit clauses + */ + static IntSet coreTailUnits(ResolutionTrace trace) { + final IntSet units = new IntTreeSet(); + + for(Iterator itr = trace.reverseIterator(trace.core()); itr.hasNext(); ) { + Clause c = itr.next(); + if (c.size()==1) { + units.add(c.maxVariable()); + } else { + break; + } + } + + return units; + } + + /** + * Returns the indices of all axioms + * in the given trace that form the translations of the formulas + * identified by the given variables. This method assumes that + * the axioms in the given trace were generated by the Kodkod + * {@linkplain Translator}. + * @return + * let C = { c: trace.prover.clauses | c.maxVariable() in relevantVars }, + * T = { c1, c2: C | c2.maxVariable() in abs(c1.literals) } | + * C.*T + */ + static IntSet clausesFor(ResolutionTrace trace, IntSet relevantVars) { +// System.out.println("relevant: " + relevantVars); + final IntSet axioms = trace.axioms(); + + final IntSet reachableVars = new IntBitSet(relevantVars.max()+1); + reachableVars.addAll(relevantVars); + + final IntSet relevantAxioms = new IntBitSet(axioms.size()); + + final Iterator itr = trace.reverseIterator(axioms); + for(int i = axioms.max(); i >= 0; i--) { + Clause clause = itr.next(); + int maxVar = clause.maxVariable(); + if (reachableVars.contains(maxVar)) { + for(IntIterator lits = clause.literals(); lits.hasNext(); ) { + reachableVars.add(StrictMath.abs(lits.next())); + } + relevantAxioms.add(i); + } + } + + return relevantAxioms; + } + + + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/instance/Bounds.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/instance/Bounds.java new file mode 100644 index 00000000..ae8f6c4d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/instance/Bounds.java @@ -0,0 +1,299 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.instance; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import kodkod.ast.Relation; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.Ints; +import kodkod.util.ints.SparseSequence; +import kodkod.util.ints.TreeSequence; + + +/** + *

A Bounds object maps a {@link kodkod.ast.Relation relation} r to two + * {@link kodkod.instance.TupleSet sets of tuples}, rL and rU, which represent the lower and upper + * bounds on the {@link kodkod.instance.Tuple set of tuples} to which an {@link kodkod.instance.Instance instance} + * based on these bounds may map r. The set rL represents all the tuples + * that a given relation must contain. The set rU represents all the tuples + * that a relation may contain. All bounding sets range over the same {@link kodkod.instance.Universe universe}. + *

+ *

A Bounds object also maps integers to singleton tupleset that represent them. A tupleset may represent more than + * one integer, but an integer is represented by at most one tupleset.

+ * @specfield universe: Universe + * @specfield relations: set Relation + * @specfield intBound: int -> lone TupleSet + * @specfield lowerBound: relations -> one TupleSet + * @specfield upperBound: relations -> one TupleSet + * @invariant all i: intBound.TupleSet | intBound[i].size() = 1 && intBound[i].arity() = 1 + * @invariant lowerBound[relations].universe = upperBound[relations].universe = universe + * @invariant all r: relations | lowerBound[r].arity = upperBound[r].arity = r.arity + * @invariant all r: relations | lowerBound[r].tuples in upperBound[r].tuples + * @author Emina Torlak + **/ +public final class Bounds implements Cloneable { + private final TupleFactory factory; + private final Map lowers, uppers; + private final SparseSequence intbounds; + + /** + * Constructs a Bounds object with the given factory and mappings. + */ + private Bounds(TupleFactory factory, Map lower, Map upper, SparseSequence intbounds) { + this.factory = factory; + this.lowers = lower; + this.uppers = upper; + this.intbounds = intbounds; + } + + /** + * Constructs new Bounds over the given universe. + * @ensures this.universe' = universe && no this.relations' && no this.intBound' + * @throws NullPointerException - universe = null + */ + public Bounds(Universe universe) { + this.factory = universe.factory(); + lowers = new LinkedHashMap(); + uppers = new LinkedHashMap(); + intbounds = new TreeSequence(); + } + + /** + * Returns this.universe. + * @return this.universe + */ + public Universe universe() { return factory.universe(); } + + + /** + * Returns the set of all relations bound by this Bounds. + * The returned set does not support the add operation. + * It supports removal iff this is not an unmodifiable + * Bounds. + * @return this.relations + */ + public Set relations() { + return lowers.keySet(); + } + + /** + * Returns the set of all integers bound by this Bounds. + * The returned set does not support the add operation. + * It supports removal iff this is not an unmodifiable Bounds. + * @return this.intBounds.TupleSet + */ + public IntSet ints() { + return intbounds.indices(); + } + + /** + * Returns the set of tuples that r must contain (the lower bound on r's contents). + * If r is not mapped by this, null is returned. + * @return r in this.relations => lowerBound[r], null + */ + public TupleSet lowerBound(Relation r) { + return lowers.get(r); + } + + /** + * Returns a map view of this.lowerBound. The returned map is not modifiable. + * @return a map view of this.lowerBound + */ + public Map lowerBounds() { + return Collections.unmodifiableMap(lowers); + } + + /** + * Returns the set of tuples that r may contain (the upper bound on r's contents). + * If r is not mapped by this, null is returned. + * @return r in this.relations => upperBound[r], null + */ + public TupleSet upperBound(Relation r) { + return uppers.get(r); + } + + /** + * Returns a map view of this.upperBound. The returned map is not modifiable. + * @return a map view of this.upperBound + */ + public Map upperBounds() { + return Collections.unmodifiableMap(uppers); + } + + /** + * Returns the set of tuples representing the given integer. If i is not + * mapped by this, null is returned. + * @return this.intBound[i] + */ + public TupleSet exactBound(int i) { + return intbounds.get(i); + } + + /** + * Returns a sparse sequence view of this.intBound. The returned sequence + * is not modifiable. + * @return a sparse sequence view of this.intBound + */ + public SparseSequence intBounds() { + return Ints.unmodifiableSequence(intbounds); + } + + /** + * @throws IllegalArgumentException - arity != bound.arity + * @throws IllegalArgumentException - bound.universe != this.universe + */ + private void checkBound(int arity, TupleSet bound) { + if (arity != bound.arity()) + throw new IllegalArgumentException("bound.arity != r.arity"); + if (!bound.universe().equals(factory.universe())) + throw new IllegalArgumentException("bound.universe != this.universe"); + } + + /** + * Sets both the lower and upper bounds of the given relation to + * the given set of tuples. + * + * @requires tuples.arity = r.arity && tuples.universe = this.universe + * @ensures this.relations' = this.relations + r + * this.lowerBound' = this.lowerBound' ++ r->tuples && + * this.upperBound' = this.lowerBound' ++ r->tuples + * @throws NullPointerException - r = null || tuples = null + * @throws IllegalArgumentException - tuples.arity != r.arity || tuples.universe != this.universe + */ + public void boundExactly(Relation r, TupleSet tuples) { + checkBound(r.arity(), tuples); + final TupleSet unmodifiableTuplesCopy = tuples.clone().unmodifiableView(); + lowers.put(r, unmodifiableTuplesCopy); + uppers.put(r, unmodifiableTuplesCopy); + } + + /** + * Sets the lower and upper bounds for the given relation. + * + * @requires lower.tuples in upper.tuples && lower.arity = upper.arity = r.arity && + * lower.universe = upper.universe = this.universe + * @ensures this.relations' = this.relations + r && + * this.lowerBound' = this.lowerBound ++ r->lower && + * this.upperBound' = this.upperBound ++ r->upper + * @throws NullPointerException - r = null || lower = null || upper = null + * @throws IllegalArgumentException - lower.arity != r.arity || upper.arity != r.arity + * @throws IllegalArgumentException - lower.universe != this.universe || upper.universe != this.universe + * @throws IllegalArgumentException - lower.tuples !in upper.tuples + */ + public void bound(Relation r, TupleSet lower, TupleSet upper) { + if (!upper.containsAll(lower)) + throw new IllegalArgumentException("lower.tuples !in upper.tuples"); + if (upper.size()==lower.size()) { + // upper.containsAll(lower) && upper.size()==lower.size() => upper.equals(lower) + boundExactly(r, lower); + } else { + checkBound(r.arity(), lower); + checkBound(r.arity(), upper); + lowers.put(r, lower.clone().unmodifiableView()); + uppers.put(r, upper.clone().unmodifiableView()); + } + } + + /** + * Makes the specified tupleset the upper bound on the contents of the given relation. + * The lower bound automatically becomen an empty tupleset with the same arity as + * the relation. + * + * @requires upper.arity = r.arity && upper.universe = this.universe + * @ensures this.relations' = this.relations + r + * this.lowerBound' = this.lowerBound ++ r->{s: TupleSet | s.universe = this.universe && s.arity = r.arity && no s.tuples} && + * this.upperBound' = this.upperBound ++ r->upper + * @throws NullPointerException - r = null || upper = null + * @throws IllegalArgumentException - upper.arity != r.arity || upper.universe != this.universe + */ + public void bound(Relation r, TupleSet upper) { + checkBound(r.arity(), upper); + lowers.put(r, factory.noneOf(r.arity()).unmodifiableView()); + uppers.put(r, upper.clone().unmodifiableView()); + } + + /** + * Makes the specified tupleset an exact bound on the relational value + * that corresponds to the given integer. + * @requires ibound.arity = 1 && i.bound.size() = 1 + * @ensures this.intBound' = this.intBound' ++ i -> ibound + * @throws NullPointerException - ibound = null + * @throws IllegalArgumentException - ibound.arity != 1 || ibound.size() != 1 + * @throws IllegalArgumentException - ibound.universe != this.universe + */ + public void boundExactly(int i, TupleSet ibound) { + checkBound(1, ibound); + if (ibound.size() != 1) + throw new IllegalArgumentException("ibound.size != 1: " + ibound); + intbounds.put(i, ibound.clone().unmodifiableView()); + } + + + /** + * Returns an unmodifiable view of this Bounds object. + * @return an unmodifiable view of his Bounds object. + */ + public Bounds unmodifiableView() { + return new Bounds(factory, Collections.unmodifiableMap(lowers), Collections.unmodifiableMap(uppers), Ints.unmodifiableSequence(intbounds)); + } + + /** + * Returns a deep copy of this Bounds object. + * @return a deep copy of this Bounds object. + */ + public Bounds clone() { + try { + return new Bounds(factory, new LinkedHashMap(lowers), + new LinkedHashMap(uppers), intbounds.clone()); + } catch (CloneNotSupportedException cnse) { + throw new InternalError(); // should not be reached + } + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + final StringBuilder str = new StringBuilder(); + str.append("relation bounds:"); + for(Map.Entry entry: lowers.entrySet()) { + str.append("\n "); + str.append(entry.getKey()); + str.append(": ["); + str.append(entry.getValue()); + TupleSet upper = uppers.get(entry.getKey()); + if (!upper.equals(entry.getValue())) { + str.append(", "); + str.append(upper); + } + str.append("]"); + } + str.append("\nint bounds: "); + str.append("\n "); + str.append(intbounds); + return str.toString(); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/instance/Instance.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/instance/Instance.java new file mode 100644 index 00000000..44e2e315 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/instance/Instance.java @@ -0,0 +1,218 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.instance; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import kodkod.ast.Relation; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.Ints; +import kodkod.util.ints.SparseSequence; +import kodkod.util.ints.TreeSequence; + + +/** + * Represents a model (an instance) of a relational formula, which is a mapping + * from {@link kodkod.ast.Relation relations} and integers to {@link kodkod.instance.TupleSet sets of tuples} + * drawn from a given {@link kodkod.instance.Universe universe}. + * + * @specfield universe: Universe + * @specfield relations: set Relation + * @specfield tuples: (relations -> one TupleSet) + (int -> lone TupleSet) + * @invariant all r: tuples.TupleSet & Relation | r.arity = tuples[r].arity && tuples[r].universe = universe + * @invariant all i: tuples.TupleSet & int | ints[i].arity = 1 && ints[i].size() = 1 + * + * @author Emina Torlak + */ +public final class Instance implements Cloneable { + private final Map tuples; + private final SparseSequence ints; + private final Universe universe; + + private Instance(Universe u, Map tuples, SparseSequence ints) { + this.universe = u; + this.tuples = tuples; + this.ints = ints; + } + + /** + * Constructs an empty instance over the given universe + * + * @ensures this.universe' = universe && no this.tuples' + * @throws NullPointerException - universe = null + */ + public Instance(final Universe universe) { + if (universe==null) throw new NullPointerException("universe=null"); + this.universe = universe; + this.tuples = new LinkedHashMap(); + this.ints = new TreeSequence(); + } + + /** + * Returns the universe from which the tuples in this instance + * are drawn. + * @return this.universe + */ + public Universe universe() { + return universe; + } + + /** + * Returns true if this instance maps the given relation to a set + * of tuples; otherwise returns false. + * @return r in this.relations + */ + public boolean contains(Relation relation) { + return tuples.containsKey(relation); + } + + /** + * Returns true if this instance maps the given integer to a singleton + * tupleset; otherwise returns false. + * @return some this.tuples[i] + */ + public boolean contains(int i) { + return ints.containsIndex(i); + } + + /** + * Returns the relations mapped by this instance. The returned set + * does not support addition. It supports remval if this is not an + * unmodifiable instance. + * @return this.relations + */ + public Set relations() { + return tuples.keySet(); + } + + /** + * Returns the integers mapped by this instance. The returned set + * does not support addition. It supports remval if this is not an + * unmodifiable instance. + * @return this.ints.TupleSet + */ + public IntSet ints() { + return ints.indices(); + } + + /** + * Maps the given relation to the given tuple set. + * @ensures this.tuples' = this.tuples ++ relation->s + * @throws NullPointerException - relation = null || s = null + * @throws IllegalArgumentException - relation.arity != s.arity + * @throws IllegalArgumentException - s.universe != this.universe + * @throws UnsupportedOperationException - this is an unmodifiable instance + */ + public void add(final Relation relation, TupleSet s) { + if (!s.universe().equals(universe)) + throw new IllegalArgumentException("s.universe!=this.universe"); + if (relation.arity()!=s.arity()) + throw new IllegalArgumentException("relation.arity!=s.arity"); + tuples.put(relation, s.clone().unmodifiableView()); + } + + /** + * Maps the given integer to the given tuple set. + * @ensures this.tuples' = this.tuples ++ i->s + * @throws NullPointerException - s = null + * @throws IllegalArgumentException - s.arity != 1 || s.size() != 1 + * @throws IllegalArgumentException - s.universe != this.universe + * @throws UnsupportedOperationException - this is an unmodifiable instance + */ + public void add(int i, TupleSet s) { + if (!s.universe().equals(universe)) + throw new IllegalArgumentException("s.universe!=this.universe"); + if (s.arity()!=1) + throw new IllegalArgumentException("s.arity!=1: " + s); + if (s.size()!=1) + throw new IllegalArgumentException("s.size()!=1: " + s); + ints.put(i, s.clone().unmodifiableView()); + } + + /** + * Returns the set of tuples assigned to the given relation by this Instance. + * If the relation is not mapped by the model, null is returned. + * + * @return this.tuples[relation] + */ + public TupleSet tuples(Relation relation) { + return tuples.get(relation); + } + + /** + * Returns a map view of Relation<:this.tuples. The returned map is unmodifiable. + * @return a map view of Relation<:this.tuples. + */ + public Map relationTuples() { + return Collections.unmodifiableMap(tuples); + } + + /** + * Returns the set of tuples assigned to the given integer by this Instance. + * If the integer is not mapped by the model, null is returned. + * + * @return this.tuples[i] + */ + public TupleSet tuples(int i) { + return ints.get(i); + } + + /** + * Returns a sparse sequence view of int<:this.tuples. The returned sequence is unmodifiable. + * @return a sparse sequence view of int<:this.tuples. + */ + public SparseSequence intTuples() { + return Ints.unmodifiableSequence(ints); + } + + /** + * Returns an unmodifiable view of this instance. + * @return an unmodifiable view of this instance. + */ + public Instance unmodifiableView() { + return new Instance(universe, Collections.unmodifiableMap(tuples), Ints.unmodifiableSequence(ints)); + } + + /** + * Returns a deep copy of this Instance object. + * @return a deep copy of this Instance object. + */ + public Instance clone() { + try { + return new Instance(universe, new LinkedHashMap(tuples), ints.clone()); + } catch (CloneNotSupportedException cnse) { + throw new InternalError(); // should not be reached + } + } + + /** + * {@inheritDoc} + * @see java.lang.Object#toString() + */ + public String toString() { + return "relations: "+tuples.toString() + "\nints: " + ints; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/instance/Tuple.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/instance/Tuple.java new file mode 100644 index 00000000..ab9405ea --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/instance/Tuple.java @@ -0,0 +1,133 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.instance; + + +/** + * Represents a sequence of atoms drawn from a given {@link kodkod.instance.Universe universe}. + * Note that a Tuple of arity n whose atoms belong to a Universe u encodes an n-digit number in + * base u.size. The decimal representation of this number is taken to be the index of the tuple + * in an n-dimensional space over the Universe u. + * + * @specfield arity: int + * @specfield universe: Universe + * @specfield atoms: [0..arity)->one Object + * @invariant atoms[int] in universe.atoms[int] + * + * @author Emina Torlak + */ +public abstract class Tuple { + + /** + * Returns the universe from which the atoms in this + * tuple are drawn. + * @return this.universe + */ + public abstract Universe universe(); + + /** + * Returns the arity of this tuple. + * @return this.arity + */ + public abstract int arity(); + + /** + * A Tuple encodes a number with this.arity digits in radix this.universe.size; + * a Tuple's index is the decimal representation of this number. + * + * @return sum({i: [0..arity) | universe.index(atoms[i]) * universe.size^(arity - 1 - i)}) + */ + public abstract int index(); + + /** + * Returns the atom at the specified index + * + * @return this.atoms[i] + * @throws IndexOutOfBoundsException - i < 0 || i >= this.arity + */ + public abstract Object atom(int i); + + /** + * Returns the index of the ith atom as given by this.universe. + * The effect of this method is the same as calling this.universe.index(this.atom(i)). + * + * @return this.universe.index(this.atoms[i]) + * @throws IndexOutOfBoundsException - i < 0 || i >= this.arity + */ + public abstract int atomIndex(int i); + + /** + * Returns true if atom is in this tuple, otherwise returns false. + * + * @return atom in this.atoms[int] + * @throws IllegalArgumentException - atom !in this.universe.atoms[int] + */ + public abstract boolean contains(Object atom); + + /** + * Returns the cross product of this and the specified tuple. + * + * @return {t : Tuple | t.atoms = this.atoms->tuple.atoms} + * @throws NullPointerException - tuple = null + * @throws IllegalArgumentException - tuple.universe != this.universe + */ + public abstract Tuple product(Tuple tuple); + + /** + * Returns true if o is a tuple with the same sequence of atoms as this, + * drawn from the same universe as this. Otherwise returns false. + * + * @return o in Tuple && o.universe = this.universe && o.atoms = this.atoms + */ + public boolean equals(Object o) { + if (this==o) return true; + else if (o instanceof Tuple) { + final Tuple t = (Tuple) o; + return universe().equals(t.universe()) && arity()==t.arity() && index()==t.index(); + } + else return false; + } + + /** + * Returns a hash code based on the tuple's arity, index, and the hash code + * of its universe, so that the general contract of Object.hashCode is obeyed. + * @return the hashcode for this tuple + */ + public int hashCode() { + return (arity() * 19 + index())^universe().hashCode(); + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + final StringBuilder ret = new StringBuilder("["); + ret.append(atom(0)); + for (int i = 1; i < arity(); i++) { + ret.append(", "); + ret.append(atom(i)); + } + ret.append("]"); + return ret.toString(); + + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/instance/TupleFactory.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/instance/TupleFactory.java new file mode 100644 index 00000000..6a12b163 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/instance/TupleFactory.java @@ -0,0 +1,394 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.instance; + +import java.util.Collection; +import java.util.List; + +import kodkod.engine.CapacityExceededException; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.Ints; + + +/** + * A factory class that facilitates creation of tuples + * and tuple sets drawn from a given universe. Only one + * factory per universe exists. + * + * @specfield universe: Universe + * @invariant no f: TupleFactory - this | f.universe = this.universe + * @author Emina Torlak + */ +public final class TupleFactory { + + private final Universe universe; + private final int base; + + /** + * Constructs a factory for the given universe. + * @requires no (TupleFactory<:universe).universe + * @ensures this.universe' = universe + * @throws NullPointerException - universe = null + */ + TupleFactory(Universe universe) { + this.universe = universe; + this.base = universe.size(); + } + + /** + * Returns the universe to which this factory belongs. + * @return this.universe + */ + public Universe universe() { return universe; } + + /** + * Returns a tuple that contains the specified sequence of atoms, + * drawn from this.universe. + * + * @return {t: Tuple | t.universe = this.universe && t.atoms = atoms } + * @throws NullPointerException - atoms = null + * @throws IllegalArgumentException - atoms.length < 1 + * @throws IllegalArgumentException - some a: atoms[int] | a !in this.universe.atoms[int] + */ + public Tuple tuple(Object... atoms) { + if (atoms.length<1) throw new IllegalArgumentException("atoms.length<1"); + return new IntTuple(atoms); + } + + /** + * Returns a tuple that contains the specified sequence of atoms, + * drawn from this.universe. + * + * @return {t: Tuple | t.universe = this.universe && t.atoms = atoms } + * @throws NullPointerException - atoms = null + * @throws IllegalArgumentException - atoms.size < 1 + * @throws IllegalArgumentException - some a: atoms[int] | a !in this.universe.atoms[int] + */ + public Tuple tuple(List atoms) { + if (atoms.size()<1) throw new IllegalArgumentException("atoms.size()<1"); + return new IntTuple(atoms.toArray()); + } + + /** + * Returns a tuple with the specified arity whose index in an arity-dimensional + * space over this.universe is given by the index parameter. + * + * @return {t: Tuple | t.universe = this.universe && t.arity = arity && + * index = sum({i : [0..arity) | universe.index(t.atoms[i]) * universe.size^(arity - 1 - i))}) } + * @throws IllegalArgumentException - arity < 1 || index < 0 || index >= universe.size^arity + */ + public Tuple tuple(final int arity, final int index) { + return new IntTuple(arity, index); + } + + /** + * Returns a set of all tuples of the given arity, drawn from this.universe. + * @return { s: TupleSet | s.universe = this.universe && s.arity = arity && + * s.tuples = {t: Tuple | t.universe = this.universe && t.arity = arity} } + * @throws IllegalArgumentException - arity < 1 + */ + public TupleSet allOf(int arity) { + return new TupleSet(universe, arity, + 0, ((int) Math.pow(base, arity)) - 1); + } + + /** + * Returns a set of tuples of arity 1, each of which wraps one of the given objects. + * The method requires that the specified object be atoms in this.universe. + * + * @return {s: TupleSet | s.universe = this.universe && s.arity = 1 && + * s.tuples = { t: Tuple | t.universe=this.universe && + * t.arity=1 && t.atoms[0] in atoms[int]}} + * @throws NullPointerException - atoms = null + * @throws IllegalArgumentException - some atoms[int] - this.universe.atoms[int] + */ + public TupleSet setOf(Object... atoms) { + final TupleSet ret = new TupleSet(universe, 1); + for (Object atom: atoms) { + ret.add(new IntTuple(atom)); + } + return ret; + } + + /** + * Returns a tuple set consisting of specified tuples. The method requires that + * all given tuples have the same arity and be drawn from this.universe. + * + * @return {s: TupleSet | s.universe = this.universe && s.arity = first.arity && + * s.tuples = first + rest[int] } + * @throws NullPointerException - first = null || rest = null + * @throws IllegalArgumentException - first.universe != this.universe + * @throws IllegalArgumentException - some t: rest[int] | t.universe != this.universe || t.arity != first.arity + */ + public TupleSet setOf(Tuple first, Tuple... rest) { + if (!first.universe().equals(universe)) + throw new IllegalArgumentException("first.universe != this.universe"); + + final TupleSet ret = new TupleSet(universe, first.arity(), first.index(), first.index()); + for(Tuple tuple: rest) { + ret.add(tuple); + } + return ret; + } + + /** + * Returns a tuple set consisting of specified tuples. The method requires that + * all given tuples have the same arity and be drawn from this.universe. + * + * @return {s: TupleSet | s.universe = this.universe && s.arity = first.arity && + * s.tuples = tuples } + * @throws NullPointerException - tuples = null + * @throws IllegalArgumentException - tuples.isEmpty() + * @throws IllegalArgumentException - tuples.universe != this.universe || #tuples.arity > 1 + */ + public TupleSet setOf(Collection tuples) { + if (tuples.isEmpty()) + throw new IllegalArgumentException("tuples.isEmpty()"); + final TupleSet ret = new TupleSet(universe, tuples.iterator().next().arity()); + for(Tuple t : tuples) { + ret.add(t); + } + return ret; + } + + /** + * Returns a set of the given arity that contains all tuples whose indeces + * are contained in the given int set. Throws an IllegalArgumentException + * if the set contains an index that is either negative or greater than + * this.universe.size()^arity - 1. The returned TupleSet is backed by a clone + * of tupleIndices. + * @requires tupleIndices is cloneable + * @return {s: TupleSet | s.universe = this.universe && s.arity = arity && + * s.tuples = {t: Tuple | t.index() in tupleIndices} } + * @throws NullPointerException - tupleIndices = null + * @throws IllegalArgumentException - tupleIndices is uncloneable + * @throws IllegalArgumentException - arity < 1 + * @throws IllegalArgumentException - tupleIndices.min() < 0 || tupleIndices.max() >= this.universe.size()^arity + */ + public TupleSet setOf(int arity, IntSet tupleIndices) { + try { + return new TupleSet(universe,arity,tupleIndices.clone()); + } catch (CloneNotSupportedException cne){ + throw new IllegalArgumentException("uncloneable int set"); + } + } + + /** + * Returns an initially empty tuple set of the given arity, based on this.universe. + * @return { s: TupleSet | s.universe = this.universe && s.arity = arity && no s.tuples } + * @throws IllegalArgumentException - arity < 1 + */ + public TupleSet noneOf(int arity) { + return new TupleSet(universe, arity); + } + + /** + * Returns a tuple set that contains all tuples between from + * and to, inclusive. More formally, the returned set contains + * all tuples whose indeces are in the range [from.index()..to.index()]. + * @return { s: TupleSet | s.universe = this.universe && s.arity = from.arity && + * s.tuples = {t: Tuple | t.universe = this.universe && + * t.arity = s.arity && + * from.index()<=t.index()<=to.index() }} + * @throws NullPointerException - from = null || to = null + * @throws IllegalArgumentException - from.arity != to.arity + * @throws IllegalArgumentException - from.universe != this.universe || to.universe != this.universe + * @throws IllegalArgumentException - from.index > to.index + */ + public TupleSet range(Tuple from, Tuple to) { + if (from.arity()!=to.arity()) + throw new IllegalArgumentException("from.arity!=to.arity"); + if (!(from.universe().equals(universe)&&to.universe().equals(universe))) + throw new IllegalArgumentException("from.universe != this.universe || to.universe != this.universe"); + return new TupleSet(universe, from.arity(), from.index(), to.index()); + } + + /** + * Returns a tuple set that contains all tuples in the specified area + * of the n-dimensional space, where n is the arity of the argument + * tuples. For example, suppose that this.universe consists of atoms + * {atom0, atom1, atom2, atom3}, where atom0 has index 0, atom1 has index 1, etc. + * Calling this method with tuples [atom0, atom2] and [atom1, atom3] as the + * first and second arguments would result in the set {[atom0, atom2], + * [atom0,atom3], [atom1,atom2], [atom1, atom3]}. That is, the returned set + * consists of all points in the rectangle whose upper left corner is the + * point [atom0, atom2] and whose lower right corner is at [atom1, atom3]. + * @return {s: TupleSet | s.arity = upperLeft.arity && + * s.universe = this.universe && + * s.tuples = {t: Tuple | all i: [0..s.arity) | + * this.universe.index(upperLeft.atoms[i]) <= + * this.universe.index(t.atoms[i]) <= + * this.universe.index(lowerRight.atoms[i]}} + * @throws NullPointerException - upperLeft = null || lowerRight = null + * @throws IllegalArgumentException - upperLeft.arity != lowerRight.arity + * @throws IllegalArgumentException - lowerRight.universe != this.universe || upperLeft.universe != this.universe + * @throws IllegalArgumentException - some i: [0..upperLeft.arity) | + * this.universe.index(upperLeft.atoms[i]) > + * this.universe.index(lowerRight.atoms[i]) + */ + public TupleSet area(Tuple upperLeft, Tuple lowerRight) { + if (!upperLeft.universe().equals(universe) || upperLeft.arity()!=lowerRight.arity()) + throw new IllegalArgumentException(); + TupleSet ret = new TupleSet(universe, 1, upperLeft.atomIndex(0),lowerRight.atomIndex(0)); + for(int i = 1; i < upperLeft.arity(); i++) { + ret = ret.product(new TupleSet(universe, 1, upperLeft.atomIndex(i),lowerRight.atomIndex(i))); + } + return ret; + } + + /** + * Throws a CapacityExceededException if all tuples of the given arity + * drawn from this.universe cannot be represented as an integer. + * @throws CapacityExceededException if all tuples of the given arity + * drawn from this.universe cannot be represented as an integer. + */ + void checkCapacity(int arity) { + if (StrictMath.pow(base,arity) > Integer.MAX_VALUE) { + throw new CapacityExceededException("Arity too large (" + arity + ") for a universe of size " + universe.size(), Ints.nCopies(arity, base)); + } + } + + /** + * Projects the tuple with the specified index and arity onto the + * specified column. + * @requires tupleIndex >= 0 && tupleIndex < this.universe.size() ^ arity + * @return this.universe.index(this.tuple(arity, tupleIndex).atoms[i]) + */ + int project(int tupleIndex, int arity, int column) { + if (column < 0 || column >= arity) throw new IndexOutOfBoundsException(column+""); + return (tupleIndex / ((int) Math.pow(base, arity-1-column))) % base; + } + + /** + * An implementation of the Tuple interface that stores + * only the tuple's arity and index, rather than the full + * sequence of atoms. Parts of the sequence are computed on + * demand, e.g. when the get method is invoked. + * + * @specfield universe: TupleFactory.this.universe + * @specfield arity: int + * @specfield index: int + * @invariant arity >= 1 && 0 <= index < TupleFactory.this.base^arity + * @invariant index = sum({i: [0..arity) | TupleFactory.this.universe.index(atoms[i]) * TupleFactory.this.base^(arity - 1 - i)) + * @author Emina Torlak + */ + private final class IntTuple extends Tuple { + private final int arity, index; + + /** + * Constructs a tuple with the specified arity and index, whose atoms + * are drawn from the factory's universe. + * + * @ensures this.arity' = arity && + * this.index' = index + * @throws IllegalArgumentException - arity < 1 || index < 0 || index >= TupleFactory.this.base^arity + */ + IntTuple(final int arity, final int index) { + checkCapacity(arity); + if (arity < 1 || index < 0 || index >= Math.pow(base, arity)) { + throw new IllegalArgumentException("arity < 1 || index < 0 || index >= universe.size^arity"); + } + this.arity = arity; + this.index = index; + } + + /** + * Constructs a tuple that contains the specified sequence of atoms, drawn from the + * enclosing factory's universe. + * + * @requires atoms.length > 0 + * @ensures this.atoms' = atoms + * @throws NullPointerException - atoms = null + * @throws IllegalArgumentException - some a: atoms[int] | a !in universe.atoms[int] + */ + IntTuple(final Object... atoms) { + this.arity = atoms.length; + checkCapacity(arity); + int tempIndex = 0, multiplier = 1; + for (int i = arity - 1; i >= 0; i--) { + tempIndex += universe.index(atoms[i]) * multiplier; + multiplier *= base; + } + this.index = tempIndex; + assert this.index >= 0; + } + + /** + * Constructs a tuple with the specified arity, with the specified atom + * at each position. + * @ensures this.arity' = arity && this.atoms = [0..arity)->atom + * @throws NullPointerException - atom = null + * @throws IllegalArgumentException - arity < 1 || atom !in this.universe.atoms[int] + */ + @SuppressWarnings("unused") + IntTuple(final int arity, final Object atom) { + checkCapacity(arity); + if (arity < 1) throw new IllegalArgumentException("arity < 1"); + this.arity = arity; + int tempIndex = 1; + for (int i = 0; i < arity; i++) { + tempIndex = tempIndex*base + 1; + } + this.index = universe.index(atom) * tempIndex; + assert this.index >= 0; + } + + /** {@inheritDoc} */ + public Universe universe() { return universe; } + + /** {@inheritDoc} */ + public int arity() { return arity; } + + /** {@inheritDoc} */ + public int index() { return index; } + + /** {@inheritDoc} */ + public Object atom(int i) { + return universe.atom(atomIndex(i)); + } + + /** {@inheritDoc} */ + public int atomIndex(int i) { + return project(index,arity,i); +// if (i < 0 || i >= arity) throw new IndexOutOfBoundsException("i < 0 || i >= this.arity"); +// return (index / ((int) Math.pow(base, arity-1-i))) % base; + } + + /** {@inheritDoc} */ + public boolean contains(Object atom) { + for (int remainder = index, atomIndex = universe.index(atom); + remainder > 0; remainder = remainder / base) { + if (remainder % base == atomIndex) return true; + } + return false; + } + + /** {@inheritDoc} */ + public Tuple product(Tuple tuple) { + if (!universe.equals(tuple.universe())) throw new IllegalArgumentException("tuple.universe != this.universe"); + return new IntTuple(arity + tuple.arity(), + index * ((int)Math.pow(base, tuple.arity())) + tuple.index()); + } + } + + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/instance/TupleSet.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/instance/TupleSet.java new file mode 100644 index 00000000..b63df63d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/instance/TupleSet.java @@ -0,0 +1,418 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.instance; + +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Iterator; + +import kodkod.util.ints.IntIterator; +import kodkod.util.ints.IntSet; +import kodkod.util.ints.Ints; + + +/** + * Represents a set of {@link kodkod.instance.Tuple tuples} + * of a given arity, constructed over a given {@link kodkod.instance.Universe universe}. + * All polymorphic methods throw a ClassCastException when passed + * an element that is not a Tuple. All methods throw a NullPointerException + * when passed null. The iterator of a TupleSet returns tuples in the order of their + * {@link kodkod.instance.Tuple#index() indeces}. + * + * @specfield tuples: set Tuple + * @specfield universe: Universe + * @specfield arity: int + * @invariant tuples.arity = arity && tuples.universe = universe + * + * @author Emina Torlak + */ +public final class TupleSet extends AbstractSet implements Cloneable { + private final Universe universe; + private final int arity; + private final IntSet tuples; + private IntSet indexView = null; + + /** + * Constructs an empty tuple set for storing tuples + * of the specified arity, over the given universe. + * + * @ensures this.universe' = universe && this.arity' = arity && no this.tuples' + * @throws NullPointerException - universe = null + * @throws IllegalArgumentException - arity < 1 + */ + TupleSet(Universe universe, int arity) { + if (arity < 1) throw new IllegalArgumentException("arity < 1"); + universe.factory().checkCapacity(arity); + this.universe = universe; + this.arity = arity; + tuples = Ints.bestSet(capacity()); + } + + /** + * Constructs a tuple set of the given arity, over the specified universe, + * which initially contains all tuples whose indeces are between fromIndex + * and toIndex, inclusive. + * + * @ensures this.universe' = universe && this.arity' = arity && + * this.tuples' = {t: Tuple | t.universe=universe && t.arity=arity && + * fromIndex()<=t.index()<=toIndex() } + * @throws NullPointerException - universe = null + * @throws IllegalArgumentException - arity < 1 || + * @throws IndexOutOfBoundsException - fromIndex !in [0..toIndex] || + * toIndex !in [0..universe.size()^arity - 1] + */ + TupleSet(Universe universe, int arity, int fromIndex, int toIndex) { + this(universe,arity); + checkRange(toIndex, 0, capacity() - 1); + checkRange(fromIndex, 0, toIndex); + for(int i = fromIndex; i <= toIndex; i++) { + tuples.add(i); + } + } + + /** + * Returns a set of the given arity that contains all tuples whose indeces + * are contained in the given int set. Throws an IllegalArgumentException + * if the set contains an index that is either negative or greater than + * this.universe.size()^arity - 1. An attempt to iterate over a tuple set backed by an invalid index + * set will result in a runtime exception. + * @return {s: TupleSet | s.universe = this.universe && s.arity = arity && + * s.tuples = {t: Tuple | t.index() in tupleIndeces} } + * @throws NullPointerException - tupleIndeces = null + * @throws IllegalArgumentException - arity < 1 + * @throws IllegalArgumentException - tupleIndeces.min() < 0 || tupleIndeces.max() >= this.universe.size()^arity + */ + TupleSet(Universe universe, int arity, IntSet tupleIndeces) { + if (arity < 1) throw new IllegalArgumentException("arity < 1"); + universe.factory().checkCapacity(arity); + this.universe = universe; + this.arity = arity; + if (!tupleIndeces.isEmpty()) { + if (tupleIndeces.min()<0 || tupleIndeces.max() >= capacity()) + throw new IllegalArgumentException(tupleIndeces.min() + "<0 || " + tupleIndeces.max()+">="+universe.size()+"^"+arity); + } + tuples = tupleIndeces; + } + + /** + * Copy constructor. + * @ensures constructs a deep copy of the given tupleset + */ + private TupleSet(TupleSet original) { + this.universe = original.universe; + this.arity = original.arity; + try { + this.tuples = original.tuples.clone(); + } catch (CloneNotSupportedException e) { + throw new InternalError(); // unreachable code + } + this.indexView = null; + } + + /** + * Throws an IndexOutOfBoundsException if index is not in [min..max] + */ + private final void checkRange(int index, int min, int max) { + if (index < min || index > max) + throw new IndexOutOfBoundsException(index + " !in " + "[" + min + ".." + max + "]"); + } + + /** + * Returns the capacity of this set -- the maximum number of tuples + * that it can hold, given its universe and arity. + * @return this.universe.size() ^ this.arity + */ + public final int capacity() { + return (int) StrictMath.pow(universe.size(),arity); + } + + /** + * Returns this.universe. + * @return this.universe + */ + public Universe universe() { return universe; } + + /** + * Returns this.arity + * @return this.arity + */ + public int arity() { return arity; } + + + + /** + * Returns an unmodifiable int set view of the tuples stored in this set. + * Specifically, the returned int set contains an integer i + * iff this set contains a tuple with the index i. The + * view is backed by this set, so changes to this set are + * reflected in the index set. + * @return { s: IntSet | s.ints = {i: int | some t: this.tuples | t.index = i} + */ + public IntSet indexView() { + if (indexView==null) { + indexView = Ints.unmodifiableIntSet(tuples); + } + return indexView; + } + + /** + * Returns an unmodifiable view of the this tupleset. This method allows modules to + * provide "read-only" access to internal tuple sets. Query operations on the returned set + * "read through" to the specified set, and attempts to modify the returned set, whether direct + * or via its iterator, result in an UnsupportedOperationException. + * @return an unmodifiable view of the this tupleset + */ + public TupleSet unmodifiableView() { + return new TupleSet(universe,arity,indexView()); + } + + /** + * Returns a tuple set that is the cross product of this and the + * specified set. + * @return {t: TupleSet | t.arity = this.arity + s.arity && + * t.universe = this.universe && + * t.tuples = this.tuples->s.tuples } + * @throws NullPointerException - s = null + * @throws IllegalArgumentException - s.universe != this.universe + */ + public TupleSet product(TupleSet s) { + if (!s.universe().equals(universe)) + throw new IllegalArgumentException("s.universe != this.universe"); + final TupleSet ret = new TupleSet(universe, arity+s.arity()); + if (!s.isEmpty()) { + final int mCapacity = (int) StrictMath.pow(universe.size(), s.arity); + for(IntIterator indeces0 = tuples.iterator(); indeces0.hasNext(); ) { + int i0 = mCapacity * indeces0.next(); + for(IntIterator indeces1 = s.tuples.iterator(); indeces1.hasNext(); ) { + ret.tuples.add(i0 + indeces1.next()); + } + } + } + return ret; + } + + /** + * Projects this TupleSet onto the given dimension. + * @return {s: TupleSet | s.arity = 1 && s.universe = this.universe && + * s.tuples = { t: Tuple | some q: this.tuples | q.atoms[dimension] = t.atoms[int] } } + * @throws IllegalArgumentException - dimension < 0 || dimension >= this.arity + */ + public TupleSet project(int dimension) { + if (dimension < 0 || dimension >= arity) { + throw new IllegalArgumentException("dimension < 0 || dimension >= this.arity"); + } + final IntSet projection = Ints.bestSet(universe.size()); + final TupleFactory factory = universe.factory(); + for(IntIterator indexIter = tuples.iterator(); indexIter.hasNext();) { + projection.add(factory.project(indexIter.next(), arity, dimension)); + } + return new TupleSet(universe,1,projection); + } + + /** + * Returns a deep copy of this tuple set. + * @return {s: TupleSet - this | s.universe = this.universe && s.tuples = this.tuples } + */ + public TupleSet clone() { + // ok to use a copy constructor to clone a final class + return new TupleSet(this); + } + + /** + * Returns an iterator over the tuples in this tupleset. + * @return an iterator over the tuples in this tupleset. + */ + @Override + public Iterator iterator() { + return new Iterator() { + IntIterator indexIter = tuples.iterator(); + public boolean hasNext() { + return indexIter.hasNext(); + } + + public Tuple next() { + return universe.factory().tuple(arity, indexIter.next()); + } + + public void remove() { + indexIter.remove(); + } + }; + } + + /** + * Returns the index of the given tuple, if the tuple has the same + * arity and universe as this. Otherwise throws an IllegalArgumentException. + * @return t.index + * @throws IllegalArgumentException - t.arity != this.arity || t.universe != this.universe + */ + private final int extractIndex(Tuple t) { + if (t.arity() != arity || !t.universe().equals(universe)) { + throw new IllegalArgumentException("t.arity != this.arity || t.universe != this.universe"); + } + return t.index(); + } + + /** + * Returns true if this contains the given object. + * @return o in this.tuples + * @throws IllegalArgumentException o.arity != this.arity || o.universe != this.universe + */ + @Override + public boolean contains(Object o) { + return tuples.contains(extractIndex((Tuple)o)); + } + + /** + * Returns the size of this tupleset. + * @return #this.tuples + */ + @Override + public int size() { return tuples.size(); } + + /** + * Removes all tuples from this tupleset. + * @ensures no this.tuples' + */ + @Override + public void clear() { + tuples.clear(); + } + + /** + * Adds the specified tuple to this tupleset. Returns + * true if this set was changed as the result of the + * operation. + * @ensures this.tuples' = this.tuples + t + * @return o !in this.tuples + * @throws IllegalArgumentException - t.universe != this.universe || t.arity != this.arity + */ + @Override + public boolean add(Tuple t) { + return tuples.add(extractIndex(t)); + } + + /** + * Removes the given object from this tupleset, if present, and + * returns true. Otherwise does nothing and returns false. + * @ensures this.tuples' = this.tuples - o + * @return o in this.tuples + * @throws IllegalArgumentException - o.universe != this.universe || o.arity != this.arity + */ + @Override + public boolean remove(Object o) { + return tuples.remove(extractIndex((Tuple)o)); + } + + /** + * If c is not a TupleSet or it is a tupleset with a universe different than + * this.universe, returns null. Otherwise, returns the tuples associated + * with the modifiable view of c. + * @requires c in TupleSet => c.arity = this.arity + * @return c in TupleSet && c.universe = this.universe && c.arity = this.arity => c.tuples, null + * @throws NullPointerException - s = null + * @throws IllegalArgumentException - this.arity!=s.arity + */ + private IntSet extractTuples(Collection c) { + if (c instanceof TupleSet) { + final TupleSet s = (TupleSet) c; + if (arity!=s.arity()) + throw new IllegalArgumentException("this.arity!=c.arity"); + return universe.equals(s.universe()) ? s.tuples : null; + } + return null; + } + + /** + * Returns true if this contains all tuples from c. Otherwise returns false. + * @return c.elements in this.tuples + * @throws IllegalArgumentException - some t: c.elements | t.universe != this.universe || t.arity != this.arity + */ + @Override + public boolean containsAll(Collection c) { + final IntSet cTuples = extractTuples(c); + return cTuples==null ? super.containsAll(c) : tuples.containsAll(cTuples); + } + + /** + * Adds all tuples from c to this, if not present, and returns + * true. Otherwise does nothing and returns false. + * @ensures this.tuples' = this.tuples + c.elements + * @return c.elements !in this.tuples + * @throws IllegalArgumentException - some t: c.elements | t.universe != this.universe || t.arity != this.arity + */ + @Override + public boolean addAll(Collection c) { + final IntSet cTuples = extractTuples(c); + return cTuples==null ? super.addAll(c) : tuples.addAll(cTuples); + } + + /** + * Removes all tuples in c from this, if present, and returns + * true. Otherwise does nothing and returns false. + * @ensures this.tuples' = this.tuples - c.elements + * @return some c.elements & this.tuples + * @throws IllegalArgumentException - some t: c.elements | t.universe != this.universe || t.arity != this.arity + */ + @Override + public boolean removeAll(Collection c) { + final IntSet cTuples = extractTuples(c); + return cTuples==null ? super.removeAll(c) : tuples.removeAll(cTuples); + } + + /** + * Removes all tuples from this that are not in c, if any, and + * returns true. Otherwise does nothing and returns false. + * @ensures this.tuples' = this.tuples & c.elements + * @return this.tuples !in c.elements + * @throws IllegalArgumentException - some t: c.elements | t.universe != this.universe || t.arity != this.arity + */ + @Override + public boolean retainAll(Collection c) { + final IntSet cTuples = extractTuples(c); + return cTuples==null ? super.retainAll(c) : tuples.retainAll(cTuples); + } + + + /** + * Returns true if o contains the same tuples as this. + * @return this.tuples = o.elements + */ + @Override + public boolean equals(Object o) { + if (this==o) return true; + if (o instanceof TupleSet) { + final TupleSet s = (TupleSet) o; + return arity==s.arity && universe.equals(s.universe) && + tuples.equals(s.tuples); + } + return super.equals(o); + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return tuples.hashCode(); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/instance/Universe.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/instance/Universe.java new file mode 100644 index 00000000..4a6cde7c --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/instance/Universe.java @@ -0,0 +1,188 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.instance; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import kodkod.util.collections.Containers; + +/** + *

Represents an ordered set of unique atoms. Objects used as atoms must properly + * implement {@link java.lang.Object#equals equals} and {@link java.lang.Object#hashCode hashCode} + * methods. The behavior of a universe is not specified if the value of an object is changed in a + * manner that affects equals comparisons while the object is an atom in the universe.

+ * + *

Each universe provides a {@link kodkod.instance.TupleFactory tuple factory} + * to facilitate creation of {@link kodkod.instance.Tuple tuples} and + * {@link kodkod.instance.TupleSet sets of tuples} based on the atoms in the universe.

+ * + *

Implementation Note: although the atoms in a universe are not interpreted in any + * way by the Kodkod engine, it is strongly recommended that the atoms + * of the same 'type' be grouped together. For instance, suppose that a client model is specified in + * terms of disjoint types Person = {Person0, Person1, Person2} and Dog = {Dog0, Dog1}. Then, + * the client may observe an improvement in performance if he constructs the universe over the + * sequences {Person0, Person1, Person2, Dog0, Dog1} or {Dog0, Dog1, Person0, Person1, Person2} rather + * than any other permutation of these five atoms. + * + * @specfield size: int + * @specfield atoms: [0..size)->one Object + * @specfield factory: TupleFactory + * @invariant factory = (TupleFactory<:universe).this + * @invariant size > 0 + * @author Emina Torlak + */ +public final class Universe implements Iterable { + private final Object[] atoms; + private final Map indices; + private final TupleFactory factory; + + /** + * Constructs a new Universe consisting of the given atoms, in the order that they are returned + * by the specified Collection's Iterator. + * + * @ensures this.size' = atoms.size && this.atoms' = atoms.iterator + * @throws NullPointerException - atoms = null + * @throws IllegalArgumentException - atoms contains duplicates + * @throws IllegalArgumentException - atoms is empty + */ + public Universe(Collection atoms) { + if (atoms.isEmpty()) throw new IllegalArgumentException("Cannot create an empty universe."); + this.atoms = new Object[atoms.size()]; + this.indices = new HashMap(); + int i = 0; + for (Object atom : atoms) { + if (indices.containsKey(atom)) + throw new IllegalArgumentException(atom + " appears multiple times."); + indices.put(atom, i); + this.atoms[i] = atom; + i++; + } + this.factory = new TupleFactory(this); + } + + /** + * Constructs a new Universe consisting of the given atoms, in the order that they appear + * in the specified array + * + * @ensures this.size' = atoms.length && this.atoms' = atoms + * @throws NullPointerException - atoms = null + * @throws IllegalArgumentException - atoms contains duplicates + * @throws IllegalArgumentException - atoms is empty + */ + public Universe(Object...atoms) { + if (atoms.length==0) throw new IllegalArgumentException("Cannot create an empty universe."); + this.atoms = Containers.copy(atoms, new Object[atoms.length]); + this.indices = new HashMap(); + for (int i = 0; i < atoms.length; i++) { + if (indices.containsKey(atoms[i])) + throw new IllegalArgumentException(atoms[i] + " appears multiple times."); + indices.put(atoms[i], i); + } + this.factory = new TupleFactory(this); + } + + /** +// * Returns a universe that stores the given atoms explicitly, in the specified order. +// * The returned universe provides constant time index and atom lookup. +// * @ensures { u: Universe | u.size = atoms.length && u.atoms = atoms } +// * @throws IllegalArgumentException - atoms contains duplicates +// * @throws IllegalArgumentException - atoms is empty +// */ +// public static Universe universe(Object...atoms) { return new ExplicitUniverse(atoms); } +// +// /** +// * Returns a universe that stores the given atoms explicitly, in the order in which they +// * are returned by the collection's iterator. The returned universe provides constant +// * time index and atom lookup. +// * @ensures { u: Universe | u.size = atoms.size() && u.atoms[int] = atoms } +// * @throws IllegalArgumentException - atoms contains duplicates +// * @throws IllegalArgumentException - atoms is empty +// */ +// public static Universe universe(Collection atoms) { return new ExplicitUniverse(atoms); } + + /** + * Returns a TupleFactory that can be used to construct tuples and sets + * of tuples based on this universe. + * @return this.factory + */ + public TupleFactory factory() { return this.factory; } + + /** + * Returns the size of this universe + * + * @return #this.atoms + */ + public int size() { return atoms.length; } + + /** + * Returns true if atom is in this universe, otherwise returns false. + * + * @return atom in this.atoms[int] + */ + public boolean contains(Object atom) { return indices.containsKey(atom); } + + /** + * Returns the i_th atom in this universe + * + * @return this.atoms[i] + * @throws IndexOutOfBoundsException - i < 0 || i >= this.size + */ + public Object atom(int index) { + if (index<0||index>=atoms.length) throw new IndexOutOfBoundsException(); + return atoms[index]; + } + + /** + * Returns the index of the specified atom in this universe; if the + * atom is not in this universe, an IllegalArgumentException is thrown. + * + * @return this.atoms.atom + * @throws IllegalArgumentException - no this.atoms.atom + */ + public int index(Object atom) { + if (indices.containsKey(atom)) return indices.get(atom); + else throw new IllegalArgumentException("no this.atoms." + atom); + } + + /** + * Returns an iterator over atoms in this universe, according to their + * order in the universe. + * @return an iterator over atoms in this universe, according to their + * order in the universe + */ + public Iterator iterator() { + return Containers.iterate(atoms); + } + + /** + * Returns a string representation of this universe. + * @return string representation of this universe. + */ + public String toString() { + return Arrays.toString(atoms); + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/ArrayStack.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/ArrayStack.java new file mode 100644 index 00000000..ba27de9c --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/ArrayStack.java @@ -0,0 +1,166 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.collections; + +import java.util.EmptyStackException; +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * A Stack implementation based on an array. + * + * @author Emina Torlak + */ +public class ArrayStack extends Stack { + /* stack elements: the last element in the array is at the top of the stack. */ + private T[] elems; + private int size; + + /** + * Constructs an empty stack with the inital capacity of 10. + * @ensures no this.elems' + */ + public ArrayStack() { + this(10); + } + + @SuppressWarnings("unchecked") + public ArrayStack(int initialCapacity) { + if (initialCapacity < 0) + throw new IllegalArgumentException(initialCapacity + "<0"); + elems = (T[]) new Object[initialCapacity]; + size = 0; + } + + /** + * Increases the capacity of this ArrayStack, if necessary, to ensure that + * it can hold at least the number of elements specified by the minimum + * capacity argument. + */ + @SuppressWarnings("unchecked") + public void ensureCapacity(int minCapacity) { + final int oldCapacity = elems.length; + if (minCapacity > oldCapacity) { + final T[] oldElems = elems; + elems = (T[]) new Object[StrictMath.max(minCapacity, (oldCapacity * 3) / 2)]; + System.arraycopy(oldElems,0,elems,0,size); + } + } + + /** + * Trims the capacity of this ArrayStack to be the + * stack's current size. An application can use this operation to minimize + * the storage of an ArrayStack instance. + */ + @SuppressWarnings("unchecked") + public void trimToSize() { + final int oldCapacity = elems.length; + if (size < oldCapacity) { + final Object oldElems[] = elems; + elems = (T[])new Object[size]; + System.arraycopy(oldElems, 0, elems, 0, size); + } + } + + /** + * @see kodkod.util.collections.Stack#size() + */ + public int size() { return size; } + + /** + * {@inheritDoc} + * @see kodkod.util.collections.Stack#push + */ + public T push(T item) { + ensureCapacity(size + 1); + elems[size++] = item; + return item; + } + + /** + * @see kodkod.util.collections.Stack#pop() + */ + public T pop() { + if (empty()) throw new EmptyStackException(); + final T top = elems[--size]; + elems[size] = null; + return top; + } + + /** + * @see kodkod.util.collections.Stack#peek() + */ + public T peek() { + if (empty()) throw new EmptyStackException(); + return elems[size-1]; + } + + /** + * @see kodkod.util.collections.Stack#search(java.lang.Object) + */ + public int search(Object o) { + for(int i = size-1; i >= 0; i--) { + if (equal(o, elems[i])) + return i; + } + return -1; + } + + /** + * @see kodkod.util.collections.Stack#empty() + */ + public boolean empty() { + return size==0; + } + + /** + * {@inheritDoc} + * @see kodkod.util.collections.Stack#iterator() + */ + public Iterator iterator() { + return new Iterator() { + int cursor = size - 1, lastReturned = -1; + + public boolean hasNext() { + return cursor >= 0; + } + + public T next() { + if (cursor < 0) + throw new NoSuchElementException(); + lastReturned = cursor; + return elems[cursor--]; + } + + public void remove() { + if (lastReturned < 0) + throw new UnsupportedOperationException(); + size--; + System.arraycopy(elems, lastReturned+1, elems, lastReturned, size - lastReturned); + elems[size] = null; + lastReturned = -1; + } + + }; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/CacheSet.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/CacheSet.java new file mode 100644 index 00000000..8d18ff82 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/CacheSet.java @@ -0,0 +1,439 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.collections; + +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * Implements the Set interface, backed by a hash table. + * It makes no guarantees as to the + * iteration order of the set; in particular, it does not guarantee that the + * order will remain constant over time. This class does not permit the null + * element.

+ * + * This class offers constant time performance for the basic operations + * (add, remove, contains and size), + * assuming the hash function disperses the elements properly among the + * buckets. Iterating over this set requires time proportional to the sum of + * the HashSet instance's size (the number of elements) plus the + * "capacity" of the backing map (the number of + * buckets). Thus, it's very important not to set the initial capacity too + * high (or the load factor too low) if iteration performance is important.

+ * + *

This set differs from Java's HashSet in that it provides methods for + * retrieving elements with a particular hashcode. This makes it + * easy to set as a cache in which cached objects' hashcodes are their keys.

+ * + *

Note that this implementation is not synchronized. + * The iterators returned by this class's iterator method are + * not fail-fast

+ * + * @specfield elts: set T + * @author Emina Torlak + */ +public final class CacheSet extends AbstractSet { + /* implementation adapted from java.util.HashMap and java.util.HashSet */ + /** + * The default initial capacity - MUST be a power of two. + */ + private static final int DEFAULT_INITIAL_CAPACITY = 16; + + /** + * The maximum capacity, used if a higher value is implicitly specified + * by either of the constructors with arguments. + * MUST be a power of two <= 1<<30. + */ + private static final int MAXIMUM_CAPACITY = 1 << 30; + + /** + * The load factor used when none specified in constructor. + **/ + private static final float DEFAULT_LOAD_FACTOR = 0.75f; + + /** + * The table, resized as necessary. Length MUST Always be a power of two. + */ + private Entry[] table; + + /** + * The number of key-value mappings contained in this identity hash map. + */ + private int size; + + /** + * The next size value at which to resize (capacity * load factor). + */ + private int threshold; + + /** + * The load factor for the hash table. + */ + final float loadFactor; + + /** + * Constructs a new, empty set; the backing map has + * default initial capacity (16) and load factor (0.75). + * @ensures no this.elts' + */ + @SuppressWarnings("unchecked") + public CacheSet() { + loadFactor = DEFAULT_LOAD_FACTOR; + threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); + table = new Entry[DEFAULT_INITIAL_CAPACITY]; + } + + /** + * Constructs a new, empty set; the backing map has + * the specified initial capacity and the specified load factor. + * + * @param initialCapacity the initial capacity of the hash map. + * @param loadFactor the load factor of the hash map. + * @throws IllegalArgumentException if the initial capacity is less + * than zero, or if the load factor is nonpositive. + * @ensures no this.elts' + */ + @SuppressWarnings("unchecked") + public CacheSet(int initialCapacity, float loadFactor) { + if (initialCapacity < 0) + throw new IllegalArgumentException("Illegal initial capacity: " + + initialCapacity); + if (initialCapacity > MAXIMUM_CAPACITY) + initialCapacity = MAXIMUM_CAPACITY; + if (loadFactor <= 0 || Float.isNaN(loadFactor)) + throw new IllegalArgumentException("Illegal load factor: " + + loadFactor); + + // Find a power of 2 >= initialCapacity + int capacity = 1; + while (capacity < initialCapacity) + capacity <<= 1; + + this.loadFactor = loadFactor; + threshold = (int)(capacity * loadFactor); + table = new Entry[capacity]; + } + + /** + * Constructs a new set containing the elements in the specified + * collection. The HashMap is created with default load factor + * (0.75) and an initial capacity sufficient to contain the elements in + * the specified collection. + * + * @param c the collection whose elements are to be placed into this set. + * @throws NullPointerException if the specified collection is null. + */ + public CacheSet(Collection c) { + this(c.size(), .75f); + addAll(c); + } + + /** + * Returns a hash value for the specified integer. + * The shift distances in this function were chosen as the result + * of an automated search over the entire four-dimensional search space. + */ + private static int hash(int h) { + h += ~(h << 9); + h ^= (h >>> 14); + h += (h << 4); + h ^= (h >>> 10); + return h; + } + + /** + * Returns a hash value for the specified object. In addition to + * the object's own hashCode, this method applies a "supplemental + * hash function," which defends against poor quality hash functions. + * This is critical because HashMap uses power-of two length + * hash tables.

+ * + * The shift distances in this function were chosen as the result + * of an automated search over the entire four-dimensional search space. + */ + private static int hash(Object x) { + return hash(x.hashCode()); + } + + /** + * Returns index for hash code h. + */ + private static int indexFor(int h, int length) { + return h & (length-1); + } + + /** + * Returns the number of elements in this set. + * @return #this.elts + * @see java.util.Set#size() + */ + public int size() { + return size; + } + + /** + * Returns true if this set is empty. + * @return no this.elts + * @see java.util.Set#isEmpty() + */ + public boolean isEmpty() { + return size==0; + } + + /** + * Returns true if this set contains the given element. + * @return elt in this.elts + * @throws NullPointerException - elt = null + * @see java.util.Set#contains(java.lang.Object) + */ + public boolean contains(Object elt) { + Entry e = table[indexFor(hash(elt), table.length)]; + while (e != null) { + if (e.val.equals(elt)) + return true; + e = e.next; + } + return false; + } + + /** + * Returns an iterator over the elements in this set. + * @return an iterator over this.elts. + * @see java.util.Set#iterator() + */ + public Iterator iterator() { + return new SetIterator(); + } + + /** + * Adds the given element to this set, if not already present. + * @ensures this.elts' = this.elts + elt + * @throws NullPointerException - elt = null + * @return elt !in this.elts + */ + public boolean add(E elt) { + final int i = indexFor(hash(elt), table.length); + + for (Entry e = table[i]; e != null; e = e.next) { + if (e.val.equals(elt)) { + return false; + } + } + + table[i] = new Entry(elt, table[i]); + if (size++ >= threshold) + resize(2 * table.length); + + return true; + } + + /** + * Rehashes the contents of this map into a new array with a + * larger capacity. This method is called automatically when the + * number of keys in this map reaches its threshold. + * + * If current capacity is MAXIMUM_CAPACITY, this method does not + * resize the map, but sets threshold to Integer.MAX_VALUE. + * This has the effect of preventing future calls. + * + * @param newCapacity the new capacity, MUST be a power of two; + * must be greater than current capacity unless current + * capacity is MAXIMUM_CAPACITY (in which case value + * is irrelevant). + */ + @SuppressWarnings("unchecked") + private void resize(int newCapacity) { + Entry[] oldTable = table; + int oldCapacity = oldTable.length; + if (oldCapacity == MAXIMUM_CAPACITY) { + threshold = Integer.MAX_VALUE; + return; + } + + Entry[] newTable = new Entry[newCapacity]; + transfer(newTable); + table = newTable; + threshold = (int)(newCapacity * loadFactor); + } + + /** + * Transfer all entries from current table to newTable. + */ + private void transfer(Entry[] newTable) { + Entry[] src = table; + int newCapacity = newTable.length; + for (int j = 0; j < src.length; j++) { + Entry e = src[j]; + if (e != null) { + src[j] = null; + do { + Entry next = e.next; + int i = indexFor(hash(e.val), newCapacity); + e.next = newTable[i]; + newTable[i] = e; + e = next; + } while (e != null); + } + } + } + + /** + * Removes the specified object from this set, if present. + * @ensures this.elts' = this.elts - elt + * @return elt in this.elts + * @throws NullPointerException - elt = null + * @see java.util.Set#remove(java.lang.Object) + */ + public boolean remove(Object elt) { + int i = indexFor(hash(elt), table.length); + Entry prev = table[i]; + Entry e = prev; + + while (e != null) { + Entry next = e.next; + if (e.val.equals(elt)) { + size--; + if (prev == e) + table[i] = next; + else + prev.next = next; + return true; + } + prev = e; + e = next; + } + + return false; + + } + + /** + * Returns an iterator over the elements + * whose hashcode() method returns the given hash. + * @return an iterator over {e: this.elts | e.hashCode() = hash } + */ + public Iterator get(final int hash) { + final int i = indexFor(hash(hash), table.length); + return new Iterator() { + + Entry current = null, next = table[i]; + + public boolean hasNext() { + while(next != null && next.val.hashCode()!=hash) { + next = next.next; + } + return next != null; + } + + public E next() { + if (!hasNext()) throw new NoSuchElementException(); + current = next; + next = next.next; + return current.val; + } + + public void remove() { + if (current==null) + throw new IllegalStateException(); + Entry prev = table[i]; + Entry e = prev; + + while (e.next != current) { + prev = e; + e = e.next; + } + + size--; + if (prev==e) + table[i] = next; + else + prev.next = next; + current = null; + } + + }; + } + + /** + * Removes all elements from this set. + * @ensures no this.elts' + * @see java.util.Set#clear() + */ + public void clear() { + for (int i = 0; i < table.length; i++) + table[i] = null; + size = 0; + } + + private static final class Entry { + Entry next; + T val; + + Entry(T val, Entry next) { + this.val = val; + this.next = next; + } + } + + private final class SetIterator implements Iterator { + Entry next; // next entry to return + int index; // current slot + Entry current; // current entry + + SetIterator() { + index = table.length; + next = null; + if (size != 0) { // advance to first entry + while (index > 0 && (next = table[--index]) == null) + ; + } + } + + public boolean hasNext() { + return next != null; + } + + public E next() { + Entry e = next; + if (e == null) + throw new NoSuchElementException(); + + Entry n = e.next; + while (n == null && index > 0) + n = table[--index]; + next = n; + return (current = e).val; + + } + + public void remove() { + if (current == null) + throw new IllegalStateException(); + + CacheSet.this.remove(current.val); + current = null; + } + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/Containers.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/Containers.java new file mode 100644 index 00000000..66e34196 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/Containers.java @@ -0,0 +1,395 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.collections; + +import java.util.AbstractSet; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Set; + +/** + * Provides utility methods for working with arrays and collections. + * + * @author Emina Torlak + */ +public final class Containers { + private static Comparator identityComparator; + private static Comparator hashComparator; + + private Containers() {} + /** + * Returns a new iterator over the given array of items. + * The iterator is backed by the given array. The contents + * of the array are not modified by the iterator. The effect + * of this method is the same as calling Iterators.iterator(0, items.length, items). + * @throws NullPointerException - items = null + */ + public static final Iterator iterate(final E... items) { + return new AscendingArrayIterator(0, items.length, items); + } + + /** + * Returns a new iterator over the given array of items. + * The iterator is backed by the given array. The contents + * of the array are not modified by the iterator. + * The returned iterator enumerates the items located between + * indeces start, inclusive, and end, exclusive. If start < end, + * the elements are returned in the ascending order; otherwise, + * they are returned in the descending order. + * @throws NullPointerException - items = null + * @throws IllegalArgumentException - start < end && (start < 0 || end > items.length) || + * start > end && (start >= items.length || end < -1) + */ + @SuppressWarnings("unchecked") + public static final Iterator iterate(int start, int end, final E... items) { + if (start < end) + return new AscendingArrayIterator(start,end,items); + else if (start > end) + return new DescendingArrayIterator(start,end,items); + else + return emptyIterator(); + } + + /** + * Returns an iterator that has no elements. That is, + * calls to hasNext will return false, and all other + * calls will result in a runtime exception. + * @return an empty iterator + */ + @SuppressWarnings("unchecked") + public static final Iterator emptyIterator() { + return (Iterator) Collections.emptySet().iterator(); + } + + /** + * Calls System.arraycopy(src, srcPos, dest, destPos, length) and returns the destination array. + * @ensures System.arraycopy(src, srcPos, dest, destPos, length) + * @return dest + */ + public static final T[] copy(T[] src, int srcPos, T[] dest, int destPos, int length) { + System.arraycopy(src, srcPos, dest, destPos, length); + return dest; + } + + /** + * Calls System.arraycopy(src, 0, dest, 0, src.length) and returns the destination array. + * @requires dest.length >= src.length + * @ensures System.arraycopy(src, 0, dest, 0, src.length) + * @return dest + */ + public static final T[] copy(T[] src, T[] dest) { + System.arraycopy(src, 0, dest, 0, src.length); + return dest; + } + + /** + * Returns a comparator that compares objects according to their + * {@link System#identityHashCode(Object) identity hashcodes}. + * @return a comparator that compares objects according to their + * {@link System#identityHashCode(Object) identity hashcodes}. + */ + public static final Comparator identityComparator() { + if (identityComparator==null) { + identityComparator = new Comparator() { + public int compare(Object o1, Object o2) { + final int c1 = System.identityHashCode(o1); + final int c2 = System.identityHashCode(o2); + return c1 == c2 ? 0 : (c1 < c2 ? -1 : 1); + } + }; + } + return identityComparator; + } + + /** + * Returns 0 if o is null, otherwise returns o.hashCode(). + * @return o=null => 0, o.hashCode() + */ + static final int hash(Object o) { + return o==null ? 0 : o.hashCode(); + } + + /** + * Returns true if both o1 and o2 are null or if o1.equals(o2) + * @return true if both o1 and o2 are null or if o1.equals(o2) + */ + static final boolean eq(Object o1, Object o2) { + return o1==null ? o2==null : o1.equals(o2); + } + + /** + * Returns a comparator that compares objects according to their + * {@link Object#hashCode() hashcodes}. The null reference is + * considered to have a hashcode of 0. + * @return a comparator that compares objects according to their + * {@link Object#hashCode() hashcodes}. + */ + public static final Comparator hashComparator() { + if (hashComparator==null) { + hashComparator = new Comparator() { + public int compare(Object o1, Object o2) { + final int c1 = hash(o1); + final int c2 = hash(o2); + return c1 == c2 ? 0 : (c1 < c2 ? -1 : 1); + } + }; + } + return hashComparator; + } + + /** + * Calls {@link java.util.Arrays#sort(Object[], Comparator)} on the + * given array and returns it. The elements are sorted in the ascending + * order of their identity hashcodes. + * @ensures java.util.Arrays.sort(array, {@link #identityComparator()}) + * @return the given array, with its elements sorted in the increasing order of identity hashcodes + */ + public static final T[] identitySort(T[] array) { + java.util.Arrays.sort(array, identityComparator()); + return array; + } + + /** + * Calls {@link java.util.Arrays#sort(Object[], Comparator)} on the + * given array and returns it. The elements are sorted in the ascending + * order of their hashcodes. + * @ensures java.util.Arrays.sort(array, {@link #hashComparator()}) + * @return the given array, with its elements sorted in the increasing order of hashcodes + */ + public static final T[] hashSort(T[] array) { + java.util.Arrays.sort(array, hashComparator()); + return array; + } + + /** + * Searches the specified array for the specified object using the binary search algorithm + * and reference equality. + * The array must be sorted into ascending order according to the identity hashcodes of its elements + * (as by {@link #identitySort(Object[])}) prior to making this call. If it is not sorted, + * the results are undefined. If the array contains multiple occurences of the specified object, + * there is no guarantee which one will be found. + * @requires all i, j: [0..array.length) | i < j => array[i].hashCode() <= array[j].hashCode()) + * @return index of the search key, if it is contained in the array; otherwise, (-(insertion point) - 1). + * The insertion point is defined as the point at which the key would be inserted into the array: the + * index of the first element greater than the key, or array.length, if all elements in the array are less + * than the specified key. Note that this guarantees that the return value will be >= 0 if and only if the + * key is found. + */ + public static final int identityBinarySearch(Object[] array, Object key) { + int low = 0; + int high = array.length-1; + int index = System.identityHashCode(key); + + while (low <= high) { + int mid = (low + high) >>> 1; + int midIndex = System.identityHashCode(array[mid]); + if (midIndex < index) + low = mid + 1; + else if (midIndex > index) + high = mid - 1; + else { // index found, now check that variables are the same + if (array[mid]==key) return mid; + // check all variables with the same index (if any) + for(int i = mid+1; i < array.length && System.identityHashCode(array[i])==index; i++) { + if (array[i]==key) return i; + } + for(int i = mid-1; i >= 0 && System.identityHashCode(array[i])==index; i--) { + if (array[i]==key) return i; + } + return -(mid+1); // var not found + } + } + + return -(low + 1); // key not found. + } + + /** + * Searches the specified array for the specified object using the binary search algorithm + * and object equality. + * The array must be sorted into ascending order according to the hashcodes of its elements + * (as by {@link #hashSort(Object[])}) prior to making this call. If it is not sorted, + * the results are undefined. If the array contains multiple occurences of the specified object, + * there is no guarantee which one will be found. + * @requires all i, j: [0..array.length) | i < j => System.identityHashCode(array[i]) <= System.identityHashCode(array[j]) + * @return index of the search key, if it is contained in the array; otherwise, (-(insertion point) - 1). + * The insertion point is defined as the point at which the key would be inserted into the array: the + * index of the first element greater than the key, or array.length, if all elements in the array are less + * than the specified key. Note that this guarantees that the return value will be >= 0 if and only if the + * key is found. + */ + public static final int hashBinarySearch(Object[] array, Object key) { + int low = 0; + int high = array.length-1; + int index = hash(key); + + while (low <= high) { + int mid = (low + high) >>> 1; + int midIndex = hash(array[mid]); + if (midIndex < index) + low = mid + 1; + else if (midIndex > index) + high = mid - 1; + else { // index found, now check that variables are the same + if (eq(array[mid], key)) return mid; + // check all variables with the same index (if any) + for(int i = mid+1; i < array.length && hash(array[i])==index; i++) { + if (eq(array[i], key)) return i; + } + for(int i = mid-1; i >= 0 && hash(array[i])==index; i--) { + if (eq(array[i], key)) return i; + } + return -(mid+1); // var not found + } + } + + return -(low + 1); // key not found. + } + + /** + * Returns an identity set backed by the given array (i.e. a set that uses + * reference equality for comparisons). + * The array must contain no duplicates, its elements must be + * sorted in the increasing order of identity hashcodes (as by {@link #identitySort(Object[])}), and its contents + * must not be changed while it is in use by the returned set. + * @requires all i, j: [0..array.length) | i < j => System.identityHashCode(array[i]) <= System.identityHashCode(array[j]) + * @return an unmodifiable identity Set view of the given array + */ + public static final Set asIdentitySet(final T[] array) { + return new AbstractSet() { + public boolean contains(Object o) { + return identityBinarySearch(array, o) >= 0; + } + public Iterator iterator() { return iterate(array); } + public int size() { return array.length; } + public int hashCode() { + int result = 0; + for (Object o : array) { result += System.identityHashCode(o); } + return result; + } + }; + } + + /** + * Returns a set backed by the given array (i.e. a set that uses + * object equality for comparisons). + * The array must contain no duplicates, its elements must be + * sorted in the increasing order of hashcodes (as by {@link #hashSort(Object[])}), and its contents + * must not be changed while it is in use by the returned set. + * @requires all i, j: [0..array.length) | i < j => array[i].hashCode() <= array[j].hashCode + * @return an unmodifiable Set view of the given array + */ + public static final Set asHashSet(final T[] array) { + return new AbstractSet() { + public boolean contains(Object o) { + return hashBinarySearch(array, o) >= 0; + } + public Iterator iterator() { return iterate(array);} + public int size() { return array.length;} + }; + } + + /** + * An unmodifying iterator over an array. + */ + private static abstract class ArrayIterator implements Iterator { + final T[] items; + final int end; + int cursor; + + /** + * Constructs a new iterator over the given array of items. + * The iterator is backed by the given array. The contents + * of the array are not modified by the iterator. The + * constructed iterator returns the items located between the + * indeces start, inclusive, and end, exclusive. + * @requires items != null && + * start < end => end in [0..items.length] && start in [0..end], + * start in [0..items.length) && end in [-1..start] + */ + ArrayIterator(int start, int end, final E... items) { + this.items = items; + this.cursor = start; + this.end = end; + } + + public final void remove() { + throw new UnsupportedOperationException(); + } + } + + /** + * An ascending iterator over an array. + */ + private static final class AscendingArrayIterator extends ArrayIterator { + + /** + * Constructs a new iterator over the given array of items. + * @requires items != null && start < end + * @throws IllegalArgumentException - start < 0 || end > items.length + */ + AscendingArrayIterator(int start, int end, E[] items) { + super(start, end, items); + if (start < 0 || end > items.length) { + throw new IllegalArgumentException("start < end && (start < 0 || end > items.length)"); + } + } + + public boolean hasNext() { + return cursor >= 0 && cursor < end; + } + + public T next() { + if (!hasNext()) throw new NoSuchElementException(); + return items[cursor++]; + } + } + + /** + * A descending iterator over an array. + */ + private static final class DescendingArrayIterator extends ArrayIterator { + /** + * Constructs a new iterator over the given array of items. + * @requires items != null && start > end + * @throws IllegalArgumentException - start >= items.length || end < -1 + */ + DescendingArrayIterator(int start, int end, E[] items) { + super(start, end, items); + if (start >= items.length || end < -1) { + throw new IllegalArgumentException("start > end && (start >= items.length || end < -1)"); + } + } + + public boolean hasNext() { + return cursor > end; + } + + public T next() { + if (!hasNext()) throw new NoSuchElementException(); + return items[cursor--]; + } + + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/FixedMap.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/FixedMap.java new file mode 100644 index 00000000..e6e55bf5 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/FixedMap.java @@ -0,0 +1,410 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.collections; + +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; + + +/** + * A map with a fixed set of keys that acts as an indexer, assigning a + * unique integer in the range [0..#keys) to each key. This class implements the + * Map interface with an array, using + * reference-equality in place of object-equality when comparing keys (and + * values). In other words, in a FixedMap, two keys + * k1 and k2 are considered equal if and only if + * (k1==k2). (In normal Map implementations (like + * HashMap) two keys k1 and k2 are considered equal + * if and only if (k1==null ? k2==null : k1.equals(k2)).)

+ * + *

This class is not a general-purpose Map + * implementation! While this class implements the Map interface, it + * intentionally violates Map's general contract, which mandates the + * use of the equals method when comparing objects.

+ * + *

This class provides {@link #put(Object, Object)} operation for the keys + * within its fixed key set and permits + * null values and the null key. The {@link #remove(Object)} + * operation is not supported. This class guarantees + * that the order of the map will remain constant over time.

+ * + *

This class provides log-time performance for the basic + * operations (get and put), assuming the system + * identity hash function ({@link System#identityHashCode(Object)}) + * disperses elements properly among the buckets.

+ * + *

This implementation is not synchronized, and its iterators are not fail-fast.

+ * + * @specfield keys: set K + * @specfield map: keys -> one V + * @specfield indices: keys lone->one [0..#keys) + * @author Emina Torlak + */ +public final class FixedMap extends AbstractMap implements Indexer { + + private final Object[] keys; + private final Object[] values; + + /** + * Constructs a new fixed map from the given map. + * @ensures this.keys' = keys && this.map = map.map + */ + public FixedMap(Map map) { + this(map.keySet()); + for(int i = 0, size = map.size(); i < size; i++) { + values[i] = map.get(keys[i]); + } + } + + /** + * Constructs a new fixed map for the given set of keys. + * @ensures this.keys' = keys && no this.map' + */ + public FixedMap(Set keys) { + final int size = keys.size(); + this.keys = Containers.identitySort(keys.toArray(new Object[size])); + values = new Object[size]; + } + + /** + * Constructs a new fixed map, backed by the given array of keys. The provided + * array must not contain duplicates, its entries must be sorted + * in the increasing order of identity hashcodes, and it must not + * be modified while in use by this map. The map will not behave correctly if + * these requirements are violated. + * @requires no disj i, j: [0..keys.length) | keys[i] == keys[j] + * @requires all i, j: [0..keys.length) | i < j => System.identityHashCode(keys[i]) <= System.identityHashCode(keys[j]) + * @ensures this.keys' = keys && no this.map' + */ + public FixedMap(K[] keys) { + this.keys = keys; + this.values = new Object[keys.length]; + } + + /** + * Returns the index of the given key, if it is in this.keys. + * Otherwise returns a negative number. + * @return key in this.keys => this.indices[key], {i: int | i < 0 } + */ + public final int indexOf(K key) { + return Containers.identityBinarySearch(keys, key); + } + + /** + * Returns the key at the given index. + * @return this.indices.index + * @throws IndexOutOfBoundsException - index !in this.indices[this.keys] + */ + @SuppressWarnings("unchecked") + public final K keyAt(int index) { + try { + return (K)keys[index]; + } catch (ArrayIndexOutOfBoundsException e) { + throw new IndexOutOfBoundsException(); + } + } + + /** + * Tests whether the specified object reference is a key in this fixed map. + * + * @return key in this.keys + */ + @SuppressWarnings("unchecked") + public final boolean containsKey(Object key) { + return indexOf((K)key) >= 0; + } + + /** + * Tests whether the specified object reference is a value in this fixed map. + * + * @return value in this.map[this.keys] + */ + public final boolean containsValue(Object value) { + for(Object o : values) { + if (o==value) return true; + } + return false; + } + + /** + * Returns a set view of the mappings contained in this map. Each element + * in the returned set is a reference-equality-based Map.Entry. + * The set is backed by the map, so changes to the map are reflected in + * the set, and vice-versa. If the map is modified while an iteration + * over the set is in progress, the results of the iteration are + * undefined. The set does support neither removal nor addition. + * + *

Like the backing map, the Map.Entry objects in the set + * returned by this method define key and value equality as + * reference-equality rather than object-equality. This affects the + * behavior of the equals and hashCode methods of these + * Map.Entry objects. A reference-equality based Map.Entry + * e is equal to an object o if and only if o is a + * Map.Entry and e.getKey()==o.getKey() && + * e.getValue()==o.getValue(). To accommodate these equals + * semantics, the hashCode method returns + * System.identityHashCode(e.getKey()) ^ + * System.identityHashCode(e.getValue()). + * + *

Owing to the reference-equality-based semantics of the + * Map.Entry instances in the set returned by this method, + * it is possible that the symmetry and transitivity requirements of + * the {@link Object#equals(Object)} contract may be violated if any of + * the entries in the set is compared to a normal map entry, or if + * the set returned by this method is compared to a set of normal map + * entries (such as would be returned by a call to this method on a normal + * map). However, the Object.equals contract is guaranteed to + * hold among identity-based map entries, and among sets of such entries. + * + * + * @return a set view of the identity-mappings contained in this map. + */ + public final Set> entrySet() { + return new AbstractSet>() { + + @SuppressWarnings("unchecked") + public boolean contains(Object o) { + final Map.Entry e = (Map.Entry) o; + final int index = FixedMap.this.indexOf(e.getKey()); + return index < 0 ? false : values[index]==e.getValue(); + } + + public Iterator> iterator() { return new EntryIterator(); } + + public int size() { return keys.length; } + + public Object[] toArray() { + int size = size(); + Object[] result = new Object[size]; + for (int i = 0; i < size; i++) + result[i] = new Entry(i); + return result; + } + + @SuppressWarnings("unchecked") + public T[] toArray(T[] a) { + int size = size(); + if (a.length < size) + a = (T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size); + for (int i = 0; i < size; i++) + a[i] = (T) new Entry(i); + if (a.length > size) + a[size] = null; + return a; + } + }; + } + + /** + * Returns the value to which the specified key is mapped in this fixed map, + * or null if the map contains no mapping for + * this key. A return value of null does not necessarily + * indicate that the map contains no mapping for the key; it is also + * possible that the map explicitly maps the key to null. The + * containsKey method may be used to distinguish these two + * cases. + * + * @return this.map[key] + */ + @SuppressWarnings("unchecked") + public final V get(Object key) { + final int index = indexOf((K)key); + return index < 0 ? null : (V)values[index]; + } + + /** + * Returns the value to which the key at the specified index is mapped in this fixed map. + * @requires index in this.indices[this.keys] + * @return this.map[this.indices.index] + * @throws IndexOutOfBoundsException - index !in this.indices[this.keys] + */ + @SuppressWarnings("unchecked") + public final V get(int index) { + try { + return (V) values[index]; + } catch (ArrayIndexOutOfBoundsException e) { + throw new IndexOutOfBoundsException(); + } + } + + /** + * @see java.util.Map#isEmpty() + */ + public final boolean isEmpty() { + return keys.length==0; + } + + /** + * Associates the specified value with the specified key in this fixed + * map. If the map previously contained a mapping for this key, the + * old value is replaced. This method assumes that the given key is + * in the fixed keyset of this map. + * + * @requires key in this.keys + * @return this.map[key] + * @ensures this.map' = this.map ++ key->value + * @throws IllegalArgumentException - key !in this.keys + */ + + @SuppressWarnings("unchecked") + public final V put(K key, V value) { + final int index = indexOf((K)key); + if (index < 0) throw new IllegalArgumentException(); + final V oldValue = (V) values[index]; + values[index] = value; + return oldValue; + } + + /** + * Throws an {@link UnsupportedOperationException} exception. + * @see java.util.Map#remove(java.lang.Object) + */ + public final V remove(Object key) { + throw new UnsupportedOperationException(); + } + + /** + * @see java.util.Map#size() + */ + public final int size() { + return keys.length; + } + + /** + * Returns the hash code value for this map. The hash code of a map + * is defined to be the sum of the hashcode of each entry in the map's + * entrySet view. This ensures that t1.equals(t2) implies + * that t1.hashCode()==t2.hashCode() for any two + * FixedMap instances t1 and t2, as + * required by the general contract of {@link Object#hashCode()}. + * + *

Owing to the reference-equality-based semantics of the + * Map.Entry instances in the set returned by this map's + * entrySet method, it is possible that the contractual + * requirement of Object.hashCode mentioned in the previous + * paragraph will be violated if one of the two objects being compared is + * an FixedMap instance and the other is a normal map. + * + * @return the hash code value for this map. + * @see Object#hashCode() + * @see Object#equals(Object) + * @see #equals(Object) + */ + public int hashCode() { + int result = 0; + for(int i = 0 ; i < keys.length; i++) + result += System.identityHashCode(keys[i]) ^ System.identityHashCode(values[i]); + return result; + } + + /** + * Compares the specified object with this map for equality. Returns + * true if the given object is also a map and the two maps + * represent identical object-reference mappings. More formally, this + * map is equal to another map m if and only if + * map this.entrySet().equals(m.entrySet()). + * + *

Owing to the reference-equality-based semantics of this map it is + * possible that the symmetry and transitivity requirements of the + * Object.equals contract may be violated if this map is compared + * to a normal map. However, the Object.equals contract is + * guaranteed to hold among FixedMap instances. + * + * @param o object to be compared for equality with this map. + * @return true if the specified object is equal to this map. + * @see Object#equals(Object) + */ + public boolean equals(Object o) { + if (o == this) { + return true; + } else if (o instanceof FixedMap) { + FixedMap m = (FixedMap) o; + if (m.size() != size()) + return false; + for(int i = 0; i < keys.length; i++) { + if (keys[i] != m.keys[i] || values[i] != m.values[i]) + return false; + } + return true; + } else if (o instanceof Map) { + Map m = (Map)o; + return entrySet().equals(m.entrySet()); + } else { + return false; // o is not a Map + } + } + + private class Entry implements Map.Entry { + int index; + Entry(int index) { + this.index = index; + } + @SuppressWarnings("unchecked") + public final K getKey() { return (K)keys[index]; } + + @SuppressWarnings("unchecked") + public final V getValue() { return (V)values[index]; } + + @SuppressWarnings("unchecked") + public V setValue(V value) { throw new UnsupportedOperationException(); } + + public int hashCode() { + return System.identityHashCode(keys[index]) ^ System.identityHashCode(values[index]); + } + @SuppressWarnings("unchecked") + public boolean equals(Object o) { + if (o instanceof Map.Entry) { + final Map.Entry e = (Map.Entry) o; + return keys[index] == e.getKey() && values[index] == e.getValue(); + } else return false; + } + public String toString() { + return keys[index] + "=" + values[index]; + } + } + + private final class EntryIterator extends Entry implements Iterator> { + int next = 0; + EntryIterator() { super(-1); } + @SuppressWarnings("unchecked") + public V setValue(V value) { + final V oldValue = (V) values[index]; + values[index] = value; + return oldValue; + } + public boolean hasNext() { return next < keys.length; } + + public Map.Entry next() { + if (!hasNext()) throw new NoSuchElementException(); + index = next++; + return this; + } + public int hashCode() { return index < 0 ? System.identityHashCode(this) : super.hashCode(); } + public boolean equals(Object o) { return index < 0 ? this==o : super.equals(o); } + public void remove() { throw new UnsupportedOperationException(); } + public String toString() { return index < 0 ? "[]" : super.toString(); } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/IdentityHashSet.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/IdentityHashSet.java new file mode 100644 index 00000000..5c91743a --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/IdentityHashSet.java @@ -0,0 +1,593 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.collections; + +import java.util.AbstractSet; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.NoSuchElementException; + + +/** + *

Implements the Set interface with a hash table, using + * reference-equality in place of object-equality when comparing elements. + * In other words, in an IdentityHashSet, two elements + * e1 and e2 are considered equal if and only if + * (e1==e2). (In normal Set implementations (like + * Set) two elements e1 and e2 are considered equal + * if and only if (e1==null ? e2==null : e1.equals(e2)).) + * + *

This class is not a general-purpose Set + * implementation! While this class implements the Set interface, it + * intentionally violates Set's general contract, which mandates the + * use of the equals method when comparing objects. This class is + * designed for use only in the rare cases wherein reference-equality + * semantics are required. + * + *

This class provides all of the optional set operations, and permits + * null elements. This class makes no + * guarantees as to the order of the set; in particular, it does not guarantee + * that the order will remain constant over time. + * + *

This class provides constant-time performance for the basic + * operations (get and put), assuming the system + * identity hash function ({@link System#identityHashCode(Object)}) + * disperses elements properly among the buckets. + * + *

This class has one tuning parameter (which affects performance but not + * semantics): expected maximum size. This parameter is the maximum + * number of elements that the set is expected to hold. Internally, + * this parameter is used to determine the number of buckets initially + * comprising the hash table. The precise relationship between the expected + * maximum size and the number of buckets is unspecified. + * + *

If the size of the set sufficiently + * exceeds the expected maximum size, the number of buckets is increased + * Increasing the number of buckets ("rehashing") may be fairly expensive, so + * it pays to create identity hash sets with a sufficiently large expected + * maximum size. On the other hand, iteration requires + * time proportional to the number of buckets in the hash table, so it + * pays not to set the expected maximum size too high if you are especially + * concerned with iteration performance or memory usage. + * + *

Note that this implementation is not synchronized. The iterators + * returned by all of this class + * are not fail-fast: in the face of concurrent + * modification, the iterator risks + * arbitrary, non-deterministic behavior at an undetermined time in the + * future. + * + *

Implementation note: This is a simple linear-probe hash table, + * as described for example in texts by Sedgewick and Knuth. For many JRE + * implementations and operation mixes, this class will yield better performance than + * {@link HashSet} (which uses chaining rather than linear-probing). + * + * @specfield elems: set T + * @author Emina Torlak + */ +public final class IdentityHashSet extends AbstractSet { + /* implementation adapted from java.util.IdentityHashMap */ + /** + * The minimum capacity, used if a lower value is implicitly specified + * by either of the constructors with arguments. The value 4 corresponds + * to an expected maximum size of 2, given a load factor of 2/3. + * MUST be a power of two. + */ + private static final int MINIMUM_CAPACITY = 4; + + /** + * The maximum capacity, used if a higher value is implicitly specified + * by either of the constructors with arguments. + * MUST be a power of two <= 1<<29. + */ + private static final int MAXIMUM_CAPACITY = 1 << 29; + + /** + * Value representing null elements inside tables. + */ + private static final Object NULL = new Object(); + + /** + * Use NULL for key if it is null. + */ + private static Object maskNull(Object o) { + return (o == null ? NULL : o); + } + + /** + * Return internal representation of null key back to caller as null + */ + private static Object unmaskNull(Object o) { + return (o == NULL ? null : o); + } + + /** + * The table, resized as necessary. Length MUST always be a power of two. + */ + private Object[] table; + + /** + * The number of key-value mappings contained in this identity hash map. + */ + private int size; + + /** + * The next size value at which to resize (capacity * load factor). + */ + private int threshold; + + /** + * Constructs a new, empty identity hash map with a default expected + * maximum size of 16. + * @ensures no this.elems' + */ + public IdentityHashSet() { + this(16); + } + + /** + * Constructs a new, empty set with the specified expected maximum size. + * Putting more than the expected number of elements into + * the set may cause the internal data structure to grow, which may be + * somewhat time-consuming. + * @ensures no this.elems' + * @throws IllegalArgumentException - expectedMaxSize < 0 + */ + public IdentityHashSet(int expectedMaxSize) { + if (expectedMaxSize < 0) + throw new IllegalArgumentException("expectedMaxSize < 0: " + expectedMaxSize); + + final int initCapacity = capacity(expectedMaxSize); + threshold = (initCapacity * 2)/3; + table = new Object[initCapacity]; + size = 0; + } + + /** + * Constructs a new identity hash set containing the elements + * in the specified collection. + * @ensures this.elems' = c.elems + * @throws NullPointerException - c = null + */ + public IdentityHashSet(Collection c) { + // Allow for a bit of growth + this((int) ((1 + c.size()) * 1.1)); + addAll(c); + } + + /** + * Returns the appropriate capacity for the specified expected maximum + * size. Returns the smallest power of two between MINIMUM_CAPACITY + * and MAXIMUM_CAPACITY, inclusive, that is greater than + * (3 * expectedMaxSize)/2, if such a number exists. Otherwise + * returns MAXIMUM_CAPACITY. If (3 * expectedMaxSize)/2 is negative, it + * is assumed that overflow has occurred, and MAXIMUM_CAPACITY is returned. + */ + private static int capacity(int expectedMaxSize) { + // Compute min capacity for expectedMaxSize given a load factor of 2/3 + final int minCapacity = (3 * expectedMaxSize)/2; + + // Compute the appropriate capacity + int result; + if (minCapacity > MAXIMUM_CAPACITY || minCapacity < 0) { + result = MAXIMUM_CAPACITY; + } else { + result = StrictMath.max(MINIMUM_CAPACITY, Integer.highestOneBit(minCapacity)); + if (result < minCapacity) result <<= 1; + } + return result; + } + + /** + * @inheritDoc + */ + @Override + public Iterator iterator() { + return new IdentityIterator(); + } + + /** + * @inheritDoc + */ + @Override + public int size() { + return size; + } + + /** + * @inheritDoc + */ + @Override + public boolean isEmpty() { + return size==0; + } + + /** + * Return index for Object x in a table of size length. + */ + private static int hash(Object x, int length) { + return System.identityHashCode(x) & (length - 1); + } + + /** + * Circularly traverse table of size length. + **/ + private static int nextKeyIndex(int i, int length) { + return (i + 3) & (length - 1); + } + + /** + * Tests whether the specified object reference is an element in this identity + * hash map. + * @return o in this.elems + */ + @Override + public boolean contains(Object o) { + o = maskNull(o); + + for (int i = hash(o, table.length); ; i = nextKeyIndex(i, table.length)) { + Object item = table[i]; + if (item == o) + return true; + if (item == null) + return false; + } + } + + /** + * @inheritDoc + */ + @Override + public boolean add(T element) { + final Object o = maskNull(element); + + int i = hash(o, table.length); + + for(Object item = table[i]; item != null; item = table[i]) { + if (item == o) return false; + i = nextKeyIndex(i, table.length); + } + + table[i] = o; + + if (++size >= threshold) + resize(table.length<<1); // newCapacity == 2 * current capacity. + + return true; + } + + /** + * Resize the table to hold given capacity. The new capacity must be a + * power of two. + */ + private void resize(int newCapacity) { + final int oldLength = table.length; + + if (oldLength == MAXIMUM_CAPACITY) {// can't expand any further + if (threshold == MAXIMUM_CAPACITY - 1) + throw new IllegalStateException("Capacity exhausted."); + threshold = MAXIMUM_CAPACITY - 1; + return; + } + + if (oldLength >= newCapacity) + return; + + final Object[] newTable = new Object[newCapacity]; + + for (int j = 0; j < oldLength; j++) { + Object o = table[j]; + if (o != null) { + table[j] = null; + int i = hash(o, newCapacity); + while (newTable[i] != null) + i = nextKeyIndex(i, newCapacity); + newTable[i] = o; + } + } + + table = newTable; + threshold = (newCapacity * 2) / 3; + } + + /** + * @inheritDoc + */ + @Override + public boolean remove(Object o) { + o = maskNull(o); + + for (int i = hash(o, table.length); ; i = nextKeyIndex(i, table.length)) { + Object item = table[i]; + if (item == o) { + size--; + table[i] = null; + closeDeletion(i); + return true; + } + if (item == null) + return false; + } + + } + + /** + * Rehash all possibly-colliding entries following a + * deletion. This preserves the linear-probe + * collision properties required by get, put, etc. + * + * @param d the index of a newly empty deleted slot + */ + private void closeDeletion(int d) { + // Adapted from Knuth Section 6.4 Algorithm R + + // Look for items to swap into newly vacated slot + // starting at index immediately following deletion, + // and continuing until a null slot is seen, indicating + // the end of a run of possibly-colliding keys. + Object item; + for (int i = nextKeyIndex(d, table.length); (item = table[i]) != null; + i = nextKeyIndex(i, table.length) ) { + // The following test triggers if the item at slot i (which + // hashes to be at slot r) should take the spot vacated by d. + // If so, we swap it in, and then continue with d now at the + // newly vacated i. This process will terminate when we hit + // the null slot at the end of this run. + // The test is messy because we are using a circular table. + int r = hash(item, table.length); + if ((i < r && (r <= d || d <= i)) || (r <= d && d <= i)) { + table[d] = item; + table[i] = null; + d = i; + } + } + } + + /** + * @inheritDoc + */ + @Override + public boolean addAll(Collection c) { + int n = c.size(); + if (n == 0) + return false; + if (n > threshold) // conservatively pre-expand + resize(capacity(n)); + + return super.addAll(c); + } + + /** + * @inheritDoc + */ + @Override + public boolean removeAll(Collection c) { + /* Must revert from AbstractSet's impl to AbstractCollection's, as + * the former contains an optimization that results in incorrect + * behavior when c is a smaller "normal" (non-identity-based) Set. + */ + boolean modified = false; + Iterator e = iterator(); + while (e.hasNext()) { + if (c.contains(e.next())) { + e.remove(); + modified = true; + } + } + return modified; + } + + /** + * @inheritDoc + */ + @Override + public void clear() { + for (int i = 0; i < table.length; i++) + table[i] = null; + size = 0; + } + + /** + * Compares the specified object with this set for equality. Returns + * true if the given object is also a set and the two sets + * contain identical object-references. + * + *

Owing to the reference-equality-based semantics of this set it is + * possible that the symmetry and transitivity requirements of the + * Object.equals contract may be violated if this set is compared + * to a normal set. However, the Object.equals contract is + * guaranteed to hold among IdentityHashSet instances. + * + * @return true if the specified object is equal to this set. + * @see Object#equals(Object) + */ + public boolean equals(Object o) { + if (o == this) { + return true; + } else if (o instanceof IdentityHashSet) { + final IdentityHashSet s = (IdentityHashSet) o; + if (s.size() != size) return false; + final Object[] tab = s.table; + for (int i = 0; i < tab.length; i++) { + Object k = tab[i]; + if (k != null && !contains(k)) + return false; + } + return true; + } else { + return super.equals(o); + } + } + + /** + * Returns the hash code value for this set. The hash code of a set + * is defined to be the sum of the hashcode of each entry in the set. + * This ensures that t1.equals(t2) implies + * that t1.hashCode()==t2.hashCode() for any two + * IdentityHashSet instances t1 and t2, as + * required by the general contract of {@link Object#hashCode()}. + * + *

Owing to the reference-equality-based semantics of the + * elements in this set, it is possible that the contractual + * requirement of Object.hashCode mentioned in the previous + * paragraph will be violated if one of the two objects being compared is + * an IdentityHashSet instance and the other is a normal set. + * + * @return the hash code value for this set. + * @see Object#hashCode() + * @see Object#equals(Object) + * @see #equals(Object) + */ + public int hashCode() { + int result = 0; + for (Object o : table) { + if (o != null) { + result += System.identityHashCode(unmaskNull(o)); + } + } + return result; + } + + + /** + * An iterator over the elements of an IdentityHashSet. + */ + private final class IdentityIterator implements Iterator { + int index = (size != 0 ? 0 : table.length); // current slot. + int lastReturnedIndex = -1; // to allow remove() + Object[] traversalTable = table; // reference to main table or copy + + public boolean hasNext() { + for (int i = index; i < traversalTable.length; i++) { + if (traversalTable[i] != null) { + index = i; + return true; + } + } + index = traversalTable.length; + return false; + } + + @SuppressWarnings("unchecked") + public T next() { + if (!hasNext()) + throw new NoSuchElementException(); + + lastReturnedIndex = index++; + return (T) unmaskNull(traversalTable[lastReturnedIndex]); + } + + public void remove() { + if (lastReturnedIndex == -1) + throw new IllegalStateException(); + + final int deletedSlot = lastReturnedIndex; + lastReturnedIndex = -1; + + // If traversing a copy, remove in real table. + // We can skip gap-closure on copy. + if (traversalTable != IdentityHashSet.this.table) { + IdentityHashSet.this.remove(traversalTable[deletedSlot]); + traversalTable[deletedSlot] = null; + } else { // we are working on the real table... + // back up index to revisit new contents after deletion + size--; + index = deletedSlot; + + // Removal code proceeds as in closeDeletion except that + // it must catch the rare case where an element already + // seen is swapped into a vacant slot that will be later + // traversed by this iterator. We cannot allow future + // next() calls to return it again. The likelihood of + // this occurring under 2/3 load factor is very slim, but + // when it does happen, we must make a copy of the rest of + // the table to use for the rest of the traversal. Since + // this can only happen when we are near the end of the table, + // even in these rare cases, this is not very expensive in + // time or space. + final Object[] tab = traversalTable; + final int length = tab.length; + + int d = deletedSlot; + tab[d] = null; // vacate the slot + + Object item; + for (int i = nextKeyIndex(d, length); (item = tab[i]) != null; i = nextKeyIndex(i, length)) { + int r = hash(item, length); + // See closeDeletion for explanation of this conditional + if ((i < r && (r <= d || d <= i)) || + (r <= d && d <= i)) { + + // If we are about to swap an already-seen element + // into a slot that may later be returned by next(), + // then clone the rest of table for use in future + // next() calls. It is OK that our copy will have + // a gap in the "wrong" place, since it will never + // be used for searching anyway. + if (i < deletedSlot && d >= deletedSlot && traversalTable == IdentityHashSet.this.table) { + int remaining = length - deletedSlot; + Object[] newTable = new Object[remaining]; + System.arraycopy(tab, deletedSlot, newTable, 0, remaining); + traversalTable = newTable; + index = 0; + } + tab[d] = item; + tab[i] = null; + d = i; + } + } + } + } + + } + +// public static void main(String[] args) { +// IdentityHashSet s = new IdentityHashSet(21); +// Integer[] elts = new Integer[21]; +// for(int i = 0; i < elts.length; i++) { +// elts[i] = new Integer(i); +// s.add(elts[i]); +// } +// System.out.println(s); +// System.out.println(s.size()); +// System.out.println(s.table.length); +// System.out.println(s.threshold); +// System.out.println(s.contains(2)); +// System.out.println(s.contains(elts[2])); +// System.out.println(s.remove(new Integer(0))); +// System.out.println(s.remove(elts[0])); +// System.out.println(s); +// +// for(Iterator iter = s.iterator(); iter.hasNext(); ) { +// System.out.println(iter.next()); +// iter.remove(); +// } +// System.out.println(s); +// +// } + + +} + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/Indexer.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/Indexer.java new file mode 100644 index 00000000..9bb94c5a --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/Indexer.java @@ -0,0 +1,56 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.collections; + + +/** + * An index generator for a set of keys. An indexer maps each key in its keyset + * to a unique integer in the range [0..#keys) + * @specfield keys: set K + * @specfield indices: keys lone->one [0..#keys) + * @author Emina Torlak + */ +public interface Indexer { + + + /** + * Returns the index of the given key, if it is in this.keys. + * Otherwise returns a negative number. + * @return key in this.keys => this.indices[key], {i: int | i < 0 } + */ + public abstract int indexOf(K key); + + /** + * Returns the key at the given index. + * @return this.indices.index + * @throws IndexOutOfBoundsException - index !in this.indices[this.keys] + */ + public abstract K keyAt(int index); + + /** + * Returns the number of keys in this.indexer. + * @return #this.keys + */ + public abstract int size(); + + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/LinkedStack.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/LinkedStack.java new file mode 100644 index 00000000..99ffb44e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/LinkedStack.java @@ -0,0 +1,167 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.collections; + +import java.util.EmptyStackException; +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * A Stack implementation based on a singly linked list. + * @author Emina Torlak + */ +public final class LinkedStack extends Stack { + private StackEntry head; + private int size; + + /** + * Constructs an empty stack. + * @ensures no this.elems' + */ + public LinkedStack() { + head = null; + size = 0; + } + + /** + * @see kodkod.util.collections.Stack#size() + */ + public int size() { return size; } + + /** + * Pushes an item onto the top of this stack and returns it. + * @ensures this.size' = this.size + 1 && this.elems'[0] = item && + * all i: [0..this.size) | this.elems'[i+1] = this.elems[i] + * @return item + */ + public T push(T item) { + head = new StackEntry(item, head); + size++; + return item; + } + + /** + * Removes the object at the top of this stack and returns that object as the value of this function. + * @ensures this.size' = this.size - 1 && + * all i: [1..this.size) | this.elems'[i-1] = this.elems[i] + * @return this.elems[0] + * @throws EmptyStackException - no this.elems + */ + public T pop() { + if (head==null) throw new EmptyStackException(); + final T pop = head.data; + head = head.next; + size--; + return pop; + } + + /** + * Looks at the object at the top of this stack without removing it from the stack. + * @return this.elems[0] + * @throws EmptyStackException - no this.elems + */ + public T peek() { + if (head==null) throw new EmptyStackException(); + return head.data; + } + + /** + * Returns the 1-based position where an object is on this stack. + * If the object o occurs as an item in this stack, this method + * returns the distance from the top of the stack of the occurrence + * nearest the top of the stack; the topmost item on the stack is + * considered to be at distance 1. The equals method is used to + * compare o to the items in this stack. + * @return o in this.elems[int] => min(this.elems.o) + 1, -1 + */ + public int search(Object o) { + StackEntry e = head; + int position = 1; + while(e != null) { + if (equal(o, e.data)) + return position; + e = e.next; + position++; + } + return -1; + } + + /** + * Returns true if the stack is empty; otherwise returns false. + * @return no this.elems + */ + public boolean empty() { return head == null; } + + /** + * Iterates over the items in this LinkedStack, starting + * at the top of the stack and working its way down. + * @return iterator over the elements in this stack. + */ + public Iterator iterator() { + return new Iterator() { + private StackEntry cursor = head, prev = null, pprev = null; + public boolean hasNext() { + return cursor != null; + } + + public T next() { + if (cursor==null) throw new NoSuchElementException(); + pprev = prev; + prev = cursor; + cursor = cursor.next; + return prev.data; + } + + public void remove() { + if (prev==pprev) { + throw new UnsupportedOperationException(); + } else if (prev==head) { + head = cursor; + } else { + pprev.next = cursor; + prev.next = null; + } + prev = pprev; + size--; + } + + }; + } + + /** + * Represents a stack entry. + * @specfield data: T + * @specfield next: StackEntry + */ + @SuppressWarnings("hiding") + private static final class StackEntry { + T data; + StackEntry next; + + StackEntry(T data, StackEntry next) { + this.data = data; + this.next = next; + } + } + + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/SingletonIdentitySet.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/SingletonIdentitySet.java new file mode 100644 index 00000000..58d1fe8a --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/SingletonIdentitySet.java @@ -0,0 +1,132 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.collections; + +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Set; + +/** + *

This is an immutable singleton set implementation that tests for + * membership using reference-equality in place of object-equality when comparing elements.

+ * @specfield element: V + * @author Emina Torlak + */ +public final class SingletonIdentitySet extends AbstractSet { + private final V element; + + /** + * Constructs a SingletonIdentitySet that will hold the given element. + * @ensures this.element' = element + */ + public SingletonIdentitySet(V element) { + this.element = element; + } + + /** + * Constructs a SingletonIdentitySet that will hold the first element + * returned by the given collection's iterator. + * @ensures this.element' = collection.iterator().next() + * @throws NoSuchElementException - collection.isEmpty() + */ + public SingletonIdentitySet(Collection collection) { + this.element = collection.iterator().next(); + } + + + /** + * Returns true iff this.element and obj are the same object. + * @return this.element == obj + */ + public boolean contains(Object obj) { + return element == obj; + } + + /** + * @see java.util.Set#containsAll(java.util.Collection) + */ + public boolean containsAll(Collection collection) { + if (collection.isEmpty()) return true; + else if (collection.size()==1) return collection.iterator().next()==this.element; + else return false; + } + + /** + * Returns false. + * @return false. + */ + public boolean isEmpty() { + return false; + } + + /** + * @see java.util.Set#iterator() + */ + @SuppressWarnings("unchecked") + public Iterator iterator() { + return Containers.iterate(this.element); + } + + /** + * Returns 1. + * @return 1 + */ + public int size() { + return 1; + } + + /** + * Compares the specified object with this set for equality. Returns + * true if the given object is also a set and the two sets + * contain identical object-references. + * + *

Owing to the reference-equality-based semantics of this set it is + * possible that the symmetry and transitivity requirements of the + * Object.equals contract may be violated if this set is compared + * to a normal set. However, the Object.equals contract is + * guaranteed to hold among SingletonHashSet instances. + * + * @return true if the specified object is equal to this set. + * @see Object#equals(Object) + */ + public boolean equals(Object o) { + if (o == this) { + return true; + } else if (o instanceof Set) { + final Set s = (Set) o; + return s.size()==1 && s.iterator().next()==this.element; + } else { + return false; + } + } + + /** + * Returns 0 if this.element is null; otherwise returns this.element.hashCode(). + * @return this.element = null ? 0 : this.element.hashCode() + * @see java.util.AbstractSet#hashCode() + */ + public int hashCode() { + return this.element==null ? 0 : element.hashCode(); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/Stack.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/Stack.java new file mode 100644 index 00000000..65ece38c --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/collections/Stack.java @@ -0,0 +1,157 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.collections; + +import java.util.EmptyStackException; +import java.util.Iterator; + + +/** + * Represents a last-in-first-out (LIFO) stack of objects. + * The usual push and pop operations are provided, as well as a method to peek at the top item on the stack, + * a method to test for whether the stack is empty, and an iterator over the elements in the stack + * (that does not support removal). When a stack is first created, it contains no items. + * + * @specfield size: int + * @specfield elems: [0..size)->one T + * @author Emina Torlak + */ +public abstract class Stack implements Iterable { + + /** + * Constructs a new stack. + */ + protected Stack() {} + + /** + * Returns the size of this stack. + * @return this.size + */ + public abstract int size(); + + /** + * Pushes an item onto the top of this stack and returns it. + * @ensures this.size' = this.size + 1 && this.elems'[0] = item && + * all i: [0..this.size) | this.elems'[i+1] = this.elems[i] + * @return item + */ + public abstract T push(T item); + + /** + * Removes the object at the top of this stack and returns that object as the value of this function. + * @ensures this.size' = this.size - 1 && + * all i: [1..this.size) | this.elems'[i-1] = this.elems[i] + * @return this.elems[0] + * @throws EmptyStackException - no this.elems + */ + public abstract T pop(); + + /** + * Looks at the object at the top of this stack without removing it from the stack. + * @return this.elems[0] + * @throws EmptyStackException - no this.elems + */ + public abstract T peek(); + + /** + * Returns the 1-based position where an object is on this stack. + * If the object o occurs as an item in this stack, this method + * returns the distance from the top of the stack of the occurrence + * nearest the top of the stack; the topmost item on the stack is + * considered to be at distance 1. The equals method is used to + * compare o to the items in this stack. + * @return o in this.elems[int] => min(this.elems.o) + 1, -1 + */ + public abstract int search(Object o); + + /** + * Returns true if the stack is empty; otherwise returns false. + * @return no this.elems + */ + public abstract boolean empty(); + + /** + * Iterates over the items in this Stack, starting + * at the top of the stack and working its way down. + * @return iterator over the elements in this stack. + */ + public abstract Iterator iterator(); + + /** + * Returns true if both o1 and o2 are null, or + * if they are non-null and 'equals' to each other. + * @return o1=null && o2=null || o1.equals(o2) + */ + static boolean equal(Object o1, Object o2) { + return (o1==null ? o2==null : o1.equals(o2)); + } + + /** + * Returns true if o is a stack containing the same elements + * as this stack, in the same order. + * @return o in Stack && this.elems = o.elems + */ + @SuppressWarnings("unchecked") + public boolean equals(Object o) { + if (this==o) return true; + else if (o instanceof Stack) { + final Stack s = (Stack) o; + if (size() != s.size()) return false; + final Iterator iter0 = iterator(), iter1 = s.iterator(); + while(iter0.hasNext()) { + if (!equal(iter0.next(), iter1.next())) + return false; + } + return true; + } + return false; + } + + /** + * Returns the hashcode for this stack. + * @return the hashcode for this stack. + */ + public int hashCode() { + int code = 0; + for(T item : this) { + if (item!=null) code += item.hashCode(); + } + return code; + } + + /** + * Returns a string represention of this stack. + */ + public String toString() { + final StringBuilder buffer = new StringBuilder("[ "); + final Iterator elems = iterator(); + if (elems.hasNext()) buffer.append(elems.next()); + while(elems.hasNext()) { + buffer.append(", "); + buffer.append(elems.next()); + } + buffer.append(" ]"); + return buffer.toString(); + } + + +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/AbstractIntCollection.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/AbstractIntCollection.java new file mode 100644 index 00000000..163ead51 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/AbstractIntCollection.java @@ -0,0 +1,182 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + +/** + * A skeletal implementation of the IntCollection interface. + * @author Emina Torlak + */ +public abstract class AbstractIntCollection implements IntCollection { + + /** + * Constructs an empty int collection. + * @ensures this.isEmpty() + */ + protected AbstractIntCollection() {} + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntSet#isEmpty() + */ + public boolean isEmpty() { return size()==0; } + + /** + * Iterates through this.ints and returns true if it + * finds i, otherwise returns false. + * @return true if i is in this collection, otherwise returns false. + */ + public boolean contains(int i) { + for(IntIterator iter = iterator(); iter.hasNext(); ) { + if (i==iter.next()) return true; + } + return false; + } + + /** + * Throws an UnsupportedOperationException. + * @throws UnsupportedOperationException + */ + public boolean add(int i) { + throw new UnsupportedOperationException(); + } + + /** + * Iterates through the elements of this, removes + * i if it finds it and returns true. Otherwise + * returns false. Throws an UnsupportedOperationException + * if this.iterator() does not support removal. + * @ensures iterates through the elements of this and removes i if it finds it + * @return true if this collection has changed as a result of the call + * @throws UnsupportedOperationException - this.iterator() does not support removal + */ + public boolean remove(int i) { + for(IntIterator iter = iterator(); iter.hasNext(); ) { + if (i==iter.next()) { + iter.remove(); + return true; + } + } + return false; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntCollection#containsAll(kodkod.util.ints.IntCollection) + */ + public boolean containsAll(IntCollection c) { + if (size()>=c.size()) { + for(IntIterator itr = c.iterator(); itr.hasNext(); ) { + if (!contains(itr.next())) + return false; + } + return true; + } + return false; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntCollection#addAll(kodkod.util.ints.IntCollection) + */ + public boolean addAll(IntCollection c) { + boolean modified = false; + for(IntIterator itr = c.iterator(); itr.hasNext(); ) { + if (add(itr.next())) + modified = true; + } + return modified; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntCollection#retainAll(kodkod.util.ints.IntCollection) + */ + public boolean retainAll(IntCollection c) { + boolean modified = false; + for(IntIterator itr = iterator(); itr.hasNext(); ) { + if (!c.contains(itr.next())) { + modified = true; + itr.remove(); + } + } + return modified; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntCollection#removeAll(kodkod.util.ints.IntCollection) + */ + public boolean removeAll(IntCollection c) { + boolean modified = false; + for(IntIterator itr = iterator(); itr.hasNext();) { + if (c.contains(itr.next())) { + modified = true; + itr.remove(); + } + } + return modified; + } + + /** + * This implementation iterates over this set, removing each + * element using the Iterator.remove operation. Most + * implementations will probably choose to override this method for + * efficiency.

+ * + * Note that this implementation will throw an + * UnsupportedOperationException if the iterator returned by this + * collection's iterator method does not implement the + * remove method and this collection is non-empty. + * + * @throws UnsupportedOperationException if the clear method is + * not supported by this collection. + */ + public void clear() { + for(IntIterator itr = iterator(); itr.hasNext();) { + itr.next(); + itr.remove(); + } + } + + /** + * Returns the result of calling {@linkplain #toArray(int[])} with + * a freshly constructed array of length this.size(). + * @return this.toArray(new int[size()]) + * @see kodkod.util.ints.IntCollection#toArray() + */ + public int[] toArray() { return toArray(new int[size()]); } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntCollection#toArray(int[]) + */ + public int[] toArray(int[] array) { + if (array.length < size()) { + array = new int[size()]; + } + int i = 0; + for(IntIterator itr = iterator(); itr.hasNext(); ) { + array[i++] = itr.next(); + } + return array; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/AbstractIntSet.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/AbstractIntSet.java new file mode 100644 index 00000000..139a2ef4 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/AbstractIntSet.java @@ -0,0 +1,133 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + +import java.util.NoSuchElementException; + +/** + * A skeletal implementation of the IntSet interface. + * @author Emina Torlak + */ +public abstract class AbstractIntSet extends AbstractIntCollection implements IntSet { + + /** + * Constructs an empty int set. + * @ensures no this.ints' + */ + protected AbstractIntSet() {} + + /** + * Throws a NoSuchElementException if this is an empty set. + * @throws NoSuchElementException - this.isEmpty() + */ + final void checkNonEmpty() { + if (isEmpty()) throw new NoSuchElementException("no this.ints"); + } + + /** + * Returns an ascending iterator over all elements in this set. + * This method calls this.iterator(Integer.MIN_VALUE, Integer.MAX_VALUE). + * @return an ascending iterator over all elements in this set. + */ + public IntIterator iterator() { + return iterator(Integer.MIN_VALUE, Integer.MAX_VALUE); + } + + /** + * Returns the first element returned by this.iterator(). + * If this set is empty, throws a NoSuchElementException(). + * @return min(this.ints) + * @throws NoSuchElementException - no this.ints + */ + public int min() { + return iterator().next(); + } + + /** + * Returns the first element returned by this.iterator(Integer.MAX_VALUE, Integer.MIN_VALUE). + * If this set is empty, throws a NoSuchElementException(). + * @return max(this.ints) + * @throws NoSuchElementException - no this.ints + */ + public int max() { + return iterator(Integer.MAX_VALUE, Integer.MIN_VALUE).next(); + } + + /** + * Returns the result of calling super.clone(). + * @return the result of calling super.clone() + * @see java.lang.Object#clone() + */ + public IntSet clone() throws CloneNotSupportedException { + return (IntSet) super.clone(); + } + + /** + * Compares the specified object with this set for equality. + * Returns true if the specified object is also an IntSet, + * the two sets have the same size, and every member of the + * specified set is contained in this set (or equivalently, + * every member of this set is contained in the specified set). + * This definition ensures that the equals method works properly + * across different implementations of the IntSet interface. + * @return o instanceof IntSet and o.size() = this.size() and this.containsAll(o) + */ + public boolean equals(Object o) { + if (o==this) return true; + else if (o instanceof IntSet) { + final IntSet s = (IntSet) o; + return size()==s.size() && containsAll(s); + } else return false; + } + + /** + * Returns the hash code value for this set. The hash code of a set is + * defined to be the {@link Ints#superFastHash(int[])} of the elements in the set, + * taken in the ascending order of values. + * This ensures that s1.equals(s2) implies that s1.hashCode()==s2.hashCode() + * for any two IntSets s1 and s2, as required by the general contract of the Object.hashCode method. + * @return Ints.superFastHash(this.toArray()) + */ + public int hashCode() { + int hash = size(); + for(IntIterator iter = iterator(); iter.hasNext();) { + hash = Ints.superFastHashIncremental(iter.next(), hash); + } + return Ints.superFastHashAvalanche(hash); + } + + /** + * Returns a string representation of this int set. + * @return a string representation of this int set. + */ + public String toString() { + final StringBuilder buf = new StringBuilder("{"); + final IntIterator itr = iterator(); + if (itr.hasNext()) buf.append(itr.next()); + while(itr.hasNext()) { + buf.append(", "); + buf.append(itr.next()); + } + buf.append("}"); + return buf.toString(); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/AbstractIntVector.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/AbstractIntVector.java new file mode 100644 index 00000000..7e47c310 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/AbstractIntVector.java @@ -0,0 +1,247 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + +import java.util.NoSuchElementException; + + +/** + * A skeletal implementation of the IntVector interface. + * + * + * @specfield length: int + * @specfield elements: [0..size) ->one int + * + * @author Emina Torlak + */ +public abstract class AbstractIntVector extends AbstractIntCollection implements IntVector { + + /** + * Constructs an empty int vector. + * @ensures no this.elements' + */ + protected AbstractIntVector() {} + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntVector#contains(int) + */ + public boolean contains(int element) { + for(int i = 0, max = size(); i < max; i++) { + if (get(i)==element) return true; + } + return false; + } + + /** + * Throws {@link UnsupportedOperationException}. + * @see kodkod.util.ints.IntVector#set(int,int) + */ + public int set(int index, int element) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntVector#indexOf(int) + */ + public int indexOf(int element) { + for(int i = 0, length=size(); i < length; i++) { + if (get(i)==element) return i; + } + return -1; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntVector#lastIndexOf(int) + */ + public int lastIndexOf(int element) { + for(int i = size()-1; i >= 0; i--) { + if (get(i)==element) return i; + } + return -1; + } + + /** + * Calls this.add(this.size(), element) + * @see kodkod.util.ints.IntVector#add(int) + * @see kodkod.util.ints.IntVector#add(int,int) + */ + public boolean add(int element) { + final int length = size(); + add(length,element); + return length != size(); + } + + /** + * Throws {@link UnsupportedOperationException} + * @see kodkod.util.ints.IntVector#add(int, int) + */ + public void add(int index, int element) { throw new UnsupportedOperationException(); } + + /** + * Returns the result of calling {@linkplain #addAll(int, IntCollection) this.addAll(size(), c)}. + * @return this.addAll(size(), c) + * @see kodkod.util.ints.AbstractIntCollection#addAll(kodkod.util.ints.IntCollection) + */ + public boolean addAll(IntCollection c) { + return addAll(size(), c); + } + + /** + * Throws an UnsupportedOperationException. + * @see kodkod.util.ints.IntVector#addAll(int, kodkod.util.ints.IntCollection) + */ + public boolean addAll(int index, IntCollection c) { throw new UnsupportedOperationException(); } + + /** + * Throws an UnsupportedOperationException. + * @see kodkod.util.ints.IntVector#removeAt(int) + */ + public int removeAt(int index) { + throw new UnsupportedOperationException(); + } + + /** + * Calls this.iterator(0, length()) + * @see kodkod.util.ints.IntVector#iterator() + * @see kodkod.util.ints.IntVector#iterator(int,int) + */ + public IntIterator iterator() { + return iterator(0, size()); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntVector#iterator(int, int) + */ + public IntIterator iterator(int fromIndex, int toIndex) { + return fromIndex<=toIndex ? new AscendingIntVectorIterator(fromIndex,toIndex) : + new DescendingIntVectorIterator(fromIndex,toIndex); + } + + /** + * Returns the hash code value for this vector. + * + * @return the hash code value for this vector. + * @see Object#hashCode() + * @see Object#equals(Object) + * @see #equals(Object) + */ + public int hashCode() { + final int length = size(); + int hash = length; + for(int i = 0; i < length; i++) { + hash = Ints.superFastHashIncremental(get(i), hash); + } + return Ints.superFastHashAvalanche(hash); + } + + /** + * Compares the specified object with this vector for equality. Returns + * true if and only if the specified object is also an int vector, both + * vectors have the same size, and all corresponding pairs of elements in + * the two vectors are equal. + * + * @return true if the specified object is equal to this vector. + */ + public boolean equals(Object o) { + if (o==this) return true; + if (o instanceof IntVector) { + final IntVector l = (IntVector) o; + final int length = size(); + if (l.size()==length) { + for (int i = 0; i < length; i++) { + if (get(i) != l.get(i)) return false; + } + return true; + } + } + return false; + } + + /** + * {@inheritDoc} + * @see java.lang.Object#toString() + */ + public String toString() { + final StringBuilder buf = new StringBuilder(); + buf.append("["); + IntIterator itr = iterator(); + if (itr.hasNext()) buf.append(itr.next()); + while(itr.hasNext()) { + buf.append(", "); + buf.append(itr.next()); + } + buf.append("]"); + return buf.toString(); + } + + + private abstract class IntVectorIterator implements IntIterator { + int next, end, last; + IntVectorIterator(int fromIndex, int toIndex) { + next = fromIndex; + end = toIndex; + last = -1; + } + public final void remove() { + if (last < 0) throw new IllegalStateException(); + AbstractIntVector.this.removeAt(last); + next = last; + last = -1; + } + } + + private final class AscendingIntVectorIterator extends IntVectorIterator { + /** + * Constructs a new AscendingIntArrayIterator. + * @requires fromIndex <= toIndex + */ + AscendingIntVectorIterator(int fromIndex, int toIndex) { + super(fromIndex, toIndex); + } + public boolean hasNext() { return last= toIndex + */ + DescendingIntVectorIterator(int fromIndex, int toIndex) { + super(fromIndex, toIndex); + } + public boolean hasNext() { return next > end; } + public int next() { + if (!hasNext()) throw new NoSuchElementException(); + last = next--; + return get(last); + } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/AbstractSparseSequence.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/AbstractSparseSequence.java new file mode 100644 index 00000000..d9c62248 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/AbstractSparseSequence.java @@ -0,0 +1,445 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * A skeletal implementation of the SparseSequence interface. + * The class provides an implementation for the isEmpty, + * putAll, contains, indices, equals, hashCode, + * and toString methods. All other methods must be + * implemented by the subclasses. + * + * @specfield entries: int -> lone V + * + * @author Emina Torlak + */ +public abstract class AbstractSparseSequence implements SparseSequence { + + /** + * Constructs a sparse sequence + * @ensures no this.entries' + */ + protected AbstractSparseSequence() {} + + /** + * Returns true if the size of this sequence is 0. + * @return this.size()==0 + */ + public boolean isEmpty() { + return size()==0; + } + + /** + * Returns an iterator over the entries in this sequence + * in the ascending order of indeces, starting at this.first(). + * This method calls this.iterator(Integer.MIN_VALUE, Integer.MAX_VALUE). + * @return an iterator over this.entries starting at the entry + * with the smallest index + */ + public Iterator> iterator() { + return iterator(Integer.MIN_VALUE, Integer.MAX_VALUE); + } + + /** + * Returns the first element in this sequence, if any. This + * method first checks that the sequence is not empty, and + * if not, returns this.iterator().next(); + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#first() + */ + public IndexedEntry first() { + return isEmpty() ? null : iterator().next(); + } + + /** + * Returns the last element in this sequence, if any. This + * method first checks that the sequence is not empty, and + * if not, returns this.iterator(Integer.MAX_VALUE, Integer.MIN_VALUE).next(); + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#last() + */ + public IndexedEntry last() { + return isEmpty() ? null : iterator(Integer.MAX_VALUE, Integer.MIN_VALUE).next(); + } + + /** + * Returns the entry whose index is the ceiling of the given index in this sequence. + * This method calls this.iterator(index, Integer.MAX_VALUE), and if the resulting iterator has + * a next element returns it. + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#ceil(int) + */ + public IndexedEntry ceil(int index) { + final Iterator> itr = iterator(index, Integer.MAX_VALUE); + return itr.hasNext() ? itr.next() : null; + } + + /** + * Returns the entry whose index is the floor of the given index in this sequence. + * This method calls this.iterator(index, Integer.MIN_VALUE), and if the resulting iterator has + * a next element returns it. + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#floor(int) + */ + public IndexedEntry floor(int index) { + final Iterator> itr = iterator(index, Integer.MIN_VALUE); + return itr.hasNext() ? itr.next() : null; + } + + /** + * Returns the set of all indices mapped by this sparse sequence. + * The returned set supports removal iff this is not an unmodifiable + * sparse sequence. + * @return {s: IntSet | s.ints = this.entries.V} + */ + public IntSet indices() { + return new AbstractIntSet() { + public IntIterator iterator(final int from, final int to) { + return new IntIterator() { + Iterator> iter = AbstractSparseSequence.this.iterator(from, to); + public boolean hasNext() { + return iter.hasNext(); + } + public int next() { + return iter.next().index(); + } + public void remove() { + iter.remove(); + } + }; + } + public int size() { + return AbstractSparseSequence.this.size(); + } + public boolean contains(int i) { + return containsIndex(i); + } + public int min() { + final IndexedEntry first = AbstractSparseSequence.this.first(); + if (first==null) + throw new NoSuchElementException(); + return first.index(); + } + public int max() { + final IndexedEntry last = AbstractSparseSequence.this.last(); + if (last==null) + throw new NoSuchElementException(); + return last.index(); + } + public boolean remove(int i) { + final boolean isMapped = containsIndex(i); + AbstractSparseSequence.this.remove(i); + return isMapped; + } + public int floor(int i) { + final IndexedEntry floor = AbstractSparseSequence.this.floor(i); + if (floor==null) + throw new NoSuchElementException(); + return floor.index(); + } + public int ceil(int i) { + final IndexedEntry ceil = AbstractSparseSequence.this.ceil(i); + if (ceil==null) + throw new NoSuchElementException(); + return ceil.index(); + } + public void clear() { + AbstractSparseSequence.this.clear(); + } + public IntSet clone() throws CloneNotSupportedException { + final IntSet s; + if (size()==0) + s = Ints.bestSet(Integer.MIN_VALUE, Integer.MAX_VALUE); + else + s = Ints.bestSet(min(), max()); + s.addAll(this); + return s; + } + }; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#values() + */ + public Collection values() { + return new AbstractCollection() { + + public int size() { + return AbstractSparseSequence.this.size(); + } + + public boolean isEmpty() { + return AbstractSparseSequence.this.isEmpty(); + } + + public boolean contains(Object arg0) { + return AbstractSparseSequence.this.contains(arg0); + } + + public Iterator iterator() { + return new Iterator() { + Iterator> iter = AbstractSparseSequence.this.iterator(); + public boolean hasNext() { + return iter.hasNext(); + } + public V next() { + return iter.next().value(); + } + public void remove() { + iter.remove(); + } + }; + } + + public void clear() { + AbstractSparseSequence.this.clear(); + } + }; + } + + /** + * Returns true if this sparse sequence has an entry for the + * given index; otherwise returns false. This method returns + * the value of this.iterator(index,index).hasNext(); + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#containsIndex(int) + */ + public boolean containsIndex(int index) { + return iterator(index,index).hasNext(); + } + + /** + * Iterates through all the entries in this sequence and returns + * true if one of the encountered entries has the given object as + * its value. + * @return {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#contains(java.lang.Object) + */ + public boolean contains(Object value) { + for(IndexedEntry v: this) { + if (equal(value, v.value())) + return true; + } + return false; + } + + /** + * Returns the result of calling super.clone(). + * @see java.lang.Object#clone() + */ + @SuppressWarnings("unchecked") + public SparseSequence clone() throws CloneNotSupportedException { + return (SparseSequence) super.clone(); + } + + /*---------- adapted from java.util.AbstractMap -----------*/ + + /** + * Removes the entry with the given index, if it exists, and + * returns the value previously stored at the index. If the + * sequence had no previous mapping for the index, null is returned. + * This method obtains an iterator from index to index and removes + * its sole element, if any. + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#remove(int) + */ + public V remove(int index) { + final Iterator> itr = iterator(index,index); + if (itr.hasNext()) { + final V ret = itr.next().value(); + itr.remove(); + return ret; + } + return null; + } + + /** + * Removes all entries from this sequences. This method + * obtains an iterator over the sequences and calls remove() + * after each call to next(). + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#clear() + */ + public void clear() { + final Iterator> itr = iterator(); + while(itr.hasNext()) { + itr.next(); + itr.remove(); + } + } + + + /** + * Throws an UnsupportedOperationException. + * @throws UnsupportedOperationException + */ + public V put(int index, V value) { + throw new UnsupportedOperationException(); + } + + /** + * Copies all of the entries from the specified sparse sequence to + * this sequence. This implementation calls put(e.index, e.value) on + * this sequence once for each entry e in the specified sequence. + * @ensures this.entries' = this.entries ++ s.entries + */ + public void putAll(SparseSequence s) { + Iterator> i = s.iterator(); + while (i.hasNext()) { + IndexedEntry e = i.next(); + put(e.index(), e.value()); + } + } + + /** + * Returns true if both o1 and o2 are null, or + * o1.equals(o2) + * @return o1 and o2 are equal + */ + static boolean equal(Object o1, Object o2) { + return o1==null ? o2==null : o1.equals(o2); + } + + /** + * Returns true if the indexed entries e0 and e1 are equal to each other. + * @requires e0 != null && e1 != null + * @return e0.index = e1.index && e0.value = e1.value + */ + static boolean equal(IndexedEntry e0, IndexedEntry e1) { + return e0.index()==e1.index() && equal(e0.value(), e1.value()); + } + + /** + * Compares the specified object with this sequence for equality. Returns + * true if the given object is also a sequence and the two sequences + * represent the same function from integers to E.

+ * + * This implementation first checks if the specified object is this sequence; + * if so it returns true. Then, it checks if the specified + * object is a sequence whose size is identical to the size of this set; if + * not, it returns false. If so, it iterates over this sequences's + * entries, and checks that the specified sequence + * contains each entry that this sequence contains. If the specified sequence + * fails to contain such an entry, false is returned. If the + * iteration completes, true is returned. + * @return o in SparseSequence && o.entries = this.entries + */ + @SuppressWarnings("unchecked") + public boolean equals(Object o) { + if (o == this) return true; + + if (!(o instanceof SparseSequence)) return false; + + SparseSequence s = (SparseSequence) o; + if (s.size() != size()) return false; + + try { + final Iterator> i1 = iterator(), i2 = s.iterator(); + while (i1.hasNext()) { + if (!equal(i1.next(), i2.next())) + return false; + } + } catch(ClassCastException unused) { + return false; + } catch(NullPointerException unused) { + return false; + } + + return true; + } + + /** + * Returns the hashcode for an indexed entry. + * @requires e != null + * @return e.index ^ e.value.hashCode() + */ + static int hashCode(IndexedEntry e) { + return e.index() ^ (e.value()==null ? 0 : e.value().hashCode()); + } + + /** + * Returns the hash code value for this sparse sequence. + * The hash code of a sparse sequence is defined to be the sum of the + * hashCodes of each entry of its entries. This ensures that t1.equals(t2) + * implies that t1.hashCode()==t2.hashCode() for any two sequences t1 and t2, + * as required by the general contract of Object.hashCode. + * This implementation iterates over this.entries, calling + * hashCode on each IndexedEntry in the sequence, and adding + * up the results. + * @return sum(this.entries.hashCode()) + */ + public int hashCode() { + int h = 0; + for (IndexedEntry e : this) + h += hashCode(e); + return h; + } + + /** + * Returns a string representation of this sequence. The string representation + * consists of a list of index-value mappings in the order returned by the + * sequences iterator, enclosed in brackets + * ("[]"). Adjacent entries are separated by the characters + * ", " (comma and space). Each index-value mapping is rendered as + * the index followed by an equals sign ("=") followed by the + * associated value. Elements are converted to strings as by + * String.valueOf(Object).

+ * + * This implementation creates an empty string buffer, appends a left + * bracket, and iterates over the map's entries, appending + * the string representation of each IndexedEntry in turn. After + * appending each entry except the last, the string ", " is + * appended. Finally a right bracket is appended. A string is obtained + * from the stringbuffer, and returned. + * + * @return a String representation of this map. + */ + public String toString() { + final StringBuilder buf = new StringBuilder(); + buf.append("["); + + final Iterator> i = iterator(); + boolean hasNext = i.hasNext(); + while (hasNext) { + IndexedEntry e = i.next(); + buf.append(e.index()); + buf.append("="); + if (e.value() == this) + buf.append("(this sequence)"); + else + buf.append(e.value()); + hasNext = i.hasNext(); + if (hasNext) buf.append(", "); + } + + buf.append("]"); + return buf.toString(); + } + + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/ArrayIntSet.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/ArrayIntSet.java new file mode 100644 index 00000000..219f4d56 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/ArrayIntSet.java @@ -0,0 +1,219 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + +import java.util.Arrays; +import java.util.NoSuchElementException; + +/** + * An immutable set of integers, stored in a sorted array. + * + * @specfield ints: set int + * @author Emina Torlak + */ +public final class ArrayIntSet extends AbstractIntSet { + private final int[] ints; + private final int hashcode; + /** + * Constructs a set view for the given array. The array must contain no duplicates, + * its elements must be sorted + * in the ascending order, and its contents + * must not be changed while it is in use by this set + * @requires all i, j: [0..ints.length) | i < j => array[i] <= array[j] + * @ensures this.ints' = ints + */ + public ArrayIntSet(int[] ints) { + this.ints = ints; + this.hashcode = Ints.superFastHash(ints); + } + + /** + * Constructs an ArrayIntSet that is equal to the + * given set. + * @ensures this.ints' = s.ints + */ + public ArrayIntSet(IntSet s) { + this(s.toArray()); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntSet#iterator(int, int) + */ + public IntIterator iterator(final int from, final int to) { + return from <= to ? new AscendingIntArrayIterator(from,to) : new DescendingIntArrayIterator(from,to); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntSet#size() + */ + public int size() { + return ints.length; + } + + /** + * @see kodkod.util.ints.IntSet#ceil(int) + */ + public int ceil(int i) { + final int index = Arrays.binarySearch(ints, i); + if (index==-ints.length-1) throw new NoSuchElementException(); + else return index >= 0 ? ints[index] : ints[-index-1]; + } + + /** + * @see kodkod.util.ints.IntSet#floor(int) + */ + public int floor(int i) { + final int index = Arrays.binarySearch(ints, i); + if (index==-1) throw new NoSuchElementException(); + else return index >= 0 ? ints[index] : ints[-index-2]; + } + + /** + * Returns true if i is in this set. + * @return i in this.ints + * @see kodkod.util.ints.IntSet#contains(int) + */ + public boolean contains(int i) { + return Arrays.binarySearch(ints, i) >= 0; + } + + /** + * Returns the smallest element in this set. + * Throws a NoSuchElementException if this set is empty. + * @return min(this.ints) + * @throws java.util.NoSuchElementException - no this.ints + * @see kodkod.util.ints.IntSet#max() + */ + @Override + public int max() { + if (ints.length==0) throw new NoSuchElementException(); + return ints[ints.length-1]; + } + + /** + * Returns the largest element in this set. + * Throws a NoSuchElementException if this set is empty. + * @return max(this.ints) + * @throws java.util.NoSuchElementException - no this.ints + * @see kodkod.util.ints.IntSet#min() + */ + @Override + public int min() { + if (ints.length==0) throw new NoSuchElementException(); + return ints[0]; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntCollection#toArray() + */ + @Override + public int[] toArray() { + final int[] ret = new int[ints.length]; + System.arraycopy(ints, 0, ret, 0, ints.length); + return ret; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntCollection#toArray(int[]) + */ + @Override + public int[] toArray(int[] array) { + if (array.length < size()) { + array = new int[ints.length]; + } + System.arraycopy(ints, 0, array, 0, ints.length); + return array; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntSet#hashCode() + */ + @Override + public int hashCode() { return hashcode; } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntSet#equals(java.lang.Object) + */ + @Override + public boolean equals(Object o) { + return (o instanceof ArrayIntSet) ? + java.util.Arrays.equals(ints, ((ArrayIntSet)o).ints) : + super.equals(o); + } + + /** + * An iterator that returns the elements of this int set in the + * ascending order. + * @author Emina Torlak + */ + private final class AscendingIntArrayIterator implements IntIterator { + private int next, end; + /** + * Constructs a new AscendingIntArrayIterator. + * @requires from <= to + */ + AscendingIntArrayIterator(int from, int to) { + final int fromIndex = Arrays.binarySearch(ints, from); + final int toIndex = Arrays.binarySearch(ints, to); + next = fromIndex >= 0 ? fromIndex : -fromIndex-1; + end = toIndex >=0 ? toIndex : -toIndex-2; + } + public boolean hasNext() { return next>=0 && next <= end; } + public int next() { + if (!hasNext()) throw new NoSuchElementException(); + return ints[next++]; + } + public final void remove() { throw new UnsupportedOperationException(); } + } + + /** + * An iterator that returns the elements of this int set in the + * descending order. + * @author Emina Torlak + */ + private final class DescendingIntArrayIterator implements IntIterator { + private int next, end; + /** + * Constructs a new AscendingIntArrayIterator. + * @requires from >= to + */ + DescendingIntArrayIterator(int from, int to) { + final int fromIndex = Arrays.binarySearch(ints, from); + final int toIndex = Arrays.binarySearch(ints, to); + next = fromIndex >= 0 ? fromIndex : -fromIndex-2; + end = toIndex >=0 ? toIndex : -toIndex-1; + } + public boolean hasNext() { return next >= end; } + public int next() { + if (!hasNext()) throw new NoSuchElementException(); + return ints[next--]; + } + public final void remove() { throw new UnsupportedOperationException(); } + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/ArrayIntVector.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/ArrayIntVector.java new file mode 100644 index 00000000..946ae275 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/ArrayIntVector.java @@ -0,0 +1,241 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + +/** + * A mutable implementation of the IntVector interface. Implements + * all optional IntVector operations. In addition to implementing the IntVector interface, + * this class provides methods to manipulate the size of the array that is + * used internally to store the elements of the IntVector.

+ * + * The size, isEmpty, get, set, + * and iterator operations run in constant + * time. The insert operations run in amortized constant time, + * that is, adding n elements requires O(n) time. All of the other operations + * run in linear time (roughly speaking).

+ * + * Each MutableIntVector instance has a capacity. The capacity is + * the size of the array used to store the elements in the list. It is always + * at least as large as the list size. As elements are added to a MutableIntVector, + * its capacity grows automatically. The details of the growth policy are not + * specified beyond the fact that adding an element has constant amortized + * time cost.

+ * + * An application can increase the capacity of an MutableIntVector instance + * before adding a large number of elements using the ensureCapacity + * operation. This may reduce the amount of incremental reallocation.

+ * + * This impementation is not synchronized and its iterators are not fail-fast. + * + * @author Emina Torlak + */ +public final class ArrayIntVector extends AbstractIntVector { + + private int[] elements; + private int size; + + /** + * Constructs an empty MutableIntVector with the specified initial capacity. + * + * @exception IllegalArgumentException if the specified initial capacity + * is negative + */ + public ArrayIntVector(int initialCapacity) { + if (initialCapacity < 0) + throw new IllegalArgumentException("Illegal Capacity: "+ + initialCapacity); + this.elements = new int[initialCapacity]; + } + + /** + * Constructs an empty MutableIntVector with an initial capacity of ten. + */ + public ArrayIntVector() { + this(10); + } + + /** + * Constructs a MutableIntVector containing the elements of the specified + * array, in proper sequence. The MutableIntVector instance has an initial capacity of + * 110% the size of the specified collection. + * + * @throws NullPointerException if the specified array is null. + */ + public ArrayIntVector(int[] array) { + size = array.length; + // Allow 10% room for growth + int capacity = (int) Math.min((size*110L)/100, Integer.MAX_VALUE); + elements = new int[capacity]; + System.arraycopy(array, 0, elements, 0, size); + } + + /** + * Trims the capacity of this MutableIntVector instance to be the + * list's current size. An application can use this operation to minimize + * the storage of an MutableIntVector instance. + */ + public void trimToSize() { + + int oldCapacity = elements.length; + if (size < oldCapacity) { + int[] oldData = elements; + elements = new int[size]; + System.arraycopy(oldData, 0, elements, 0, size); + } + } + + /** + * Increases the capacity of this MutableIntVector instance, if + * necessary, to ensure that it can hold at least the number of elements + * specified by the minimum capacity argument. + */ + public void ensureCapacity(int minCapacity) { + + int oldCapacity = elements.length; + if (minCapacity > oldCapacity) { + int[] oldData = elements; + int newCapacity = (oldCapacity * 3)/2 + 1; + if (newCapacity < minCapacity) + newCapacity = minCapacity; + elements = new int[newCapacity]; + System.arraycopy(oldData, 0, elements, 0, size); + } + } + + + + /** + * @throws IndexOutOfBoundsException - index < 0 or index >= size + */ + private void checkExcludeLength(int index) { + if (index < 0 || index >= size) + throw new IndexOutOfBoundsException(); + } + + /** + * @throws IndexOutOfBoundsException - index < 0 or index > size + */ + private void checkIncludeLength(int index) { + if (index < 0 || index > size) + throw new IndexOutOfBoundsException(); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntVector#get(int) + */ + public int get(int index) { + checkExcludeLength(index); + return elements[index]; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntVector#size() + */ + public int size() { + return size; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntVector#set(int, int) + */ + @Override + public int set(int index, int element) { + final int oldValue = get(index); + elements[index] = element; + return oldValue; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntVector#add(int) + */ + @Override + public boolean add(int element) { + ensureCapacity(size+1); + elements[size++] = element; + return true; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntVector#add(int, int) + */ + @Override + public void add(int index, int element) { + checkIncludeLength(index); + + ensureCapacity(size+1); + System.arraycopy(elements, index, elements, index + 1, size - index); + elements[index] = element; + size++; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntVector#addAll(int, kodkod.util.ints.IntCollection) + */ + @Override + public boolean addAll(int index, IntCollection c) { + checkIncludeLength(index); + + final int csize = c.size(); + if (csize==0) return false; + + ensureCapacity(size+csize); + System.arraycopy(elements, index, elements, index + csize, size - index); + + for(IntIterator iter = c.iterator(); iter.hasNext(); ) { + elements[index++] = iter.next(); + } + + return true; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.AbstractIntVector#removeAt(int) + */ + @Override + public int removeAt(int index) { + checkExcludeLength(index); + final int old = elements[index]; + System.arraycopy(elements, index+1, elements, index, size - index - 1); + size--; + return old; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.AbstractIntCollection#toArray(int[]) + */ + @Override + public int[] toArray(int[] array) { + if (array.length < size) { + array = new int[size]; + } + System.arraycopy(elements, 0, array, 0, size); + return array; + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/ArraySequence.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/ArraySequence.java new file mode 100644 index 00000000..5a4dbc81 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/ArraySequence.java @@ -0,0 +1,387 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + +import java.util.Iterator; +import java.util.NoSuchElementException; + + +/** + * An implementation of a sparse sequence based on an array. + * This implementation can be used only when the indices + * of the sequence are known in advance. The indices with + * which an ArraySequence is construct remain fixed throughout. + * The put operation fails whenever its index argument is not one + * of the sequence's pre-set indices, and iteration time is proportional + * to the number of pre-set indices. This sequence does not + * allow null values. The lookup and put operations are logarithmic in + * the number of pre-set indices. + * + * @specfield indeces: set int + * @specfield entries: indeces -> lone (V - null) + * @author Emina Torlak + */ +public final class ArraySequence extends AbstractSparseSequence implements Cloneable { + private final EntryView[] entries; + private int size; + + /** + * Constructs an array sequence that contains + * the given indeces. + * @ensures this.indeces' = indeces && no this.entries' + * @throws NullPointerException - indeces = null + */ + @SuppressWarnings("unchecked") + public ArraySequence(IntSet indices) { + this.entries = new EntryView[indices.size()]; + this.size = indices.size(); + final IntIterator indexIter = indices.iterator(); + for(int i = 0; indexIter.hasNext(); i++) { + entries[i] = new EntryView(indexIter.next(), null); + } + } + + /** + * Constructs a new array sequence with the same index/value mappings + * as the given sequence. + * @ensures this.entries' = s.entries + * @throws NullPointerException - s = null || null in s + */ + @SuppressWarnings("unchecked") + public ArraySequence(SparseSequence s) { + this.entries = new EntryView[s.size()]; + this.size = s.size(); + int i = 0; + for(IndexedEntry entry : s) { + if (entry.value()==null) + throw new NullPointerException(); + entries[i++] = new EntryView(entry.index(), (V)entry.value()); + } + } + + /** + * Copy constructor. + * @ensures constructs a deep copy of the original array sequence. + */ + @SuppressWarnings("unchecked") + private ArraySequence(ArraySequence original) { + this.size = original.size; + this.entries = new EntryView[original.entries.length]; + int i = 0; + for(EntryView e : original.entries) + this.entries[i++] = new EntryView(e.index(), e.value()); + } + + /** + * Returns the number of entries in this sequence. + * @return #this.entries + * @see kodkod.util.ints.SparseSequence#size() + */ + public int size() { + return size; + } + + /** + * Returns true if this sequence is empty; otherwise returns false. + * @return no this.entries + * @see kodkod.util.ints.SparseSequence#isEmpty() + */ + public boolean isEmpty() { + return size==0; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#clear() + */ + public void clear() { + for(EntryView e : entries) { + e.setValue(null); + } + } + + /** + * Searches this.entries for the specified index using the + * binary search algorithm. If the index is not found, then + * -insertionPoint - 1 is returned, where insertionPoint is + * the point at which the given index would be inserted into + * this.entries. + * @return the position in this.entries where the entry with + * the given index is located, or -insertionPoint - 1 if + * the index is not in this.indeces + */ + private final int search(int index) { + int low = 0; + int high = entries.length-1; + + while (low <= high) { + int mid = (low + high) >>> 1; + int midIndex = entries[mid].index(); + if (midIndex < index) + low = mid + 1; + else if (midIndex > index) + high = mid - 1; + else + return mid; // key found + } + + return -(low + 1); // key not found. + } + + /** + * Puts the given value at the specified index. If the + * sequence already mapped the index to a value, the + * previous value is replaced with the new one and returned. + * + * @ensures this.entries' = this.entries + index->value + * @return this.entries[index] + * @throws IndexOutOfBoundsException - index !in this.indeces + * @throws NullPointerException - value = null + * @see kodkod.util.ints.SparseSequence#put(int, Object) + */ + public V put(int index, V value) { + if (value==null) + throw new NullPointerException(); + final int position = search(index); + if (position < 0) + throw new IndexOutOfBoundsException(""+index); + if (entries[position]==null) size++; + return entries[position].setValue(value); + } + + /** + * Returns the value to which this sequence maps the given + * index. If the index is not mapped, null is returned. + * @return this.entries[index] + * @see kodkod.util.ints.SparseSequence#get(int) + */ + public V get(int index) { + final int position = search(index); + return position < 0 ? null : entries[position].value(); + } + + /** + * Removes the entry with the given index, if it exists, and + * returns the value previously stored at the index. If the + * sequence had no previous mapping for the index, null is returned. + * @ensures this.entries' = this.entries - index->E + * @return this.entries[index] + * @see kodkod.util.ints.SparseSequence#remove(int) + */ + public V remove(int index) { + final int position = search(index); + if (position < 0) + return null; + else { + if (entries[position].value()!=null) size--; + return entries[position].setValue(null); + } + } + + /** + * Returns true if this sparse sequence has an entry for the + * given index; otherwise returns false. + * @return index in this.indeces + * @see kodkod.util.ints.SparseSequence#containsIndex(int) + */ + public boolean containsIndex(int index) { + final int position = search(index); + return position >= 0 && entries[position].value()!=null; + } + + /** + * Returns an iterator over the entries in this sequence, + * whose indeces are between from and to. If from < to, + * the entries are returned in the ascending order of + * indeces. Otherwise, they are returned in the descending + * order of indeces. + * @return an iterator over the entries in this sequence + * whose indeces are between from and to. Formally, if + * from < to, then the first and last entries returned + * by the iterator are this.ceil(from) and this.floor(to). + * Otherwise, they are this.floor(from) and this.ceil(to). + * @see kodkod.util.ints.SparseSequence#iterator(int, int) + */ + public Iterator> iterator(int from, int to) { + return from <= to ? new AscendingIterator(from, to) : new DescendingIterator(from, to); + } + + /** + * Returns the entry with the smallest index. If the sequence + * is empty, returns null. + * @return {e: IndexedEntry | e.index = min(this.entries.E) && + * e.value = this.entries[e.index] } + * @see kodkod.util.ints.SparseSequence#first() + */ + public IndexedEntry first() { + if (size==0) + return null; + for(EntryView e : entries) { + if (e.value()!=null) + return e; + } + throw new InternalError(); // unreachable code + } + + /** + * Returns the entry with the largest index. If the sequence + * is empty, returns null. + * @return {e: IndexedEntry | e.index = max(this.entries.E) && + * e.value = this.entries[e.index] } + * @see kodkod.util.ints.SparseSequence#last() + */ + public IndexedEntry last() { + if (size==0) + return null; + for(int i = entries.length-1; i>=0; i--) { + if (entries[i].value()!=null) + return entries[i]; + } + throw new InternalError(); // unreachable code + } + + /** + * If an entry for the given index exists, it is returned. Otherwise, + * successor(index) is returned. + * @return this.containsIndex(index) => + * {e: IndexedEntry | e.index = index && e.value = this.entries[index] }, + * successor(index) + * @see kodkod.util.ints.SparseSequence#ceil(int) + */ + public IndexedEntry ceil(int index) { + final int position = search(index); + for(int i = position < 0 ? -position-1 : position; i < entries.length; i++) { + if (entries[i].value()!=null) + return entries[i]; + } + return null; + } + + /** + * If an entry for the given index exists, it is returned. Otherwise, + * predecessor(index) is returned. + * @return this.containsIndex(index) => + * {e: IndexedEntry | e.index = index && e.value = this.entries[index] }, + * predecessor(index) + * @see kodkod.util.ints.SparseSequence#floor(int) + */ + public IndexedEntry floor(int index) { + final int position = search(index); + for(int i = position < -1 ? -position-2 : position; i >=0 ; i--) { + if (entries[i].value()!=null) + return entries[i]; + } + return null; + } + + /** + * Returns a copy of this sparse sequence. The copy is independent of this + * sequence. + * @return a copy of this sparse sequence. + * @see kodkod.util.ints.SparseSequence#clone() + */ + public ArraySequence clone() { + return new ArraySequence(this); + } + + /** + * An iterator that traverses this sequence in the ascending order. + * + * @author Emina Torlak + */ + private final class AscendingIterator implements Iterator> { + final int endIndex; + IndexedEntry lastReturned = null; + int cursor; + + /** + * @requires from <= to + */ + AscendingIterator(int from, int to) { + final int fromPos = search(from); + final int toPos = search(to); + cursor = fromPos < 0 ? -fromPos-1 : fromPos; + endIndex = toPos < -1 ? -toPos-2 : toPos; + } + + public boolean hasNext() { + while (cursor < entries.length && entries[cursor].value()==null) + cursor++; + return cursor<=endIndex; + } + + public IndexedEntry next() { + if (!hasNext()) + throw new NoSuchElementException(); + return lastReturned=entries[cursor++]; + } + + public void remove() { + if (lastReturned==null) + throw new IllegalStateException(); + entries[lastReturned.index()].setValue(null); + lastReturned = null; + } + } + + /** + * An iterator that traverses this sequence in the descending order. + * + * @author Emina Torlak + */ + private final class DescendingIterator implements Iterator> { + final int endIndex; + IndexedEntry lastReturned = null; + int cursor; + + /** + * @requires from >= to + */ + DescendingIterator(int from , int to) { + final int fromPos = search(from); + final int toPos = search(to); + cursor = fromPos < -1 ? -fromPos-2 : fromPos; + endIndex = toPos < 0 ? -toPos-1 : toPos; + } + + public boolean hasNext() { + while (cursor >= 0 && entries[cursor].value()==null) + cursor--; + return cursor>=endIndex; + } + + public IndexedEntry next() { + if (!hasNext()) + throw new NoSuchElementException(); + return lastReturned=entries[cursor--]; + } + + public void remove() { + if (lastReturned==null) + throw new IllegalStateException(); + entries[lastReturned.index()].setValue(null); + lastReturned = null; + } + + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/EntryView.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/EntryView.java new file mode 100644 index 00000000..abc64364 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/EntryView.java @@ -0,0 +1,137 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + +/** + * A mutable IndexedEntry. This class provides + * various convience method for changing the entry state. + * @author Emina Torlak + */ +class EntryView implements IndexedEntry { + private int index; + private V value; + + /** + * Constructs a new entry view with the given index and value. + * @ensures this.index' = index and this.value' = value + */ + EntryView(int index, V value) { + this.index = index; + this.value = value; + } + + + /** + * Sets this.index to the given index, + * and returns the old index. + * @ensures this.index' = newIndex + * @return this.index + */ + int setIndex(int newIndex) { + final int oldIndex = this.index; + this.index = newIndex; + return oldIndex; + } + + /** + * Sets this.value to the given value, + * and returns the old value. + * @ensures this.value' = newValue + * @return this.value + */ + V setValue(V newValue) { + final V oldValue = this.value; + this.value = newValue; + return oldValue; + } + + /** + * Sets this.index and this.value to the given + * index and value, and returns this. + * @ensures this.index' = newIndex && this.value' = newValue + * @return this + */ + IndexedEntry setView(int newIndex, V newValue) { + this.index = newIndex; + this.value = newValue; + return this; + } + + /** + * Sets this.index to the given + * index, and returns this. + * @ensures this.index' = newIndex + * @return this + */ + IndexedEntry setIndexView(int newIndex) { + this.index = newIndex; + return this; + } + + /** + * Sets this.value to the given + * value, and returns this. + * @ensures this.value' = newValue + * @return this + */ + IndexedEntry setValueView(V newValue) { + this.value = newValue; + return this; + } + + /** + * @see kodkod.util.ints.IndexedEntry#index() + */ + public int index() { + return index; + } + + /** + * @see kodkod.util.ints.IndexedEntry#value() + */ + public V value() { + return value; + } + + /** + * @see java.lang.Object#toString() + */ + public final String toString() { + return index + "=" + value; + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public final boolean equals(Object o) { + if (o==this) return true; + if (!(o instanceof IndexedEntry)) return false; + return AbstractSparseSequence.equal(this, (IndexedEntry)o); + } + + /** + * @see java.lang.Object#hashCode() + */ + public final int hashCode() { + return AbstractSparseSequence.hashCode(this); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/HomogenousSequence.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/HomogenousSequence.java new file mode 100644 index 00000000..7e71c8f5 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/HomogenousSequence.java @@ -0,0 +1,327 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + +import java.util.Iterator; + +/** + * A sparse sequence implementation based on an {@link kodkod.util.ints.IntSet IntSet}. + * This implementation can be used only when all entries in the sequence map to the same value. + * + *

Important Implementation Note: As this implementation does not actually store any + * {@link kodkod.util.ints.IndexedEntry indexed entries}, + * the methods {@link #first()}, {@link #last()}, {@link #ceil(int)}, and {@link #floor(int)} + * may re-use the same IndexedEntry object. For example, suppose that an entry e with e.index = 1 + * is returned by a call to predecessor(2) on a homogenous sequence h = {<0,v>, <1,v>, <2,v>}. + * A subsequent call to h.predecessor(1) may return the same object e, with its index set to 0. Hence, + * the following assertion may fail:

+ *
+ * IndexedEntry e1 = h.predecessor(2);
+ * assert e1.index()==1; // this will work
+ * IndexedEntry e2 = h.predecessor(1);
+ * assert e1.index()==1; // this may fail, as e1 may be == to e2
+ * 
+ *

The entries returned by this implementation's {@link #iterator()} are unique + * to that iterator (but not necessarily independent of each other). For example,

+ *
+ * // let s be a range sequence abstractly represented as { 0->v, 1->v, 2->v }
+ * Iterator> iter1 = s.iterator();
+ * IndexedEntry e1 = iter1.next();
+ * assert e1.index()==0; // this will work
+ * iter1.next();
+ * assert e1.index()==0; // this may fail, as the previous call may have changed the state of e1
+ * Iterator> iter2 = s.iterator();
+ * IndexedEntry e2 = iter2.next();
+ * iter1.next();
+ * assert e2.index()==0; // this will work
+ * 
+ * @specfield indeces: set int + * @specfield entries: indeces -> one V + * @author Emina Torlak + */ +public final class HomogenousSequence extends AbstractSparseSequence { + private final IntSet indices; + private final V value; + private final EntryView view; + + /** + * Constructs a new homogenous sequence for the given value, backed + * by a {@link IntTreeSet IntTreeSet} instance. + * @ensures this.value' = value && no this.indices' + */ + public HomogenousSequence(V value) { + this.value = value; + this.indices = new IntTreeSet(); + this.view = new EntryView(Integer.MIN_VALUE, value); + } + + /** + * Constructs a new homogenous sequence for the given value, backed + * by the specified intset. Any changes to the provided set will + * be reflected in this sequence, and vice versa. This sequence will + * be unmodifiable if the given index set is unmodifiable. + * @requires indices is cloneable + * @ensures this.value' = value && this.indices' = indices + */ + public HomogenousSequence(V value, IntSet indices) { + this.value = value; + this.indices = indices; + this.view = new EntryView(Integer.MIN_VALUE, value); + } + + /** + * Copy constructor + * @ensures constructs a deep copy of the original + */ + private HomogenousSequence(HomogenousSequence original) { + this.value = original.value; + this.view = new EntryView(Integer.MIN_VALUE, value); + try { + this.indices = original.indices.clone(); + } catch (CloneNotSupportedException e) { + throw new InternalError(); // unreachable code. + } + } + + /** + * Constructs a new homogeneous sequence from the provided sequence. The + * returned sequence is backed by a {@link IntTreeSet IntTreeSet} instance. + * @requires one seq.entries[int] + * @ensures this.value' = seq.entries[int] && this.indices' = seq.indices() + * @throws NullPointerException - seq = null + * @throws IllegalArgumentException - seq.isEmpty() + * @throws IllegalArgumentException - #seq.entries[int] > 1 + */ + public HomogenousSequence(SparseSequence seq) { + if (seq.isEmpty()) + throw new IllegalArgumentException(); + this.indices = new IntTreeSet(); + this.value = seq.first().value(); + this.view = new EntryView(Integer.MIN_VALUE, value); + for(IndexedEntry e : seq) { + if (!value.equals(e.value())) + throw new IllegalArgumentException(); + indices.add(e.index()); + } + } + + /** + * Returns the set of all indices mapped by this sparse sequence. + * The returned set supports removal and addition iff this is not + * backed by an unmodifiable intset. + * @return {s: IntSet | s.ints = this.entries.V} + */ + public IntSet indices() { + return indices; + } + + /** + * Returns an iterator over the entries in this sequence, + * whose indeces are between from and to. If from < to, + * the entries are returned in the ascending order of + * indeces. Otherwise, they are returned in the descending + * order of indeces. + *

While the returned iterator i re-uses the same IndexedEntry + * object, it is not shared with other iterators or other method calls. + * In particular, no other call except i.next() can change the + * value of the re-used object.

+ * @return an iterator over the entries in this sequence + * whose indeces are between from and to. Formally, if + * from < to, then the first and last entries returned + * by the iterator are this.ceil(from) and this.floor(to). + * Otherwise, they are this.floor(from) and this.ceil(to). + * @see kodkod.util.ints.AbstractSparseSequence#iterator(int, int) + */ + public Iterator> iterator(int from, int to) { + return new HomogenousIterator(indices.iterator(from, to), value); + } + + /** + * Returns the number of entries in this sequence. + * @return #this.entries + * @see kodkod.util.ints.SparseSequence#size() + */ + public int size() { + return indices.size(); + } + + /** + * Removes all entries from this sequences. + * @ensures no this.entries' + * @see kodkod.util.ints.SparseSequence#clear() + */ + public void clear() { + indices.clear(); + } + + /** + * Puts the given value at the specified index. If the + * sequence already mapped the index to a value, the + * previous value is replaced with the new one and returned. + * + * @requires this.value = value + * @ensures this.indices' = this.indices + index + * @return this.entries[index] + * @throws IllegalArgumentException - this.value != value + * @see kodkod.util.ints.SparseSequence#put(int, Object) + */ + public V put(int index, V value) { + if (!equal(this.value, value)) + throw new IllegalArgumentException(); + return indices.add(index) ? null : value; + } + + /** + * Returns the value to which this sequence maps the given + * index. If the index is not mapped, null is returned. + * @return this.entries[index] + * @see kodkod.util.ints.SparseSequence#get(int) + */ + public V get(int index) { + return indices.contains(index) ? value : null; + } + + /** + * Removes the entry with the given index, if it exists, and + * returns the value previously stored at the index. If the + * sequence had no previous mapping for the index, null is returned. + * @ensures this.entries' = this.entries - index->E + * @return this.entries[index] + * @see kodkod.util.ints.SparseSequence#remove(int) + */ + public V remove(int index) { + return indices.remove(index) ? value : null; + } + + /** + * Returns true if this sparse sequence has an entry for the + * given index; otherwise returns false. + * @return some this.entries[index] + * @see kodkod.util.ints.SparseSequence#containsIndex(int) + */ + public boolean containsIndex(int index) { + return indices.contains(index); + } + + /** + * Returns true if this sequence has an entry with the given value; + * otherwise returns false. + * @return some this.indices && this.value = value + * @see kodkod.util.ints.SparseSequence#contains(java.lang.Object) + */ + public boolean contains(Object value) { + return !indices.isEmpty() && equal(this.value, value); + } + + /** + * Returns the entry with the smallest index. If the sequence + * is empty, returns null. + * @return {e: IndexedEntry | e.index = min(this.entries.E) && + * e.value = this.entries[e.index] } + * @see kodkod.util.ints.SparseSequence#first() + */ + public IndexedEntry first() { + return indices.isEmpty() ? null : view.setIndexView(indices.min()); + } + + /** + * Returns the entry with the largest index. If the sequence + * is empty, returns null. + * @return {e: IndexedEntry | e.index = max(this.entries.E) && + * e.value = this.entries[e.index] } + * @see kodkod.util.ints.SparseSequence#last() + */ + public IndexedEntry last() { + return indices.isEmpty() ? null : view.setIndexView(indices.max()); + } + + /** + * If an entry for the given index exists, it is returned. Otherwise, + * successor(index) is returned. + * @return this.containsIndex(index) => + * {e: IndexedEntry | e.index = index && e.value = this.entries[index] }, + * successor(index) + * @see kodkod.util.ints.SparseSequence#ceil(int) + */ + public IndexedEntry ceil(int index) { + if (indices.isEmpty() || index > indices.max()) + return null; + else + return view.setIndexView(indices.ceil(index)); + } + + /** + * If an entry for the given index exists, it is returned. Otherwise, + * predecessor(index) is returned. + * @return this.containsIndex(index) => + * {e: IndexedEntry | e.index = index && e.value = this.entries[index] }, + * predecessor(index) + * @see kodkod.util.ints.SparseSequence#floor(int) + */ + public IndexedEntry floor(int index) { + if (indices.isEmpty() || index < indices.min()) + return null; + else + return view.setIndexView(indices.floor(index)); + } + + /** + * Returns a copy of this sparse sequence. The copy is independent of this + * sequence. + * @return a copy of this sparse sequence. + * @see kodkod.util.ints.SparseSequence#clone() + */ + public HomogenousSequence clone() { + // ok to clone a final class using a copy constructor + return new HomogenousSequence(this); + } + + /** + * An iterator over a homogenous sequence. + * @author Emina Torlak + */ + private static final class HomogenousIterator extends EntryView implements Iterator> { + private final IntIterator iter; + + /** + * Constructs a wrapper for the given IntIterator and value + */ + HomogenousIterator(IntIterator iter, V value) { + super(Integer.MIN_VALUE, value); + this.iter = iter; + } + + public boolean hasNext() { + return iter.hasNext(); + } + + public IndexedEntry next() { + return setIndexView(iter.next()); + } + + public void remove() { + iter.remove(); + } + + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IndexedEntry.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IndexedEntry.java new file mode 100644 index 00000000..6da96761 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IndexedEntry.java @@ -0,0 +1,66 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + +/** + * An entry in a {@link SparseSequence sparse sequence}. + * + * @specfield index: int + * @specfield value: E + * + * @author Emina Torlak + */ +public interface IndexedEntry { + + /** + * Returns the index of this entry. + * @return this.index + */ + public abstract int index(); + + /** + * Returns the value stored in this entry. + * @return this.value + */ + public abstract E value(); + + /** + * Compares the specified object with this entry for equality. Returns true if + * the given object is also an indexed entry and the two entries + * have the same indeces and values. More formally, two entries e1 and e2 + * are equal if e1.index = e2.index && e1.value = e2.value. This ensures + * that the equals method works properly across different implementations of + * the IndexedEntry interface. + * @return o in IndexedEntry && o.index = this.index && o.value = this.value + */ + public abstract boolean equals(Object o); + + /** + * Returns the hash code value for this indexed entry. The hash code of an + * indexed entry e is defined to be: + * e.index ^ (e.value=null ? 0 : e.value.hashCode()). + * This ensures that e1.equals(e2) implies that e1.hashCode()==e2.hashCode() + * for any two IndexedEntries e1 and e2, as required by the general contract of + * Object.hashCode. + */ + public abstract int hashCode(); +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntBitSet.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntBitSet.java new file mode 100644 index 00000000..5bd5402b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntBitSet.java @@ -0,0 +1,527 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + +import java.util.Arrays; +import java.util.NoSuchElementException; + +/** + * An implementation of the IntSet interface based on a bit map. + * An IntBitSet can store only numbers in the half-open range + * [0..capacity) where capacity is a user-specified value. + * The implementation will allocated enough bits to explicitly represent all allowed + * integers; it performs better than a tree set when the stored integers + * are not clustered. + * @specfield capacity: [0..Integer.MAX_VALUE] + * @invariant all i: this.ints | 0 <= i < capacity + * @author Emina Torlak + */ +public final class IntBitSet extends AbstractIntSet implements Cloneable { + // implementation adapted from java.util.JumboEnumSet + private final int capacity; + /* + * Bit vector representation of this set. The ith bit of the jth + * element of this array represents the presence of universe[64*j +i] + * in this set. + */ + private long elements[]; + + // Redundant - maintained for performance + private int size; + + /** + * Constructs an empty IntBitSet that can store up + * to capacity elements. + * @ensures no this.ints' && this.capacity' = capacity + * @throws IllegalArgumentException - capacity < 0 + */ + public IntBitSet(int capacity) { + if (capacity < 0) throw new IllegalArgumentException("capacity < 0"); + this.capacity = capacity; + elements = new long[(capacity >>> 6) + 1]; + size = 0; + } + + /** + * Constructs an IntBitSet that can store up to capacity elements. + * The set is initialized to contain all integers i such that + * data[i>>>6] & (1L<>>6] & (1L<>>6)+1 > data.length + * @throws IllegalArgumentException - capacity is out of range + */ + public IntBitSet(int capacity, long[] data) { + if (capacity > (data.length<<6)) throw new IllegalArgumentException("capacity too large: " + capacity + ", max: " + (data.length<<6)); + this.capacity = capacity; + this.elements = data; + recalculateSize(); + +// System.out.println("capacity: " + capacity + ", max: " + max() + ", data.length: " + data.length); +// System.out.println(Arrays.toString(data)); + if (size > 0 && capacity <= max()) throw new IllegalArgumentException("capacity too small"); + } + + /** + * Returns the smallest element in this set. + * Throws a NoSuchElementException if this set is empty. + * @return min(this.ints) + * @throws java.util.NoSuchElementException - no this.ints + * @see kodkod.util.ints.IntSet#min() + */ + @Override + public int min() { + checkNonEmpty(); + int minWordIndex = 0; + while(elements[minWordIndex]==0) { minWordIndex++; } + return (minWordIndex << 6) + Long.numberOfTrailingZeros(elements[minWordIndex]); + } + + /** + * Returns the largest element in this set. + * Throws a NoSuchElementException if this set is empty. + * @return max(this.ints) + * @throws java.util.NoSuchElementException - no this.ints + * @see kodkod.util.ints.IntSet#max() + */ + @Override + public int max() { + checkNonEmpty(); + int maxWordIndex = elements.length-1; + while(elements[maxWordIndex]==0) { maxWordIndex--; } + return (maxWordIndex << 6) + 63 - Long.numberOfLeadingZeros(elements[maxWordIndex]); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntSet#ceil(int) + */ + public int ceil(int i) { + if (i <= 0) + return min(); + int wordIndex = wordIndex(i); + long word = 0; + if (wordIndex < elements.length) { + word = (extendedMask(i) & elements[wordIndex]); + } + while(word==0 && wordIndex < elements.length-1) { + word = elements[++wordIndex]; + } + if (word==0) + throw new NoSuchElementException(); + else + return (wordIndex << 6) + Long.numberOfTrailingZeros(word); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntSet#floor(int) + */ + public int floor(int i) { + if (i < 0) + throw new NoSuchElementException(); + int wordIndex = wordIndex(i); + long word = 0; + if (wordIndex < elements.length) { + word = ((~extendedMask(i+1)) & elements[wordIndex]); + } else { + wordIndex = elements.length-1; + word = elements[wordIndex]; + } + while(word==0 && wordIndex > 0) { + word = elements[--wordIndex]; + } + if (word==0) + throw new NoSuchElementException(); + else + return (wordIndex << 6) + 63 - Long.numberOfLeadingZeros(word); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntSet#iterator() + */ + @Override + public IntIterator iterator() { + return new AscendingIterator(0,capacity); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntSet#iterator(int, int) + */ + public IntIterator iterator(int from, int to) { + return from > to ? new DescendingIterator(from,to) : new AscendingIterator(from,to); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntSet#size() + */ + public int size() { + return size; + } + + /** + * Returns the capacity of this int bit set + * @return this.capacity + */ + public int capacity() { return capacity; } + + /** + * Returns the index of the word that contains + * the bit that represents the integer i. + * @requires 0 <= i < this.capacity + */ + private final int wordIndex(int i) { + return i >>> 6; + } + + /** + * Returns a bit mask that has 1 in the position representing the + * given integer within its word (obtained by wordIndex(i)) + * @requires 0 <= i < this.capacity + */ + private final long bitMask(int i) { + return 1L << i; + } + + /** + * Returns a bit mask that has 1 at every index greater than + * or equal to the position representing the + * given integer within its word. + * @requires 0 <= i < this.capacity + */ + private final long extendedMask(int i) { + return -1L << i; + } + + /** + * @return i in [0..this.capacity) + */ + private final boolean allows(int i) { + return 0 <= i && i < capacity; + } + + /** + * Returns true if i is in this set. + * @return i in this.ints + * @see kodkod.util.ints.IntSet#contains(int) + */ + @Override + public boolean contains(int i) { + return allows(i) && (elements[wordIndex(i)] & (bitMask(i))) != 0; + } + + /** + * Adds the given integer to this set if not already present + * and returns true. Otherwise does nothing and returns false. + * @ensures this.ints' = this.ints + i + * @return i in this.ints' + * @throws IllegalArgumentException - i !in [0..this.capacity) + * @see kodkod.util.ints.IntSet#add(int) + */ + @Override + public boolean add(int i) { + if (!allows(i)) throw new IllegalArgumentException(i + " !in [0.." + capacity + ")"); + + final int wordIndex = wordIndex(i); + final long oldElements = elements[wordIndex]; + elements[wordIndex] |= bitMask(i); + if (elements[wordIndex] != oldElements) { + size++; + return true; + } + return false; + } + + /** + * Removes the given integer from this set if already present and + * returns true. Otherwise does nothing and returns false. + * @ensures this.ints' = this.ints - i + * @return i !in this.ints' + * @see kodkod.util.ints.IntSet#remove(int) + */ + @Override + public boolean remove(int i) { + if (allows(i)) { + final int wordIndex = wordIndex(i); + final long oldElements = elements[wordIndex]; + elements[wordIndex] &= ~bitMask(i); + if (elements[wordIndex] != oldElements) { + size--; + return true; + } + } + + return false; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntCollection#isEmpty() + */ + @Override + public boolean isEmpty() { + return size==0; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntSet#containsAll(kodkod.util.ints.IntCollection) + */ + @Override + public boolean containsAll(IntCollection other) { + if (other instanceof IntBitSet) { + final IntBitSet s = (IntBitSet) other; + if (isEmpty() || s.isEmpty()) return isEmpty() ? s.isEmpty():true; + if (size < s.size || max() < s.max()) return false; + final int minLength = StrictMath.min(elements.length, s.elements.length); + for(int wordIndex = 0; wordIndex < minLength; wordIndex++) { + if ((s.elements[wordIndex] & ~elements[wordIndex]) != 0) + return false; + } + return true; + } + return super.containsAll(other); + } + + /** + * Recalculates the size and returns true if the size has changed. + */ + private boolean recalculateSize() { + final int oldSize = size; + size = 0; + for(long elt: elements) { + size += Long.bitCount(elt); + } + return size!=oldSize; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntSet#addAll(kodkod.util.ints.IntCollection) + */ + @Override + public boolean addAll(IntCollection other) { + if (other instanceof IntBitSet) { + final IntBitSet s = (IntBitSet) other; + if (s.isEmpty()) return false; + if (s.max() >= capacity) + throw new IllegalArgumentException(s.max()+" !in [0.." + capacity + ")"); + final int minLength = StrictMath.min(elements.length, s.elements.length); + for(int wordIndex = 0; wordIndex < minLength; wordIndex++) { + elements[wordIndex] |= s.elements[wordIndex]; + } + return recalculateSize(); + } + return super.addAll(other); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntSet#retainAll(kodkod.util.ints.IntCollection) + */ + @Override + public boolean retainAll(IntCollection other) { + if (other instanceof IntBitSet) { + final IntBitSet s = (IntBitSet) other; + final int minLength = StrictMath.min(elements.length, s.elements.length); + int wordIndex = 0; + for(; wordIndex < minLength; wordIndex++) { + elements[wordIndex] &= s.elements[wordIndex]; + } + for(; wordIndex < elements.length; wordIndex++) { + elements[wordIndex] = 0; + } + return recalculateSize(); + } + return super.retainAll(other); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntSet#removeAll(kodkod.util.ints.IntCollection) + */ + @Override + public boolean removeAll(IntCollection other) { + if (other instanceof IntBitSet) { + final IntBitSet s = (IntBitSet) other; + final int minLength = StrictMath.min(elements.length, s.elements.length); + for(int wordIndex = 0; wordIndex < minLength; wordIndex++) { + elements[wordIndex] &= ~s.elements[wordIndex]; + } + return recalculateSize(); + } + return super.removeAll(other); + } + + /** + * Removes all elements from this set. + * @ensures no this.ints' + * @see kodkod.util.ints.IntCollection#clear() + */ + @Override + public void clear() { + Arrays.fill(elements, 0); + size = 0; + } + + /** + * Returns a copy of this int bit set. The copy is independent of this + * IntSet. + * @return a copy of this IntSet. + * @see kodkod.util.ints.IntSet#clone() + */ + @Override + public IntBitSet clone() { + try { + final IntBitSet ret = (IntBitSet) super.clone(); + ret.elements = (long[]) this.elements.clone(); + return ret; + } catch (CloneNotSupportedException e) { + throw new InternalError(); // unreachable code + } + + } + + /** + * Stores common fields and methods for the ascending and descending iterators. + */ + private abstract class AbstractIterator implements IntIterator { + long unseen; + int unseenIndex, lastReturned; + + public void remove() { + if (lastReturned < 0) + throw new IllegalStateException(); + elements[wordIndex(lastReturned)] -= bitMask(lastReturned); + size--; + lastReturned = -1; + } + } + + /** + * Implementation of an ascending iterator over (a subset of) this set. + */ + private final class AscendingIterator extends AbstractIterator { + private final long maxMask; + private final int maxIndex; + + /** + * Constructs an ascending iterator that returns elements between + * from and to. + * @requires from <= to + */ + AscendingIterator(int from, int to) { + if (from >= capacity || to < 0) { + unseenIndex = maxIndex = elements.length; + unseen = maxMask = 0L; + } else { + if (to >= capacity) { + maxIndex = elements.length - 1; + maxMask = -1L; + } else { + maxIndex = wordIndex(to); + maxMask = (bitMask(to)==Long.MIN_VALUE ? -1L : ~extendedMask(to+1)); + } + if (from < 0) { + unseenIndex = 0; + unseen = elements[0]; + } else { + unseenIndex = wordIndex(from); + unseen = elements[unseenIndex] & extendedMask(from); + } + + } + lastReturned = -1; + } + + public boolean hasNext() { + while (unseen == 0 && unseenIndex < elements.length - 1) + unseen = elements[++unseenIndex]; + return (unseenIndex < maxIndex && unseen != 0) || + (unseenIndex == maxIndex && (unseen & maxMask) != 0); + } + + public int next() { + if (!hasNext()) throw new NoSuchElementException(); + final long lastReturnedMask = Long.lowestOneBit(unseen); + unseen -= lastReturnedMask; + lastReturned = (unseenIndex << 6) + Long.numberOfTrailingZeros(lastReturnedMask); + return lastReturned; + } + + } + + /** + * Implementation of a descending iterator over (a subset of) this set. + */ + private final class DescendingIterator extends AbstractIterator { + private final long minMask; + private final int minIndex; + + /** + * Constructs a descending iterator that returns elements between + * from and to. + * @requires from >= to + */ + DescendingIterator(int from, int to) { + if (to >= capacity || from < 0) { + unseenIndex = minIndex = 0; + unseen = minMask = 0L; + } else { + if (from < capacity) { + unseenIndex = wordIndex(from); + unseen = elements[unseenIndex] & + (bitMask(from)==Long.MIN_VALUE ? -1L : ~extendedMask(from+1)); + } else { + unseenIndex = elements.length-1; + unseen = elements[unseenIndex]; + } + if (to < 0) { + minIndex = 0 ; + minMask = -1L; + } else { + minIndex = wordIndex(to); + minMask = extendedMask(to); + } + } + lastReturned = -1; + } + + public boolean hasNext() { + while (unseen == 0 && unseenIndex > 0) + unseen = elements[--unseenIndex]; + return (unseenIndex > minIndex && unseen != 0) || + (unseenIndex == minIndex && (unseen & minMask) != 0); + } + + public int next() { + if (!hasNext()) throw new NoSuchElementException(); + final long lastReturnedMask = Long.highestOneBit(unseen); + unseen -= lastReturnedMask; + lastReturned = (unseenIndex << 6) + 63 - Long.numberOfLeadingZeros(lastReturnedMask); + return lastReturned; + } + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntCollection.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntCollection.java new file mode 100644 index 00000000..8e6a90ad --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntCollection.java @@ -0,0 +1,140 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + +/** + * The root interface in the int collection hierarchy. A collection + * represents a group of integers, known as its elements. Some collections + * allow duplicate elements and others do not. Some are ordered and others unordered. + * Some allow all integers and others only integers in a certain range. + * + * @author Emina Torlak + */ +public interface IntCollection { + + /** + * Returns the number of elements in this collection. + * @return number of elements in this collection. + */ + public abstract int size(); + + /** + * Returns true if this collection has no elements; + * otherwise returns false. + * @return true if this collection has no elements, + * false otherwise. + */ + public abstract boolean isEmpty(); + + /** + * Returns an iterator over the elements in this collection. + * There are no guarantees concerning the order in which the elements + * are returned (unless this collection is an instance of some class that provides a guarantee). + * @return an iterator over the elements in this collection + */ + public abstract IntIterator iterator(); + + /** + * Returns true if i is an element in this collection. + * @return true if i is an element in this collection. + */ + public abstract boolean contains(int i); + + /** + * Ensures that this collection contains the given integer, and returns true + * if this collection has changed as a result of the call. + * @return true if this collection has changed as a result of the call + * @throws UnsupportedOperationException - this is an unmodifiable collection + * @throws IllegalArgumentException - some aspect of the element prevents it + * from being added to this collection. + */ + public abstract boolean add(int i); + + /** + * Removes a single instance of the given integer from this collection, + * and returns true if this collection has changed as a result of the call. + * @return true if this collection has changed as a result of the call + * @throws UnsupportedOperationException - this is an unmodifiable collection + */ + public abstract boolean remove(int i); + + /** + * Returns true if this collection contains all of the elements in the specified collection. + * @return true if this collection contains all of the elements in the specified collection. + * @throws NullPointerException - c = null + */ + public abstract boolean containsAll(IntCollection c); + + /** + * Adds all of the elements in the specified collection to this collection. + * Returns true if this collection has changed as a result of the call. + * @return true if this collection has changed as a result of the call + * @throws NullPointerException - c = null + * @throws UnsupportedOperationException - this is an unmodifiable collection + * @throws IllegalArgumentException - some aspect of an element of the specified + * collection prevents it from being added to this collection. + */ + public abstract boolean addAll(IntCollection c); + + /** + * Removes all of this collection's elements that are also contained in the specified + * collection. After this call returns, this collection will contain no elements in + * common with the specified collection. Returns true if this collection has changed as a result of the call. + * @return true if this collection has changed as a result of the call + * @throws NullPointerException - c = null + * @throws UnsupportedOperationException - this is an unmodifiable collection + */ + public abstract boolean removeAll(IntCollection c); + + /** + * Retains only the elements in this collection that are contained in the specified + * collection. In other words, removes from this collection all of its elements that + * are not contained in the specified collection. Returns true if this collection has changed as a result of the call. + * @return rue if this collection has changed as a result of the call + * @throws NullPointerException - c = null + * @throws UnsupportedOperationException - this is an unmodifiable collection + */ + public abstract boolean retainAll(IntCollection c); + + /** + * Removes all elements from this collection. + * @throws UnsupportedOperationException - this is an unmodifiable collection + */ + public abstract void clear(); + + /** + * Returns an array containing all of the elements in this collection. + * @return an array containing all of the elements in this collection. + */ + public abstract int[] toArray(); + + /** + * Copies the elements of this collection into the specified array, provided + * that it is large enough, and returns it. If the array is not large enough, + * the effect of this method is the same as calling {@linkplain #toArray()}. + * @return the given array, filled with the elements from this collection, if + * the it is large enough; otherwise a new array containing all of the elements + * in this collection. + * @throws NullPointerException - array = null + */ + public abstract int[] toArray(int[] array); +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntIterator.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntIterator.java new file mode 100644 index 00000000..49895e3b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntIterator.java @@ -0,0 +1,55 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + + +/** + * An iterator over integer primitives. + * + * @author Emina Torlak + */ +public interface IntIterator { + + /** + * Returns true if this iteration has more elements. + * @return true if this iteration has more elements. + */ + public abstract boolean hasNext(); + + /** + * Returns the next int in the iteration, if any. + * Otherwise throws a NoSuchElementException. + * @return the next element in the iteration + * @throws java.util.NoSuchElementException - the iteration is empty. + */ + public abstract int next(); + + /** + * Removes the last returned element from the underlying collection. + * @ensures removes the last returned element from the underlying collection. + * @throws UnsupportedOperationException - removal is not supported + * @throws IllegalStateException - next() has not been called yet or remove() + * has already been called since the last call to next(). + */ + public abstract void remove(); + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntRange.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntRange.java new file mode 100644 index 00000000..57fa4401 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntRange.java @@ -0,0 +1,161 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + + +/** + * Represents a range of integers, [min..max]. + * + * @specfield min: int + * @specfield max: int + * @invariant min <= max + * @author Emina Torlak + */ +public abstract class IntRange { + + private IntRange() { } + + /** + * Returns the left endpoint of this range. + * @return this.min + */ + public abstract int min(); + + /** + * Returns the right endpoint of this range. + * @return this.max + */ + public abstract int max(); + + /** + * Returns the number of element in this range. + * @return this.max - this.min + 1 + */ + public int size() { + return max() - min() + 1; + } + + /** + * Returns true if the given integer is within + * this range; otherwise returns false. + * @return i in [min..max] + */ + public boolean contains(int i) { + return i >= min() && i <= max(); + } + + /** + * Returns true if this range contains the + * given range. + * @return this.min <= range.min <= range.max <= this.max + * @throws NullPointerException - range = null + */ + public boolean contains(IntRange range) { + return min() <= range.min() && range.max() <= max(); + } + + /** + * Returns true if this and the given range intersect. + * @return some i: int | this.contains(i) && range.contains(i) + * @throws NullPointerException - range = null + */ + public boolean intersects(IntRange range) { + return contains(range.min()) || contains(range.max()); + } + + + /** + * Returns true if o is an int range with the same endpoints as this. + * @return o in IntRange && o.min==this.min && o.max==this.max + */ + public boolean equals(Object o) { + if (o instanceof IntRange) { + final IntRange r = (IntRange) o; + return min()==r.min() && max()==r.max(); + } + return false; + } + + /** + * Returns the hash code for this int range. The implementation + * is guaranteed to obey the Object contract. + * @return the hashcode for this intrange + */ + public int hashCode() { + return min()==max() ? min() : min() ^ max(); + } + + public String toString() { + return "[" + min() + ".." + max() + "]"; + } + + /** + * Represents an int range that consists of a single point. + * + * @invariant min==max + * @author Emina Torlak + */ + static final class OnePointRange extends IntRange { + private final int min; + + /** + * Constructs a new one point range. + */ + OnePointRange(int min) { + this.min = min; + } + + @Override + public final int min() { return min; } + + @Override + public final int max() { return min; } + } + + /** + * Represents an int range with two distinct end points. + * + * @invariant min < max + * @author Emina Torlak + */ + static final class TwoPointRange extends IntRange { + private final int min, max; + + /** + * Constructs a new two point range. + * @requires min < max + */ + TwoPointRange(int min, int max) { + assert min < max; + this.min = min; + this.max = max; + } + + @Override + public final int min() { return min; } + + @Override + public final int max() { return max; } + } + + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntSet.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntSet.java new file mode 100644 index 00000000..2b735221 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntSet.java @@ -0,0 +1,217 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + +import java.util.NoSuchElementException; + +/** + * An ordered set of integers. + * + * @specfield ints: set int + * @author Emina Torlak + */ +public interface IntSet extends IntCollection, Cloneable { + + /** + * Returns the cardinality of this set. + * @return #this.ints + */ + public abstract int size(); + + /** + * Returns true if this set has no elements; + * otherwise returns false. + * @return no this.ints + */ + public abstract boolean isEmpty(); + + /** + * Returns true if i is in this set. + * @return i in this.ints + */ + public abstract boolean contains(int i); + + /** + * Returns the smallest element in this set. + * Throws a NoSuchElementException if this set is empty. + * @return min(this.ints) + * @throws java.util.NoSuchElementException - no this.ints + */ + public abstract int min(); + + /** + * Returns the largest element in this set. + * Throws a NoSuchElementException if this set is empty. + * @return max(this.ints) + * @throws java.util.NoSuchElementException - no this.ints + */ + public abstract int max(); + + /** + * Returns the largest element in this set that + * is smaller than or equal to i. If this is emtpy or i is less than this.min(), + * NoSuchElementException is thrown. + * @return {j: this.ints | j <= i && no k: this.ints - j | k > j && k <= i} + * @throws NoSuchElementException - no this.ints || i < this.min() + */ + public abstract int floor(int i); + + /** + * Returns the smallest element in this set that + * is greater than or equal to i. If this is emtpy or i is greater than this.max(), + * NoSuchElementException is thrown. + * @return {j: this.ints | j >= i && no k: this.ints - j | k < j && k >= i} + * @throws NoSuchElementException - no this.ints || i > this.max() + */ + public abstract int ceil(int i); + + /** + * Returns an iterator over the integers in this set, + * in the ascending element order. + * @return an IntIterator over the integers in this set. + */ + public abstract IntIterator iterator(); + + /** + * Returns an iterator over the elements of this set that + * are in the closed range [from..to]. If from < to, + * the elements are returned in the ascending order. + * Otherwise, they are returned in the descending order. + * @return an iterator over the elements in this set + * that are in the closed range [from..to]. + */ + public abstract IntIterator iterator(int from, int to); + + /** + * Adds the given integer to this set if not already present + * and returns true. Otherwise does nothing and returns false. + * @ensures this.ints' = this.ints + i + * @return i in this.ints' + * @throws IllegalArgumentException - this is a bounded set + * and i is out of bounds + */ + public abstract boolean add(int i); + + /** + * Removes the given integer from this set if already present and + * returns true. Otherwise does nothing and returns false. + * @ensures this.ints' = this.ints - i + * @return i !in this.ints' + */ + public abstract boolean remove(int i); + + /** + * Returns true if the elements of c are a subset of this set. + * @return { i: int | c.contains(i) } in this.ints + * @throws NullPointerException - c = null + */ + public abstract boolean containsAll(IntCollection c); + + /** + * Adds all of the elements in the specified collection to this set + * if they're not already present. + * @ensures this.ints' = this.ints + { i: int | c.contains(i) } + * @return this.ints' != this.ints + * @throws NullPointerException - c = null + * @throws UnsupportedOperationException - this is an unmodifiable set + * @throws IllegalArgumentException - some aspect of an element of the specified + * collection prevents it from being added to this collection. + */ + public abstract boolean addAll(IntCollection c); + + /** + * Removes from this set all of its elements that are contained in the + * specified set. + * @ensures this.ints' = this.ints - { i: int | c.contains(i) } + * @return this.ints' != this.ints + * @throws NullPointerException - s = null + * @throws UnsupportedOperationException - this is an unmodifiable set + */ + public abstract boolean removeAll(IntCollection c); + + /** + * Retains only the elements in this set that are contained in the + * specified set. + * @ensures this.ints' = this.ints & { i: int | c.contains(i) } + * @return this.ints' != this.ints + * @throws NullPointerException - s = null + * @throws UnsupportedOperationException - this is an unmodifiable set + */ + public abstract boolean retainAll(IntCollection c); + + /** + * Removes all elements from this set. + * @ensures no this.ints' + */ + public abstract void clear(); + + /** + * Returns a copy of this IntSet. The copy is independent of this + * IntSet unless this is a singleton or an immutable set, in which case + * clone() may return this. An implementing class that does not support + * cloning may throw a CloneNotSupportedException. + * @return a copy of this IntSet. + * @throws CloneNotSupportedException - this is not cloneable + */ + public abstract IntSet clone() throws CloneNotSupportedException; + + /** + * Returns an array containing all of the elements in this set in the + * ascending order. + * + * @return an array containing all of the elements in this set in the + * ascending order. + */ + public abstract int[] toArray(); + + /** + * Copies the elements of this set into the specified array, in the ascending + * order, provided that the array is large enough. If the array is not large enough, + * the effect of this method is the same as calling {@linkplain #toArray()}. + * @ensures array.length>=this.size() => all i: [0..this.size()) | array'[i] in this.ints and #{e: this.ints | e < array'[i]} = i + * @return array.length>=this.size() => array' else this.toArray() + * @throws NullPointerException - array = null + */ + public abstract int[] toArray(int[] array); + + /** + * Compares the specified object with this set for equality. + * Returns true if the specified object is also an IntSet, + * the two sets have the same size, and every member of the + * specified set is contained in this set (or equivalently, + * every member of this set is contained in the specified set). + * This definition ensures that the equals method works properly + * across different implementations of the IntSet interface. + * @return o instanceof IntSet and o.size() = this.size() and this.containsAll(o) + */ + public abstract boolean equals(Object o); + + /** + * Returns the hash code value for this set. The hash code of a set is + * defined to be the {@link Ints#superFastHash(int[])} of the elements in the set, + * taken in the ascending order of values. + * This ensures that s1.equals(s2) implies that s1.hashCode()==s2.hashCode() + * for any two IntSets s1 and s2, as required by the general contract of the Object.hashCode method. + * @return Ints.superFastHash(this.toArray()) + */ + public abstract int hashCode(); +} \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntTree.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntTree.java new file mode 100644 index 00000000..0472ba99 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntTree.java @@ -0,0 +1,632 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package kodkod.util.ints; + +/** + * A tree with integer keys. + * + * @specfield root: lone N + * @specfield nodes: root.*(left + right) + * @author Emina Torlak + */ +final class IntTree> implements Cloneable { + private static final boolean BLACK = true, RED = false; + + private N root; + + /** + * Creates an empty IntTree. + * + * @ensures no this.root' + */ + IntTree() { + root = null; + } + + /** + * Discards all elements from this tree. + * + * @ensures no this.root' + **/ + final void clear() { + root = null; + } + + /** + * Returns the node with the given key, or null no such node exists. + * + * @return this.nodes & key.index + */ + final N search(int k) { + N node = root; + while (node != null) { + if (node.key == k) + break; + else if (node.key > k) + node = node.left; + else + node = node.right; + } + return node; + } + + /** + * Returns the node whose key is the ceiling of k in this tree, or null if no such node + * exists. + * + * @return {n: this.nodes | n.key >= k && no n': this.nodes - n | n'.key >= k && n'.key < n.key } + */ + final N searchGTE(int k) { + if (root == null) + return null; + N c = root; + while (true) { + if (c.key == k) { + return c; + } else if (c.key > k) { + if (c.left != null) + c = c.left; + else + return c; + } else { + if (c.right != null) + c = c.right; + else + return successor(c); + } + } + } + + /** + * Returns the node whose key is the floor of k in this tree, or null if no such node + * exists. + * + * @return {n: this.nodes | n.key <= k && no n': this.nodes - n | n'.key <= k && n'.key > n.key } + */ + final N searchLTE(int k) { + if (root == null) + return null; + N f = root; + while (true) { + if (f.key == k) + return f; + else if (f.key > k) { + if (f.left != null) + f = f.left; + else + return predecessor(f); + } else { + if (f.right != null) + f = f.right; + else + return f; + } + } + } + + /** + * Implementation of the tree-predecessor algorithm from CLR. Returns the given node's + * predecessor, if it exists. Otherwise returns null. + * + * @return the given node's predecessor + * @throws NullPointerException - node = null + */ + final N predecessor(N node) { + if (node.left != null) { + return max(node.left); + } else { + N n = node; + N ancestor = n.parent; + while (ancestor != null && n == ancestor.left) { + n = ancestor; + ancestor = ancestor.parent; + } + return ancestor; + } + } + + /** + * Implementation of the tree-successor algorithm from CLR. Returns the given node's successor, if + * it exists. Otherwise returns null. + * + * @return the given node's successor + * @throws NullPointerException - node = null + */ + final N successor(N node) { + if (node.right != null) { + return min(node.right); + } else { + N n = node; + N ancestor = n.parent; + while (ancestor != null && n == ancestor.right) { + n = ancestor; + ancestor = ancestor.parent; + } + return ancestor; + } + } + + /** + * Returns the node with the smallest key. + * + * @return key.(min(this.nodes.key)) + */ + final N min() { + return min(root); + } + + /** + * Returns the node with the largest key. + * + * @return key.(max(this.nodes.key)) + */ + final N max() { + return max(root); + } + + /** + * Returns the leftmost node in the subtree rooted at start. The behavior of this method is + * unspecified if the given node is not in this tree. + * + * @requires node in this.nodes + * @return {n: start.*left | no n.left } + */ + private final N min(N start) { + if (start != null) { + while (start.left != null) { + start = start.left; + } + } + return start; + } + + /** + * Returns the rightmost in the subtree rooted at start. The behavior of this method is + * unspecified if the given node is not in this tree. + * + * @requires node in this.nodes + * @return {n: start.*left | no n.right } + */ + private final N max(N start) { + if (start != null) { + while (start.right != null) { + start = start.right; + } + } + return start; + } + + /** + * Replaces the old node, o, with the given new node, n, in this tree. + * + * @requires no n.(left + right + parent) + * @requires o = o.parent.left => n.key < o.parent.key + * @requires o = o.parent.right => n.key > o.parent.key + * @requires some o.left => n.key > o.left.key + * @requires some o.right => n.key < o.right.key + * @ensures this.nodes' = this.nodes - o + n + * @ensures o.parent' = o.left' = o.right' = null + */ + @SuppressWarnings("unchecked") + final void replace(N o, N n) { + n.color = o.color; + n.parent = o.parent; + n.left = o.left; + n.right = o.right; + if (o.left != null) { + o.left.parent = n; + } + if (o.right != null) { + o.right.parent = n; + } + if (o.parent == null) { + root = n; + } else if (o == o.parent.left) { + o.parent.left = n; + } else { + o.parent.right = n; + } + o.parent = o.left = o.right = null; + } + + private final N parentOf(N n) { + return n == null ? null : n.parent; + } + + private final N leftOf(N n) { + return n == null ? null : n.left; + } + + private final N rightOf(N n) { + return n == null ? null : n.right; + } + + private final boolean colorOf(N n) { + return n == null ? BLACK : n.color; + } + + private final void setColor(N n, boolean color) { + if (n != null) + n.color = color; + } + + /** + * Implementation of the CLR insertion algorithm. + * + * @requires no z.key & this.nodes.key + * @ensures this.nodes' = this.nodes + z + */ + @SuppressWarnings("unchecked") + final void insert(N z) { + N y = null; + for (N x = root; x != null;) { + y = x; + if (x.key > z.key) + x = x.left; + else + x = x.right; + } + + z.parent = y; + z.left = z.right = null; + if (y == null) { + root = z; + } else { + z.color = RED; + if (y.key > z.key) { + y.left = z; + } else { + y.right = z; + } + + insertFixUp(z); + } + } + + /** + * A slightly modified implementation of the CLR deletion algorithm. + * + * @requires z in this.nodes + * @ensures this.nodes' = this.nodes - z + */ + @SuppressWarnings("unchecked") + final void delete(N z) { + N y = (z.left == null || z.right == null ? z : successor(z)); + N x = (y.left != null ? y.left : y.right); + + N yparent = y.parent; + final boolean yleft = (y == leftOf(y.parent)); + final boolean ycolor = y.color; + + if (x != null) { + x.parent = yparent; + } + + if (yparent == null) { + root = x; + } else if (yleft) { + yparent.left = x; + } else { + yparent.right = x; + } + + if (y != z) { + replace(z, y); + } + + if (ycolor == BLACK) { + if (x != null) { + deleteFixUp(x); + } else if (yparent != null) { // z is not the only node + + if (z == yparent) + yparent = y; // y, z's successor, is z's right child + z.color = BLACK; + z.left = z.right = null; + z.parent = yparent; + if (yleft) { + yparent.left = z; + } else { + yparent.right = z; + } + + deleteFixUp(z); + if (z == z.parent.left) { + z.parent.left = null; + } else { + z.parent.right = null; + } + } + } + + z.left = z.right = z.parent = null; // cut z out of the tree by nulling out its pointers + } + + /** + * {@inheritDoc} + * + * @see java.lang.Object#clone() + * @throws CloneNotSupportedException - nodes contained in this tree are not cloneable + */ + @SuppressWarnings("unchecked") + protected IntTree clone() throws CloneNotSupportedException { + final IntTree ret = (IntTree) super.clone(); + ret.root = clone(root, null); + return ret; + } + + /** + * Recursively clones the given node. + */ + @SuppressWarnings("unchecked") + private N clone(N n, N parent) throws CloneNotSupportedException { + if (n == null) + return null; + N clone = (N) n.clone(); + clone.parent = parent; + clone.left = clone(n.left, clone); + clone.right = clone(n.right, clone); + return clone; + } + + /*---------balancing operations (CLR, pp.278-289)---------*/ + /** + * From CLR. + */ + @SuppressWarnings("unchecked") + private void insertFixUp(N z) { + while (z != null && z != root && z.parent.color == RED) { + if (parentOf(z) == leftOf(parentOf(parentOf(z)))) { + N y = rightOf(parentOf(parentOf(z))); + if (colorOf(y) == RED) { + setColor(parentOf(z), BLACK); + setColor(y, BLACK); + setColor(parentOf(parentOf(z)), RED); + z = parentOf(parentOf(z)); + } else { + if (z == rightOf(parentOf(z))) { + z = parentOf(z); + rotateLeft(z); + } + setColor(parentOf(z), BLACK); + setColor(parentOf(parentOf(z)), RED); + if (parentOf(parentOf(z)) != null) + rotateRight(parentOf(parentOf(z))); + } + } else { + N y = leftOf(parentOf(parentOf(z))); + if (colorOf(y) == RED) { + setColor(parentOf(z), BLACK); + setColor(y, BLACK); + setColor(parentOf(parentOf(z)), RED); + z = parentOf(parentOf(z)); + } else { + if (z == leftOf(parentOf(z))) { + z = parentOf(z); + rotateRight(z); + } + setColor(parentOf(z), BLACK); + setColor(parentOf(parentOf(z)), RED); + if (parentOf(parentOf(z)) != null) + rotateLeft(parentOf(parentOf(z))); + } + } + } + root.color = BLACK; + } + + /** + * From CLR. + */ + @SuppressWarnings("unchecked") + private void deleteFixUp(N x) { + while (x != root && colorOf(x) == BLACK) { + if (x == leftOf(parentOf(x))) { + N sib = rightOf(parentOf(x)); + + if (colorOf(sib) == RED) { + setColor(sib, BLACK); + setColor(parentOf(x), RED); + rotateLeft(parentOf(x)); + sib = rightOf(parentOf(x)); + } + + if (colorOf(leftOf(sib)) == BLACK && colorOf(rightOf(sib)) == BLACK) { + setColor(sib, RED); + x = parentOf(x); + } else { + if (colorOf(rightOf(sib)) == BLACK) { + setColor(leftOf(sib), BLACK); + setColor(sib, RED); + rotateRight(sib); + sib = rightOf(parentOf(x)); + } + setColor(sib, colorOf(parentOf(x))); + setColor(parentOf(x), BLACK); + setColor(rightOf(sib), BLACK); + rotateLeft(parentOf(x)); + x = root; + } + } else { // symmetric + N sib = leftOf(parentOf(x)); + + if (colorOf(sib) == RED) { + setColor(sib, BLACK); + setColor(parentOf(x), RED); + rotateRight(parentOf(x)); + sib = leftOf(parentOf(x)); + } + + if (colorOf(rightOf(sib)) == BLACK && colorOf(leftOf(sib)) == BLACK) { + setColor(sib, RED); + x = parentOf(x); + } else { + if (colorOf(leftOf(sib)) == BLACK) { + setColor(rightOf(sib), BLACK); + setColor(sib, RED); + rotateLeft(sib); + sib = leftOf(parentOf(x)); + } + setColor(sib, colorOf(parentOf(x))); + setColor(parentOf(x), BLACK); + setColor(leftOf(sib), BLACK); + rotateRight(parentOf(x)); + x = root; + } + } + } + + setColor(x, BLACK); + + } + + /** + * From CLR. + */ + @SuppressWarnings("unchecked") + private void rotateLeft(N x) { + N y = x.right; + x.right = y.left; + if (y.left != null) + y.left.parent = x; + y.parent = x.parent; + if (x.parent == null) + root = y; + else if (x.parent.left == x) + x.parent.left = y; + else + x.parent.right = y; + y.left = x; + x.parent = y; + } + + /** + * From CLR. + */ + @SuppressWarnings("unchecked") + private void rotateRight(N x) { + N y = x.left; + x.left = y.right; + if (y.right != null) + y.right.parent = x; + y.parent = x.parent; + if (x.parent == null) + root = y; + else if (x.parent.right == x) + x.parent.right = y; + else + x.parent.left = y; + y.right = x; + x.parent = y; + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + return root.toString(); + } + + /** + * A node in an int tree. Subclasses need to implement the clone method iff IntTree.clone will be + * called on the tree containing the nodes. + * + * @specfield key: int + * @specfield parent: lone N + * @specfield left: lone N + * @specfield right: lone N + * @author Emina Torlak + */ + abstract static class Node> implements Cloneable { + N parent; + N left; + N right; + boolean color; + /** + * Subclasses are required to maintain the following invariant: + * + * @invariant this = this.parent.left => this.key < this.parent.key && this = this.parent.right + * => this.key > this.parent.key && some this.left => this.key > this.left.key && + * some this.right => this.key < this.right.key + */ + protected int key; + + /** + * Constructs an empty node with the given key. + * + * @ensures no this.(parent' + left' + right') && this.key' = key + */ + Node(int key) { + this.parent = this.left = this.right = null; + this.color = BLACK; + this.key = key; + } + + /** + * Returns the left child of this node. + * + * @return this.left + */ + final N left() { + return left; + } + + /** + * Returns the right child of this node. + * + * @return this.right + */ + final N right() { + return right; + } + + /** + * Return the parent of this node. + * + * @return this.parent + */ + final N parent() { + return parent; + } + + /** + * Clones this node. Subclasses must override this method (and call super.clone()) in order for + * IntTree.clone() to function properly. + * + * @throws CloneNotSupportedException + * @see java.lang.Object#clone() + */ + @SuppressWarnings("unchecked") + protected Node clone() throws CloneNotSupportedException { + Node ret = (Node) super.clone(); + ret.parent = ret.left = ret.right = null; + return ret; + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + return "[" + key + " " + (color ? "b" : "r") + " " + (left == this ? key : left) + " " + + (right == this ? key : right) + "]"; + + } + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntTreeSet.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntTreeSet.java new file mode 100644 index 00000000..b6e7af99 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntTreeSet.java @@ -0,0 +1,410 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + +import java.util.NoSuchElementException; + +/** + * An implementation of the IntTreeSet interface based + * on a balanced binary search tree. + * + * @specfield ints: set int + * @author Emina Torlak + */ +public final class IntTreeSet extends AbstractIntSet implements Cloneable { + /* The endpoints of the ranges in the tree do not touch, and they are + * sorted by their right endpoints. + * @invariant all n: tree.nodes | n.max = n.key && n.min <= n.max && + * all n': tree.nodes - n | n'.max < n.min - 1 || n'.min > n.max + 1 + */ + private final IntTree tree; + private int size; + + /** + * Constructs an empty int set. + * @ensures no this.ints' + */ + public IntTreeSet() { + tree = new IntTree(); + size = 0; + } + + /** + * Constructs a new int set containing the elements + * in the specified set. + * @ensures this.ints' = s.ints + * @throws NullPointerException - s = null + */ + public IntTreeSet(IntSet s) { + this(); + addAll(s); + } + + /** + * Copy constructor. + * @ensures constructs a deep copy of the original set. + */ + @SuppressWarnings("unchecked") + private IntTreeSet(IntTreeSet original) { + this.size = original.size; + try { + this.tree = original.tree.clone(); + } catch (CloneNotSupportedException e) { + throw new InternalError(); // unreachable code + } + } + +// public String toString() { +// for(Range next = tree.min(); next != null; next = tree.successor(next) ) { +// System.out.print("[" + next.min + " .. " + next.key+ "] "); +// } +// System.out.println(""); +// return ""; +// } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntSet#iterator(int,int) + */ + public IntIterator iterator(int from, int to) { + return from <= to ? new AscendingIterator(from, to) : new DescendingIterator(from, to); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntSet#size() + */ + public int size() { + return size; + } + + /** + * Returns true if i is in this set. + * @return i in this.ints + * @see kodkod.util.ints.IntSet#contains(int) + */ + @Override + public boolean contains(int i) { + final Range r = tree.searchGTE(i); + return r != null && r.min <= i; + } + + /** + * Returns the smallest element in this set. + * Throws a NoSuchElementException if this set is empty. + * @return min(this.ints) + * @throws java.util.NoSuchElementException - no this.ints + * @see kodkod.util.ints.IntSet#min() + */ + @Override + public int min() { + checkNonEmpty(); + return tree.min().min; + } + + /** + * Returns the largest element in this set. + * Throws a NoSuchElementException if this set is empty. + * @return max(this.ints) + * @throws java.util.NoSuchElementException - no this.ints + * @see kodkod.util.ints.IntSet#max() + */ + @Override + public int max() { + checkNonEmpty(); + return tree.max().key; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntSet#floor(int) + */ + public int floor(int i) { + checkNonEmpty(); + Range r = tree.searchGTE(i); + if (r==null || r.min > i) { + r = tree.searchLTE(i); + return r == null ? null : r.key; + } else + return i; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntSet#ceil(int) + */ + public int ceil(int i) { + checkNonEmpty(); + final Range r = tree.searchGTE(i); + return r == null ? null : StrictMath.max(i, r.min); + } + + /** + * Adds the given integer to this set if not already present + * and returns true. Otherwise does nothing and returns false. + * @ensures this.ints' = this.ints + i + * @return i in this.ints' + * @see kodkod.util.ints.IntSet#add(int) + */ + @Override + public boolean add(int i) { + final Range ceil = tree.searchGTE(i); + if (ceil==null || ceil.min > i) { + + final Range floor = tree.searchLTE(i); + + if (floor != null && floor.key==i-1) { + if (ceil != null && ceil.min==i+1) { + tree.delete(ceil); + floor.key = ceil.key; + } else { + floor.key = i; + } + } else if (ceil != null && ceil.min==i+1) { + ceil.min = i; + } else { + tree.insert(new Range(i,i)); + } + + size++; + return true; + } + + return false; + } + + /** + * Removes the given integer from this set if already present and + * returns true. Otherwise does nothing and returns false. + * @ensures this.ints' = this.ints - i + * @return i !in this.ints' + * @see kodkod.util.ints.IntSet#remove(int) + */ + @Override + public boolean remove(int i) { + final Range ceil = tree.searchGTE(i); + + if (ceil != null && i >= ceil.min) { + if (ceil.min==ceil.key) { + tree.delete(ceil); + } else if (i==ceil.min) { + ceil.min++; + } else if (i==ceil.key) { + ceil.key = i-1; + } else { // split the range in two + tree.insert(new Range(ceil.min, i-1)); + ceil.min = i+1; + } + size--; + assert size >= 0; + return true; + } + + return false; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.IntSet#containsAll(kodkod.util.ints.IntCollection) + */ + @Override + public boolean containsAll(IntCollection other) { + if (other instanceof IntTreeSet) { + IntTreeSet s = (IntTreeSet) other; + if (size>=s.size) { + for(Range r1 = s.tree.min(); r1 != null; r1 = s.tree.successor(r1)) { + Range r0 = tree.searchGTE(r1.key); + if (r0==null || r1.min < r0.min) + return false; + } + return true; + } + return false; + } + return super.containsAll(other); + } + + /** + * Removes all elements from this set. + * @ensures no this.ints' + * @see kodkod.util.ints.IntCollection#clear() + */ + @Override + public void clear() { + tree.clear(); + size = 0; + } + + /** + * Returns a copy of this int tree set. The copy is independent of this + * IntSet. + * @return a copy of this IntSet. + * @see kodkod.util.ints.IntSet#clone() + */ + @SuppressWarnings("unchecked") + @Override + public IntTreeSet clone() { + // ok to use copy constructor to clone a final class + return new IntTreeSet(this); + } + + /** + * A range of integers in an int set. + * @specfield min: int + * @specfield max: int + * @invariant min <= max + * @invariant max = key + * @author Emina Torlak + */ + private static final class Range extends IntTree.Node implements Cloneable { + private int min; + + Range(int min, int max) { + super(max); + this.min = min; + } + + protected Range clone() throws CloneNotSupportedException { + return (Range)super.clone(); + } + + } + + /** + * An iterator that traverses the ints in this set in the + * ascending order. + * @author Emina Torlak + */ + private final class AscendingIterator implements IntIterator { + private Range next; + private final int endpoint; + private int currentMax, cursor, lastReturned; + private boolean canRemove; + + /** + * @requires from <= to + */ + AscendingIterator(int from, int to) { + endpoint = to; + lastReturned = Integer.MIN_VALUE; + canRemove = false; + next = tree.searchGTE(from); + if (next==null) { + cursor = 0; + currentMax = -1; + } else { + cursor = StrictMath.max(next.min, from); + currentMax = next.key; + next = tree.successor(next); + } + } + + public boolean hasNext() { + if (cursor > currentMax) { + if (next==null) return false; + this.cursor = next.min; + this.currentMax = next.key; + next = tree.successor(next); + } + return lastReturned= to + */ + DescendingIterator(int from, int to) { + endpoint = to; + lastReturned = Integer.MAX_VALUE; + canRemove = false; + next = tree.searchGTE(from); + if (next==null || next.min > from) { + next = tree.searchLTE(from); + if (next==null) { + cursor = -1; + currentMin = 0; + } else { + cursor = StrictMath.min(next.key, from); + currentMin = next.min; + } + } else { + cursor = StrictMath.min(next.key, from); + currentMin = next.min; + } + } + + public boolean hasNext() { + if (cursor < currentMin) { + if (next==null) return false; + this.cursor = next.key; + this.currentMin = next.min; + next = tree.predecessor(next); + } + return lastReturned>Integer.MIN_VALUE && cursor >= endpoint; + } + + public int next() { + if (!hasNext()) + throw new NoSuchElementException(); + canRemove = true; + return lastReturned = cursor--; + } + + public void remove() { + if (!canRemove) + throw new IllegalStateException(); + IntTreeSet.this.remove(lastReturned); + next = tree.searchLTE(cursor); + canRemove = false; + } + + } + + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntVector.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntVector.java new file mode 100644 index 00000000..0f2bc21c --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/IntVector.java @@ -0,0 +1,271 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + + +/** + * A resizable array of integers. + * + * @specfield length: int + * @specfield elements: [0..size) ->one int + * + * @author Emina Torlak + */ +public interface IntVector extends IntCollection { + /** + * Returns the number of elements in this vector. + * @return this.length + */ + public int size(); + + /** + * Returns true if this vector contains no elements. + * + * @return no this.elements + */ + public boolean isEmpty(); + + /** + * Returns true if this vector contains the specified element. + * @return element in this.elements[int] + */ + public boolean contains(int element); + + /** + * Returns the element at the specified position in this vector. + * + * @return this.elements[index] + * + * @throws IndexOutOfBoundsException if the index is out of range (index + * < 0 || index >= length()). + */ + public int get(int index); + + /** + * Returns an iterator over the elements in this vector in proper sequence. + * + * @return an iterator over the elements in this vector in proper sequence. + */ + public IntIterator iterator(); + + /** + * Returns an iterator over the elements in this vector in proper sequence, + * starting fromIndex<\tt>, inclusive, and ending at toIndex<\tt>, exclusive. + * If fromIndex<\tt> is less than toIndex<\tt>, then the iterator will return + * the elements in the descending order. + * @return an iterator over the elements in this vector in proper sequence, + * starting at fromIndex<\tt>, inclusive, and ending at toIndex<\tt>. + * @throws IndexOutOfBoundsException - fromIndex !in [0..this.length) || toIndex !in [-1..this.length] + */ + public IntIterator iterator(int fromIndex, int toIndex); + + /** + * Replaces the element at the specified position in this vector with the + * specified element, and returns the previous element (optional operation). + * + * @ensures this.elements' = this.elements' ++ index -> element + * @return this.elements[index] + * + * @throws UnsupportedOperationException if the set method is not + * supported by this vector. + * @throws IllegalArgumentException if some aspect of the specified + * element prevents it from being added to this vector. + * @throws IndexOutOfBoundsException if the index is out of range + * (index < 0 || index >= length()). + */ + public int set(int index, int element); + + /** + * Removes all of the elements from this vector (optional operation). This + * vector will be empty after this call returns (unless it throws an + * exception). + * @ensures this.length' = 0 && no this.elements' + * @throws UnsupportedOperationException if the clear method is + * not supported by this vector. + */ + public void clear(); + + /** + * Returns the index in this vector of the first occurrence of the specified + * element, or -1 if this vector does not contain this element. + * + * @return element in this.elements[int] => min(this.elements.element), -1 + */ + public int indexOf(int element); + + /** + * Returns the index in this vector of the last occurrence of the specified + * element, or -1 if this vector does not contain this element. + * + * @return element in this.elements[int] => max(this.elements.element), -1 + */ + public int lastIndexOf(int element); + + /** + * Adds the specified element to the end of this vector (optional + * operation), and returns true if this vector has changed as a result + * of the call. + * @ensures this.length' = this.length + 1 && this.elements' = this.elements + this.length -> element + * @return this.elements != this.elements' + * @throws UnsupportedOperationException if the add method is not supported by this vector. + * @throws IllegalArgumentException if some aspect of this element prevents it from being added to this vector. + */ + public boolean add(int element); + + /** + * Inserts the specified element at the specified position in this vector + * (optional operation), and returns true if this vector has changed as a result of the call. + * Shifts the element currently at that position + * (if any) and any subsequent elements to the right (adds one to their + * indices). + * + * @ensures this.length' = this.length + 1 && + * this.elements' = { i: [0..this.length'), e: int | i < index => e = this.elements[i], + * i = index => e = element, e = this.elements[i-1] } + * @throws UnsupportedOperationException if the add method is not + * supported by this vector. + * @throws IllegalArgumentException if some aspect of the specified + * element prevents it from being added to this vector. + * @throws IndexOutOfBoundsException if the index is out of range + * (index < 0 || index > length()). + */ + public void add(int index, int element); + + /** + * Appends the specified elements to the end of this vector (optional + * operation), and returns true if this vector has changed as a result of the call. + * @ensures appends the specified elements to the end of this vector + * @return this.elements != this.elements' + * @throws UnsupportedOperationException if the add method is not + * supported by this vector. + * @throws IllegalArgumentException if some aspect of an element in the given vector + * prevents it from being added to this vector. + */ + public boolean addAll(IntCollection c); + + /** + * Inserts the specified elements at the specified position in this vector + * (optional operation), and returns true if this vector has changed as a result of the call. + * Shifts the element currently at that position + * (if any) and any subsequent elements to the right. + * + * @ensures inserts the specified elements at the specified position in this vector + * @return this.elements != this.elements + * @throws UnsupportedOperationException if the add method is not + * supported by this vector. + * @throws IllegalArgumentException if some aspect of an element in the specified + * collection prevents it from being added to this vector. + * @throws IndexOutOfBoundsException if the index is out of range + * (index < 0 || index > length()). + */ + public boolean addAll(int index, IntCollection c); + + /** + * Removes the first occurrence of the given integer from this vector, + * and returns true if this vector has changed as a result of the call. + * @ensures removes the first occurrence of the given integer from this vector + * @return this.elements != this.elements' + * @throws UnsupportedOperationException - this is an unmodifiable collection + */ + public abstract boolean remove(int i); + + /** + * Removes the element at the specified position in this vector (optional + * operation). Shifts any subsequent elements to the left (subtracts one + * from their indices). Returns the element that was removed from the + * vector. + * @return this.elements[index] + * @ensures this.length' = this.length - 1 && + * this.elements' = { i: [0..this.length'), e: int | i < index => e = this.elements[i], + * e = this.elements[i+1] } + * @throws UnsupportedOperationException if the remove method is + * not supported by this vector. + * @throws IndexOutOfBoundsException if the index is out of range (index + * < 0 || index >= length()). + */ + public int removeAt(int index); + + /** + * Removes all of this vector's elements that are also contained in the specified + * collection. After this call returns, this collection will contain no elements in + * common with the specified collection. Returns true if this collection has changed as a result of the call. + * @ensures removes all of this vector's elements that are also contained in the specified + * collection + * @return this.elements != this.elements' + * @throws NullPointerException - c = null + * @throws UnsupportedOperationException - this is an unmodifiable collection + */ + public abstract boolean removeAll(IntCollection c); + + /** + * Retains only the elements in this vector that are contained in the specified + * collection. In other words, removes from this collection all of its elements that + * are not contained in the specified collection. Returns true if this collection has changed as a result of the call. + * @ensures retains only the elements in this vector that are contained in the specified + * collection + * @return this.elements != this.elements' + * @throws NullPointerException - c = null + * @throws UnsupportedOperationException - this is an unmodifiable collection + */ + public abstract boolean retainAll(IntCollection c); + + /** + * Compares the specified object with this vector for equality. Returns + * true if and only if the specified object is also an int vector, both + * vectors have the same size, and all corresponding pairs of elements in + * the two vectors are equal. + * + * @return true if the specified object is equal to this vector. + */ + public boolean equals(Object o); + + /** + * Returns the hash code value for this vector. The hash code of an int vector is + * defined to be the {@link Ints#superFastHash(int[])} of the elements in the vector, + * taken in the ascending order of indices. + * This ensures that v1.equals(v2) implies that v1.hashCode()==v2.hashCode() + * for any two IntVectors v1 and v2, as required by the general contract of the Object.hashCode method. + * @return Ints.superFastHash(this.toArray()) + */ + public int hashCode(); + + /** + * Returns an array containing all of the elements in this vector in proper + * sequence. + * + * @return an array containing all of the elements in this vector in proper + * sequence. + */ + public int[] toArray(); + + /** + * Copies the components of this vector into the specified array, provided that + * it is large enough, and returns it. The item at index + * k in this vector is copied into component k of the given array. If the + * given array is not large enough, the effect of this method is the same as + * calling {@linkplain #toArray()}. + * @ensures array.length>=this.length => all i: [0..this.length) | array'[i] = this.elements[i] + * @return array.length>=this.length => array' else this.toArray() + * @throws NullPointerException - array = null + */ + public int[] toArray(int[] array); +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/Ints.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/Ints.java new file mode 100644 index 00000000..6038825c --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/Ints.java @@ -0,0 +1,510 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import kodkod.util.ints.IntRange.OnePointRange; +import kodkod.util.ints.IntRange.TwoPointRange; + + +/** + * Contains various utility methods for working with + * integers, {@link kodkod.util.ints.IntRange IntRanges}, + * {@link kodkod.util.ints.IntSet IntSets}, and {@link kodkod.util.ints.SparseSequence SparseSequences}. + * + *

The methods in this class all throw a NullPointerException if + * given a null reference unless otherwise specified.

+ * + * @author Emina Torlak + */ +public final class Ints { + /** An immutable empty int set. The clone method returns the empty set itself. */ + public static final IntSet EMPTY_SET = + new AbstractIntSet() { + public boolean contains(int i) { return false; } + public int min() { throw new NoSuchElementException(); } + public int max() { throw new NoSuchElementException(); } + public IntIterator iterator(int from, int to) { + return new IntIterator() { + public boolean hasNext() { return false; } + public int next() { throw new NoSuchElementException(); } + public void remove() { throw new UnsupportedOperationException(); } + }; + } + public int size() { return 0; } + public int floor(int i) { throw new NoSuchElementException(); } + public int ceil(int i) { throw new NoSuchElementException(); } + public IntSet clone() { return EMPTY_SET;} + }; + + private Ints() {} + + /*-----------SETS AND RANGES-----------*/ + + /** + * Returns an integer range from min, inclusive, to max, inclusive. + * @return { r: IntRange | r.min = min && r.max = max } + * @throws IllegalArgumentException - min > max + */ + public static IntRange range(int min, int max) { + if (min < max) return new TwoPointRange(min,max); + else if (min==max) return new OnePointRange(min); + else throw new IllegalArgumentException("min > max"); + } + + /** + * Returns the smallest IntRange r that contains + * both r1 and r2. + * @return { r: IntRange | r.contains(r1) && r.contains(r2) && + * no r' : IntRange - r | r'.contains(r1) && r'.contains(r2) && r'.size() < r.size() } + * @throws NullPointerException - range = null + */ + public static IntRange merge(IntRange r1, IntRange r2) { + if (r1.contains(r2)) return r1; + else if (r2.contains(r1)) return r2; + else return range(StrictMath.min(r1.min(),r2.min()), StrictMath.max(r1.max(), r2.max())); + } + + /** + * Returns an unmodifiable view of the specified set. This method + * allows modules to provide users with "read-only" access to internal int sets. + * Query operations on the returned set "read through" to the specified set, and + * attempts to modify the returned set, whether direct or via its iterator, result + * in an UnsupportedOperationException. The clone() method of the returned set + * returns the result of calling s.clone(). + * @return an unmodifiable view of s + * @throws NullPointerException - s = null + */ + public static IntSet unmodifiableIntSet(final IntSet s) { + if (s==null) + throw new NullPointerException("s = null"); + else if (s instanceof UnmodifiableIntSet || s instanceof SingletonIntSet || s instanceof RangeIntSet) + return s; + else + return new UnmodifiableIntSet(s); + } + + /** + * Returns an unmodifiable IntSet whose sole + * element is the given integer. The clone method + * of the returned set returns the set itself. + * @return {s: IntSet | s.ints = i} + */ + public static IntSet singleton(final int i) { + return new SingletonIntSet(i); + } + + /** + * Returns an unmodifiable IntSet that contains + * all the elements in the given range. The clone + * method of the returned set returns the set itself. + * @return {s: IntSet | s.ints = [range.min()..range.max()] } + */ + public static IntSet rangeSet(IntRange range) { + if (range==null) + throw new NullPointerException(); + return new RangeIntSet(range); + } + + /** + * Returns an implementation of the int set interface + * that offers the best time/space trade-off for a + * set that can store all elements in the half open + * range [0..max). The returned instance may or may + * not admit elements out of the range [0..max). + * @return an int set that can store at least the + * elements in [0..max). + */ + public static IntSet bestSet(int max) { + // cut-off for using a bit map is 512 + return max > 512 ? new IntTreeSet() : new IntBitSet(max); + } + + /** + * Returns an implementation of the int set interface + * that offers the best time/space trade-off for a + * set that can store all elements in the closed range [min..max]. + * The returned instance may or may not admit elements + * out of the specified range. + * @return an int set that can store at least the + * elements in the given range. + * @throws IllegalArgumentException - min > max + */ + public static IntSet bestSet(int min, int max) { + if (min > max) throw new IllegalArgumentException("min > max"); + return min < 0 ? new IntTreeSet() : bestSet(max+1); + } + + /** + * Returns an IntSet that is backed by the given array of integers. + * The array must contain no duplicates, its elements must be sorted + * in the ascending order, and its contents + * must not be changed while it is in use by the returned set. + * @requires all i, j: [0..ints.length) | i < j => array[i] <= Sarray[j] + * @return an unmodifiable IntSet view of the given array + */ + public static IntSet asSet(int[] ints) { + return ints.length==0 ? EMPTY_SET : new ArrayIntSet(ints); + } + + /** + * Returns an unmodifiable IntArray backed by the given array of integers. + * @return an unmodifiable IntArray backed by the given array of integers. + */ + public static IntVector asIntVector(final int[] ints) { + return new AbstractIntVector() { + public int get(int index) { return ints[index]; } + public int size() { return ints.length; } + public int[] toArray(int[] array) { + if (array.length < ints.length) { + array = new int[ints.length]; + } + System.arraycopy(ints, 0, array, 0, ints.length); + return array; + } + }; + } + + /** + * Returns an unmodifiable IntArray of length n which contains the given + * element at each position. + * @return an unmodifiable IntArray of length n which contains the given + * element at each position + */ + public static IntVector nCopies(final int n, final int elt) { + return new AbstractIntVector() { + public int get(int index) { + if (index < 0 || index >= n) throw new IndexOutOfBoundsException(); + return elt; + } + public int size() { return n; } + public int[] toArray(int[] array) { + if (array.length < n) { + array = new int[n]; + } + for(int i = 0; i < n; i++) { array[i] = elt; } + return array; + } + }; + } + + /*-----------SEQUENCES-----------*/ + /** + * Returns an unmodifiable view of the specified sparse sequence. This method + * allows modules to provide users with "read-only" access to internal sparse sequences. + * Query operations on the returned sequence "read through" to the specified sequence, and + * attempts to modify the returned sequence, whether direct or via its iterator, result + * in an UnsupportedOperationException. The clone() method of the returned sequence + * returns the result of calling s.clone(). + * @return an unmodifiable view of s + * @throws NullPointerException - s = null + */ + public static SparseSequence unmodifiableSequence(SparseSequence s) { + if (s==null) + throw new NullPointerException(); + if (s instanceof UnmodifiableSparseSequence) + return s; + else return new UnmodifiableSparseSequence(s); + } + + /*-----------INTEGER MANIPULATION-----------*/ + + /** + * Returns an integer whose value is the 16 low order bits of the given key. + * @return key & 0x0000ffff + */ + private static int low16(int key) { + return key & 0x0000ffff; + } + + /** + * Returns an integer whose value is the 16 high order bits of the given key. + * @return (key >>> 16) & 0x0000ffff + */ + private static int high16(int key) { + return low16(key>>>16); + } + + /** + * Performs the bit avalanching step of Paul Hsieh's + * hashing function (http://www.azillionmonkeys.com/qed/hash.html) + * @return the bit avalanched version of the given hash value + */ + public static int superFastHashAvalanche(int hash) { + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; + } + + /** + * Performs the hashing step of Paul Hsieh's hashing function, + * described at http://www.azillionmonkeys.com/qed/hash.html. + * The method returns a 32 bit hash of the given integer, starting + * with the given initial hash. This method does not perform + * bit avalanching. To get the full hash, call {@linkplain #superFastHashAvalanche(int)} + * on the value returned by this method. + * @return a 32 bit hash of the given integer, based on the given hash + */ + public static int superFastHashIncremental(int key, int hash) { + + hash += low16(key); + final int tmp = (high16(key) << 11) ^ hash; + hash = (hash << 16) ^ tmp; + hash += hash >> 11; + + // no end cases since the key has exactly 4 bytes + return hash; + } + + /** + * An implementation of Paul Hsieh's hashing function, + * described at http://www.azillionmonkeys.com/qed/hash.html. + * The method returns a 32 bit hash of the given integer. + * This function is very fast and collision resistent; e.g. + * it hashes the four million integers in the range + * [-2000000,...-1, 1,..., 2000000] to distinct values. + * The initial hash is taken to be 11. + * @return a 32 bit hash of the given integer + */ + public static int superFastHash(int key) { + return superFastHashAvalanche(superFastHashIncremental(key, 11)); + } + + /** + * An implementation of Paul Hsieh's hashing function, + * described at http://www.azillionmonkeys.com/qed/hash.html. + * The method returns a 32 bit hash of the given integers, + * or 0 if the array is empty. The initial hash is taken to be + * the number of keys. + * @return a 32 bit hash of the given integers + */ + public static int superFastHash(int... key) { + if (key.length==0) return 0; + int hash = key.length; + + for(int word : key) { + hash = superFastHashIncremental(word, hash); + } + // no end cases since key parts are ints + return superFastHashAvalanche(hash); + } + + /** + * An implementation of Paul Hsieh's hashing function, + * described at http://www.azillionmonkeys.com/qed/hash.html. + * The method returns a 32 bit hash of the given objects' hash codes, + * or zero if the array is empty. Any null references in the array + * are taken to have 0 as their hash code value. + * @return a 32 bit hash of the given objects' hashCodes + */ + public static int superFastHash(Object... key) { + if (key.length==0) return 0; + int hash = key.length; + + for(Object o : key) { + hash = superFastHashIncremental(o == null ? 0 : o.hashCode(), hash); + } + // no end cases since the hashcodes of key parts are ints + return superFastHashAvalanche(hash); + } + + /** + * An implementation of an IntSet wrapper for an IntRange. + */ + private static final class RangeIntSet extends AbstractIntSet { + private final IntRange range; + /** + * Constructs an unmodifiable IntSet wrapper for a range. + */ + RangeIntSet(IntRange range) { + this.range = range; + } + public boolean contains(int i) { return range.contains(i); } + public int min() { return range.min(); } + public int max() { return range.max(); } + public IntIterator iterator(final int from, final int to) { + return new IntIterator() { + final boolean ascending = (from <= to); + long cursor = ascending ? StrictMath.max(range.min(), from) : StrictMath.min(range.max(), from); + final int end = ascending ? StrictMath.min(range.max(), to) : StrictMath.max(range.min(), to); + public boolean hasNext() { + return ascending && cursor<=end || !ascending && cursor >= end; + } + public int next() { + if (!hasNext()) throw new NoSuchElementException(); + return ascending ? (int)cursor++ : (int)cursor--; + } + public void remove() { throw new UnsupportedOperationException(); } + + }; + } + public int size() { return range.size(); } + public IntSet copy() { return this; } + public int floor(int i) { + if (irange.max()) + throw new NoSuchElementException(); + return StrictMath.max(i, range.min()); + } + public IntSet clone() { return this; } + } + + /** + * An implementation of an IntSet wrapper for a single integer. + */ + private static final class SingletonIntSet extends AbstractIntSet { + private final int i; + /** + * Constructs an unmodifiable intset wrapper for the given integer. + */ + SingletonIntSet(int i) { + this.i = i; + } + public boolean contains(int j) { return i==j; } + public int min() { return i; } + public int max() { return i; } + public IntIterator iterator(final int from, final int to) { + return new IntIterator() { + boolean cursor = (from<=i && i<=to) || (to<=i && i<=from); + public boolean hasNext() { return cursor; } + public int next() { + if (!hasNext()) throw new NoSuchElementException(); + cursor = false; + return i; + } + public void remove() { throw new UnsupportedOperationException(); } + }; + } + public int size() { return 1; } + public IntSet copy() { return this; } + public boolean equals(Object o) { + if (this==o) return true; + else if (o instanceof IntSet) { + final IntSet s = (IntSet) o; + return s.size()==1 && s.min()==i; + } else + return super.equals(o); + } + public int hashCode() { return i; } + public int floor(int j) { + if (i<=j) return i; + else throw new NoSuchElementException(); + } + public int ceil(int j) { + if (i>=j) return i; + else throw new NoSuchElementException(); + } + public IntSet clone() { return this; } + } + + /** + * An implementation of an unmodifiable IntSet view. + * @author Emina Torlak + */ + private static final class UnmodifiableIntSet extends AbstractIntSet { + private final IntSet s; + + /** + * Constructs an unmodifiable wrapper for the given intset. + * @requires set != null + */ + UnmodifiableIntSet(IntSet set) { + this.s = set; + } + public int size() { return s.size(); } + public boolean contains(int i) { return s.contains(i); } + public int min() { return s.min(); } + public int max() { return s.max(); } + public boolean containsAll(IntSet other) { return s.containsAll(other ); } + public IntIterator iterator(final int from, final int to) { + return new IntIterator() { + IntIterator iter = s.iterator(from,to); + public boolean hasNext() { return iter.hasNext(); } + public int next() { return iter.next(); } + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + public int floor(int i) { return s.floor(i); } + public int ceil(int i) { return s.ceil(i); } + public IntSet clone() throws CloneNotSupportedException { return s.clone(); } + } + + /** + * An implementation of an unmodifiable SparseSequence view. + * @author Emina Torlak + */ + private static final class UnmodifiableSparseSequence extends AbstractSparseSequence { + private final SparseSequence s; + + UnmodifiableSparseSequence(SparseSequence s) { + this.s = s; + } + + public Iterator> iterator(final int from, final int to) { + return new Iterator>() { + Iterator> iter = s.iterator(from, to); + public boolean hasNext() { + return iter.hasNext(); + } + + public IndexedEntry next() { + return iter.next(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + }; + } + + public int size() { return s.size(); } + public void clear() { throw new UnsupportedOperationException(); } + public V put(int index, V value) { throw new UnsupportedOperationException(); } + public V get(int index) { return s.get(index); } + public V remove(int index) { throw new UnsupportedOperationException(); } + public IndexedEntry first() { return s.first(); } + public IndexedEntry last() { return s.last(); } + + public IndexedEntry ceil(int index) { return s.ceil(index); } + public IndexedEntry floor(int index) { return s.floor(index); } + public boolean containsIndex(int index) { return s.containsIndex(index); } + public boolean contains(Object value) { return s.contains(value); } + + public SparseSequence clone() throws CloneNotSupportedException { + return s.clone(); + } + + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/RangeSequence.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/RangeSequence.java new file mode 100644 index 00000000..e7f5580b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/RangeSequence.java @@ -0,0 +1,614 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + *

A tree-based sparse sequence implementation. Unlike {@link kodkod.util.ints.TreeSequence}, + * this is not a general-purpose sparse sequence implementation. In particular, + * the entries with consecutive indices and the same value are not stored explicitly. As a result, + * methods + * that return an {@link kodkod.util.ints.IndexedEntry} may re-use the same object. + * Specifically, the last assertion in the following code snippet may fail.

+ *
+ * // let s be a range sequence abstractly represented as { 0->v, 1->v, 2->v }
+ * IndexedEntry e1 = s.predecessor(2);
+ * assert e1.index()==1; // this will work
+ * IndexedEntry e2 = s.predecessor(1);
+ * assert e1.index()==1; // this may fail, as e1 may be == to e2
+ * 
+ *

The entries returned by this implementation's {@link #iterator()} are unique + * to that iterator (but not necessarily independent of each other). For example,

+ *
+ * // let s be a range sequence abstractly represented as { 0->v, 1->v, 2->v }
+ * Iterator> iter1 = s.iterator();
+ * IndexedEntry e1 = iter1.next();
+ * assert e1.index()==0; // this will work
+ * iter1.next();
+ * assert e1.index()==0; // this may fail, as the previous call may have changed the state of e1
+ * Iterator> iter2 = s.iterator();
+ * IndexedEntry e2 = iter2.next();
+ * iter1.next();
+ * assert e2.index()==0; // this will work
+ * 
+ *

This implementation is a good choice when the client expects the usage pattern with many consecutive + * indices mapped to the same value, and when there is no need for entry uniqueness.

+ * @author Emina Torlak + */ +public final class RangeSequence extends AbstractSparseSequence implements Cloneable { + /* The ranges are sorted by their right endpoints. All consecutive indices + * that map to the same value are represented by a single range node. + * @invariant (all n: tree.nodes | n.max = n.key && n.min <= n.max) && + * (no disj n, n': tree.nodes | n.value=n'.value && n.max = n'.min-1) + */ + private final IntTree> tree; + private final EntryView view; + private int size; + + /** + * Constructs an empty RangeSequence. + * @ensures no this.entries' + */ + public RangeSequence() { + view = new EntryView(Integer.MIN_VALUE,null); + tree = new IntTree>(); + size = 0; + } + + /** + * Copy constructor. + * @ensures creatres a deep copy of the original + */ + @SuppressWarnings("unchecked") + private RangeSequence(RangeSequence original) { + this.size = original.size; + try { + this.tree = original.tree.clone(); + } catch (CloneNotSupportedException e) { + throw new InternalError(); // unreachable code; + } + view = new EntryView(Integer.MIN_VALUE,null); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#iterator(int, int) + */ + public Iterator> iterator(int from, int to) { + return from <= to ? new AscendingIterator(from, to) : new DescendingIterator(from, to); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#size() + */ + public int size() { + return size; + } + + /** + * Removes all entries from this sequences. + * @ensures no this.entries' + * @see kodkod.util.ints.SparseSequence#clear() + */ + public void clear() { + tree.clear(); + size = 0; + } + + /** + * Returns true if e is the head of a contiguous homogenous + * sequence starting with the mapping e.min->e.value and + * ending with the mapping index->value. + * @return e!=null index-1 = e.key && equal(value, e.value) + */ + private boolean isHeadOf(Entry e, int index, V value){ + return e!=null && e.key==index-1 && equal(e.value, value); + } + + /** + * Returns true if e is the tail of a contiguous homogenous + * sequence starting with the mapping index->value and + * ending with the mapping e.max->e.value. + * @return e!=null && index+1 = e.min && equal(value, e.value) + */ + private boolean isTailOf(Entry e, int index, V value) { + return e!=null && e.min()==index+1 && equal(e.value, value); + } + + + /** + * Merges the mapping index->value into its floor or ceiling, if + * possible. Otherwise creates a new node for index->value and + * inserts into the tree. + * @requires index !in this.nodes.key + * @requires f = searchLTE(index) && c = searchGTE(index) + * @ensures this.entries' = this.entries + index->value + */ + private void merge(int index, V value, Entry f, Entry c) { + if (isHeadOf(f, index, value)) { + if (f.isPoint()) { + if (isTailOf(c, index, value)) { + if (c.isPoint()) { // [f: 0->a][i: 1->a][c: 2->a] ---> [{0,1,2}->a] + tree.delete(c); + tree.replace(f, new Range(f.key, c.key, value)); + } else { // [f: 0->a][i: 1->a][c: {2,3}->a] ---> [c: {0,1,2,3}->a] + tree.delete(f); + ((Range)c).min = f.key; + } + } else { // [f: 0->a][i: 1->a] ---> [{0,1}->a] + tree.replace(f, new Range(f.key, index, value)); + } + } else { + if (isTailOf(c, index, value)) { // [f: {-1,0}->a][i: 1->a][c: 2->a] ---> [f: {-1,0,1,2}->a] + tree.delete(c); + f.key = c.key; + } else { // [f: {-1,0}->a][i: 1->a] ---> [f: {0,1,2}->a] + f.key = index; + } + } + } else if (isTailOf(c, index, value)) { + if (c.isPoint()) { // [i: 1->a][c: 2->a] ---> [{1,2}->a] + tree.replace(c, new Range(index, c.key, value)); + } else { // [i: 1->a][c: {2,3}->a] ---> [c: {1,2,3}->a] + ((Range)c).min = index; + } + } else { // can't merge anything + tree.insert(new Point(index,value)); + } + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#put(int, Object) + */ + public V put(int index, V value) { + Entry c = tree.searchGTE(index); + if (c==null || c.min() > index) { // we are adding a new index + size++; + merge(index, value, tree.searchLTE(index), c); + return null; + } else { // the index already exists + if (equal(value, c.value)) { + return value; // nothing to do + } else if (c.isPoint()) { + if (isHeadOf(tree.predecessor(c), index, value) || + isTailOf(tree.successor(c), index, value)) { + final V oldVal = remove(index); + put(index, value); + return oldVal; + } + return c.setValue(value); + } else { // split the range + final V oldVal = split(index, c); + tree.insert(new Point(index,value)); + return oldVal; + } + } + + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#get(int) + */ + public V get(int index) { + final Entry e = tree.searchGTE(index); + return e==null || e.min() > index ? null : e.value; + } + + /** + * Splits the z entry into the least number of entries + * that do not contain the given index. + * @requires z.min() <= index <= z.max() + * @requires z != NIL + * @ensures this.entries' = this.entries' - index->V + * @return z.value + */ + private V split(int index, Entry z) { + final V val = z.value; + if (z.isPoint()) + tree.delete(z); + else { // z contains a range of keys + final Range r = (Range) z; + final int min = r.min, max = r.key; + if (min==index) { + if (min+1(max, val)); + } else if (max==index) { + if (max-1>min) + r.key--; + else + tree.replace(r, new Point(min, val)); + } else { // index is between min and max + if (min==index-1) { + tree.replace(r, new Point(index-1, val)); + if (max==index+1) { + tree.insert(new Point(max, val)); + } else { + r.min = index+1; + tree.insert(r); + } + } else { + r.key = index-1; + if (max==index+1) { + tree.insert(new Point(max, val)); + } else { + tree.insert(new Range(index+1, max, val)); + } + } + } + } + return val; + } + + /** + * Removes the entry with the given index, if it exists, and + * returns the value previously stored at the index. If the + * sequence had no previous mapping for the index, null is returned. + * @ensures this.entries' = this.entries - index->E + * @return this.entries[index] + * @see kodkod.util.ints.SparseSequence#remove(int) + */ + public V remove(int index) { + final Entry z = tree.searchGTE(index); + if (z==null || index < z.min()) return null; + size--; + return split(index,z); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#containsIndex(int) + */ + public boolean containsIndex(int index) { + final Entry e = tree.searchGTE(index); + return e != null && e.min() <= index; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#first() + */ + public IndexedEntry first() { + final Entry e = tree.min(); + return e==null ? null : view.setView(e.min(), e.value); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#last() + */ + public IndexedEntry last() { + final Entry e = tree.max(); + return e==null ? null : view.setView(e.max(), e.value); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#ceil(int) + */ + public IndexedEntry ceil(int index) { + final Entry e = tree.searchGTE(index); + return e == null ? null : view.setView(StrictMath.max(index, e.min()), e.value); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#floor(int) + */ + public IndexedEntry floor(int index) { + Entry e = tree.searchGTE(index); + if (e==null || e.min() > index) { + e = tree.searchLTE(index); + return e == null ? null : view.setView(e.max(), e.value); + } else + return view.setView(index, e.value); + } + + /** + * Returns a copy of this sparse sequence. The copy is independent of this + * sequence. + * @return a copy of this sparse sequence. + * @see kodkod.util.ints.SparseSequence#clone() + */ + @SuppressWarnings("unchecked") + public RangeSequence clone() { + // ok to use copy constructor to clone a final class + return new RangeSequence(this); + + } + + /** + * A mapping from range of integers in to a value + * @specfield min: int + * @specfield max: int + * @specfield value: V + * @invariant min <= max + * @invariant max = key + * @author Emina Torlak + */ + private static abstract class Entry extends IntTree.Node> implements Cloneable { + V value; + + Entry(int max, V value) { + super(max); + this.value = value; + } + + V setValue(V newValue) { + final V oldValue = value; + value = newValue; + return oldValue; + } + + /** + * Returns the minimum of this. + * @return this.min + */ + abstract int min(); + + /** + * Returns the maximum of this. + * @return this.max + */ + final int max() { return key; } + + /** + * Return true if this.min=this.max + * @return this.min = this.max + */ + abstract boolean isPoint(); + + /** + * {@inheritDoc} + * @throws CloneNotSupportedException + * @see java.lang.Object#clone() + */ + @SuppressWarnings("unchecked") + protected Entry clone() throws CloneNotSupportedException { + return (Entry) super.clone(); + } + } + + /** + * A point entry in a range sequence. + * @specfield min: int + * @specfield max: int + * @specfield value: V + * @specfield index: [min..max] + * @invariant min = max + */ + private static final class Point extends Entry { + /** + * Constructs an entry with the given index and value. + * @ensures this.index' = index && this.value' = value + * @ensures this.min' = this.max' = index + */ + Point(int index, V value) { + super(index, value); + } + + @Override + int min() { return key; } + + @Override + boolean isPoint() { return true; } + + @SuppressWarnings("unchecked") + protected Point clone() throws CloneNotSupportedException { + return (Point) super.clone(); + } + } + + /** + * A range entry in a range sequence. + * @specfield min: int + * @specfield max: int + * @specfield value: V + * @invariant min < max + */ + private static final class Range extends Entry { + int min; + + /** + * Constructs an entry with the given min/max and value. + * @ensures this.index' = min && this.value' = value + * @ensures this.min' = min && this.max' = max + */ + Range(int min, int max, V value) { + super(max, value); + this.min = min; + } + + @Override + int min() { return min; } + + @Override + boolean isPoint() { return false; } + + @SuppressWarnings("unchecked") + protected Range clone() throws CloneNotSupportedException { + return (Range) super.clone(); + } + } + + /** + * An iterator over the entries in this sequence. + */ + private abstract class EntryIterator implements Iterator>, IndexedEntry { + final int endIndex; + int endpoint, cursor, index; + boolean canRemove; + Entry next; + V value; + + /** + * @ensures this.endIndex' = endIndex && canRemove = false; + */ + EntryIterator(int endIndex) { + this.endIndex = endIndex; + this.canRemove = false; + } + + public final int index() { return index; } + public final V value() { return value; } + + public final boolean equals(Object o) { + if (o==this) return true; + if (!(o instanceof IndexedEntry)) return false; + return AbstractSparseSequence.equal(this, (IndexedEntry)o); + } + + public final int hashCode() { + return AbstractSparseSequence.hashCode(this); + } + + public final String toString() { + return index + "=" + value; + } + } + + /** + * An iterator that returns the entries in this sequence + * in the ascending order of indices. + * + * @author Emina Torlak + */ + private final class AscendingIterator extends EntryIterator { + + /** + * Constructs an ascending iterator over the entries with + * indeces between from and to. + * @requires from <= to + */ + @SuppressWarnings("unchecked") + AscendingIterator(int from, int to) { + super(to); + next = tree.searchGTE(from); + index = Integer.MIN_VALUE; + if (next==null) { + cursor = 0; + endpoint = -1; + value = null; + } else { + cursor = StrictMath.max(next.min(), from); + endpoint = next.key; + value = next.value; + next = tree.successor(next); + } + } + + public boolean hasNext() { + if (cursor > endpoint) { + if (next==null) return false; + this.cursor = next.min(); + this.endpoint = next.key; + this.value = next.value; + next = tree.successor(next); + } + return index next() { + if (!hasNext()) + throw new NoSuchElementException(); + index = cursor++; + canRemove = true; + return this; + } + + public void remove() { + if (!canRemove) + throw new IllegalStateException(); + RangeSequence.this.remove(index); + next = tree.searchGTE(cursor); + canRemove = false; + } + } + + /** + * An iterator that returns the entries in this sequence + * in the descending order of indices. + * + * @author Emina Torlak + */ + private final class DescendingIterator extends EntryIterator { + + /** + * Constructs a descending iterator over the entries with + * indeces between from and to. + * @requires from >= to + */ + DescendingIterator(int from, int to) { + super(to); + next = tree.searchGTE(from); + index = Integer.MAX_VALUE; + if (next==null || next.min() > from) { + next = tree.searchLTE(from); + if (next==null) { + cursor = -1; + endpoint = 0; + value = null; + } else { + cursor = next.key; + endpoint = next.min(); + value = next.value; + } + } else { + cursor = StrictMath.min(next.key, from); + endpoint = next.min(); + value = next.value; + next = tree.predecessor(next); + } + } + + public boolean hasNext() { + if (cursor < endpoint) { + if (next==null) return false; + this.cursor = next.key; + this.endpoint = next.min(); + this.value = next.value; + next = tree.predecessor(next); + } + return index>Integer.MIN_VALUE && cursor >= endIndex; + } + public IndexedEntry next() { + if (!hasNext()) + throw new NoSuchElementException(); + index = cursor--; + canRemove = true; + return this; + } + public void remove() { + if (!canRemove) + throw new IllegalStateException(); + RangeSequence.this.remove((int) index); + next = tree.searchLTE((int)cursor); + canRemove = false; + } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/SparseSequence.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/SparseSequence.java new file mode 100644 index 00000000..57766e35 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/SparseSequence.java @@ -0,0 +1,224 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + +import java.util.Collection; +import java.util.Iterator; + +/** + *

Represents a sparse sequence -- a sequence whose indices are not + * necessarily contiguous. For example, a sparse sequence can have + * elements at indices 10, 2121, and 3000, without having any elements + * in between. This specification of sparse sequences also supports + * negative indeces. Formally, the following methods specify a partial + * function from integers to values of type V.

+ * + *

Sequence implementations are not required to support mutation. + * All mutating operations are optional and may + * throw an UnsupportedOperationException.

+ * + * @specfield entries: int -> lone V + * + * @author Emina Torlak + */ +public interface SparseSequence extends Iterable> { + + /** + * Returns the number of entries in this sequence. + * @return #this.entries + */ + public abstract int size(); + + /** + * Returns true if this sequence is empty; otherwise returns false. + * @return no this.entries + */ + public abstract boolean isEmpty(); + + /** + * Removes all entries from this sequences. + * @ensures no this.entries' + */ + public abstract void clear(); + + /** + * Puts the given value at the specified index. If the + * sequence already mapped the index to a value, the + * previous value is replaced with the new one and returned. + * + * @ensures this.entries' = this.entries + index->value + * @return this.entries[index] + * @throws IndexOutOfBoundsException - the given index + * is not valid for this sequence. + * @throws IllegalArgumentException - the given value cannot + * be stored in this sequence. + */ + public abstract V put(int index, V value); + + /** + * Copies all of the entries from the specified sparse sequence to + * this sequence. The effect of this call is equivalent to that of + * calling put(e.index, e.value) on this sequence once for each entry + * e in the specified sequence. + * @ensures this.entries' = this.entries ++ s.entries + * @throws IndexOutOfBoundsException - s contains indeces that are + * not valid for this sequence. + * @throws IllegalArgumentException - s contains a value that cannot + * be stored in this sequence. + */ + public abstract void putAll(SparseSequence s); + + + /** + * Returns the value to which this sequence maps the given + * index. If the index is not mapped, null is returned. + * @return this.entries[index] + */ + public abstract V get(int index); + + /** + * Removes the entry with the given index, if it exists, and + * returns the value previously stored at the index. If the + * sequence had no previous mapping for the index, null is returned. + * @ensures this.entries' = this.entries - index->E + * @return this.entries[index] + */ + public abstract V remove(int index); + + /** + * Returns true if this sparse sequence has an entry for the + * given index; otherwise returns false. + * @return some this.entries[index] + */ + public abstract boolean containsIndex(int index); + + /** + * Returns the set of all indices mapped by this sparse sequence. + * The returned set supports removal iff this is not an unmodifiable + * sparse sequence. The returned set may be uncloneable. + * @return {s: IntSet | s.ints = this.entries.V} + */ + public abstract IntSet indices(); + + /** + * Returns true if this sequence has an entry with the given value; + * otherwise returns false. + * @return some this.entries.value + */ + public abstract boolean contains(Object value); + + /** + * Returns a Collection view of the values stored in this sequence. + * The returned collection supports removal iff this is not an + * unmodifiable sparse sequence. + * @return {c: Collection | c.size()=this.size() && + * all v: V | c.contains(v) <=> this.contains(v) } + */ + public abstract Collection values(); + + /** + * Returns an iterator over the entries in this sequence + * in the ascending order of indeces, starting at this.first(). + * @return an iterator over this.entries starting at the entry + * with the smallest index + */ + public abstract Iterator> iterator(); + + /** + * Returns an iterator over the entries in this sequence, + * whose indeces are between from and to. If from < to, + * the entries are returned in the ascending order of + * indeces. Otherwise, they are returned in the descending + * order of indeces. + * @return an iterator over the entries in this sequence + * whose indeces are between from and to. Formally, if + * from < to, then the first and last entries returned + * by the iterator are this.ceil(from) and this.floor(to). + * Otherwise, they are this.floor(from) and this.ceil(to). + */ + public abstract Iterator> iterator(int from, int to); + + /** + * Returns the entry with the smallest index. If the sequence + * is empty, returns null. + * @return {e: IndexedEntry | e.index = min(this.entries.E) && + * e.value = this.entries[e.index] } + */ + public abstract IndexedEntry first(); + + /** + * Returns the entry with the largest index. If the sequence + * is empty, returns null. + * @return {e: IndexedEntry | e.index = max(this.entries.E) && + * e.value = this.entries[e.index] } + */ + public abstract IndexedEntry last(); + + /** + * If an entry for the given index exists, it is returned. Otherwise, + * successor(index) is returned. + * @return this.containsIndex(index) => + * {e: IndexedEntry | e.index = index && e.value = this.entries[index] }, + * successor(index) + */ + public abstract IndexedEntry ceil(int index); + + /** + * If an entry for the given index exists, it is returned. Otherwise, + * predecessor(index) is returned. + * @return this.containsIndex(index) => + * {e: IndexedEntry | e.index = index && e.value = this.entries[index] }, + * predecessor(index) + */ + public abstract IndexedEntry floor(int index); + + /** + * Compares the specified object with this sequence for equality. + * Returns true if the given object is also a sparse sequence and the two + * sequences have the same entries. More formally, two sequences t1 and t2 have the + * the same entries if they represent the same function from integers to values: i.e. + * t1.entries = t2.entries. This ensures that the equals method works properly across + * different implementations of the SparseSequence interface. + * @return o in SparseSequence && o.entries = this.entries + */ + public abstract boolean equals(Object o); + + /** + * Returns the hash code value for this sparse sequence. + * A hash function for a sparse sequence must ensure that t1.equals(t2) + * implies that t1.hashCode()==t2.hashCode() for any two sequences t1 and t2, + * as required by the general contract of Object.hashCode. + * @return hash code for this sparse sequence + */ + public abstract int hashCode(); + + /** + * Returns a copy of this sparse sequence. The copy is independent of this + * sequence unless this is a singleton or immutable, in which case + * clone() may return this. An implementing class that does not support + * cloning may throw a CloneNotSupportedException. + * @return a copy of this sparse sequence. + * @throws CloneNotSupportedException - this is not cloneable + */ + public abstract SparseSequence clone() throws CloneNotSupportedException; + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/TreeSequence.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/TreeSequence.java new file mode 100644 index 00000000..0acb2a27 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/ints/TreeSequence.java @@ -0,0 +1,335 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.ints; + +import java.util.Iterator; +import java.util.NoSuchElementException; + + +/** + * An implementation of a sparse sequence based on a + * balanced binary search tree. + * + * @author Emina Torlak + */ +public final class TreeSequence extends AbstractSparseSequence + implements Cloneable { + private final IntTree> tree; + private int size; + /** + * Constructs an empty tree sequence. + * @ensures no this.entries' + */ + public TreeSequence() { + tree = new IntTree>(); + size = 0; + } + + /** + * Copy constructor. + * @ensures creatres a deep copy of the original + */ + @SuppressWarnings("unchecked") + private TreeSequence(TreeSequence original) { + this.size = original.size; + try { + this.tree = original.tree.clone(); + } catch (CloneNotSupportedException e) { + throw new InternalError(); // unreachable code; + } + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#iterator(int, int) + */ + public Iterator> iterator(int from, int to) { + return from <= to ? new AscendingIterator(from, to) : new DescendingIterator(from, to); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#size() + */ + public int size() { + return size; + } + + /** + * Removes all entries from this sequences. + * @ensures no this.entries' + * @see kodkod.util.ints.SparseSequence#clear() + */ + public void clear() { + tree.clear(); + size = 0; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#put(int, Object) + */ + public V put(int index, V value) { + final Entry e = tree.search(index); + if (e==null) { + size++; + tree.insert(new Entry(index, value)); + return null; + } else { + return e.setValue(value); + } + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#get(int) + */ + public V get(int index) { + final Entry e = tree.search(index); + return e==null ? null : e.value; + } + + /** + * Removes the entry with the given index, if it exists, and + * returns the value previously stored at the index. If the + * sequence had no previous mapping for the index, null is returned. + * @ensures this.entries' = this.entries - index->E + * @return this.entries[index] + * @see kodkod.util.ints.SparseSequence#remove(int) + */ + public V remove(int index) { + final Entry e = tree.search(index); + if (e==null) + return null; + else { + size--; + tree.delete(e); + return e.value; + } + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#containsIndex(int) + */ + public boolean containsIndex(int index) { + return tree.search(index) != null; + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#first() + */ + public IndexedEntry first() { + return tree.min(); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#last() + */ + public IndexedEntry last() { + return tree.max(); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#ceil(int) + */ + public IndexedEntry ceil(int index) { + return tree.searchGTE(index); + } + + /** + * {@inheritDoc} + * @see kodkod.util.ints.SparseSequence#floor(int) + */ + public IndexedEntry floor(int index) { + return tree.searchLTE(index); + } + + /** + * Returns a copy of this sparse sequence. The copy is independent of this + * sequence. + * @return a copy of this sparse sequence. + * @see kodkod.util.ints.SparseSequence#clone() + */ + @SuppressWarnings("unchecked") + public TreeSequence clone() { + // ok to use copy constructor to clone a final class + return new TreeSequence(this); + + } + +// public String toString() { +// return tree.toString(); +// } + + private static final class Entry extends IntTree.Node> implements IndexedEntry, Cloneable { + V value; + + Entry(int key, V value) { + super(key); + this.value = value; + } + + public int index() { + return key; + } + + public V value() { + return value; + } + + /** + * Sets this.value to the given value and returns the previous value. + * @ensures this.value' = value + * @requires this.value + */ + V setValue(V value) { + V oldValue = this.value; + this.value = value; + return oldValue; + } + + public boolean equals(Object o) { + if (o==this) return true; + if (!(o instanceof IndexedEntry)) return false; + return AbstractSparseSequence.equal(this, (IndexedEntry)o); + } + + public int hashCode() { + return AbstractSparseSequence.hashCode(this); + } + + public String toString() { + return key + "=" + value; + } + + @SuppressWarnings("unchecked") + protected Entry clone() throws CloneNotSupportedException { + return (Entry)super.clone(); + } + } + + + private abstract class EntryIterator implements Iterator> { + final int endIndex; + Entry lastReturned ; + Entry next; + + /** + * Constructs a tree iterator which traverses the tree starting at + * the given Entry in either descending or ascending order, depending + * on whether start.index is greater than endIndex. + */ + EntryIterator(Entry start, int endIndex) { + this.next = start; + this.lastReturned = null; + this.endIndex = endIndex; + } + + /** + * Advances the next pointer to its successor, + * if this is an ascending iterator or to + * its predecessor, if this is a descending iterator. + * @requires next != NIL + */ + abstract void advance(); + + public abstract boolean hasNext(); + + public IndexedEntry next() { + if (!hasNext()) + throw new NoSuchElementException(); + lastReturned = next; + advance(); + return lastReturned; + } + + public final void remove() { + if (lastReturned == null) + throw new IllegalStateException(); + if (next==null) { + TreeSequence.this.remove(lastReturned.key); + } else { + final int nextIndex = next.key; + TreeSequence.this.remove(lastReturned.key); + // necessary since the structural modifications made by the delete + // procedure may affect the next pointer + next = tree.search(nextIndex); + } + lastReturned = null; + } + } + + private final class AscendingIterator extends EntryIterator { + /** + * Constructs an ascending iterator over the entries with + * indeces between from and to. + * @requires from <= to + */ + AscendingIterator(int from, int to) { + super(tree.searchGTE(from),to); + } + /** + * Sets next to its successor. + */ + final void advance() { + next = tree.successor(next); + } + + /** + * Returns true if next != NIL and its index is less + * than or equal to the ending index. + */ + public boolean hasNext() { + return next != null && next.key<=endIndex; + } + } + + private final class DescendingIterator extends EntryIterator { + /** + * Constructs a descending iterator over the entries with + * indeces between from and to. + * @requires from >= to + */ + DescendingIterator(int from, int to) { + super(tree.searchLTE(from),to); + } + /** + * Sets next to its predecessor. + */ + final void advance() { + next = tree.predecessor(next); + } + + /** + * Returns true if next != NIL and its index is greater + * than or equal to the ending index. + */ + public boolean hasNext() { + return next != null && next.key>=endIndex; + } + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/nodes/AnnotatedNode.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/nodes/AnnotatedNode.java new file mode 100644 index 00000000..73507c16 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/nodes/AnnotatedNode.java @@ -0,0 +1,533 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.nodes; + +import static kodkod.ast.RelationPredicate.Name.ACYCLIC; +import static kodkod.ast.RelationPredicate.Name.FUNCTION; +import static kodkod.ast.RelationPredicate.Name.TOTAL_ORDERING; +import static kodkod.ast.operator.FormulaOperator.AND; +import static kodkod.ast.operator.FormulaOperator.IMPLIES; +import static kodkod.ast.operator.FormulaOperator.OR; + +import java.util.Collections; +import java.util.EnumMap; +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.Set; + +import kodkod.ast.BinaryFormula; +import kodkod.ast.ComparisonFormula; +import kodkod.ast.Comprehension; +import kodkod.ast.ConstantExpression; +import kodkod.ast.Decl; +import kodkod.ast.Decls; +import kodkod.ast.ExprToIntCast; +import kodkod.ast.Expression; +import kodkod.ast.Formula; +import kodkod.ast.IfExpression; +import kodkod.ast.IfIntExpression; +import kodkod.ast.IntComparisonFormula; +import kodkod.ast.IntToExprCast; +import kodkod.ast.MultiplicityFormula; +import kodkod.ast.NaryFormula; +import kodkod.ast.Node; +import kodkod.ast.NotFormula; +import kodkod.ast.QuantifiedFormula; +import kodkod.ast.Relation; +import kodkod.ast.RelationPredicate; +import kodkod.ast.SumExpression; +import kodkod.ast.Variable; +import kodkod.ast.operator.ExprCastOperator; +import kodkod.ast.operator.FormulaOperator; +import kodkod.ast.visitor.AbstractDetector; +import kodkod.ast.visitor.AbstractVoidVisitor; +import kodkod.util.collections.ArrayStack; +import kodkod.util.collections.IdentityHashSet; +import kodkod.util.collections.Stack; + +/** + * A node annotated with information about + * structural sharing in its ast/dag. The class + * also provides utility methods for collecting + * various information about annotated nodes. + * + * @specfield node: N // annotated node + * @specfield source: node.*components ->one Node // maps the subnodes of this.node to nodes from + * // which they were derived by some transformation process + * // (e.g. skolemization, predicate inlining) + * @author Emina Torlak + */ +public final class AnnotatedNode { + private final N node; + private final Set sharedNodes; + private final Map source; + + /** + * Constructs a new annotator for the given node. + * @ensures this.node' = node && this.source' = node.*components<:iden + */ + private AnnotatedNode(N node) { + this.node = node; + final SharingDetector detector = new SharingDetector(); + node.accept(detector); + this.sharedNodes = Collections.unmodifiableSet(detector.sharedNodes()); + this.source = Collections.emptyMap(); + } + + + /** + * Constructs a new annotator for the given node and source map. + * @ensures this.node' = node && this.source' = node.*components<:iden ++ source + */ + private AnnotatedNode(N node, Map source) { + this.node = node; + final SharingDetector detector = new SharingDetector(); + node.accept(detector); + this.sharedNodes = Collections.unmodifiableSet(detector.sharedNodes()); + this.source = source; + } + + /** + * Returns an annotation for the given node. The source map of the returned annotation object + * maps each descendant of the node to itself. + * @return { a: AnnotatedNode | a.node = node && a.source = node.*components<:iden } + */ + public static AnnotatedNode annotate(N node) { return new AnnotatedNode(node); } + + /** + * Returns an annotation for the given node. The source map of the returned annotation object + * maps each descendant of the node to its value in the given source map, or to itself + * if the given source map has no value for that descendant. + * @return { a: AnnotatedNode | a.node = node && a.source = (node.*components<:iden) ++ source } + */ + public static AnnotatedNode annotate(N node, Map source) { return new AnnotatedNode(node,source); } + + /** + * Returns an annotation for an n-ary conjunctions of {@linkplain Nodes#roots(Formula) roots} of the given formula. + * The source map of the returned annotation object maps each descendant of the node to itself. + * The root conjunction itself is mapped to the input formula. + * @return { a: AnnotatedNode | a.node = Formula.and(Nodes.roots(formula)) && a.source = (node.^components<:iden) + a.node->formula } + */ + public static AnnotatedNode annotateRoots(Formula formula) { + final Formula flat = Formula.and(Nodes.roots(formula)); + return new AnnotatedNode(flat, Collections.singletonMap(flat, formula)); + } + + /** + * Returns this.node. + * @return this.node + */ + public final N node() { + return node; + } + + /** + * Returns the source of the the given descendant of this.node. + * @requires n in this.node.*components + * @return this.source[n] + */ + public final Node sourceOf(Node n) { + final Node d = source.get(n); + return d==null ? n : d; + } + + + /** + * Returns the set of all non-leaf descendants of this.node that have more than one parent. + * @return {n: Node | some n.children && #(n.~components & this.node.*components) > 1 } + */ + public final Set sharedNodes() { + return sharedNodes; + } + + /** + * Returns the set of all relations at the leaves of this annotated node. + * @return Relation & this.node.*components + */ + public final Set relations() { + final Set relations = new IdentityHashSet(); + final AbstractVoidVisitor visitor = new AbstractVoidVisitor() { + private final Set visited = new IdentityHashSet(sharedNodes.size()); + protected boolean visited(Node n) { + return sharedNodes.contains(n) && !visited.add(n); + } + public void visit(Relation relation) { + relations.add(relation); + } + }; + node.accept(visitor); + return relations; + } + + /** + * Returns true if this.node contains a child whose meaning depends on + * integer bounds (i.e. an ExprToIntCast node with SUM operator or an IntToExprCast node or Expression.INTS constant). + * @return true if this.node contains a child whose meaning depends on + * integer bounds (i.e. an ExprToIntCast node with SUM operator or an IntToExprCast node or Expression.INTS constant). + */ + public final boolean usesInts() { + final AbstractDetector detector = new AbstractDetector(sharedNodes) { + public Boolean visit(IntToExprCast expr) { + return cache(expr, Boolean.TRUE); + } + public Boolean visit(ExprToIntCast intExpr) { + if (intExpr.op()==ExprCastOperator.CARDINALITY) + super.visit(intExpr); + return cache(intExpr, Boolean.TRUE); + } + public Boolean visit(ConstantExpression expr) { + return expr==Expression.INTS ? Boolean.TRUE : Boolean.FALSE; + } + }; + return (Boolean)node.accept(detector); + } + + /** + * Returns a map of RelationPredicate names to sets of top-level relation predicates with + * the corresponding names in this.node. + * @return a map of RelationPredicate names to sets of top-level relation predicates with + * the corresponding names in this.node. A predicate is considered 'top-level' + * if it is a component of the top-level conjunction, if any, of this.node. + */ + public final Map> predicates() { + final PredicateCollector collector = new PredicateCollector(sharedNodes); + node.accept(collector); + return collector.preds; + } + + /** + * Returns a Detector that will return TRUE when applied to a descendent + * of this.node iff the descendent contains a quantified formula. + * @return a Detector that will return TRUE when applied to a descendent + * of this.node iff the descendent contains a quantified formula. + */ + public final AbstractDetector quantifiedFormulaDetector() { + return new AbstractDetector(sharedNodes) { + public Boolean visit(QuantifiedFormula quantFormula) { + return cache(quantFormula, true); + } + }; + } + + /** + * Returns a Detector that will return TRUE when applied to a descendent + * of this.node iff the descendent contains a free variable. + * @return a Detector that will return TRUE when applied to a descendent + * of this.node iff the descendent contains a free variable. + */ + public final AbstractDetector freeVariableDetector() { + return new FreeVariableDetector(sharedNodes); + } + + /** + * Returns a string representation of this annotated node. + * @return string representation of this annotated node. + */ + public String toString() { + final StringBuilder ret = new StringBuilder(); + ret.append("node: "); + ret.append(node); + ret.append("\nshared nodes: "); + ret.append(sharedNodes); + ret.append("\nsources: "); + ret.append(source); + return ret.toString(); + } + + /** + * Detects shared non-leaf descendents of a given node. + * + * @specfield node: Node // node to which the analyzer is applied + */ + private static final class SharingDetector extends AbstractVoidVisitor { + /* maps each internal node with more than one parent to TRUE and all + * other internal nodes to FALSE */ + final IdentityHashMap sharingStatus; + /* @invariant numShareNodes = #sharingStatus.TRUE */ + int numSharedNodes; + + SharingDetector() { + sharingStatus = new IdentityHashMap(); + } + + /** + * Returns the shared internal nodes of this.node. This method should + * be called only after this visitor has been applied to this.node. + * @return {n: Node | #(n.~children & node.*children) > 1 } + */ + IdentityHashSet sharedNodes() { + final IdentityHashSet shared = new IdentityHashSet(numSharedNodes); + for(Map.Entry entry : sharingStatus.entrySet()) { + if (entry.getValue()==Boolean.TRUE) + shared.add(entry.getKey()); + } + return shared; + } + + /** + * Records the visit to the given node in the status map. + * If the node has not been visited before, it is mapped + * to Boolean.FALSE and false is returned. Otherwise, + * it is mapped to Boolean.TRUE and true is returned. + * The first time a Node is mapped to true, numSharedNodes + * is incremented by one. + * @ensures no this.shared[node] => this.shared' = this.shared + node->FALSE, + * this.shared[node] = FALSE => this.shared' = this.shared + node->TRUE, + * this.shared' = this.shared + * @return this.shared'[node] + */ + protected final boolean visited(Node node) { + Boolean status = sharingStatus.get(node); + if (!Boolean.TRUE.equals(status)) { + if (status==null) { + status = Boolean.FALSE; + } else { // status == Boolean.FALSE + status = Boolean.TRUE; + numSharedNodes++; + } + sharingStatus.put(node,status); + } + return status; + } + } + + /** + * A visitor that detects free variables of a node. + * @author Emina Torlak + */ + private static final class FreeVariableDetector extends AbstractDetector { + /* Holds the variables that are currently in scope, with the + * variable at the top of the stack being the last declared variable. */ + + private final Stack varsInScope = new ArrayStack(); + + /** + * Constructs a new free variable detector. + */ + FreeVariableDetector(Set sharedNodes) { + super(sharedNodes); + } + + /** + * Visits the given comprehension, quantified formula, or sum expression. + * The method returns TRUE if the creator body contains any + * variable not bound by the decls; otherwise returns FALSE. + */ + private Boolean visit(Node creator, Decls decls, Node body) { + Boolean ret = lookup(creator); + if (ret!=null) return ret; + boolean retVal = false; + for(Decl decl : decls) { + retVal = decl.expression().accept(this) || retVal; + varsInScope.push(decl.variable()); + } + retVal = ((Boolean)body.accept(this)) || retVal; + for(int i = decls.size(); i > 0; i--) { + varsInScope.pop(); + } + return cache(creator, retVal); + } + /** + * Returns TRUE if the given variable is free in its parent, otherwise returns FALSE. + * @return TRUE if the given variable is free in its parent, otherwise returns FALSE. + */ + public Boolean visit(Variable variable) { + return Boolean.valueOf(varsInScope.search(variable)<0); + } + public Boolean visit(Decl decl) { + Boolean ret = lookup(decl); + if (ret!=null) return ret; + return cache(decl, decl.expression().accept(this)); + } + public Boolean visit(Comprehension comprehension) { + return visit(comprehension, comprehension.decls(), comprehension.formula()); + } + public Boolean visit(SumExpression intExpr) { + return visit(intExpr, intExpr.decls(), intExpr.intExpr()); + } + public Boolean visit(QuantifiedFormula qformula) { + return visit(qformula, qformula.decls(), qformula.formula()); + } + } + + /** + * A visitor that detects and collects + * top-level relation predicates; i.e. predicates that + * are components in the top-level conjunction, if any, on ANY + * path starting at the root. + */ + private static final class PredicateCollector extends AbstractVoidVisitor { + protected boolean negated; + private final Set sharedNodes; + /* if a given node is not mapped at all, it means that it has not been visited; + * if it is mapped to FALSE, it has been visited with negated=FALSE, + * if it is mapped to TRUE, it has been visited with negated=TRUE, + * if it is mapped to null, it has been visited with both values of negated. */ + private final Map visited; + /* holds the top level predicates at the the end of the visit*/ + final EnumMap> preds; + /** + * Constructs a new collector. + * @ensures this.negated' = false + */ + PredicateCollector(Set sharedNodes) { + this.sharedNodes = sharedNodes; + this.visited = new IdentityHashMap(); + this.negated = false; + preds = new EnumMap>(RelationPredicate.Name.class); + preds.put(ACYCLIC, new IdentityHashSet(4)); + preds.put(TOTAL_ORDERING, new IdentityHashSet(4)); + preds.put(FUNCTION, new IdentityHashSet(8)); + } + /** + * Returns true if n has already been visited with the current value of the + * negated flag; otherwise returns false. + * @ensures records that n is being visited with the current value of the negated flag + * @return true if n has already been visited with the current value of the + * negated flag; otherwise returns false. + */ + @Override + protected final boolean visited(Node n) { + if (sharedNodes.contains(n)) { + if (!visited.containsKey(n)) { // first visit + visited.put(n, Boolean.valueOf(negated)); + return false; + } else { + final Boolean visit = visited.get(n); + if (visit==null || visit==negated) { // already visited with same negated value + return true; + } else { // already visited with different negated value + visited.put(n, null); + return false; + } + } + } + return false; + } + /** + * Calls visited(comp); comp's children are not top-level formulas + * so they are not visited. + */ + public void visit(Comprehension comp) { + visited(comp); + } + /** + * Calls visited(ifexpr); ifexpr's children are not top-level formulas + * so they are not visited. + */ + public void visit(IfExpression ifexpr) { + visited(ifexpr); + } + /** + * Calls visited(ifexpr); ifexpr's children are not top-level formulas + * so they are not visited. + */ + public void visit(IfIntExpression ifexpr) { + visited(ifexpr); + } + /** + * Calls visited(intComp); intComp's children are not top-level formulas + * so they are not visited. + */ + public void visit(IntComparisonFormula intComp) { + visited(intComp); + } + /** + * Calls visited(quantFormula); quantFormula's children are not top-level formulas + * so they are not visited. + */ + public void visit(QuantifiedFormula quantFormula) { + visited(quantFormula); + } + /** + * Visits the children of the given formula if it has not been visited already with + * the given value of the negated flag and if binFormula.op==IMPLIES && negated or + * binFormula.op==AND && !negated or binFormula.op==OR && negated. Otherwise does nothing. + * @see kodkod.ast.visitor.AbstractVoidVisitor#visit(kodkod.ast.BinaryFormula) + */ + public void visit(BinaryFormula binFormula) { + if (visited(binFormula)) return; + final FormulaOperator op = binFormula.op(); + + if ((!negated && op==AND) || (negated && op==OR)) { // op==AND || op==OR + binFormula.left().accept(this); + binFormula.right().accept(this); + } else if (negated && op==IMPLIES) { // !(a => b) = !(!a || b) = a && !b + negated = !negated; + binFormula.left().accept(this); + negated = !negated; + binFormula.right().accept(this); + } + } + /** + * Visits the children of the given formula if it has not been visited already with + * the given value of the negated flag and if formula.op==OR && negated or + * formula.op==AND && !negated. Otherwise does nothing. + * @see kodkod.ast.visitor.AbstractVoidVisitor#visit(kodkod.ast.NaryFormula) + */ + public void visit(NaryFormula formula) { + if (visited(formula)) return; + final FormulaOperator op = formula.op(); + if ((!negated && op==AND) || (negated && op==OR)) { // op==AND || op==OR + for(Formula child : formula) { + child.accept(this); + } + } + } + + /** + * Visits the children of the child of the child formula, with + * the negation of the current value of the negated flag, + * if it has not already been visited + * with the current value of this.negated; otherwise does nothing. + */ + public void visit(NotFormula not) { + if (visited(not)) return; + negated = !negated; + not.formula().accept(this); + negated = !negated; + } + /** + * Calls visited(compFormula); compFormula's children are not top-level formulas + * so they are not visited. + */ + public void visit(ComparisonFormula compFormula) { + visited(compFormula); + } + /** + * Calls visited(multFormula); multFormula's child is not top-level formulas + * so it is not visited. + */ + public void visit(MultiplicityFormula multFormula) { + visited(multFormula); + } + /** + * Records the visit to this predicate if it is not negated. + */ + public void visit(RelationPredicate pred) { + if (visited(pred)) return; + if (!negated) { + preds.get(pred.name()).add(pred); + } + } + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/nodes/Nodes.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/nodes/Nodes.java new file mode 100644 index 00000000..bcb03a6e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/nodes/Nodes.java @@ -0,0 +1,199 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.nodes; + +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Set; + +import kodkod.ast.BinaryFormula; +import kodkod.ast.Formula; +import kodkod.ast.NaryFormula; +import kodkod.ast.Node; +import kodkod.ast.operator.FormulaOperator; +import kodkod.ast.visitor.AbstractDetector; +import kodkod.ast.visitor.AbstractVoidVisitor; +import kodkod.ast.visitor.VoidVisitor; +import kodkod.util.collections.Containers; +import kodkod.util.collections.IdentityHashSet; + +/** + * Provides utility methods for extracting roots (top-level) conjuncts + * of Kodkod formulas + * + * @author Emina Torlak + */ +public final class Nodes { + private Nodes() {} + + /** + * Returns the roots of the given formula. + * In other words, breaks up the given formula into its conjunctive + * components, {f0, ..., fk}, + * such that, for all 0<=i<=k, fi is not a conjunction and + * [[f0 && ... && fk]] <=> [[formula]]. + * @return subformulas, {f0, ..., fk}, of the given formula such that, for all 0<=i<=k, + * fi is not a conjuction and [[f0 && ... && fk]] <=> [[formula]]. + */ + public static Set roots(Formula formula) { + + final List formulas = new LinkedList(); + formulas.add(formula); + + final ListIterator itr = formulas.listIterator(); + while(itr.hasNext()) { + final Formula f = itr.next(); + if (f instanceof BinaryFormula) { + final BinaryFormula bin = (BinaryFormula) f; + if (bin.op()==FormulaOperator.AND) { + itr.remove(); + itr.add(bin.left()); + itr.add(bin.right()); + itr.previous(); + itr.previous(); + } + } else if (f instanceof NaryFormula) { + final NaryFormula nf = (NaryFormula) f; + if (nf.op()==FormulaOperator.AND) { + itr.remove(); + for(Formula child : nf) { + itr.add(child); + } + for(int i = nf.size(); i>0; i--) { + itr.previous(); + } + } + } + } + + return new LinkedHashSet(formulas); + } + + /** + * Returns an unmodifiable set consisting of the children of the given formula, if the formula is a binary or an nary conjunction. Otherwise + * returns a singleton set containing the formula itself. + * @return an unmodifiable set consisting of children of the given formula, if the formula is a binary or an nary conjunction. Otherwise + * returns a singleton set containing the formula itself. + */ + public static Set conjuncts(Formula formula) { + if (formula instanceof BinaryFormula) { + final BinaryFormula bin = (BinaryFormula) formula; + if (bin.op()==FormulaOperator.AND) { + final Formula left = bin.left(), right = bin.right(); + if (left==right) return Collections.singleton(left); + else return new AbstractSet() { + @Override + public boolean contains(Object o) { return left==o || right==o; } + @Override + public Iterator iterator() { return Containers.iterate(left, right); } + @Override + public int size() { return 2; } + + }; + } + } else if (formula instanceof NaryFormula) { + final NaryFormula nf = (NaryFormula) formula; + if (nf.op()==FormulaOperator.AND) { + final LinkedHashSet children = new LinkedHashSet(1+(nf.size()*4)/3); + for(Formula child : nf) { children.add(child); } + return Collections.unmodifiableSet(children); + } + } + + return Collections.singleton(formula); + + } + + /** + * Returns a minimal subset of {@linkplain #roots(Formula) roots} of the given formula such that all nodes in the given collection + * are reachable from those roots. The returned subset is a local minimum in that none of its members can be removed without leaving + * some node in the descendants set unreachable from the remaining roots. + * @requires descendants in formula.*components + * @return { s: Set | s.elements in roots(formula) and descendants in s.elements.*components and + * no s': Set | s.containsAll(s') and s'.size() minRoots(Formula formula, Collection descendants) { + + final Set desc = new IdentityHashSet(descendants); + final VoidVisitor visitor = new AbstractVoidVisitor() { + final Set visited = new IdentityHashSet(); + @Override + protected boolean visited(Node n) { + if (visited.add(n)) { + desc.remove(n); + return false; + } + return true; + } + }; + + final Set roots = new LinkedHashSet(); + for(Formula root : roots(formula)) { + final int size = desc.size(); + root.accept(visitor); + if (desc.size() allRoots(Formula formula, Collection descendants) { + final Set desc = new IdentityHashSet(descendants); + final AbstractDetector detector = new AbstractDetector(Collections.EMPTY_SET) { + protected Boolean lookup(Node n) { + return desc.contains(n) ? Boolean.TRUE : cache.get(n); + } + protected Boolean cache(Node n, boolean val) { + final Boolean ret = Boolean.valueOf(val); + cache.put(n, ret); + return ret; + } + }; + + final Set roots = new LinkedHashSet(); + for(Formula root : roots(formula)) { + if (root.accept(detector)) { + roots.add(root); + } + } + + return roots; + } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/nodes/PrettyPrinter.java b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/nodes/PrettyPrinter.java new file mode 100644 index 00000000..5c2debf3 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/kodkod/util/nodes/PrettyPrinter.java @@ -0,0 +1,769 @@ +/* + * Kodkod -- Copyright (c) 2005-2011, Emina Torlak + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package kodkod.util.nodes; + +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import kodkod.ast.BinaryExpression; +import kodkod.ast.BinaryFormula; +import kodkod.ast.BinaryIntExpression; +import kodkod.ast.ComparisonFormula; +import kodkod.ast.Comprehension; +import kodkod.ast.ConstantExpression; +import kodkod.ast.ConstantFormula; +import kodkod.ast.Decl; +import kodkod.ast.Decls; +import kodkod.ast.ExprToIntCast; +import kodkod.ast.Expression; +import kodkod.ast.Formula; +import kodkod.ast.IfExpression; +import kodkod.ast.IfIntExpression; +import kodkod.ast.IntComparisonFormula; +import kodkod.ast.IntConstant; +import kodkod.ast.IntExpression; +import kodkod.ast.IntToExprCast; +import kodkod.ast.LeafExpression; +import kodkod.ast.MultiplicityFormula; +import kodkod.ast.NaryExpression; +import kodkod.ast.NaryFormula; +import kodkod.ast.NaryIntExpression; +import kodkod.ast.Node; +import kodkod.ast.NotFormula; +import kodkod.ast.ProjectExpression; +import kodkod.ast.QuantifiedFormula; +import kodkod.ast.Relation; +import kodkod.ast.RelationPredicate; +import kodkod.ast.SumExpression; +import kodkod.ast.UnaryExpression; +import kodkod.ast.UnaryIntExpression; +import kodkod.ast.Variable; +import kodkod.ast.operator.ExprOperator; +import kodkod.ast.operator.FormulaOperator; +import kodkod.ast.operator.IntOperator; +import kodkod.ast.operator.Multiplicity; +import kodkod.ast.visitor.VoidVisitor; + +/** + * Pretty-prints Kodkod nodes. + * + * @author Emina Torlak + */ +public final class PrettyPrinter { + + /** + * Returns a dot representation of the given node that can be visualized with GraphViz. + * @return a dot representation of the given node that can be visualized with GraphViz. + */ + public static String dotify(Node node) { + return Dotifier.apply(node); + } + /** + * Returns a pretty-printed string representation of the + * given node, with each line offset by at least the given + * number of whitespaces. The line parameter determines the + * length of each pretty-printed line, including the offset. + * @requires 0 <= offset < line + * @return a pretty-printed string representation of the + * given node + */ + public static String print(Node node, int offset, int line) { + final Formatter formatter = new Formatter(offset,line); + node.accept(formatter); + return formatter.tokens.toString(); + } + + /** + * Returns a pretty-printed string representation of the + * given node, with each line offset by at least the given + * number of whitespaces. + * @requires 0 <= offset < 80 + * @return a pretty-printed string representation of the + * given node + */ + public static String print(Node node, int offset) { + return print(node,offset,80); + } + + /** + * Returns a pretty-printed string representation of the + * given formulas, with each line offset by at least the given + * number of whitespaces. + * @requires 0 <= offset < 80 + * @return a pretty-printed string representation of the + * given formulas + */ + public static String print(Set formulas, int offset) { + return print(formulas,offset,80); + } + + /** + * Returns a pretty-printed string representation of the + * given formulas, with each line offset by at least the given + * number of whitespaces. The line parameter determines the + * length of each pretty-printed line, including the offset. + * @requires 0 <= offset < line + * @return a pretty-printed string representation of the + * given formulas + */ + public static String print(Set formulas, int offset, int line) { + final Formatter formatter = new Formatter(offset,line); + for(Formula f : formulas) { + f.accept(formatter); + formatter.newline(); + } + return formatter.tokens.toString(); + } + + + + /** + * Generates a buffer of tokens comprising the string representation + * of a given node. The buffer contains at least the parentheses + * needed to correctly represent the node's tree structure. + * + * @specfield tokens: seq + * @author Emina Torlak + */ + private static class Formatter implements VoidVisitor { + final StringBuilder tokens ; + //final int offset; + private final int lineLength; + private int indent, lineStart; + + /** + * Constructs a new tokenizer. + * @ensures no this.tokens + */ + Formatter(int offset, int line) { + assert offset >= 0 && offset < line; + this.tokens = new StringBuilder(); + //this.offset = offset; + this.lineLength = line; + this.lineStart = 0; + this.indent = offset; + indent(); + } + + /*--------------FORMATTERS---------------*/ + + + /** @ensures this.tokens' = concat [ this.tokens, " ", token, " " ]*/ + private void infix(Object token) { + space(); + tokens.append(token); + space(); + } + + /** @ensures this.tokens' = concat [ this.tokens, token, " " ]*/ + private void keyword(Object token) { + append(token); + space(); + } + + /** @ensures this.tokens' = concat [ this.tokens, ", " ]*/ + private void comma() { + tokens.append(","); + space(); + } + + /** @ensures this.tokens' = concat [ this.tokens, ": " ]*/ + private void colon() { + tokens.append(":"); + space(); + } + + /** @ensures adds this.indent spaces to this.tokens */ + private void indent() { for(int i = 0; i < indent; i++) { space(); } } + + /** @ensures adds newline plus this.indent spaces to this.tokens */ + private void newline() { + tokens.append("\n"); + lineStart = tokens.length(); + indent(); + } + + /** @ensures this.tokens' = concat[ this.tokens, " " ] **/ + private void space() { tokens.append(" "); } + + /** @ensures this.tokens' = concat [ this.tokens, token ]*/ + private void append(Object token) { + final String str = String.valueOf(token); + if ((tokens.length() - lineStart + str.length()) > lineLength) { + newline(); + } + tokens.append(str); + } + + /*--------------LEAVES---------------*/ + /** @ensures this.tokens' = concat[ this.tokens, node ] */ + public void visit(Relation node) { append(node); } + + /** @ensures this.tokens' = concat[ this.tokens, node ] */ + public void visit(Variable node) { append(node); } + + /** @ensures this.tokens' = concat[ this.tokens, node ] */ + public void visit(ConstantExpression node) { append(node); } + + /** @ensures this.tokens' = concat[ this.tokens, node ] */ + public void visit(IntConstant node) { append(node); } + + /** @ensures this.tokens' = concat[ this.tokens, node ] */ + public void visit(ConstantFormula node) { append(node); } + + /*--------------DECLARATIONS---------------*/ + /** + * @ensures this.tokens' = + * concat[ this.tokens, tokenize[ node.variable ], ":", tokenize[ node.expression ] + **/ + public void visit(Decl node) { + node.variable().accept(this); + colon(); + if (node.multiplicity()!=Multiplicity.ONE) { + append(node.multiplicity()); + space(); + } + node.expression().accept(this); + } + + /** + * @ensures this.tokens' = + * concat[ this.tokens, tokenize[ node.declarations[0] ], ",", + * ..., tokenize[ node.declarations[ node.size() - 1 ] ] ] + **/ + public void visit(Decls node) { + Iterator decls = node.iterator(); + decls.next().accept(this); + while(decls.hasNext()) { + comma(); + decls.next().accept(this); + } + } + + /*--------------UNARY NODES---------------*/ + + /** @ensures this.tokenize' = + * (parenthesize => concat [ this.tokens, "(", tokenize[child], ")" ] else + * concat [ this.tokens, tokenize[child] ]*/ + private void visitChild(Node child, boolean parenthesize) { + if (parenthesize) { append("("); } + child.accept(this); + if (parenthesize) { append(")"); } + } + + /** @return true if the given expression should be parenthesized when a + * child of a compound parent */ + private boolean parenthesize(Expression child) { + return child instanceof BinaryExpression || child instanceof IfExpression; + } + + /** @return true if the given expression should be parenthesized when a + * child of a compound parent */ + private boolean parenthesize(IntExpression child) { + return !(child instanceof UnaryIntExpression || + child instanceof IntConstant || + child instanceof ExprToIntCast); + } + + /** @return true if the given formula should be parenthesized when a + * child of a compound parent */ + private boolean parenthesize(Formula child) { + return !(child instanceof NotFormula || child instanceof ConstantFormula || + child instanceof RelationPredicate); + } + + /** @ensures appends the given op and child to this.tokens; the child is + * parenthesized if it's an instance of binary expression or an if expression. **/ + public void visit(UnaryExpression node) { + append(node.op()); + visitChild(node.expression(), parenthesize(node.expression())); + } + + + /** @ensures appends the given op and child to this.tokens; the child is + * parenthesized if it's not an instance of unary int expression or int constant. **/ + public void visit(UnaryIntExpression node) { + final IntExpression child = node.intExpr(); + final IntOperator op = node.op(); + final boolean parens = + (op==IntOperator.ABS) || (op==IntOperator.SGN) || + parenthesize(child); + append(node.op()); + visitChild(child, parens); + } + + /** @ensures appends the given op and child to this.tokens; the child is + * parenthesized if it's not an instance of not formula, constant formula, or + * relation predicate. **/ + public void visit(NotFormula node) { + append("!"); + final boolean pchild = parenthesize(node.formula()); + indent += pchild ? 2 : 1; + visitChild(node.formula(), parenthesize(node.formula())); + indent -= pchild ? 2 : 1; + } + + /** @ensures appends the given op and child to this.tokens; the child is + * parenthesized if it's an instance of binary expression or an if expression. **/ + public void visit(MultiplicityFormula node) { + keyword(node.multiplicity()); + visitChild(node.expression(), parenthesize(node.expression())); + } + + /*--------------BINARY NODES---------------*/ + + /** @return true if the given expression needs to be parenthesized if a + * child of a binary expression with the given operator */ + private boolean parenthesize(ExprOperator op, Expression child) { + return child instanceof IfExpression || + child instanceof NaryExpression || + (child instanceof BinaryExpression && + (op==ExprOperator.JOIN || + ((BinaryExpression)child).op()!=op)); + } + + /** @ensures appends the tokenization of the given node to this.tokens */ + public void visit(BinaryExpression node) { + final ExprOperator op = node.op(); + visitChild(node.left(), parenthesize(op, node.left())); + infix(op); + visitChild(node.right(), parenthesize(op, node.right())); + } + + + + /** @return true if the given operator is assocative */ + private boolean associative(IntOperator op) { + switch(op) { + case DIVIDE : case MODULO : case SHA : case SHL : case SHR : return false; + default : return true; + } + } + + /** @return true if the given int expression needs to be parenthesized if a + * child of a binary int expression with the given operator */ + private boolean parenthesize(IntOperator op, IntExpression child) { + return child instanceof SumExpression || + child instanceof IfIntExpression || + child instanceof NaryIntExpression || + (child instanceof BinaryIntExpression && + (!associative(op) || ((BinaryIntExpression)child).op()!=op)); + } + + /** @ensures appends the tokenization of the given node to this.tokens */ + public void visit(BinaryIntExpression node) { + final IntOperator op = node.op(); + visitChild(node.left(), parenthesize(op, node.left())); + infix(op); + visitChild(node.right(), parenthesize(op, node.right())); + } + + /** @return true if the given formula needs to be parenthesized if a + * child of a binary formula with the given operator */ + private boolean parenthesize(FormulaOperator op, Formula child) { + return child instanceof QuantifiedFormula || + //child instanceof NaryFormula || + (child instanceof BinaryFormula && + (op==FormulaOperator.IMPLIES || + ((BinaryFormula)child).op()!=op)); + } + + /** @ensures appends the tokenization of the given node to this.tokens */ + public void visit(BinaryFormula node) { + final FormulaOperator op = node.op(); + final boolean pleft = parenthesize(op, node.left()); + if (pleft) indent++; + visitChild(node.left(), pleft); + if (pleft) indent--; + infix(op); + newline(); + final boolean pright = parenthesize(op, node.right()); + if (pright) indent++; + visitChild(node.right(), pright); + if (pright) indent--; + } + + /** @ensures this.tokens' = concat[ this.tokens, tokenize[node.left], node.op, tokenize[node.right] */ + public void visit(ComparisonFormula node) { + visitChild(node.left(), parenthesize(node.left())); + infix(node.op()); + visitChild(node.right(), parenthesize(node.right())); + } + + /** @ensures this.tokens' = concat[ this.tokens, tokenize[node.left], node.op, tokenize[node.right] */ + public void visit(IntComparisonFormula node) { + visitChild(node.left(), parenthesize(node.left())); + infix(node.op()); + visitChild(node.right(), parenthesize(node.right())); + } + + /*--------------TERNARY NODES---------------*/ + + /** @ensures appends the tokenization of the given node to this.tokens */ + public void visit(IfExpression node) { + visitChild(node.condition(), parenthesize(node.condition())); + infix("=>"); + indent++; + newline(); + visitChild(node.thenExpr(), parenthesize(node.thenExpr())); + infix("else"); + newline(); + visitChild(node.elseExpr(), parenthesize(node.elseExpr())); + indent--; + } + + /** @ensures appends the tokenization of the given node to this.tokens */ + public void visit(IfIntExpression node) { + visitChild(node.condition(), parenthesize(node.condition())); + infix("=>"); + indent++; + newline(); + visitChild(node.thenExpr(), parenthesize(node.thenExpr())); + infix("else"); + newline(); + visitChild(node.elseExpr(), parenthesize(node.elseExpr())); + indent--; + } + + /*--------------VARIABLE CREATOR NODES---------------*/ + /** @ensures this.tokens' = concat[ this.tokens, + * "{", tokenize[node.decls], "|", tokenize[ node.formula ], "}" ]*/ + public void visit(Comprehension node) { + append("{"); + node.decls().accept(this); + infix("|"); + node.formula().accept(this); + append("}"); + } + + /** @ensures this.tokens' = concat[ this.tokens, "sum", + * tokenize[node.decls], "|", tokenize[ node.intExpr ], ]*/ + public void visit(SumExpression node) { + keyword("sum"); + node.decls().accept(this); + infix("|"); + node.intExpr().accept(this); + } + + /** @ensures this.tokens' = concat[ this.tokens, node.quantifier, + * tokenize[node.decls], "|", tokenize[ node.formula ] ]*/ + public void visit(QuantifiedFormula node) { + keyword(node.quantifier()); + node.decls().accept(this); + infix("|"); + indent++; + newline(); + node.formula().accept(this); + indent--; + } + + /*--------------NARY NODES---------------*/ + + /** @ensures appends the tokenization of the given node to this.tokens */ + public void visit(NaryExpression node) { + final ExprOperator op = node.op(); + visitChild(node.child(0), parenthesize(op, node.child(0))); + for(int i = 1, size = node.size(); i < size; i++) { + infix(op); + visitChild(node.child(i), parenthesize(op, node.child(i))); + } + } + /** @ensures appends the tokenization of the given node to this.tokens */ + public void visit(NaryIntExpression node) { + final IntOperator op = node.op(); + visitChild(node.child(0), parenthesize(op, node.child(0))); + for(int i = 1, size = node.size(); i < size; i++) { + infix(op); + visitChild(node.child(i), parenthesize(op, node.child(i))); + } + } + /** @ensures appends the tokenization of the given node to this.tokens */ + public void visit(NaryFormula node) { + final FormulaOperator op = node.op(); + boolean parens = parenthesize(op, node.child(0)); + if (parens) indent++; + visitChild(node.child(0), parens); + if (parens) indent--; + for(int i = 1, size = node.size(); i < size; i++) { + infix(op); + newline(); + parens = parenthesize(op, node.child(i)); + if (parens) indent++; + visitChild(node.child(i), parens); + if (parens) indent--; + } + } + /*--------------OTHER NODES---------------*/ + + /** @ensures appends the tokenization of the given node to this.tokens */ + public void visit(ProjectExpression node) { + append("project"); + append("["); + node.expression().accept(this); + comma(); + append("<"); + final Iterator cols = node.columns(); + cols.next().accept(this); + while(cols.hasNext()) { + comma(); + cols.next().accept(this); + } + append(">"); + append("]"); + } + + /** @ensures this.tokens' = concat[ this.tokens, "Int","[", + * tokenize[node.intExpr], "]" ] **/ + public void visit(IntToExprCast node) { + append("Int"); + append("["); + node.intExpr().accept(this); + append("]"); + } + + /** @ensures this.tokens' = concat[ this.tokens, "int","[", + * tokenize[node.expression], "]" ] **/ + public void visit(ExprToIntCast node) { + switch(node.op()) { + case SUM: + append("int"); + append("["); + node.expression().accept(this); + append("]"); + break; + case CARDINALITY : + append("#"); + append("("); + node.expression().accept(this); + append(")"); + break; + default : throw new IllegalArgumentException("unknown operator: " + node.op()); + } + + } + + /** @ensures appends the tokenization of the given node to this.tokens */ + public void visit(RelationPredicate node) { + switch(node.name()) { + case ACYCLIC : + append("acyclic"); + append("["); + node.relation().accept(this); + append("]"); + break; + case FUNCTION : + RelationPredicate.Function func = (RelationPredicate.Function)node; + append("function"); + append("["); + func.relation().accept(this); + colon(); + func.domain().accept(this); + infix("->"); + keyword(func.targetMult()); + func.range().accept(this); + append("]"); + break; + case TOTAL_ORDERING : + RelationPredicate.TotalOrdering ord = (RelationPredicate.TotalOrdering)node; + append("ord"); + append("["); + ord.relation().accept(this); + comma(); + ord.ordered().accept(this); + comma(); + ord.first().accept(this); + comma(); + ord.last().accept(this); + append("]"); + break; + default: + throw new AssertionError("unreachable"); + } + + } + + } + + private static class Dotifier implements VoidVisitor { + private final StringBuilder graph = new StringBuilder(); + private final Map ids = new LinkedHashMap(); + + static String apply(Node node) { + final Dotifier dot = new Dotifier(); + dot.graph.append("digraph {\n"); + node.accept(dot); + dot.graph.append("}"); + return dot.graph.toString(); + } + + + private boolean visited(Node n) { + if (ids.containsKey(n)) return true; + ids.put(n, ids.size()); + return false; + } + + private String id(Node n) { return "N" + ids.get(n); } + + private void node(Node n, String label) { + graph.append(id(n)); + graph.append("[ label=\"" ); + graph.append(ids.get(n)); + graph.append("("); + graph.append(label); + graph.append(")\"];\n"); + } + + private void edge(Node n1, Node n2) { + if (n2 instanceof LeafExpression || n2 instanceof ConstantFormula || n2 instanceof IntConstant) { + + } + graph.append(id(n1)); + graph.append("->"); + graph.append(id(n2)); + graph.append(";\n"); + } + + private void visit(Node parent, Object label) { + if (visited(parent)) return; + node(parent, label.toString()); + } + + private void visit(Node parent, Object label, Node child) { + if (visited(parent)) return; + node(parent, label.toString()); + child.accept(this); + edge(parent, child); + } + + private void visit(Node parent, Object label, Node left, Node right) { + if (visited(parent)) return; + node(parent, label.toString()); + left.accept(this); + right.accept(this); + edge(parent, left); + edge(parent, right); + } + + private void visit(Node parent, Object label, Node left, Node middle, Node right) { + if (visited(parent)) return; + node(parent, label.toString()); + left.accept(this); + middle.accept(this); + right.accept(this); + edge(parent, left); + edge(parent, middle); + edge(parent, right); + } + + private void visit(Node parent, Object label, Iterator children) { + if (visited(parent)) return; + node(parent, label.toString()); + while(children.hasNext()) { + Node child = children.next(); + child.accept(this); + edge(parent, child); + } + } + + private void visit(Node parent, Object label, Node child, Iterator children) { + if (visited(parent)) return; + node(parent, label.toString()); + child.accept(this); + edge(parent, child); + while(children.hasNext()) { + Node other = children.next(); + other.accept(this); + edge(parent, other); + } + } + + public void visit(Decls decls) { visit(decls, "decls", decls.iterator()); } + + public void visit(Decl decl) { visit(decl, "decl", decl.variable(), decl.expression()); } + + public void visit(Relation relation) { visit(relation, relation.name()); } + public void visit(Variable variable) { visit(variable, variable.name()); } + public void visit(ConstantExpression constExpr) { visit(constExpr, constExpr.name()); } + + + public void visit(NaryExpression expr) { + visit(expr, expr.op(), expr.iterator()); + } + public void visit(BinaryExpression binExpr) { + visit(binExpr, binExpr.op(), binExpr.left(), binExpr.right()); + } + public void visit(UnaryExpression unaryExpr) { + visit(unaryExpr, unaryExpr.op(), unaryExpr.expression()); + } + public void visit(Comprehension comprehension) { + visit(comprehension, "setcomp", comprehension.decls(), comprehension.formula()); + } + public void visit(IfExpression ifExpr) { + visit(ifExpr, "ite", ifExpr.condition(), ifExpr.thenExpr(), ifExpr.elseExpr()); + } + public void visit(ProjectExpression project) { + visit(project, "proj", project.expression(), project.columns()); + } + + public void visit(IntToExprCast castExpr) { visit(castExpr, castExpr.op(), castExpr.intExpr()); } + public void visit(IntConstant intConst) { visit(intConst, intConst.value()); } + + public void visit(IfIntExpression intExpr) { + visit(intExpr, "ite", intExpr.condition(), intExpr.thenExpr(), intExpr.elseExpr()); + } + public void visit(ExprToIntCast intExpr) { visit(intExpr, intExpr.op(), intExpr.expression()); } + public void visit(NaryIntExpression intExpr) { visit(intExpr, intExpr.op(), intExpr.iterator());} + public void visit(BinaryIntExpression intExpr) { visit(intExpr, intExpr.op(), intExpr.left(), intExpr.right()); } + public void visit(UnaryIntExpression intExpr) { visit(intExpr, intExpr.op(), intExpr.intExpr());} + public void visit(SumExpression intExpr) { visit(intExpr, "sum", intExpr.decls(), intExpr.intExpr()); } + + public void visit(IntComparisonFormula intComp) { visit(intComp, intComp.op(), intComp.left(), intComp.right());} + public void visit(QuantifiedFormula quantFormula) { + visit(quantFormula, quantFormula.quantifier(), quantFormula.decls(), quantFormula.formula()); + } + public void visit(NaryFormula formula) { visit(formula, formula.op(), formula.iterator()); } + public void visit(BinaryFormula binFormula) { visit(binFormula, binFormula.op(), binFormula.left(), binFormula.right()); } + public void visit(NotFormula not) { visit(not, "not", not.formula()); } + public void visit(ConstantFormula constant) { visit(constant, constant.booleanValue()); } + public void visit(ComparisonFormula compFormula) { visit(compFormula, compFormula.op(), compFormula.left(), compFormula.right());} + public void visit(MultiplicityFormula multFormula) { + visit(multFormula, multFormula.multiplicity(), multFormula.expression()); + } + public void visit(RelationPredicate pred) { + if (visited(pred)) return; + + if (pred.name()==RelationPredicate.Name.FUNCTION) { + final RelationPredicate.Function fp = (RelationPredicate.Function) pred; + visit(fp, fp.name(), fp.domain(), fp.range() ); + } else if (pred.name()==RelationPredicate.Name.TOTAL_ORDERING) { + final RelationPredicate.TotalOrdering tp = (RelationPredicate.TotalOrdering) pred; + visit(tp, tp.name(), tp.ordered(), tp.first(), tp.last() ); + } else { + throw new IllegalArgumentException("Unknown predicate: " + pred); + } + } + + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/addressBook1.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/addressBook1.als new file mode 100644 index 00000000..06c2abf8 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/addressBook1.als @@ -0,0 +1,19 @@ +module appendixA/addressBook1 + +abstract sig Name { + address: set Addr+Name + } + +sig Alias, Group extends Name { } + +sig Addr { } + +fact { + // the invariants should go here + } + +pred show { + // simulation constraints should go here + } + +run show for 3 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/addressBook2.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/addressBook2.als new file mode 100644 index 00000000..02ba6373 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/addressBook2.als @@ -0,0 +1,27 @@ +module appendixA/addressBook2 + +sig Addr, Name { } + +sig Book { + addr: Name -> (Name + Addr) + } + +pred inv [b: Book] { + let addr = b.addr | + all n: Name { + n not in n.^addr + some addr.n => some n.^addr & Addr + } + } + +pred add [b, b': Book, n: Name, t: Name+Addr] { + b'.addr = b.addr + n->t + } + +pred del [b, b': Book, n: Name, t: Name+Addr] { + b'.addr = b.addr - n->t + } + +fun lookup [b: Book, n: Name] : set Addr { + n.^(b.addr) & Addr + } diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/barbers.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/barbers.als new file mode 100644 index 00000000..6205b5f4 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/barbers.als @@ -0,0 +1,9 @@ +module appendixA/barbers + +sig Man { shaves: set Man } + +one sig Barber extends Man { } + +fact { + Barber.shaves = { m: Man | m not in m.shaves } + } diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/closure.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/closure.als new file mode 100644 index 00000000..6a50e404 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/closure.als @@ -0,0 +1,16 @@ +module appendixA/closure + +pred transCover [R, r: univ->univ] { + // You have to fill in the appropriate formula here +} + +pred transClosure [R, r: univ->univ] { + transCover [R, r] + // You have to fill in the appropriate formula here +} + +assert Equivalence { + all R, r: univ->univ | transClosure [R,r] iff R = ^r +} + +check Equivalence for 3 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/distribution.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/distribution.als new file mode 100644 index 00000000..6614b2e6 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/distribution.als @@ -0,0 +1,7 @@ +module appendixA/distribution + +assert union { + all s: set univ, p, q: univ->univ | s.(p+q) = s.p + s.q +} + +check union for 4 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/phones.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/phones.als new file mode 100644 index 00000000..98c13677 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/phones.als @@ -0,0 +1,6 @@ +module appendixA/phones + +sig Phone { + requests: set Phone, + connects: lone Phone + } diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/prison.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/prison.als new file mode 100644 index 00000000..42e9ea00 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/prison.als @@ -0,0 +1,17 @@ +module appendixA/prison + +sig Gang { members: set Inmate } + +sig Inmate { room: Cell } + +sig Cell { } + +pred safe { + // your constraints should go here + } + +pred show { + // your constraints should go here + } + +run show diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/properties.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/properties.als new file mode 100644 index 00000000..cc06cc1e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/properties.als @@ -0,0 +1,23 @@ +module appendixA/properties + +pred show { + some r: univ->univ { + some r -- nonempty + r.r in r -- transitive + no iden & r -- irreflexive + ~r in r -- symmetric + ~r.r in iden -- functional + r.~r in iden -- injective + univ in r.univ -- total + univ in univ.r -- onto + } + } + +run show for 4 + +assert ReformulateNonEmptinessOK { + all r: univ->univ | + some r iff (some x, y: univ | x->y in r) + } + +check ReformulateNonEmptinessOK diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/ring.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/ring.als new file mode 100644 index 00000000..ec577666 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/ring.als @@ -0,0 +1,9 @@ +module appendixA/ring + +sig Node { next: set Node } + +pred isRing { + // You have to fill in the appropriate formula here +} + +run isRing for exactly 4 Node diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/spanning.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/spanning.als new file mode 100644 index 00000000..5218e700 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/spanning.als @@ -0,0 +1,17 @@ +module appendixA/spanning + +pred isTree [r: univ->univ] { + // You have to fill in the appropriate formula here +} + +pred spans [r1, r2: univ->univ] { + // You have to fill in the appropriate formula here +} + +pred show [r, t1, t2: univ->univ] { + spans [t1,r] and isTree [t1] + spans [t2,r] and isTree [t2] + t1 != t2 +} + +run show for 3 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/tree.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/tree.als new file mode 100644 index 00000000..74750d40 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/tree.als @@ -0,0 +1,7 @@ +module appendixA/tree + +pred isTree [r:univ->univ] { + // You have to fill in the appropriate formula here +} + +run isTree for 4 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/tube.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/tube.als new file mode 100644 index 00000000..03af8de9 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/tube.als @@ -0,0 +1,21 @@ +module appendixA/tube + +abstract sig Station { + jubilee, central, circle: set Station + } + +sig Jubilee, Central, Circle in Station {} + +one sig + Stanmore, BakerStreet, BondStreet, Westminster, Waterloo, + WestRuislip, EalingBroadway, NorthActon, NottingHillGate, + LiverpoolStreet, Epping + extends Station {} + +fact { + // the constraints should go here + } + +pred show {} + +run show diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/undirected.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/undirected.als new file mode 100644 index 00000000..937cedb1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixA/undirected.als @@ -0,0 +1,11 @@ +module appendixA/undirected + +sig Node { adjs: set Node } + +pred acyclic { + adjs = ~adjs + // You have to fill in additional formula here +} + +run acyclic for 4 + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixE/hotel.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixE/hotel.thm new file mode 100644 index 00000000..fe20fbe1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixE/hotel.thm @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixE/p300-hotel.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixE/p300-hotel.als new file mode 100644 index 00000000..813846b2 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixE/p300-hotel.als @@ -0,0 +1,66 @@ +module hotel + +open util/ordering [Time] as timeOrder + +sig Key, Time {} + +sig Card { + fst, snd: Key + } + +sig Room { + key: Key one->Time + } + +one sig Desk { + issued: Key->Time, + prev: (Room->lone Key)->Time + } + +sig Guest { + cards: Card->Time + } + +pred init [t: Time] { + Desk.prev.t = key.t + no issued.t and no cards.t ------ bug! (see page 303) + } + +pred checkin [t,t': Time, r: Room, g: Guest] { + some c: Card { + c.fst = r.(Desk.prev.t) + c.snd not in Desk.issued.t + cards.t' = cards.t + g->c ------------- bug! (see page 306) + Desk.issued.t' = Desk.issued.t + c.snd + Desk.prev.t' = Desk.prev.t ++ r->c.snd + } + key.t = key.t' + } + +pred enter [t,t': Time, r: Room, g: Guest] { + some c: g.cards.t | + let k = r.key.t { + c.snd = k and key.t' = key.t + or c.fst = k and key.t' = key.t ++ r->c.snd + } + issued.t = issued.t' and (Desk<:prev).t = prev.t' + cards.t = cards.t' + } + +fact Traces { + init [first] + all t: Time - last | some g: Guest, r: Room | + checkin [t, t.next, r, g] or enter[t, t.next, r, g] + } + +assert NoIntruder { + no t1: Time, g: Guest, g': Guest-g, r: Room | + let t2=t1.next, t3=t2.next, t4=t3.next { + enter [t1, t2, r, g] + enter [t2, t3, r, g'] + enter [t3, t4, r, g] + } + } + +-- This check reveals a bug (similar to Fig E.3) in which the initial key was issued twice. +check NoIntruder for 3 but 6 Time, 1 Room, 2 Guest diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixE/p303-hotel.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixE/p303-hotel.als new file mode 100644 index 00000000..652de3d8 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixE/p303-hotel.als @@ -0,0 +1,70 @@ +module hotel + +open util/ordering [Time] as timeOrder + +sig Key, Time {} + +sig Card { + fst, snd: Key + } + +sig Room { + key: Key one->Time + } + +one sig Desk { + issued: Key->Time, + prev: (Room->lone Key)->Time + } + +sig Guest { + cards: Card->Time + } + +pred init [t: Time] { + Desk.prev.t = key.t + Desk.issued.t = Room.key.t and no cards.t + } + +pred checkin [t,t': Time, r: Room, g: Guest] { + some c: Card { + c.fst = r.(Desk.prev.t) + c.snd not in Desk.issued.t + cards.t' = cards.t + g->c ------------- bug! (see page 306) + Desk.issued.t' = Desk.issued.t + c.snd + Desk.prev.t' = Desk.prev.t ++ r->c.snd + } + key.t = key.t' + } + +pred enter [t,t': Time, r: Room, g: Guest] { + some c: g.cards.t | + let k = r.key.t { + c.snd = k and key.t' = key.t + or c.fst = k and key.t' = key.t ++ r->c.snd + } + issued.t = issued.t' and (Desk<:prev).t = prev.t' + cards.t = cards.t' + } + +fact Traces { + init [first] + all t: Time - last | some g: Guest, r: Room | + checkin [t, t.next, r, g] or enter[t, t.next, r, g] + } + +assert NoIntruder { + no t1: Time, g: Guest, g': Guest-g, r: Room | + let t2=t1.next, t3=t2.next, t4=t3.next { + enter [t1, t2, r, g] + enter [t2, t3, r, g'] + enter [t3, t4, r, g] + } + } + +-- This check now succeeds without finding any counterexample. +check NoIntruder for 3 but 6 Time, 1 Room, 2 Guest + +-- To increase our confidence, we can increase the scope. +-- This time, it finds a counterexample. +check NoIntruder for 4 but 7 Time, 1 Room, 2 Guest diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixE/p306-hotel.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixE/p306-hotel.als new file mode 100644 index 00000000..efcd7e7d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/appendixE/p306-hotel.als @@ -0,0 +1,73 @@ +module hotel + +open util/ordering [Time] as timeOrder + +sig Key, Time {} + +sig Card { + fst, snd: Key + } + +sig Room { + key: Key one->Time + } + +one sig Desk { + issued: Key->Time, + prev: (Room->lone Key)->Time + } + +sig Guest { + cards: Card->Time + } + +pred init [t: Time] { + Desk.prev.t = key.t + Desk.issued.t = Room.key.t and no cards.t + } + +pred checkin [t,t': Time, r: Room, g: Guest] { + some c: Card { + c.fst = r.(Desk.prev.t) + c.snd not in Desk.issued.t + cards.t' = cards.t ++ g->c + Desk.issued.t' = Desk.issued.t + c.snd + Desk.prev.t' = Desk.prev.t ++ r->c.snd + } + key.t = key.t' + } + +pred enter [t,t': Time, r: Room, g: Guest] { + some c: g.cards.t | + let k = r.key.t { + c.snd = k and key.t' = key.t + or c.fst = k and key.t' = key.t ++ r->c.snd + } + issued.t = issued.t' and (Desk<:prev).t = prev.t' + cards.t = cards.t' + } + +fact Traces { + init [first] + all t: Time - last | some g: Guest, r: Room | + checkin [t, t.next, r, g] or enter[t, t.next, r, g] + } + +assert NoIntruder { + no t1: Time, g: Guest, g': Guest-g, r: Room | + let t2=t1.next, t3=t2.next, t4=t3.next { + enter [t1, t2, r, g] + enter [t2, t3, r, g'] + enter [t3, t4, r, g] + } + } + +-- This check now succeeds without finding any counterexample. +check NoIntruder for 3 but 6 Time, 1 Room, 2 Guest + +-- This check now succeeds without finding any counterexample. +check NoIntruder for 4 but 7 Time, 1 Room, 2 Guest + +-- We can try to increase the scope further. +-- This check also succeeds without finding any counterexample. +check NoIntruder for 6 but 12 Time, 3 Room, 3 Guest diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1a.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1a.als new file mode 100644 index 00000000..643c0f2c --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1a.als @@ -0,0 +1,12 @@ +module tour/addressBook1a ----- Page 6 + +sig Name, Addr { } + +sig Book { + addr: Name -> lone Addr +} + +pred show { } + +// This command generates an instance similar to Fig 2.1 +run show for 3 but 1 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1b.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1b.als new file mode 100644 index 00000000..1d4255e9 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1b.als @@ -0,0 +1,14 @@ +module tour/addressBook1b ----- Page 8 + +sig Name, Addr { } + +sig Book { + addr: Name -> lone Addr +} + +pred show [b: Book] { + #b.addr > 1 +} + +// This command generates an instance similar to Fig 2.2 +run show for 3 but 1 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1c.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1c.als new file mode 100644 index 00000000..85b18616 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1c.als @@ -0,0 +1,15 @@ +module tour/addressBook1c ----- Page 8 + +sig Name, Addr { } + +sig Book { + addr: Name -> lone Addr +} + +pred show [b: Book] { + #b.addr > 1 + some n: Name | #n.(b.addr) > 1 +} + +// This command should not find any instance. +run show for 3 but 1 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1d.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1d.als new file mode 100644 index 00000000..c553a4f9 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1d.als @@ -0,0 +1,15 @@ +module tour/addressBook1d ----- Page 9 + +sig Name, Addr { } + +sig Book { + addr: Name -> lone Addr +} + +pred show [b: Book] { + #b.addr > 1 + #Name.(b.addr) > 1 +} + +// This command generates an instance similar to Fig 2.3 +run show for 3 but 1 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1e.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1e.als new file mode 100644 index 00000000..18165f34 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1e.als @@ -0,0 +1,14 @@ +module tour/addressBook1e ----- Page 11 + +sig Name, Addr { } + +sig Book { + addr: Name -> lone Addr +} + +pred add [b, b': Book, n: Name, a: Addr] { + b'.addr = b.addr + n->a +} + +// This command generates an instance similar to Fig 2.4 +run add for 3 but 2 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1f.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1f.als new file mode 100644 index 00000000..8774cd7b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1f.als @@ -0,0 +1,19 @@ +module tour/addressBook1f ----- Page 12 + +sig Name, Addr { } + +sig Book { + addr: Name -> lone Addr +} + +pred add [b, b': Book, n: Name, a: Addr] { + b'.addr = b.addr + n->a +} + +pred showAdd [b, b': Book, n: Name, a: Addr] { + add [b, b', n, a] + #Name.(b'.addr) > 1 +} + +// This command generates an instance similar to Fig 2.5 +run showAdd for 3 but 2 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1g.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1g.als new file mode 100644 index 00000000..4eeac73a --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1g.als @@ -0,0 +1,29 @@ +module tour/addressBook1g ----- Page 14 + +sig Name, Addr { } + +sig Book { + addr: Name -> lone Addr +} + +pred add [b, b': Book, n: Name, a: Addr] { + b'.addr = b.addr + n->a +} + +pred del [b, b': Book, n: Name] { + b'.addr = b.addr - n->Addr +} + +fun lookup [b: Book, n: Name] : set Addr { + n.(b.addr) +} + +assert delUndoesAdd { + all b, b', b'': Book, n: Name, a: Addr | + add [b, b', n, a] and del [b', b'', n] + implies + b.addr = b''.addr +} + +// This command generates an instance similar to Fig 2.6 +check delUndoesAdd for 3 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1h.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1h.als new file mode 100644 index 00000000..115eab78 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook1h.als @@ -0,0 +1,64 @@ +module tour/addressBook1h ------- Page 14..16 + +sig Name, Addr { } + +sig Book { + addr: Name -> lone Addr +} + +pred show [b: Book] { + #b.addr > 1 + #Name.(b.addr) > 1 +} +run show for 3 but 1 Book + +pred add [b, b': Book, n: Name, a: Addr] { + b'.addr = b.addr + n->a +} + +pred del [b, b': Book, n: Name] { + b'.addr = b.addr - n->Addr +} + +fun lookup [b: Book, n: Name] : set Addr { + n.(b.addr) +} + +pred showAdd [b, b': Book, n: Name, a: Addr] { + add [b, b', n, a] + #Name.(b'.addr) > 1 +} +run showAdd for 3 but 2 Book + +assert delUndoesAdd { + all b, b', b'': Book, n: Name, a: Addr | + no n.(b.addr) and add [b, b', n, a] and del [b', b'', n] + implies + b.addr = b''.addr +} + +assert addIdempotent { + all b, b', b'': Book, n: Name, a: Addr | + add [b, b', n, a] and add [b', b'', n, a] + implies + b'.addr = b''.addr +} + +assert addLocal { + all b, b': Book, n, n': Name, a: Addr | + add [b, b', n, a] and n != n' + implies + lookup [b, n'] = lookup [b', n'] +} + +// This command should not find any counterexample. +check delUndoesAdd for 3 + +// This command should not find any counterexample. +check delUndoesAdd for 10 but 3 Book + +// This command should not find any counterexample. +check addIdempotent for 3 + +// This command should not find any counterexample. +check addLocal for 3 but 2 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook2a.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook2a.als new file mode 100644 index 00000000..ab94951b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook2a.als @@ -0,0 +1,16 @@ +module tour/addressBook2a ----- Page 18 + +abstract sig Target { } +sig Addr extends Target { } +abstract sig Name extends Target { } + +sig Alias, Group extends Name { } + +sig Book { + addr: Name->Target +} + +pred show [b:Book] { some b.addr } + +// This command generates an instance similar to Fig 2.9 +run show for 3 but 1 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook2b.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook2b.als new file mode 100644 index 00000000..a6d1da91 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook2b.als @@ -0,0 +1,18 @@ +module tour/addressBook2b ----- Page 19 + +abstract sig Target { } +sig Addr extends Target { } +abstract sig Name extends Target { } + +sig Alias, Group extends Name { } + +sig Book { + addr: Name->Target +} { + no n: Name | n in n.^addr +} + +pred show [b:Book] { some b.addr } + +// This command generates an instance similar to Fig 2.10 +run show for 3 but 1 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook2c.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook2c.als new file mode 100644 index 00000000..33ded6b3 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook2c.als @@ -0,0 +1,18 @@ +module tour/addressBook2c ----- Page 20 + +abstract sig Target { } +sig Addr extends Target { } +abstract sig Name extends Target { } + +sig Alias, Group extends Name { } + +sig Book { + addr: Name->Target +} { + no n: Name | n in n.^addr +} + +pred show [b:Book] { some Alias.(b.addr) } + +// This command generates an instance similar to Fig 2.11 +run show for 3 but 1 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook2d.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook2d.als new file mode 100644 index 00000000..adac4fbe --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook2d.als @@ -0,0 +1,19 @@ +module tour/addressBook2d ----- Page 21 + +abstract sig Target { } +sig Addr extends Target { } +abstract sig Name extends Target { } + +sig Alias, Group extends Name { } + +sig Book { + addr: Name->Target +} { + no n: Name | n in n.^addr + all a: Alias | lone a.addr +} + +pred show [b:Book] { some Alias.(b.addr) } + +// This command generates an instance similar to Fig 2.12 +run show for 3 but 1 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook2e.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook2e.als new file mode 100644 index 00000000..3baea5ac --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook2e.als @@ -0,0 +1,56 @@ +module tour/addressBook2e --- this is the final model in Fig 2.14 + +abstract sig Target { } +sig Addr extends Target { } +abstract sig Name extends Target { } + +sig Alias, Group extends Name { } + +sig Book { + names: set Name, + addr: names->some Target +} { + no n: Name | n in n.^addr + all a: Alias | lone a.addr +} + +pred add [b, b': Book, n: Name, t: Target] { b'.addr = b.addr + n->t } +pred del [b, b': Book, n: Name, t: Target] { b'.addr = b.addr - n->t } +fun lookup [b: Book, n: Name] : set Addr { n.^(b.addr) & Addr } + +assert delUndoesAdd { + all b, b', b'': Book, n: Name, t: Target | + no n.(b.addr) and add [b, b', n, t] and del [b', b'', n, t] + implies + b.addr = b''.addr +} + +// This should not find any counterexample. +check delUndoesAdd for 3 + +assert addIdempotent { + all b, b', b'': Book, n: Name, t: Target | + add [b, b', n, t] and add [b', b'', n, t] + implies + b'.addr = b''.addr +} + +// This should not find any counterexample. +check addIdempotent for 3 + +assert addLocal { + all b, b': Book, n, n': Name, t: Target | + add [b, b', n, t] and n != n' + implies + lookup [b, n'] = lookup [b', n'] +} + +// This shows a counterexample similar to Fig 2.13 +check addLocal for 3 but 2 Book + +assert lookupYields { + all b: Book, n: b.names | some lookup [b,n] +} + +// This shows a counterexample similar to Fig 2.12 +check lookupYields for 4 but 1 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook3a.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook3a.als new file mode 100644 index 00000000..5ff9eee0 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook3a.als @@ -0,0 +1,38 @@ +module tour/addressBook3a ----- Page 25 + +open util/ordering [Book] as BookOrder + +abstract sig Target { } +sig Addr extends Target { } +abstract sig Name extends Target { } + +sig Alias, Group extends Name { } + +sig Book { + names: set Name, + addr: names->some Target +} { + no n: Name | n in n.^addr + all a: Alias | lone a.addr +} + +pred add [b, b': Book, n: Name, t: Target] { b'.addr = b.addr + n->t } +pred del [b, b': Book, n: Name, t: Target] { b'.addr = b.addr - n->t } +fun lookup [b: Book, n: Name] : set Addr { n.^(b.addr) & Addr } + +pred init [b: Book] { no b.addr } + +fact traces { + init [first] + all b: Book-last | + let b' = b.next | + some n: Name, t: Target | + add [b, b', n, t] or del [b, b', n, t] +} + +------------------------------------------------------ + +pred show { } + +// This command generates an instance similar to Fig 2.15 +run show for 4 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook3b.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook3b.als new file mode 100644 index 00000000..5c4b835d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook3b.als @@ -0,0 +1,76 @@ +module tour/addressBook3b ----- Page 26 + +open util/ordering [Book] as BookOrder + +abstract sig Target { } +sig Addr extends Target { } +abstract sig Name extends Target { } + +sig Alias, Group extends Name { } + +sig Book { + names: set Name, + addr: names->some Target +} { + no n: Name | n in n.^addr + all a: Alias | lone a.addr +} + +pred add [b, b': Book, n: Name, t: Target] { b'.addr = b.addr + n->t } +pred del [b, b': Book, n: Name, t: Target] { b'.addr = b.addr - n->t } +fun lookup [b: Book, n: Name] : set Addr { n.^(b.addr) & Addr } + +pred init [b: Book] { no b.addr } + +fact traces { + init [first] + all b: Book-last | + let b' = b.next | + some n: Name, t: Target | + add [b, b', n, t] or del [b, b', n, t] +} + +------------------------------------------------------ + +assert delUndoesAdd { + all b, b', b'': Book, n: Name, t: Target | + no n.(b.addr) and add [b, b', n, t] and del [b', b'', n, t] + implies + b.addr = b''.addr +} + +// This should not find any counterexample. +check delUndoesAdd for 3 + +------------------------------------------------------ + +assert addIdempotent { + all b, b', b'': Book, n: Name, t: Target | + add [b, b', n, t] and add [b', b'', n, t] + implies + b'.addr = b''.addr +} + +// This should not find any counterexample. +check addIdempotent for 3 + +------------------------------------------------------ + +assert addLocal { + all b, b': Book, n, n': Name, t: Target | + add [b, b', n, t] and n != n' + implies + lookup [b, n'] = lookup [b', n'] +} + +// This should not find any counterexample. +check addLocal for 3 but 2 Book + +------------------------------------------------------ + +assert lookupYields { + all b: Book, n: b.names | some lookup [b,n] +} + +// This shows a counterexample similar to Fig 2.16 +check lookupYields for 3 but 4 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook3c.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook3c.als new file mode 100644 index 00000000..284f8c36 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook3c.als @@ -0,0 +1,81 @@ +module tour/addressBook3c ----- Page 27 + +open util/ordering [Book] as BookOrder + +abstract sig Target { } +sig Addr extends Target { } +abstract sig Name extends Target { } + +sig Alias, Group extends Name { } + +sig Book { + names: set Name, + addr: names->some Target +} { + no n: Name | n in n.^addr + all a: Alias | lone a.addr +} + +pred add [b, b': Book, n: Name, t: Target] { + t in Addr or some lookup [b, Name&t] + b'.addr = b.addr + n->t +} + +pred del [b, b': Book, n: Name, t: Target] { b'.addr = b.addr - n->t } + +fun lookup [b: Book, n: Name] : set Addr { n.^(b.addr) & Addr } + +pred init [b: Book] { no b.addr } + +fact traces { + init [first] + all b: Book-last | + let b' = b.next | + some n: Name, t: Target | + add [b, b', n, t] or del [b, b', n, t] +} + +------------------------------------------------------ + +assert delUndoesAdd { + all b, b', b'': Book, n: Name, t: Target | + no n.(b.addr) and add [b, b', n, t] and del [b', b'', n, t] + implies + b.addr = b''.addr +} + +// This should not find any counterexample. +check delUndoesAdd for 3 + +------------------------------------------------------ + +assert addIdempotent { + all b, b', b'': Book, n: Name, t: Target | + add [b, b', n, t] and add [b', b'', n, t] + implies + b'.addr = b''.addr +} + +// This should not find any counterexample. +check addIdempotent for 3 + +------------------------------------------------------ + +assert addLocal { + all b, b': Book, n, n': Name, t: Target | + add [b, b', n, t] and n != n' + implies + lookup [b, n'] = lookup [b', n'] +} + +// This should not find any counterexample. +check addLocal for 3 but 2 Book + +------------------------------------------------------ + +assert lookupYields { + all b: Book, n: b.names | some lookup [b,n] +} + +// This shows a counterexample similar to Fig 2.17 +check lookupYields for 3 but 4 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook3d.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook3d.als new file mode 100644 index 00000000..aceac514 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/addressBook3d.als @@ -0,0 +1,87 @@ +module tour/addressBook3d ----- this is the final model in fig 2.18 + +open util/ordering [Book] as BookOrder + +abstract sig Target { } +sig Addr extends Target { } +abstract sig Name extends Target { } + +sig Alias, Group extends Name { } + +sig Book { + names: set Name, + addr: names->some Target +} { + no n: Name | n in n.^addr + all a: Alias | lone a.addr +} + +pred add [b, b': Book, n: Name, t: Target] { + t in Addr or some lookup [b, Name&t] + b'.addr = b.addr + n->t +} + +pred del [b, b': Book, n: Name, t: Target] { + no b.addr.n or some n.(b.addr) - t + b'.addr = b.addr - n->t +} + +fun lookup [b: Book, n: Name] : set Addr { n.^(b.addr) & Addr } + +pred init [b: Book] { no b.addr } + +fact traces { + init [first] + all b: Book-last | + let b' = b.next | + some n: Name, t: Target | + add [b, b', n, t] or del [b, b', n, t] +} + +------------------------------------------------------ + +assert delUndoesAdd { + all b, b', b'': Book, n: Name, t: Target | + no n.(b.addr) and add [b, b', n, t] and del [b', b'', n, t] + implies + b.addr = b''.addr +} + +// This should not find any counterexample. +check delUndoesAdd for 3 + +------------------------------------------------------ + +assert addIdempotent { + all b, b', b'': Book, n: Name, t: Target | + add [b, b', n, t] and add [b', b'', n, t] + implies + b'.addr = b''.addr +} + +// This should not find any counterexample. +check addIdempotent for 3 + +------------------------------------------------------ + +assert addLocal { + all b, b': Book, n, n': Name, t: Target | + add [b, b', n, t] and n != n' + implies + lookup [b, n'] = lookup [b', n'] +} + +// This should not find any counterexample. +check addLocal for 3 but 2 Book + +------------------------------------------------------ + +assert lookupYields { + all b: Book, n: b.names | some lookup [b,n] +} + +// This should not find any counterexample. +check lookupYields for 3 but 4 Book + +// This should not find any counterexample. +check lookupYields for 6 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/theme.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/theme.thm new file mode 100644 index 00000000..2b839993 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter2/theme.thm @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter4/filesystem.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter4/filesystem.als new file mode 100644 index 00000000..c45e776b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter4/filesystem.als @@ -0,0 +1,28 @@ +module chapter4/filesystem ----- The model from page 125 + +abstract sig Object {} + +sig Dir extends Object {contents: set Object} + +one sig Root extends Dir { } + +sig File extends Object {} + +fact { + Object in Root.*contents + } + +assert SomeDir { + all o: Object - Root | some contents.o + } +check SomeDir // This assertion is valid + +assert RootTop { + no o: Object | Root in o.contents + } +check RootTop // This assertion should produce a counterexample + +assert FileInDir { + all f: File | some contents.f + } +check FileInDir // This assertion is valid diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter4/grandpa1.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter4/grandpa1.als new file mode 100644 index 00000000..c05c85c9 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter4/grandpa1.als @@ -0,0 +1,44 @@ +module language/grandpa1 ---- Page 84, 85 + +abstract sig Person { + father: lone Man, + mother: lone Woman + } + +sig Man extends Person { + wife: lone Woman + } + +sig Woman extends Person { + husband: lone Man + } + +fact { + no p: Person | p in p.^(mother+father) + wife = ~husband + } + +assert NoSelfFather { + no m: Man | m = m.father + } + +// This should not find any counterexample. +check NoSelfFather + +fun grandpas [p: Person] : set Person { + p.(mother+father).father + } + +pred ownGrandpa [p: Person] { + p in p.grandpas + } + +// This should not find any instance. +run ownGrandpa for 4 Person + +assert NoSelfGrandpa { + no p: Person | p in p.grandpas + } + +// This should not find any counterexample +check NoSelfGrandpa for 4 Person diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter4/grandpa2.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter4/grandpa2.als new file mode 100644 index 00000000..08dda731 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter4/grandpa2.als @@ -0,0 +1,38 @@ +module language/grandpa2 ---- Page 86 + +abstract sig Person { + father: lone Man, + mother: lone Woman + } + +sig Man extends Person { + wife: lone Woman + } + +sig Woman extends Person { + husband: lone Man + } + +fact { + no p: Person | p in p.^(mother+father) + wife = ~husband + } + +assert NoSelfFather { + no m: Man | m = m.father + } + +// This should not find any counterexample. +check NoSelfFather + +fun grandpas [p: Person] : set Person { + let parent = mother + father + father.wife + mother.husband | + p.parent.parent & Man + } + +pred ownGrandpa [p: Person] { + p in p.grandpas + } + +// This generates an instance similar to Fig 4.2 +run ownGrandpa for 4 Person diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter4/grandpa3.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter4/grandpa3.als new file mode 100644 index 00000000..d9147cbf --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter4/grandpa3.als @@ -0,0 +1,70 @@ +module language/grandpa3 ---- the final model in fig 4.4 + +abstract sig Person { + father: lone Man, + mother: lone Woman + } + +sig Man extends Person { + wife: lone Woman + } + +sig Woman extends Person { + husband: lone Man + } + +fact Biology { + no p: Person | p in p.^(mother+father) + } + +fact Terminology { + wife = ~husband + } + +fact SocialConvention { + no (wife+husband) & ^(mother+father) + } + +------------------------------------------ + +assert NoSelfFather { + no m: Man | m = m.father + } + +// This should not find any counterexample. +check NoSelfFather + +------------------------------------------ + +fun grandpas [p: Person] : set Person { + let parent = mother + father + father.wife + mother.husband | + p.parent.parent & Man + } + +pred ownGrandpa [p: Person] { + p in p.grandpas + } + +// This generates an instance similar to Fig 4.3 +run ownGrandpa for 4 Person + +------------------------------------------ + +pred SocialConvention1 { + no (wife + husband) & ^(mother + father) + } + +pred SocialConvention2 { + let parent = mother + father { + no m: Man | some m.wife and m.wife in m.*parent.mother + no w: Woman | some w.husband and w.husband in w.*parent.father + } + } + +// This assertion was described on page 90. +assert Same { + SocialConvention1 iff SocialConvention2 + } + +// This should not find any counterexample +check Same diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter4/lights.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter4/lights.als new file mode 100644 index 00000000..24997705 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter4/lights.als @@ -0,0 +1,41 @@ +module chapter4/lights ----- The model from page 127 + +abstract sig Color {} + +one sig Red, Yellow, Green extends Color {} + +fun colorSequence: Color -> Color { + Color <: iden + Red->Green + Green->Yellow + Yellow->Red + } + +sig Light {} +sig LightState {color: Light -> one Color} +sig Junction {lights: set Light} + +fun redLights [s: LightState]: set Light { s.color.Red } + +pred mostlyRed [s: LightState, j: Junction] { + lone j.lights - redLights[s] + } + +pred trans [s, s': LightState, j: Junction] { + lone x: j.lights | s.color[x] != s'.color[x] + all x: j.lights | + let step = s.color[x] -> s'.color[x] { + step in colorSequence + step in Red->(Color-Red) => j.lights in redLights[s] + } + } + +assert Safe { + all s, s': LightState, j: Junction | + mostlyRed [s, j] and trans [s, s', j] => mostlyRed [s', j] + } + +check Safe for 3 but 1 Junction + +//assert ColorSequenceDeterministic { +// all c: Color | lone c.colorSequence +// } +// +//check ColorSequenceDeterministic diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter5/addressBook.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter5/addressBook.als new file mode 100644 index 00000000..5d7dee56 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter5/addressBook.als @@ -0,0 +1,26 @@ +module chapter5/addressBook --- the model in fig 5.1 + +abstract sig Target {} + +sig Addr extends Target {} +sig Name extends Target {} +sig Book {addr: Name -> Target} + +fact Acyclic {all b: Book | no n: Name | n in n.^(b.addr)} + +pred add [b, b': Book, n: Name, t: Target] { + b'.addr = b.addr + n -> t + } + +// This command should produce an instance similar to Fig 5.2 +run add for 3 but 2 Book + +fun lookup [b: Book, n: Name]: set Addr {n.^(b.addr) & Addr} + +assert addLocal { + all b,b': Book, n,n': Name, t: Target | + add [b,b',n,t] and n != n' => lookup [b,n'] = lookup [b',n'] + } + +// This command should produce a counterexample similar to Fig 5.3 +check addLocal for 3 but 2 Book diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter5/lists.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter5/lists.als new file mode 100644 index 00000000..79cbd0da --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter5/lists.als @@ -0,0 +1,23 @@ +module chapter5/lists ---- page 157 + +some sig Element {} + +abstract sig List {} +one sig EmptyList extends List {} +sig NonEmptyList extends List { + element: Element, + rest: List + } + +fact ListGenerator { + all list: List, e: Element | + some list': List | list'.rest = list and list'.element = e + } + +assert FalseAssertion { + all list: List | list != list + } + +// This check finds no counterexample since +// the only possible counterexamples are infinite. +check FalseAssertion diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter5/sets1.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter5/sets1.als new file mode 100644 index 00000000..dc998820 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter5/sets1.als @@ -0,0 +1,16 @@ +module chapter5/sets1 ----- page 156 + +sig Set { + elements: set Element +} + +sig Element {} + +assert Closed { + all s0, s1: Set | + some s2: Set | + s2.elements = s0.elements + s1.elements + } + +// This check should produce a counterexample +check Closed diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter5/sets2.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter5/sets2.als new file mode 100644 index 00000000..265a1e64 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter5/sets2.als @@ -0,0 +1,21 @@ +module chapter5/sets2 ----- page 157 + +sig Set { + elements: set Element +} + +sig Element {} + +assert Closed { + all s0, s1: Set | + some s2: Set | + s2.elements = s0.elements + s1.elements + } + +fact SetGenerator { + some s: Set | no s.elements + all s: Set, e: Element | some s': Set | s'.elements = s.elements + e + } + +// This check should not produce a counterexample +check Closed for 4 Element, 16 Set diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/hotel.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/hotel.thm new file mode 100644 index 00000000..acdb8d09 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/hotel.thm @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/hotel1.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/hotel1.als new file mode 100644 index 00000000..22610689 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/hotel1.als @@ -0,0 +1,101 @@ +module chapter6/hotel1 --- the model up to the top of page 191 + +open util/ordering[Time] as to +open util/ordering[Key] as ko + +sig Key {} +sig Time {} + +sig Room { + keys: set Key, + currentKey: keys one -> Time + } + +fact DisjointKeySets { + -- each key belongs to at most one room + Room<:keys in Room lone-> Key + } + +one sig FrontDesk { + lastKey: (Room -> lone Key) -> Time, + occupant: (Room -> Guest) -> Time + } + +sig Guest { + keys: Key -> Time + } + +fun nextKey [k: Key, ks: set Key]: set Key { + min [k.nexts & ks] + } + +pred init [t: Time] { + no Guest.keys.t + no FrontDesk.occupant.t + all r: Room | FrontDesk.lastKey.t [r] = r.currentKey.t + } + +pred entry [t, t': Time, g: Guest, r: Room, k: Key] { + k in g.keys.t + let ck = r.currentKey | + (k = ck.t and ck.t' = ck.t) or + (k = nextKey[ck.t, r.keys] and ck.t' = k) + noRoomChangeExcept [t, t', r] + noGuestChangeExcept [t, t', none] + noFrontDeskChange [t, t'] + } + +pred noFrontDeskChange [t, t': Time] { + FrontDesk.lastKey.t = FrontDesk.lastKey.t' + FrontDesk.occupant.t = FrontDesk.occupant.t' + } + +pred noRoomChangeExcept [t, t': Time, rs: set Room] { + all r: Room - rs | r.currentKey.t = r.currentKey.t' + } + +pred noGuestChangeExcept [t, t': Time, gs: set Guest] { + all g: Guest - gs | g.keys.t = g.keys.t' + } + +pred checkout [t, t': Time, g: Guest] { + let occ = FrontDesk.occupant { + some occ.t.g + occ.t' = occ.t - Room ->g + } + FrontDesk.lastKey.t = FrontDesk.lastKey.t' + noRoomChangeExcept [t, t', none] + noGuestChangeExcept [t, t', none] + } + +pred checkin [t, t': Time, g: Guest, r: Room, k: Key] { + g.keys.t' = g.keys.t + k + let occ = FrontDesk.occupant { + no occ.t [r] + occ.t' = occ.t + r -> g + } + let lk = FrontDesk.lastKey { + lk.t' = lk.t ++ r -> k + k = nextKey [lk.t [r], r.keys] + } + noRoomChangeExcept [t, t', none] + noGuestChangeExcept [t, t', g] + } + +fact traces { + init [first] + all t: Time-last | let t' = t.next | + some g: Guest, r: Room, k: Key | + entry [t, t', g, r, k] + or checkin [t, t', g, r, k] + or checkout [t, t', g] + } + +assert NoBadEntry { + all t: Time, r: Room, g: Guest, k: Key | + let t' = t.next, o = FrontDesk.occupant.t[r] | + entry [t, t', g, r, k] and some o => g in o + } + +// This generates a counterexample similar to Fig 6.6 +check NoBadEntry for 3 but 2 Room, 2 Guest, 5 Time diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/hotel2.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/hotel2.als new file mode 100644 index 00000000..09378f2e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/hotel2.als @@ -0,0 +1,110 @@ +module chapter6/hotel2 --- the final model in Fig 6.7 + +open util/ordering[Time] as to +open util/ordering[Key] as ko + +sig Key {} +sig Time {} + +sig Room { + keys: set Key, + currentKey: keys one -> Time + } + +fact DisjointKeySets { + -- each key belongs to at most one room + Room<:keys in Room lone-> Key + } + +one sig FrontDesk { + lastKey: (Room -> lone Key) -> Time, + occupant: (Room -> Guest) -> Time + } + +sig Guest { + keys: Key -> Time + } + +fun nextKey [k: Key, ks: set Key]: set Key { + min [k.nexts & ks] + } + +pred init [t: Time] { + no Guest.keys.t + no FrontDesk.occupant.t + all r: Room | FrontDesk.lastKey.t [r] = r.currentKey.t + } + +pred entry [t, t': Time, g: Guest, r: Room, k: Key] { + k in g.keys.t + let ck = r.currentKey | + (k = ck.t and ck.t' = ck.t) or + (k = nextKey[ck.t, r.keys] and ck.t' = k) + noRoomChangeExcept [t, t', r] + noGuestChangeExcept [t, t', none] + noFrontDeskChange [t, t'] + } + +pred noFrontDeskChange [t, t': Time] { + FrontDesk.lastKey.t = FrontDesk.lastKey.t' + FrontDesk.occupant.t = FrontDesk.occupant.t' + } + +pred noRoomChangeExcept [t, t': Time, rs: set Room] { + all r: Room - rs | r.currentKey.t = r.currentKey.t' + } + +pred noGuestChangeExcept [t, t': Time, gs: set Guest] { + all g: Guest - gs | g.keys.t = g.keys.t' + } + +pred checkout [t, t': Time, g: Guest] { + let occ = FrontDesk.occupant { + some occ.t.g + occ.t' = occ.t - Room ->g + } + FrontDesk.lastKey.t = FrontDesk.lastKey.t' + noRoomChangeExcept [t, t', none] + noGuestChangeExcept [t, t', none] + } + +pred checkin [t, t': Time, g: Guest, r: Room, k: Key] { + g.keys.t' = g.keys.t + k + let occ = FrontDesk.occupant { + no occ.t [r] + occ.t' = occ.t + r -> g + } + let lk = FrontDesk.lastKey { + lk.t' = lk.t ++ r -> k + k = nextKey [lk.t [r], r.keys] + } + noRoomChangeExcept [t, t', none] + noGuestChangeExcept [t, t', g] + } + +fact traces { + init [first] + all t: Time-last | let t' = t.next | + some g: Guest, r: Room, k: Key | + entry [t, t', g, r, k] + or checkin [t, t', g, r, k] + or checkout [t, t', g] + } + +fact NoIntervening { + all t: Time-last | let t' = t.next, t" = t'.next | + all g: Guest, r: Room, k: Key | + checkin [t, t', g, r, k] => (entry [t', t", g, r, k] or no t") + } + +assert NoBadEntry { + all t: Time, r: Room, g: Guest, k: Key | + let t' = t.next, o = FrontDesk.occupant.t[r] | + entry [t, t', g, r, k] and some o => g in o + } + +// After adding the NoIntervening fact, +// these commands no longer generate counterexamples +check NoBadEntry for 3 but 2 Room, 2 Guest, 5 Time +check NoBadEntry for 3 but 3 Room, 3 Guest, 7 Time +check NoBadEntry for 5 but 3 Room, 3 Guest, 9 Time diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/hotel3.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/hotel3.als new file mode 100644 index 00000000..b3ad4b49 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/hotel3.als @@ -0,0 +1,92 @@ +module chapter6/hotel3 --- model in Fig 6.10 without the NonIntervening fact + +open util/ordering[Time] as to +open util/ordering[Key] as ko + +sig Key, Time {} + +sig Room { + keys: set Key, + currentKey: keys one -> Time + } + +fact { + Room <: keys in Room lone -> Key + } + +one sig FrontDesk { + lastKey: (Room -> lone Key) -> Time, + occupant: (Room -> Guest) -> Time + } + +sig Guest { + keys: Key -> Time + } + +fun nextKey [k: Key, ks: set Key]: set Key { + min [k.nexts & ks] + } + +pred init [t: Time] { + no Guest.keys.t + no FrontDesk.occupant.t + all r: Room | FrontDesk.lastKey.t [r] = r.currentKey.t + } + +abstract sig Event { + pre, post: Time, + guest: Guest + } + +abstract sig RoomKeyEvent extends Event { + room: Room, + key: Key + } + +sig Entry extends RoomKeyEvent { } { + key in guest.keys.pre + let ck = room.currentKey | + (key = ck.pre and ck.post = ck.pre) or + (key = nextKey[ck.pre, room.keys] and ck.post = key) + currentKey.post = currentKey.pre ++ room->key + } + +sig Checkin extends RoomKeyEvent { } { + keys.post = keys.pre + guest -> key + let occ = FrontDesk.occupant { + no occ.pre [room] + occ.post = occ.pre + room -> guest + } + let lk = FrontDesk.lastKey { + lk.post = lk.pre ++ room -> key + key = nextKey [lk.pre [room], room.keys] + } + } + +sig Checkout extends Event { } { + let occ = FrontDesk.occupant { + some occ.pre.guest + occ.post = occ.pre - Room -> guest + } + } + +fact Traces { + init [first] + all t: Time-last | + let t' = t.next | + some e: Event { + e.pre = t and e.post = t' + currentKey.t != currentKey.t' => e in Entry + occupant.t != occupant.t' => e in Checkin + Checkout + (lastKey.t != lastKey.t' or keys.t != keys.t') => e in Checkin + } + } + +assert NoBadEntry { + all e: Entry | + let o=FrontDesk.occupant.(e.pre) [e.room] | + some o => e.guest in o + } + +// This generates a counterexample similar to Fig 6.13 +check NoBadEntry for 5 but 3 Room, 3 Guest, 5 Time, 4 Event diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/hotel4.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/hotel4.als new file mode 100644 index 00000000..35f3566b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/hotel4.als @@ -0,0 +1,103 @@ +module chapter6/hotel4 --- model in Fig 6.10 with the NonIntervening fact + +open util/ordering[Time] as to +open util/ordering[Key] as ko + +sig Key, Time {} + +sig Room { + keys: set Key, + currentKey: keys one -> Time + } + +fact { + Room <: keys in Room lone -> Key + } + +one sig FrontDesk { + lastKey: (Room -> lone Key) -> Time, + occupant: (Room -> Guest) -> Time + } + +sig Guest { + keys: Key -> Time + } + +fun nextKey [k: Key, ks: set Key]: set Key { + min [k.nexts & ks] + } + +pred init [t: Time] { + no Guest.keys.t + no FrontDesk.occupant.t + all r: Room | FrontDesk.lastKey.t [r] = r.currentKey.t + } + +abstract sig Event { + pre, post: Time, + guest: Guest + } + +abstract sig RoomKeyEvent extends Event { + room: Room, + key: Key + } + +sig Entry extends RoomKeyEvent { } { + key in guest.keys.pre + let ck = room.currentKey | + (key = ck.pre and ck.post = ck.pre) or + (key = nextKey[ck.pre, room.keys] and ck.post = key) + currentKey.post = currentKey.pre ++ room->key + } + +sig Checkin extends RoomKeyEvent { } { + keys.post = keys.pre + guest -> key + let occ = FrontDesk.occupant { + no occ.pre [room] + occ.post = occ.pre + room -> guest + } + let lk = FrontDesk.lastKey { + lk.post = lk.pre ++ room -> key + key = nextKey [lk.pre [room], room.keys] + } + } + +sig Checkout extends Event { } { + let occ = FrontDesk.occupant { + some occ.pre.guest + occ.post = occ.pre - Room -> guest + } + } + +fact Traces { + init [first] + all t: Time-last | + let t' = t.next | + some e: Event { + e.pre = t and e.post = t' + currentKey.t != currentKey.t' => e in Entry + occupant.t != occupant.t' => e in Checkin + Checkout + (lastKey.t != lastKey.t' or keys.t != keys.t') => e in Checkin + } + } + +assert NoBadEntry { + all e: Entry | + let o=FrontDesk.occupant.(e.pre) [e.room] | + some o => e.guest in o + } + +fact NoIntervening { + all c: Checkin | + c.post = last + or some e: Entry { + e.pre = c.post + e.room = c.room + e.guest = c.guest + } + } + +// After adding the NoIntervening fact, +// this command no longer generates a counterexample +check NoBadEntry for 5 but 3 Room, 3 Guest, 9 Time, 8 Event diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/mediaAssets.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/mediaAssets.als new file mode 100644 index 00000000..668b3130 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/mediaAssets.als @@ -0,0 +1,117 @@ +module chapter6/mediaAssets + +sig ApplicationState { + catalogs: set Catalog, + catalogState: catalogs -> one CatalogState, + currentCatalog: catalogs, + buffer: set Asset + } + +sig Catalog, Asset {} + +sig CatalogState { + assets: set Asset, + disj hidden, showing: set assets, + selection: set assets + Undefined + } { + hidden+showing = assets + } + +one sig Undefined {} + +pred catalogInv [cs: CatalogState] { + cs.selection = Undefined or (some cs.selection and cs.selection in cs.showing) + } + +pred appInv [xs: ApplicationState] { + all cs: xs.catalogs | catalogInv [xs.catalogState[cs]] + } + +pred showSelected [cs, cs': CatalogState] { + cs.selection != Undefined + cs'.showing = cs.selection + cs'.selection = cs.selection + cs'.assets = cs.assets + } + +pred hideSelected [cs, cs': CatalogState] { + cs.selection != Undefined + cs'.hidden = cs.hidden + cs.selection + cs'.selection = Undefined + cs'.assets = cs.assets + } + +pred cut [xs, xs': ApplicationState] { + let cs = xs.currentCatalog.(xs.catalogState), sel = cs.selection { + sel != Undefined + xs'.buffer = sel + some cs': CatalogState { + cs'.assets = cs.assets - sel + cs'.showing = cs.showing - sel + cs'.selection = Undefined + xs'.catalogState = xs.catalogState ++ xs.currentCatalog -> cs' + } + } + xs'.catalogs = xs.catalogs + xs'.currentCatalog = xs.currentCatalog + } + +pred paste [xs, xs': ApplicationState] { + let cs = xs.currentCatalog.(xs.catalogState), buf = xs.buffer { + xs'.buffer = buf + some cs': CatalogState { + cs'.assets = cs.assets + buf + cs'.showing = cs.showing + (buf - cs.assets) + cs'.selection = buf - cs.assets + xs'.catalogState = xs.catalogState ++ xs.currentCatalog -> cs' + } + } + xs'.catalogs = xs.catalogs + xs'.currentCatalog = xs.currentCatalog + } + +assert HidePreservesInv { + all cs, cs': CatalogState | + catalogInv [cs] and hideSelected [cs, cs'] => catalogInv [cs'] + } + +// This check should not find any counterexample +check HidePreservesInv + +pred sameApplicationState [xs, xs': ApplicationState] { + xs'.catalogs = xs.catalogs + all c: xs.catalogs | sameCatalogState [c.(xs.catalogState), c.(xs'.catalogState)] + xs'.currentCatalog = xs.currentCatalog + xs'.buffer = xs.buffer + } + +pred sameCatalogState [cs, cs': CatalogState] { + cs'.assets = cs.assets + cs'.showing = cs.showing + cs'.selection = cs.selection + } + +assert CutPaste { + all xs, xs', xs": ApplicationState | + (appInv [xs] and cut [xs, xs'] and paste [xs', xs"]) => sameApplicationState [xs, xs"] + } + +// This check should find a counterexample +check CutPaste + +assert PasteCut { + all xs, xs', xs": ApplicationState | + (appInv [xs] and paste [xs, xs'] and cut [xs', xs"]) => sameApplicationState [xs, xs"] + } + +// This check should find a counterexample +check PasteCut + +assert PasteNotAffectHidden { + all xs, xs': ApplicationState | + (appInv [xs] and paste [xs, xs']) => + let c = xs.currentCatalog | xs'.catalogState[c].hidden = xs.catalogState[c].hidden + } + +// This check should not find any counterexample +check PasteNotAffectHidden diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/memory/abstractMemory.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/memory/abstractMemory.als new file mode 100644 index 00000000..3d676d50 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/memory/abstractMemory.als @@ -0,0 +1,33 @@ +module chapter6/memory/abstractMemory [Addr, Data] ----- the model from page 217 + +sig Memory { + data: Addr -> lone Data + } + +pred init [m: Memory] { + no m.data + } + +pred write [m, m': Memory, a: Addr, d: Data] { + m'.data = m.data ++ a -> d + } + +pred read [m: Memory, a: Addr, d: Data] { + let d' = m.data [a] | some d' implies d = d' + } + +fact Canonicalize { + no disj m, m': Memory | m.data = m'.data + } + +// This command should not find any counterexample +WriteRead: check { + all m, m': Memory, a: Addr, d1, d2: Data | + write [m, m', a, d1] and read [m', a, d2] => d1 = d2 + } + +// This command should not find any counterexample +WriteIdempotent: check { + all m, m', m": Memory, a: Addr, d: Data | + write [m, m', a, d] and write [m', m", a, d] => m' = m" + } diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/memory/cacheMemory.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/memory/cacheMemory.als new file mode 100644 index 00000000..c95fe22b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/memory/cacheMemory.als @@ -0,0 +1,43 @@ +module chapter6/memory/cacheMemory [Addr, Data] ----- the model from page 219 + +sig CacheSystem { + main, cache: Addr -> lone Data + } + +pred init [c: CacheSystem] { + no c.main + c.cache + } + +pred write [c, c': CacheSystem, a: Addr, d: Data] { + c'.main = c.main + c'.cache = c.cache ++ a -> d + } + +pred read [c: CacheSystem, a: Addr, d: Data] { + some d + d = c.cache [a] + } + +pred load [c, c': CacheSystem] { + some addrs: set c.main.Data - c.cache.Data | + c'.cache = c.cache ++ addrs <: c.main + c'.main = c.main + } + +pred flush [c, c': CacheSystem] { + some addrs: some c.cache.Data { + c'.main = c.main ++ addrs <: c.cache + c'.cache = c.cache - addrs -> Data + } + } + +// This command should not find any counterexample +LoadNotObservable: check { + all c, c', c": CacheSystem, a1, a2: Addr, d1, d2, d3: Data | + { + read [c, a2, d2] + write [c, c', a1, d1] + load [c', c"] + read [c", a2, d3] + } implies d3 = (a1=a2 => d1 else d2) + } diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/memory/checkCache.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/memory/checkCache.als new file mode 100644 index 00000000..8214389b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/memory/checkCache.als @@ -0,0 +1,34 @@ +module chapter6/memory/checkCache [Addr, Data] + +open chapter6/memory/cacheMemory [Addr, Data] as cache +open chapter6/memory/abstractMemory [Addr, Data] as amemory + +fun alpha [c: CacheSystem]: Memory { + {m: Memory | m.data = c.main ++ c.cache} + } + +// This check should not produce a counterexample +ReadOK: check { + // introduction of m, m' ensures that they exist, and gives witnesses if counterexample + all c: CacheSystem, a: Addr, d: Data, m: Memory | + cache/read [c, a, d] and m = alpha [c] => amemory/read [m, a, d] + } + +// This check should not produce a counterexample +WriteOK: check { + all c, c': CacheSystem, a: Addr, d: Data, m, m': Memory | + cache/write [c, c', a, d] and m = alpha [c] and m' = alpha [c'] + => amemory/write [m, m', a, d] + } + +// This check should not produce a counterexample +LoadOK: check { + all c, c': CacheSystem, m, m': Memory | + cache/load [c, c'] and m = alpha [c] and m' = alpha [c'] => m = m' + } + +// This check should not produce a counterexample +FlushOK: check { + all c, c': CacheSystem, m, m': Memory | + cache/flush [c, c'] and m = alpha [c] and m' = alpha [c'] => m = m' + } diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/memory/checkFixedSize.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/memory/checkFixedSize.als new file mode 100644 index 00000000..20d291d1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/memory/checkFixedSize.als @@ -0,0 +1,28 @@ +module chapter6/memory/checkFixedSize [Addr, Data] + +open chapter6/memory/fixedSizeMemory_H [Addr, Data] as fmemory +open chapter6/memory/abstractMemory [Addr, Data] as amemory + +// define abstraction function from history-extended concrete state to abstract state +pred alpha [fm: fmemory/Memory_H, am: amemory/Memory] { + am.data = fm.data - (fm.unwritten -> Data) + } + +// This check should not find a counterexample +initOk: check { + all fm: fmemory/Memory_H, am: amemory/Memory | + fmemory/init [fm] and alpha [fm, am] => amemory/init [am] + } + +// This check should not find a counterexample +readOk: check { + all fm: fmemory/Memory_H, a: Addr, d: Data, am: amemory/Memory | + fmemory/read [fm, a, d] and alpha [fm, am] => amemory/read [am, a, d] + } + +// This check should not find a counterexample +writeOk: check { + all fm, fm': fmemory/Memory_H, a: Addr, d: Data, am, am': amemory/Memory | + fmemory/write [fm, fm', a, d] and alpha [fm, am] and alpha [fm', am'] + implies amemory/write [am, am', a, d] + } diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/memory/fixedSizeMemory.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/memory/fixedSizeMemory.als new file mode 100644 index 00000000..df6ab2a9 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/memory/fixedSizeMemory.als @@ -0,0 +1,21 @@ +module chapter6/memory/fixedSizeMemory [Addr, Data] + +sig Memory { + data: Addr -> one Data + } + +pred init [m: Memory] { + // This predicate is empty in order to allow non-deterministic initialization + } + +pred write [m, m': Memory, a: Addr, d: Data] { + m'.data = m.data ++ a -> d + } + +pred read [m: Memory, a: Addr, d: Data] { + d = m.data [a] + } + +fact Canonicalize { + no disj m, m': Memory | m.data = m'.data + } diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/memory/fixedSizeMemory_H.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/memory/fixedSizeMemory_H.als new file mode 100644 index 00000000..15785991 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/memory/fixedSizeMemory_H.als @@ -0,0 +1,21 @@ +module chapter6/memory/fixedSizeMemory_H [Addr, Data] + +open chapter6/memory/fixedSizeMemory [Addr, Data] as memory + +sig Memory_H extends memory/Memory { + unwritten: set Addr + } + +pred init [m: Memory_H] { + memory/init [m] + m.unwritten = Addr + } + +pred read [m: Memory_H, a: Addr, d: Data] { + memory/read [m, a, d] + } + +pred write [m, m': Memory_H, a: Addr, d: Data] { + memory/write [m, m', a, d] + m'.unwritten = m.unwritten - a + } diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/ringElection.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/ringElection.thm new file mode 100644 index 00000000..0d172180 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/ringElection.thm @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/ringElection1.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/ringElection1.als new file mode 100644 index 00000000..043b6a07 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/ringElection1.als @@ -0,0 +1,57 @@ +module chapter6/ringElection1 --- the version up to the top of page 181 + +open util/ordering[Time] as TO +open util/ordering[Process] as PO + +sig Time {} + +sig Process { + succ: Process, + toSend: Process -> Time, + elected: set Time + } + +fact ring { + all p: Process | Process in p.^succ + } + +pred init [t: Time] { + all p: Process | p.toSend.t = p + } + +pred step [t, t': Time, p: Process] { + let from = p.toSend, to = p.succ.toSend | + some id: from.t { + from.t' = from.t - id + to.t' = to.t + (id - p.succ.prevs) + } + } + +fact defineElected { + no elected.first + all t: Time-first | elected.t = {p: Process | p in p.toSend.t - p.toSend.(t.prev)} + } + +fact traces { + init [first] + all t: Time-last | + let t' = t.next | + all p: Process | + step [t, t', p] or step [t, t', succ.p] or skip [t, t', p] + } + +pred skip [t, t': Time, p: Process] { + p.toSend.t = p.toSend.t' + } + +pred show { some elected } +run show for 3 Process, 4 Time +// This generates an instance similar to Fig 6.4 + +assert AtMostOneElected { lone elected.Time } +check AtMostOneElected for 3 Process, 7 Time +// This should not find any counterexample + +assert AtLeastOneElected { some t: Time | some elected.t } +check AtLeastOneElected for 3 Process, 7 Time +// This generates a counterexample in which nothing happens diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/ringElection2.als b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/ringElection2.als new file mode 100644 index 00000000..16bee928 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/book/chapter6/ringElection2.als @@ -0,0 +1,74 @@ +module chapter6/ringElection2 --- the final version (as depicted in Fig 6.1) + +open util/ordering[Time] as TO +open util/ordering[Process] as PO + +sig Time {} + +sig Process { + succ: Process, + toSend: Process -> Time, + elected: set Time + } + +fact ring { + all p: Process | Process in p.^succ + } + +pred init [t: Time] { + all p: Process | p.toSend.t = p + } + +pred step [t, t': Time, p: Process] { + let from = p.toSend, to = p.succ.toSend | + some id: from.t { + from.t' = from.t - id + to.t' = to.t + (id - p.succ.prevs) + } + } + +fact defineElected { + no elected.first + all t: Time-first | elected.t = {p: Process | p in p.toSend.t - p.toSend.(t.prev)} + } + +fact traces { + init [first] + all t: Time-last | + let t' = t.next | + all p: Process | + step [t, t', p] or step [t, t', succ.p] or skip [t, t', p] + } + +pred skip [t, t': Time, p: Process] { + p.toSend.t = p.toSend.t' + } + +pred show { some elected } +run show for 3 Process, 4 Time +// This generates an instance similar to Fig 6.4 + +assert AtMostOneElected { lone elected.Time } +check AtMostOneElected for 3 Process, 7 Time +// This should not find any counterexample + +pred progress { + all t: Time - TO/last | + let t' = TO/next [t] | + some Process.toSend.t => some p: Process | not skip [t, t', p] + } + +assert AtLeastOneElected { progress => some elected.Time } +check AtLeastOneElected for 3 Process, 7 Time +// This should not find any counterexample + +pred looplessPath { no disj t, t': Time | toSend.t = toSend.t' } + +// This produces an instance +run looplessPath for 3 Process, 12 Time + +// This does not produce an instance +run looplessPath for 3 Process, 13 Time + +// Therefore, we can conclude that a scope of 12 for Time is +// sufficient to reach all states of the protocol for a three-node ring. diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/dijkstra.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/dijkstra.als new file mode 100644 index 00000000..ab342811 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/dijkstra.als @@ -0,0 +1,120 @@ +module examples/algorithms/dijkstra + +/* + * Models how mutexes are grabbed and released by processes, and + * how Dijkstra's mutex ordering criterion can prevent deadlocks. + * + * For a detailed description, see: + * E. W. Dijkstra, Cooperating sequential processes. Technological + * University, Eindhoven, The Netherlands, September 1965. + * Reprinted in Programming Languages, F. Genuys, Ed., Academic + * Press, New York, 1968, 43-112. + * + * Acknowledgements to Ulrich Geilmann for finding and fixing a bug + * in the GrabMutex predicate. + * + */ + +open util/ordering [State] as so +open util/ordering [Mutex] as mo + +sig Process {} +sig Mutex {} + +sig State { holds, waits: Process -> Mutex } + + +pred Initial [s: State] { no s.holds + s.waits } + +pred IsFree [s: State, m: Mutex] { + // no process holds this mutex + no m.~(s.holds) + // all p: Process | m !in p.(this.holds) +} + +pred IsStalled [s: State, p: Process] { some p.(s.waits) } + +pred GrabMutex [s: State, p: Process, m: Mutex, s': State] { + // a process can only act if it is not + // waiting for a mutex + !s.IsStalled[p] + // can only grab a mutex we do not yet hold + m !in p.(s.holds) + // mutexes are grabbed in order + all m': p.(s.holds) | mo/lt[m',m] + s.IsFree[m] => { + // if the mutex is free, we now hold it, + // and do not become stalled + p.(s'.holds) = p.(s.holds) + m + no p.(s'.waits) + } else { + // if the mutex was not free, + // we still hold the same mutexes we held, + // and are now waiting on the mutex + // that we tried to grab. + p.(s'.holds) = p.(s.holds) + p.(s'.waits) = m + } + all otherProc: Process - p | { + otherProc.(s'.holds) = otherProc.(s.holds) + otherProc.(s'.waits) = otherProc.(s.waits) + } +} + +pred ReleaseMutex [s: State, p: Process, m: Mutex, s': State] { + !s.IsStalled[p] + m in p.(s.holds) + p.(s'.holds) = p.(s.holds) - m + no p.(s'.waits) + no m.~(s.waits) => { + no m.~(s'.holds) + no m.~(s'.waits) + } else { + some lucky: m.~(s.waits) | { + m.~(s'.waits) = m.~(s.waits) - lucky + m.~(s'.holds) = lucky + } + } + all mu: Mutex - m { + mu.~(s'.waits) = mu.~(s.waits) + mu.~(s'.holds)= mu.~(s.holds) + } +} + +/** + * for every adjacent (pre,post) pair of States, + * one action happens: either some process grabs a mutex, + * or some process releases a mutex, + * or nothing happens (have to allow this to show deadlocks) + */ +pred GrabOrRelease { + Initial[so/first] && + ( + all pre: State - so/last | let post = so/next [pre] | + (post.holds = pre.holds && post.waits = pre.waits) + || + (some p: Process, m: Mutex | pre.GrabMutex [p, m, post]) + || + (some p: Process, m: Mutex | pre.ReleaseMutex [p, m, post]) + + ) +} + +pred Deadlock { + some Process + some s: State | all p: Process | some p.(s.waits) +} + +assert DijkstraPreventsDeadlocks { + GrabOrRelease => ! Deadlock +} + + +pred ShowDijkstra { + GrabOrRelease && Deadlock + some waits +} + +run Deadlock for 3 expect 1 +run ShowDijkstra for 5 State, 2 Process, 2 Mutex expect 1 +check DijkstraPreventsDeadlocks for 5 State, 5 Process, 4 Mutex expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/dijkstra.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/dijkstra.thm new file mode 100644 index 00000000..3be2d6c2 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/dijkstra.thm @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/messaging.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/messaging.als new file mode 100644 index 00000000..0815fb44 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/messaging.als @@ -0,0 +1,228 @@ +module examples/algorithms/messaging + +/* + * Generic messaging among several nodes + * + * By default, messages can be lost (i.e. never become visible to the + * recipient node) or may be arbitrarily delayed. Also, by default + * out-of-order delivery is allowed. + */ + +open util/ordering[Tick] as ord +open util/relation as rel + +sig Node {} + +sig MsgState { + /** Node that sent the message */ + from: Node, + + /** Intended recipient(s) of a message; note that broadcasts are allowed */ + to: set Node +} + +sig Msg { + state: MsgState, + + /** Timestamp: the tick on which the message was sent */ + sentOn: Tick, + + /** tick at which node reads message, if read */ + readOn: Node -> lone Tick +}{ + readOn.Tick in state.to +} + +sig Tick { + /** The state of each node */ + state: Node -> one NodeState, + + /** + * Definition of what each node does on this tick: + * + * Typically, a node would determine + * the messages it sends and its next state, based on its current + * state and the messages it reads. + * + * Messages that the node _can_ read in this tick, i.e. messages available + * for reading at the beginning of this tick. The messages that + * the node actually reads are a subset of this set. Determined by + * constraints in this module. + */ + visible: Node -> Msg, + + /** + * Messages that the node _actually reads_ in this tick. Must be a subset + * of visible. Determined by constraints of the particular system + * that uses this module. + */ + read: Node -> Msg, + + /** + * Messages sent by the node in this tick. They become visible to + * (and can be read by) their recipients on the next tick. + */ + sent: Node -> Msg, + + /** + * Messages available for sending at this tick. A given message + * atom is only used once, and then it gets removed from the available + * set and cannot be used to represent messages sent on subsequent ticks. + * Also, two different nodes cannot send the same message atom. + * So, a message atom represents a particular single physical message + * sent by a given node on a given tick. + */ + available: set Msg, + + /** + * For each node, at each tick, the number of messages it _needs_ to send. + * Used to rule out "proofs" of liveness violations that are caused + * solely by not having enough messages available for sending. + */ + needsToSend: Node -> Msg +} + +fun MsgsSentOnTick[t: Tick]: set Msg { t.sent[Node] } +fun MsgsVisibleOnTick[t: Tick]: set Msg { t.visible[Node] } +fun MsgsReadOnTick[t: Tick]: set Msg { t.read[Node] } + +fact MsgMovementConstraints { + // At the beginning, no messages have been sent yet + no ord/first.visible[Node] + + // Messages sent on a given tick become visible to recipient(s) + // on the subsequent tick. + all pre: Tick - ord/last | + let post = ord/next[pre] | { + // messages sent on this tick are no longer available on subsequent tick + post.available = pre.available - MsgsSentOnTick[pre] + } + + all t: Tick | { + // Messages sent on a tick are taken from the pool of available + // (not-yet-sent) message atoms + MsgsSentOnTick[t] in t.available + + // Timestamps are correct + MsgsSentOnTick[t].sentOn in t + MsgsReadOnTick[t].readOn[Node] in t + + // The only new message atoms are those sent by nodes + MsgsSentOnTick[t] = t.sent[Node] + + all n: Node, m: Msg | + m.readOn[n] = t => m in t.read[n] + // Return addresses are correct + all n: Node | t.sent[n].state.from in n + + // messages sent to a node on a tick become visible to that node on some subseqent tick, + // and permanently stop being visible to that node on the tick after that node reads the message + all n: Node, m: Msg | { + // message starts being visible to node n no earlier than it is sent; + // only messages sent to this node are visible to this node. + (m in t.visible[n] => (n in m.state.to && m.sentOn in ord/prevs[t])) + // message permanently stops being visible immediately after being read + (m in t.read[n] => m !in ord/nexts[t].visible[n]) + } + } +} + +sig NodeState { +} + +fun MsgsLiveOnTick[t: Tick]: set Msg { + Msg - { future: Msg | future.sentOn in ord/nexts[t] } + - { past: Msg | all n: past.state.to | past.readOn[n] in ord/prevs[t] } +} + +pred TicksEquivalent[t1, t2: Tick] { + t1.state = t2.state + some r: (MsgsLiveOnTick[t1] - MsgsVisibleOnTick[t1]) one -> one (MsgsLiveOnTick[t2] - MsgsVisibleOnTick[t2]) | + all m1: dom[r] | let m2 = m1.r | { + m1.(Msg<:state) = m2.state + } + some r: MsgsVisibleOnTick[t1] one -> one MsgsVisibleOnTick[t2] | + all m1: dom[r] | let m2 = m1.r | { + m1.(Msg<:state) = m2.state + } +} + +pred Loop { + some t: Tick - ord/last | TicksEquivalent[t, ord/last] +} + +fact CleanupViz { + // cleans up visualization without precluding any interesting traces + + // all messages must be sent + Msg in Tick.sent[Node] +} + +pred ReadInOrder { + // + // This function ensures that messages are read in order. + // + + // for all pairs of nodes + all n1, n2: Node | + // for all pairs of messages sent from n1 to n2 + all m1, m2: Msg | + { + m1.state.from = n1 + m2.state.from = n1 + m1.state.to = n2 + m2.state.to = n2 + } => { + // if both m1 and m2 are read by n2, *and* + // n2 reads m1 before m2, then m1 must have + // been sent before m2 + (some m1.readOn[n2] && some m2.readOn[n2] && + m1.readOn[n2] in ord/prevs[m2.readOn[n2]]) => + ord/lte[m1.sentOn, m2.sentOn] + } +} + +fact ReadOnlyVisible { read in visible } + +/** + * this function ensures that messages will not + * be lost, i.e. a message send to a node will + * eventually be visible to that node + */ +pred NoLostMessages { + all m: Msg | + (m.sentOn != ord/last) => (all n: m.state.to | + some t: ord/nexts[m.sentOn] | + m in t.visible[n]) +} + +/** + * this function ensures that there will be + * no shortage of messages in the available + * message pool during the trace + */ +pred NoMessageShortage { + all t: Tick - ord/last | + (sum n: Node | # t.needsToSend[n]) =< # t.available +} + +pred SomeState { + # Node > 1 + //# Tick$read > 1 +} + +pred OutOfOrder { + ! ReadInOrder + # Msg = 2 +} + +run SomeState for 2 expect 1 +run OutOfOrder for 4 expect 1 + + + +// DEFINED VARIABLES +// Defined variables are uncalled, no-argument functions. +// They are helpful for getting good visualization. +fun FROM: Msg -> Node {{m: Msg, n: Node | n in m.state.from}} +fun TO: Msg -> Node {{m: Msg, n: Node | n in m.state.to}} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/messaging.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/messaging.thm new file mode 100644 index 00000000..53f28d8d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/messaging.thm @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/opt_spantree.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/opt_spantree.als new file mode 100644 index 00000000..7c129325 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/opt_spantree.als @@ -0,0 +1,220 @@ +module examples/algorithms/opt_spantree + +/* + * Direct specification of a distributed spanning tree algorithm + * over arbitrary network topologies + * + * Each process has a parent and a level, both of which are + * initally null. A distinct root node exists at which the + * algorithm starts. In the first step, the root assigns itself + * the level of zero and sends its level to its neighbors. + * Subsequently, if a node reads a message with level k, it sets + * its level to k+1, records the sender of the message as its + * parent, and sends the level k+1 to its neighbors. Once a node + * has set its level and parent, it ignores subsequent messages. + * Eventually, the parent pointers will form a spanning tree, + * rooted at Root. + * + * We model communication through a state-reading model, in which + * nodes can directly read the state of their neighbors. Messages + * are not explicity modelled. This makes no difference for this + * algorithm since once a node sends a message, the state of the + * node stays the same as the contents of the message. + */ + +open util/ordering[Lvl] as lo +open util/ordering[State] as so +open util/graph[Process] as graph + +sig Process { + adj : set Process +} + +one sig Root extends Process {} + +/** + * intuitively, the depth level at which + * a process resides in the spanning tree, + * with the root at level zero + */ +sig Lvl {} + +fact processGraph { + graph/noSelfLoops[adj] // for viz + graph/undirected[adj] // adjacency is symmetric + Process in Root.*adj // everything reachable from root +} + +sig State { + /** + * the set of processes which execute in this state. + * used to allow flexibility in how many processes + * run simultaneously + */ + runs : set Process, + + /** + * the level of a process in this state + */ + lvl: Process -> lone Lvl, + + /** + * who the process thinks is its parent in this state. + * the parent pointers should eventually become + * the spanning tree + */ + parent: Process -> lone Process +} + +/** + * initially, the lvl and parent fields are blank + */ +pred Init { + let fs = so/first | { + no fs.lvl + no fs.parent + } +} + +/** + * simple NOP transition + */ +pred TRNop[p : Process, pre, post: State] { + pre.lvl[p] = post.lvl[p] + pre.parent[p] = post.parent[p] +} + +/** + * preconditions for a process to actually act + * in a certain pre-state + * used to preclude stalling of entire system + * for no reason (see TransIfPossible) + */ +pred TRActPreConds[p : Process, pre : State] { + // can't already have a level + no pre.lvl[p] + // must have a neighbor with a set level so + // p can read it + // Root doesn't need to read value from a + // neighbor + (p = Root || some pre.lvl[p.adj]) +} + +/** + * transition which changes state of a process + */ +pred TRAct[p : Process, pre, post : State] { + // can't already have a level + no pre.lvl[p] + (p = Root) => { + // the root sets its level to + // 0, and has no parent pointer + post.lvl[p] = lo/first + no post.parent[p] + } else { + // choose some adjacent process + // whose level is already set + some adjProc: p.adj | + let nLvl = pre.lvl[adjProc] | { + some nLvl + // p's parent is the adjacent + // process, and p's level is one greater than + // the level of the adjacent process (since + // its one level deeper) + post.lvl[p] = lo/next[nLvl] + post.parent[p] = adjProc + } + } +} + +pred Trans[p : Process, pre, post : State] { + TRAct[p, pre, post] || + TRNop[p, pre, post] +} + +/** + * all processes do a nop transition in some + * state only when no process can act because + * preconditions are not met + */ +fact TransIfPossible { + all s : State - so/last | + (all p : Process | TRNop[p, s, so/next[s]]) => + (all p : Process | !TRActPreConds[p,s]) +} + +fact LegalTrans { + Init + all s : State - so/last | + let s' = so/next[s] | { + all p : Process | + p in s.runs => Trans[p, s, s'] else TRNop[p,s,s'] + } +} + +pred PossTrans[s, s' : State] { + all p : Process | Trans[p,s,s'] +} + +pred SpanTreeAtState[s : State] { + // all processes reachable through inverted parent pointers + // from root (spanning) + Process in Root.*~(s.parent) + // parent relation is a tree (DAG) + // we only need to check the DAG condition since there can + // be at most one parent for a process (constrained by + // multiplicity) + graph/dag[~(s.parent)] +} + +/** + * show a run that produces a spanning tree + */ +pred SuccessfulRun { + SpanTreeAtState[so/last] + all s : State - so/last | !SpanTreeAtState[s] +} + +/** + * show a trace without a loop + */ +pred TraceWithoutLoop { + all s, s' : State | s!=s' => { + !EquivStates[s, s'] + (s' in so/nexts[s] && (s' != so/next[s])) => !PossTrans[s,s'] + } + all s: State | !SpanTreeAtState[s] +} + +/** + * defines equivalent states + */ +pred EquivStates[s, s' : State] { + s.lvl = s'.lvl + s.parent = s'.parent +} + +/** + * show a trace that violates liveness + */ +pred BadLivenessTrace { + // two different states equivalent (loop) + some s, s' : State | s!=s' && EquivStates[s, s'] + all s : State | !SpanTreeAtState[s] +} + +/** + * check that once spanning tree is constructed, + * it remains + */ +assert Closure { + all s : State - so/last | + SpanTreeAtState[s] => (s.parent = so/next[s].parent) +} + +// note that for the worst case topology and choice of root, +// the scope of Lvl must equal the scope of Process +run SuccessfulRun for 4 State, exactly 5 Process, 3 Lvl expect 1 +// run TraceWithoutLoop for 8 but 9 State expect 1 +run BadLivenessTrace for 5 but 7 State expect 0 +check Closure for 5 but 7 State expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/opt_spantree.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/opt_spantree.thm new file mode 100644 index 00000000..1254faed --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/opt_spantree.thm @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/peterson.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/peterson.als new file mode 100644 index 00000000..6e6d59e5 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/peterson.als @@ -0,0 +1,206 @@ +module examples/algorithms/peterson + +/* + * Model of Peterson's algorithm for mutual exclusion of n + * processes. The names kept similar to Murphi specification + * to make correspondence clear. + */ + +open util/ordering[priority] as po +open util/ordering[State] as so + +sig pid { +} + +sig priority { +} + +fact { + # priority = # pid + 1 +} + +abstract sig label_t {} + +// here subtyping would help +one sig L0, L1, L2, L3, L4 extends label_t {} + +sig State { + P: pid -> label_t, + Q: pid -> priority, + turn: priority -> pid, + localj: pid -> priority +} + +pred NOPTrans[i: pid, pre, post : State] { + post.P[i] = pre.P[i] + post.Q[i] = pre.Q[i] + post.localj[i] = pre.localj[i] +} + +pred L0TransPre[i : pid, pre : State] { + // precondition + pre.P[i] = L0 +} + +pred L0Trans[i: pid, pre, post : State] { + L0TransPre[i, pre] + // localj[i] := 1 + post.localj[i] = po/next[po/first] + post.P[i] = L1 + post.Q[i] = pre.Q[i] + // something for turn? + post.turn = pre.turn +} + +pred L1TransPre[i : pid, pre : State] { + // precondition + pre.P[i] = L1 +} + +pred L1Trans[i : pid, pre, post : State] { + L1TransPre[i, pre] + post.localj[i] = pre.localj[i] + post.Q[i] = pre.localj[i] + post.P[i] = L2 + // something for turn? + post.turn = pre.turn +} + +pred L2TransPre[i : pid, pre : State] { + // precondition + pre.P[i] = L2 +} + +pred L2Trans[i : pid, pre, post : State] { + L2TransPre[i, pre] + post.localj[i] = pre.localj[i] + post.Q[i] = pre.Q[i] + post.P[i] = L3 + post.turn[post.localj[i]] = i + all j : priority - post.localj[i] | + post.turn[j] = pre.turn[j] +} + +pred L3TransPre[i : pid, pre : State] { + // precondition + pre.P[i] = L3 + + all k : pid - i | + po/lt[pre.Q[k], pre.localj[i]] || + pre.turn[pre.localj[i]] != i +} + +pred L3Trans[i : pid, pre, post : State] { + L3TransPre[i, pre] + post.localj[i] = po/next[pre.localj[i]] + po/lt[post.localj[i], po/last] => + post.P[i] = L1 + else + post.P[i] = L4 + post.Q[i] = pre.Q[i] + post.turn = pre.turn +} + +pred L4TransPre[i : pid, pre : State] { + // precondition + pre.P[i] = L4 +} + +pred L4Trans[i : pid, pre, post : State] { + L4TransPre[i, pre] + + post.P[i] = L0 + post.Q[i] = po/first + post.localj[i] = pre.localj[i] + post.turn = pre.turn +} + +pred RealTrans[i : pid, pre, post : State] { + L0Trans[i,pre,post] || + L1Trans[i,pre,post] || + L2Trans[i,pre,post] || + L3Trans[i,pre,post] || + L4Trans[i,pre,post] +} + +pred SomePre[i : pid, pre : State] { + L0TransPre[i, pre] || + L1TransPre[i, pre] || + L2TransPre[i, pre] || + L3TransPre[i, pre] || + L4TransPre[i, pre] +} + +fact Init { + let firstState = so/first | { + all i : pid | { + firstState.P[i] = L0 + firstState.Q[i] = po/first + } + no firstState.turn + no firstState.localj + } +} + +fact LegalTrans { + all pre : State - so/last | + let post = so/next[pre] | { + /*some i : pid | { + // HACK: + // need to specify that if some node + // can make a non-NOP transition, it + // does, but i can't figure out how + // right now + Trans(i,pre,post) && !NOPTrans(i,pre,post) + all j : pid - i | + NOPTrans(j,pre,post) + }*/ + all i : pid | + RealTrans[i,pre,post] || NOPTrans[i,pre,post] + (all i : pid | NOPTrans[i,pre,post]) => { + all i : pid | !SomePre[i,pre] + post.turn = pre.turn + } + } +} + +assert Safety { + all i1, i2 : pid, s : State | i1!=i2 => not (s.P[i1] = L4 && s.P[i2] = L4) +} + +assert NotStuck { + all pre : State - so/last | + let post = so/next[pre] | + some i : pid | + RealTrans[i, pre, post] && !NOPTrans[i,pre,post] +} + +pred TwoRun { + some s1, s2: State, i1, i2: pid | { + s1!=s2 + i1!=i2 + s1.P[i1] = L4 + s2.P[i2] = L4 + } +} + +pred ThreeRun { + some disj s1, s2, s3: State, disj i1, i2, i3: pid | { + s1.P[i1] = L4 + s2.P[i2] = L4 + s3.P[i3] = L4 + } +} + +// 2 pids requires 8 states +// 3 pids requires 16 states +run TwoRun for 13 but 3 pid, 4 priority, 5 label_t expect 1 + +// haven't run this one successfully yet +run ThreeRun for 19 but 3 pid,4 priority,5 label_t expect 1 + +// how many states do we need for this to match murphi? +check Safety for 10 but 2 pid, 3 priority, 5 label_t expect 0 + +// this assertion is trivial because of the hack described above +check NotStuck for 10 but 2 pid, 3 priority, 5 label_t expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/ringlead.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/ringlead.als new file mode 100644 index 00000000..b5a786a8 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/ringlead.als @@ -0,0 +1,150 @@ +module examples/algorithms/ringlead + +/* + * Model of leader election on a ring + * + * Each process has a unique ID, IDs are ordered. + * The algorithm elects the process with the highest + * ID the leader, as follows. First, each process + * sends its own ID to its right neighbor. + * Then, whenever a process receives an ID, if the + * ID is greater than the process' own ID it forwards + * the ID to its right neighbor, otherwise does nothing. + * When a process receives its own ID that process + * is the leader. + */ + +open util/boolean as bool +open examples/algorithms/messaging as msg +open util/ordering[msg/Node] as nodeOrd +open util/ordering[msg/Tick] as tickOrd + +sig RingLeadNode extends msg/Node { + rightNeighbor: msg/Node +} + +fact DefineRing { + (one msg/Node || (no n: msg/Node | n = n.rightNeighbor)) + all n: msg/Node | msg/Node in n.^rightNeighbor +} + +sig RingLeadMsgState extends msg/MsgState { + id: msg/Node +} + +sig MsgViz extends msg/Msg { + vFrom: msg/Node, + vTo: set msg/Node, + vId: msg/Node +} + +fact { + MsgViz = msg/Msg + vFrom = state.from + vTo = state.to + vId = state.id +} + + +sig RingLeadNodeState extends msg/NodeState { + leader: Bool +} + + +pred RingLeadFirstTrans [self: msg/Node, pre, post: msg/NodeState, + sees, reads, sends, needsToSend: set msg/Msg] { + one sends + # needsToSend = 1 + sends.state.to = self.rightNeighbor + sends.state.id = self + post.leader = False +} + +fact InitRingLeadState { + all n: msg/Node | + tickOrd/first.state[n].leader = False +} + +pred RingLeadRestTrans [self: msg/Node, pre, post: msg/NodeState, + sees, reads, sends, needsToSend: set msg/Msg] { + RingLeadTransHelper[self, sees, reads, sends, needsToSend] + post.leader = True iff (pre.leader = True || + self in reads.state.id) +} + +/** + * we take any messages whose node ids are higher than ours, + * and we forward them to the right neighbor. we drop + * all other messages. if we get a message with our own + * id, we're the leader. + */ +pred RingLeadTransHelper[self: msg/Node, sees, reads, sends, needsToSend: set msg/Msg] { + reads = sees + + all received: reads | + (received.state.id in nodeOrd/nexts[self]) => + (one weSend: sends | (weSend.state.id = received.state.id && weSend.state.to = self.rightNeighbor)) + + all weSend: sends | { + let mID = weSend.state.id | { + mID in nodeOrd/nexts[self] + mID in reads.state.id + weSend.state.to = self.rightNeighbor + } + //weSend.sentBecauseOf = { received : reads | received.id = weSend.id } + //all otherWeSend: sends - weSend | otherWeSend.id != weSend.id + } + + # needsToSend = # { m: reads | m.state.id in nodeOrd/nexts[self] } +} +fact RingLeadTransitions { + all n: msg/Node { + all t: msg/Tick - tickOrd/last | { + t = tickOrd/first => + RingLeadFirstTrans[n, t.state[n], tickOrd/next[t].state[n], t.visible[n], t.read[n], t.sent[n], t.needsToSend[n]] + else + RingLeadRestTrans[n, t.state[n], tickOrd/next[t].state[n], t.visible[n], t.read[n], t.sent[n], t.needsToSend[n]] + } + // also constrain last tick + RingLeadTransHelper[n, tickOrd/last.visible[n], tickOrd/last.read[n], tickOrd/last.sent[n], tickOrd/last.needsToSend[n]] + } +} + +assert OneLeader { + all t: msg/Tick | + lone n: msg/Node | + t.state[n].leader = True +} + +fact CleanupViz { + RingLeadNode = msg/Node + RingLeadMsgState = msg/MsgState + RingLeadNodeState = msg/NodeState +} + +pred SomeLeaderAtTick[t: msg/Tick] { + some n: msg/Node | t.state[n].leader = True +} + +pred NeverFindLeader { + msg/Loop + all t: msg/Tick | ! SomeLeaderAtTick[t] +} + +assert Liveness { + (msg/NoLostMessages && msg/NoMessageShortage) => ! NeverFindLeader +} + +pred SomeLeader { some t: msg/Tick | SomeLeaderAtTick[t] } + +assert LeaderHighest { + all t: msg/Tick, n: msg/Node | + t.state[n].leader = True => n = nodeOrd/last +} + +run NeverFindLeader for 1 but 3 msg/Tick, 2 Bool, 2 msg/NodeState expect 1 +check Liveness for 3 but 6 msg/Msg, 2 Bool, 2 msg/NodeState expect 0 +check OneLeader for 5 but 2 Bool, 2 msg/NodeState expect 0 +run SomeLeader for 2 but 3 msg/Node, 5 msg/Msg, 5 msg/Tick, 5 msg/MsgState expect 1 +check LeaderHighest for 3 but 2 msg/NodeState, 5 msg/Msg, 5 msg/MsgState, 5 msg/Tick expect 0 + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/ringlead.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/ringlead.thm new file mode 100644 index 00000000..95977a51 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/ringlead.thm @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/s_ringlead.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/s_ringlead.als new file mode 100644 index 00000000..8f96b477 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/s_ringlead.als @@ -0,0 +1,153 @@ +module examples/algorithms/s_ringlead + +/* + * Model of leader election on a ring. + * + * Each process has a unique ID, IDs are ordered. The algorithm + * elects the process with the highest ID the leader, as follows. + * First, each process sends its own ID to its right neighbor. + * Then, whenever a process receives an ID, if the ID is greater + * than the process' own ID it forwards the ID to its right + * neighbor, otherwise does nothing. When a process receives its + * own ID that process is the leader. + * + * Note: This file needs higher order quantifiers turned on. + */ + +open util/ordering[State] as so +open util/ordering[Process] as po +open util/graph[Process] as graph + +sig Process { + rightNeighbor: Process +} + +sig State { + // buffer which the right neighbor can read from + buffer: Process -> Process, + //sends, reads: Process -> Process, + runs: set Process, + leader: set Process +} + +fact DefineRing { + graph/ring[rightNeighbor] +} + +fact InitialState { + no so/first.buffer + no so/first.leader + Process in so/first.runs +} + + +fact CleanupLast { + let ls = so/last | + no ls.runs +} + +pred ValidTrans2[s, s': State] { + all p : s.runs | VT2Helper[p,s,s'] + all p : Process - s.runs | NOP2[p,s,s'] + NoMagicMsg[s,s'] + +} + +pred NoMagicMsg[s, s' : State] { + // no magically appearing messages + all p : Process, m : s'.buffer[p] | + m in s.buffer[p] || (!NOP2[p,s,s'] && + ((s = so/first && m = p) || + (s != so/first && m in s.buffer[p.~rightNeighbor] + && m !in s'.buffer[p.~rightNeighbor] && po/gt[m,p]))) +} + +pred PossTrans[s, s' : State] { + all p : Process | VT2Helper[p,s,s'] || NOP2[p,s,s'] + NoMagicMsg[s,s'] +} + +pred VT2Helper[p : Process, s, s' : State] { + ( + let readable=s.buffer[p.~rightNeighbor] | + (s = so/first) => { + p = s'.buffer[p] + readable in s'.buffer[p.~rightNeighbor] + p !in s'.leader + } else { + (some readable) => { + some m : set readable | { + m !in s'.buffer[p.~rightNeighbor] + // nothing else gets deleted + readable - m in s'.buffer[p.~rightNeighbor] + { m': m | po/gt[m',p] } /*m & nexts(p)*/ in s'.buffer[p] + p in s'.leader iff (p in s.leader || p in m) + } + } else NOP2[p,s,s'] + } + ) +} + +pred NOP2[p : Process, s,s': State] { + p in s'.leader iff p in s.leader + // no reads + s.buffer[p.~rightNeighbor] in s'.buffer[p.~rightNeighbor] + // no sends + s'.buffer[p] in s.buffer[p] +} + +pred Preconds[p : Process, s : State] { + s = so/first || some s.buffer[p.~rightNeighbor] +} + +fact TransIfPossible { + all s : State - so/last | + (all p : Process | NOP2[p, s, so/next[s]]) => + (all p : Process | !Preconds[p,s]) +} + +fact LegalTrans { + all s : State - so/last | + let s' = so/next[s] | + ValidTrans2[s,s'] +} + +pred EquivStates[s, s': State] { + s.buffer = s'.buffer + s.leader = s'.leader +} + +assert Safety { + all s : State | lone s.leader +} + +pred Legit[s : State] { + one s.leader +} + +pred BadLivenessTrace { + all s : State | !Legit[s] + let ls = so/last | + some s : State - ls | { + EquivStates[s, ls] + Process in (so/nexts[s] + s).runs + } +} + +pred TraceWithoutLoop { + all t1, t2 : State | t1!=t2 => !EquivStates[t1,t2] + all s, s' : State | (s' in (so/nexts[s] - so/next[s])) => !PossTrans[s,s'] + all s : State | !Legit[s] +} + +pred AltTrans { + SomeLeader +} + +pred SomeLeader { some State.leader } + +run BadLivenessTrace for 3 but 8 State expect 0 +run SomeLeader for 4 but 6 State expect 1 +check Safety for 7 expect 0 +// run TraceWithoutLoop for 5 but 13 State expect 1 +run AltTrans for 5 but 8 State expect 1 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/stable_mutex_ring.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/stable_mutex_ring.als new file mode 100644 index 00000000..d4a21f12 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/stable_mutex_ring.als @@ -0,0 +1,202 @@ +module examples/algorithms/stable_mutex_ring + +/* + * Dijkstra's K-state mutual exclusion algorithm for a ring + * + * Original paper describing the algorithm: + * [1] E.W.Dijkstra, "Self-Stabilizing Systems in Spite of + * Distributed Control", Comm. ACM, vol. 17, no. 11, pp. + * 643-644, Nov. 1974 + * + * Proof of algorithm's correctness: + * [2] E.W.Dijkstra, "A Belated Proof of Self-Stabilization", + * in Distributed Computing, vol. 1, no. 1, pp. 5-6, 1986 + * + * SMV analysis of this algorithm is described in: + * [3] "Symbolic Model Checking for Self-Stabilizing Algorithms", + * by Tatsuhiro Tsuchiya, Shini'ichi Nagano, Rohayu Bt Paidi, and + * Tohru Kikuno, in IEEE Transactions on Parallel and Distributed + * Systems, vol. 12, no. 1, January 2001 + * + * Description of algorithm (adapted from [3]): + * + * Consider a distributed system that consists of n processes + * connected in the form of a ring. We assume the state-reading + * model in which processes can directly read the state of their + * neighbors. We define _privilege_ of a process as its ability to + * change its current state. This ability is based on a Boolean + * predicate that consists of its current state and the state of + * one of its neighboring processes. + * + * We then define the legitimate states as those in which the + * following two properties hold: 1) exactly one process has a + * privilege, and 2) every process will eventually have a privilege. + * These properties correspond to a form of mutual exclusion, because + * the privileged process can be regarded as the only process that is + * allowed in its critical section. + * + * In the K-state algorithm, the state of each process is in + * {0,1,2,...,K-1}, where K is an integer larger than or equal to n. + * For any process p_i, we use the symbols S and L to denote its + * state and the state of its neighbor p_{i-1}, respectively, and + * process p_0 is treated differently from all other processes. The + * K-state algorithm is described below. + * + * process p_0: if (L=S) { S := (S+1) mod K; } + * process P_i(i=1,...,n-1): if (L!=S) { S:=L; } + */ + +open util/ordering[Tick] as to +open util/graph[Process] as pg +open util/graph[Val] as vg + +sig Process { + rightNeighbor: Process +} + +sig Val { + nextVal : Val +} + +fact MoreValThanProcess { + # Val > # Process +} + +fact DefineRings { + pg/ring[rightNeighbor] + vg/ring[nextVal] + //Val$nextVal = Ord[Val].next + (Ord[Val].last -> Ord[Val].first) +} + +sig Tick { + val: Process -> one Val, + runs: set Process, // processes scheduled to run on this tick + // for visualization + priv: set Process // the set of priviledged processes on this tick +} +{ + priv = { p : Process | Privileged[p, this] } +} + +one sig FirstProc extends Process { +} + + +fun FirstProcTrans[curVal, neighborVal : Val]: Val { + (curVal = neighborVal) => curVal.nextVal else curVal +} + +fun RestProcTrans[curVal, neighborVal : Val]: Val { + (curVal != neighborVal) => neighborVal else curVal +} + +fact LegalTrans { + all tp : Tick - to/last | + let tn = to/next[tp] | { + all p: Process | + let curVal = tp.val[p], neighborVal = tp.val[p.rightNeighbor], newVal = tn.val[p] | { + p !in tp.runs => newVal = curVal else { + p = FirstProc => + newVal = FirstProcTrans[curVal, neighborVal] + else + newVal = RestProcTrans[curVal, neighborVal] + } + } + } +} + +pred TickTrans[tp, tn : Tick] { + all p : Process | + let curVal = tp.val[p], neighborVal = tp.val[p.rightNeighbor], newVal = tn.val[p] | { + p = FirstProc => + newVal = FirstProcTrans[curVal, neighborVal] + else + newVal = RestProcTrans[curVal, neighborVal] + } +} + +/** + * whether this process can enter its critical section + * on this tick + */ +pred Privileged[p : Process, t : Tick] { + p = FirstProc => + t.val[p] = t.val[p.rightNeighbor] + else + t.val[p] != t.val[p.rightNeighbor] +} + +pred IsomorphicStates[val1, val2: Process -> one Val] { + some processMap: Process one -> one Process, + valMap: Val one -> one Val | { + FirstProc.processMap = FirstProc + all p: Process, v: Val | { + p->v in val1 iff (p.processMap) -> (v.valMap) in val2 + } + all v1,v2: Val | v1->v2 in nextVal iff (v1.valMap) -> (v2.valMap) in nextVal + all p1,p2: Process | p1->p2 in rightNeighbor + iff (p1.processMap) -> (p2.processMap) in rightNeighbor + } +} + +/** + * Find a trace that goes into a loop + * containing a bad tick, i.e. a tick + * at which two distinct processes + * try to run their critical sections + * simultaneously. In such a trace the + * algorithm never "stabilizes". + */ +pred BadSafetyTrace { + let lst = to/last | + some t : Tick - lst | { + //IsomorphicStates(ft.val, lst.val) + t.val = lst.val + Process in (to/nexts[t] + t - lst).runs + some badTick : to/nexts[t] + t | + BadTick[badTick] + } +} + +/** + * Two different processes simultaneously + * try to run their critical sections at this tick + */ +pred BadTick[badTick : Tick] { + some p1 , p2 : Process | { + p1!=p2 + Privileged[p1, badTick] + Privileged[p2, badTick] + } +} + +assert Closure { + not BadTick[to/first] => (all t : Tick | not BadTick[t]) +} + +pred TwoPrivileged { + BadTick[to/first] + some p1, p2 : Process, t1, t2 : Tick - to/first | { + p1!=p2 + Privileged[p1,t1] + Privileged[p2,t2] + } +} + +pred TraceWithoutLoop { + all t1, t2 : Tick | t1!=t2 => t1.val != t2.val +} + +pred TraceShorterThanMaxSimpleLoop { + to/first.val = to/last.val + all t : Tick - to/first - to/last | + !(t.val = to/first.val) +} + +run TraceShorterThanMaxSimpleLoop for 7 but 2 Process, 3 Val expect 1 +run TwoPrivileged for 5 but 3 Process, 4 Val expect 1 +check Closure for 5 but 5 Process, 6 Val expect 0 +//run BadSafetyTrace for 16 but 3 Process, 4 Val +//run TraceWithoutLoop for 21 but 4 Process, 5 Val + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/stable_mutex_ring.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/stable_mutex_ring.thm new file mode 100644 index 00000000..5f31f3ac --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/stable_mutex_ring.thm @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/stable_orient_ring.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/stable_orient_ring.als new file mode 100644 index 00000000..c6fec3fe --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/stable_orient_ring.als @@ -0,0 +1,90 @@ +module examples/algorithms/stable_orient_ring + +/* + * A self-stabilizing algorithm for orienting uniform rings. + * Communication model is the state-reading model. + */ + +open util/boolean as bool +open util/ordering[Tick] as ord +open util/graph[Process] as graph + +sig Process { + rightNeighbor: Process, + AP1, AP2: Process +} + +fun leftNeighbor[p: Process]: Process { + p.~(rightNeighbor) +} + +fact { + all p: Process { + (p.AP1=p.rightNeighbor && p.AP2=leftNeighbor[p]) || + (p.AP2=p.rightNeighbor && p.AP1=leftNeighbor[p]) + } +} + +fact DefineRing { + graph/ring[rightNeighbor] +} + +sig Tick { + runs: set Process, + dir, S, T: Process -> one Bool, + ring_: Process -> Process +} +{ + all p: Process | p.ring_ = (p.dir=True => p.AP1 else p.AP2) +} + +pred Eq3[b1,b2,b3: Bool] { b1 = b2 && b2 = b3 } +pred Eq4[b1,b2,b3,b4: Bool] { Eq3[b1,b2,b3] && b3=b4 } + +fact Transitions { + all tp: Tick - ord/last | let tn = ord/next[tp] | + all p: Process | + let p1 = p.AP1, p2 = p.AP2, pS = tp.S, pT=tp.T, nS=tn.S, nT=tn.T | + let S1p=p1.pS, S2p=p2.pS, + T1p=p1.pT, T2p=p2.pT, + Sp = p.pS, Sn=p.nS, + Tp = p.pT, Tn=p.nT, + dirp = p.(tp.dir), dirn = p.(tn.dir) | { + p !in tp.runs => ( Sn = Sp && Tn = Tp && dirn = dirp ) else ( + S1p = S2p => ( Sn = Not[S1p] && Tn = True && dirn=dirp) else ( + (Eq3[S1p, Sp, Not[S2p]] && + Eq4[Not[T1p],Tp,T2p,True]) => + (Sn = Not[Sp] && Tn = False && dirn = True) + else ( + (Eq3[Not[S1p],Sp,S2p] && Eq4[T1p,Tp,Not[T2p],True]) => + (Sn = Not[Sp] && Tn = False && dirn = False) else ( + ((Eq3[S1p,Sp,Not[S2p]] && T1p=Tp) || + (Eq3[Not[S1p],Sp,S2p] && Tp=T2p)) => + (Tn = Not[Tp] && Sn=Sp && dirn=dirp) else ( + Sn=Sp && Tn=Tp && dirn=dirp + ) + ) + ) + ) + ) + } +} + +pred RingAtTick[t: Tick] { + let rng = t.ring_ | + graph/ring[rng] || graph/ring[~rng] +} + +assert Closure { + // if the ring is properly oriented + all t: Tick - ord/last | + RingAtTick[t] => RingAtTick[ord/next[t]] +} + +pred SomeState { + !graph/ring[ord/first.ring_] + some t: Tick | graph/ring[t.ring_] +} + +run SomeState for 1 but 2 Tick, 2 Bool, 3 Process expect 1 +check Closure for 1 but 2 Tick, 2 Bool, 3 Process expect 1 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/stable_orient_ring.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/stable_orient_ring.thm new file mode 100644 index 00000000..0a8cba73 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/stable_orient_ring.thm @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/stable_ringlead.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/stable_ringlead.als new file mode 100644 index 00000000..577257f8 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/stable_ringlead.als @@ -0,0 +1,180 @@ +module examples/algorithms/stable_ringlead + +/* + * Huang's self-stabilizing leader-election algorithm + * for rings. + */ + +open util/ordering[Process] as po +open util/ordering[Val] as vo +open util/ordering[State] as so +open util/graph[Process] as graph + +sig Process { + rightNeighbor: Process +} + +sig Val { + nextVal : Val +} + +fact { + graph/ring[rightNeighbor] + vo/next + (vo/last -> vo/first) = nextVal + # Val = # Process +} + +sig State { + val : Process -> one Val, + running : set Process + // for visualization + //leader : set Process +} { + //leader = { p : Process | LeaderAtState(p, this) } +} + +fact { + no so/last.running +} + +fun LeadersAtState[t : State] : set Process { + { p : Process | LeaderAtState[p,t] } +} + +pred LeaderAtState[p : Process, t : State] { ValAtState[p,t] = vo/first } + +fun ValAtState[p : Process, t : State] : Val { t.val[p] } + +fun LeftValAtState[p : Process, t : State] : Val { t.val[p.~rightNeighbor] } + +fun RightValAtState[p : Process, t : State] : Val { t.val[p.rightNeighbor] } + +fun XAtState[p : Process, t : State] : Int { + g[LeftValAtState[p,t],ValAtState[p,t]] +} + +fun YAtState[p : Process, t : State] : Int { + g[ValAtState[p,t],RightValAtState[p,t]] +} + +fun g[a, b : Val] : Int { + (a = b) => Int[# Val] else minus[b,a] +} + +fun minus[v1, v2 : Val] : Int { + Int[ (v1 = v2) => 0 + else vo/gt[v1, v2] => (# (vo/nexts[v2] & vo/prevs[v1] + v1)) + else (# (Val - (vo/nexts[v1] & vo/prevs[v2] + v1))) + ] +} + +fun Trans[oldVal : Val, x, y : Int] : Val { + ((int x = int y && int y = # Val) || (int x < int y)) => oldVal.nextVal else oldVal +} + +pred OneAtATimeTrans { + all tp: State - so/last | + let tn = so/next[tp] | + some p : Process | { + tp.running = p + TransHelper[p,tp,tn] + all other : Process - p | + ValAtState[other,tn] = ValAtState[other,tp] + } +} + +pred DDaemonTrans { + all tp: State - so/last | + let tn = so/next[tp] | { + some tp.running + all p : tp.running | TransHelper[p,tp,tn] + all other : Process - tp.running | + ValAtState[other,tn] = ValAtState[other,tp] + } +} + +pred TransHelper[p : Process, tp, tn : State] { + let oldVal = ValAtState[p, tp], + newVal = ValAtState[p, tn], + x = XAtState[p, tp], + y = YAtState[p,tp] | + newVal = Trans[oldVal, x, y] + +} + +pred StateTrans[s, s' : State] { + all p : Process | + TransHelper[p, s, s'] || ValAtState[p,s] = ValAtState[p,s'] +} + + + +pred CBadLivenessTrace { + OneAtATimeTrans + BadLivenessHelper +} + +pred DBadLivenessTrace { + DDaemonTrans + BadLivenessHelper +} + +pred BadLivenessHelper { + let ls = so/last | + some s : State - ls | { + s.val = ls.val + // fair + Process in (so/nexts[s] + s - ls).running + } + all s : State | ! Legit[s] + } + +pred CTraceWithoutLoop { + OneAtATimeTrans + all t, t' : State | t!=t' => t.val != t'.val +} + +pred DTraceWithoutLoop { + DDaemonTrans + all t, t' : State | t!=t' => { + t.val != t'.val + (t' in so/nexts[t] && t' != so/next[t]) => !StateTrans[t,t'] + } + all t : State | !Legit[t] +} + +pred ConvergingRun { + OneAtATimeTrans + !Legit[so/first] + some t : State | Legit[t] +} + +pred OnlyFairLoops { + OneAtATimeTrans + all s, s' : State | + (s' in so/nexts[s] && s'.val = s.val) => + (let loopStates = (so/nexts[s] & so/prevs[s']) + s + s' | Process in loopStates.running) +} + +assert CMustConverge { + OnlyFairLoops => (some s : State | Legit[s]) +} + +pred Legit [s : State] { + one LeadersAtState[s] + all p : Process | { + int XAtState[p,s] < # Val + int YAtState[p,s] < # Val + } + all p, p' : Process | { + int XAtState[p,s] = int XAtState[p',s] + int YAtState[p,s] = int YAtState[p',s] + } +} + +run ConvergingRun for 3 but 4 State expect 1 +run DTraceWithoutLoop for 3 but 4 State expect 1 +run DBadLivenessTrace for 3 but 4 State expect 1 +run CTraceWithoutLoop for 3 but 5 State expect 0 +run CBadLivenessTrace for 4 but 5 State expect 1 +check CMustConverge for 3 but 4 State expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/stable_ringlead.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/stable_ringlead.thm new file mode 100644 index 00000000..d580f3a1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/algorithms/stable_ringlead.thm @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/INSLabel.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/INSLabel.als new file mode 100644 index 00000000..9f8a2024 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/INSLabel.als @@ -0,0 +1,149 @@ +module examples/case_studies/INSLabel + +/* + * Models an Intentional Naming System (INS), a scheme for + * dynamic resource discovery in a dynamic environment. + * + * For a detailed description, see: + * http://sdg.lcs.mit.edu/pubs/2000/INS_ASE00.pdf + * + * author: Sarfraz Khurshid + */ + +sig Record {} + +sig Label {} + +sig Node { + label: Label +} + +sig LabelTree { + root: Node, + nodes: set Node, + children: nodes one -> (nodes - root) +} +{ // connected + nodes = root.*children + some root.children +} + +pred Get[db: DB, r: Record, a:Advertisement] { + root[a] = root[db] + nodes[a] = + nodes[db] & r.~(db.recs).*(~(db.children)) + anodes[a] = + anodes[db] & r.~(db.recs).*(~(db.children)) + vnodes[a] = + vnodes[db] & r.~(db.recs).*(~(db.children)) + all n: a.nodes | + n.~(a.children) = n.~(db.children) +} + +sig Attribute extends Label {} + +sig Value extends Label {} + +one sig Wildcard, Null extends Value {} + +sig AVTree extends LabelTree { + vnodes, anodes: set nodes +} +{ + root in vnodes + root.label = Null + Null !in (vnodes - root).label + anodes.label + anodes.label in Attribute + vnodes.label in Value + all n: nodes | all /* disj */ c,c': n.children | + c.label != c'.label + all a: anodes | a.children in vnodes && some a.children + all v: vnodes | v.children in anodes + no Wildcard.~label.children +} + +one sig Query extends AVTree {} +{ + all a: anodes | one a.children +} + +one sig Advertisement extends AVTree {} +{ + Wildcard !in vnodes.label +} + +one sig DB extends AVTree { + records: set Record, + recs: (vnodes - root) some -> records +} +{ + Wildcard !in vnodes.label + all a: anodes | no a.recs + all v: vnodes { + no v.children => some v.recs + no v.recs & v.^(~children).recs } + all a: anodes | all disj v,v': a.children | + (no v.*children.recs & v'.*children.recs) +} + +one sig State { + conforms: Query -> Advertisement -> Node -> Node, + lookup: DB -> Query -> Node -> Node -> Record +} + +fact ConformsFixPoint { + all q: Query | all a: Advertisement | + all nq: Node | all na: Node | + q.ConformsAux[a,nq,na] <=> + { + nq.label in Wildcard + na.label + all nq': q.children[nq] | some na': a.children[na] | + q.ConformsAux[a,nq',na'] + } +} + +pred Query.ConformsAux[a: Advertisement, nq: Node, na: Node] { + na in State.conforms[this][a][nq] +} + +pred Conforms[q: Query, a:Advertisement] { + q.ConformsAux[a, q.root, a.root] +} + +fact LookupFixPoint { + all db: DB, q: Query, T: Node, n: Node, r: Record | + r in db.LookupAux[q,T,n] <=> // record r is in the result if and only if + { + all na: n.(q.children) | all nv: na.(q.children) | // for all child av-pairs (na,nv) of av-pair n in q + some Ta: T.(db.children) { + Ta.label = na.label // Ta is a child node with attribute na + nv.label = Wildcard => // wildcard matching + r in Ta.^(db.children).(db.recs) else // r is a record of any child of Ta + (some Tv: Ta.(db.children) { // normal matching + Tv.label = nv.label // Tv is a child of Ta with value nv + no nv.(q.children) => // if Tv is a leaf-node + r in Tv.*(db.children).(db.recs) else // r is a record of Tv or of v + r in db.LookupAux[q,Tv,nv] }) } // else r is a record of the recursive call at Tv + } +} + +fun DB.LookupAux[q: Query, vd: Node, vq: Node]: set Record { // helper function for Lookup + State.lookup[this][q][vd][vq] +} + +fun Lookup[db: DB, q: Query]: set Record { // models Lookup-Name algorithm invocation + db.LookupAux[q, db.root, q.root] +} + +assert LookupConforms2 { //soundness and completeness + all q: Query | all db: DB | all r: Record | all a: Advertisement | + Get[db,r,a] => // all n: a.nodes | n.~(db.children) + {r in db.Lookup[q] <=> q.Conforms[a]} +} + +// < 10 sec +check LookupConforms2 for 4 but 1 State, 3 LabelTree, 2 Record expect 0 +// ~ 25 min +//check LookupConforms2 for 6 but 1 State, 3 LabelTree, 2 Record +//check LookupConforms2 for 6 but 1 State, 3 LabelTree, 3 Record +run Lookup for 3 expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/chord.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/chord.als new file mode 100644 index 00000000..f7a042f1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/chord.als @@ -0,0 +1,260 @@ +module examples/case_studies/chord + +/* + * Models the chord distributed hash table lookup protocol. + * + * For a detailed description, see: + * http://www.pdos.lcs.mit.edu/papers/chord:sigcomm01/ + */ + +open util/relation as rel + +sig Id {next: Id} +fact {all i: Id | Id in i.*next} + +/** + * true iff i precedes j in the order starting at from + */ +pred less_than [from, i,j: Id] { + let next' = Id<:next - (Id->from) | j in i.^next' // if from=j, returns true if # nodes > 1 + } +pred less_than_eq [from, i,j: Id] { + let next' = Id<:next - (Id->from) | j in i.*next' + } + +sig Node {id: Id} +fact {all m,n: Node | m!=n => m.id != n.id} + + +sig NodeData { + prev, next: Node, + finger: Id -> lone Node, + closest_preceding_finger: Id -> one Node, + find_predecessor: Id -> one Node, + find_successor: Id -> one Node + } + +sig State { + active: set Node, + data: active -> one NodeData + } + +/** + * node n's next node is defined to be the m where n's finger table maps the id + * that follows n.id to m + * next holds the first entry of the finger table + */ +fact {all s: State | all n: s.active | n.(s.data).next = n.(s.data).finger[n.id.next]} + +pred NextCorrect [s: State] { + all n: s.active { + -- no intervening node (ie, close enough) + no n': s.active - n | less_than [n.id, n'.id, n.(s.data).next.id] + -- can reach all other active nodes (ie, far enough) + -- need this because can't rule out case of next being node itself (because of 1-node ring) + -- s.active in n.*(s.data.next) + n.(s.data).next != n || #s.active = 1 + } + } + +pred NextCorrect' [s: State] { +-- next seems to be correct for 1,2,3 nodes + all n: s.active | let nd = (s.data)[n] { + let next' = Id<:next - (Id -> nd.next.id) { + no n' : s.active { n'.id in n.id.^next' } + }} + } + +// valid +assert Same1 {all s: State | NextCorrect[s] => NextCorrect'[s]} +check Same1 for 3 but 1 State expect 0 + +// valid unless active condition removed +assert Same2 {all s: State | s.active = Node => (NextCorrect'[s] => NextCorrect[s])} +check Same2 for 3 but 1 State expect 0 + +-- assert NextInFinger {all s: State | all n: s.active | some n.s.data.finger[n.id.next] } + + +-- says that finger entry maps an id to a node so that there are no intervening nodes +-- between the id and the node +pred FingersCorrect [s: State] { + all nd: s.active.(s.data) | all start:nd.finger.univ | + nd.finger[start] in s.active && + (no n' : s.active | less_than [start, n'.id, nd.finger[start].id]) + } + + +pred FingersCorrect' [s: State] { + all n: s.active | let nd = (s.data)[n] | all start: Node.~(nd.finger) { + nd.finger[start] in s.active && + (let next' = Id<:next - (nd.finger[start].id -> Id) { + no n' : s.active - nd.finger[start] { + n'.id in start.*next' + } + }) + } + } + + +assert SameFC {all s: State | FingersCorrect [s] iff FingersCorrect'[s]} +check SameFC for 3 but 1 State expect 0 + + +pred ShowMeFC { + all s : State | s.active = Node && FingersCorrect[s] +} + +run ShowMeFC for 2 but 1 State expect 1 + +pred ClosestPrecedingFinger[s: State] { + all n: s.active | let nd = n.(s.data) | + all i: Id | let cpf = nd.closest_preceding_finger[i] { + no n': nd.finger[Id] + n - cpf | less_than [cpf.id, n'.id, i] + cpf in nd.finger[Id] + n + cpf.id != i || # s.active = 1 + //less_than (n.id, cpf.id, i) + } + } + + +pred ClosestPrecedingFinger'[s: State] { + all n: s.active | let nd = (s.data)[n] | all i: Id { + let next' = Id<:next - (Id -> i) { + nd.next.id in n.id.^next' => + // nd.closest_preceding_finger[i] = nd.next, + (some n1: nd.finger[Id] { + nd.closest_preceding_finger[i] = n1 + //n1 in nd.finger[Id] + n1.id in n.id.^next' + no n2: nd.finger[Id] | n2.id in n1.id.^next' + }) else + nd.closest_preceding_finger[i] = n + }} + } + + +assert SameCPF {all s: State | FingersCorrect[s] => (ClosestPrecedingFinger [s] iff ClosestPrecedingFinger' [s])} +assert SameCPF1 {all s: State | FingersCorrect[s] => (ClosestPrecedingFinger [s] => ClosestPrecedingFinger' [s])} +assert SameCPF2 { + all s: State | ((s.active = Node && FingersCorrect[s] && ClosestPrecedingFinger' [s]) + => ClosestPrecedingFinger [s]) } + +check SameCPF for 3 but 1 State expect 0 +check SameCPF1 for 2 but 1 State expect 0 +check SameCPF2 for 3 but 1 State expect 0 + + +pred ShowMeCPF { + all s : State | s.active = Node && FingersCorrect[s] && + // not ClosestPrecedingFinger(s) && ClosestPrecedingFinger'(s) + ClosestPrecedingFinger[s] + //all s : State | all nd : s.active.s.data | nd.finger[Id] = Node + # Node = 2 + # State = 1 +} + + +run ShowMeCPF for 2 but 1 State expect 1 + + +pred FindPredecessor[s: State] { + all n: s.active | let nd = n.(s.data) | all i: Id { + nd.find_predecessor[i] = + (less_than_eq [n.id, i, nd.next.id] && (n.id != i || # s.active = 1) + => n + else (nd.closest_preceding_finger[i].(s.data).find_predecessor)[i]) + } + } + + +assert FPisActive { + all s: State | FingersCorrect[s] && ClosestPrecedingFinger[s] && FindPredecessor[s] + => (all n: s.active | all nd: n.(s.data) | nd.find_predecessor[Id] in s.active) } +check FPisActive for 3 but 1 State expect 1 + + +pred FindPredecessor'[s: State] { + all n: s.active | let nd = (s.data)[n] | all i: Id { + let next' = Id<:next - (nd.next.id -> Id) { + one s.active or i in n.id.^next' => // *next' -> ^next' 1/8/02 + nd.find_predecessor[i] = n else + nd.find_predecessor[i] = + ((s.data)[nd.closest_preceding_finger[i]]).find_predecessor[i] + }} + } + + +assert SameFP {all s: State | FingersCorrect[s] // && s.active = Node + => (FindPredecessor [s] iff FindPredecessor' [s])} + +assert SameFP1 { + all s: State | FingersCorrect[s] && s.active = Node + => (FindPredecessor [s] => FindPredecessor' [s])} +assert SameFP2 { + all s: State | FingersCorrect[s] && s.active = Node + => (FindPredecessor' [s] => FindPredecessor [s])} + +check SameFP for 3 but 1 State expect 1 +check SameFP1 for 3 but 1 State expect 0 +check SameFP2 for 3 but 1 State expect 0 + + +pred FindSuccessor[s: State] { + all n: s.active | let nd = (s.data)[n] | all i: Id { + nd.find_successor[i] = ((s.data)[nd.find_predecessor[i]]).next + }} + + +// should be able to check that closest_p_f, etc returns +// only active nodes if FingersCorrect. + + +pred ShowMe1Node { + #Node = 1 + all s : State | NextCorrect[s] + State.active = Node +} + +run ShowMe1Node for 2 but 1 State, 1 Node expect 1 + +pred ShowMe1 { + #Node = 2 + #State = 1 + all s : State | NextCorrect[s] + State.active = Node +} + + +pred ShowMe2 { + #Node = 3 + #State = 1 + all s : State | NextCorrect[s] && FingersCorrect[s] + State.active = Node + //all n: NodeData | one n.finger[Id] +} + + +assert OK1 { + #Node = 3 && + #State = 1 && + (all s : State | NextCorrect[s] && FingersCorrect[s]) && + State.active = Node +} + + +run ShowMe1 for 3 expect 1 +run ShowMe2 for 3 expect 1 + +assert InjectiveIds {all i, j: Id | i!=j => i.next != j.next} +check InjectiveIds for 5 expect 0 + + +assert FindSuccessorWorks { + all s: State, i: Id | + let nd = s.active.(s.data) | + let succ = nd.find_successor [i] | + FingersCorrect [s] // && s.active = Node + => (no n': s.active | less_than [i, n'.id, succ.id]) + } +check FindSuccessorWorks for 3 but 1 State expect 1 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/chord2.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/chord2.als new file mode 100644 index 00000000..ea7c3429 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/chord2.als @@ -0,0 +1,274 @@ +module examples/case_studies/chord2 + +/* + * Models the chord distributed hash table lookup protocol. + * + * For a detailed description, see: + * http://www.pdos.lcs.mit.edu/papers/chord:sigcomm01/ + */ + +open util/relation as rel + +sig Id {next: Id} +fact {all i: Id | Id in i.*next} + +/** + * true iff i precedes j in the order starting at from + */ +pred less_than [from, i,j: Id] { + let next' = Id<:next - (Id->from) | j in i.^next' // if from=j, returns true if # nodes > 1 + } +pred less_than_eq [from, i,j: Id] { + let next' = Id<:next - (Id->from) | j in i.*next' + } + +sig Node {id: Id} +fact {all m,n: Node | m!=n => m.id != n.id} + +sig NodeData { + prev, next: Node, + finger: Id -> lone Node, + closest_preceding_finger: Id -> one Node, + find_predecessor: Id -> one Node, + find_successor: Id -> one Node + } + +sig State { + active: set Node, + data: active -> one NodeData + } + +/** + * node n's next node is defined to be the m where n's finger table maps the id + * that follows n.id to m + * next holds the first entry of the finger table + */ +fact {all s: State | all n: s.active | n.(s.data).next = n.(s.data).finger[n.id.next]} + +pred NextCorrect [s: State] { + all n: s.active { + -- no intervening node (ie, close enough) + no n': s.active - n | less_than [n.id, n'.id, n.(s.data).next.id] + -- can reach all other active nodes (ie, far enough) + -- need this because can't rule out case of next being node itself (because of 1-node ring) + -- s.active in n.*(s.data.next) + n.(s.data).next != n || #s.active = 1 + } + } + +/* +-- abortive attempt at simplifying next condition +fun NextCorrect" (s: State) { + all n: s.active | let nx = s.data.next { + s.active in n.*nx + less_than (n.id, n.id, n.nx.id) + } + } +*/ + +pred NextCorrect' [s: State] { +-- next seems to be correct for 1,2,3 nodes + all n: s.active | let nd = (s.data)[n] { + let next' = Id<:next - (Id -> nd.next.id) { + no n' : s.active { n'.id in n.id.^next' } + }} + } + +assert Same1 {all s: State | NextCorrect[s] => NextCorrect'[s]} +//check Same1 for 3 but 1 State -- valid +assert Same2 {all s: State | s.active = Node => (NextCorrect'[s] => NextCorrect[s])} +//check Same2 for 3 but 1 State -- invalid if active condition removed + +-- assert NextInFinger {all s: State | all n: s.active | some n.s.data.finger[n.id.next] } + +/** + * says that finger entry maps an id to a node so that there are no intervening nodes + * between the id and the node + */ +pred FingersCorrect [s: State] { + all nd: s.active.(s.data) | all start:nd.finger.univ | + nd.finger[start] in s.active && + (no n' : s.active | less_than [start, n'.id, nd.finger[start].id]) + } + +pred FingersCorrect' [s: State] { + all n: s.active | let nd = (s.data)[n] | all start: Node.~(nd.finger) { + nd.finger[start] in s.active && + (let next' = Id<:next - (nd.finger[start].id -> Id) { + no n' : s.active - nd.finger[start] { + n'.id in start.*next' + }})} + } + +assert SameFC {all s: State | FingersCorrect [s] iff FingersCorrect'[s]} +//check SameFC for 3 but 1 State + +pred ShowMeFC { + all s : State | s.active = Node && FingersCorrect[s] +} + +//run ShowMeFC for 2 but 1 State + +/* +fun ClosestPrecedingFinger(s: State) { + all n: s.active | let nd = n.s.data | + all i: Id | let cpf = nd.closest_preceding_finger[i] { + no n': nd.finger[Id] | less_than (cpf.id, n'.id, i) + cpf in nd.finger[Id] + n + less_than (n.id, cpf.id, i) + } + } +*/ + +pred ClosestPrecedingFinger_SAVE [s: State] { + all n: s.active | let nd = n.(s.data) | + all i: Id | let cpf = nd.closest_preceding_finger[i] { + no n': (nd.finger[Id] + n) - cpf | less_than [cpf.id, n'.id, i] + cpf in nd.finger[Id] + n + cpf.id != i || # s.active = 1 + //less_than (n.id, cpf.id, i) + } + } + +pred CPFBody [s: State, n: Node, nd: NodeData, i: Id, cpf: Node] { + no n': (nd.finger[Id] + n) - cpf | less_than [cpf.id, n'.id, i] + cpf in nd.finger[Id] + n + cpf.id != i || # s.active = 1 + } +pred ClosestPrecedingFinger[s: State] { + all n: s.active | let nd = n.(s.data) | + all i: Id | + some cpf: Node | CPFBody [s,n,nd,i,cpf] => CPFBody [s,n,nd,i,nd.closest_preceding_finger[i]] + } + +pred ClosestPrecedingFinger'[s: State] { + all n: s.active | let nd = (s.data)[n] | all i: Id { + let next' = Id<:next - (Id -> i) { + nd.next.id in n.id.^next' => + // nd.closest_preceding_finger[i] = nd.next, + (some n1: nd.finger[Id] { + nd.closest_preceding_finger[i] = n1 + //n1 in nd.finger[Id] + n1.id in n.id.^next' + no n2: nd.finger[Id] | n2.id in n1.id.^next' + }) else + nd.closest_preceding_finger[i] = n + }} + } + +assert SameCPF {all s: State | FingersCorrect[s] => (ClosestPrecedingFinger [s] iff ClosestPrecedingFinger' [s])} +assert SameCPF1 {all s: State | FingersCorrect[s] => (ClosestPrecedingFinger [s] => ClosestPrecedingFinger' [s])} +assert SameCPF2 { + all s: State | ((s.active = Node && FingersCorrect[s] && ClosestPrecedingFinger' [s]) + => ClosestPrecedingFinger [s]) } +//check SameCPF for 3 but 1 State +//check SameCPF1 for 2 but 1 State +//check SameCPF2 for 3 but 1 State + +pred ShowMeCPF { + all s : State | s.active = Node && FingersCorrect[s] && + // not ClosestPrecedingFinger(s) && ClosestPrecedingFinger'(s) + ClosestPrecedingFinger[s] + //all s : State | all nd : s.active.s.data | nd.finger[Id] = Node + # Node = 2 + # State = 1 +} + +//run ShowMeCPF for 2 but 1 State + +pred FindPredecessor[s: State] { + all n: s.active | let nd = n.(s.data) | all i: Id { + nd.find_predecessor[i] = + ((less_than_eq [n.id, i, nd.next.id] && (n.id != i || # s.active = 1)) + => n + else (nd.closest_preceding_finger[i].(s.data).find_predecessor)[i]) + } + } +-- problem : could return node that's inactive ??? + +assert FPisActive { + all s: State | FingersCorrect[s] && ClosestPrecedingFinger[s] && FindPredecessor[s] + => (all n: s.active | all nd: n.(s.data) | nd.find_predecessor[Id] in s.active) +} + +//check FPisActive for 3 but 1 State + +pred FindPredecessor'[s: State] { + all n: s.active | let nd = (s.data)[n] | all i: Id { + let next' = Id<:next - (nd.next.id -> Id) { + one s.active or i in n.id.^next' => + nd.find_predecessor[i] = n else + nd.find_predecessor[i] = + ((s.data)[nd.closest_preceding_finger[i]]).find_predecessor[i] + }} + } + +assert SameFP {all s: State | FingersCorrect[s] && s.active = Node + => (FindPredecessor [s] iff FindPredecessor' [s])} +assert SameFP1 { + all s: State | FingersCorrect[s] && s.active = Node + => (FindPredecessor [s] => FindPredecessor' [s])} +assert SameFP2 { + all s: State | FingersCorrect[s] && s.active = Node + => (FindPredecessor' [s] => FindPredecessor [s])} +//check SameFP for 3 but 1 State +//check SameFP1 for 3 but 1 State +//check SameFP2 for 3 but 1 State + +pred FindSuccessor[s: State] { + all n: s.active | let nd = (s.data)[n] | all i: Id { + nd.find_successor[i] = ((s.data)[nd.find_predecessor[i]]).next + }} + +fact { all s : State { + ClosestPrecedingFinger[s] + FindPredecessor[s] + FindSuccessor[s] + }} + +// should be able to //check that closest_p_f, etc returns +// only active nodes if FingersCorrect. + +pred ShowMe1Node { + #Node = 1 + all s : State | NextCorrect[s] + State.active = Node +} + +//run ShowMe1Node for 2 but 1 State, 1 Node +-- does the expected correct thing for 1 node. + +pred ShowMe1 { + #Node = 2 + #State = 1 + all s : State | NextCorrect[s] + State.active = Node +} + +pred ShowMe2 { + #Node = 3 + #State = 1 + all s : State | NextCorrect[s] && FingersCorrect[s] + State.active = Node + //all n: NodeData | one n.finger[Id] +} + +assert OK1 { + #Node = 3 && + #State = 1 && + (all s : State | NextCorrect[s] && FingersCorrect[s]) && + State.active = Node +} + +assert FindSuccessorWorks { + all s: State, i: Id | + let nd = s.active.(s.data) | + let succ = nd.find_successor [i] | + FingersCorrect [s] + => { + no n': s.active | less_than [i, n'.id, succ.id] + succ in s.active + } + } + +check FindSuccessorWorks for 4 but 1 State, 3 Node, 3 NodeData expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/chordbugmodel.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/chordbugmodel.als new file mode 100644 index 00000000..de6c36bb --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/chordbugmodel.als @@ -0,0 +1,232 @@ +module examples/case_studies/chord + +/* + * Models the chord distributed hash table lookup protocol. + * + * For a detailed description, see: + * http://www.pdos.lcs.mit.edu/papers/chord:sigcomm01/ + */ + +sig Id {next: Id} +fact {all i: Id | Id in i.*next} + +pred less_than [from, i,j: Id] { + let next' = Id<:next - (Id->from) | j in i.^next' +} + +pred less_than_eq [from, i,j: Id] { + let next' = Id<:next - (Id->from) | j in i.*next' +} + +sig Node {id: Id} +fact {all m,n: Node | m!=n => m.id != n.id} + +sig NodeData { + next: Node, + finger: Id -> lone Node, + closest_preceding_finger: Id -> one Node, + find_successor: Id -> one Node +} + +sig State { + active: set Node, + data: active -> one NodeData +} + +fact { + all s: State | all n: s.active | + n.(s.data).next = n.(s.data).finger[n.id.next] +} + +pred NextCorrect [s: State] { + all n: s.active | let succ = n.(s.data).next { + no n': s.active - n | less_than [n.id, n'.id, succ.id] + succ != n || #s.active = 1 + succ in s.active + } +} + +pred FingersCorrect [s: State] { + all nd: s.active.(s.data) | all start: (nd.finger).Node | + nd.finger[start] in s.active && + (no n' : s.active | less_than [start, n'.id, nd.finger[start].id]) +} + +pred save_ClosestPrecedingFinger [s: State] { + all n: s.active | let nd = n.(s.data) | + all i: Id | let cpf = nd.closest_preceding_finger[i] { + no n': (nd.finger[Id] + n) - cpf | less_than [cpf.id, n'.id, i] + cpf in nd.finger[Id] + n + cpf.id != i || # s.active = 1 + } +} + +pred save_FindSuccessor[s: State] { + all n: s.active | let nd = n.(s.data) | all i: Id { + nd.find_successor[i] = + (((less_than_eq [n.id, i, nd.next.id] && n.id != i) || # s.active = 1) + => nd.next + else + (nd.closest_preceding_finger[i].(s.data).find_successor)[i]) + } +} + +pred IrrelevantFact1 { + all s : State { + ClosestPrecedingFinger[s] + FindSuccessor[s] + } +} + +pred ShowMe1Node { + #Node = 1 + all s : State | NextCorrect[s] && FingersCorrect[s] + State.active = Node +} + +run ShowMe1Node for 2 but 1 State, 1 Node expect 1 + +pred ShowMeGood { + #Id = 4 + all s : State | NextCorrect[s] && FingersCorrect[s] + State.active = Node +} + +run ShowMeGood for 4 but 1 State, 2 Node expect 1 + +pred FindSuccessorIsCorrect[s: State] { + all i: Id | all n: s.active | + let succ = (n.(s.data)).find_successor [i] { + succ in s.active + no n': s.active | less_than [i, n'.id, succ.id] + } +} + +pred ShowMeCorrectSuccessorEg { + #Node = 3 + State.active = Node + all s: State | FingersCorrect[s] && FindSuccessorIsCorrect[s] +} + +run ShowMeCorrectSuccessorEg for 3 but 1 State expect 1 + +pred ShowMe3 { + #Id = 5 + #Node = 3 + #State = 1 + all s : State | NextCorrect[s] && !FingersCorrect[s] + State.active = Node +} + +run ShowMe3 for 5 but 1 State expect 1 + +pred FindSuccessorWorks { + IrrelevantFact1 + ! ( + all s: State | FingersCorrect[s] + => FindSuccessorIsCorrect[s] + ) +} + +assert StrongerFindSuccessorWorks { + all s: State | NextCorrect[s] => FindSuccessorIsCorrect[s] +} + +run FindSuccessorWorks for 4 but 1 State expect 0 +check StrongerFindSuccessorWorks for 4 but 1 State expect 1 + +/* +\section Variations + +In the pseudocode presented in [\cite{chord1}, +\cite{chord2}], there is some ambiguity as to what the +expression \tt<(n, n.successor]> means in boundary cases +where there is exactly one node and \tt. +The intention of the authors is that the set includes +\tt. We consider variations of the alloy model with the +bug where the set \tt<(n, n]> does not include \tt, and +observe how it affects the \tt and +the \tt routines. + +\subsection faulty \tt + +Suppose we change \tt as follows: + +\code +*/ + +pred ClosestPrecedingFinger [s: State] { + all n: s.active | let nd = n.(s.data) | + all i: Id | let cpf = nd.closest_preceding_finger[i] { + no n': (nd.finger[Id] + n) - cpf | less_than [cpf.id, n'.id, i] + cpf in nd.finger[Id] + n + cpf.id != i + } +} + +/* +The only change here is in the last line +\cite{cpf-variation}, where we removed the clause \tt< || # +s.active=1>. The assertion \tt will +still hold for scope up to 4, but \tt will fail +to generate an example! This is an example of a +over-constraint, where the inconsistency only shows up when +there is exactly one node. What happens here is that the +model requires that a closest preceding finger node has a +distinct identifier from the input identifier, but this +cannot happen if there is exactly one node and if the input +identifer equals that of the node. + +\subsection faulty \tt + +Consider the following pseudocode segment from [\cite{chord2}]: + +n.find_successor(id) + if (id in (n, n.successor]) + return n.successor; + else + n' = closest_preceding_finger(id); + return n'.find_successor(id); + +In the buggy scenario with a single node, the \tt loop +always terminates at \cite{if-condition1}, leading to an +infinite loop. + +Consider the corresponding change to \tt as follows: + +*/ + +pred FindSuccessor[s: State] { + all n: s.active | let nd = n.(s.data) | all i: Id { + nd.find_successor[i] = + ((less_than_eq [n.id, i, nd.next.id] && n.id != i) + => nd.next + else + (nd.closest_preceding_finger[i].(s.data).find_successor)[i]) + } +} + +/* +The only change here is in the fourth line +\cite{sf-variation}, where we removed the clause \tt< || # +s.active = 1>. For the same reason, the \tt loop +in this case always proceeds to the \tt clause, +and since \tt always returns +\tt (the only node in the network), we end up +with a tautological statement: + +\code + nd.find_successor[i] = n.s.data.find_successor)[i] + +This means that there is no additional constraint placed on +\tt, other than that its return type is +\tt. Now, if there is no distinction between active +and inactive nodes, that is, we have exactly one active node +in the network and no inactive ones, \tt +will return the right answer due to the type constraint, +therefore obscuring the bug. On the other hand, since we +have introduced inactive nodes, the assertion +\tt now fails with exactly one active +node and some inactive node(s), with \tt +returning an inactive node. +*/ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/com.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/com.als new file mode 100644 index 00000000..8cf6f08c --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/com.als @@ -0,0 +1,96 @@ +module examples/case_studies/com + +/* + * Model of Microsoft Component Object Model (COM) query + * interface and aggregation mechanism. + * + * For a detailed description, see: + * http://sdg.lcs.mit.edu/~dnj/publications/com-fse00.pdf + * + * author: Daniel Jackson + */ + +open util/relation as rel + +sig IID {} + +sig Interface { + qi : IID -> lone Interface, + iids : set IID, + // next two lines should use domain() or range() functions + iidsKnown : IID, + reaches : Interface +}{ + iidsKnown = dom[qi] + reaches = ran[qi] +} + +sig Component { + interfaces : set Interface, + iids : set IID, // can't do iids = interfaces.Interface$iids + first, identity : interfaces, + eqs: set Component, + aggregates : set Component +} + +fact defineEqs { + all c1, c2: Component | + c1->c2 in eqs <=> c1.identity = c2.identity +} + +fact IdentityAxiom { + some unknown : IID | all c : Component | + all i : c.interfaces | unknown.(i.qi) = c.identity +} + +fact ComponentProps { + all c : Component { + c.iids = c.interfaces.iids + all i : c.interfaces | all x : IID | x.(i.qi) in c.interfaces + } +} + +sig LegalInterface extends Interface { } +fact { all i : LegalInterface | all x : i.iidsKnown | x in x.(i.qi).iids} + +sig LegalComponent extends Component { } +fact { LegalComponent.interfaces in LegalInterface } + +fact Reflexivity { all i : LegalInterface | i.iids in i.iidsKnown } +fact Symmetry { all i, j : LegalInterface | j in i.reaches => i.iids in j.iidsKnown } +fact Transitivity { all i, j : LegalInterface | j in i.reaches => j.iidsKnown in i.iidsKnown } + +fact Aggregation { + no c : Component | c in c.^aggregates + all outer : Component | all inner : outer.aggregates | + (some inner.interfaces & outer.interfaces) + && (some o: outer.interfaces | all i: inner.interfaces - inner.first | all x: Component | (x.iids).(i.qi) = (x.iids).(o.qi)) + } + +assert Theorem1 { + all c: LegalComponent | all i: c.interfaces | i.iidsKnown = c.iids + } + +assert Theorem2 { + all outer: Component | all inner : outer.aggregates | + inner in LegalComponent => inner.iids in outer.iids + } + +assert Theorem3 { + all outer: Component | all inner : outer.aggregates | inner in outer.eqs + } + +assert Theorem4a { + all c1: Component, c2: LegalComponent | + some (c1.interfaces & c2.interfaces) => c2.iids in c1.iids + } + +assert Theorem4b { + all c1, c2: Component | some (c1.interfaces & c2.interfaces) => c1 in c2.eqs + } + +check Theorem1 for 3 expect 0 +check Theorem2 for 3 expect 0 +check Theorem3 for 3 expect 0 +check Theorem4a for 3 expect 0 +check Theorem4b for 3 expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/firewire.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/firewire.als new file mode 100644 index 00000000..5de1afaf --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/firewire.als @@ -0,0 +1,384 @@ +module examples/case_studies/firewire + +/* + * A model of leader election in the Firewire protocol. + * + * Adapted from: + * [DG+01] M.C.A. Devillers, W.O.D. GriAEoen, J.M.T Romijn, and F.W. Vaandrager. + * Verification of a leader election protocol -- formal methods applied to IEEE + * 1394. Technical Report CSI-R9728, Computing Science Institute, University of + * Nijmegen, December 1997. Also, Formal Methods in System Design, 2001. + * + * This model describes a leader election protocol used in Firewire, an IEEE + * standard for connecting consumer electronic devices. The model is a + * straightforward translation into Alloy of a model [DG+01] developed in Lynch's + * IO Automata which has been analyzed using PVS, a theorem prover, but which, as + * far as we know, has not been subjected to fully automatic analysis. We are able + * to express the key correctness property -- that exactly one leader is elected + * -- more directly, as a trace property rather than a refinement property, and + * can check it without the need for the 15 invariants used in the more + * traditional proof. And the analysis does not hardwire + * a particular topology, so would be tricky to do with a standard model checker. + * + * The network is assumed to consist of a collection of nodes connected by + * links. Each link between a pair of nodes is matched by a link in the other + * direction. Viewing a link and its dual as a single, undirected edge, the + * network as a whole is assumed to form a tree. The purpose of the algorithm is + * to construct such a tree; in the model, this is achieved by labelling some + * subset of the links as parent links (each pointing from a node to its parent), + * and by marking a single node as the root. + * + * The algorithm, described in detail elsewhere [DG+01], works briefly as + * follows. When a node detects that all of its incoming links (or all but one) + * has been marked as a parent link, it sends a message on each outgoing link, + * either an acknowledgment (indicating its willingness to act as parent), or a + * request (indicating its desire to be a child), according to whether the dual of + * the outgoing link has been marked or not. Leaf nodes (with only one incoming + * link) may thus initiate the algorithm by sending requests to their adjacent + * nodes. Performing this action changes a node's status from {\em waiting} to + * {\em active}. A node that is still waiting, and which receives a message on a + * link, may label that link a parent link. Once active, a node that receives an + * acknowledgment on a link may also label the link, but if it receives a request, + * instead changes its node status to {\em contending}. The resolving of + * contentions is modelled simplistically by a single action that arbitrarily + * labels one of the two links a pair of contending nodes. Finally, a node all of + * whose incoming links are parent links designates itself a root. + * + * The specification is given below. Each signature introduces a basic type + * and some relations whose first column has that type: + * + * \begin{itemize} + * + * \item {\em Msg} represents the type of messages. {\em Req} is the request + * message and {\em Ack} is the acknowledgment message; these are actually + * declared as singleton (keyword {\em static}) subsets of {\em Msg}, the set of + * all messages, that form a partition (keyword {\em part}). + * + * \item {\em Node} represents the nodes of the network. The relations {\em to} + * and {\em from} associate each node with a set of incoming and outgoing links + * respectively. + * + * \item {\em Link} represents the links. The relations {\em target} and {\em + * source} map a link to its end nodes; {\em reverse} maps a link to its dual. The + * facts in the signatures {\em Node} and {\em Link} ensure that all these + * relations are consistent with one another: that the incoming links of a node + * are those whose target is that node, etc. + * + * \item {\em Op} introduces a set of names for the operations of the + * protocol. This is merely for convenience; it allows us to ask for an execution + * in which named operations occur, or example. + * + * \item {\em State} represents the global states. Each state has a partition of + * the nodes into one of four statuses: {\em waiting} to participate, {\em active} + * (having sent messages on outgoing links), {\em contending} (having sent a + * request on a link and received a request on its dual), and {\em elected} + * (having designated itself as a root). A set of links are labelled as parent + * links. There is a message queue associated with each link. Finally, the state + * is associated with the operation that produced it. + * + * \item {\em Queue} represents the message queues. Each queue has a slot that + * optionally contains a message; the relation {\em slot} is a partial function + * from queues to messages. In our first attempt at a model, we represented a + * queue as a sequence (a partial function from a prefix of the integers to + * messages), but having checked that no queue ever contained more than one + * message, we simplified the model. The {\em overflow} field is included just in + * case this was a mistake; a write to a queue that already contains a message + * puts an arbitrary value there, which is easily detected. + * + * \end{itemize} + * + * The {\em facts} record the assumptions about the topology. The one named {\em + * Topology} says that there is some partial function on nodes and some root such + * that (1) every node is reachable from the root ({\tt *r} being the reflexive + * transitive closure of the relation {\tt r}); (2) there are no cycles (expressed + * by saying that the transitive closure has no intersection with the identity + * relation on nodes); and (3) the relation obtained by following the {\em source} + * relation backwards (from a node to the link for which it is a source), and then + * the {\em target} relation forwards (from the link to its target) is this + * relation, plus its transpose (so that each tree edge becomes two + * links). Although the quantifier appears to be higher-order, it will be + * skolemized away by the analyzer. + * + * The {\em functions} of the model are parameterized formulas. The function {\em + * Trans} relates a pre-state {\tt s} to a post-state {\tt s'}. It has a case for + * each operation. Look at the clause for the operation {\em WriteReqOrAck}, for + * example. If this operation is deemed to have occurred, each of the constraints + * in the curly braces must hold. The first says that the labelling of links as + * parent links is unchanged. The second constraint (the quantified formula) + * constrains with respect to the node at which the operation occurs. The + * subformulas, from first to last, say that the node belongs to the waiting set + * before and the active set afterwards; that there is at most one ({\em sole}) + * link that is incoming but not a parent link in the pre-state; that there are no + * changes to node status except at this node; that a message is queued onto each + * outgoing link; and that queues on all other links are unchanged. + * + * An 'invoked' function is simply short for the formula in its body with the + * formal arguments replaced by the actual expressions. {\em WriteQueue}, for + * example, says that if the queue's slot is not filled in the pre-state, then the + * new queue in the post-state (given the local name {\tt q}) contains the message + * {\tt m} in its slot, and has no message in its overflow. Otherwise, some + * message is placed arbitrarily in the overflow, and the slot is + * unconstrained. In {\em WriteReqOrAck}, the arguments {\tt s} and {\tt s'} are + * bound to the {\tt s} and {\tt s'} of {\em Trans}; {\tt x} is bound to one of + * the outgoing links from the set {\tt n.from}; and {\tt msg} is bound either to + * the acknowledgment or request message. + * + * The function {\em Execution} constrains the set of states. It makes use of a + * library module that defines a polymorphic ordering relation. The expression + * {\tt Ord[State]} gives an ordering on all states. The two formulas of the + * function say that {\tt Initialization} holds in the first state, and that any + * pair of adjacent states is related by {\tt Trans}. The function {\em NoRepeats} + * adds the constraints that there are no equivalent states in the trace, and that + * no stuttering occurs. + * + * The three assertions are theorems for which the analyzer will search for + * counterexamples. They assert respectively that: in every state of the trace, + * there is at most one node that has been elected; that there is some state in + * which a node has been elected; and that no queue overflows. + * + * The rest of the model is a collection of commands executed to find instances of + * the functions or counterexamples to the theorems. We started by presenting a + * variety of functions as a sanity check; here, only one is given, that asks for + * an execution involving 2 nodes, 4 links, 4 queues and a trace of 6 states. The + * standard semantics of these {\em scope} declarations in Alloy is that the + * numbers represent an upper bound, so an instance may involve fewer than 4 + * queues, for example. The ordering module (not shown here), however, for + * technical reasons, constrains the ordered set to match its scope, so a trace + * with fewer than 6 states will not be acceptable. + * + * We then established some bounds on the diameter of the state machine for + * various topology bounds. For 2 nodes and 2 links, for example, there are no + * non-repeating traces of length 4; checking traces of length 3 is thus + * sufficient in this case. The number of queues was limited to 5, to accommodate + * the empty queue, a queue containing an {\tt Ack} or {\tt Req}, and each of + * these with overflow. For 3 nodes and 6 links, a trace length of 8 suffices. + * + * We then checked that for these various topology bounds, the queues never + * overflow. Finally, we checked the correctness properties, taken advantage of + * the earlier results that justify the short traces and queues. We are thus able + * to verify the properties for all topologies involving the given number of nodes + * and links, without any assumptions about trace length, queue size or the + * particular topological structure. + * + * author: Daniel Jackson + * visualization: Robert Seater + */ + +open util/ordering[State] as ord + +abstract sig Msg {} +one sig Req, Ack extends Msg {} + +sig Node {to, from: set Link} { + to = {x: Link | x.target = this} + from = {x: Link | x.source = this} + } + +sig Link {target, source: Node, reverse: Link} { + reverse.@source = target + reverse.@target = source + } + +/** + * at most one link between a pair of nodes in a given direction + */ +fact {no x,y: Link | x!=y && x.source = y.source && x.target = y.target} + +/** + * topology is tree-like: acyclic when viewed as an undirected graph + */ +fact Topology { +some tree: Node lone -> Node, root: Node { + Node in root.*tree + no ^tree & iden & Node->Node + tree + ~tree = ~source.target + } +} + +sig Op {} +one sig Init, AssignParent, ReadReqOrAck, Elect, WriteReqOrAck, +ResolveContention, Stutter extends Op {} + +sig State { + disj waiting, active, contending, elected: set Node, + parentLinks: set Link, + queue: Link -> one Queue, + op: Op -- the operation that produced the state + } { + waiting + active + contending + elected = Node +} + +pred SameState [s, s': State] { + s.waiting = s'.waiting + s.active = s'.active + s.contending = s'.contending + s.elected = s'.elected + s.parentLinks = s'.parentLinks + all x: Link | SameQueue [s.queue[x], s'.queue[x]] + } + +pred Trans [s, s': State] { + s'.op != Init + s'.op = Stutter => SameState [s, s'] + s'.op = AssignParent => { + some x: Link { + x.target in s.waiting & s'.waiting + NoChangeExceptAt [s, s', x.target] + ! IsEmptyQueue [s, x] + s'.parentLinks = s.parentLinks + x + ReadQueue [s, s', x] + }} + s'.op = ReadReqOrAck => { + s'.parentLinks = s.parentLinks + some x: Link { + x.target in s.(active + contending) & (PeekQueue [s, x, Ack] => s'.contending else s'.active) + NoChangeExceptAt [s, s', x.target] + ! IsEmptyQueue [s, x] + ReadQueue [s', s, x] + }} + s'.op = Elect => { + s'.parentLinks = s.parentLinks + some n: Node { + n in s.active & s'.elected + NoChangeExceptAt [s, s', n] + n.to in s.parentLinks + QueuesUnchanged [s, s', Link] + }} + s'.op = WriteReqOrAck => { + -- note how this requires access to child ptr + s'.parentLinks = s.parentLinks + some n: Node { + n in s.waiting & s'.active + lone n.to - s.parentLinks + NoChangeExceptAt [s, s', n] + all x: n.from | + let msg = (x.reverse in s.parentLinks => Ack else Req) | + WriteQueue [s, s', x, msg] + QueuesUnchanged [s, s', Link - n.from] + }} + s'.op = ResolveContention => { + some x: Link { + let contenders = x.(source + target) { + contenders in s.contending & s'.active + NoChangeExceptAt [s, s', contenders] + } + s'.parentLinks = s.parentLinks + x + } + QueuesUnchanged [s, s', Link] + } +} + +pred NoChangeExceptAt [s, s': State, nodes: set Node] { + let ns = Node - nodes { + ns & s.waiting = ns & s'.waiting + ns & s.active = ns & s'.active + ns & s.contending = ns & s'.contending + ns & s.elected = ns & s'.elected + }} + +sig Queue {slot: lone Msg, overflow: lone Msg} + +pred SameQueue [q, q': Queue] { + q.slot = q'.slot && q.overflow = q'.overflow + } + +pred ReadQueue [s, s': State, x: Link] { +-- let q = s'.queue[x] | no q.(slot + overflow) + no s'.queue[x].(slot + overflow) + all x': Link - x | s'.queue[x'] = s.queue[x'] + } + +pred PeekQueue [s: State, x: Link, m: Msg] { + m = s.queue[x].slot + } + +pred WriteQueue [s, s': State, x: Link, m: Msg] { + let q = s'.queue[x] | + no s.queue[x].slot => + ( q.slot = m && no q.overflow) else + some q.overflow + } + +pred QueuesUnchanged [s, s': State, xs: set Link] { + all x: xs | s'.queue[x] = s.queue[x] + } + +pred IsEmptyQueue [s: State, x: Link] { + no s.queue[x].(slot + overflow) +-- let q = s.queue[x] | no q.(slot + overflow) + } + +pred Initialization [s: State] { + s.op = Init + Node in s.waiting + no s.parentLinks + all x: Link | IsEmptyQueue [s, x] + } + +pred Execution { + Initialization [ord/first] + all s: State - ord/last | let s' = ord/next[s] | Trans [s, s'] + } + +pred ElectionHappens { + Execution + some s: State | some s.elected + some s: State | no s.elected +} + +pred NoRepeats { + Execution + no s, s': State | s!=s' && SameState [s, s'] + no s: State | s.op = Stutter + } + +pred NoShortCuts { + all s: State | -- remove this to speed up analysis - Ord[State].last - OrdPrev (Ord[State].last) | + ! Trans [s, ord/next[ord/next[s]]] + } + +assert AtMostOneElected { + Execution => (all s: State | lone s.elected) + } + +assert OneEventuallyElected { + Execution => (some s: State | some s.elected) + } + +assert NoOverflow { + Execution => (all s: State, x: Link | no s.queue[x].overflow) + } + +run Execution for 7 Op, 2 Msg, + 2 Node, 4 Link, 4 Queue, 6 State expect 1 + +run ElectionHappens for 7 Op, 2 Msg, + exactly 3 Node, 6 Link, 3 Queue, 7 State expect 1 + +-- solution for 3 State but not for 4 State +run NoRepeats for 7 Op, 2 Msg, + 2 Node, 2 Link, 2 Queue, 4 State expect 0 + +-- solution for 8 but not 9 State +run NoRepeats for 7 Op, 2 Msg, + 3 Node, 6 Link, 6 Queue, 8 State expect 0 + +-- only 5 queues needed: just count +-- no solution: establishes at most 3 queues needed +check NoOverflow for 7 Op, 2 Msg, + 3 Node, 6 Link, 5 Queue, 9 State expect 0 + +check AtMostOneElected for 7 Op, 2 Msg, + 3 Node, 6 Link, 3 Queue, 9 State expect 0 + +check OneEventuallyElected for 7 Op, 2 Msg, + 3 Node, 6 Link, 3 Queue, 9 State expect 1 + + + +// DEFINED VARIABLES +// Defined variables are uncalled, no-argument functions. +// They are helpful for getting good visualization. +fun queued: State -> Link -> Msg { + {s: State, L: Link, m: Msg | m in L.(s.queue).slot} +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/firewire.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/firewire.thm new file mode 100644 index 00000000..04793a40 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/firewire.thm @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/ins.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/ins.als new file mode 100644 index 00000000..e5596229 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/ins.als @@ -0,0 +1,115 @@ +module examples/case_studies/ins + +/* + * Models an Intentional Naming System (INS), a scheme for + * dynamic resource discovery in a dynamic environment. + * + * For a detailed description, see: + * http://sdg.lcs.mit.edu/pubs/2000/INS_ASE00.pdf + * + * author: Sarfraz Khurshid + */ + +open util/relation as rel + +sig Attribute {} +sig Value {} +sig Record {} + +one sig Wildcard extends Value {} + +sig AVTree { + values: set Value, + attributes: set Attribute, + root: values - Wildcard, + av: attributes one -> some (values - root), + va: (values - Wildcard) one -> attributes +}{ + // values (and attributes) of tree are those reachable from root + values = root.*(va.av) +} + +sig Query extends AVTree {} {all a:attributes | one a.av} + +sig DB extends AVTree { + records : set Record, + recs: (values - root) some -> records, + lookup : Query -> (values -> records) +}{ + Wildcard !in values +} + +fact AddInvariants { + all db: DB { + all v: db.values | no v.(db.recs) & v.^(~(db.av).~(db.va)).(db.recs) + all a: db.attributes | all disj v1, v2: a.(db.av) | + (some rr: *((db.va).(db.av)).(db.recs) | no v1.rr & v2.rr) + } +} + +pred Get [db: DB, r: Record, q: Query] { + q.values = r.~(db.recs).*(~(db.av).~(db.va)) + q.attributes = q.values.~(db.av) + q.root = db.root + all a : attributes| a.~(q.va) = a.~(db.va) + all v : values | v.~(q.av) = v.~(db.av) +} + +pred Conforms [db: DB, q: Query, r: Record] { + some p: Query { + db.Get[r, p] + q.va in p.va + (q.av - Attribute -> Wildcard) in p.av + } +} + +pred indSubset[db : DB, q: Query, r: set Record, v: Value] { + all a : v.(q.va) | + (a.(q.av) in a.(db.av) => r in (a.(q.av)).(q.(db.lookup))) && + (a.(q.av) = Wildcard => r in a.(db.av).*((db.va).(db.av)).(db.recs)) +} + +pred Lookup[db: DB, q: Query, found: set Record] { + all v: Value | not v.(q.va) in v.(db.va) => no v.(q.(db.lookup)) + all v: Value | all a : v.(q.va) | + a.(q.av) != Wildcard && not a.(q.av) in a.(db.av) => no v.(q.(db.lookup)) + all v: Value - Wildcard | + no v.(q.va) => v.(q.(db.lookup)) = v.*((db.va).(db.av)).(db.recs) + all v: Value | + some v.(q.va) => indSubset[db, q, v.(q.(db.lookup)), v] && + (no r: Record - v.(q.(db.lookup)) | indSubset[db, q, v.(q.(db.lookup)) + r, v]) + found = db.root.(q.(db.lookup)) +} + +assert CorrectLookup { + all db: DB | all q : Query | all r : Record | + Conforms [db,q,r] <=> db.Lookup[q, r] +} + +pred Add [me: DB, adv: Query, r: Record, db: DB] { + // restricted version - only advertisements with fresh attributes and values added + no me.attributes & adv.attributes + me.values & adv.values = me.root + me.root = adv.root + Wildcard !in adv.values + r !in me.records + db.values = me.values + adv.values + db.attributes = me.attributes + adv.attributes + db.root = me.root + db.av = me.av + adv.av + db.va = me.va + adv.va + db.recs = me.recs + ((db.values - dom[db.va]) -> r) +} + +pred RemoveWildCard[me: Query, q: Query] { + q.values = me.values - Wildcard + q.attributes = me.attributes - Wildcard.~(me.av) + q.root = me.root + q.av = me.av - Attribute -> Wildcard + q.va = me.va - Value -> Wildcard.~(me.av) +} + +assert MissingAttributeAsWildcard { + all db : DB, q, q' : Query, found: set Record | + db.Lookup[q, found] && q.RemoveWildCard[q'] => db.Lookup[q', found] +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/iolus.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/iolus.als new file mode 100644 index 00000000..cc27ba39 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/iolus.als @@ -0,0 +1,320 @@ +module examples/case_studies/iolus + +/* + * This is a model of Iolus, a scheme for secure multicasting. + * In this scheme, nodes multicast messages to other nodes + * within a group whose membership changes dynamically. The + * group is partitioned into subgroups, arranged in a tree, + * each with its own Key Distribution Server (KDS). + * + * For a detailed description, see: + * Mana Taghdiri, "Lightweight Modelling and Automatic Analysis + * of Multicast Key Management Schemes", Masters Thesis, Dept. + * of EECS, MIT, Dec. 2002. + * http://sdg.lcs.mit.edu/pubs/theses/taghdiri_masters.pdf + * + * author: Mana Taghdiri + */ + +open util/ordering[Tick] as ord + +sig Tick {} + +/** + * It can be abstract, since the fact below says Key=GroupKey + */ +abstract sig Key {} + +/** + * It can be abstract, since the fact below says Message=DataMessage + */ +abstract sig Message { + sender : Member, + sentTime : Tick, + key : Key +} + +/** + * It can be abstract, since the fact below says KDS=GSA + */ +abstract sig KDS { + keys : Tick -> Key, + members : Tick -> Member +}{ + Monotonic[keys] + all t : Tick | let t' = ord/prev[t] { + all m : members[t]-members[t'] | Join[m, t, this] + all m : members[t']-members[t] | Leave[m, t] + } +} + +/** + * It can be abstract, since the fact below says "Member=Client" + */ +abstract sig Member { + ownedKeys : Tick -> Key, + receivedMessages : Tick -> Message +}{ + Monotonic[ownedKeys] + Monotonic[receivedMessages] +} + +fact MemberBehavior { + Init[ord/first] + all m : Member, t : Tick - ord/first | + (some msg : Message | + SendMessage[m, t, msg] || ReceiveMessage[m, t, msg]) || + (some kds : KDS | Join[m, t, kds]) || + Leave[m, t] || MemberInactive[m, t] +} + +pred Monotonic[r : Tick -> univ] { + all t : Tick | ord/prev[t].r in t.r +} + +---------------------------------------------- +sig GroupKey extends Key { + generator : GSA, + generatedTime : Tick +}{ + some c : Client | + (Join[c, generatedTime, c.server] || Leave[c, generatedTime]) && + c.server = generator +} + +sig DataMessage extends Message { + gsaID : GSA, + retransmitTime : Tick } +{ SendMessage[sender, sentTime, this] || + (some msg' : DataMessage | + Remulticast[gsaID, msg', retransmitTime, this]) } + +sig GSA extends KDS { + parent : lone GSA } +{ keys[Tick].generator = this + all t : Tick, k : keys[t] - keys[ord/prev[t]] | + k.generatedTime = t } + +sig Client extends Member { + server : GSA } +{ all t : Tick, k : ownedKeys[t] - ownedKeys[ord/prev[t]] | + k.generator = server && k.generatedTime = t } + +fact IolusProperties { + no k, k' : GroupKey | k!=k' && k.generator = k'.generator && k.generatedTime = k'.generatedTime + all g : GSA, msg : DataMessage, t : Tick | RemulticastConditions[g, msg, t] => + (some msg': DataMessage | Remulticast[g, msg, t, msg']) +} + +fact GSATree { + let root = {g : GSA | no g.parent} { + one root + GSA in root.*~parent }} + +fact { + Member = Client + KDS = GSA + Message = DataMessage + Key = GroupKey + no m, m' : DataMessage { + m!=m' + m.sender = m'.sender + m.sentTime = m'.sentTime + m.key = m'.key + m.gsaID = m'.gsaID + m.retransmitTime = m'.retransmitTime } +} + +---------------------------------------------- +pred Init[t : Tick] { + no Member.receivedMessages[t] + no Member.ownedKeys[t] + no KDS.keys[t] + no KDS.members[t] } + +pred Join[m : Member, t : Tick, kds : KDS] { + kds = m.server + JoinRequest[m, kds, t] + NoChange[m.receivedMessages, t] +} +pred JoinRequest[c : Client, gsa : GSA, t : Tick] { + c !in gsa.members[ord/prev[t]] + KeyUpdate[gsa, t] + c in gsa.members[t] } + +pred Leave[m : Member, t : Tick] { + LeaveRequest[m, m.server, t] + NoChange[m.receivedMessages, t] } + +pred LeaveRequest[c : Client, gsa : GSA, t : Tick] { + c in gsa.members[ord/prev[t]] + KeyUpdate[gsa, t] + c !in gsa.members[t] } + +pred SendMessage[m : Member, t : Tick, msg : Message] { + SendRequest[m, m.server, t, msg] + m.receivedMessages[t] = m.receivedMessages[ord/prev[t]] + msg + ConstantMembership[m, t] } + +pred SendRequest[c : Client, gsa : GSA, t : Tick, msg : DataMessage] { + c in gsa.members[t] + msg.sender = c + msg.sentTime = t + NewestKey[gsa.keys[t], msg.key] + msg.gsaID = gsa + msg.retransmitTime = t + (some gsa.parent.members[t]) => + (some msg' : DataMessage | Remulticast[gsa, msg, t, msg']) } + +pred ReceiveMessage[m : Member, t : Tick, msg : Message] { + ReceiveConditions[m, t, msg] + m.receivedMessages[t] = m.receivedMessages[ord/prev[t]] + msg } + +pred MemberInactive[m : Member, t : Tick] { + NoChange[m.receivedMessages, t] --does not constrain owned keys + ConstantMembership[m, t] } + +pred ReceiveConditions[m : Member, t : Tick, msg : Message] { + ConstantMembership[m, t] + msg !in m.receivedMessages[ord/prev[t]] + msg.retransmitTime in ord/prevs[t] + msg.key in m.ownedKeys[t] } + +pred CanReceive[m : Member, t : Tick, msg : Message] { + some msg' : DataMessage { + msg'.sentTime = msg.sentTime + msg'.sender = msg.sender + msg' in m.receivedMessages[ord/prev[t]] || ReceiveConditions[m, t, msg'] }} + +pred IsMember[m : Member, t : Tick] { + some kds : KDS | m in kds.members[t] +} + +------------------------------------------- +pred RemulticastConditions[g : GSA, msg : DataMessage, t : Tick] { + msg.retransmitTime in ord/prevs[t] + msg.key in g.keys[t] + g.parent.keys[t] + some g.parent + g - msg.gsaID } + +pred Remulticast[g : GSA, msg : DataMessage, t : Tick, msg': lone DataMessage] { + RemulticastConditions[g, msg, t] + let g' = g.parent + g - msg.gsaID | NewestKey[g'.keys[msg.sentTime], msg'.key] + msg'.sender = msg.sender + msg'.sentTime = msg.sentTime + msg'.retransmitTime = t + msg'.gsaID = g +} + +pred KeyUpdate[g : GSA, t : Tick] { + some k : Key { + GeneratedKey[g, t, k] + all c : Client | c in g.members[t] <=> k in c.ownedKeys[t] + k in g.keys[t] }} + +pred NewestKey[keys : set GroupKey, newest: lone GroupKey] { + some keys <=> some newest + newest in keys + no ord/nexts[newest.generatedTime] & keys.generatedTime } + +pred GeneratedKey[g : GSA, t : Tick, key : GroupKey] { + key.generator = g + key.generatedTime = t +} + +pred ConstantMembership[c : Client, t : Tick] { + IsMember[c, t] <=> IsMember[c, ord/prev[t]] } + + +pred NoChange[r : Tick -> univ, t : Tick] { + r[ord/prev[t]] = r[t] +} + +-------------------------------------------- +assert Acyclic { + all g : GSA | g !in g.^parent } + +//check Acyclic for 6 -- one min + +assert Connected { + all g, g' : GSA | g in g'.*(parent + ~parent) } + +//check Connected for 6 + +assert TimeProceeds { + no msg : DataMessage | msg.retransmitTime in ord/prevs[msg.sentTime] } + +//check TimeProceeds for 6 + +pred LoopFree { + no t, t' : Tick { + t!=t' + all k : KDS | k.members[t] = k.members[t'] -- no constraint on keys + all m : Member | m.receivedMessages[t] = m.receivedMessages[t'] + all m : DataMessage | m.retransmitTime = t => + (some m' : DataMessage { + m'.retransmitTime = t' + m.sender = m'.sender + m.sentTime = m'.sentTime + m.gsaID = m'.gsaID + m.key = m'.key }) + }} + +//fact NoLoop { LoopFree() } -- Property-specific diameter + +------------------------------------------------ +assert loop { + !LoopFree } +//check loop for 13 but 2 Member, 1 KDS, 1 Message + +assert NonLinearTopology { + (no g : GSA | #g.~parent > 1) || + !(some m, m' : DataMessage | Remulticast[m.gsaID, m', m.retransmitTime, m] + && !SendMessage[m.sender, m.sentTime, m] + && (some c : Client | m in c.receivedMessages[ord/nexts[m.retransmitTime]]))} + +//check NonLinearTopology for 5 but 3 KDS, 3 Member, 2 Message -- > good scenario + +assert NotOutside { + no msg : DataMessage | !IsMember[msg.sender, msg.sentTime] } + +//check NotOutside for 5 + +assert Trivial { + 0 = 1 } + +//check Trivial for 2 but 1 KDS + +assert x { + !(LoopFree && some DataMessage && + (some t : Tick | some m, m' : Member | + m!=m' && IsMember[m, t] && IsMember[m', t] && t != ord/next[ord/first])) +} + +//check x for 3 but 2 Member, 2 KDS, 2 Message + ------------------------------------------- +assert OutsiderCantRead { + no msg : Message, m : Member, t : Tick { + IsMember[msg.sender, msg.sentTime] + !IsMember[m, msg.sentTime] + CanReceive[m, t, msg] + } +} +assert OutsiderCantSend { + no msg : Message, m : Member, t : Tick { + !IsMember[msg.sender, msg.sentTime] + IsMember[m, t] + msg !in m.receivedMessages[ord/prev[t]] + CanReceive[m, t, msg] + } +} +assert InsiderCanRead { + all msg : Message, m : Member | + some t : Tick - ord/last | all t' : ord/nexts[t] | + (IsMember[msg.sender, msg.sentTime] && + IsMember[m, msg.sentTime]) => CanReceive[m, t', msg] +} + +check OutsiderCantRead for 5 but 3 Member expect 0 +//check OutsiderCantSend for 5 but 3 Member -- 5 min +//check InsiderCanRead for 9 but 2 Member, 1 KDS, 1 Message +//check InsiderCanRead for 10 but 2 Member, 2 KDS, 2 Message -- not able to check diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/sync.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/sync.als new file mode 100644 index 00000000..b79c5b5d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/sync.als @@ -0,0 +1,134 @@ +module examples/case_studies/sync + +/* + * Model of a generic file synchronizer. + * + * Adapted from: + * Reference: S. Balasubramaniam and Benjamin C. Pierce, + * "What is a File Synchronizer", Indiana University CSCI + * Technical Report #507, April 22, 1998 + * + * For a detailed description, see: + * http://sdg.lcs.mit.edu/pubs/theses/tnolte_masters.pdf + * + * author: Tina Nolte + */ + +private open util/graph[Name] as graph + +/** + * The Name atom represents the hierarchy of all name sequences + * used in the model. A Name atom represents the name, and the path + * in the sequence of names to the root excluding the RootName. + */ +sig Name { + children: set Name +} + +fact { graph/tree[children] } + +one sig RootName extends Name { } + +fact { Name in RootName.*children } + +// We assume that the empty path always + +sig FileContents { } +one sig Dir extends FileContents { } + +pred IsValidFS[fs: Name -> lone FileContents] { + all n: Name - RootName | { + // files don't have children + n.fs != Dir => no (n.^children).fs + // if a path maps to something non-nil, all prefixes do also + some n.fs => some (n.~children).fs + } + // the root of a file system must be a directory + RootName.fs = Dir +} + +pred IsValidDirty[dirty: set Name] { + all n: dirty | n.~children in dirty + RootName in dirty => some dirty - RootName +} + +pred DirtiesValid[A, B: Name -> lone FileContents, Adirty, Bdirty: set Name] { + some O: Name -> lone FileContents | { + IsValidFS[O] + { n: Name | n.O != n.A } in Adirty + { n: Name | n.O != n.B } in Bdirty + } +} + +fun RestrictFS[fs: Name -> lone FileContents, p: Name]: Name -> lone FileContents { + fs & (p.*children -> FileContents) +} + +fun RestrictFSComplement[fs: Name -> lone FileContents, p: Name]: Name -> lone FileContents { + fs & ((Name - p.*children) -> FileContents) +} + +/** + * The following function test whether a particular synchronizer + * operation satisfies the "reasonableness" conditions. + * The arguments are: + * O - the original filesystem. + * A,B - separately modified copies + * Adirty, Bdirty - sets of paths modified in A and B, respectively, from O. + * + * A',B' - results of synchronizer operation + */ +pred SyncSpec[A, B, A', B': Name -> lone FileContents, Adirty, Bdirty: set Name] { + { + IsValidFS[A] + IsValidFS[B] + IsValidDirty[Adirty] + IsValidDirty[Bdirty] + } => { + { + all p: Name | IsRelevantPath[p, A, B] => { + SyncSpecForPath[p, A, B, A', B', Adirty, Bdirty] + } + } + IsValidFS[A'] + IsValidFS[B'] + } +} + +pred SyncSpecForPath[p: Name, A, B, A', B': Name -> lone FileContents, Adirty, Bdirty: set Name] { + (p.A = p.B => (p.A' = p.A && p.B' = p.B)) + (p !in Adirty => (RestrictFS[A', p] = RestrictFS[B, p] && RestrictFS[B', p] = RestrictFS[B, p])) + (p !in Bdirty => (RestrictFS[B', p] = RestrictFS[A, p] && RestrictFS[A', p] = RestrictFS[A, p])) + ((p in Adirty && p in Bdirty && p.A != p.B) => (RestrictFS[A',p] = RestrictFS[A,p] && RestrictFS[B',p] = RestrictFS[B,p])) +} + +pred IsRelevantPath[p: Name, A, B: Name -> lone FileContents] { + p = RootName || { + (p.~children).A = Dir + (p.~children).B = Dir + } +} + +pred SyncSpecExample[A, B, A', B': Name -> lone FileContents, Adirty, Bdirty: set Name] { + IsValidFS[A] + IsValidFS[B] + IsValidDirty[Adirty] + IsValidDirty[Bdirty] + SyncSpec[A, B, A', B', Adirty, Bdirty] + A != A' +} + +//run SyncSpecExample for 3 + +pred SyncSpecNotUnique { + some A, B, A1', B1', A2', B2': Name -> lone FileContents, Adirty, Bdirty: set Name | { + IsValidFS[A] && IsValidFS[B] + IsValidDirty[Adirty] && IsValidDirty[Bdirty] + //DirtiesValid(A, B, Adirty, Bdirty) + (A1' != A2' || B1' != B2') + SyncSpec[A, B, A1', B1', Adirty, Bdirty] + SyncSpec[A, B, A2', B2', Adirty, Bdirty] + } +} + +run SyncSpecNotUnique for 5 expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/syncimpl.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/syncimpl.als new file mode 100644 index 00000000..fe20377e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/case_studies/syncimpl.als @@ -0,0 +1,107 @@ +module examples/case_studies/syncimpl + +/* + * Model of a file synchronizer reconciliation algorithm. + * + * Adapted from: + * Reference: S. Balasubramaniam and Benjamin C. Pierce, + * "What is a File Synchronizer", Indiana University CSCI + * Technical Report #507, April 22, 1998 + * + * For a detailed description, see: + * http://sdg.lcs.mit.edu/pubs/theses/tnolte_masters.pdf + * + * author: Tina Nolte + */ + +open examples/case_studies/sync as sync +open util/ordering[sync/Name] as ord +open util/relation as rel + +// Model the reconciliation algorithm + +sig ReconName extends Name { + Ain, Bin, Aout, Bout: Name->FileContents, + p_children: set Name, + first_p_child, last_p_child: lone Name, + prev_p_child: (p_children - first_p_child) -> p_children +} + +fact { + all x: ReconName { + x.p_children = ChildrenAB[x.Ain, x.Bin, x] + x.first_p_child = { pc: x.p_children | x.p_children in (pc + nexts[pc]) } + x.last_p_child = { pc: x.p_children | x.p_children in (pc + prevs[pc]) } + all p_child: x.p_children - x.first_p_child | { + let earlierChildren = prevs[p_child] & x.p_children | + p_child . (x.prev_p_child) = { earlierChild: earlierChildren | earlierChildren in (earlierChild + @prevs[earlierChild]) } + } + } +} + +fact { ReconName = Name } + +fun ChildrenAB[A, B: Name -> lone FileContents, p: Name]: set Name { + p.children & (dom[A] + dom[B]) +} + +pred reconHelper[Adirty, Bdirty: set Name] { + all p: Name { + let A = p.Ain, B = p.Bin, A' = p.Aout, B' = p.Bout | { + some p.(A+B) => { + (p !in Adirty && p !in Bdirty) => (A' = A && B' = B) else { + (p.A = Dir && p.B = Dir) => { + no p_children => { + p.Aout = p.Ain + p.Bout = p.Bin + } else { + p.first_p_child.Ain = p.Ain + p.first_p_child.Bin = p.Bin + p.Aout = p.last_p_child.Aout + p.Bout = p.last_p_child.Bout + all pchild: p.p_children - p.first_p_child | { + pchild.Ain = (pchild.(p.prev_p_child)).Aout + pchild.Bin = (pchild.(p.prev_p_child)).Bout + } + } // some p_children + } else { // !(p.A = Dir && p.B = Dir) + p !in Adirty => { + A' = RestrictFS[B, p] + RestrictFSComplement[A, p] + B' = B + } else { + p !in Bdirty => { + A' = A + B' = RestrictFS[A, p] + RestrictFSComplement[B, p] + } else { + A' = A + B' = B + } + } // not "p !in Adirty" + } // not case 2 i.e. not both are dirs + } // not both clean + } // some p.(A+B) + } // let A =, B=, A'=, B'= + } // all p: Name +} // reconHelper() + +pred recon[A, B, A', B': Name -> lone FileContents, Adirty, Bdirty: set Name] { + A = ReconName.Ain + B = ReconName.Bin + A' = ReconName.Aout + B' = ReconName.Bout + reconHelper[Adirty, Bdirty] +} + +assert Correctness { + all A, B, A', B': Name -> lone FileContents, Adirty, Bdirty: set Name | { + { + DirtiesValid[A, B, Adirty, Bdirty] + recon[A, B, A', B', Adirty, Bdirty] + //no Adirty + Bdirty + } + => + SyncSpec[A, B, A', B', Adirty, Bdirty] + } +} + +check Correctness for 4 but 2 FileContents expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/puzzles/farmer.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/puzzles/farmer.als new file mode 100644 index 00000000..d3636486 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/puzzles/farmer.als @@ -0,0 +1,92 @@ +module examples/puzzles/farmer + +/* + * The classic river crossing puzzle. A farmer is carrying a fox, a + * chicken, and a sack of grain. He must cross a river using a boat + * that can only hold the farmer and at most one other thing. If the + * farmer leaves the fox alone with the chicken, the fox will eat the + * chicken; and if he leaves the chicken alone with the grain, the + * chicken will eat the grain. How can the farmer bring everything + * to the far side of the river intact? + * + * authors: Greg Dennis, Rob Seater + * + * Acknowledgements to Derek Rayside and his students for finding and + * fixing a bug in the "crossRiver" predicate. + */ + +open util/ordering[State] as ord + +/** + * The farmer and all his possessions will be represented as Objects. + * Some objects eat other objects when the Farmer's not around. + */ +abstract sig Object { eats: set Object } +one sig Farmer, Fox, Chicken, Grain extends Object {} + +/** + * Define what eats what when the Farmer' not around. + * Fox eats the chicken and the chicken eats the grain. + */ +fact eating { eats = Fox->Chicken + Chicken->Grain } + +/** + * The near and far relations contain the objects held on each + * side of the river in a given state, respectively. + */ +sig State { + near: set Object, + far: set Object +} + +/** + * In the initial state, all objects are on the near side. + */ +fact initialState { + let s0 = ord/first | + s0.near = Object && no s0.far +} + +/** + * Constrains at most one item to move from 'from' to 'to'. + * Also constrains which objects get eaten. + */ +pred crossRiver [from, from', to, to': set Object] { + // either the Farmer takes no items + (from' = from - Farmer - from'.eats and + to' = to + Farmer) or + // or the Farmer takes one item + (one x : from - Farmer | { + from' = from - Farmer - x - from'.eats + to' = to + Farmer + x }) +} + +/** + * crossRiver transitions between states + */ +fact stateTransition { + all s: State, s': ord/next[s] { + Farmer in s.near => + crossRiver[s.near, s'.near, s.far, s'.far] else + crossRiver[s.far, s'.far, s.near, s'.near] + } +} + +/** + * the farmer moves everything to the far side of the river. + */ +pred solvePuzzle { + ord/last.far = Object +} + +run solvePuzzle for 8 State expect 1 + +/** + * no Object can be in two places at once + * this is implied by both definitions of crossRiver + */ +assert NoQuantumObjects { + no s : State | some x : Object | x in s.near and x in s.far +} + +check NoQuantumObjects for 8 State expect 0 \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/puzzles/farmer.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/puzzles/farmer.thm new file mode 100644 index 00000000..41d7ada7 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/puzzles/farmer.thm @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/puzzles/handshake.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/puzzles/handshake.als new file mode 100644 index 00000000..8fce6178 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/puzzles/handshake.als @@ -0,0 +1,64 @@ +module examples/puzzles/handshake + +/* + * Alloy model of the Halmos handshake problem + * + * Hilary and Jocelyn are married. They invite four couples who are friends for dinner. When + * they arrive, they shake hands with each other. Nobody shakes hands with him or herself + * or with his or her spouse. After there has been some handshaking, Jocelyn jumps up on + * a chair and says "Stop shaking hands!", and then asks how many hands each person has + * shaken. All the answers are different. How many hands has Hilary shaken? + * + * The Alloy model represents the problem as a set of constraints. Properties of the spouse + * relationship and of handshaking in general are given as facts. The particular situation + * is cast as a function. + * + * There are 9 people answering, and all answers are different. Nobody can shake more than + * 8 hands. So answers must be 0..8. The one (p8 say) who answered 8 has shaken everybody's + * hand except for his or her own, and his or her spouse's. Now consider the person who shook + * 0 hands (p0 say). The persons p0 and p8 are distinct. If they are not married, then p8 cannot + * have shaken 8 hands, because he or she did not shake the hand of p0 or of his or her spouse. + * So p8's spouse to p0. Now imagine Jocelyn asking the question again, with p0 and p8 out of + * the room, and excluding hand shakes with them. Since p8 shook hands with everyone else + * except p0 and p8, everyone gives an answer one smaller than they did before, giving 0..6. + * The argument now applies recursively. So Hilary is left alone, having shaken 4 hands. + * + * author: Daniel Jackson, 11/15/01 + */ + +sig Person {spouse: Person, shaken: set Person} +one sig Jocelyn, Hilary extends Person {} + +fact ShakingProtocol { + // nobody shakes own or spouse's hand + all p: Person | no (p + p.spouse) & p.shaken + // if p shakes q, q shakes p + all p, q: Person | p in q.shaken => q in p.shaken + } + +fact Spouses { + all p, q: Person | p!=q => { + // if q is p's spouse, p is q's spouse + p.spouse = q => q.spouse = p + // no spouse sharing + p.spouse != q.spouse + } + all p: Person { + // a person is his or her spouse's spouse + p.spouse.spouse = p + // nobody is his or her own spouse + p != p.spouse + } + } + +pred Puzzle { + // everyone but Jocelyn has shaken a different number of hands + all p,q: Person - Jocelyn | p!=q => #p.shaken != #q.shaken + // Hilary's spouse is Jocelyn + Hilary.spouse = Jocelyn + } + +P10: run Puzzle for exactly 10 Person, 5 int expect 1 +P12: run Puzzle for exactly 12 Person, 5 int expect 1 +P14: run Puzzle for exactly 14 Person, 5 int expect 1 +P16: run Puzzle for exactly 16 Person, 6 int expect 1 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/puzzles/handshake.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/puzzles/handshake.thm new file mode 100644 index 00000000..0bc070b1 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/puzzles/handshake.thm @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/puzzles/hanoi.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/puzzles/hanoi.als new file mode 100644 index 00000000..f936fa5f --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/puzzles/hanoi.als @@ -0,0 +1,140 @@ +module examples/puzzles/hanoi + +/* + * Towers of Hanoi model + * + * Description of problem from http://www.cut-the-knot.com/recurrence/hanoi.html + * + * The Tower of Hanoi puzzle was invented by the French mathematician Edouard Lucas + * in 1883. We are given a tower of eight disks, initially stacked in decreasing size on + * one of three pegs. The objective is to transfer the entire tower to one of the other + * pegs, moving only one disk at a time and never a larger one onto a smaller. + * + * The Alloy model below is written so that a solution to the model is a complete + * sequence of valid moves solving an instance of the problem. We define constraints + * for the initial state (all discs on left stake), the final state (all discs on right stake), + * and each pair of adjacent states (the top disc is moved from one stake to another, + * not putting larger discs on smaller discs), and let Alloy Analyzer solve for the + * sequence of states satisfying these constraints. Since each adjacent pair of states is + * constrained to be related by a single move, it is easy to see the sequence of moves + * once you have the sequence of states. + * + * For n discs, 2^n states are needed for a solution + * (including the initial state and the final state). + * + * Performance: currently, the problem can be solved for up to 5 discs; this takes + * several minutes with the Chaff solver. + * + * author: Ilya Shlyakhter + */ + +open util/ordering[State] as states +open util/ordering[Stake] as stakes +open util/ordering[Disc] as discs + +sig Stake { } + +sig Disc { } + +/** + * sig State: the complete state of the system -- + * which disc is on which stake. An solution is a + * sequence of states. + */ +sig State { + on: Disc -> one Stake // _each_ disc is on _exactly one_ stake + // note that we simply record the set of discs on each stake -- + // the implicit assumption is that on each stake the discs + // on that stake are ordered by size with smallest disc on top + // and largest on bottom, as the problem requires. +} + +/** + * compute the set of discs on the given stake in this state. + * ~(this.on) map the stake to the set of discs on that stake. + */ +fun discsOnStake[st: State, stake: Stake]: set Disc { + stake.~(st.on) +} + +/** + * compute the top disc on the given stake, or the empty set + * if the stake is empty + */ +fun topDisc[st: State, stake: Stake]: lone Disc { + { d: st.discsOnStake[stake] | st.discsOnStake[stake] in discs/nexts[d] + d } +} + +/** + * Describes the operation of moving the top disc from stake fromStake + * to stake toStake. This function is defined implicitly but is + * nevertheless deterministic, i.e. the result state is completely + * determined by the initial state and fromStake and toStake; hence + * the "det" modifier above. (It's important to use the "det" modifier + * to tell the Alloy Analyzer that the function is in fact deterministic.) + */ +pred Move [st: State, fromStake, toStake: Stake, s': State] { + let d = st.topDisc[fromStake] | { + // all discs on toStake must be larger than d, + // so that we can put d on top of them + st.discsOnStake[toStake] in discs/nexts[d] + // after, the fromStake has the discs it had before, minus d + s'.discsOnStake[fromStake] = st.discsOnStake[fromStake] - d + // after, the toStake has the discs it had before, plus d + s'.discsOnStake[toStake] = st.discsOnStake[toStake] + d + // the remaining stake afterwards has exactly the discs it had before + let otherStake = Stake - fromStake - toStake | + s'.discsOnStake[otherStake] = st.discsOnStake[otherStake] + } +} + +/** + * there is a leftStake that has all the discs at the beginning, + * and a rightStake that has all the discs at the end + */ +pred Game1 { + Disc in states/first.discsOnStake[stakes/first] + some finalState: State | Disc in finalState.discsOnStake[stakes/last] + + // each adjacent pair of states are related by a valid move of one disc + all preState: State - states/last | + let postState = states/next[preState] | + some fromStake: Stake | { + // must have at least one disk on fromStake to be able to move + // a disc from fromStake to toStake + some preState.discsOnStake[fromStake] + // post- results from pre- by making one disc move + some toStake: Stake | preState.Move[fromStake, toStake, postState] + } +} + +/** + * there is a leftStake that has all the discs at the beginning, + * and a rightStake that has all the discs at the end + */ +pred Game2 { + Disc in states/first.discsOnStake[stakes/first] + some finalState: State | Disc in finalState.discsOnStake[stakes/last] + + // each adjacent pair of states are related by a valid move of one disc + all preState: State - states/last | + let postState = states/next[preState] | + some fromStake: Stake | + let d = preState.topDisc[fromStake] | { + // must have at least one disk on fromStake to be able to move + // a disc from fromStake to toStake + some preState.discsOnStake[fromStake] + postState.discsOnStake[fromStake] = preState.discsOnStake[fromStake] - d + some toStake: Stake | { + // post- results from pre- by making one disc move + preState.discsOnStake[toStake] in discs/nexts[d] + postState.discsOnStake[toStake] = preState.discsOnStake[toStake] + d + // the remaining stake afterwards has exactly the discs it had before + let otherStake = Stake - fromStake - toStake | + postState.discsOnStake[otherStake] = preState.discsOnStake[otherStake] + } + } + } + +run Game1 for 1 but 3 Stake, 5 Disc, 32 State expect 1 +run Game2 for 1 but 3 Stake, 3 Disc, 8 State expect 1 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/puzzles/hanoi.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/puzzles/hanoi.thm new file mode 100644 index 00000000..f56b5722 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/puzzles/hanoi.thm @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/file_system.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/file_system.als new file mode 100644 index 00000000..60fd959b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/file_system.als @@ -0,0 +1,59 @@ +module examples/systems/file_system + +/* + * Model of a generic file system. + */ + +abstract sig Object {} + +sig Name {} + +sig File extends Object {} { some d: Dir | this in d.entries.contents } + +sig Dir extends Object { + entries: set DirEntry, + parent: lone Dir +} { + parent = this.~@contents.~@entries + all e1, e2 : entries | e1.name = e2.name => e1 = e2 + this !in this.^@parent + this != Root => Root in this.^@parent +} + +one sig Root extends Dir {} { no parent } + +lone sig Cur extends Dir {} + +sig DirEntry { + name: Name, + contents: Object +} { + one this.~entries +} + + +/** + * all directories besides root have one parent + */ +pred OneParent_buggyVersion { + all d: Dir - Root | one d.parent +} + +/** + * all directories besides root have one parent + */ +pred OneParent_correctVersion { + all d: Dir - Root | (one d.parent && one contents.d) +} + +/** + * Only files may be linked (that is, have more than one entry) + * That is, all directories are the contents of at most one directory entry + */ +pred NoDirAliases { + all o: Dir | lone o.~contents +} + +check { OneParent_buggyVersion => NoDirAliases } for 5 expect 1 + +check { OneParent_correctVersion => NoDirAliases } for 5 expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/file_system.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/file_system.thm new file mode 100644 index 00000000..4b740ad3 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/file_system.thm @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/javatypes_soundness.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/javatypes_soundness.als new file mode 100644 index 00000000..6bf50ed7 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/javatypes_soundness.als @@ -0,0 +1,140 @@ +module examples/systems/javatypes + +/* + * Model of the Java type system. The TypeSoundness assertion + * claims that if a Java program type checks successfully, + * then a field will cannot be assigned an incorrect type. + * + * author: Daniel Jackson + */ + +open util/graph[Type] as graph + +abstract sig Type { + xtends: set Type + } +sig Interface extends Type {} + { xtends in Interface } +sig Class extends Type { + implements: set Interface, + fields: set Field + } { lone xtends && xtends in Class } +-- optional: best omitted to allow private etc +-- {xtends.@fields in fields} +sig Field { + declType: Type + } + +fact { + graph/dag[xtends] + } + +abstract sig Value {} +one sig Null extends Value {} +sig Object extends Value { + type: Class, + slot: Field lone -> lone Slot + } {slot.Slot = type.fields} +sig Slot {} + +abstract sig Statement {} +sig Assignment extends Statement { + var: Variable, + expr: Expr + } +sig Setter extends Statement { + field: Field, + lexpr, rexpr: Expr + } + +abstract sig Expr { + type: Type, + subexprs: set Expr + } {subexprs = this + this.^@expr} +sig Variable extends Expr { + declType: Type + } {type = declType} +sig Constructor extends Expr { + class: Class + } +sig Getter extends Expr { + field: Field, + expr: Expr + } {type = field.declType} + +sig State { + objects: set Object, + reaches: Object -> Object, + vars: set Variable, + holds: (Slot + Variable) -> lone Value, + val: Expr -> lone Value + } { + all o: Object | o.reaches = holds[o.slot[Field]] & Object + holds.Value & Variable = vars + objects = holds[vars].^reaches + all e: Expr | let v = val[e] { + e in Variable => v = holds[e] + e in Getter => v = holds[(val[e.expr]).slot[e.field]] + e in Constructor => v in Object and v.type = e.type } + } + +pred RuntimeTypesOK [s: State] { + all o: s.objects, f: o.type.fields | + let v = s.holds [o.slot [f]] | HasType [v, f.declType] + all var: s.vars | + let v = s.holds [var] | HasType [v, var.declType] + } + +pred HasType [v: Value, t: Type] { + v in Null or Subtype [v.type, t] + } + +pred Subtype [t, t': Type] { + t in Class => + (let supers = (t & Class).*(Class<:xtends) | + t' in (supers + supers.implements.*(Interface<:xtends))) + t in Interface => t' in (t & Interface).*(Interface<:xtends) + } + +pred TypeChecksSetter [stmt: Setter] { + all g: Getter & stmt.(lexpr+rexpr).subexprs | g.field in g.expr.type.fields + stmt.field in stmt.lexpr.type.fields + Subtype [stmt.rexpr.type, stmt.field.declType] + } + +pred ExecuteSetter [s, s': State, stmt: Setter] { + stmt.(rexpr+lexpr).subexprs & Variable in s.vars + s'.objects = s.objects and s'.vars = s.vars + let rval = s.val [stmt.rexpr], lval = s.val [stmt.lexpr] { + no lval & Null + s'.holds = s.holds ++ (lval.slot[stmt.field] -> rval) + } + } + +assert TypeSoundness { + all s, s': State, stmt: Setter | + {RuntimeTypesOK[s] + ExecuteSetter [s, s', stmt] + TypeChecksSetter[stmt] + } => RuntimeTypesOK[s'] + } + +fact {all o, o': Object | some o.slot[Field] & o'.slot[Field] => o = o'} +fact {all g: Getter | no g & g.^subexprs} + +fact ScopeFact { + #Assignment =< 1 + #Class =< 5 + #Interface =< 5 +} + +check TypeSoundness for 3 expect 0 + +check TypeSoundness for 2 State, 1 Assignment, +1 Statement, 5 Interface, 5 Class, 1 Null, +7 Object, 12 Expr, 3 Field, 3 Slot expect 0 + +// very slow +// check TypeSoundness for 2 State, 1 Statement, +// 10 Type, 8 Value, 12 Expr, +// 3 Field, 3 Slot expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/lists.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/lists.als new file mode 100644 index 00000000..aabd5f63 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/lists.als @@ -0,0 +1,48 @@ +/* + * a simple list module + * which demonstrates how to create predicates and fields that mirror each other + * thus allowing recursive constraints (even though recursive predicates are not + * currently supported by Alloy) + * author: Robert Seater + */ + +module list + +sig Thing {} +fact NoStrayThings {Thing in List.car} + +abstract sig List { + equivTo: set List, + prefixes: set List + } +sig NonEmptyList extends List { + car: one Thing, + cdr: one List + } +sig EmptyList extends List {} + +pred isFinite [L:List] {some e: EmptyList | e in L.*cdr} +fact finite {all L: List | isFinite[L]} + +fact Equivalence { + all a,b: List | (a in b.equivTo) <=> ((a.car = b.car and b.cdr in a.cdr.equivTo) and (#a.*cdr = #b.*cdr)) + } +assert reflexive {all L: List | L in L.equivTo} +check reflexive for 6 expect 0 +assert symmetric {all a,b: List | a in b.equivTo <=> b in a.equivTo} +check symmetric for 6 expect 0 +assert empties {all a,b: EmptyList | a in b.equivTo} +check empties for 6 expect 0 + +fact prefix { //a is a prefix of b + all e: EmptyList, L:List | e in L.prefixes + all a,b: NonEmptyList | (a in b.prefixes) <=> (a.car = b.car + and a.cdr in b.cdr.prefixes + and #a.*cdr < #b.*cdr) +} + +pred show { + some a, b: NonEmptyList | a!=b && b in a.prefixes + } +run show for 4 expect 1 + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/lists.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/lists.thm new file mode 100644 index 00000000..6da43857 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/lists.thm @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/marksweepgc.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/marksweepgc.als new file mode 100644 index 00000000..b8081e3f --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/marksweepgc.als @@ -0,0 +1,83 @@ +module examples/systems/marksweepgc + +/* + * Model of mark and sweep garbage collection. + */ + +// a node in the heap +sig Node {} + +sig HeapState { + left, right : Node -> lone Node, + marked : set Node, + freeList : lone Node +} + +pred clearMarks[hs, hs' : HeapState] { + // clear marked set + no hs'.marked + // left and right fields are unchanged + hs'.left = hs.left + hs'.right = hs.right +} + +/** + * simulate the recursion of the mark() function using transitive closure + */ +fun reachable[hs: HeapState, n: Node] : set Node { + n + n.^(hs.left + hs.right) +} + +pred mark[hs: HeapState, from : Node, hs': HeapState] { + hs'.marked = hs.reachable[from] + hs'.left = hs.left + hs'.right = hs.right +} + +/** + * complete hack to simulate behavior of code to set freeList + */ +pred setFreeList[hs, hs': HeapState] { + // especially hackish + hs'.freeList.*(hs'.left) in (Node - hs.marked) + all n: Node | + (n !in hs.marked) => { + no hs'.right[n] + hs'.left[n] in (hs'.freeList.*(hs'.left)) + n in hs'.freeList.*(hs'.left) + } else { + hs'.left[n] = hs.left[n] + hs'.right[n] = hs.right[n] + } + hs'.marked = hs.marked +} + +pred GC[hs: HeapState, root : Node, hs': HeapState] { + some hs1, hs2: HeapState | + hs.clearMarks[hs1] && hs1.mark[root, hs2] && hs2.setFreeList[hs'] +} + +assert Soundness1 { + all h, h' : HeapState, root : Node | + h.GC[root, h'] => + (all live : h.reachable[root] | { + h'.left[live] = h.left[live] + h'.right[live] = h.right[live] + }) +} + +assert Soundness2 { + all h, h' : HeapState, root : Node | + h.GC[root, h'] => + no h'.reachable[root] & h'.reachable[h'.freeList] +} + +assert Completeness { + all h, h' : HeapState, root : Node | + h.GC[root, h'] => + (Node - h'.reachable[root]) in h'.reachable[h'.freeList] +} + +check Soundness1 for 3 expect 0 +check Soundness2 for 3 expect 0 +check Completeness for 3 expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/views.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/views.als new file mode 100644 index 00000000..3a5ab82b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/systems/views.als @@ -0,0 +1,217 @@ +module examples/systems/views + +/* + * Model of views in object-oriented programming. + * + * Two object references, called the view and the backing, + * are related by a view mechanism when changes to the + * backing are automatically propagated to the view. Note + * that the state of a view need not be a projection of the + * state of the backing; the keySet method of Map, for + * example, produces two view relationships, and for the + * one in which the map is modified by changes to the key + * set, the value of the new map cannot be determined from + * the key set. Note that in the iterator view mechanism, + * the iterator is by this definition the backing object, + * since changes are propagated from iterator to collection + * and not vice versa. Oddly, a reference may be a view of + * more than one backing: there can be two iterators on the + * same collection, eg. A reference cannot be a view under + * more than one view type. + * + * A reference is made dirty when it is a backing for a view + * with which it is no longer related by the view invariant. + * This usually happens when a view is modified, either + * directly or via another backing. For example, changing a + * collection directly when it has an iterator invalidates + * it, as does changing the collection through one iterator + * when there are others. + * + * More work is needed if we want to model more closely the + * failure of an iterator when its collection is invalidated. + * + * As a terminological convention, when there are two + * complementary view relationships, we will give them types + * t and t'. For example, KeySetView propagates from map to + * set, and KeySetView' propagates from set to map. + * + * author: Daniel Jackson + */ + +open util/ordering[State] as so +open util/relation as rel + +sig Ref {} +sig Object {} + +-- t->b->v in views when v is view of type t of backing b +-- dirty contains refs that have been invalidated +sig State { + refs: set Ref, + obj: refs -> one Object, + views: ViewType -> refs -> refs, + dirty: set refs +-- , anyviews: Ref -> Ref -- for visualization + } +-- {anyviews = ViewType.views} + +sig Map extends Object { + keys: set Ref, + map: keys -> one Ref + }{all s: State | keys + Ref.map in s.refs} +sig MapRef extends Ref {} +fact {State.obj[MapRef] in Map} + +sig Iterator extends Object { + left, done: set Ref, + lastRef: lone done + }{all s: State | done + left + lastRef in s.refs} +sig IteratorRef extends Ref {} +fact {State.obj[IteratorRef] in Iterator} + +sig Set extends Object { + elts: set Ref + }{all s: State | elts in s.refs} +sig SetRef extends Ref {} +fact {State.obj[SetRef] in Set} + +abstract sig ViewType {} +one sig KeySetView, KeySetView', IteratorView extends ViewType {} +fact ViewTypes { + State.views[KeySetView] in MapRef -> SetRef + State.views[KeySetView'] in SetRef -> MapRef + State.views[IteratorView] in IteratorRef -> SetRef + all s: State | s.views[KeySetView] = ~(s.views[KeySetView']) + } + +/** + * mods is refs modified directly or by view mechanism + * doesn't handle possibility of modifying an object and its view at once? + * should we limit frame conds to non-dirty refs? + */ +pred modifies [pre, post: State, rs: set Ref] { + let vr = pre.views[ViewType], mods = rs.*vr { + all r: pre.refs - mods | pre.obj[r] = post.obj[r] + all b: mods, v: pre.refs, t: ViewType | + b->v in pre.views[t] => viewFrame [t, pre.obj[v], post.obj[v], post.obj[b]] + post.dirty = pre.dirty + + {b: pre.refs | some v: Ref, t: ViewType | + b->v in pre.views[t] && !viewFrame [t, pre.obj[v], post.obj[v], post.obj[b]] + } + } + } + +pred allocates [pre, post: State, rs: set Ref] { + no rs & pre.refs + post.refs = pre.refs + rs + } + +/** + * models frame condition that limits change to view object from v to v' when backing object changes to b' + */ +pred viewFrame [t: ViewType, v, v', b': Object] { + t in KeySetView => v'.elts = dom [b'.map] + t in KeySetView' => b'.elts = dom [v'.map] + t in KeySetView' => (b'.elts) <: (v.map) = (b'.elts) <: (v'.map) + t in IteratorView => v'.elts = b'.left + b'.done + } + +pred MapRef.keySet [pre, post: State, setRefs: SetRef] { + post.obj[setRefs].elts = dom [pre.obj[this].map] + modifies [pre, post, none] + allocates [pre, post, setRefs] + post.views = pre.views + KeySetView->this->setRefs + KeySetView'->setRefs->this + } + +pred MapRef.put [pre, post: State, k, v: Ref] { + post.obj[this].map = pre.obj[this].map ++ k->v + modifies [pre, post, this] + allocates [pre, post, none] + post.views = pre.views + } + +pred SetRef.iterator [pre, post: State, iterRef: IteratorRef] { + let i = post.obj[iterRef] { + i.left = pre.obj[this].elts + no i.done + i.lastRef + } + modifies [pre,post,none] + allocates [pre, post, iterRef] + post.views = pre.views + IteratorView->iterRef->this + } + +pred IteratorRef.remove [pre, post: State] { + let i = pre.obj[this], i' = post.obj[this] { + i'.left = i.left + i'.done = i.done - i.lastRef + no i'.lastRef + } + modifies [pre,post,this] + allocates [pre, post, none] + pre.views = post.views + } + +pred IteratorRef.next [pre, post: State, ref: Ref] { + let i = pre.obj[this], i' = post.obj[this] { + ref in i.left + i'.left = i.left - ref + i'.done = i.done + ref + i'.lastRef = ref + } + modifies [pre, post, this] + allocates [pre, post, none] + pre.views = post.views + } + +pred IteratorRef.hasNext [s: State] { + some s.obj[this].left + } + +assert zippishOK { + all + ks, vs: SetRef, + m: MapRef, + ki, vi: IteratorRef, + k, v: Ref | + let s0=so/first, + s1=so/next[s0], + s2=so/next[s1], + s3=so/next[s2], + s4=so/next[s3], + s5=so/next[s4], + s6=so/next[s5], + s7=so/next[s6] | + ({ + precondition [s0, ks, vs, m] + no s0.dirty + ks.iterator [s0, s1, ki] + vs.iterator [s1, s2, vi] + ki.hasNext [s2] + vi.hasNext [s2] + ki.this/next [s2, s3, k] + vi.this/next [s3, s4, v] + m.put [s4, s5, k, v] + ki.remove [s5, s6] + vi.remove [s6, s7] + } => no State.dirty) + } + +pred precondition [pre: State, ks, vs, m: Ref] { + // all these conditions and other errors discovered in scope of 6 but 8,3 + // in initial state, must have view invariants hold + (all t: ViewType, b, v: pre.refs | + b->v in pre.views[t] => viewFrame [t, pre.obj[v], pre.obj[v], pre.obj[b]]) + // sets are not aliases +-- ks != vs + // sets are not views of map +-- no (ks+vs)->m & ViewType.pre.views + // no iterator currently on either set +-- no Ref->(ks+vs) & ViewType.pre.views + } + +check zippishOK for 6 but 8 State, 3 ViewType expect 1 + +/** + * experiment with controlling heap size + */ +fact {all s: State | #s.obj < 5} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/birthday.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/birthday.als new file mode 100644 index 00000000..092097f0 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/birthday.als @@ -0,0 +1,68 @@ +module examples/toys/birthday + +/* + * Birthday Book + * + * A classic Z example to explain the basic form of an Alloy model. For the original, + * see J.M. Spivey, The Z Notation, Second Edition, Prentice Hall, 1992. + * + * A birthday book has two fields: known, a set of names (of persons whose birthdays are known), + * and date, a function from known names to dates. The operation AddBirthday adds an association + * between a name and a date; it uses the relational override operator (++), so any existing + * mapping from the name to a date is replaced. DelBirthday removes the entry for a given name. + * FindBirthday obtains the date d for a name n. The argument d is declared to be optional (that is, + * a singleton or empty set), so if there is no entry for n, d will be empty. Remind gives the set + * of names whose birthdays fall on a particular day. + * + * The assertion AddWorks says that if you add an entry, then look it up, you get back what you + * just entered. DelIsUndo says that doing DelBirthday after AddBirthday undoes it, as if the add + * had never happened. The first of these assertions is valid; the second isn't. + * + * The function BusyDay shows a case in which Remind produces more than one card. + * + * author: Daniel Jackson, 11/14/01 + */ + +sig Name {} +sig Date {} +sig BirthdayBook {known: set Name, date: known -> one Date} + +pred AddBirthday [bb, bb': BirthdayBook, n: Name, d: Date] { + bb'.date = bb.date ++ (n->d) + } + +pred DelBirthday [bb, bb': BirthdayBook, n: Name] { + bb'.date = bb.date - (n->Date) + } + +pred FindBirthday [bb: BirthdayBook, n: Name, d: lone Date] { + d = bb.date[n] + } + +pred Remind [bb: BirthdayBook, today: Date, cards: set Name] { + cards = (bb.date).today + } + +pred InitBirthdayBook [bb: BirthdayBook] { + no bb.known + } + +assert AddWorks { + all bb, bb': BirthdayBook, n: Name, d: Date, d': lone Date | + AddBirthday [bb,bb',n,d] && FindBirthday [bb',n,d'] => d = d' + } + +assert DelIsUndo { + all bb1,bb2,bb3: BirthdayBook, n: Name, d: Date| + AddBirthday [bb1,bb2,n,d] && DelBirthday [bb2,bb3,n] + => bb1.date = bb3.date + } + +check AddWorks for 3 but 2 BirthdayBook expect 0 +check DelIsUndo for 3 but 2 BirthdayBook expect 1 + +pred BusyDay [bb: BirthdayBook, d: Date]{ + some cards: set Name | Remind [bb,d,cards] && !lone cards + } + +run BusyDay for 3 but 1 BirthdayBook expect 1 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/birthday.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/birthday.thm new file mode 100644 index 00000000..3c3b050b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/birthday.thm @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/ceilingsAndFloors.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/ceilingsAndFloors.als new file mode 100644 index 00000000..e02fe438 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/ceilingsAndFloors.als @@ -0,0 +1,46 @@ +module models/examples/toys/CeilingsAndFloors + +/* + * In his 1973 song, Paul Simon said "One Man's Ceiling Is Another Man's Floor". + * Does it follow that "One Man's Floor Is Another Man's Ceiling"? + * + * To see why not, check the assertion BelowToo. + * + * Perhaps simply preventing man's own floor from being his ceiling is enough, + * as is done in the Geometry constraint. BelowToo' shows that there are still + * cases where Geometry holds but the implication does not, although now + * the smallest solution has 3 Men and 3 Platforms instead of just 2 of each. + * + * What if we instead prevent floors and ceilings from being shared, + * as is done in the NoSharing constraint? The assertion BelowToo'' + * has no counterexamples, demonstrating that the implication now + * holds for all small examples. + * + * model author: Daniel Jackson (11/2001) + * modified by Robert Seater (11/2004) + */ + +sig Platform {} +sig Man {ceiling, floor: Platform} + +fact PaulSimon {all m: Man | some n: Man | n.Above[m]} + +pred Above[m, n: Man] {m.floor = n.ceiling} + +assert BelowToo { all m: Man | some n: Man | m.Above[n] } + +check BelowToo for 2 expect 1 + +pred Geometry {no m: Man | m.floor = m.ceiling} + +assert BelowToo' { Geometry => (all m: Man | some n: Man | m.Above[n]) } +check BelowToo' for 2 expect 0 +check BelowToo' for 3 expect 1 + +pred NoSharing { + no m,n: Man | m!=n && (m.floor = n.floor || m.ceiling = n.ceiling) +} + +assert BelowToo'' { NoSharing => (all m: Man | some n: Man | m.Above[n]) } +check BelowToo'' for 6 expect 0 +check BelowToo'' for 10 expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/ceilingsAndFloors.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/ceilingsAndFloors.thm new file mode 100644 index 00000000..b58a5b0d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/ceilingsAndFloors.thm @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/genealogy.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/genealogy.als new file mode 100644 index 00000000..2a9e2134 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/genealogy.als @@ -0,0 +1,74 @@ +module examples/toys/genealogy + +/* + * Toy model of genealogical relationships + * + * The purpose of this model is to introduce basic concepts in Alloy. + * The signature Person introduces a set of persons; this is paritioned into + * two subsets, Man and Woman. The subsignature Adam declares a set of men + * with one element -- that is, a scalar. Similarly, Eve declares a single + * woman. + * + * The Person signature declares two fields: a person has one or zero spouses + * and a set of parents. + * + * The facts should be self-explanatory. Note that the constraint that + * spouse is a symmetric relation (that is, p is a spouse of q if q is a spouse + * of p) is written by equating the field, viewed as a relation, to its + * transpose. Since signatures have their own namespaces, and the same field + * name can refer to different fields in different relations, it is necessary + * to indicate which signature the field belongs to. This is not necessary when + * dereferencing a field, because the appropriate field is automatically + * determined by the type of the referencing expression. + * + * The command has no solutions. Given only 5 persons, it's not possible + * to have a couple distinct from Adam and Eve without incest. To understand + * the model, try weakening the constraints by commenting lines out (just + * put two hyphens at the start of a line) and rerunning the command. + * + * author: Daniel Jackson, 11/13/01 + */ + +abstract sig Person {spouse: lone Person, parents: set Person} +sig Man, Woman extends Person {} +one sig Eve extends Woman {} +one sig Adam extends Man {} + +fact Biology { + -- nobody is his or her own ancestor + no p: Person | p in p.^parents + } + +fact Bible { + -- every person except Adam and Eve has a mother and father + all p: Person - (Adam + Eve) | one mother: Woman, father: Man | + p.parents = mother + father + -- Adam and Eve have no parents + no (Adam + Eve).parents + -- Adam's spouse is Eve + Adam.spouse = Eve + } + +fact SocialNorms { + -- nobody is his or her own spouse + no p: Person | p.spouse = p + -- spouse is symmetric + spouse = ~spouse + -- a man's spouse is a woman and vice versa + Man.spouse in Woman && Woman.spouse in Man + } + +fact NoIncest { + -- can't marry a sibling + no p: Person | some p.spouse.parents & p.parents + -- can't marry a parent + no p: Person | some p.spouse & p.parents + } + +pred Show { + some p: Person - (Adam + Eve) | some p.spouse + } +run Show for 6 expect 1 + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/genealogy.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/genealogy.thm new file mode 100644 index 00000000..fbeb5cad --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/genealogy.thm @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/grandpa.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/grandpa.als new file mode 100644 index 00000000..099cd0d5 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/grandpa.als @@ -0,0 +1,88 @@ +module grandpa + +/* + * An Alloy model of the song "I Am My Own Grandpa" + * by Dwight B. Latham and Moe Jaffe + * + * The challenge is to produce a man who is his own grandfather + * without resorting to incest or time travel. Executing the predicate + * "ownGrandpa" will demonstrate how such a thing can occur. + * + * The full song lyrics, which describe an isomorophic solution, + * are included at the end of this file. + * + * model author: Daniel Jackson + */ + +abstract sig Person { + father: lone Man, + mother: lone Woman + } + +sig Man extends Person { wife: lone Woman } + +sig Woman extends Person { husband: lone Man } + +fact Biology { no p: Person | p in p.^(mother+father) } + +fact Terminology { wife = ~husband } + +fact SocialConvention { + no wife & *(mother+father).mother + no husband & *(mother+father).father + } + +fun grandpas [p: Person]: set Person { + let parent = mother + father + father.wife + mother.husband | + p.parent.parent & Man + } + +pred ownGrandpa [m: Man] { m in grandpas[m] } + +run ownGrandpa for 4 Person expect 1 + +/* defined variables: + * + * spouse = husband+wife + */ + +/* +I Am My Own Grandpa +by Dwight B. Latham and Moe Jaffe + +Many many years ago, when I was twenty-three, +I was married to a widow as pretty as can be, +This widow had a grown-up daughter who had hair of red, +My father fell in love with her and soon the two were wed. + + I'm my own grandpa, I'm my own grandpa. + It sounds funny, I know, but it really is so + I'm my own grandpa. + +This made my dad my son-in-law and changed my very life, +For my daughter was my mother, for she was my father's wife. +To complicate the matter, even though it brought me joy, +I soon became the father of a bouncing baby boy. + +My little baby thus became a brother-in-law to dad, +And so became my uncle, though it made me very sad, +For if he was my uncle then that also made him brother +To the widow's grown-up daughter, who of course was my step-mother. + +Father's wife then had a son who kept them on the run. +And he became my grandchild for he was my daughter's son. +My wife is now my mother's mother and it makes me blue, +Because although she is my wife, she's my grandmother, too. + +Oh, if my wife's my grandmother then I am her grandchild. +And every time I think of it, it nearly drives me wild. +For now I have become the strangest case you ever saw +As the husband of my grandmother, I am my own grandpa. + + I'm my own grandpa, I'm my own grandpa. + It sounds funny, I know, but it really is so + I'm my own grandpa. + I'm my own grandpa, I'm my own grandpa. + It sounds funny, I know, but it really is so + I'm my own grandpa. +*/ diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/grandpa.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/grandpa.thm new file mode 100644 index 00000000..781b6c9f --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/grandpa.thm @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/javatypes.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/javatypes.als new file mode 100644 index 00000000..2e60d64d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/javatypes.als @@ -0,0 +1,46 @@ +module examples/toys/javatypes + +/* + * A simple model of typing in Java. + * + * This model describes the basic notions of typing in Java. + * It ignores primitive types and null references. Each type has + * some set of subtypes. Types are partitioned into class and + * interface types. Object is a particular class. + * + * The fact TypeHierarchy says that every type is a direct or + * indirect subtype of Object; that no type is a direct or indirect + * of itself; and every type is a subtype of at most one class. + * + * An object instance has a type (its creation type) that is a class. + * A variable may hold an instance, and has a declared type. The + * fact TypeSoundness says that all instances held by a variable + * have types that are direct or indirect subtypes of the variable's + * declared type. + * + * The function Show specifies a case in which there is a class + * distinct from Object; there is some interface; and some variable + * has a declared type that is an interface. + * + * author: Daniel Jackson, 11/13/01 + */ + +abstract sig Type {subtypes: set Type} +sig Class, Interface extends Type {} +one sig Object extends Class {} +fact TypeHierarchy { + Type in Object.*subtypes + no t: Type | t in t.^subtypes + all t: Type | lone t.~subtypes & Class + } +sig Instance {type: Class} +sig Variable {holds: lone Instance, type: Type} +fact TypeSoundness { + all v: Variable | v.holds.type in v.type.*subtypes + } +pred Show { + some Class - Object + some Interface + some Variable.type & Interface + } +run Show for 3 expect 1 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/life.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/life.als new file mode 100644 index 00000000..5ee1b159 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/life.als @@ -0,0 +1,94 @@ +module examples/toys/life + +/* + * John Conway's Game of Life + * + * For a detailed description, see: + * http://www.math.com/students/wonders/life/life.html + * + * authors: Bill Thies, Manu Sridharan + */ + +open util/ordering[State] as ord + +sig Point { + right: lone Point, + below: lone Point +} + +fact Acyclic { + all p: Point | p !in p.^(right + below) +} + +one sig Root extends Point {} + +fact InnerSquaresCommute { + all p: Point { + p.below.right = p.right.below + some p.below && some p.right => some p.below.right + } +} + +fact TopRow { + all p: Point - Root | no p.~below => # p.*below = # Root.*below +} + +fact Connected { + Root.*(right + below) = Point +} + +pred Square { + # Root.*right = # Root.*below +} + +run Square for 6 Point, 3 State expect 1 + +pred Rectangle {} + +sig State { + live : set Point +} + +fun Neighbors[p : Point] : set Point { + p.right + p.right.below + p.below + + p.below.~right + p.~right + + p.~right.~below + p.~below + + p.~below.right +} + +fun LiveNeighborsInState[p : Point, s : State] : set Point { + Neighbors[p] & s.live +} + +pred Trans[pre, post: State, p : Point] { + let preLive = LiveNeighborsInState[p,pre] | + // dead cell w/ 3 live neighbors becomes live + (p !in pre.live && # preLive = 3) => + p in post.live + else ( + // live cell w/ 2 or 3 live neighbors stays alive + (p in pre.live && (# preLive = 2 || # preLive = 3)) => + p in post.live else p !in post.live + ) +} + +fact ValidTrans { + all pre : State - ord/last | + let post = ord/next[pre] | + all p : Point | + Trans[pre,post,p] +} + +pred Show {} + +// slow +run Show for exactly 12 Point, 3 State expect 1 + +// a small but interesting example +pred interesting { + some State.live + some Point - State.live + some right + some below +} +run interesting for exactly 6 Point, 3 State expect 1 \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/life.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/life.thm new file mode 100644 index 00000000..3a015d56 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/life.thm @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/numbering.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/numbering.als new file mode 100644 index 00000000..f8c9b5f3 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/numbering.als @@ -0,0 +1,129 @@ +module examples/toys/numbering + +/* + * Alloy model of paragraph numbering + * + * This model addresses some issues that arose in the design of a text tagging tool. The + * tool receives as input a text stream in which paragraphs are tagged with style names, + * along with a style sheet that indicates how paragraphs of a given style are to be numbered. + * In practice, the style sheet includes such details as what symbols to use for numbering (eg, + * roman numericals, letters of the alphabet, etc), but these details are uninteresting. + * + * In the simplest case, the styles are organized into chains. For example, there may be a + * single chain, chapter-section-subsection, so that chapters are numbered 1, 2, 3, etc, + * sections are numbered 1.1, 1.2, 1.3, etc, and subsections are numbered 1.1.1, 1.1.2, + * etc, each paragraph being numbered according to a number associated with its own + * style, and a number for each ancestor. + * + * Some styles, however, should be numbered independently of one another, but still + * according to the same ancestors. For example, we might also have a figure style + * that is numbered, like section, according to its chapter, with figures and sections in + * some arbitrary interleaving, the numbering of one not affecting the other. + * + * So in our style hierarchy, a style can have more than one "child". A more tricky complication + * allows multiple parents. We might want to have an appendix style, for example, with a + * different numbering from the chapter style, but would want section and subsection to work + * within appendix exactly as they would work within chapter. So the first section in an + * appendix numbered A might be numbered A.1, but if placed in a chapter numbered 1, + * it would be numbered 1.1 instead. + * + * To account for this, styles are organized into replacement classes. Chapter and appendix, + * for example, are replacements of one another. When a chapter style is encountered, it + * is as if the style hierarchy contains only chapter, with children section, figure and so on; + * when appendix is encountered subsequently, chapter is replaced, and figure and section + * become children of appendix. We'll call the set of styles active in the tree at a given time + * the "context". + * + * The first part focuses on the replacement mechanism. It characterizes a well-formed + * style sheet (with the fact StyleSheet), and a well-formed state (with the fact Forest). An + * operation addStyleToContext describes how the context is altered, and includes a + * precondition requiring that, for example, a child is not encountered before its parents + * (a document can't start with subsection, eg). The assertion PreservesForest checks that the + * operation preserves the well-formedness of the state; it was analyzing this that helped + * determine an appropriate precondition and the appropriate constraints in the invariant. + * + * The second part adds the numbering of styles. Note the idiom of declaring a subsignature + * and then equating it to the supersignature, thus essentially retrofitting the new fields to the + * old signature. A second operation describes how numbers are assigned; the conjunction of the + * two operations is what happens when a style is encountered. The assertion AddNeverReduces + * checks that when a style is encountered the number associated with each style in the context is + * not decreased. The first assertion is valid; the second isn't. + * + * author: Daniel Jackson, 11/15/01 + */ + +open util/relation as rel + +sig Style { + replaces, parents: set Style + } + +fact StyleSheet { + equivalence [replaces, Style] + acyclic [parents, Style] + all x: Style { + x.replaces.parents.replaces = x.parents + all y,z: x.parents | y in z.replaces + } + } + +sig State { + context: set Style, + ancestors: Style -> Style + } + +fact DefineAncestors { + all s: State, x: Style | s.ancestors [x] = x.*parents & s.context + } + +pred Forest [s: State] { + all x: s.context | + some root: s.ancestors[x] { + no root.parents + all y: s.ancestors[x] - root | one y.parents & s.context + } + all x: Style | lone x.replaces & s.context + } + +pred AddStyleToContext [s, s': State, style: Style] { + all x: style.^parents | some x.replaces & s.context + s'.context = s.context - style.replaces + style + } + +assert PreserveForest { + all s,s': State, z: Style | + Forest[s] && AddStyleToContext [s,s',z] => Forest[s'] + } + +check PreserveForest for 4 expect 0 + +sig Value {next: Value} +sig NumberedStyle extends Style { + initial: Value + } +sig NumberedState extends State { + value: Style -> one Value + } +fact {Style = NumberedStyle} +fact {State = NumberedState} + +pred AddStyleToNumbering [s, s': State, style: Style] { + s'.value[style] = (style in s.context => s.value[style].next else style.initial) + s'.context = s.context - style.replaces + style + all x: Style - style | + s'.value[x] = (style in x.^parents => x.initial else s.value[x]) + } + +pred AddStyle [s, s': State, style: Style] { + AddStyleToContext [s,s',style] + AddStyleToNumbering [s,s',style] + } + +assert AddNeverReduces { + all s,s': State, z: Style | + Forest[s] && AddStyle [s,s',z] => + (all y: s'.context | s'.value[y] in s.value[y].*next) + } + +check AddNeverReduces for 5 expect 1 + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/railway.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/railway.als new file mode 100644 index 00000000..549bdb92 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/railway.als @@ -0,0 +1,64 @@ +module examples/toys/railway + +/* + * A simple model of a railway system. Trains sit on segments of tracks + * and segments overlap one another. It shows a that simple gate policy + * does not ensure train safety. + * + * author: Daniel Jackson + */ + +sig Seg {next, overlaps: set Seg} +fact {all s: Seg | s in s.overlaps} +fact {all s1, s2: Seg | s1 in s2.overlaps => s2 in s1.overlaps} + +sig Train {} +sig GateState {closed: set Seg} +sig TrainState {on: Train -> lone Seg, occupied: set Seg} +fact {all x: TrainState | + x.occupied = {s: Seg | some t: Train | t.(x.on) = s} + } + +pred Safe [x: TrainState] {all s: Seg | lone s.overlaps.~(x.on)} + +pred MayMove [g: GateState, x: TrainState, ts: set Train] { + no ts.(x.on) & g.closed + } + +pred TrainsMove [x, x': TrainState, ts: set Train] { + all t: ts | t.(x'.on) in t.(x.on).next + all t: Train - ts | t.(x'.on) = t.(x.on) + } + +pred GatePolicy [g: GateState, x: TrainState] { + x.occupied.overlaps.~next in g.closed + all s1, s2: Seg | some s1.next.overlaps & s2.next => lone (s1+s2) - g.closed +} + +assert PolicyWorks { + all x, x': TrainState, g: GateState, ts: set Train | + {MayMove [g, x, ts] + TrainsMove [x, x', ts] + Safe [x] + GatePolicy [g, x] + } => Safe [x'] + } + +-- has counterexample in scope of 4 +check PolicyWorks for 2 Train, 1 GateState, 2 TrainState, 4 Seg expect 1 + +pred TrainsMoveLegal [x, x': TrainState, g: GateState, ts: set Train] { + TrainsMove [x, x', ts] + MayMove [g, x, ts] + GatePolicy [g, x] + } +run TrainsMoveLegal for 3 expect 1 + + + +// DEFINED VARIABLES +// Defined variables are uncalled, no-argument functions. +// They are helpful for getting good visualization. +fun contains [] : TrainState -> Seg -> Train { + {state: TrainState, seg: Seg, train: Train | seg = train.(state.on)} +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/railway.thm b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/railway.thm new file mode 100644 index 00000000..40baef57 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/railway.thm @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/trivial.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/trivial.als new file mode 100644 index 00000000..71f19d3d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/toys/trivial.als @@ -0,0 +1,8 @@ +//a trivial model whose command has no solution +module trivial + +sig S {} + +fact { 1=2 } + +run {some S} expect 0 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/examples/tutorial/farmer.als b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/tutorial/farmer.als new file mode 100644 index 00000000..94ea0d5d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/examples/tutorial/farmer.als @@ -0,0 +1,92 @@ +module examples/tutorial/farmer + +/* + * The classic river crossing puzzle. A farmer is carrying a fox, a + * chicken, and a sack of grain. He must cross a river using a boat + * that can only hold the farmer and at most one other thing. If the + * farmer leaves the fox alone with the chicken, the fox will eat the + * chicken; and if he leaves the chicken alone with the grain, the + * chicken will eat the grain. How can the farmer bring everything + * to the far side of the river intact? + * + * authors: Greg Dennis, Rob Seater + * + * Acknowledgements to Derek Rayside and his students for finding and + * fixing a bug in the "crossRiver" predicate. + */ + +open util/ordering[State] as ord + +/** + * The farmer and all his possessions will be represented as Objects. + * Some objects eat other objects when the Farmer's not around. + */ +abstract sig Object { eats: set Object } +one sig Farmer, Fox, Chicken, Grain extends Object {} + +/** + * Define what eats what when the Farmer' not around. + * Fox eats the chicken and the chicken eats the grain. + */ +fact eating { eats = Fox->Chicken + Chicken->Grain } + +/** + * The near and far relations contain the objects held on each + * side of the river in a given state, respectively. + */ +sig State { + near: set Object, + far: set Object +} + +/** + * In the initial state, all objects are on the near side. + */ +fact initialState { + let s0 = ord/first | + s0.near = Object && no s0.far +} + +/** + * Constrains at most one item to move from 'from' to 'to'. + * Also constrains which objects get eaten. + */ +pred crossRiver [from, from', to, to': set Object] { + // either the Farmer takes no items + (from' = from - Farmer - from'.eats and + to' = to + Farmer) or + // or the Farmer takes one item + (one x : from - Farmer | { + from' = from - Farmer - x - from'.eats + to' = to + Farmer + x }) +} + +/** + * crossRiver transitions between states + */ +fact stateTransition { + all s: State, s': ord/next[s] { + Farmer in s.near => + crossRiver[s.near, s'.near, s.far, s'.far] else + crossRiver[s.far, s'.far, s.near, s'.near] + } +} + +/** + * the farmer moves everything to the far side of the river. + */ +pred solvePuzzle { + ord/last.far = Object +} + +run solvePuzzle for 8 State expect 1 + +/** + * no Object can be in two places at once + * this is implied by both definitions of crossRiver + */ +assert NoQuantumObjects { + no s : State | some x : Object | x in s.near and x in s.far +} + +check NoQuantumObjects for 8 State expect 0 \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/util/boolean.als b/Source/eu.modelwriter.alloyanalyzer/src/models/util/boolean.als new file mode 100644 index 00000000..61d8744e --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/util/boolean.als @@ -0,0 +1,43 @@ +module util/boolean + +/* + * Creates a Bool type with two singleton subtypes: True + * and False. Provides common boolean operations. + * + * author: Greg Dennis + */ + +abstract sig Bool {} +one sig True, False extends Bool {} + +pred isTrue[b: Bool] { b in True } + +pred isFalse[b: Bool] { b in False } + +fun Not[b: Bool] : Bool { + Bool - b +} + +fun And[b1, b2: Bool] : Bool { + subset_[b1 + b2, True] +} + +fun Or[b1, b2: Bool] : Bool { + subset_[True, b1 + b2] +} + +fun Xor[b1, b2: Bool] : Bool { + subset_[Bool, b1 + b2] +} + +fun Nand[b1, b2: Bool] : Bool { + subset_[False, b1 + b2] +} + +fun Nor[b1, b2: Bool] : Bool { + subset_[b1 + b2, False] +} + +fun subset_[s1, s2: set Bool] : Bool { + (s1 in s2) => True else False +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/util/graph.als b/Source/eu.modelwriter.alloyanalyzer/src/models/util/graph.als new file mode 100644 index 00000000..b722ac13 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/util/graph.als @@ -0,0 +1,78 @@ +module util/graph[node] + +/* + * Utilities for some common operations and contraints + * on graphs. + * + * author: Greg Dennis + */ + +open util/relation as rel + +/** graph in undirected */ +pred undirected [r: node->node] { + symmetric[r] +} + +/** graph has no self-loops */ +pred noSelfLoops[r: node->node] { + irreflexive[r] +} + +/** graph is weakly connected */ +pred weaklyConnected[r: node->node] { + all n1, n2: node | n1 in n2.*(r + ~r) // Changed from ^ to * to permit singleton +} + +/** graph is strongly connected */ +pred stronglyConnected[r: node->node] { + all n1, n2: node | n1 in n2.*r // Changed from ^ to * to permit singleton +} + +/** graph is rooted at root */ +pred rootedAt[r: node->node, root: node] { + node in root.*r +} + +/** graph is a ring */ +pred ring [r: node->node] { + all n: node | one n.r && rootedAt[r, n] +} + +/** graph is a dag */ +pred dag [r: node->node] { + acyclic[r, node] +} + +/** graph is a forest */ +pred forest [r: node->node] { + dag[r] + all n: node | lone r.n +} + +/** graph is a tree */ +pred tree [r: node->node] { + forest[r] + lone root: node | no r.root +} + +/** graph is a tree rooted at root */ +pred treeRootedAt[r: node->node, root: node] { + forest[r] + rootedAt[r, root] +} + +/** returns the roots of the graph */ +fun roots [r: node->node] : set node { + node - node.^r +} + +/** returns the leaves of the grpah */ +fun leaves [r: node->node] : set node { + node - node.^~r +} + +/** returns the inner nodes (non-leaves) of the graph */ +fun innerNodes [r: node->node] : set node { + node - leaves[r] +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/util/integer.als b/Source/eu.modelwriter.alloyanalyzer/src/models/util/integer.als new file mode 100644 index 00000000..488c25e2 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/util/integer.als @@ -0,0 +1,112 @@ +module util/integer + +/* + * A collection of utility functions for using Integers in Alloy. + * Note that integer overflows are silently truncated to the current bitwidth + * using the 2's complement arithmetic, unless the "forbid overfows" option is + * turned on, in which case only models that don't have any overflows are + * analyzed. + */ + +fun add [n1, n2: Int] : Int { this/plus[n1, n2] } +fun plus [n1, n2: Int] : Int { n1 fun/add n2 } + +fun sub [n1, n2: Int] : Int { this/minus[n1, n2] } +fun minus [n1, n2: Int] : Int { n1 fun/sub n2 } + +fun mul [n1, n2: Int] : Int { n1 fun/mul n2 } + +/** + * Performs the division with "round to zero" semantics, except the following 3 cases + * 1) if a is 0, then it returns 0 + * 2) else if b is 0, then it returns 1 if a is negative and -1 if a is positive + * 3) else if a is the smallest negative integer, and b is -1, then it returns a + */ +fun div [n1, n2: Int] : Int { n1 fun/div n2 } + +/** answer is defined to be the unique integer that satisfies "a = ((a/b)*b) + remainder" */ +fun rem [n1, n2: Int] : Int { n1 fun/rem n2 } + +/** negate */ +fun negate [n: Int] : Int { 0 fun/sub n } + +/** equal to */ +pred eq [n1, n2: Int] { int[n1] = int[n2] } + +/** greater than */ +pred gt [n1, n2: Int] { n1 > n2 } + +/** less then */ +pred lt [n1, n2: Int] { n1 < n2 } + +/** greater than or equal */ +pred gte [n1, n2: Int] { n1 >= n2 } + +/** less than or equal */ +pred lte [n1, n2: Int] { n1 <= n2 } + +/** integer is zero */ +pred zero [n: Int] { n = 0 } + +/** positive */ +pred pos [n: Int] { n > 0 } + +/** negative */ +pred neg [n: Int] { n < 0 } + +/** non-positive */ +pred nonpos [n: Int] { n <= 0 } + +/** non-negative */ +pred nonneg [n: Int] { n >= 0 } + +/** signum (aka sign or sgn) */ +fun signum [n: Int] : Int { n<0 => (0 fun/sub 1) else (n>0 => 1 else 0) } + +/** + * returns the ith element (zero-based) from the set s + * in the ordering of 'next', which is a linear ordering + * relation like that provided by util/ordering + */ +fun int2elem[i: Int, next: univ->univ, s: set univ] : lone s { + {e: s | #^next.e = int i } +} + +/** + * returns the index of the element (zero-based) in the + * ordering of next, which is a linear ordering relation + * like that provided by util/ordering + */ +fun elem2int[e: univ, next: univ->univ] : lone Int { + Int[#^next.e] +} + +/** returns the largest integer in the current bitwidth */ +fun max:one Int { fun/max } + +/** returns the smallest integer in the current bitwidth */ +fun min:one Int { fun/min } + +/** maps each integer (except max) to the integer after it */ +fun next:Int->Int { fun/next } + +/** maps each integer (except min) to the integer before it */ +fun prev:Int->Int { ~next } + +/** given a set of integers, return the largest element */ +fun max [es: set Int]: lone Int { es - es.^prev } + +/** given a set of integers, return the smallest element */ +fun min [es: set Int]: lone Int { es - es.^next } + +/** given an integer, return all integers prior to it */ +fun prevs [e: Int]: set Int { e.^prev } + +/** given an integer, return all integers following it */ +fun nexts [e: Int]: set Int { e.^next } + +/** returns the larger of the two integers */ +fun larger [e1, e2: Int]: Int { let a=int[e1], b=int[e2] | (a b else a) } + +/** returns the smaller of the two integers */ +fun smaller [e1, e2: Int]: Int { let a=int[e1], b=int[e2] | (a a else b) } diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/util/natural.als b/Source/eu.modelwriter.alloyanalyzer/src/models/util/natural.als new file mode 100644 index 00000000..5d9f6246 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/util/natural.als @@ -0,0 +1,78 @@ +module util/natural + +/* + * Utility function and predicates for using the set of + * nonnegative integers (0, 1, 2, . . .). The number of + * naturals present in an analysis will be equal to the + * scope on Natural. Specifically, if the scope on Natural + * is N, then the naturals 0 through N-1 will be present. + * + * Note that the functions that return Naturals, such as + * 'add' and 'div', may return an empty set if no such + * Natural exists for that integer value. + * + * To write an Alloy model that makes use of negative + * integers, use the util/integer module instead. + * + * @author Greg Dennis + */ + +private open util/ordering[Natural] as ord +private open util/integer as integer + +sig Natural {} + +/** the integer zero */ +one sig Zero in Natural {} + +/** the integer one will be the empty set if the scope on Natural is less than two */ +lone sig One in Natural {} + +fact { + first in Zero + next[first] in One +} + +/** returns n + 1 */ +fun inc [n: Natural] : lone Natural { ord/next[n] } + +/** returns n - 1 */ +fun dec [n: Natural] : lone Natural { ord/prev[n] } + +/** returns n1 + n2 */ +fun add [n1, n2: Natural] : lone Natural { + {n: Natural | #ord/prevs[n] = #ord/prevs[n1] + #ord/prevs[n2]} +} + +/** returns n1 - n2 */ +fun sub [n1, n2: Natural] : lone Natural { + {n: Natural | #ord/prevs[n1] = #ord/prevs[n2] + #ord/prevs[n]} +} + +/** returns n1 * n2 */ +fun mul [n1, n2: Natural] : lone Natural { + {n: Natural | #ord/prevs[n] = #(ord/prevs[n1]->ord/prevs[n2])} +} + +/** returns n1 / n2 */ +fun div [n1, n2: Natural] : lone Natural { + {n: Natural | #ord/prevs[n1] = #(ord/prevs[n2]->ord/prevs[n])} +} + +/** returns true iff n1 is greater than n2 */ +pred gt [n1, n2: Natural] { ord/gt [n1, n2] } + +/** returns true iff n1 is less than n2 */ +pred lt [n1, n2: Natural] { ord/lt [n1, n2] } + +/** returns true iff n1 is greater than or equal to n2 */ +pred gte [n1, n2: Natural] { ord/gte[n1, n2] } + +/** returns true iff n1 is less than or equal to n2 */ +pred lte [n1, n2: Natural] { ord/lte[n1, n2] } + +/** returns the maximum integer in ns */ +fun max [ns: set Natural] : lone Natural { ord/max[ns] } + +/** returns the minimum integer in ns */ +fun min [ns: set Natural] : lone Natural { ord/min[ns] } diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/util/ordering.als b/Source/eu.modelwriter.alloyanalyzer/src/models/util/ordering.als new file mode 100644 index 00000000..e26d7bd0 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/util/ordering.als @@ -0,0 +1,106 @@ +module util/ordering[exactly elem] + +/* + * Creates a single linear ordering over the atoms in elem. It also constrains all + * the atoms to exist that are permitted by the scope on elem. That is, if the scope + * on a signature S is 5, opening util/ordering[S] will force S to have 5 elements + * and create a linear ordering over those five elements. The predicates and + * functions below provide access to properties of the linear ordering, such as + * which element is first in the ordering, or whether a given element precedes + * another. You cannotcreate multiple linear orderings over the same signature with + * this model. If you that functionality, try using the util/sequence module instead. + * + * Technical comment: + * An important constraint: elem must contain all atoms permitted by the scope. + * This is to let the analyzer optimize the analysis by setting all fields of each + * instantiation of Ord to predefined values: e.g. by setting 'last' to the highest + * atom of elem and by setting 'next' to {,,...}, where n is + * the scope of elem. Without this constraint, it might not be true that Ord.last is + * a subset of elem, and that the domain and range of Ord.next lie inside elem. + * + * author: Ilya Shlyakhter + * revisions: Daniel jackson + */ + +private one sig Ord { + First: set elem, + Next: elem -> elem +} { + pred/totalOrder[elem,First,Next] +} + +/** first */ +fun first: one elem { Ord.First } + +/** last */ +fun last: one elem { elem - (next.elem) } + +/** return a mapping from each element to its predecessor */ +fun prev : elem->elem { ~(Ord.Next) } + +/** return a mapping from each element to its successor */ +fun next : elem->elem { Ord.Next } + +/** return elements prior to e in the ordering */ +fun prevs [e: elem]: set elem { e.^(~(Ord.Next)) } + +/** return elements following e in the ordering */ +fun nexts [e: elem]: set elem { e.^(Ord.Next) } + +/** e1 is less than e2 in the ordering */ +pred lt [e1, e2: elem] { e1 in prevs[e2] } + +/** e1 is greater than e2 in the ordering */ +pred gt [e1, e2: elem] { e1 in nexts[e2] } + +/** e1 is less than or equal to e2 in the ordering */ +pred lte [e1, e2: elem] { e1=e2 || lt [e1,e2] } + +/** e1 is greater than or equal to e2 in the ordering */ +pred gte [e1, e2: elem] { e1=e2 || gt [e1,e2] } + +/** returns the larger of the two elements in the ordering */ +fun larger [e1, e2: elem]: elem { lt[e1,e2] => e2 else e1 } + +/** returns the smaller of the two elements in the ordering */ +fun smaller [e1, e2: elem]: elem { lt[e1,e2] => e1 else e2 } + +/** + * returns the largest element in es + * or the empty set if es is empty + */ +fun max [es: set elem]: lone elem { es - es.^(~(Ord.Next)) } + +/** + * returns the smallest element in es + * or the empty set if es is empty + */ +fun min [es: set elem]: lone elem { es - es.^(Ord.Next) } + +assert correct { + let mynext = Ord.Next | + let myprev = ~mynext | { + ( all b:elem | (lone b.next) && (lone b.prev) && (b !in b.^mynext) ) + ( (no first.prev) && (no last.next) ) + ( all b:elem | (b!=first && b!=last) => (one b.prev && one b.next) ) + ( !one elem => (one first && one last && first!=last && one first.next && one last.prev) ) + ( one elem => (first=elem && last=elem && no myprev && no mynext) ) + ( myprev=~mynext ) + ( elem = first.*mynext ) + (all disj a,b:elem | a in b.^mynext or a in b.^myprev) + (no disj a,b:elem | a in b.^mynext and a in b.^myprev) + (all disj a,b,c:elem | (b in a.^mynext and c in b.^mynext) =>(c in a.^mynext)) + (all disj a,b,c:elem | (b in a.^myprev and c in b.^myprev) =>(c in a.^myprev)) + } +} +run {} for exactly 0 elem expect 0 +run {} for exactly 1 elem expect 1 +run {} for exactly 2 elem expect 1 +run {} for exactly 3 elem expect 1 +run {} for exactly 4 elem expect 1 +check correct for exactly 0 elem +check correct for exactly 1 elem +check correct for exactly 2 elem +check correct for exactly 3 elem +check correct for exactly 4 elem +check correct for exactly 5 elem diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/util/relation.als b/Source/eu.modelwriter.alloyanalyzer/src/models/util/relation.als new file mode 100644 index 00000000..d648a77c --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/util/relation.als @@ -0,0 +1,101 @@ +module util/relation + +/* + * Utilities for some common operations and constraints + * on binary relations. The keyword 'univ' represents the + * top-level type, which all other types implicitly extend. + * Therefore, all the functions and predicates in this model + * may be applied to binary relations of any type. + * + * author: Greg Dennis + */ + +/** returns the domain of a binary relation */ +fun dom [r: univ->univ] : set (r.univ) { r.univ } + +/** returns the range of a binary relation */ +fun ran [r: univ->univ] : set (univ.r) { univ.r } + +/** r is total over the domain s */ +pred total [r: univ->univ, s: set univ] { + all x: s | some x.r +} + +/** r is a partial function over the domain s */ +pred functional [r: univ->univ, s: set univ] { + all x: s | lone x.r +} + +/** r is a total function over the domain s */ +pred function [r: univ->univ, s: set univ] { + all x: s | one x.r +} + +/** r is surjective over the codomain s */ +pred surjective [r: univ->univ, s: set univ] { + all x: s | some r.x +} + +/** r is injective */ +pred injective [r: univ->univ, s: set univ] { + all x: s | lone r.x +} + +/** r is bijective over the codomain s */ +pred bijective[r: univ->univ, s: set univ] { + all x: s | one r.x +} + +/** r is a bijection over the domain d and the codomain c */ +pred bijection[r: univ->univ, d, c: set univ] { + function[r, d] && bijective[r, c] +} + +/** r is reflexive over the set s */ +pred reflexive [r: univ -> univ, s: set univ] {s<:iden in r} + +/** r is irreflexive */ +pred irreflexive [r: univ -> univ] {no iden & r} + +/** r is symmetric */ +pred symmetric [r: univ -> univ] {~r in r} + +/** r is anti-symmetric */ +pred antisymmetric [r: univ -> univ] {~r & r in iden} + +/** r is transitive */ +pred transitive [r: univ -> univ] {r.r in r} + +/** r is acyclic over the set s */ +pred acyclic[r: univ->univ, s: set univ] { + all x: s | x !in x.^r +} + +/** r is complete over the set s */ +pred complete[r: univ->univ, s: univ] { + all x,y:s | (x!=y => x->y in (r + ~r)) +} + +/** r is a preorder (or a quasi-order) over the set s */ +pred preorder [r: univ -> univ, s: set univ] { + reflexive[r, s] + transitive[r] +} + +/** r is an equivalence relation over the set s */ +pred equivalence [r: univ->univ, s: set univ] { + preorder[r, s] + symmetric[r] +} + +/** r is a partial order over the set s */ +pred partialOrder [r: univ -> univ, s: set univ] { + preorder[r, s] + antisymmetric[r] +} + +/** r is a total order over the set s */ +pred totalOrder [r: univ -> univ, s: set univ] { + partialOrder[r, s] + complete[r, s] +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/util/seqrel.als b/Source/eu.modelwriter.alloyanalyzer/src/models/util/seqrel.als new file mode 100644 index 00000000..1fe3802d --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/util/seqrel.als @@ -0,0 +1,108 @@ +module util/seqrel[elem] + +/* + * A sequence utility for modeling sequences as just a + * relation as opposed to reifying them into sequence + * atoms like the util/sequence module does. + * + * @author Greg Dennis + */ + +open util/integer +open util/ordering[SeqIdx] as ord + +sig SeqIdx {} + +/** sequence covers a prefix of SeqIdx */ +pred isSeq[s: SeqIdx -> elem] { + s in SeqIdx -> lone elem + s.inds - ord/next[s.inds] in ord/first +} + +/** returns all the elements in this sequence */ +fun elems [s: SeqIdx -> elem]: set elem { SeqIdx.s } + +/** returns the first element in the sequence */ +fun first [s: SeqIdx -> elem]: lone elem { s[ord/first] } + +/** returns the last element in the sequence */ +fun last [s: SeqIdx -> elem]: lone elem { s[lastIdx[s]] } + +/** returns the cdr of the sequence */ +fun rest [s: SeqIdx -> elem] : SeqIdx -> elem { + (ord/next).s +} + +/** returns all but the last element of the sequence */ +fun butlast [s: SeqIdx -> elem] : SeqIdx -> elem { + (SeqIdx - lastIdx[s]) <: s +} + +/** true if the sequence is empty */ +pred isEmpty [s: SeqIdx -> elem] { no s } + +/** true if this sequence has duplicates */ +pred hasDups [s: SeqIdx -> elem] { # elems[s] < # inds[s] } + +/** returns all the indices occupied by this sequence */ +fun inds [s: SeqIdx -> elem]: set SeqIdx { s.elem } + +/** returns last index occupied by this sequence */ +fun lastIdx [s: SeqIdx -> elem]: lone SeqIdx { ord/max[inds[s]] } + +/** + * returns the index after the last index + * if this sequence is empty, returns the first index, + * if this sequence is full, returns empty set + */ +fun afterLastIdx [s: SeqIdx -> elem] : lone SeqIdx { + ord/min[SeqIdx - inds[s]] +} + +/** returns first index at which given element appears or the empty set if it doesn't */ +fun idxOf [s: SeqIdx -> elem, e: elem] : lone SeqIdx { ord/min[indsOf[s, e]] } + +/** returns last index at which given element appears or the empty set if it doesn't */ +fun lastIdxOf [s: SeqIdx -> elem, e: elem] : lone SeqIdx { ord/max[indsOf[s, e]] } + +/** returns set of indices at which given element appears or the empty set if it doesn't */ +fun indsOf [s: SeqIdx -> elem, e: elem] : set SeqIdx { s.e } + +/** + * return the result of appending e to the end of s + * just returns s if s exhausted SeqIdx + */ +fun add [s: SeqIdx -> elem, e: elem] : SeqIdx -> elem { + setAt[s, afterLastIdx[s], e] +} + +/** returns the result of setting the value at index i in sequence to e */ +fun setAt [s: SeqIdx -> elem, i: SeqIdx, e: elem] : SeqIdx -> elem { + s ++ i -> e +} + +/** returns the result of inserting value e at index i */ +fun insert [s: SeqIdx -> elem, i: SeqIdx, e: elem] : SeqIdx -> elem { + (ord/prevs[i] <: s) + (i->e) + (~(ord/next)).((ord/nexts[i] + i) <: s) +} + +/** returns the result of deleting the value at index i */ +fun delete[s: SeqIdx -> elem, i: SeqIdx] : SeqIdx -> elem { + (ord/prevs[i] <: s) + (ord/next).(ord/nexts[i] <: s) +} + +/** appended is the result of appending s2 to s1 */ +fun append [s1, s2: SeqIdx -> elem] : SeqIdx -> elem { + let shift = {i', i: SeqIdx | #ord/prevs[i'] = add[#ord/prevs[i], add[#ord/prevs[lastIdx[s1]], 1]] } | + s1 + shift.s2 +} + +/** returns the subsequence of s between from and to, inclusive */ +fun subseq [s: SeqIdx -> elem, from, to: SeqIdx] : SeqIdx -> elem { + let shift = {i', i: SeqIdx | #ord/prevs[i'] = sub[#ord/prevs[i], #ord/prevs[from]] } | + shift.((SeqIdx - ord/nexts[to]) <: s) +} + +fun firstIdx: SeqIdx { ord/first } + +fun finalIdx: SeqIdx { ord/last } \ No newline at end of file diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/util/sequence.als b/Source/eu.modelwriter.alloyanalyzer/src/models/util/sequence.als new file mode 100644 index 00000000..524e3cf7 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/util/sequence.als @@ -0,0 +1,166 @@ +module util/sequence[elem] + +/* + * Creates sequences (or lists) of elements. The ordered signature SeqIdx + * represents the indexes at which elements can be located, and a sequence + * is modeled as a mapping from indexes to elements. Empty sequences are + * allowed, and a sequence may have a single element appear multiple times. + * Maximum length of a sequence is determined by the scope of SeqIdx. + * + * Sequences always cover an initial segment of SeqIdx. That is, every + * sequence (except the empty sequence) begins at the first SeqIdx and does + * not have gaps in indexes that it covers. In other words, if a sequence has + * its last element at index i, then the sequence has elements at all the + * indexes that precede i. + * + * Oftentimes, a model will need to require that all sequences that could + * exist, do exist. Calling the allExist predicate will ensure that that there is + * a Seq atom for each possible sequences of elements with length less than + * or equal to the scope of SeqIdx. + * + * The functions and predicates at the bottom of this module provide all + * functionality of util/ordering on SeqIdx. + * + * revisions: Greg Dennis + */ + +open util/ordering[SeqIdx] as ord + +sig SeqIdx {} + +sig Seq { + seqElems: SeqIdx -> lone elem +} +{ + // Ensure that elems covers only an initial segment of SeqIdx, + // equal to the length of the signature + all i: SeqIdx - ord/first | some i.seqElems => some ord/prev[i].seqElems +} + +/** no two sequences are identical */ +fact canonicalizeSeqs { + no s1, s2: Seq | s1!=s2 && s1.seqElems=s2.seqElems +} + +/** invoke if you want none of the sequences to have duplicates */ +pred noDuplicates { + all s: Seq | !s.hasDups +} + +/** invoke if you want all sequences within scope to exist */ +pred allExist { + (some s: Seq | s.isEmpty) && + (all s: Seq | SeqIdx !in s.inds => (all e: elem | some s': Seq | s.add[e, s'])) +} + +/** invoke if you want all sequences within scope with no duplicates */ +pred allExistNoDuplicates { + some s: Seq | s.isEmpty + all s: Seq { + !s.hasDups + SeqIdx !in s.inds => (all e: elem - s.elems | some s': Seq | s.add[e, s']) + } +} + +/** returns element at the given index */ +fun at [s: Seq, i: SeqIdx]: lone elem { i.(s.seqElems) } + +/** returns all the elements in this sequence */ +fun elems [s: Seq]: set elem { SeqIdx.(s.seqElems) } + +/** returns the first element in the sequence */ +fun first [s:Seq]: lone elem { s.at[ord/first] } + +/** returns the last element in the sequence */ +fun last [s:Seq]: lone elem { s.at[s.lastIdx] } + +/** + * true if the argument is the "cdr" of this sequence + * false if this sequence is empty + */ +pred rest [s, r: Seq] { + !s.isEmpty + all i: SeqIdx | r.at[i] = s.at[ord/next[i]] +} + +/** true if the sequence is empty */ +pred isEmpty [s:Seq] { no s.elems } + +/** true if this sequence has duplicates */ +pred hasDups [s:Seq] { # elems[s] < # inds[s] } + +/** returns all the indices occupied by this sequence */ +fun inds [s:Seq] : set SeqIdx { elem.~(s.seqElems) } + +/** returns last index occupied by this sequence */ +fun lastIdx [s:Seq] : lone SeqIdx { ord/max[s.inds] } + +/** + * returns the index after the last index + * if this sequence is empty, returns the first index, + * if this sequence is full, returns empty set + */ +fun afterLastIdx [s:Seq] : lone SeqIdx { + ord/min[SeqIdx - s.inds] +} + +/** returns first index at which given element appears or the empty set if it doesn't */ +fun idxOf [s: Seq, e: elem] : lone SeqIdx { ord/min[s.indsOf[e]] } + +/** returns last index at which given element appears or the empty set if it doesn't */ +fun lastIdxOf [s: Seq, e: elem] : lone SeqIdx { ord/max[s.indsOf[e]] } + +/** returns set of indices at which given element appears or the empty set if it doesn't */ +fun indsOf [s: Seq, e: elem] : set SeqIdx { (s.seqElems).e } + +/** true if this starts with prefix */ +pred startsWith [s, prefix: Seq] { + all i: prefix.inds | s.at[i] = prefix.at[i] +} + +/** added is the result of appending e to the end of s */ +pred add [s: Seq, e: elem, added: Seq] { + added.startsWith[s] + added.seqElems[s.afterLastIdx] = e + #added.inds = #s.inds.add[1] +} + +/** setted is the result of setting value at index i to e */ +pred setAt [s: Seq, idx: SeqIdx, e: elem, setted: Seq] { + setted.seqElems = s.seqElems ++ idx->e +} + +/** inserts is the result of inserting value e at index i */ +pred insert [s: Seq, idx: SeqIdx, e: elem, inserted: Seq] { + inserted.at[idx] = e + all i: ord/prevs[idx] | inserted.at[i] = s.at[i] + all i: ord/nexts[idx] | inserted.at[i] = s.at[ord/prev[i]] + #inserted.inds = #s.inds.add[1] +} + +/** copies source into dest starting at destStart */ +pred copy [source, dest: Seq, destStart: SeqIdx] { + all sourceIdx : source.inds | some destIdx: SeqIdx { + ord/gte[destIdx, destStart] + dest.at[destIdx] = source.at[sourceIdx] + #ord/prevs[sourceIdx] = #(ord/prevs[destIdx] - ord/prevs[destStart]) + } +} + +/** appended is the result of appending s2 to s1 */ +pred append [s1, s2, appended: Seq] { + appended.startsWith[s1] + copy[s2, appended, s1.afterLastIdx] + #appended.inds = #s1.inds.add[#s2.inds] +} + +/** sub is the subsequence of s between from and to, inclusive */ +pred subseq [s, sub: Seq, from, to: SeqIdx] { + ord/lte[from, to] + copy[sub, s, from] + #sub.inds = #(to + ord/prevs[to] - ord/prevs[from]) +} + +fun firstIdx: SeqIdx { ord/first } + +fun finalIdx: SeqIdx { ord/last } diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/util/sequniv.als b/Source/eu.modelwriter.alloyanalyzer/src/models/util/sequniv.als new file mode 100644 index 00000000..efa8bf42 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/util/sequniv.als @@ -0,0 +1,137 @@ +module util/sequniv + +open util/integer as ui + +/* + * NOTE: Do not include this module manually. + * Instead, use the "seq" keyword which will automatically + * import this module with the correct additional constraints as needed. + */ + +/* + * A sequence utility for modeling sequences as just a + * relation as opposed to reifying them into sequence + * atoms like the util/sequence module does. + * + * Precondition: each input sequence must range over a prefix + * of seq/Int. + * + * Postcondition: we guarantee the returned sequence + * also ranges over a prefix of seq/Int. + * + * @author Greg Dennis + */ + +/** sequence covers a prefix of seq/Int */ +pred isSeq[s: Int -> univ] { + s in seq/Int -> lone univ + s.inds - ui/next[s.inds] in 0 +} + +/** returns all the elements in this sequence */ +fun elems [s: Int -> univ]: set (Int.s) { seq/Int . s } + +/** + * returns the first element in the sequence + * (Returns the empty set if the sequence is empty) + */ +fun first [s: Int -> univ]: lone (Int.s) { s[0] } + +/** + * returns the last element in the sequence + * (Returns the empty set if the sequence is empty) + */ +fun last [s: Int -> univ]: lone (Int.s) { s[lastIdx[s]] } + +/** + * returns the cdr of the sequence + * (Returns the empty sequence if the sequence has 1 or fewer element) + */ +fun rest [s: Int -> univ] : s { seq/Int <: ((ui/next).s) } + +/** returns all but the last element of the sequence */ +fun butlast [s: Int -> univ] : s { + (seq/Int - lastIdx[s]) <: s +} + +/** true if the sequence is empty */ +pred isEmpty [s: Int -> univ] { no s } + +/** true if this sequence has duplicates */ +pred hasDups [s: Int -> univ] { # elems[s] < # inds[s] } + +/** returns all the indices occupied by this sequence */ +fun inds [s: Int -> univ]: set Int { s.univ } + +/** + * returns last index occupied by this sequence + * (Returns the empty set if the sequence is empty) + */ +fun lastIdx [s: Int -> univ]: lone Int { ui/max[inds[s]] } + +/** + * returns the index after the last index + * if this sequence is empty, returns 0 + * if this sequence is full, returns empty set + */ +fun afterLastIdx [s: Int -> univ] : lone Int { ui/min[seq/Int - inds[s]] } + +/** returns first index at which given element appears or the empty set if it doesn't */ +fun idxOf [s: Int -> univ, e: univ] : lone Int { ui/min[indsOf[s, e]] } + +/** returns last index at which given element appears or the empty set if it doesn't */ +fun lastIdxOf [s: Int -> univ, e: univ] : lone Int { ui/max[indsOf[s, e]] } + +/** returns set of indices at which given element appears or the empty set if it doesn't */ +fun indsOf [s: Int -> univ, e: univ] : set Int { s.e } + +/** + * return the result of appending e to the end of s + * (returns s if s exhausted seq/Int) + */ +fun add [s: Int -> univ, e: univ] : s + (seq/Int->e) { + setAt[s, afterLastIdx[s], e] +} + +/** + * returns the result of setting the value at index i in sequence to e + * Precondition: 0 <= i < #s + */ +fun setAt [s: Int -> univ, i: Int, e: univ] : s + (seq/Int->e) { + s ++ i -> e +} + +/** + * returns the result of inserting value e at index i + * (if sequence was full, the original last element will be removed first) + * Precondition: 0 <= i <= #s + */ +fun insert [s: Int -> univ, i: Int, e: univ] : s + (seq/Int->e) { + seq/Int <: ((ui/prevs[i] <: s) + (i->e) + ui/prev.((ui/nexts[i] + i) <: s)) +} + +/** + * returns the result of deleting the value at index i + * Precondition: 0 <= i < #s + */ +fun delete[s: Int -> univ, i: Int] : s { + (ui/prevs[i] <: s) + (ui/next).(ui/nexts[i] <: s) +} + +/** + * appended is the result of appending s2 to s1 + * (If the resulting sequence is too long, it will be truncated) + */ +fun append [s1, s2: Int -> univ] : s1+s2 { + let shift = {i', i: seq/Int | int[i'] = ui/add[int[i], ui/add[int[lastIdx[s1]], 1]] } | + no s1 => s2 else (s1 + shift.s2) +} + +/** + * returns the subsequence of s between from and to, inclusive + * Precondition: 0 <= from <= to < #s + */ +fun subseq [s: Int -> univ, from, to: Int] : s { + let shift = {i', i: seq/Int | int[i'] = ui/sub[int[i], int[from]] } | + shift.((seq/Int - ui/nexts[to]) <: s) +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/util/ternary.als b/Source/eu.modelwriter.alloyanalyzer/src/models/util/ternary.als new file mode 100644 index 00000000..6dbc0881 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/util/ternary.als @@ -0,0 +1,50 @@ +module util/ternary + +/* + * Utilities for some common operations and constraints + * on ternary relations. The keyword 'univ' represents the + * top-level type, which all other types implicitly extend. + * Therefore, all the functions and predicates in this model + * may be applied to ternary relations of any type. + * + * author: Greg Dennis + */ + +/** returns the domain of a ternary relation */ +fun dom [r: univ->univ->univ] : set ((r.univ).univ) { (r.univ).univ } + +/** returns the range of a ternary relation */ +fun ran [r: univ->univ->univ] : set (univ.(univ.r)) { univ.(univ.r) } + +/** returns the "middle range" of a ternary relation */ +fun mid [r: univ->univ->univ] : set (univ.(r.univ)) { univ.(r.univ) } + +/** returns the first two columns of a ternary relation */ +fun select12 [r: univ->univ->univ] : r.univ { + r.univ +} + +/** returns the first and last columns of a ternary relation */ +fun select13 [r: univ->univ->univ] : ((r.univ).univ) -> (univ.(univ.r)) { + {x: (r.univ).univ, z: univ.(univ.r) | some (x.r).z} +} + +/** returns the last two columns of a ternary relation */ +fun select23 [r: univ->univ->univ] : univ.r { + univ.r +} + +/** flips the first two columns of a ternary relation */ +fun flip12 [r: univ->univ->univ] : (univ.(r.univ))->((r.univ).univ)->(univ.(univ.r)) { + {x: univ.(r.univ), y: (r.univ).univ, z: univ.(univ.r) | y->x->z in r} +} + +/** flips the first and last columns of a ternary relation */ +fun flip13 [r: univ->univ->univ] : (univ.(univ.r))->(univ.(r.univ))->((r.univ).univ) { + {x: univ.(univ.r), y: univ.(r.univ), z: (r.univ).univ | z->y->x in r} +} + +/** flips the last two columns of a ternary relation */ +fun flip23 [r: univ->univ->univ] : ((r.univ).univ)->(univ.(univ.r))->(univ.(r.univ)) { + {x: (r.univ).univ, y: univ.(univ.r), z: univ.(r.univ) | x->z->y in r} +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/models/util/time.als b/Source/eu.modelwriter.alloyanalyzer/src/models/util/time.als new file mode 100644 index 00000000..b6f9d8ca --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/models/util/time.als @@ -0,0 +1,53 @@ +open util/ordering[Time] + +sig Time { } + +let dynamic[x] = x one-> Time + +let dynamicSet[x] = x -> Time + +let then [a, b, t, t'] { + some x:Time | a[t,x] && b[x,t'] +} + +let while = while3 + +let while9 [cond, body, t, t'] { + some x:Time | (cond[t] => body[t,x] else t=x) && while8[cond,body,x,t'] +} + +let while8 [cond, body, t, t'] { + some x:Time | (cond[t] => body[t,x] else t=x) && while7[cond,body,x,t'] +} + +let while7 [cond, body, t, t'] { + some x:Time | (cond[t] => body[t,x] else t=x) && while6[cond,body,x,t'] +} + +let while6 [cond, body, t, t'] { + some x:Time | (cond[t] => body[t,x] else t=x) && while5[cond,body,x,t'] +} + +let while5 [cond, body, t, t'] { + some x:Time | (cond[t] => body[t,x] else t=x) && while4[cond,body,x,t'] +} + +let while4 [cond, body, t, t'] { + some x:Time | (cond[t] => body[t,x] else t=x) && while3[cond,body,x,t'] +} + +let while3 [cond, body, t, t'] { + some x:Time | (cond[t] => body[t,x] else t=x) && while2[cond,body,x,t'] +} + +let while2 [cond, body, t, t'] { + some x:Time | (cond[t] => body[t,x] else t=x) && while1[cond,body,x,t'] +} + +let while1 [cond, body, t, t'] { + some x:Time | (cond[t] => body[t,x] else t=x) && while0[cond,body,x,t'] +} + +let while0 [cond, body, t, t'] { + !cond[t] && t=t' +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/org/sat4j/messages.properties b/Source/eu.modelwriter.alloyanalyzer/src/org/sat4j/messages.properties new file mode 100644 index 00000000..2b3f0f00 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/org/sat4j/messages.properties @@ -0,0 +1,8 @@ +Lanceur.wrong.framework=Wrong framework: try minisat or ubcsat +MoreThanSAT.0=Satisfiable \! +MoreThanSAT.1=BackBone: +MoreThanSAT.2=Counting solutions... +MoreThanSAT.3=Number of solutions: +MoreThanSAT.4=Unsatisfiable\! +MoreThanSAT.5=Unsatisfiable (trivial)\! +MoreThanSAT.6=Timeout, sorry\! diff --git a/Source/eu.modelwriter.alloyanalyzer/src/sat4j.version b/Source/eu.modelwriter.alloyanalyzer/src/sat4j.version new file mode 100644 index 00000000..a27f8f26 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/sat4j.version @@ -0,0 +1 @@ +2.3.2.v20120709 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/target/META-INF/MANIFEST.MF b/Source/eu.modelwriter.alloyanalyzer/src/target/META-INF/MANIFEST.MF new file mode 100644 index 00000000..f14a9926 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/target/META-INF/MANIFEST.MF @@ -0,0 +1,31 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %bundleName +Bundle-SymbolicName: org.sat4j.core +Bundle-Version: 2.3.2.v20120709 +Export-Package: org.sat4j;version="2.3.2.v20120709", + org.sat4j.core;version="2.3.2.v20120709", + org.sat4j.minisat;version="2.3.2.v20120709", + org.sat4j.minisat.constraints;version="2.3.2.v20120709", + org.sat4j.minisat.constraints.card;version="2.3.2.v20120709", + org.sat4j.minisat.constraints.cnf;version="2.3.2.v20120709", + org.sat4j.minisat.core;version="2.3.2.v20120709", + org.sat4j.minisat.learning;version="2.3.2.v20120709", + org.sat4j.minisat.orders;version="2.3.2.v20120709", + org.sat4j.minisat.restarts;version="2.3.2.v20120709", + org.sat4j.opt;version="2.3.2.v20120709", + org.sat4j.reader;version="2.3.2.v20120709", + org.sat4j.specs;version="2.3.2.v20120709", + org.sat4j.tools;version="2.3.2.v20120709", + org.sat4j.tools.xplain;version="2.3.2.v20120709" +Bundle-Vendor: %providerName +Bundle-Localization: plugin +Built-By: Daniel Le Berre +Main-Class: org.sat4j.BasicLauncher +Specification-Title: SAT4J +Specification-Version: NA +Specification-Vendor: Daniel Le Berre +Implementation-Title: SAT4J +Implementation-Version: 2.3.2.v20120709 +Implementation-Vendor: CRIL CNRS UMR 8188 - Universite d'Artois +Bundle-RequiredExecutionEnvironment: J2SE-1.5 diff --git a/Source/eu.modelwriter.alloyanalyzer/src/tmp/EvaluatorExample.java b/Source/eu.modelwriter.alloyanalyzer/src/tmp/EvaluatorExample.java new file mode 100644 index 00000000..24e16a2b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/tmp/EvaluatorExample.java @@ -0,0 +1,113 @@ +package tmp; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.XMLNode; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; +import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Options; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.A4SolutionReader; +import edu.mit.csail.sdg.alloy4compiler.translator.TranslateAlloyToKodkod; + +public class EvaluatorExample { + + private static String model = + "sig Point {} \n sig File { r: set Point } \n" + "\n" + "run { } for 1"; + private static String outputfilename = "C:\\Users\\3\\Desktop\\Analyzerrr\\edu\\tmp\\myissue.xml"; + + public static void main(String[] args) throws Exception { + A4Reporter rep = new A4Reporter(); + File tmpAls = File.createTempFile("alloyEvaluator", ".als"); + tmpAls.deleteOnExit(); + flushModelToFile(tmpAls); + { + Module world = CompUtil.parseEverything_fromFile(rep, null, tmpAls.getAbsolutePath()); + A4Options opt = new A4Options(); + opt.originalFilename = tmpAls.getAbsolutePath(); + opt.solver = A4Options.SatSolver.SAT4J; + Command cmd = world.getAllCommands().get(0); + A4Solution sol = TranslateAlloyToKodkod.execute_commandFromBook(rep, + world.getAllReachableSigs(), cmd, opt); + assert sol.satisfiable(); + sol.writeXML(outputfilename); + + // eval with existing A4Solution + Expr e = CompUtil.parseOneExpression_fromString(world, "univ"); + System.out.println(sol.eval(e)); + e = CompUtil.parseOneExpression_fromString(world, "Point"); + System.out.println(sol.eval(e)); + } + // reload everything from files + { + XMLNode xmlNode = new XMLNode(new File(outputfilename)); + String alloySourceFilename = xmlNode.iterator().next().getAttribute("filename"); + Module ansWorld = CompUtil.parseEverything_fromFile(rep, null, alloySourceFilename); + A4Solution ans = A4SolutionReader.read(ansWorld.getAllReachableSigs(), xmlNode); + + Expr e = CompUtil.parseOneExpression_fromString(ansWorld, "univ"); + System.out.println(ans.eval(e)); + e = CompUtil.parseOneExpression_fromString(ansWorld, "Point"); + System.out.println(ans.eval(e)); + } + } + + private static void flushModelToFile(File tmpAls) throws IOException { + BufferedOutputStream bos = null; + try { + bos = new BufferedOutputStream(new FileOutputStream(tmpAls)); + bos.write(model.getBytes()); + bos.flush(); + } finally { + if (bos != null) + bos.close(); + } + } + + + // private static String model = + // "sig Point {} \n" + + // "\n" + + // "run { #Point > 1 } for 3 but 3 Int"; + // + // public static void main(String[] args) throws Exception { + // A4Reporter rep = new A4Reporter(); + // File tmpAls = File.createTempFile("alloyEvaluator", ".als"); + // tmpAls.deleteOnExit(); + // flushModelToFile(tmpAls); + // Module world = CompUtil.parseEverything_fromFile(rep, null, tmpAls.getAbsolutePath()); + // A4Options opt = new A4Options(); + // opt.originalFilename = tmpAls.getAbsolutePath(); + // opt.solver = A4Options.SatSolver.SAT4J; + // Command cmd = world.getAllCommands().get(0); + // A4Solution sol = TranslateAlloyToKodkod.execute_commandFromBook(rep, + // world.getAllReachableSigs(), cmd, opt); + // assert sol.satisfiable(); + // + // // eval: univ + // Expr e = CompUtil.parseOneExpression_fromString(world, "univ"); + // System.out.println(sol.eval(e)); + // + // // eval: Point + // e = CompUtil.parseOneExpression_fromString(world, "Point"); + // System.out.println(sol.eval(e)); + // } + // + // private static void flushModelToFile(File tmpAls) throws IOException { + // BufferedOutputStream bos = null; + // try { + // bos = new BufferedOutputStream(new FileOutputStream(tmpAls)); + // bos.write(model.getBytes()); + // bos.flush(); + // } finally { + // if (bos != null) bos.close(); + // } + // } + +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/tmp/KK.java b/Source/eu.modelwriter.alloyanalyzer/src/tmp/KK.java new file mode 100644 index 00000000..92f910f5 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/tmp/KK.java @@ -0,0 +1,76 @@ +package tmp; +import java.util.LinkedList; +import java.util.List; + +import kodkod.ast.Formula; +import kodkod.ast.IntConstant; +import kodkod.ast.IntExpression; +import kodkod.ast.Relation; +import kodkod.engine.Evaluator; +import kodkod.engine.Solution; +import kodkod.engine.Solver; +import kodkod.engine.config.Options; +import kodkod.engine.satlab.SATFactory; +import kodkod.instance.Bounds; +import kodkod.instance.Instance; +import kodkod.instance.TupleFactory; +import kodkod.instance.TupleSet; +import kodkod.instance.Universe; +import kodkod.util.nodes.PrettyPrinter; + +public final class KK { + + public static void main(String[] args) throws Exception { + + Relation x6 = Relation.unary("R"); + int[] ints = new int[] {0, 1, 2}; + + List atomlist = new LinkedList(); + atomlist.add("R$0"); + atomlist.add("R$1"); + atomlist.add("R$2"); + for (int i : ints) atomlist.add(i); + + Universe universe = new Universe(atomlist); + TupleFactory factory = universe.factory(); + Bounds bounds = new Bounds(universe); + + TupleSet x6_upper = factory.noneOf(1); + x6_upper.add(factory.tuple("R$0")); + x6_upper.add(factory.tuple("R$1")); + x6_upper.add(factory.tuple("R$2")); + bounds.bound(x6, x6_upper); + + for (int i : ints) { + bounds.boundExactly(i, factory.setOf(i)); + } + + Formula x11 = x6.some(); + IntExpression x5 = x6.count(); + Formula x9 = x11.implies(x5.gt(IntConstant.constant(0))); + Formula x7 = x9.not(); + + Solver solver = new Solver(); + solver.options().setSolver(SATFactory.DefaultSAT4J); + solver.options().setBitwidth(2); + solver.options().setFlatten(false); + solver.options().setIntEncoding(Options.IntEncoding.TWOSCOMPLEMENT); + solver.options().setSymmetryBreaking(20); + solver.options().setSkolemDepth(0); + System.out.println("Solving..."); + System.out.println(PrettyPrinter.print(x7, 0)); + System.out.println(bounds); + Solution sol = solver.solve(x7, bounds); + System.out.println(sol.toString()); + + Instance inst = sol.instance(); + Evaluator ev = new Evaluator(inst); + System.out.println(ev.evaluate(x6.some())); + System.out.println(ev.evaluate(x5)); + System.out.println(ev.evaluate(x5.gt(IntConstant.constant(0)))); + System.out.println(ev.evaluate(x6.some().implies(x5.gt(IntConstant.constant(0))).not())); + System.out.println(ev.evaluate(x7)); + + + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/tmp/Ok.java b/Source/eu.modelwriter.alloyanalyzer/src/tmp/Ok.java new file mode 100644 index 00000000..49b97aef --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/tmp/Ok.java @@ -0,0 +1,2229 @@ +package tmp; +import java.util.Arrays; +import java.util.List; +import kodkod.ast.*; +import kodkod.ast.operator.*; +import kodkod.instance.*; +import kodkod.engine.*; +import kodkod.engine.satlab.SATFactory; +import kodkod.engine.config.Options; + +public final class Ok { + + public static void main(String[] args) throws Exception { + + Relation x0 = Relation.unary("Int/min"); + Relation x1 = Relation.unary("Int/zero"); + Relation x2 = Relation.unary("Int/max"); + Relation x3 = Relation.nary("Int/next", 2); + Relation x4 = Relation.unary("seq/Int"); + Relation x5 = Relation.unary("String"); + Relation x6 = Relation.unary("this/A"); + Relation x7 = Relation.unary("this/B"); + Relation x8 = Relation.unary("this/Relation1"); + Relation x9 = Relation.unary("this/Relation2"); + Relation x10 = Relation.unary("this/Relation3"); + Relation x11 = Relation.unary("this/Relation4"); + Relation x12 = Relation.nary("this/Relation1.r", 3); + Relation x13 = Relation.nary("this/Relation2.r", 3); + Relation x14 = Relation.nary("this/Relation3.r", 3); + Relation x15 = Relation.nary("this/Relation4.r", 3); + + List atomlist = Arrays.asList("-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "0", + "1", "2", "3", "4", "5", "6", "7", "A$0", "B$0", "Relation1$0", "Relation2$0", + "Relation3$0", "Relation4$0"); + + Universe universe = new Universe(atomlist); + TupleFactory factory = universe.factory(); + Bounds bounds = new Bounds(universe); + + TupleSet x0_upper = factory.noneOf(1); + x0_upper.add(factory.tuple("-8")); + bounds.boundExactly(x0, x0_upper); + + TupleSet x1_upper = factory.noneOf(1); + x1_upper.add(factory.tuple("0")); + bounds.boundExactly(x1, x1_upper); + + TupleSet x2_upper = factory.noneOf(1); + x2_upper.add(factory.tuple("7")); + bounds.boundExactly(x2, x2_upper); + + TupleSet x3_upper = factory.noneOf(2); + x3_upper.add(factory.tuple("-8").product(factory.tuple("-7"))); + x3_upper.add(factory.tuple("-7").product(factory.tuple("-6"))); + x3_upper.add(factory.tuple("-6").product(factory.tuple("-5"))); + x3_upper.add(factory.tuple("-5").product(factory.tuple("-4"))); + x3_upper.add(factory.tuple("-4").product(factory.tuple("-3"))); + x3_upper.add(factory.tuple("-3").product(factory.tuple("-2"))); + x3_upper.add(factory.tuple("-2").product(factory.tuple("-1"))); + x3_upper.add(factory.tuple("-1").product(factory.tuple("0"))); + x3_upper.add(factory.tuple("0").product(factory.tuple("1"))); + x3_upper.add(factory.tuple("1").product(factory.tuple("2"))); + x3_upper.add(factory.tuple("2").product(factory.tuple("3"))); + x3_upper.add(factory.tuple("3").product(factory.tuple("4"))); + x3_upper.add(factory.tuple("4").product(factory.tuple("5"))); + x3_upper.add(factory.tuple("5").product(factory.tuple("6"))); + x3_upper.add(factory.tuple("6").product(factory.tuple("7"))); + bounds.boundExactly(x3, x3_upper); + + TupleSet x4_upper = factory.noneOf(1); + x4_upper.add(factory.tuple("0")); + bounds.boundExactly(x4, x4_upper); + + TupleSet x5_upper = factory.noneOf(1); + bounds.boundExactly(x5, x5_upper); + + TupleSet x6_upper = factory.noneOf(1); + x6_upper.add(factory.tuple("A$0")); + bounds.bound(x6, x6_upper); + + TupleSet x7_upper = factory.noneOf(1); + x7_upper.add(factory.tuple("B$0")); + bounds.bound(x7, x7_upper); + + TupleSet x8_upper = factory.noneOf(1); + x8_upper.add(factory.tuple("Relation1$0")); + bounds.bound(x8, x8_upper); + + TupleSet x9_upper = factory.noneOf(1); + x9_upper.add(factory.tuple("Relation2$0")); + bounds.bound(x9, x9_upper); + + TupleSet x10_upper = factory.noneOf(1); + x10_upper.add(factory.tuple("Relation3$0")); + bounds.bound(x10, x10_upper); + + TupleSet x11_upper = factory.noneOf(1); + x11_upper.add(factory.tuple("Relation4$0")); + bounds.bound(x11, x11_upper); + + TupleSet x12_upper = factory.noneOf(3); + x12_upper.add(factory.tuple("Relation1$0").product(factory.tuple("A$0")).product( + factory.tuple("A$0"))); + x12_upper.add(factory.tuple("Relation1$0").product(factory.tuple("A$0")).product( + factory.tuple("B$0"))); + x12_upper.add(factory.tuple("Relation1$0").product(factory.tuple("B$0")).product( + factory.tuple("A$0"))); + x12_upper.add(factory.tuple("Relation1$0").product(factory.tuple("B$0")).product( + factory.tuple("B$0"))); + bounds.bound(x12, x12_upper); + + TupleSet x13_upper = factory.noneOf(3); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("A$0")).product( + factory.tuple("A$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("A$0")).product( + factory.tuple("B$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("A$0")).product( + factory.tuple("-8"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("A$0")).product( + factory.tuple("-7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("A$0")).product( + factory.tuple("-6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("A$0")).product( + factory.tuple("-5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("A$0")).product( + factory.tuple("-4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("A$0")).product( + factory.tuple("-3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("A$0")).product( + factory.tuple("-2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("A$0")).product( + factory.tuple("-1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("A$0")).product( + factory.tuple("0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("A$0")).product( + factory.tuple("1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("A$0")).product( + factory.tuple("2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("A$0")).product( + factory.tuple("3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("A$0")).product( + factory.tuple("4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("A$0")).product( + factory.tuple("5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("A$0")).product( + factory.tuple("6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("A$0")).product( + factory.tuple("7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("B$0")).product( + factory.tuple("A$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("B$0")).product( + factory.tuple("B$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("B$0")).product( + factory.tuple("-8"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("B$0")).product( + factory.tuple("-7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("B$0")).product( + factory.tuple("-6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("B$0")).product( + factory.tuple("-5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("B$0")).product( + factory.tuple("-4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("B$0")).product( + factory.tuple("-3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("B$0")).product( + factory.tuple("-2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("B$0")).product( + factory.tuple("-1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("B$0")).product( + factory.tuple("0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("B$0")).product( + factory.tuple("1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("B$0")).product( + factory.tuple("2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("B$0")).product( + factory.tuple("3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("B$0")).product( + factory.tuple("4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("B$0")).product( + factory.tuple("5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("B$0")).product( + factory.tuple("6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("B$0")).product( + factory.tuple("7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-8")).product( + factory.tuple("A$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-8")).product( + factory.tuple("B$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-8")).product( + factory.tuple("-8"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-8")).product( + factory.tuple("-7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-8")).product( + factory.tuple("-6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-8")).product( + factory.tuple("-5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-8")).product( + factory.tuple("-4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-8")).product( + factory.tuple("-3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-8")).product( + factory.tuple("-2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-8")).product( + factory.tuple("-1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-8")).product( + factory.tuple("0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-8")).product( + factory.tuple("1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-8")).product( + factory.tuple("2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-8")).product( + factory.tuple("3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-8")).product( + factory.tuple("4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-8")).product( + factory.tuple("5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-8")).product( + factory.tuple("6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-8")).product( + factory.tuple("7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-7")).product( + factory.tuple("A$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-7")).product( + factory.tuple("B$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-7")).product( + factory.tuple("-8"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-7")).product( + factory.tuple("-7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-7")).product( + factory.tuple("-6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-7")).product( + factory.tuple("-5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-7")).product( + factory.tuple("-4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-7")).product( + factory.tuple("-3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-7")).product( + factory.tuple("-2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-7")).product( + factory.tuple("-1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-7")).product( + factory.tuple("0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-7")).product( + factory.tuple("1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-7")).product( + factory.tuple("2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-7")).product( + factory.tuple("3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-7")).product( + factory.tuple("4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-7")).product( + factory.tuple("5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-7")).product( + factory.tuple("6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-7")).product( + factory.tuple("7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-6")).product( + factory.tuple("A$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-6")).product( + factory.tuple("B$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-6")).product( + factory.tuple("-8"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-6")).product( + factory.tuple("-7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-6")).product( + factory.tuple("-6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-6")).product( + factory.tuple("-5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-6")).product( + factory.tuple("-4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-6")).product( + factory.tuple("-3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-6")).product( + factory.tuple("-2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-6")).product( + factory.tuple("-1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-6")).product( + factory.tuple("0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-6")).product( + factory.tuple("1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-6")).product( + factory.tuple("2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-6")).product( + factory.tuple("3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-6")).product( + factory.tuple("4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-6")).product( + factory.tuple("5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-6")).product( + factory.tuple("6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-6")).product( + factory.tuple("7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-5")).product( + factory.tuple("A$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-5")).product( + factory.tuple("B$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-5")).product( + factory.tuple("-8"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-5")).product( + factory.tuple("-7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-5")).product( + factory.tuple("-6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-5")).product( + factory.tuple("-5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-5")).product( + factory.tuple("-4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-5")).product( + factory.tuple("-3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-5")).product( + factory.tuple("-2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-5")).product( + factory.tuple("-1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-5")).product( + factory.tuple("0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-5")).product( + factory.tuple("1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-5")).product( + factory.tuple("2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-5")).product( + factory.tuple("3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-5")).product( + factory.tuple("4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-5")).product( + factory.tuple("5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-5")).product( + factory.tuple("6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-5")).product( + factory.tuple("7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-4")).product( + factory.tuple("A$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-4")).product( + factory.tuple("B$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-4")).product( + factory.tuple("-8"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-4")).product( + factory.tuple("-7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-4")).product( + factory.tuple("-6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-4")).product( + factory.tuple("-5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-4")).product( + factory.tuple("-4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-4")).product( + factory.tuple("-3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-4")).product( + factory.tuple("-2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-4")).product( + factory.tuple("-1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-4")).product( + factory.tuple("0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-4")).product( + factory.tuple("1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-4")).product( + factory.tuple("2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-4")).product( + factory.tuple("3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-4")).product( + factory.tuple("4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-4")).product( + factory.tuple("5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-4")).product( + factory.tuple("6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-4")).product( + factory.tuple("7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-3")).product( + factory.tuple("A$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-3")).product( + factory.tuple("B$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-3")).product( + factory.tuple("-8"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-3")).product( + factory.tuple("-7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-3")).product( + factory.tuple("-6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-3")).product( + factory.tuple("-5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-3")).product( + factory.tuple("-4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-3")).product( + factory.tuple("-3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-3")).product( + factory.tuple("-2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-3")).product( + factory.tuple("-1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-3")).product( + factory.tuple("0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-3")).product( + factory.tuple("1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-3")).product( + factory.tuple("2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-3")).product( + factory.tuple("3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-3")).product( + factory.tuple("4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-3")).product( + factory.tuple("5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-3")).product( + factory.tuple("6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-3")).product( + factory.tuple("7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-2")).product( + factory.tuple("A$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-2")).product( + factory.tuple("B$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-2")).product( + factory.tuple("-8"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-2")).product( + factory.tuple("-7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-2")).product( + factory.tuple("-6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-2")).product( + factory.tuple("-5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-2")).product( + factory.tuple("-4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-2")).product( + factory.tuple("-3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-2")).product( + factory.tuple("-2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-2")).product( + factory.tuple("-1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-2")).product( + factory.tuple("0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-2")).product( + factory.tuple("1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-2")).product( + factory.tuple("2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-2")).product( + factory.tuple("3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-2")).product( + factory.tuple("4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-2")).product( + factory.tuple("5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-2")).product( + factory.tuple("6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-2")).product( + factory.tuple("7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-1")).product( + factory.tuple("A$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-1")).product( + factory.tuple("B$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-1")).product( + factory.tuple("-8"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-1")).product( + factory.tuple("-7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-1")).product( + factory.tuple("-6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-1")).product( + factory.tuple("-5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-1")).product( + factory.tuple("-4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-1")).product( + factory.tuple("-3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-1")).product( + factory.tuple("-2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-1")).product( + factory.tuple("-1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-1")).product( + factory.tuple("0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-1")).product( + factory.tuple("1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-1")).product( + factory.tuple("2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-1")).product( + factory.tuple("3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-1")).product( + factory.tuple("4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-1")).product( + factory.tuple("5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-1")).product( + factory.tuple("6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("-1")).product( + factory.tuple("7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("0")).product( + factory.tuple("A$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("0")).product( + factory.tuple("B$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("0")).product( + factory.tuple("-8"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("0")).product( + factory.tuple("-7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("0")).product( + factory.tuple("-6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("0")).product( + factory.tuple("-5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("0")).product( + factory.tuple("-4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("0")).product( + factory.tuple("-3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("0")).product( + factory.tuple("-2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("0")).product( + factory.tuple("-1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("0")).product( + factory.tuple("0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("0")).product( + factory.tuple("1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("0")).product( + factory.tuple("2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("0")).product( + factory.tuple("3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("0")).product( + factory.tuple("4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("0")).product( + factory.tuple("5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("0")).product( + factory.tuple("6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("0")).product( + factory.tuple("7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("1")).product( + factory.tuple("A$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("1")).product( + factory.tuple("B$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("1")).product( + factory.tuple("-8"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("1")).product( + factory.tuple("-7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("1")).product( + factory.tuple("-6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("1")).product( + factory.tuple("-5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("1")).product( + factory.tuple("-4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("1")).product( + factory.tuple("-3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("1")).product( + factory.tuple("-2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("1")).product( + factory.tuple("-1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("1")).product( + factory.tuple("0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("1")).product( + factory.tuple("1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("1")).product( + factory.tuple("2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("1")).product( + factory.tuple("3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("1")).product( + factory.tuple("4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("1")).product( + factory.tuple("5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("1")).product( + factory.tuple("6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("1")).product( + factory.tuple("7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("2")).product( + factory.tuple("A$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("2")).product( + factory.tuple("B$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("2")).product( + factory.tuple("-8"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("2")).product( + factory.tuple("-7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("2")).product( + factory.tuple("-6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("2")).product( + factory.tuple("-5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("2")).product( + factory.tuple("-4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("2")).product( + factory.tuple("-3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("2")).product( + factory.tuple("-2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("2")).product( + factory.tuple("-1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("2")).product( + factory.tuple("0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("2")).product( + factory.tuple("1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("2")).product( + factory.tuple("2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("2")).product( + factory.tuple("3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("2")).product( + factory.tuple("4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("2")).product( + factory.tuple("5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("2")).product( + factory.tuple("6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("2")).product( + factory.tuple("7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("3")).product( + factory.tuple("A$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("3")).product( + factory.tuple("B$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("3")).product( + factory.tuple("-8"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("3")).product( + factory.tuple("-7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("3")).product( + factory.tuple("-6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("3")).product( + factory.tuple("-5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("3")).product( + factory.tuple("-4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("3")).product( + factory.tuple("-3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("3")).product( + factory.tuple("-2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("3")).product( + factory.tuple("-1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("3")).product( + factory.tuple("0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("3")).product( + factory.tuple("1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("3")).product( + factory.tuple("2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("3")).product( + factory.tuple("3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("3")).product( + factory.tuple("4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("3")).product( + factory.tuple("5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("3")).product( + factory.tuple("6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("3")).product( + factory.tuple("7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("4")).product( + factory.tuple("A$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("4")).product( + factory.tuple("B$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("4")).product( + factory.tuple("-8"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("4")).product( + factory.tuple("-7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("4")).product( + factory.tuple("-6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("4")).product( + factory.tuple("-5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("4")).product( + factory.tuple("-4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("4")).product( + factory.tuple("-3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("4")).product( + factory.tuple("-2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("4")).product( + factory.tuple("-1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("4")).product( + factory.tuple("0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("4")).product( + factory.tuple("1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("4")).product( + factory.tuple("2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("4")).product( + factory.tuple("3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("4")).product( + factory.tuple("4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("4")).product( + factory.tuple("5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("4")).product( + factory.tuple("6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("4")).product( + factory.tuple("7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("5")).product( + factory.tuple("A$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("5")).product( + factory.tuple("B$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("5")).product( + factory.tuple("-8"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("5")).product( + factory.tuple("-7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("5")).product( + factory.tuple("-6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("5")).product( + factory.tuple("-5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("5")).product( + factory.tuple("-4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("5")).product( + factory.tuple("-3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("5")).product( + factory.tuple("-2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("5")).product( + factory.tuple("-1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("5")).product( + factory.tuple("0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("5")).product( + factory.tuple("1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("5")).product( + factory.tuple("2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("5")).product( + factory.tuple("3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("5")).product( + factory.tuple("4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("5")).product( + factory.tuple("5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("5")).product( + factory.tuple("6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("5")).product( + factory.tuple("7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("6")).product( + factory.tuple("A$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("6")).product( + factory.tuple("B$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("6")).product( + factory.tuple("-8"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("6")).product( + factory.tuple("-7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("6")).product( + factory.tuple("-6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("6")).product( + factory.tuple("-5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("6")).product( + factory.tuple("-4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("6")).product( + factory.tuple("-3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("6")).product( + factory.tuple("-2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("6")).product( + factory.tuple("-1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("6")).product( + factory.tuple("0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("6")).product( + factory.tuple("1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("6")).product( + factory.tuple("2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("6")).product( + factory.tuple("3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("6")).product( + factory.tuple("4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("6")).product( + factory.tuple("5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("6")).product( + factory.tuple("6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("6")).product( + factory.tuple("7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("7")).product( + factory.tuple("A$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("7")).product( + factory.tuple("B$0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("7")).product( + factory.tuple("-8"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("7")).product( + factory.tuple("-7"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("7")).product( + factory.tuple("-6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("7")).product( + factory.tuple("-5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("7")).product( + factory.tuple("-4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("7")).product( + factory.tuple("-3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("7")).product( + factory.tuple("-2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("7")).product( + factory.tuple("-1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("7")).product( + factory.tuple("0"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("7")).product( + factory.tuple("1"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("7")).product( + factory.tuple("2"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("7")).product( + factory.tuple("3"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("7")).product( + factory.tuple("4"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("7")).product( + factory.tuple("5"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("7")).product( + factory.tuple("6"))); + x13_upper.add(factory.tuple("Relation2$0").product(factory.tuple("7")).product( + factory.tuple("7"))); + bounds.bound(x13, x13_upper); + + TupleSet x14_upper = factory.noneOf(3); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("A$0")).product( + factory.tuple("A$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("A$0")).product( + factory.tuple("B$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("A$0")).product( + factory.tuple("-8"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("A$0")).product( + factory.tuple("-7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("A$0")).product( + factory.tuple("-6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("A$0")).product( + factory.tuple("-5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("A$0")).product( + factory.tuple("-4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("A$0")).product( + factory.tuple("-3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("A$0")).product( + factory.tuple("-2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("A$0")).product( + factory.tuple("-1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("A$0")).product( + factory.tuple("0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("A$0")).product( + factory.tuple("1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("A$0")).product( + factory.tuple("2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("A$0")).product( + factory.tuple("3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("A$0")).product( + factory.tuple("4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("A$0")).product( + factory.tuple("5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("A$0")).product( + factory.tuple("6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("A$0")).product( + factory.tuple("7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("B$0")).product( + factory.tuple("A$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("B$0")).product( + factory.tuple("B$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("B$0")).product( + factory.tuple("-8"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("B$0")).product( + factory.tuple("-7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("B$0")).product( + factory.tuple("-6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("B$0")).product( + factory.tuple("-5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("B$0")).product( + factory.tuple("-4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("B$0")).product( + factory.tuple("-3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("B$0")).product( + factory.tuple("-2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("B$0")).product( + factory.tuple("-1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("B$0")).product( + factory.tuple("0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("B$0")).product( + factory.tuple("1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("B$0")).product( + factory.tuple("2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("B$0")).product( + factory.tuple("3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("B$0")).product( + factory.tuple("4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("B$0")).product( + factory.tuple("5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("B$0")).product( + factory.tuple("6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("B$0")).product( + factory.tuple("7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-8")).product( + factory.tuple("A$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-8")).product( + factory.tuple("B$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-8")).product( + factory.tuple("-8"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-8")).product( + factory.tuple("-7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-8")).product( + factory.tuple("-6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-8")).product( + factory.tuple("-5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-8")).product( + factory.tuple("-4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-8")).product( + factory.tuple("-3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-8")).product( + factory.tuple("-2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-8")).product( + factory.tuple("-1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-8")).product( + factory.tuple("0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-8")).product( + factory.tuple("1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-8")).product( + factory.tuple("2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-8")).product( + factory.tuple("3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-8")).product( + factory.tuple("4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-8")).product( + factory.tuple("5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-8")).product( + factory.tuple("6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-8")).product( + factory.tuple("7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-7")).product( + factory.tuple("A$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-7")).product( + factory.tuple("B$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-7")).product( + factory.tuple("-8"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-7")).product( + factory.tuple("-7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-7")).product( + factory.tuple("-6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-7")).product( + factory.tuple("-5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-7")).product( + factory.tuple("-4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-7")).product( + factory.tuple("-3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-7")).product( + factory.tuple("-2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-7")).product( + factory.tuple("-1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-7")).product( + factory.tuple("0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-7")).product( + factory.tuple("1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-7")).product( + factory.tuple("2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-7")).product( + factory.tuple("3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-7")).product( + factory.tuple("4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-7")).product( + factory.tuple("5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-7")).product( + factory.tuple("6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-7")).product( + factory.tuple("7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-6")).product( + factory.tuple("A$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-6")).product( + factory.tuple("B$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-6")).product( + factory.tuple("-8"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-6")).product( + factory.tuple("-7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-6")).product( + factory.tuple("-6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-6")).product( + factory.tuple("-5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-6")).product( + factory.tuple("-4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-6")).product( + factory.tuple("-3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-6")).product( + factory.tuple("-2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-6")).product( + factory.tuple("-1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-6")).product( + factory.tuple("0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-6")).product( + factory.tuple("1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-6")).product( + factory.tuple("2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-6")).product( + factory.tuple("3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-6")).product( + factory.tuple("4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-6")).product( + factory.tuple("5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-6")).product( + factory.tuple("6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-6")).product( + factory.tuple("7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-5")).product( + factory.tuple("A$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-5")).product( + factory.tuple("B$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-5")).product( + factory.tuple("-8"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-5")).product( + factory.tuple("-7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-5")).product( + factory.tuple("-6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-5")).product( + factory.tuple("-5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-5")).product( + factory.tuple("-4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-5")).product( + factory.tuple("-3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-5")).product( + factory.tuple("-2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-5")).product( + factory.tuple("-1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-5")).product( + factory.tuple("0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-5")).product( + factory.tuple("1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-5")).product( + factory.tuple("2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-5")).product( + factory.tuple("3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-5")).product( + factory.tuple("4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-5")).product( + factory.tuple("5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-5")).product( + factory.tuple("6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-5")).product( + factory.tuple("7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-4")).product( + factory.tuple("A$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-4")).product( + factory.tuple("B$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-4")).product( + factory.tuple("-8"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-4")).product( + factory.tuple("-7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-4")).product( + factory.tuple("-6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-4")).product( + factory.tuple("-5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-4")).product( + factory.tuple("-4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-4")).product( + factory.tuple("-3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-4")).product( + factory.tuple("-2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-4")).product( + factory.tuple("-1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-4")).product( + factory.tuple("0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-4")).product( + factory.tuple("1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-4")).product( + factory.tuple("2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-4")).product( + factory.tuple("3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-4")).product( + factory.tuple("4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-4")).product( + factory.tuple("5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-4")).product( + factory.tuple("6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-4")).product( + factory.tuple("7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-3")).product( + factory.tuple("A$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-3")).product( + factory.tuple("B$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-3")).product( + factory.tuple("-8"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-3")).product( + factory.tuple("-7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-3")).product( + factory.tuple("-6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-3")).product( + factory.tuple("-5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-3")).product( + factory.tuple("-4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-3")).product( + factory.tuple("-3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-3")).product( + factory.tuple("-2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-3")).product( + factory.tuple("-1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-3")).product( + factory.tuple("0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-3")).product( + factory.tuple("1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-3")).product( + factory.tuple("2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-3")).product( + factory.tuple("3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-3")).product( + factory.tuple("4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-3")).product( + factory.tuple("5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-3")).product( + factory.tuple("6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-3")).product( + factory.tuple("7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-2")).product( + factory.tuple("A$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-2")).product( + factory.tuple("B$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-2")).product( + factory.tuple("-8"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-2")).product( + factory.tuple("-7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-2")).product( + factory.tuple("-6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-2")).product( + factory.tuple("-5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-2")).product( + factory.tuple("-4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-2")).product( + factory.tuple("-3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-2")).product( + factory.tuple("-2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-2")).product( + factory.tuple("-1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-2")).product( + factory.tuple("0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-2")).product( + factory.tuple("1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-2")).product( + factory.tuple("2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-2")).product( + factory.tuple("3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-2")).product( + factory.tuple("4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-2")).product( + factory.tuple("5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-2")).product( + factory.tuple("6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-2")).product( + factory.tuple("7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-1")).product( + factory.tuple("A$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-1")).product( + factory.tuple("B$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-1")).product( + factory.tuple("-8"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-1")).product( + factory.tuple("-7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-1")).product( + factory.tuple("-6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-1")).product( + factory.tuple("-5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-1")).product( + factory.tuple("-4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-1")).product( + factory.tuple("-3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-1")).product( + factory.tuple("-2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-1")).product( + factory.tuple("-1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-1")).product( + factory.tuple("0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-1")).product( + factory.tuple("1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-1")).product( + factory.tuple("2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-1")).product( + factory.tuple("3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-1")).product( + factory.tuple("4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-1")).product( + factory.tuple("5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-1")).product( + factory.tuple("6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("-1")).product( + factory.tuple("7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("0")).product( + factory.tuple("A$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("0")).product( + factory.tuple("B$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("0")).product( + factory.tuple("-8"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("0")).product( + factory.tuple("-7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("0")).product( + factory.tuple("-6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("0")).product( + factory.tuple("-5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("0")).product( + factory.tuple("-4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("0")).product( + factory.tuple("-3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("0")).product( + factory.tuple("-2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("0")).product( + factory.tuple("-1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("0")).product( + factory.tuple("0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("0")).product( + factory.tuple("1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("0")).product( + factory.tuple("2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("0")).product( + factory.tuple("3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("0")).product( + factory.tuple("4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("0")).product( + factory.tuple("5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("0")).product( + factory.tuple("6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("0")).product( + factory.tuple("7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("1")).product( + factory.tuple("A$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("1")).product( + factory.tuple("B$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("1")).product( + factory.tuple("-8"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("1")).product( + factory.tuple("-7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("1")).product( + factory.tuple("-6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("1")).product( + factory.tuple("-5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("1")).product( + factory.tuple("-4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("1")).product( + factory.tuple("-3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("1")).product( + factory.tuple("-2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("1")).product( + factory.tuple("-1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("1")).product( + factory.tuple("0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("1")).product( + factory.tuple("1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("1")).product( + factory.tuple("2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("1")).product( + factory.tuple("3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("1")).product( + factory.tuple("4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("1")).product( + factory.tuple("5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("1")).product( + factory.tuple("6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("1")).product( + factory.tuple("7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("2")).product( + factory.tuple("A$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("2")).product( + factory.tuple("B$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("2")).product( + factory.tuple("-8"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("2")).product( + factory.tuple("-7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("2")).product( + factory.tuple("-6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("2")).product( + factory.tuple("-5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("2")).product( + factory.tuple("-4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("2")).product( + factory.tuple("-3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("2")).product( + factory.tuple("-2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("2")).product( + factory.tuple("-1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("2")).product( + factory.tuple("0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("2")).product( + factory.tuple("1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("2")).product( + factory.tuple("2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("2")).product( + factory.tuple("3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("2")).product( + factory.tuple("4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("2")).product( + factory.tuple("5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("2")).product( + factory.tuple("6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("2")).product( + factory.tuple("7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("3")).product( + factory.tuple("A$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("3")).product( + factory.tuple("B$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("3")).product( + factory.tuple("-8"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("3")).product( + factory.tuple("-7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("3")).product( + factory.tuple("-6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("3")).product( + factory.tuple("-5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("3")).product( + factory.tuple("-4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("3")).product( + factory.tuple("-3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("3")).product( + factory.tuple("-2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("3")).product( + factory.tuple("-1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("3")).product( + factory.tuple("0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("3")).product( + factory.tuple("1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("3")).product( + factory.tuple("2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("3")).product( + factory.tuple("3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("3")).product( + factory.tuple("4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("3")).product( + factory.tuple("5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("3")).product( + factory.tuple("6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("3")).product( + factory.tuple("7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("4")).product( + factory.tuple("A$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("4")).product( + factory.tuple("B$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("4")).product( + factory.tuple("-8"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("4")).product( + factory.tuple("-7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("4")).product( + factory.tuple("-6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("4")).product( + factory.tuple("-5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("4")).product( + factory.tuple("-4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("4")).product( + factory.tuple("-3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("4")).product( + factory.tuple("-2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("4")).product( + factory.tuple("-1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("4")).product( + factory.tuple("0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("4")).product( + factory.tuple("1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("4")).product( + factory.tuple("2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("4")).product( + factory.tuple("3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("4")).product( + factory.tuple("4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("4")).product( + factory.tuple("5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("4")).product( + factory.tuple("6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("4")).product( + factory.tuple("7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("5")).product( + factory.tuple("A$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("5")).product( + factory.tuple("B$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("5")).product( + factory.tuple("-8"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("5")).product( + factory.tuple("-7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("5")).product( + factory.tuple("-6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("5")).product( + factory.tuple("-5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("5")).product( + factory.tuple("-4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("5")).product( + factory.tuple("-3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("5")).product( + factory.tuple("-2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("5")).product( + factory.tuple("-1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("5")).product( + factory.tuple("0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("5")).product( + factory.tuple("1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("5")).product( + factory.tuple("2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("5")).product( + factory.tuple("3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("5")).product( + factory.tuple("4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("5")).product( + factory.tuple("5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("5")).product( + factory.tuple("6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("5")).product( + factory.tuple("7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("6")).product( + factory.tuple("A$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("6")).product( + factory.tuple("B$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("6")).product( + factory.tuple("-8"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("6")).product( + factory.tuple("-7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("6")).product( + factory.tuple("-6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("6")).product( + factory.tuple("-5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("6")).product( + factory.tuple("-4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("6")).product( + factory.tuple("-3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("6")).product( + factory.tuple("-2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("6")).product( + factory.tuple("-1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("6")).product( + factory.tuple("0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("6")).product( + factory.tuple("1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("6")).product( + factory.tuple("2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("6")).product( + factory.tuple("3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("6")).product( + factory.tuple("4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("6")).product( + factory.tuple("5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("6")).product( + factory.tuple("6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("6")).product( + factory.tuple("7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("7")).product( + factory.tuple("A$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("7")).product( + factory.tuple("B$0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("7")).product( + factory.tuple("-8"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("7")).product( + factory.tuple("-7"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("7")).product( + factory.tuple("-6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("7")).product( + factory.tuple("-5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("7")).product( + factory.tuple("-4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("7")).product( + factory.tuple("-3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("7")).product( + factory.tuple("-2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("7")).product( + factory.tuple("-1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("7")).product( + factory.tuple("0"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("7")).product( + factory.tuple("1"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("7")).product( + factory.tuple("2"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("7")).product( + factory.tuple("3"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("7")).product( + factory.tuple("4"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("7")).product( + factory.tuple("5"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("7")).product( + factory.tuple("6"))); + x14_upper.add(factory.tuple("Relation3$0").product(factory.tuple("7")).product( + factory.tuple("7"))); + bounds.bound(x14, x14_upper); + + TupleSet x15_upper = factory.noneOf(3); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("A$0")).product( + factory.tuple("A$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("A$0")).product( + factory.tuple("B$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("A$0")).product( + factory.tuple("-8"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("A$0")).product( + factory.tuple("-7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("A$0")).product( + factory.tuple("-6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("A$0")).product( + factory.tuple("-5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("A$0")).product( + factory.tuple("-4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("A$0")).product( + factory.tuple("-3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("A$0")).product( + factory.tuple("-2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("A$0")).product( + factory.tuple("-1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("A$0")).product( + factory.tuple("0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("A$0")).product( + factory.tuple("1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("A$0")).product( + factory.tuple("2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("A$0")).product( + factory.tuple("3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("A$0")).product( + factory.tuple("4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("A$0")).product( + factory.tuple("5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("A$0")).product( + factory.tuple("6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("A$0")).product( + factory.tuple("7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("B$0")).product( + factory.tuple("A$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("B$0")).product( + factory.tuple("B$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("B$0")).product( + factory.tuple("-8"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("B$0")).product( + factory.tuple("-7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("B$0")).product( + factory.tuple("-6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("B$0")).product( + factory.tuple("-5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("B$0")).product( + factory.tuple("-4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("B$0")).product( + factory.tuple("-3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("B$0")).product( + factory.tuple("-2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("B$0")).product( + factory.tuple("-1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("B$0")).product( + factory.tuple("0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("B$0")).product( + factory.tuple("1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("B$0")).product( + factory.tuple("2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("B$0")).product( + factory.tuple("3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("B$0")).product( + factory.tuple("4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("B$0")).product( + factory.tuple("5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("B$0")).product( + factory.tuple("6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("B$0")).product( + factory.tuple("7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-8")).product( + factory.tuple("A$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-8")).product( + factory.tuple("B$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-8")).product( + factory.tuple("-8"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-8")).product( + factory.tuple("-7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-8")).product( + factory.tuple("-6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-8")).product( + factory.tuple("-5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-8")).product( + factory.tuple("-4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-8")).product( + factory.tuple("-3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-8")).product( + factory.tuple("-2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-8")).product( + factory.tuple("-1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-8")).product( + factory.tuple("0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-8")).product( + factory.tuple("1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-8")).product( + factory.tuple("2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-8")).product( + factory.tuple("3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-8")).product( + factory.tuple("4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-8")).product( + factory.tuple("5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-8")).product( + factory.tuple("6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-8")).product( + factory.tuple("7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-7")).product( + factory.tuple("A$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-7")).product( + factory.tuple("B$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-7")).product( + factory.tuple("-8"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-7")).product( + factory.tuple("-7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-7")).product( + factory.tuple("-6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-7")).product( + factory.tuple("-5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-7")).product( + factory.tuple("-4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-7")).product( + factory.tuple("-3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-7")).product( + factory.tuple("-2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-7")).product( + factory.tuple("-1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-7")).product( + factory.tuple("0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-7")).product( + factory.tuple("1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-7")).product( + factory.tuple("2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-7")).product( + factory.tuple("3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-7")).product( + factory.tuple("4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-7")).product( + factory.tuple("5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-7")).product( + factory.tuple("6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-7")).product( + factory.tuple("7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-6")).product( + factory.tuple("A$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-6")).product( + factory.tuple("B$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-6")).product( + factory.tuple("-8"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-6")).product( + factory.tuple("-7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-6")).product( + factory.tuple("-6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-6")).product( + factory.tuple("-5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-6")).product( + factory.tuple("-4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-6")).product( + factory.tuple("-3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-6")).product( + factory.tuple("-2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-6")).product( + factory.tuple("-1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-6")).product( + factory.tuple("0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-6")).product( + factory.tuple("1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-6")).product( + factory.tuple("2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-6")).product( + factory.tuple("3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-6")).product( + factory.tuple("4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-6")).product( + factory.tuple("5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-6")).product( + factory.tuple("6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-6")).product( + factory.tuple("7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-5")).product( + factory.tuple("A$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-5")).product( + factory.tuple("B$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-5")).product( + factory.tuple("-8"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-5")).product( + factory.tuple("-7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-5")).product( + factory.tuple("-6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-5")).product( + factory.tuple("-5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-5")).product( + factory.tuple("-4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-5")).product( + factory.tuple("-3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-5")).product( + factory.tuple("-2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-5")).product( + factory.tuple("-1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-5")).product( + factory.tuple("0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-5")).product( + factory.tuple("1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-5")).product( + factory.tuple("2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-5")).product( + factory.tuple("3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-5")).product( + factory.tuple("4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-5")).product( + factory.tuple("5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-5")).product( + factory.tuple("6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-5")).product( + factory.tuple("7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-4")).product( + factory.tuple("A$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-4")).product( + factory.tuple("B$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-4")).product( + factory.tuple("-8"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-4")).product( + factory.tuple("-7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-4")).product( + factory.tuple("-6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-4")).product( + factory.tuple("-5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-4")).product( + factory.tuple("-4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-4")).product( + factory.tuple("-3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-4")).product( + factory.tuple("-2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-4")).product( + factory.tuple("-1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-4")).product( + factory.tuple("0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-4")).product( + factory.tuple("1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-4")).product( + factory.tuple("2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-4")).product( + factory.tuple("3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-4")).product( + factory.tuple("4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-4")).product( + factory.tuple("5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-4")).product( + factory.tuple("6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-4")).product( + factory.tuple("7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-3")).product( + factory.tuple("A$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-3")).product( + factory.tuple("B$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-3")).product( + factory.tuple("-8"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-3")).product( + factory.tuple("-7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-3")).product( + factory.tuple("-6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-3")).product( + factory.tuple("-5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-3")).product( + factory.tuple("-4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-3")).product( + factory.tuple("-3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-3")).product( + factory.tuple("-2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-3")).product( + factory.tuple("-1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-3")).product( + factory.tuple("0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-3")).product( + factory.tuple("1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-3")).product( + factory.tuple("2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-3")).product( + factory.tuple("3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-3")).product( + factory.tuple("4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-3")).product( + factory.tuple("5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-3")).product( + factory.tuple("6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-3")).product( + factory.tuple("7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-2")).product( + factory.tuple("A$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-2")).product( + factory.tuple("B$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-2")).product( + factory.tuple("-8"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-2")).product( + factory.tuple("-7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-2")).product( + factory.tuple("-6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-2")).product( + factory.tuple("-5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-2")).product( + factory.tuple("-4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-2")).product( + factory.tuple("-3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-2")).product( + factory.tuple("-2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-2")).product( + factory.tuple("-1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-2")).product( + factory.tuple("0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-2")).product( + factory.tuple("1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-2")).product( + factory.tuple("2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-2")).product( + factory.tuple("3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-2")).product( + factory.tuple("4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-2")).product( + factory.tuple("5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-2")).product( + factory.tuple("6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-2")).product( + factory.tuple("7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-1")).product( + factory.tuple("A$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-1")).product( + factory.tuple("B$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-1")).product( + factory.tuple("-8"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-1")).product( + factory.tuple("-7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-1")).product( + factory.tuple("-6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-1")).product( + factory.tuple("-5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-1")).product( + factory.tuple("-4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-1")).product( + factory.tuple("-3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-1")).product( + factory.tuple("-2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-1")).product( + factory.tuple("-1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-1")).product( + factory.tuple("0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-1")).product( + factory.tuple("1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-1")).product( + factory.tuple("2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-1")).product( + factory.tuple("3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-1")).product( + factory.tuple("4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-1")).product( + factory.tuple("5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-1")).product( + factory.tuple("6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("-1")).product( + factory.tuple("7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("0")).product( + factory.tuple("A$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("0")).product( + factory.tuple("B$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("0")).product( + factory.tuple("-8"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("0")).product( + factory.tuple("-7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("0")).product( + factory.tuple("-6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("0")).product( + factory.tuple("-5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("0")).product( + factory.tuple("-4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("0")).product( + factory.tuple("-3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("0")).product( + factory.tuple("-2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("0")).product( + factory.tuple("-1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("0")).product( + factory.tuple("0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("0")).product( + factory.tuple("1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("0")).product( + factory.tuple("2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("0")).product( + factory.tuple("3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("0")).product( + factory.tuple("4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("0")).product( + factory.tuple("5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("0")).product( + factory.tuple("6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("0")).product( + factory.tuple("7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("1")).product( + factory.tuple("A$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("1")).product( + factory.tuple("B$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("1")).product( + factory.tuple("-8"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("1")).product( + factory.tuple("-7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("1")).product( + factory.tuple("-6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("1")).product( + factory.tuple("-5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("1")).product( + factory.tuple("-4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("1")).product( + factory.tuple("-3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("1")).product( + factory.tuple("-2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("1")).product( + factory.tuple("-1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("1")).product( + factory.tuple("0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("1")).product( + factory.tuple("1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("1")).product( + factory.tuple("2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("1")).product( + factory.tuple("3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("1")).product( + factory.tuple("4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("1")).product( + factory.tuple("5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("1")).product( + factory.tuple("6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("1")).product( + factory.tuple("7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("2")).product( + factory.tuple("A$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("2")).product( + factory.tuple("B$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("2")).product( + factory.tuple("-8"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("2")).product( + factory.tuple("-7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("2")).product( + factory.tuple("-6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("2")).product( + factory.tuple("-5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("2")).product( + factory.tuple("-4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("2")).product( + factory.tuple("-3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("2")).product( + factory.tuple("-2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("2")).product( + factory.tuple("-1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("2")).product( + factory.tuple("0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("2")).product( + factory.tuple("1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("2")).product( + factory.tuple("2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("2")).product( + factory.tuple("3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("2")).product( + factory.tuple("4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("2")).product( + factory.tuple("5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("2")).product( + factory.tuple("6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("2")).product( + factory.tuple("7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("3")).product( + factory.tuple("A$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("3")).product( + factory.tuple("B$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("3")).product( + factory.tuple("-8"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("3")).product( + factory.tuple("-7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("3")).product( + factory.tuple("-6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("3")).product( + factory.tuple("-5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("3")).product( + factory.tuple("-4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("3")).product( + factory.tuple("-3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("3")).product( + factory.tuple("-2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("3")).product( + factory.tuple("-1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("3")).product( + factory.tuple("0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("3")).product( + factory.tuple("1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("3")).product( + factory.tuple("2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("3")).product( + factory.tuple("3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("3")).product( + factory.tuple("4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("3")).product( + factory.tuple("5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("3")).product( + factory.tuple("6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("3")).product( + factory.tuple("7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("4")).product( + factory.tuple("A$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("4")).product( + factory.tuple("B$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("4")).product( + factory.tuple("-8"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("4")).product( + factory.tuple("-7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("4")).product( + factory.tuple("-6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("4")).product( + factory.tuple("-5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("4")).product( + factory.tuple("-4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("4")).product( + factory.tuple("-3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("4")).product( + factory.tuple("-2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("4")).product( + factory.tuple("-1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("4")).product( + factory.tuple("0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("4")).product( + factory.tuple("1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("4")).product( + factory.tuple("2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("4")).product( + factory.tuple("3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("4")).product( + factory.tuple("4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("4")).product( + factory.tuple("5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("4")).product( + factory.tuple("6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("4")).product( + factory.tuple("7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("5")).product( + factory.tuple("A$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("5")).product( + factory.tuple("B$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("5")).product( + factory.tuple("-8"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("5")).product( + factory.tuple("-7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("5")).product( + factory.tuple("-6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("5")).product( + factory.tuple("-5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("5")).product( + factory.tuple("-4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("5")).product( + factory.tuple("-3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("5")).product( + factory.tuple("-2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("5")).product( + factory.tuple("-1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("5")).product( + factory.tuple("0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("5")).product( + factory.tuple("1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("5")).product( + factory.tuple("2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("5")).product( + factory.tuple("3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("5")).product( + factory.tuple("4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("5")).product( + factory.tuple("5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("5")).product( + factory.tuple("6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("5")).product( + factory.tuple("7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("6")).product( + factory.tuple("A$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("6")).product( + factory.tuple("B$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("6")).product( + factory.tuple("-8"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("6")).product( + factory.tuple("-7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("6")).product( + factory.tuple("-6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("6")).product( + factory.tuple("-5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("6")).product( + factory.tuple("-4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("6")).product( + factory.tuple("-3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("6")).product( + factory.tuple("-2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("6")).product( + factory.tuple("-1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("6")).product( + factory.tuple("0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("6")).product( + factory.tuple("1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("6")).product( + factory.tuple("2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("6")).product( + factory.tuple("3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("6")).product( + factory.tuple("4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("6")).product( + factory.tuple("5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("6")).product( + factory.tuple("6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("6")).product( + factory.tuple("7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("7")).product( + factory.tuple("A$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("7")).product( + factory.tuple("B$0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("7")).product( + factory.tuple("-8"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("7")).product( + factory.tuple("-7"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("7")).product( + factory.tuple("-6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("7")).product( + factory.tuple("-5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("7")).product( + factory.tuple("-4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("7")).product( + factory.tuple("-3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("7")).product( + factory.tuple("-2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("7")).product( + factory.tuple("-1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("7")).product( + factory.tuple("0"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("7")).product( + factory.tuple("1"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("7")).product( + factory.tuple("2"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("7")).product( + factory.tuple("3"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("7")).product( + factory.tuple("4"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("7")).product( + factory.tuple("5"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("7")).product( + factory.tuple("6"))); + x15_upper.add(factory.tuple("Relation4$0").product(factory.tuple("7")).product( + factory.tuple("7"))); + bounds.bound(x15, x15_upper); + + bounds.boundExactly(-8, factory.range(factory.tuple("-8"), factory.tuple("-8"))); + bounds.boundExactly(-7, factory.range(factory.tuple("-7"), factory.tuple("-7"))); + bounds.boundExactly(-6, factory.range(factory.tuple("-6"), factory.tuple("-6"))); + bounds.boundExactly(-5, factory.range(factory.tuple("-5"), factory.tuple("-5"))); + bounds.boundExactly(-4, factory.range(factory.tuple("-4"), factory.tuple("-4"))); + bounds.boundExactly(-3, factory.range(factory.tuple("-3"), factory.tuple("-3"))); + bounds.boundExactly(-2, factory.range(factory.tuple("-2"), factory.tuple("-2"))); + bounds.boundExactly(-1, factory.range(factory.tuple("-1"), factory.tuple("-1"))); + bounds.boundExactly(0, factory.range(factory.tuple("0"), factory.tuple("0"))); + bounds.boundExactly(1, factory.range(factory.tuple("1"), factory.tuple("1"))); + bounds.boundExactly(2, factory.range(factory.tuple("2"), factory.tuple("2"))); + bounds.boundExactly(3, factory.range(factory.tuple("3"), factory.tuple("3"))); + bounds.boundExactly(4, factory.range(factory.tuple("4"), factory.tuple("4"))); + bounds.boundExactly(5, factory.range(factory.tuple("5"), factory.tuple("5"))); + bounds.boundExactly(6, factory.range(factory.tuple("6"), factory.tuple("6"))); + bounds.boundExactly(7, factory.range(factory.tuple("7"), factory.tuple("7"))); + + Variable x19 = Variable.unary("p1_this"); + Decls x18 = x19.oneOf(x8); + Expression x23 = x19.join(x12); + Expression x25 = x6.union(x7); + Expression x26 = x6.union(x7); + Expression x24 = x25.product(x26); + Formula x22 = x23.in(x24); + Variable x29 = Variable.unary("v60"); + Decls x28 = x29.oneOf(x25); + Expression x32 = x29.join(x23); + Formula x31 = x32.one(); + Expression x34 = x6.union(x7); + Formula x33 = x32.in(x34); + Formula x30 = x31.and(x33); + Formula x27 = x30.forAll(x28); + Formula x21 = x22.and(x27); + Variable x37 = Variable.unary("v61"); + Decls x36 = x37.oneOf(x26); + Expression x39 = x23.join(x37); + Expression x40 = x6.union(x7); + Formula x38 = x39.in(x40); + Formula x35 = x38.forAll(x36); + Formula x20 = x21.and(x35); + Formula x17 = x20.forAll(x18); + Expression x43 = x12.join(Expression.UNIV); + Expression x42 = x43.join(Expression.UNIV); + Formula x41 = x42.in(x8); + Variable x47 = Variable.unary("p1_this"); + Decls x46 = x47.oneOf(x9); + Expression x51 = x47.join(x13); + Expression x54 = x6.union(x7); + Expression x53 = x54.union(Expression.INTS); + Expression x57 = x6.union(x7); + Expression x56 = x57.union(Expression.INTS); + Expression x52 = x53.product(x56); + Formula x50 = x51.in(x52); + Variable x60 = Variable.unary("v62"); + Decls x59 = x60.oneOf(x53); + Expression x62 = x60.join(x51); + Expression x64 = x6.union(x7); + Expression x63 = x64.union(Expression.INTS); + Formula x61 = x62.in(x63); + Formula x58 = x61.forAll(x59); + Formula x49 = x50.and(x58); + Variable x67 = Variable.unary("v63"); + Decls x66 = x67.oneOf(x56); + Expression x70 = x51.join(x67); + Formula x69 = x70.one(); + Expression x73 = x6.union(x7); + Expression x72 = x73.union(Expression.INTS); + Formula x71 = x70.in(x72); + Formula x68 = x69.and(x71); + Formula x65 = x68.forAll(x66); + Formula x48 = x49.and(x65); + Formula x45 = x48.forAll(x46); + Expression x76 = x13.join(Expression.UNIV); + Expression x75 = x76.join(Expression.UNIV); + Formula x74 = x75.in(x9); + Variable x79 = Variable.unary("p1_this"); + Decls x78 = x79.oneOf(x10); + Expression x83 = x79.join(x14); + Expression x86 = x6.union(x7); + Expression x85 = x86.union(Expression.INTS); + Expression x88 = x6.union(x7); + Expression x87 = x88.union(Expression.INTS); + Expression x84 = x85.product(x87); + Formula x82 = x83.in(x84); + Variable x91 = Variable.unary("v64"); + Decls x90 = x91.oneOf(x85); + Expression x94 = x91.join(x83); + Formula x93 = x94.one(); + Expression x97 = x6.union(x7); + Expression x96 = x97.union(Expression.INTS); + Formula x95 = x94.in(x96); + Formula x92 = x93.and(x95); + Formula x89 = x92.forAll(x90); + Formula x81 = x82.and(x89); + Variable x100 = Variable.unary("v65"); + Decls x99 = x100.oneOf(x87); + Expression x103 = x83.join(x100); + Formula x102 = x103.one(); + Expression x106 = x6.union(x7); + Expression x105 = x106.union(Expression.INTS); + Formula x104 = x103.in(x105); + Formula x101 = x102.and(x104); + Formula x98 = x101.forAll(x99); + Formula x80 = x81.and(x98); + Formula x77 = x80.forAll(x78); + Expression x109 = x14.join(Expression.UNIV); + Expression x108 = x109.join(Expression.UNIV); + Formula x107 = x108.in(x10); + Variable x112 = Variable.unary("p1_this"); + Decls x111 = x112.oneOf(x11); + Expression x114 = x112.join(x15); + Expression x117 = x6.union(x7); + Expression x116 = x117.union(Expression.INTS); + Expression x119 = x6.union(x7); + Expression x118 = x119.union(Expression.INTS); + Expression x115 = x116.product(x118); + Formula x113 = x114.in(x115); + Formula x110 = x113.forAll(x111); + Expression x122 = x15.join(Expression.UNIV); + Expression x121 = x122.join(Expression.UNIV); + Formula x120 = x121.in(x11); + Variable x126 = Variable.unary("p1_r1"); + Decls x125 = x126.oneOf(x8); + Variable x129 = Variable.unary("p1_x"); + Expression x130 = x6.union(x7); + Decls x128 = x129.oneOf(x130); + Expression x133 = x126.join(x12); + Expression x132 = x129.join(x133); + Formula x131 = x132.one(); + Formula x127 = x131.forAll(x128); + Formula x124 = x127.forAll(x125); + Formula x123 = x124.not(); + Formula x134 = x0.eq(x0); + Formula x135 = x1.eq(x1); + Formula x136 = x2.eq(x2); + Formula x137 = x3.eq(x3); + Formula x138 = x4.eq(x4); + Formula x139 = x5.eq(x5); + Formula x140 = x6.eq(x6); + Formula x141 = x7.eq(x7); + Formula x142 = x8.eq(x8); + Formula x143 = x9.eq(x9); + Formula x144 = x10.eq(x10); + Formula x145 = x11.eq(x11); + Formula x146 = x12.eq(x12); + Formula x147 = x13.eq(x13); + Formula x148 = x14.eq(x14); + Formula x149 = x15.eq(x15); + Formula x16 = Formula.compose(FormulaOperator.AND, x17, x41, x45, x74, x77, x107, x110, + x120, x123, x134, x135, x136, x137, x138, x139, x140, x141, x142, x143, x144, x145, + x146, x147, x148, x149); + + Solver solver = new Solver(); + solver.options().setSolver(SATFactory.DefaultSAT4J); + solver.options().setBitwidth(4); + solver.options().setFlatten(false); + solver.options().setIntEncoding(Options.IntEncoding.TWOSCOMPLEMENT); + solver.options().setSymmetryBreaking(20); + solver.options().setSkolemDepth(0); + System.out.println("Solving..."); + System.out.flush(); + Solution sol = solver.solve(x16, bounds); + System.out.println(sol.toString()); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/tmp/Test.java b/Source/eu.modelwriter.alloyanalyzer/src/tmp/Test.java new file mode 100644 index 00000000..34a66ea7 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/tmp/Test.java @@ -0,0 +1,83 @@ +package tmp; + +import java.util.Arrays; +import java.util.List; +import kodkod.ast.*; +import kodkod.ast.operator.*; +import kodkod.instance.*; +import kodkod.engine.*; +import kodkod.engine.satlab.SATFactory; +import kodkod.engine.config.Options; + +/* + ================================================== + kodkod formula: + ================================================== + #(this/A) = (#(this/B) + 1) && + Int/min = Int/min && + Int/zero = Int/zero && + Int/max = Int/max && + Int/next = Int/next && + seq/Int = seq/Int && + String = String && + this/A = this/A && + this/B = this/B + ================================================== + */ +public final class Test { + + public static void main(String[] args) throws Exception { + + Relation x5 = Relation.unary("String"); + Relation x6 = Relation.unary("this/A"); + Relation x7 = Relation.unary("this/B"); + + List atomlist = Arrays.asList("A$0", "unused0", "unused1", "unused2", "unused3", "unused4", "unused5", "unused6", + "unused7", "unused8"); + + Universe universe = new Universe(atomlist); + TupleFactory factory = universe.factory(); + Bounds bounds = new Bounds(universe); + + TupleSet x5_upper = factory.noneOf(1); + bounds.boundExactly(x5, x5_upper); + + TupleSet x6_upper = factory.noneOf(1); + x6_upper.add(factory.tuple("unused0")); + x6_upper.add(factory.tuple("unused1")); + x6_upper.add(factory.tuple("unused2")); + x6_upper.add(factory.tuple("unused3")); + x6_upper.add(factory.tuple("A$0")); + bounds.bound(x6, x6_upper); + + TupleSet x7_upper = factory.noneOf(1); + x7_upper.add(factory.tuple("unused4")); + x7_upper.add(factory.tuple("unused5")); + x7_upper.add(factory.tuple("unused6")); + x7_upper.add(factory.tuple("unused7")); + x7_upper.add(factory.tuple("unused8")); + bounds.bound(x7, x7_upper); + + IntExpression x10 = x6.count(); + IntExpression x12 = x7.count(); + IntExpression x13 = IntConstant.constant(1); + IntExpression x11 = x12.plus(x13); + Formula x9 = x10.eq(x11); + Formula x19 = x5.eq(x5); + Formula x20 = x6.eq(x6); + Formula x21 = x7.eq(x7); + Formula x8 = Formula.compose(FormulaOperator.AND, x9, x19, x20, x21); + + Solver solver = new Solver(); + solver.options().setSolver(SATFactory.DefaultSAT4J); + solver.options().setBitwidth(4); + solver.options().setFlatten(false); + solver.options().setIntEncoding(Options.IntEncoding.TWOSCOMPLEMENT); + solver.options().setSymmetryBreaking(20); + solver.options().setSkolemDepth(0); + System.out.println("Solving..."); + System.out.flush(); + Solution sol = solver.solve(x8, bounds); + System.out.println(sol.toString()); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/tmp/Test1.java b/Source/eu.modelwriter.alloyanalyzer/src/tmp/Test1.java new file mode 100644 index 00000000..60292b2a --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/tmp/Test1.java @@ -0,0 +1,100 @@ +package tmp; +import java.util.Arrays; +import java.util.List; +import kodkod.ast.*; +import kodkod.ast.operator.*; +import kodkod.instance.*; +import kodkod.util.nodes.PrettyPrinter; +import kodkod.engine.*; +import kodkod.engine.satlab.SATFactory; +import kodkod.engine.config.Options; + +public final class Test1 { + + public static void main(String[] args) throws Exception { + + Relation x0 = Relation.unary("Int/min"); + Relation x1 = Relation.unary("Int/zero"); + Relation x2 = Relation.unary("Int/max"); + Relation x3 = Relation.nary("Int/next", 2); + Relation x4 = Relation.unary("seq/Int"); + Relation x5 = Relation.unary("String"); + Relation x6 = Relation.unary("this/R"); + + List atomlist = Arrays.asList("-1", "-2", "0", "1", "R$0", "R$1", "unused0"); + + Universe universe = new Universe(atomlist); + TupleFactory factory = universe.factory(); + Bounds bounds = new Bounds(universe); + + TupleSet x0_upper = factory.noneOf(1); + x0_upper.add(factory.tuple("-2")); + bounds.boundExactly(x0, x0_upper); + + TupleSet x1_upper = factory.noneOf(1); + x1_upper.add(factory.tuple("0")); + bounds.boundExactly(x1, x1_upper); + + TupleSet x2_upper = factory.noneOf(1); + x2_upper.add(factory.tuple("1")); + bounds.boundExactly(x2, x2_upper); + + TupleSet x3_upper = factory.noneOf(2); + x3_upper.add(factory.tuple("-2").product(factory.tuple("-1"))); + x3_upper.add(factory.tuple("-1").product(factory.tuple("0"))); + x3_upper.add(factory.tuple("0").product(factory.tuple("1"))); + bounds.boundExactly(x3, x3_upper); + + TupleSet x4_upper = factory.noneOf(1); + x4_upper.add(factory.tuple("0")); + bounds.boundExactly(x4, x4_upper); + + TupleSet x5_upper = factory.noneOf(1); + bounds.boundExactly(x5, x5_upper); + + TupleSet x6_upper = factory.noneOf(1); + x6_upper.add(factory.tuple("unused0")); + x6_upper.add(factory.tuple("R$0")); + x6_upper.add(factory.tuple("R$1")); + bounds.bound(x6, x6_upper); + + bounds.boundExactly(-2, factory.range(factory.tuple("-2"), factory.tuple("-2"))); + bounds.boundExactly(-1, factory.range(factory.tuple("-1"), factory.tuple("-1"))); + bounds.boundExactly(0, factory.range(factory.tuple("0"), factory.tuple("0"))); + bounds.boundExactly(1, factory.range(factory.tuple("1"), factory.tuple("1"))); + + Formula x11 = x6.some(); + Formula x10 = x11.not(); + IntExpression x13 = x6.count(); + IntExpression x14 = IntConstant.constant(0); + Formula x12 = x13.gt(x14); + Formula x9 = x10.or(x12); + Formula x8 = x9.not(); + Formula x15 = x0.eq(x0); + Formula x16 = x1.eq(x1); + Formula x17 = x2.eq(x2); + Formula x18 = x3.eq(x3); + Formula x19 = x4.eq(x4); + Formula x20 = x5.eq(x5); + Formula x21 = x6.eq(x6); + Formula x7 = Formula.compose(FormulaOperator.AND, x8, x15, x16, x17, x18, x19, x20, x21); + + Solver solver = new Solver(); + solver.options().setSolver(SATFactory.DefaultSAT4J); + solver.options().setBitwidth(2); + solver.options().setFlatten(false); + solver.options().setIntEncoding(Options.IntEncoding.TWOSCOMPLEMENT); + solver.options().setSymmetryBreaking(20); + solver.options().setSkolemDepth(0); + System.out.println("Solving..."); + System.out.println(PrettyPrinter.print(x7, 2)); + System.out.println(bounds); + System.out.flush(); + Solution sol = solver.solve(x7, bounds); + System.out.println(sol.toString()); + Evaluator ev = new Evaluator(sol.instance(), solver.options()); + System.out.println(ev.evaluate(x7)); + System.out.println(ev.evaluate(x6.count())); + System.out.println(ev.evaluate(x6.count().gt(IntConstant.constant(0)))); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/tmp/TestSlow.java b/Source/eu.modelwriter.alloyanalyzer/src/tmp/TestSlow.java new file mode 100644 index 00000000..f23a6030 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/tmp/TestSlow.java @@ -0,0 +1,266 @@ +package tmp; +import java.util.Arrays; +import java.util.List; +import kodkod.ast.*; +import kodkod.ast.operator.*; +import kodkod.instance.*; +import kodkod.util.nodes.PrettyPrinter; +import kodkod.engine.*; +import kodkod.engine.satlab.SATFactory; +import kodkod.engine.config.Options; + +public final class TestSlow { + + public static void main(String[] args) throws Exception { + + Relation x0 = Relation.unary("Int/min"); + Relation x1 = Relation.unary("Int/zero"); + Relation x2 = Relation.unary("Int/max"); + Relation x3 = Relation.nary("Int/next", 2); + Relation x4 = Relation.unary("seq/Int"); + Relation x5 = Relation.unary("String"); + Relation x6 = Relation.unary("this/A"); + Relation x7 = Relation.unary("this/Relation"); + Relation x8 = Relation.nary("this/Relation.r", 5); + + List atomlist = Arrays.asList("-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "0", + "1", "2", "3", "4", "5", "6", "7", "unused0", "unused1"); + + Universe universe = new Universe(atomlist); + TupleFactory factory = universe.factory(); + Bounds bounds = new Bounds(universe); + + TupleSet x0_upper = factory.noneOf(1); + x0_upper.add(factory.tuple("-8")); + bounds.boundExactly(x0, x0_upper); + + TupleSet x1_upper = factory.noneOf(1); + x1_upper.add(factory.tuple("0")); + bounds.boundExactly(x1, x1_upper); + + TupleSet x2_upper = factory.noneOf(1); + x2_upper.add(factory.tuple("7")); + bounds.boundExactly(x2, x2_upper); + + TupleSet x3_upper = factory.noneOf(2); + x3_upper.add(factory.tuple("-8").product(factory.tuple("-7"))); + x3_upper.add(factory.tuple("-7").product(factory.tuple("-6"))); + x3_upper.add(factory.tuple("-6").product(factory.tuple("-5"))); + x3_upper.add(factory.tuple("-5").product(factory.tuple("-4"))); + x3_upper.add(factory.tuple("-4").product(factory.tuple("-3"))); + x3_upper.add(factory.tuple("-3").product(factory.tuple("-2"))); + x3_upper.add(factory.tuple("-2").product(factory.tuple("-1"))); + x3_upper.add(factory.tuple("-1").product(factory.tuple("0"))); + x3_upper.add(factory.tuple("0").product(factory.tuple("1"))); + x3_upper.add(factory.tuple("1").product(factory.tuple("2"))); + x3_upper.add(factory.tuple("2").product(factory.tuple("3"))); + x3_upper.add(factory.tuple("3").product(factory.tuple("4"))); + x3_upper.add(factory.tuple("4").product(factory.tuple("5"))); + x3_upper.add(factory.tuple("5").product(factory.tuple("6"))); + x3_upper.add(factory.tuple("6").product(factory.tuple("7"))); + bounds.boundExactly(x3, x3_upper); + + TupleSet x4_upper = factory.noneOf(1); + x4_upper.add(factory.tuple("0")); + bounds.boundExactly(x4, x4_upper); + + TupleSet x5_upper = factory.noneOf(1); + bounds.boundExactly(x5, x5_upper); + + TupleSet x6_upper = factory.noneOf(1); + x6_upper.add(factory.tuple("unused0")); + bounds.bound(x6, x6_upper); + + TupleSet x7_upper = factory.noneOf(1); + x7_upper.add(factory.tuple("unused1")); + bounds.bound(x7, x7_upper); + + TupleSet x8_upper = factory.noneOf(5); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("unused0")).product( + factory.tuple("unused0")).product(factory.tuple("unused0")).product( + factory.tuple("unused0"))); + bounds.bound(x8, x8_upper); + + bounds.boundExactly(-8, factory.range(factory.tuple("-8"), factory.tuple("-8"))); + bounds.boundExactly(-7, factory.range(factory.tuple("-7"), factory.tuple("-7"))); + bounds.boundExactly(-6, factory.range(factory.tuple("-6"), factory.tuple("-6"))); + bounds.boundExactly(-5, factory.range(factory.tuple("-5"), factory.tuple("-5"))); + bounds.boundExactly(-4, factory.range(factory.tuple("-4"), factory.tuple("-4"))); + bounds.boundExactly(-3, factory.range(factory.tuple("-3"), factory.tuple("-3"))); + bounds.boundExactly(-2, factory.range(factory.tuple("-2"), factory.tuple("-2"))); + bounds.boundExactly(-1, factory.range(factory.tuple("-1"), factory.tuple("-1"))); + bounds.boundExactly(0, factory.range(factory.tuple("0"), factory.tuple("0"))); + bounds.boundExactly(1, factory.range(factory.tuple("1"), factory.tuple("1"))); + bounds.boundExactly(2, factory.range(factory.tuple("2"), factory.tuple("2"))); + bounds.boundExactly(3, factory.range(factory.tuple("3"), factory.tuple("3"))); + bounds.boundExactly(4, factory.range(factory.tuple("4"), factory.tuple("4"))); + bounds.boundExactly(5, factory.range(factory.tuple("5"), factory.tuple("5"))); + bounds.boundExactly(6, factory.range(factory.tuple("6"), factory.tuple("6"))); + bounds.boundExactly(7, factory.range(factory.tuple("7"), factory.tuple("7"))); + + Variable x12 = Variable.unary("this"); + Decls x11 = x12.oneOf(x7); + Expression x16 = x12.join(x8); + Expression x19 = x6.product(x6); + Expression x18 = x6.product(x19); + Expression x17 = x6.product(x18); + Formula x15 = x16.in(x17); + Variable x22 = Variable.unary("x22"); + Decls x21 = x22.oneOf(x6); + Expression x26 = x22.join(x16); + Expression x28 = x6.product(x6); + Expression x27 = x6.product(x28); + Formula x25 = x26.in(x27); + Variable x31 = Variable.unary("x31"); + Decls x30 = x31.oneOf(x6); + Expression x35 = x31.join(x26); + Expression x36 = x6.product(x6); + Formula x34 = x35.in(x36); + Variable x39 = Variable.unary("x39"); + Decls x38 = x39.oneOf(x6); + Expression x42 = x39.join(x35); + Formula x41 = x42.one(); + Formula x43 = x42.in(x6); + Formula x40 = x41.and(x43); + Formula x37 = x40.forAll(x38); + Formula x33 = x34.and(x37); + Variable x46 = Variable.unary("x46"); + Decls x45 = x46.oneOf(x6); + Expression x48 = x35.join(x46); + Formula x47 = x48.in(x6); + Formula x44 = x47.forAll(x45); + Formula x32 = x33.and(x44); + Formula x29 = x32.forAll(x30); + Formula x24 = x25.and(x29); + Variable x52 = Variable.unary("x52"); + Decls x51 = x52.oneOf(x6); + Variable x55 = Variable.unary("x55"); + Decls x54 = x55.oneOf(x6); + Decls x50 = x51.and(x54); + Expression x60 = x52.product(x55); + Expression x61 = x6.product(x6); + Formula x59 = x60.in(x61); + Variable x64 = Variable.unary("x64"); + Decls x63 = x64.oneOf(x6); + Expression x67 = x64.join(x60); + Formula x66 = x67.one(); + Formula x68 = x67.in(x6); + Formula x65 = x66.and(x68); + Formula x62 = x65.forAll(x63); + Formula x58 = x59.and(x62); + Variable x71 = Variable.unary("x71"); + Decls x70 = x71.oneOf(x6); + Expression x73 = x60.join(x71); + Formula x72 = x73.in(x6); + Formula x69 = x72.forAll(x70); + Formula x57 = x58.and(x69); + Expression x76 = x26.join(x55); + Expression x75 = x76.join(x52); + Formula x74 = x75.in(x6); + Formula x56 = x57.implies(x74); + Formula x49 = x56.forAll(x50); + Formula x23 = x24.and(x49); + Formula x20 = x23.forAll(x21); + Formula x14 = x15.and(x20); + Variable x80 = Variable.unary("x80"); + Decls x79 = x80.oneOf(x6); + Variable x82 = Variable.unary("x82"); + Decls x81 = x82.oneOf(x6); + Variable x84 = Variable.unary("x84"); + Decls x83 = x84.oneOf(x6); + Decls x78 = x79.and(x81).and(x83); + Expression x90 = x82.product(x84); + Expression x89 = x80.product(x90); + Expression x92 = x6.product(x6); + Expression x91 = x6.product(x92); + Formula x88 = x89.in(x91); + Variable x95 = Variable.unary("x95"); + Decls x94 = x95.oneOf(x6); + Expression x99 = x95.join(x89); + Expression x100 = x6.product(x6); + Formula x98 = x99.in(x100); + Variable x103 = Variable.unary("x103"); + Decls x102 = x103.oneOf(x6); + Expression x106 = x103.join(x99); + Formula x105 = x106.one(); + Formula x107 = x106.in(x6); + Formula x104 = x105.and(x107); + Formula x101 = x104.forAll(x102); + Formula x97 = x98.and(x101); + Variable x110 = Variable.unary("x110"); + Decls x109 = x110.oneOf(x6); + Expression x112 = x99.join(x110); + Formula x111 = x112.in(x6); + Formula x108 = x111.forAll(x109); + Formula x96 = x97.and(x108); + Formula x93 = x96.forAll(x94); + Formula x87 = x88.and(x93); + Variable x116 = Variable.unary("x116"); + Decls x115 = x116.oneOf(x6); + Variable x118 = Variable.unary("x118"); + Decls x117 = x118.oneOf(x6); + Decls x114 = x115.and(x117); + Expression x123 = x116.product(x118); + Expression x124 = x6.product(x6); + Formula x122 = x123.in(x124); + Variable x127 = Variable.unary("x127"); + Decls x126 = x127.oneOf(x6); + Expression x130 = x127.join(x123); + Formula x129 = x130.one(); + Formula x131 = x130.in(x6); + Formula x128 = x129.and(x131); + Formula x125 = x128.forAll(x126); + Formula x121 = x122.and(x125); + Variable x134 = Variable.unary("x134"); + Decls x133 = x134.oneOf(x6); + Expression x136 = x123.join(x134); + Formula x135 = x136.in(x6); + Formula x132 = x135.forAll(x133); + Formula x120 = x121.and(x132); + Expression x139 = x89.join(x118); + Expression x138 = x139.join(x116); + Formula x137 = x138.in(x6); + Formula x119 = x120.implies(x137); + Formula x113 = x119.forAll(x114); + Formula x86 = x87.and(x113); + Expression x143 = x16.join(x84); + Expression x142 = x143.join(x82); + Expression x141 = x142.join(x80); + Formula x140 = x141.in(x6); + Formula x85 = x86.implies(x140); + Formula x77 = x85.forAll(x78); + Formula x13 = x14.and(x77); + Formula x10 = x13.forAll(x11); + Expression x148 = x8.join(Expression.UNIV); + Expression x147 = x148.join(Expression.UNIV); + Expression x146 = x147.join(Expression.UNIV); + Expression x145 = x146.join(Expression.UNIV); + Formula x144 = x145.in(x7); + Formula x149 = x0.eq(x0); + Formula x150 = x1.eq(x1); + Formula x151 = x2.eq(x2); + Formula x152 = x3.eq(x3); + Formula x153 = x4.eq(x4); + Formula x154 = x5.eq(x5); + Formula x155 = x6.eq(x6); + Formula x156 = x7.eq(x7); + Formula x157 = x8.eq(x8); + Formula x9 = Formula.compose(FormulaOperator.AND, x10, x144, x149, x150, x151, x152, x153, + x154, x155, x156, x157); + + Solver solver = new Solver(); + solver.options().setSolver(SATFactory.DefaultSAT4J); + solver.options().setBitwidth(4); + solver.options().setFlatten(false); + solver.options().setIntEncoding(Options.IntEncoding.TWOSCOMPLEMENT); + solver.options().setSymmetryBreaking(20); + solver.options().setSkolemDepth(0); + + System.out.println(PrettyPrinter.print(x9, 0)); + + System.out.println("Solving..."); + System.out.flush(); + Solution sol = solver.solve(x9, bounds); + System.out.println(sol.toString()); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/tmp/TestSmallFast.java b/Source/eu.modelwriter.alloyanalyzer/src/tmp/TestSmallFast.java new file mode 100644 index 00000000..9e89d3c2 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/tmp/TestSmallFast.java @@ -0,0 +1,328 @@ +package tmp; +import java.util.Arrays; +import java.util.List; +import kodkod.ast.*; +import kodkod.ast.operator.*; +import kodkod.instance.*; +import kodkod.util.nodes.PrettyPrinter; +import kodkod.engine.*; +import kodkod.engine.satlab.SATFactory; +import kodkod.engine.config.Options; + +public final class TestSmallFast { + + public static void main(String[] args) throws Exception { + + Relation x0 = Relation.unary("Int/min"); + Relation x1 = Relation.unary("Int/zero"); + Relation x2 = Relation.unary("Int/max"); + Relation x3 = Relation.nary("Int/next", 2); + Relation x4 = Relation.unary("seq/Int"); + Relation x5 = Relation.unary("String"); + Relation x6 = Relation.unary("this/A"); + Relation x7 = Relation.unary("this/Relation"); + Relation x8 = Relation.nary("this/Relation.r", 4); + + List atomlist = Arrays.asList("-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "0", + "1", "2", "3", "4", "5", "6", "7", "A$0", "A$1", "A$2", "Relation$0", "Relation$1", + "Relation$2"); + + Universe universe = new Universe(atomlist); + TupleFactory factory = universe.factory(); + Bounds bounds = new Bounds(universe); + + TupleSet x0_upper = factory.noneOf(1); + x0_upper.add(factory.tuple("-8")); + bounds.boundExactly(x0, x0_upper); + + TupleSet x1_upper = factory.noneOf(1); + x1_upper.add(factory.tuple("0")); + bounds.boundExactly(x1, x1_upper); + + TupleSet x2_upper = factory.noneOf(1); + x2_upper.add(factory.tuple("7")); + bounds.boundExactly(x2, x2_upper); + + TupleSet x3_upper = factory.noneOf(2); + x3_upper.add(factory.tuple("-8").product(factory.tuple("-7"))); + x3_upper.add(factory.tuple("-7").product(factory.tuple("-6"))); + x3_upper.add(factory.tuple("-6").product(factory.tuple("-5"))); + x3_upper.add(factory.tuple("-5").product(factory.tuple("-4"))); + x3_upper.add(factory.tuple("-4").product(factory.tuple("-3"))); + x3_upper.add(factory.tuple("-3").product(factory.tuple("-2"))); + x3_upper.add(factory.tuple("-2").product(factory.tuple("-1"))); + x3_upper.add(factory.tuple("-1").product(factory.tuple("0"))); + x3_upper.add(factory.tuple("0").product(factory.tuple("1"))); + x3_upper.add(factory.tuple("1").product(factory.tuple("2"))); + x3_upper.add(factory.tuple("2").product(factory.tuple("3"))); + x3_upper.add(factory.tuple("3").product(factory.tuple("4"))); + x3_upper.add(factory.tuple("4").product(factory.tuple("5"))); + x3_upper.add(factory.tuple("5").product(factory.tuple("6"))); + x3_upper.add(factory.tuple("6").product(factory.tuple("7"))); + bounds.boundExactly(x3, x3_upper); + + TupleSet x4_upper = factory.noneOf(1); + x4_upper.add(factory.tuple("0")); + x4_upper.add(factory.tuple("1")); + x4_upper.add(factory.tuple("2")); + bounds.boundExactly(x4, x4_upper); + + TupleSet x5_upper = factory.noneOf(1); + bounds.boundExactly(x5, x5_upper); + + TupleSet x6_upper = factory.noneOf(1); + x6_upper.add(factory.tuple("A$0")); + x6_upper.add(factory.tuple("A$1")); + x6_upper.add(factory.tuple("A$2")); + bounds.boundExactly(x6, x6_upper); + + TupleSet x7_upper = factory.noneOf(1); + x7_upper.add(factory.tuple("Relation$0")); + x7_upper.add(factory.tuple("Relation$1")); + x7_upper.add(factory.tuple("Relation$2")); + bounds.boundExactly(x7, x7_upper); + + TupleSet x8_upper = factory.noneOf(4); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$0")).product( + factory.tuple("A$0")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$0")).product( + factory.tuple("A$0")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$0")).product( + factory.tuple("A$0")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$0")).product( + factory.tuple("A$1")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$0")).product( + factory.tuple("A$1")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$0")).product( + factory.tuple("A$1")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$0")).product( + factory.tuple("A$2")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$0")).product( + factory.tuple("A$2")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$0")).product( + factory.tuple("A$2")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$1")).product( + factory.tuple("A$0")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$1")).product( + factory.tuple("A$0")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$1")).product( + factory.tuple("A$0")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$1")).product( + factory.tuple("A$1")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$1")).product( + factory.tuple("A$1")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$1")).product( + factory.tuple("A$1")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$1")).product( + factory.tuple("A$2")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$1")).product( + factory.tuple("A$2")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$1")).product( + factory.tuple("A$2")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$2")).product( + factory.tuple("A$0")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$2")).product( + factory.tuple("A$0")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$2")).product( + factory.tuple("A$0")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$2")).product( + factory.tuple("A$1")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$2")).product( + factory.tuple("A$1")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$2")).product( + factory.tuple("A$1")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$2")).product( + factory.tuple("A$2")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$2")).product( + factory.tuple("A$2")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$2")).product( + factory.tuple("A$2")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$0")).product( + factory.tuple("A$0")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$0")).product( + factory.tuple("A$0")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$0")).product( + factory.tuple("A$0")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$0")).product( + factory.tuple("A$1")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$0")).product( + factory.tuple("A$1")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$0")).product( + factory.tuple("A$1")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$0")).product( + factory.tuple("A$2")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$0")).product( + factory.tuple("A$2")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$0")).product( + factory.tuple("A$2")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$1")).product( + factory.tuple("A$0")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$1")).product( + factory.tuple("A$0")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$1")).product( + factory.tuple("A$0")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$1")).product( + factory.tuple("A$1")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$1")).product( + factory.tuple("A$1")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$1")).product( + factory.tuple("A$1")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$1")).product( + factory.tuple("A$2")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$1")).product( + factory.tuple("A$2")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$1")).product( + factory.tuple("A$2")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$2")).product( + factory.tuple("A$0")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$2")).product( + factory.tuple("A$0")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$2")).product( + factory.tuple("A$0")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$2")).product( + factory.tuple("A$1")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$2")).product( + factory.tuple("A$1")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$2")).product( + factory.tuple("A$1")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$2")).product( + factory.tuple("A$2")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$2")).product( + factory.tuple("A$2")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$1").product(factory.tuple("A$2")).product( + factory.tuple("A$2")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$0")).product( + factory.tuple("A$0")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$0")).product( + factory.tuple("A$0")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$0")).product( + factory.tuple("A$0")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$0")).product( + factory.tuple("A$1")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$0")).product( + factory.tuple("A$1")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$0")).product( + factory.tuple("A$1")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$0")).product( + factory.tuple("A$2")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$0")).product( + factory.tuple("A$2")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$0")).product( + factory.tuple("A$2")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$1")).product( + factory.tuple("A$0")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$1")).product( + factory.tuple("A$0")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$1")).product( + factory.tuple("A$0")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$1")).product( + factory.tuple("A$1")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$1")).product( + factory.tuple("A$1")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$1")).product( + factory.tuple("A$1")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$1")).product( + factory.tuple("A$2")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$1")).product( + factory.tuple("A$2")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$1")).product( + factory.tuple("A$2")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$2")).product( + factory.tuple("A$0")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$2")).product( + factory.tuple("A$0")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$2")).product( + factory.tuple("A$0")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$2")).product( + factory.tuple("A$1")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$2")).product( + factory.tuple("A$1")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$2")).product( + factory.tuple("A$1")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$2")).product( + factory.tuple("A$2")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$2")).product( + factory.tuple("A$2")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$2").product(factory.tuple("A$2")).product( + factory.tuple("A$2")).product(factory.tuple("A$2"))); + bounds.bound(x8, x8_upper); + + bounds.boundExactly(-8, factory.range(factory.tuple("-8"), factory.tuple("-8"))); + bounds.boundExactly(-7, factory.range(factory.tuple("-7"), factory.tuple("-7"))); + bounds.boundExactly(-6, factory.range(factory.tuple("-6"), factory.tuple("-6"))); + bounds.boundExactly(-5, factory.range(factory.tuple("-5"), factory.tuple("-5"))); + bounds.boundExactly(-4, factory.range(factory.tuple("-4"), factory.tuple("-4"))); + bounds.boundExactly(-3, factory.range(factory.tuple("-3"), factory.tuple("-3"))); + bounds.boundExactly(-2, factory.range(factory.tuple("-2"), factory.tuple("-2"))); + bounds.boundExactly(-1, factory.range(factory.tuple("-1"), factory.tuple("-1"))); + bounds.boundExactly(0, factory.range(factory.tuple("0"), factory.tuple("0"))); + bounds.boundExactly(1, factory.range(factory.tuple("1"), factory.tuple("1"))); + bounds.boundExactly(2, factory.range(factory.tuple("2"), factory.tuple("2"))); + bounds.boundExactly(3, factory.range(factory.tuple("3"), factory.tuple("3"))); + bounds.boundExactly(4, factory.range(factory.tuple("4"), factory.tuple("4"))); + bounds.boundExactly(5, factory.range(factory.tuple("5"), factory.tuple("5"))); + bounds.boundExactly(6, factory.range(factory.tuple("6"), factory.tuple("6"))); + bounds.boundExactly(7, factory.range(factory.tuple("7"), factory.tuple("7"))); + + Variable x12 = Variable.unary("this"); + Decls x11 = x12.oneOf(x7); + Expression x16 = x12.join(x8); + Expression x18 = x6.product(x6); + Expression x17 = x18.product(x6); + Formula x15 = x16.in(x17); + Variable x22 = Variable.unary("x22"); + Decls x21 = x22.oneOf(Expression.UNIV); + Variable x25 = Variable.unary("x25"); + Decls x24 = x25.oneOf(Expression.UNIV); + Decls x20 = x21.and(x24); + Expression x28 = x25.product(x22); + Expression x29 = x6.product(x6); + Formula x27 = x28.in(x29); + Expression x33 = x25.join(x16); + Expression x32 = x22.join(x33); + Formula x31 = x32.one(); + Formula x34 = x32.in(x6); + Formula x30 = x31.and(x34); + Formula x26 = x27.implies(x30); + Formula x19 = x26.forAll(x20); + Formula x14 = x15.and(x19); + Variable x37 = Variable.unary("x37"); + Decls x36 = x37.oneOf(x6); + Expression x39 = x16.join(x37); + Expression x40 = x6.product(x6); + Formula x38 = x39.in(x40); + Formula x35 = x38.forAll(x36); + Formula x13 = x14.and(x35); + Formula x10 = x13.forAll(x11); + Expression x44 = x8.join(Expression.UNIV); + Expression x43 = x44.join(Expression.UNIV); + Expression x42 = x43.join(Expression.UNIV); + Formula x41 = x42.in(x7); + Formula x45 = x0.eq(x0); + Formula x46 = x1.eq(x1); + Formula x47 = x2.eq(x2); + Formula x48 = x3.eq(x3); + Formula x49 = x4.eq(x4); + Formula x50 = x5.eq(x5); + Formula x51 = x6.eq(x6); + Formula x52 = x7.eq(x7); + Formula x53 = x8.eq(x8); + Formula x9 = Formula.compose(FormulaOperator.AND, x10, x41, x45, x46, x47, x48, x49, x50, + x51, x52, x53); + + Solver solver = new Solver(); + solver.options().setSolver(SATFactory.DefaultSAT4J); + solver.options().setBitwidth(4); + solver.options().setFlatten(false); + solver.options().setIntEncoding(Options.IntEncoding.TWOSCOMPLEMENT); + solver.options().setSymmetryBreaking(20); + solver.options().setSkolemDepth(0); + + System.out.println(PrettyPrinter.print(x9, 0)); + + System.out.println("Solving..."); + System.out.flush(); + Solution sol = solver.solve(x9, bounds); + System.out.println(sol.toString()); + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/tmp/TestSmallSlow.java b/Source/eu.modelwriter.alloyanalyzer/src/tmp/TestSmallSlow.java new file mode 100644 index 00000000..2826fb8b --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/tmp/TestSmallSlow.java @@ -0,0 +1,374 @@ +package tmp; +import java.util.Arrays; +import java.util.List; +import kodkod.ast.*; +import kodkod.ast.operator.*; +import kodkod.instance.*; +import kodkod.util.nodes.PrettyPrinter; +import kodkod.engine.*; +import kodkod.engine.satlab.SATFactory; +import kodkod.engine.config.Options; + +public final class TestSmallSlow { + + public static void main(String[] args) throws Exception { + + Relation x0 = Relation.unary("Int/min"); + Relation x1 = Relation.unary("Int/zero"); + Relation x2 = Relation.unary("Int/max"); + Relation x3 = Relation.nary("Int/next", 2); + Relation x4 = Relation.unary("seq/Int"); + Relation x5 = Relation.unary("String"); + Relation x6 = Relation.unary("this/A"); + Relation x7 = Relation.unary("this/Relation"); + Relation x8 = Relation.nary("this/Relation.r", 4); + + List atomlist = Arrays.asList("-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "0", + "1", "2", "3", "4", "5", "6", "7", "A$0", "A$1", "A$2", "Relation$0", "unused0", + "unused1"); + + Universe universe = new Universe(atomlist); + TupleFactory factory = universe.factory(); + Bounds bounds = new Bounds(universe); + + TupleSet x0_upper = factory.noneOf(1); + x0_upper.add(factory.tuple("-8")); + bounds.boundExactly(x0, x0_upper); + + TupleSet x1_upper = factory.noneOf(1); + x1_upper.add(factory.tuple("0")); + bounds.boundExactly(x1, x1_upper); + + TupleSet x2_upper = factory.noneOf(1); + x2_upper.add(factory.tuple("7")); + bounds.boundExactly(x2, x2_upper); + + TupleSet x3_upper = factory.noneOf(2); + x3_upper.add(factory.tuple("-8").product(factory.tuple("-7"))); + x3_upper.add(factory.tuple("-7").product(factory.tuple("-6"))); + x3_upper.add(factory.tuple("-6").product(factory.tuple("-5"))); + x3_upper.add(factory.tuple("-5").product(factory.tuple("-4"))); + x3_upper.add(factory.tuple("-4").product(factory.tuple("-3"))); + x3_upper.add(factory.tuple("-3").product(factory.tuple("-2"))); + x3_upper.add(factory.tuple("-2").product(factory.tuple("-1"))); + x3_upper.add(factory.tuple("-1").product(factory.tuple("0"))); + x3_upper.add(factory.tuple("0").product(factory.tuple("1"))); + x3_upper.add(factory.tuple("1").product(factory.tuple("2"))); + x3_upper.add(factory.tuple("2").product(factory.tuple("3"))); + x3_upper.add(factory.tuple("3").product(factory.tuple("4"))); + x3_upper.add(factory.tuple("4").product(factory.tuple("5"))); + x3_upper.add(factory.tuple("5").product(factory.tuple("6"))); + x3_upper.add(factory.tuple("6").product(factory.tuple("7"))); + bounds.boundExactly(x3, x3_upper); + + TupleSet x4_upper = factory.noneOf(1); + x4_upper.add(factory.tuple("0")); + x4_upper.add(factory.tuple("1")); + x4_upper.add(factory.tuple("2")); + bounds.boundExactly(x4, x4_upper); + + TupleSet x5_upper = factory.noneOf(1); + bounds.boundExactly(x5, x5_upper); + + TupleSet x6_upper = factory.noneOf(1); + x6_upper.add(factory.tuple("A$0")); + x6_upper.add(factory.tuple("A$1")); + x6_upper.add(factory.tuple("A$2")); + bounds.boundExactly(x6, x6_upper); + + TupleSet x7_upper = factory.noneOf(1); + x7_upper.add(factory.tuple("unused0")); + x7_upper.add(factory.tuple("unused1")); + x7_upper.add(factory.tuple("Relation$0")); + bounds.bound(x7, x7_upper); + + TupleSet x8_upper = factory.noneOf(4); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$0")).product( + factory.tuple("A$0")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$0")).product( + factory.tuple("A$0")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$0")).product( + factory.tuple("A$0")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$0")).product( + factory.tuple("A$1")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$0")).product( + factory.tuple("A$1")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$0")).product( + factory.tuple("A$1")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$0")).product( + factory.tuple("A$2")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$0")).product( + factory.tuple("A$2")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$0")).product( + factory.tuple("A$2")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$1")).product( + factory.tuple("A$0")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$1")).product( + factory.tuple("A$0")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$1")).product( + factory.tuple("A$0")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$1")).product( + factory.tuple("A$1")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$1")).product( + factory.tuple("A$1")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$1")).product( + factory.tuple("A$1")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$1")).product( + factory.tuple("A$2")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$1")).product( + factory.tuple("A$2")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$1")).product( + factory.tuple("A$2")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$2")).product( + factory.tuple("A$0")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$2")).product( + factory.tuple("A$0")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$2")).product( + factory.tuple("A$0")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$2")).product( + factory.tuple("A$1")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$2")).product( + factory.tuple("A$1")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$2")).product( + factory.tuple("A$1")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$2")).product( + factory.tuple("A$2")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$2")).product( + factory.tuple("A$2")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("unused0").product(factory.tuple("A$2")).product( + factory.tuple("A$2")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$0")).product( + factory.tuple("A$0")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$0")).product( + factory.tuple("A$0")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$0")).product( + factory.tuple("A$0")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$0")).product( + factory.tuple("A$1")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$0")).product( + factory.tuple("A$1")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$0")).product( + factory.tuple("A$1")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$0")).product( + factory.tuple("A$2")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$0")).product( + factory.tuple("A$2")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$0")).product( + factory.tuple("A$2")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$1")).product( + factory.tuple("A$0")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$1")).product( + factory.tuple("A$0")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$1")).product( + factory.tuple("A$0")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$1")).product( + factory.tuple("A$1")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$1")).product( + factory.tuple("A$1")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$1")).product( + factory.tuple("A$1")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$1")).product( + factory.tuple("A$2")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$1")).product( + factory.tuple("A$2")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$1")).product( + factory.tuple("A$2")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$2")).product( + factory.tuple("A$0")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$2")).product( + factory.tuple("A$0")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$2")).product( + factory.tuple("A$0")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$2")).product( + factory.tuple("A$1")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$2")).product( + factory.tuple("A$1")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$2")).product( + factory.tuple("A$1")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$2")).product( + factory.tuple("A$2")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$2")).product( + factory.tuple("A$2")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("unused1").product(factory.tuple("A$2")).product( + factory.tuple("A$2")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$0")).product( + factory.tuple("A$0")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$0")).product( + factory.tuple("A$0")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$0")).product( + factory.tuple("A$0")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$0")).product( + factory.tuple("A$1")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$0")).product( + factory.tuple("A$1")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$0")).product( + factory.tuple("A$1")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$0")).product( + factory.tuple("A$2")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$0")).product( + factory.tuple("A$2")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$0")).product( + factory.tuple("A$2")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$1")).product( + factory.tuple("A$0")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$1")).product( + factory.tuple("A$0")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$1")).product( + factory.tuple("A$0")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$1")).product( + factory.tuple("A$1")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$1")).product( + factory.tuple("A$1")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$1")).product( + factory.tuple("A$1")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$1")).product( + factory.tuple("A$2")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$1")).product( + factory.tuple("A$2")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$1")).product( + factory.tuple("A$2")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$2")).product( + factory.tuple("A$0")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$2")).product( + factory.tuple("A$0")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$2")).product( + factory.tuple("A$0")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$2")).product( + factory.tuple("A$1")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$2")).product( + factory.tuple("A$1")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$2")).product( + factory.tuple("A$1")).product(factory.tuple("A$2"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$2")).product( + factory.tuple("A$2")).product(factory.tuple("A$0"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$2")).product( + factory.tuple("A$2")).product(factory.tuple("A$1"))); + x8_upper.add(factory.tuple("Relation$0").product(factory.tuple("A$2")).product( + factory.tuple("A$2")).product(factory.tuple("A$2"))); + bounds.bound(x8, x8_upper); + + bounds.boundExactly(-8, factory.range(factory.tuple("-8"), factory.tuple("-8"))); + bounds.boundExactly(-7, factory.range(factory.tuple("-7"), factory.tuple("-7"))); + bounds.boundExactly(-6, factory.range(factory.tuple("-6"), factory.tuple("-6"))); + bounds.boundExactly(-5, factory.range(factory.tuple("-5"), factory.tuple("-5"))); + bounds.boundExactly(-4, factory.range(factory.tuple("-4"), factory.tuple("-4"))); + bounds.boundExactly(-3, factory.range(factory.tuple("-3"), factory.tuple("-3"))); + bounds.boundExactly(-2, factory.range(factory.tuple("-2"), factory.tuple("-2"))); + bounds.boundExactly(-1, factory.range(factory.tuple("-1"), factory.tuple("-1"))); + bounds.boundExactly(0, factory.range(factory.tuple("0"), factory.tuple("0"))); + bounds.boundExactly(1, factory.range(factory.tuple("1"), factory.tuple("1"))); + bounds.boundExactly(2, factory.range(factory.tuple("2"), factory.tuple("2"))); + bounds.boundExactly(3, factory.range(factory.tuple("3"), factory.tuple("3"))); + bounds.boundExactly(4, factory.range(factory.tuple("4"), factory.tuple("4"))); + bounds.boundExactly(5, factory.range(factory.tuple("5"), factory.tuple("5"))); + bounds.boundExactly(6, factory.range(factory.tuple("6"), factory.tuple("6"))); + bounds.boundExactly(7, factory.range(factory.tuple("7"), factory.tuple("7"))); + + Variable x12 = Variable.unary("this"); + Decls x11 = x12.oneOf(x7); + Expression x16 = x12.join(x8); + Expression x18 = x6.product(x6); + Expression x17 = x6.product(x18); + Formula x15 = x16.in(x17); + Variable x21 = Variable.unary("x21"); + Decls x20 = x21.oneOf(x6); + Expression x25 = x21.join(x16); + Expression x26 = x6.product(x6); + Formula x24 = x25.in(x26); + Variable x29 = Variable.unary("x29"); + Decls x28 = x29.oneOf(x6); + Expression x32 = x29.join(x25); + Formula x31 = x32.one(); + Formula x33 = x32.in(x6); + Formula x30 = x31.and(x33); + Formula x27 = x30.forAll(x28); + Formula x23 = x24.and(x27); + Variable x36 = Variable.unary("x36"); + Decls x35 = x36.oneOf(x6); + Expression x38 = x25.join(x36); + Formula x37 = x38.in(x6); + Formula x34 = x37.forAll(x35); + Formula x22 = x23.and(x34); + Formula x19 = x22.forAll(x20); + Formula x14 = x15.and(x19); + Variable x42 = Variable.unary("x42"); + Decls x41 = x42.oneOf(Expression.UNIV); + Variable x45 = Variable.unary("x45"); + Decls x44 = x45.oneOf(Expression.UNIV); + Decls x40 = x41.and(x44); + Expression x50 = x42.product(x45); + Expression x51 = x6.product(x6); + Formula x49 = x50.in(x51); + Variable x54 = Variable.unary("x54"); + Decls x53 = x54.oneOf(x6); + Expression x57 = x54.join(x50); + Formula x56 = x57.one(); + Formula x58 = x57.in(x6); + Formula x55 = x56.and(x58); + Formula x52 = x55.forAll(x53); + Formula x48 = x49.and(x52); + Variable x61 = Variable.unary("x61"); + Decls x60 = x61.oneOf(x6); + Expression x63 = x50.join(x61); + Formula x62 = x63.in(x6); + Formula x59 = x62.forAll(x60); + Formula x47 = x48.and(x59); + Expression x66 = x16.join(x45); + Expression x65 = x66.join(x42); + Formula x64 = x65.in(x6); + Formula x46 = x47.implies(x64); + Formula x39 = x46.forAll(x40); + Formula x13 = x14.and(x39); + Formula x10 = x13.forAll(x11); + Expression x70 = x8.join(Expression.UNIV); + Expression x69 = x70.join(Expression.UNIV); + Expression x68 = x69.join(Expression.UNIV); + Formula x67 = x68.in(x7); + Formula x71 = x0.eq(x0); + Formula x72 = x1.eq(x1); + Formula x73 = x2.eq(x2); + Formula x74 = x3.eq(x3); + Formula x75 = x4.eq(x4); + Formula x76 = x5.eq(x5); + Formula x77 = x6.eq(x6); + Formula x78 = x7.eq(x7); + Formula x79 = x8.eq(x8); + Formula x9 = Formula.compose(FormulaOperator.AND, x10, x67, x71, x72, x73, x74, x75, x76, + x77, x78, x79); + + Solver solver = new Solver(); + solver.options().setSolver(SATFactory.DefaultSAT4J); + solver.options().setBitwidth(4); + solver.options().setFlatten(false); + solver.options().setIntEncoding(Options.IntEncoding.TWOSCOMPLEMENT); + solver.options().setSymmetryBreaking(20); + solver.options().setSkolemDepth(0); + + System.out.println(PrettyPrinter.print(x9, 0)); + System.out.println(bounds); + + System.out.println("Solving..."); + System.out.flush(); + Solution sol = solver.solve(x9, bounds); + System.out.println(sol.toString()); + + Instance inst = sol.instance(); + Evaluator ev = new Evaluator(inst); + + System.out.println("Universe: " + ev.evaluate(Expression.UNIV)); + Formula xx = x46.forAll(x40).forAll(x11); + System.out.println(PrettyPrinter.print(xx, 2)); + System.out.println(ev.evaluate(xx)); + + System.out.println(PrettyPrinter.print(x46, 4)); + +// Variable r = Variable.unary("this"); +// Variable u1 = Variable.unary("u1"); +// Variable u2 = Variable.unary("u2"); +// +// Formula ff = u1.product(u2).in(x6.product(x6)).forAll(u1.oneOf(Expression.UNIV).and(u2.oneOf(Expression.UNIV))).forAll(r.oneOf(x7)); +// System.out.println(PrettyPrinter.print(ff, 0)); +// System.out.println(ev.evaluate(ff)); + + } +} diff --git a/Source/eu.modelwriter.alloyanalyzer/src/tmp/TestXml.java b/Source/eu.modelwriter.alloyanalyzer/src/tmp/TestXml.java new file mode 100644 index 00000000..ed602823 --- /dev/null +++ b/Source/eu.modelwriter.alloyanalyzer/src/tmp/TestXml.java @@ -0,0 +1,243 @@ +package tmp; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.prefs.Preferences; + +import javax.swing.JDialog; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.Computer; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.Util.BooleanPref; +import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.alloy4.XMLNode; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; +import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil; +import edu.mit.csail.sdg.alloy4compiler.sim.SimInstance; +import edu.mit.csail.sdg.alloy4compiler.sim.SimTuple; +import edu.mit.csail.sdg.alloy4compiler.sim.SimTupleset; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.A4SolutionReader; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Tuple; +import edu.mit.csail.sdg.alloy4compiler.translator.A4TupleSet; +import edu.mit.csail.sdg.alloy4viz.AlloyInstance; +import edu.mit.csail.sdg.alloy4viz.StaticInstanceReader; +import edu.mit.csail.sdg.alloy4viz.VizGUI; +import edu.mit.csail.sdg.alloy4viz.VizGraphPanel; +import edu.mit.csail.sdg.alloy4viz.VizState; +import kodkod.engine.fol2sat.HigherOrderDeclException; + +public class TestXml { + + private static final BooleanPref ImplicitThis = new BooleanPref("ImplicitThis"); + // static String filename = "C:\\Users\\3\\Desktop\\Alloyyy\\alloyXmlSample.xml"; + // C:\\Users\\Mete\\runtime-EclipseApplication\\.modelwriter\\persistance.xml + static String filename = + "C:\\Users\\Mete\\runtime-EclipseApplication\\.modelwriter\\persistence.xml"; + + public static void showViz() { + final String xmlFileName = Util.canon(filename); + File f = new File(xmlFileName); + AlloyInstance myInstance = null; + try { + if (!f.exists()) + throw new IOException("File " + xmlFileName + " does not exist."); + myInstance = StaticInstanceReader.parseInstance(f); + } catch (Err e1) { + + e1.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + VizState myState = null; + + myState = new VizState(myInstance); + + VizGraphPanel graph = new VizGraphPanel(myState, false); + JDialog dialog = new JDialog(); + dialog.add(graph); + dialog.setVisible(true); + dialog.pack(); + + } + + + public static void main(String[] args) { + + // VizGUI gui = new VizGUI(false, filename, null); + // gui.loadXML(filename, false); + + showViz(); + + Computer evaluator = new Computer() { + // private String filename = null; + + public final String compute(final Object input) throws Exception { + // if (input instanceof File) { + // filename = ((File) input).getAbsolutePath(); + // return ""; + // } + if (!(input instanceof String)) + return ""; + final String str = (String) input; + if (str.trim().length() == 0) + return ""; // Empty line + Module root = null; + A4Solution ans = null; + try { + Map fc = new LinkedHashMap(); + XMLNode x = new XMLNode(new File(filename)); + if (!x.is("alloy")) + throw new Exception(); + String mainname = null; + for (XMLNode sub : x) + if (sub.is("instance")) { + mainname = sub.getAttribute("filename"); + break; + } + if (mainname == null) + throw new Exception(); + for (XMLNode sub : x) + if (sub.is("source")) { + String name = sub.getAttribute("filename"); + String content = sub.getAttribute("content"); + fc.put(name, content); + } + root = CompUtil.parseEverything_fromFile(A4Reporter.NOP, fc, mainname, + (Version.experimental && ImplicitThis.get()) ? 2 : 1); + ans = A4SolutionReader.read(root.getAllReachableSigs(), x); + for (ExprVar a : ans.getAllAtoms()) { + root.addGlobal(a.label, a); + } + for (ExprVar a : ans.getAllSkolems()) { + root.addGlobal(a.label, a); + } + } catch (Throwable ex) { + throw new ErrorFatal("Failed to read or parse the XML file."); + } + try { + Expr e = CompUtil.parseOneExpression_fromString(root, str); + if ("yes".equals(System.getProperty("debug")) && Verbosity.get() == Verbosity.FULLDEBUG) { + SimInstance simInst = convert(root, ans); + return simInst.visitThis(e).toString() + (simInst.wasOverflow() ? " (OF)" : ""); + } else + return ans.eval(e).toString(); + } catch (HigherOrderDeclException ex) { + throw new ErrorType("Higher-order quantification is not allowed in the evaluator."); + } + } + }; + + VizGUI gui = new VizGUI(false, filename, null, null, evaluator); + try { + String str = evaluator.compute("eClassifiers"); + + System.out.println(str); + } catch (Exception e) { + + e.printStackTrace(); + } + } + + private static SimTupleset convert(Object object) throws Err { + if (!(object instanceof A4TupleSet)) + throw new ErrorFatal("Unexpected type error: expecting an A4TupleSet."); + A4TupleSet s = (A4TupleSet) object; + if (s.size() == 0) + return SimTupleset.EMPTY; + List list = new ArrayList(s.size()); + int arity = s.arity(); + for (A4Tuple t : s) { + String[] array = new String[arity]; + for (int i = 0; i < t.arity(); i++) + array[i] = t.atom(i); + list.add(SimTuple.make(array)); + } + return SimTupleset.make(list); + } + + private static SimInstance convert(Module root, A4Solution ans) throws Err { + SimInstance ct = new SimInstance(root, ans.getBitwidth(), ans.getMaxSeq()); + for (Sig s : ans.getAllReachableSigs()) { + if (!s.builtin) + ct.init(s, convert(ans.eval(s))); + for (Field f : s.getFields()) + if (!f.defined) + ct.init(f, convert(ans.eval(f))); + } + for (ExprVar a : ans.getAllAtoms()) + ct.init(a, convert(ans.eval(a))); + for (ExprVar a : ans.getAllSkolems()) + ct.init(a, convert(ans.eval(a))); + return ct; + } + + private enum Verbosity { + /** Level 0. */ + DEFAULT("0", "low"), + /** Level 1. */ + VERBOSE("1", "medium"), + /** Level 2. */ + DEBUG("2", "high"), + /** Level 3. */ + FULLDEBUG("3", "debug only"); + /** Returns true if it is greater than or equal to "other". */ + public boolean geq(Verbosity other) { + return ordinal() >= other.ordinal(); + } + + /** This is a unique String for this value; it should be kept consistent in future versions. */ + private final String id; + /** This is the label that the toString() method will return. */ + private final String label; + + /** Constructs a new Verbosity value with the given id and label. */ + private Verbosity(String id, String label) { + this.id = id; + this.label = label; + } + + /** + * Given an id, return the enum value corresponding to it (if there's no match, then return + * DEFAULT). + */ + private static Verbosity parse(String id) { + for (Verbosity vb : values()) + if (vb.id.equals(id)) + return vb; + return DEFAULT; + } + + /** Returns the human-readable label for this enum value. */ + @Override + public final String toString() { + return label; + } + + /** Saves this value into the Java preference object. */ + private void set() { + Preferences.userNodeForPackage(Util.class).put("Verbosity", id); + } + + /** + * Reads the current value of the Java preference object (if it's not set, then return DEFAULT). + */ + private static Verbosity get() { + return parse(Preferences.userNodeForPackage(Util.class).get("Verbosity", "")); + } + }; + +} diff --git a/Source/eu.modelwriter.configuration/.classpath b/Source/eu.modelwriter.configuration/.classpath new file mode 100644 index 00000000..eca7bdba --- /dev/null +++ b/Source/eu.modelwriter.configuration/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Source/eu.modelwriter.configuration/.gitignore b/Source/eu.modelwriter.configuration/.gitignore new file mode 100644 index 00000000..ae3c1726 --- /dev/null +++ b/Source/eu.modelwriter.configuration/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/Source/eu.modelwriter.configuration/.project b/Source/eu.modelwriter.configuration/.project new file mode 100644 index 00000000..3419f1a1 --- /dev/null +++ b/Source/eu.modelwriter.configuration/.project @@ -0,0 +1,28 @@ + + + eu.modelwriter.configuration + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/Source/eu.modelwriter.configuration/.settings/org.eclipse.jdt.core.prefs b/Source/eu.modelwriter.configuration/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..0c68a61d --- /dev/null +++ b/Source/eu.modelwriter.configuration/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/Source/eu.modelwriter.configuration/.settings/org.eclipse.pde.core.prefs b/Source/eu.modelwriter.configuration/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 00000000..923c37fb --- /dev/null +++ b/Source/eu.modelwriter.configuration/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +resolve.requirebundle=false diff --git a/Source/eu.modelwriter.configuration/FileSystem.als b/Source/eu.modelwriter.configuration/FileSystem.als new file mode 100644 index 00000000..8ee65292 --- /dev/null +++ b/Source/eu.modelwriter.configuration/FileSystem.als @@ -0,0 +1,21 @@ +module ferhat/FileSystem + +abstract sig Object {} +sig Directory extends Object { contents: set Object} +one sig Root extends Directory { } +sig File extends Object { } +sig Alias extends Object { refs: set Word } +sig Word extends File { } + +fact { + no d:Directory | d in d.^contents --no directory cycles + Object in Root.*contents --each object is reacble from the root + all o: Object | lone o.~contents --each object has at most one parent + no disj a, a': Alias | some a.refs & a'.refs --no overlapping references to objects, + --each references maps each Alias to different objects +} + + + +pred example {#Alias >2 #refs> 2 #Directory >2} +run example for exactly 10 Object diff --git a/Source/eu.modelwriter.configuration/Helper.als b/Source/eu.modelwriter.configuration/Helper.als new file mode 100644 index 00000000..f7df902d --- /dev/null +++ b/Source/eu.modelwriter.configuration/Helper.als @@ -0,0 +1,4 @@ +module ferhat/Helper + +/* Helper Predicates*/ +pred acyclic [s: set univ, r: univ->univ] { no x: s | x in x.^r } diff --git a/Source/eu.modelwriter.configuration/META-INF/MANIFEST.MF b/Source/eu.modelwriter.configuration/META-INF/MANIFEST.MF new file mode 100644 index 00000000..a1e0b19c --- /dev/null +++ b/Source/eu.modelwriter.configuration/META-INF/MANIFEST.MF @@ -0,0 +1,38 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Configuration +Bundle-SymbolicName: eu.modelwriter.configuration;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: eu.modelwriter.configuration.Activator +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.core.resources, + eu.modelwriter.traceability.core.persistence;bundle-version="1.0.0", + eu.modelwriter.alloyanalyzer, + org.eclipse.emf.ecore +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ActivationPolicy: lazy +Export-Package: eu.modelwriter.configuration.alloy, + eu.modelwriter.configuration.alloy.analysis.provider;uses:="org.eclipse.ui", + eu.modelwriter.configuration.alloy.discovery;uses:="eu.modelwriter.traceability.core.persistence", + eu.modelwriter.configuration.alloy.evaluator, + eu.modelwriter.configuration.alloy.reasoning;uses:="eu.modelwriter.traceability.core.persistence,edu.mit.csail.sdg.alloy4compiler.translator", + eu.modelwriter.configuration.alloy.trace, + eu.modelwriter.configuration.alloy.validation, + eu.modelwriter.configuration.alloy2emf, + eu.modelwriter.configuration.emf2alloy, + eu.modelwriter.configuration.generation, + eu.modelwriter.configuration.internal; + uses:="org.eclipse.emf.ecore, + eu.modelwriter.traceability.core.persistence, + org.eclipse.emf.common.util, + org.eclipse.core.resources, + org.eclipse.emf.ecore.resource, + edu.mit.csail.sdg.alloy4viz, + org.eclipse.jface.viewers", + eu.modelwriter.configuration.specificreasoning, + eu.modelwriter.configuration.synthesis;uses:="org.eclipse.emf.ecore,org.eclipse.core.resources" +Import-Package: eu.modelwriter.marker.internal, + org.eclipse.emf.ecore.resource, + org.eclipse.jface.text +Bundle-ClassPath: . diff --git a/Source/eu.modelwriter.configuration/RequirementNoOpposite.als b/Source/eu.modelwriter.configuration/RequirementNoOpposite.als new file mode 100644 index 00000000..f764fad4 --- /dev/null +++ b/Source/eu.modelwriter.configuration/RequirementNoOpposite.als @@ -0,0 +1,84 @@ +module ferhat/Requirement + +abstract sig Element {} + +--@exclude +abstract sig State {} + +abstract sig ElementState extends State {} +one sig Deleted, Changed, Created extends ElementState {} + +abstract sig TaskState extends State {} +one sig Done, ToDo, Cancelled, Ready extends TaskState {} + +abstract sig Requirement extends Element { + state: one ElementState +} + +sig Task extends Element { + precede: lone Task, + state: one TaskState +}{ all t: Task | one t.~task} + + +one sig Project extends Requirement { + requirement: some ContractRequirement +} + +sig ContractRequirement extends Requirement { + system: set SystemRequirement, + relate: set ContractRequirement +}{all c: ContractRequirement | one c.~requirement} + +--@name: "System Requirement" +sig SystemRequirement extends Requirement { + child: some Implementation +}{ all s: SystemRequirement | one s.~system} + +abstract sig Implementation extends Requirement { + task: set Task +} +{ all i: Implementation | one i.~child} + +--@context.editor: "ReqIFEditor" //context'leri bir attribute ile tanıt kullanıcı dokümanlarını yaratırken bunlardan seçsin +//contenttype +sig SoftwareRequirement extends Implementation { + test: some TestCase +} + +sig HardwareRequirement extends Implementation {} + +sig TestCase extends Element { +}{ all t:TestCase | one t.~test} + + +fact noSelfRelation{ + no c: ContractRequirement | c in c.relate + no t: Task | t in t.precede +} + +fact noCycles{ + no t:Task | t in t.^precede +} + +fact realismConstraint { + some ContractRequirement + some HardwareRequirement + some SoftwareRequirement + some precede +} + +/* Counterexample Finding */ + + +/* Instance Finding */ +pred example { + #ContractRequirement >1 and #SystemRequirement >2 and + #SoftwareRequirement >1 and #HardwareRequirement >1 and + #precede >1 and #task >1 #(Task <: state).Cancelled >1 and + #(Requirement <: state).Created >4 and + #(Requirement <: state).Changed >1 and + #(Requirement <: state).Deleted >1 +} +run example for exactly 20 Element + diff --git a/Source/eu.modelwriter.configuration/SimlifiedConfigurationModel.als b/Source/eu.modelwriter.configuration/SimlifiedConfigurationModel.als new file mode 100644 index 00000000..7b163051 --- /dev/null +++ b/Source/eu.modelwriter.configuration/SimlifiedConfigurationModel.als @@ -0,0 +1,58 @@ +module Haveksan/Requirement + +abstract sig Requirement {} + +sig Task { + precede: lone Task, +}{ all t: Task | one t.~task} + +one sig Project extends Requirement { + requirement: some ContractRequirement } + +sig ContractRequirement extends Requirement { + system: set SystemRequirement, + relate: set ContractRequirement +}{all c: ContractRequirement | one c.~requirement} + +--@name: "System Requirement" +sig SystemRequirement extends Requirement { + child: some Implementation +}{ all s: SystemRequirement | one s.~system} + +abstract sig Implementation extends Requirement { + task: set Task +}{ all i: Implementation | one i.~child} + +--@context.editor: "ReqIFEditor" +sig SoftwareRequirement extends Implementation { + test: some TestCase +} + +sig HardwareRequirement extends Implementation {} + +sig TestCase { }{ all t:TestCase | one t.~test} + + +fact noSelfRelation{ + no c: ContractRequirement | c in c.relate + no t: Task | t in t.precede } + +fact noCycles{no t:Task | t in t.^precede} + +fact realismConstraint { + some ContractRequirement + some HardwareRequirement + some SoftwareRequirement + some precede} + +/* Counterexample Finding */ + + +/* Instance Finding */ +pred example { + #ContractRequirement >1 and #SystemRequirement >2 and + #SoftwareRequirement >1 and #HardwareRequirement >1 and + #precede >1 and #task >1 +} +run example for 10 + diff --git a/Source/eu.modelwriter.configuration/Type.als b/Source/eu.modelwriter.configuration/Type.als new file mode 100644 index 00000000..05c58e26 --- /dev/null +++ b/Source/eu.modelwriter.configuration/Type.als @@ -0,0 +1,8 @@ +module ferhat/Type + +/*Type Module*/ +abstract sig Element {} +sig string extends Element {} +abstract sig boolean extends Element {} +one sig false,true extends boolean {} +--sig integer extends Element {} diff --git a/Source/eu.modelwriter.configuration/build.properties b/Source/eu.modelwriter.configuration/build.properties new file mode 100644 index 00000000..c34b2af8 --- /dev/null +++ b/Source/eu.modelwriter.configuration/build.properties @@ -0,0 +1,23 @@ +############################################################################### +# Copyright (c) 2015 UNIT Information Technologies R&D Ltd +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Ferhat Erata - initial API and implementation +# H. Emre Kirmizi - initial API and implementation +# Serhat Celik - initial API and implementation +# U. Anil Ozturk - initial API and implementation +############################################################################### +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + lib/,\ + bin/,\ + .settings/,\ + .project,\ + .classpath,\ + build.properties diff --git a/Source/eu.modelwriter.configuration/empty.als b/Source/eu.modelwriter.configuration/empty.als new file mode 100644 index 00000000..e69de29b diff --git a/Source/eu.modelwriter.configuration/grandpa.als b/Source/eu.modelwriter.configuration/grandpa.als new file mode 100644 index 00000000..df0fffe1 --- /dev/null +++ b/Source/eu.modelwriter.configuration/grandpa.als @@ -0,0 +1,26 @@ +abstract sig Person { + father: lone Man, + mother: lone Woman + } + +sig Man extends Person { wife: lone Woman } + +sig Woman extends Person { husband: lone Man } + +fact Biology { no p: Person | p in p.^(mother+father) } + +fact Terminology { wife = ~husband } + +fact SocialConvention { + no wife & *(mother+father).mother + no husband & *(mother+father).father + } + +fun grandpas [p: Person] : set Person { + let parent = mother + father + father.wife + mother.husband | + p.parent.parent & Man + } + +pred ownGrandpa [m: Man] { m in grandpas[m] } + +run ownGrandpa for 4 Person \ No newline at end of file diff --git a/Source/eu.modelwriter.configuration/lib/alloy4.2.jar b/Source/eu.modelwriter.configuration/lib/alloy4.2.jar new file mode 100644 index 00000000..3be21612 Binary files /dev/null and b/Source/eu.modelwriter.configuration/lib/alloy4.2.jar differ diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/Activator.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/Activator.java new file mode 100644 index 00000000..a23c7158 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/Activator.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.configuration; + +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + // The shared instance + private static Activator plugin; + + // The plug-in ID + public static final String PLUGIN_ID = "eu.modelwriter.configuration"; //$NON-NLS-1$ + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return Activator.plugin; + } + + /** + * The constructor + */ + public Activator() {} + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + Activator.plugin = this; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + @Override + public void stop(BundleContext context) throws Exception { + Activator.plugin = null; + super.stop(context); + } + + public static Shell getShell() { + return getActiveWorkbenchWindow().getShell(); + } + + public static IWorkbenchWindow getActiveWorkbenchWindow() { + return PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/AlloyParser.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/AlloyParser.java new file mode 100644 index 00000000..0f782d44 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/AlloyParser.java @@ -0,0 +1,442 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.configuration.alloy; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.ui.PlatformUI; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.SafeList; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.SubsetSig; +import edu.mit.csail.sdg.alloy4compiler.ast.Type; +import edu.mit.csail.sdg.alloy4compiler.ast.Type.ProductType; +import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil; +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.internal.MarkerTypeElement; +import eu.modelwriter.traceability.core.persistence.AlloyType; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; +import eu.modelwriter.traceability.core.persistence.FieldType; +import eu.modelwriter.traceability.core.persistence.InstanceType; +import eu.modelwriter.traceability.core.persistence.RelationType; +import eu.modelwriter.traceability.core.persistence.RepositoryType; +import eu.modelwriter.traceability.core.persistence.SigType; +import eu.modelwriter.traceability.core.persistence.SourceType; +import eu.modelwriter.traceability.core.persistence.TypeType; +import eu.modelwriter.traceability.core.persistence.TypesType; +import eu.modelwriter.traceability.core.persistence.persistenceFactory; + +public class AlloyParser { + + private String filename; + private final ArrayList rels = new ArrayList(); + private final Map sigTypeParentMap = new HashMap(); + private final ArrayList types = new ArrayList(); + + AlloyParser() {} + + public AlloyParser(final String filename) { + this.filename = filename; + this.parse(filename); + } + + private MarkerTypeElement convertToMarkerType(final Sig rootSig) { + if (rootSig instanceof PrimSig) { + final PrimSig primSig = (PrimSig) rootSig; + MarkerTypeElement rootType; + if (primSig.isAbstract != null) { + rootType = new MarkerTypeElement( + primSig.toString().substring(primSig.toString().indexOf("/") + 1) + " {abs}"); + } else { + rootType = new MarkerTypeElement( + primSig.toString().substring(primSig.toString().indexOf("/") + 1)); + } + try { + if (primSig.children().isEmpty()) { + return rootType; + } else { + for (int i = 0; i < primSig.children().size(); i++) { + rootType.getChildren().add(this.convertToMarkerType(primSig.children().get(i))); + } + return rootType; + } + } catch (final Err e) { + final MessageDialog dialog = + new MessageDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), + "Alloy Error Information", null, e.getMessage(), MessageDialog.INFORMATION, + new String[] {"OK"}, 0); + dialog.open(); + } + } else if (rootSig instanceof SubsetSig) { + final SubsetSig subsetSig = (SubsetSig) rootSig; + String parentName = subsetSig.type().toString(); + parentName = parentName.substring(parentName.indexOf("/") + 1, parentName.length() - 1); + final MarkerTypeElement parentMarkerType = + this.getMarkTypeElementByName(parentName, this.types); + parentMarkerType.getChildren().add(new MarkerTypeElement( + subsetSig.toString().substring(subsetSig.toString().indexOf("/") + 1))); + } + return null; + } + + private DocumentRoot createBaseXmlFile() { + // Resource res = AlloyUtilities.getResource(); + // RepositoryType oldRepositoryType = null; + // + // if (res == null) { + // res = AlloyUtilities.createResource(); + // } else { + // DocumentRoot oldDocumentRoot = (DocumentRoot) res.getContents().get(0); + // oldRepositoryType = oldDocumentRoot.getAlloy().getRepository(); + // } + + RepositoryType oldRepositoryType = null; + RelationType oldRelationType = null; + final DocumentRoot oldDocumentRoot = AlloyUtilities.getDocumentRoot(); + if (oldDocumentRoot != null) { + oldRepositoryType = oldDocumentRoot.getAlloy().getRepository(); + oldRelationType = oldDocumentRoot.getAlloy().getRelation(); + } + + // RepositoryType oldRepositoryType = null; + // if (res.getContents().size() != 0) { + // DocumentRoot oldDocumentRoot = (DocumentRoot) res.getContents().get(0); + // oldRepositoryType = oldDocumentRoot.getAlloy().getRepository(); + // } + + final DocumentRoot documentRoot = persistenceFactory.eINSTANCE.createDocumentRoot(); + + final AlloyType alloyType = persistenceFactory.eINSTANCE.createAlloyType(); + documentRoot.setAlloy(alloyType); + alloyType.setBuilddate(""); + if (oldRepositoryType == null) { + final RepositoryType repositoryType = persistenceFactory.eINSTANCE.createRepositoryType(); + repositoryType.setNextId(0); + alloyType.setRepository(repositoryType); + } else { + alloyType.setRepository(oldRepositoryType); + } + + if (oldRelationType == null) { + final RelationType relationType = persistenceFactory.eINSTANCE.createRelationType(); + alloyType.setRelation(relationType); + } else { + alloyType.setRelation(oldRelationType); + } + + final InstanceType instanceType = persistenceFactory.eINSTANCE.createInstanceType(); + alloyType.setInstance(instanceType); + instanceType.setBitwidth(0); + instanceType.setFilename(this.filename); + instanceType.setMaxseq(0); + + final SigType sigSegInt = persistenceFactory.eINSTANCE.createSigType(); + instanceType.getSig().add(sigSegInt); + sigSegInt.setID(0); + sigSegInt.setLabel("seq/Int"); + sigSegInt.setParentID(1); + sigSegInt.setBuiltin("yes"); + + final SigType sigInt = persistenceFactory.eINSTANCE.createSigType(); + instanceType.getSig().add(sigInt); + sigInt.setID(1); + sigInt.setLabel("Int"); + sigInt.setParentID(2); + sigInt.setBuiltin("yes"); + + final SigType sigUniv = persistenceFactory.eINSTANCE.createSigType(); + instanceType.getSig().add(sigUniv); + sigUniv.setID(2); + sigUniv.setLabel("univ"); + sigUniv.setBuiltin("yes"); + + final SigType sigString = persistenceFactory.eINSTANCE.createSigType(); + instanceType.getSig().add(sigString); + sigString.setID(3); + sigString.setLabel("String"); + sigString.setParentID(2); + sigString.setBuiltin("yes"); + + + + // AlloyUtilities.saveResource(res, documentRoot); + + return documentRoot; + } + + private FieldType getFieldType(final Field field, final int idIndex, + final EList fieldTypeList, final EList sigTypeList) { + final FieldType fieldType = persistenceFactory.eINSTANCE.createFieldType(); + + final int fieldParentId = this.parentId(field.sig.label.toString(), sigTypeList); + final int firstTypeId = this.parentId( + field.type().toString().substring(1, field.type().toString().indexOf("->")), sigTypeList); + fieldType.setLabel(field.label); + fieldType.setID(idIndex); + fieldType.setParentID(fieldParentId); + + final Iterator iter = field.decl().expr.type().iterator(); + while (iter.hasNext()) { + final Type.ProductType productType = iter.next(); + + final TypesType typesType = persistenceFactory.eINSTANCE.createTypesType(); + fieldType.getTypes().add(typesType); + + final TypeType firstTypeType = persistenceFactory.eINSTANCE.createTypeType(); + typesType.getType().add(firstTypeType); + firstTypeType.setID(firstTypeId); + + final TypeType secondTypeType = persistenceFactory.eINSTANCE.createTypeType(); + typesType.getType().add(secondTypeType); + final int secondTypeId = this.parentId(productType.toString(), sigTypeList); + secondTypeType.setID(secondTypeId); + } + + return fieldType; + } + + private MarkerTypeElement getMarkTypeElementByName(final String elementName, + final ArrayList typeList) { + MarkerTypeElement element = null; + + for (final MarkerTypeElement markerTypeElement : typeList) { + if (markerTypeElement.getType().contains("{abs}") && markerTypeElement.getType() + .substring(0, markerTypeElement.getType().indexOf(" {abs}")).equals(elementName) + || markerTypeElement.getType().equals(elementName)) { + return markerTypeElement; + } + if (markerTypeElement.getChildren().size() != 0) { + element = this.getMarkTypeElementByName(elementName, markerTypeElement.getChildren()); + } + if (element != null) { + break; + } + } + + return element; + } + + public ArrayList getRels() { + return this.rels; + } + + private SigType getSigType(final PrimSig primSig, final int idIndex, + final EList sigTypeList) { + final String parentName = primSig.parent.toString(); + + + // int parentId = parentId(parentName, sigTypeList); + + final SigType sigType = persistenceFactory.eINSTANCE.createSigType(); + sigType.setID(idIndex); + sigType.setLabel(primSig.label); + // sigType.setParentID(parentId); + + this.sigTypeParentMap.put(sigType, parentName); + + this.setStatuofSig(primSig, sigType); + + return sigType; + } + + private SigType getSigType(final SubsetSig subsetSig, final int idIndex, + final EList sigTypeList) { + String typeName = subsetSig.type().toString(); + typeName = typeName.substring(1, typeName.length() - 1); + + final SigType sigType = persistenceFactory.eINSTANCE.createSigType(); + sigType.setID(idIndex); + sigType.setLabel(subsetSig.label); + + for (final SigType sigTypes : sigTypeList) { + if (sigTypes.getLabel().equals(typeName)) { + final TypeType type = persistenceFactory.eINSTANCE.createTypeType(); + type.setID(sigTypes.getID()); + sigType.getType().add(type); + break; + } + + } + + this.setStatuofSig(subsetSig, sigType); + + return sigType; + + } + + public ArrayList getTypes() { + return this.types; + } + + private int parentId(final String parentName, final EList sigTypeList) { + + for (final SigType sigType : sigTypeList) { + if (sigType.getLabel().equals(parentName)) { + return sigType.getID(); + } + } + + return -1; + + } + + private void parse(final String filename) { + // AlloyUtilities.createXMLFromAlloy(filename); + try { + // Parse+typecheck the model + // System.out.println("=========== Parsing+Typechecking " + filename + " ============="); + Module world; + + final DocumentRoot documentRoot = this.createBaseXmlFile(); + final EList xmlSigList = documentRoot.getAlloy().getInstance().getSig(); + final EList xmlFieldList = documentRoot.getAlloy().getInstance().getField(); + + int idIndex = 4; + final Map map = new LinkedHashMap(); + world = CompUtil.parseEverything_fromFile(new A4Reporter(), map, filename); + for (final Module modules : world.getAllReachableModules()) { + final SafeList list = modules.getAllSigs(); + for (final Sig sig : list) { + if (sig instanceof PrimSig) { + final PrimSig primSig = (PrimSig) sig; + + xmlSigList.add(this.getSigType(primSig, idIndex, xmlSigList)); + idIndex++; + + if (primSig.children().size() == 0 && primSig.toString() + .substring(primSig.toString().indexOf("/") + 1).equals("Univ")) { + break; + } + if (primSig.isTopLevel()) { + this.types.add(this.convertToMarkerType(primSig)); + } + } else if (sig instanceof SubsetSig) { + final SubsetSig subsetSig = (SubsetSig) sig; + this.convertToMarkerType(subsetSig); + xmlSigList.add(this.getSigType(subsetSig, idIndex, xmlSigList)); + idIndex++; + // this.types.add(this.convertToMarkerType(subsetSig)); + } + } + } + + this.setParentIdForSigTypes(xmlSigList); + + for (final Module modules : world.getAllReachableModules()) { + final SafeList list = modules.getAllSigs(); + for (final Sig sig : list) { + final SafeList fields = sig.getFields(); + for (final Field field : fields) { + + xmlFieldList.add(this.getFieldType(field, idIndex, xmlFieldList, xmlSigList)); + idIndex++; + + String product = ""; + if (field.decl().expr.type().size() > 1) { + final Iterator iter = field.decl().expr.type().iterator(); + while (iter.hasNext()) { + final Type.ProductType productType = iter.next(); + if (iter.hasNext()) { + product += + productType.toString().substring(productType.toString().indexOf("/") + 1) + + ","; + } else { + product += + productType.toString().substring(productType.toString().indexOf("/") + 1); + } + } + } else { + product = field.decl().expr.type().toExpr().toString() + .substring(field.decl().expr.type().toExpr().toString().indexOf("/") + 1); + } + final String str2 = field.label + " : " + + field.sig.toString().substring(field.sig.toString().indexOf("/") + 1) + " -> " + + field.decl().expr.mult() + " " + product; + this.rels.add(str2); + } + } + } + + final Iterator> mapIter = map.entrySet().iterator(); + while (mapIter.hasNext()) { + final Entry entry = mapIter.next(); + final SourceType sourceType = persistenceFactory.eINSTANCE.createSourceType(); + sourceType.setFilename(entry.getKey()); + sourceType.setContent(entry.getValue()); + documentRoot.getAlloy().getSource().add(sourceType); + } + + AlloyUtilities.writeDocumentRoot(documentRoot); + // AlloyUtilities.saveResource(AlloyUtilities.getResource(), documentRoot); + + final MessageDialog messageDialog = + new MessageDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), + "Information", null, "Alloy file has been parsed succesfully", + MessageDialog.INFORMATION, new String[] {"OK"}, 0); + messageDialog.open(); + } catch (final Err e) { + final MessageDialog dialog = + new MessageDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), + "Alloy Error Information", null, e.getMessage(), MessageDialog.INFORMATION, + new String[] {"OK"}, 0); + dialog.open(); + } + } + + + private void setParentIdForSigTypes(final EList sigTypeList) { + + for (final SigType sigType : sigTypeList) { + final String parentName = this.sigTypeParentMap.get(sigType); + if (parentName != null) { + final int parentId = this.parentId(parentName, sigTypeList); + sigType.setParentID(parentId); + } + } + } + + private void setStatuofSig(final Sig sig, final SigType sigType) { + if (sig.isAbstract != null) { + sigType.setAbstract("yes"); + } + if (sig.isEnum != null) { + sigType.setEnum("yes"); + } + if (sig.isLone != null) { + sigType.setLone("yes"); + } + if (sig.isMeta != null) { + sigType.setMeta("yes"); + } + if (sig.isOne != null) { + sigType.setOne("yes"); + } + if (sig.isPrivate != null) { + sigType.setPrivate("yes"); + } + if (sig.isSome != null) { + sigType.setSome("yes"); + } + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/AlloyParserForMetamodel.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/AlloyParserForMetamodel.java new file mode 100644 index 00000000..8732f8e0 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/AlloyParserForMetamodel.java @@ -0,0 +1,424 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.configuration.alloy; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.ui.PlatformUI; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.SafeList; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.PrimSig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.SubsetSig; +import edu.mit.csail.sdg.alloy4compiler.ast.Type; +import edu.mit.csail.sdg.alloy4compiler.ast.Type.ProductType; +import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil; +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.internal.MarkerTypeElement; +import eu.modelwriter.traceability.core.persistence.AlloyType; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; +import eu.modelwriter.traceability.core.persistence.FieldType; +import eu.modelwriter.traceability.core.persistence.InstanceType; +import eu.modelwriter.traceability.core.persistence.RelationType; +import eu.modelwriter.traceability.core.persistence.RepositoryType; +import eu.modelwriter.traceability.core.persistence.SigType; +import eu.modelwriter.traceability.core.persistence.SourceType; +import eu.modelwriter.traceability.core.persistence.TypeType; +import eu.modelwriter.traceability.core.persistence.TypesType; +import eu.modelwriter.traceability.core.persistence.persistenceFactory; + +public class AlloyParserForMetamodel { + + private static ArrayList rels; + + private static ArrayList sigs; + + public static ArrayList getRels() { + return rels; + } + + public static ArrayList getSigs() { + return sigs; + } + + private String xmlName; + private String filepath; + private final Map sigTypeParentMap = new HashMap<>(); + + private final ArrayList types = new ArrayList<>(); + + AlloyParserForMetamodel() {} + + public AlloyParserForMetamodel(final String filepath, final String xmlName) throws Err { + this.filepath = filepath; + this.xmlName = xmlName; + this.parse(); + } + + private MarkerTypeElement convertToMarkerType(final Sig rootSig) { + if (rootSig instanceof PrimSig) { + final PrimSig primSig = (PrimSig) rootSig; + MarkerTypeElement rootType; + if (primSig.isAbstract != null) { + rootType = new MarkerTypeElement( + primSig.toString().substring(primSig.toString().indexOf("/") + 1) + " {abs}"); + } else { + rootType = new MarkerTypeElement( + primSig.toString().substring(primSig.toString().indexOf("/") + 1)); + } + try { + if (primSig.children().isEmpty()) { + return rootType; + } else { + for (int i = 0; i < primSig.children().size(); i++) { + rootType.getChildren().add(this.convertToMarkerType(primSig.children().get(i))); + } + return rootType; + } + } catch (final Err e) { + final MessageDialog dialog = + new MessageDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), + "Alloy Error Information", null, e.getMessage(), MessageDialog.INFORMATION, + new String[] {"OK"}, 0); + dialog.open(); + } + } else if (rootSig instanceof SubsetSig) { + final SubsetSig subsetSig = (SubsetSig) rootSig; + String parentName = subsetSig.type().toString(); + parentName = parentName.substring(parentName.indexOf("/") + 1, parentName.length() - 1); + final MarkerTypeElement parentMarkerType = + this.getMarkTypeElementByName(parentName, this.types); + parentMarkerType.getChildren().add(new MarkerTypeElement( + subsetSig.toString().substring(subsetSig.toString().indexOf("/") + 1))); + } + return null; + } + + private DocumentRoot createBaseXmlFile() { + // Resource res = AlloyUtilities.getResource(); + // RepositoryType oldRepositoryType = null; + // + // if (res == null) { + // res = AlloyUtilities.createResource(); + // } else { + // DocumentRoot oldDocumentRoot = (DocumentRoot) res.getContents().get(0); + // oldRepositoryType = oldDocumentRoot.getAlloy().getRepository(); + // } + + // RepositoryType oldRepositoryType = null; + // RelationType oldRelationType = null; + // DocumentRoot oldDocumentRoot = AlloyUtilities.getDocumentRoot(); + // if (oldDocumentRoot != null) { + // oldRepositoryType = oldDocumentRoot.getAlloy().getRepository(); + // oldRelationType = oldDocumentRoot.getAlloy().getRelation(); + // } + + // RepositoryType oldRepositoryType = null; + // if (res.getContents().size() != 0) { + // DocumentRoot oldDocumentRoot = (DocumentRoot) res.getContents().get(0); + // oldRepositoryType = oldDocumentRoot.getAlloy().getRepository(); + // } + + final DocumentRoot documentRoot = persistenceFactory.eINSTANCE.createDocumentRoot(); + + final AlloyType alloyType = persistenceFactory.eINSTANCE.createAlloyType(); + documentRoot.setAlloy(alloyType); + alloyType.setBuilddate(""); + // if (oldRepositoryType == null) { + final RepositoryType repositoryType = persistenceFactory.eINSTANCE.createRepositoryType(); + repositoryType.setNextId(0); + alloyType.setRepository(repositoryType); + // } else { + // alloyType.setRepository(oldRepositoryType); + // } + + // if (oldRelationType == null) { + final RelationType relationType = persistenceFactory.eINSTANCE.createRelationType(); + alloyType.setRelation(relationType); + // } else { + // alloyType.setRelation(oldRelationType); + // } + + final InstanceType instanceType = persistenceFactory.eINSTANCE.createInstanceType(); + alloyType.setInstance(instanceType); + instanceType.setBitwidth(0); + instanceType.setFilename(AlloyUtilities.getLocationForMetamodel(this.xmlName)); + instanceType.setMaxseq(0); + instanceType.setMetamodel("yes"); + + final SigType sigSegInt = persistenceFactory.eINSTANCE.createSigType(); + instanceType.getSig().add(sigSegInt); + sigSegInt.setID(0); + sigSegInt.setLabel("seq/Int"); + sigSegInt.setParentID(1); + sigSegInt.setBuiltin("yes"); + + final SigType sigInt = persistenceFactory.eINSTANCE.createSigType(); + instanceType.getSig().add(sigInt); + sigInt.setID(1); + sigInt.setLabel("Int"); + sigInt.setParentID(2); + sigInt.setBuiltin("yes"); + + final SigType sigUniv = persistenceFactory.eINSTANCE.createSigType(); + instanceType.getSig().add(sigUniv); + sigUniv.setID(2); + sigUniv.setLabel("univ"); + sigUniv.setBuiltin("yes"); + + final SigType sigString = persistenceFactory.eINSTANCE.createSigType(); + instanceType.getSig().add(sigString); + sigString.setID(3); + sigString.setLabel("String"); + sigString.setParentID(2); + sigString.setBuiltin("yes"); + + return documentRoot; + } + + private FieldType getFieldType(final Field field, final int idIndex, + final EList fieldTypeList, final EList sigTypeList) { + final FieldType fieldType = persistenceFactory.eINSTANCE.createFieldType(); + + final int fieldParentId = this.parentId(field.sig.label.toString(), sigTypeList); + final int firstTypeId = this.parentId( + field.type().toString().substring(1, field.type().toString().indexOf("->")), sigTypeList); + fieldType.setLabel(field.label); + fieldType.setID(idIndex); + fieldType.setParentID(fieldParentId); + + final Iterator iter = field.decl().expr.type().iterator(); + while (iter.hasNext()) { + final Type.ProductType productType = iter.next(); + + final TypesType typesType = persistenceFactory.eINSTANCE.createTypesType(); + fieldType.getTypes().add(typesType); + + final TypeType firstTypeType = persistenceFactory.eINSTANCE.createTypeType(); + typesType.getType().add(firstTypeType); + firstTypeType.setID(firstTypeId); + + final TypeType secondTypeType = persistenceFactory.eINSTANCE.createTypeType(); + typesType.getType().add(secondTypeType); + final int secondTypeId = this.parentId(productType.toString(), sigTypeList); + secondTypeType.setID(secondTypeId); + } + + return fieldType; + } + + private MarkerTypeElement getMarkTypeElementByName(final String elementName, + final ArrayList typeList) { + MarkerTypeElement element = null; + + for (final MarkerTypeElement markerTypeElement : typeList) { + if (markerTypeElement.getType().contains("{abs}") && markerTypeElement.getType() + .substring(0, markerTypeElement.getType().indexOf(" {abs}")).equals(elementName) + || markerTypeElement.getType().equals(elementName)) { + return markerTypeElement; + } + if (markerTypeElement.getChildren().size() != 0) { + element = this.getMarkTypeElementByName(elementName, markerTypeElement.getChildren()); + } + if (element != null) { + break; + } + } + + return element; + } + + private SigType getSigType(final PrimSig primSig, final int idIndex, + final EList sigTypeList) { + final String parentName = primSig.parent.toString(); + + + // int parentId = parentId(parentName, sigTypeList); + + final SigType sigType = persistenceFactory.eINSTANCE.createSigType(); + sigType.setID(idIndex); + sigType.setLabel(primSig.label); + // sigType.setParentID(parentId); + + this.sigTypeParentMap.put(sigType, parentName); + + this.setStatuofSig(primSig, sigType); + + return sigType; + } + + private SigType getSigType(final SubsetSig subsetSig, final int idIndex, + final EList sigTypeList) { + String typeName = subsetSig.type().toString(); + typeName = typeName.substring(1, typeName.length() - 1); + + final SigType sigType = persistenceFactory.eINSTANCE.createSigType(); + sigType.setID(idIndex); + sigType.setLabel(subsetSig.label); + + for (final SigType sigTypes : sigTypeList) { + if (sigTypes.getLabel().equals(typeName)) { + final TypeType type = persistenceFactory.eINSTANCE.createTypeType(); + type.setID(sigTypes.getID()); + sigType.getType().add(type); + break; + } + + } + + this.setStatuofSig(subsetSig, sigType); + + return sigType; + + } + + private int parentId(final String parentName, final EList sigTypeList) { + + for (final SigType sigType : sigTypeList) { + if (sigType.getLabel().equals(parentName)) { + return sigType.getID(); + } + } + + return -1; + + } + + private void parse() throws Err { + final ArrayList relations = new ArrayList<>(); + final ArrayList signatures = new ArrayList<>(); + + // Parse+typecheck the model + // System.out.println("=========== Parsing+Typechecking " + this.filepath + " ============="); + + final DocumentRoot documentRoot = this.createBaseXmlFile(); + final EList xmlSigList = documentRoot.getAlloy().getInstance().getSig(); + final EList xmlFieldList = documentRoot.getAlloy().getInstance().getField(); + + int idIndex = 4; + final Map map = new LinkedHashMap<>(); + final Module world = CompUtil.parseEverything_fromFile(new A4Reporter(), map, this.filepath); + for (final Module modules : world.getAllReachableModules()) { + final SafeList list = modules.getAllSigs(); + for (final Sig sig : list) { + if (sig instanceof PrimSig) { + final PrimSig primSig = (PrimSig) sig; + xmlSigList.add(this.getSigType(primSig, idIndex, xmlSigList)); + idIndex++; + + if (primSig.children().size() == 0 + && primSig.toString().substring(primSig.toString().indexOf("/") + 1).equals("Univ")) { + break; + } + if (primSig.isTopLevel()) { + this.types.add(this.convertToMarkerType(primSig)); + } + } else if (sig instanceof SubsetSig) { + final SubsetSig subsetSig = (SubsetSig) sig; + this.convertToMarkerType(subsetSig); + xmlSigList.add(this.getSigType(subsetSig, idIndex, xmlSigList)); + idIndex++; + } + } + } + + this.setParentIdForSigTypes(xmlSigList); + + for (final Module modules : world.getAllReachableModules()) { + final SafeList list = modules.getAllSigs(); + for (final Sig sig : list) { + if (!signatures.contains(sig.label)) { + signatures.add(sig.label.substring(sig.label.indexOf("/") + 1)); + } + final SafeList fields = sig.getFields(); + for (final Field field : fields) { + + xmlFieldList.add(this.getFieldType(field, idIndex, xmlFieldList, xmlSigList)); + idIndex++; + + if (!relations.contains(field.label)) { + relations.add(field.label); + } + } + } + } + + final Iterator> mapIter = map.entrySet().iterator(); + while (mapIter.hasNext()) { + final Entry entry = mapIter.next(); + final SourceType sourceType = persistenceFactory.eINSTANCE.createSourceType(); + if (entry.getKey().contains("temp")) { + sourceType.setFilename(AlloyUtilities.getLocationForMetamodel(this.xmlName)); + } else { + sourceType.setFilename(entry.getKey()); + } + sourceType.setContent(entry.getValue()); + documentRoot.getAlloy().getSource().add(sourceType); + } + + // If the code reaches here, it means there is not any parse error. + // we'r loading these fields because of reconciler and completions usage. + rels = new ArrayList<>(); + rels.addAll(relations); + + sigs = new ArrayList<>(); + sigs.addAll(signatures); + + AlloyUtilities.writeDocumentRootForMetamodel(documentRoot, this.xmlName); + } + + private void setParentIdForSigTypes(final EList sigTypeList) { + + for (final SigType sigType : sigTypeList) { + final String parentName = this.sigTypeParentMap.get(sigType); + if (parentName != null) { + final int parentId = this.parentId(parentName, sigTypeList); + sigType.setParentID(parentId); + } + } + } + + + private void setStatuofSig(final Sig sig, final SigType sigType) { + if (sig.isAbstract != null) { + sigType.setAbstract("yes"); + } + if (sig.isEnum != null) { + sigType.setEnum("yes"); + } + if (sig.isLone != null) { + sigType.setLone("yes"); + } + if (sig.isMeta != null) { + sigType.setMeta("yes"); + } + if (sig.isOne != null) { + sigType.setOne("yes"); + } + if (sig.isPrivate != null) { + sigType.setPrivate("yes"); + } + if (sig.isSome != null) { + sigType.setSome("yes"); + } + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/analysis/provider/AnalysisSourceProvider.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/analysis/provider/AnalysisSourceProvider.java new file mode 100644 index 00000000..effd7761 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/analysis/provider/AnalysisSourceProvider.java @@ -0,0 +1,101 @@ +package eu.modelwriter.configuration.alloy.analysis.provider; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.ui.AbstractSourceProvider; +import org.eclipse.ui.ISources; + +public class AnalysisSourceProvider extends AbstractSourceProvider { + + public static enum AnalysisState { + ACTIVE, PASSIVE + } + + public static enum ReasoningType { + DISCOVER_RELATION, DISCOVER_ATOM, DISCOVER_RELATION_FOR_ATOM + } + + public static enum EvaluationState { + OPEN, CLOSE + } + + public static final String ANALYSIS_STATE = + "eu.modelwriter.configuration.alloy.analysissourceprovider.analysisState"; + public static final String REASONING_TYPE = + "eu.modelwriter.configuration.alloy.analysissourceprovider.reasoningType"; + public static final String EVALUATION_STATE = + "eu.modelwriter.configuration.alloy.analysissourceprovider.evaluationState"; + + private AnalysisState currentState = AnalysisState.PASSIVE; + + private ReasoningType reasoningType; + + private EvaluationState evaluationState = EvaluationState.CLOSE; + + @Override + public void dispose() {} + + @SuppressWarnings("rawtypes") + @Override + public Map getCurrentState() { + final Map map = new HashMap<>(1); + + if (currentState == AnalysisState.ACTIVE) { + map.put(AnalysisSourceProvider.ANALYSIS_STATE, AnalysisState.ACTIVE.toString()); + if (reasoningType == ReasoningType.DISCOVER_ATOM) { + map.put(AnalysisSourceProvider.REASONING_TYPE, ReasoningType.DISCOVER_ATOM.toString()); + } else if (reasoningType == ReasoningType.DISCOVER_RELATION) { + map.put(AnalysisSourceProvider.REASONING_TYPE, ReasoningType.DISCOVER_RELATION.toString()); + } else if (reasoningType == ReasoningType.DISCOVER_RELATION_FOR_ATOM) { + map.put(AnalysisSourceProvider.REASONING_TYPE, + ReasoningType.DISCOVER_RELATION_FOR_ATOM.toString()); + } + } else if (currentState == AnalysisState.PASSIVE) { + map.put(AnalysisSourceProvider.ANALYSIS_STATE, AnalysisState.PASSIVE.toString()); + } + + if (evaluationState == EvaluationState.OPEN) { + map.put(AnalysisSourceProvider.EVALUATION_STATE, EvaluationState.OPEN.toString()); + } else if (evaluationState == EvaluationState.CLOSE) { + map.put(AnalysisSourceProvider.EVALUATION_STATE, EvaluationState.CLOSE.toString()); + } + + return map; + } + + @Override + public String[] getProvidedSourceNames() { + return new String[] {AnalysisSourceProvider.ANALYSIS_STATE, + AnalysisSourceProvider.REASONING_TYPE, AnalysisSourceProvider.EVALUATION_STATE}; + } + + public void setActive(final ReasoningType TYPE) { + this.fireSourceChanged(ISources.WORKBENCH, AnalysisSourceProvider.ANALYSIS_STATE, + AnalysisState.ACTIVE.toString()); + currentState = AnalysisState.ACTIVE; + setReasoningType(TYPE); + } + + public void setPassive() { + this.fireSourceChanged(ISources.WORKBENCH, AnalysisSourceProvider.ANALYSIS_STATE, + AnalysisState.PASSIVE.toString()); + currentState = AnalysisState.PASSIVE; + } + + public ReasoningType getReasoningType() { + return reasoningType; + } + + public void setReasoningType(final ReasoningType reasoningType) { + this.reasoningType = reasoningType; + } + + public EvaluationState getEvaluationState() { + return evaluationState; + } + + public void setEvaluationState(final EvaluationState evaluationState) { + this.evaluationState = evaluationState; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/discovery/AlloyDiscovering.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/discovery/AlloyDiscovering.java new file mode 100644 index 00000000..4b0d6f04 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/discovery/AlloyDiscovering.java @@ -0,0 +1,265 @@ +package eu.modelwriter.configuration.alloy.discovery; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import javax.swing.JOptionPane; + +import org.eclipse.emf.common.util.EList; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.traceability.core.persistence.AtomType; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; +import eu.modelwriter.traceability.core.persistence.FieldType; +import eu.modelwriter.traceability.core.persistence.SigType; +import eu.modelwriter.traceability.core.persistence.TupleType; +import eu.modelwriter.traceability.core.persistence.TypesType; +import eu.modelwriter.traceability.core.persistence.persistenceFactory; + +public class AlloyDiscovering { + private int addStrayedAtom2Sig(final DocumentRoot documentRoot, final String sigName) { + int count = 0; + final String id = MarkerFactory.generateId(documentRoot); + + final AtomType atomType = persistenceFactory.eINSTANCE.createAtomType(); + atomType.setLabel(id); + atomType.setReasoned(true); + + for (final SigType sigType : documentRoot.getAlloy().getInstance().getSig()) { + String label = sigType.getLabel(); + label = label.substring(sigType.getLabel().lastIndexOf("/") + 1); + if (label.equals(sigName)) { + sigType.getAtom().add(atomType); + count = sigType.getAtom().size(); + break; + } + } + + AlloyUtilities.writeDocumentRoot(documentRoot); + + return count - 1; + } + + private final String alsPath = + InstanceTranslatorDiscovering.baseFileDirectory + "discovering.als"; + + private final String xmlPath = + InstanceTranslatorDiscovering.baseFileDirectory + "discovering.xml"; + + public boolean discovering() { + final File discoveringXml = new File(xmlPath); + if (discoveringXml.exists()) { + discoveringXml.delete(); + } + final File discoveringAls = new File(alsPath); + if (discoveringAls.exists()) { + discoveringAls.delete(); + } + + if (!AlloyValidatorDiscovering.validate()) { + return false; + } + + final AlloyParserForDiscovering parser = new AlloyParserForDiscovering(alsPath); + + AlloyOtherSolutionDiscovering.getInstance() + .setDiscoverSigs(AlloyValidatorDiscovering.discoverSigs); + + final DocumentRoot documentRootDiscovering = parser.parse(); + final DocumentRoot documentRootOriginal = AlloyUtilities.getDocumentRoot(); + if (documentRootDiscovering == null) { + return false; + } + + discover(documentRootOriginal, documentRootDiscovering); + + return true; + } + + private void discover(DocumentRoot documentRootOriginal, + final DocumentRoot documentRootDiscovering) { + final Map discoverSigs = AlloyValidatorDiscovering.discoverSigs; + int discoveredAtomCount = 0; + int discoveredRelationCount = 0; + + final String moduleName = AlloyUtilities.getOriginalModuleName(); + + final Map reasonedTuples_D = new HashMap<>(); + final Map discoveredAtoms_D = new HashMap<>(); + + for (final SigType sigType_D : documentRootDiscovering.getAlloy().getInstance().getSig()) { + if (!sigType_D.getLabel().contains(moduleName)) { + continue; + } + final String label = sigType_D.getLabel(); + final String sigName = label.substring(label.lastIndexOf("/") + 1); + if (!discoverSigs.containsKey(sigName)) { + continue; + } + + final int discoveredAtomSize = sigType_D.getAtom().size(); + discoveredAtomCount += discoveredAtomSize; + for (int i = 0; i < discoveredAtomSize; i++) { + discoveredAtoms_D.put(sigType_D.getAtom().get(i), sigName); + } + + final int id = sigType_D.getID(); + final ArrayList allParentIds = + AlloyUtilities.getAllParentIds(id, documentRootDiscovering); + + for (final FieldType fieldType_D : documentRootDiscovering.getAlloy().getInstance() + .getField()) { + for (final TypesType typesType_D : fieldType_D.getTypes()) { + for (int i = 0; i < typesType_D.getType().size(); i++) { + if (allParentIds.contains(typesType_D.getType().get(i).getID())) { + for (final TupleType tupleType_D : fieldType_D.getTuple()) { + for (final AtomType atomType : tupleType_D.getAtom()) { + if (atomType.getLabel().contains(moduleName)) { + reasonedTuples_D.put(tupleType_D, fieldType_D); + break; + } + } + } + } + } + } + } + } + + final Map label2AtomIndex = new HashMap<>(); + for (final Entry entry : discoveredAtoms_D.entrySet()) { + final AtomType atomType_D = entry.getKey(); + final String sigName = entry.getValue(); + final int index = addStrayedAtom2Sig(documentRootOriginal, entry.getValue()); // W + documentRootOriginal = AlloyUtilities.getDocumentRoot(); // R + + final SigType sigType = + AlloyUtilities.getSigTypeById(AlloyUtilities.getSigTypeIdByName(sigName)); + if (AlloyOtherSolutionDiscovering.getInstance().getOldDiscoverSigs() + .get(sigType.getID()) == null) { + AlloyOtherSolutionDiscovering.getInstance().getOldDiscoverSigs().put(sigType.getID(), + new ArrayList<>(Arrays.asList(sigType.getAtom().get(index)))); + } else { + AlloyOtherSolutionDiscovering.getInstance().getOldDiscoverSigs().get(sigType.getID()) + .add(sigType.getAtom().get(index)); + } + + label2AtomIndex.put(atomType_D.getLabel(), index); + } + + for (final Entry entry : reasonedTuples_D.entrySet()) { + documentRootOriginal = AlloyUtilities.getDocumentRoot(); // R + + final TupleType tupleType_D = entry.getKey(); + final FieldType fieldType_D = entry.getValue(); + final String fieldName = fieldType_D.getLabel(); + + final EList fieldTypesList = + documentRootOriginal.getAlloy().getInstance().getField(); + for (final FieldType fieldType_O : fieldTypesList) { + documentRootOriginal = AlloyUtilities.getDocumentRoot(); // R + + final String originalParentName = AlloyUtilities.getSigNameById(fieldType_O.getParentID()); + final String discoverParentName = + AlloyUtilities.getSigNameById(fieldType_D.getParentID(), documentRootDiscovering); + + if (originalParentName.equals(discoverParentName) + && fieldType_O.getLabel().equals(fieldName)) { + + final String sourceAtomLabel = tupleType_D.getAtom().get(0).getLabel(); + String sourceAtomType = sourceAtomLabel.substring(sourceAtomLabel.lastIndexOf("/") + 1); + sourceAtomType = sourceAtomType.substring(0, sourceAtomType.indexOf("$")); + final Integer sourceAtomIndex = label2AtomIndex.get(sourceAtomLabel); + AtomType atomType_OS = sourceAtomIndex == null + ? getOriginalAtomType(documentRootOriginal, sourceAtomLabel) : null; + + final String targetAtomLabel = tupleType_D.getAtom().get(1).getLabel(); + String targetAtomType = targetAtomLabel.substring(targetAtomLabel.lastIndexOf("/") + 1); + targetAtomType = targetAtomType.substring(0, targetAtomType.indexOf("$")); + final Integer targetAtomIndex = label2AtomIndex.get(targetAtomLabel); + AtomType atomType_OT = targetAtomIndex == null + ? getOriginalAtomType(documentRootOriginal, targetAtomLabel) : null; + + final EList sigTypes = documentRootOriginal.getAlloy().getInstance().getSig(); + for (final SigType sigType : sigTypes) { + String label = sigType.getLabel(); + label = label.substring(label.lastIndexOf("/") + 1); + if (sourceAtomType.equals(label)) { + if (sourceAtomIndex != null) { + atomType_OS = sigType.getAtom().get(sourceAtomIndex); + } + } + if (targetAtomType.equals(label)) { + if (targetAtomIndex != null) { + atomType_OT = sigType.getAtom().get(targetAtomIndex); + } + } + } + + final TupleType tupleType = persistenceFactory.eINSTANCE.createTupleType(); + if (atomType_OS.equals(atomType_OT)) { + atomType_OS = AlloyUtilities.cloneAtomType(atomType_OS); + } + tupleType.getAtom().add(atomType_OS); + tupleType.getAtom().add(atomType_OT); + tupleType.setReasoned(true); + discoveredRelationCount++; + + documentRootOriginal = AlloyUtilities.getDocumentRoot(); // R + for (final FieldType fieldType : documentRootOriginal.getAlloy().getInstance() + .getField()) { + if (fieldType.getID() == fieldType_O.getID()) { + fieldType.getTuple().add(tupleType); + break; + } + } + + if (AlloyOtherSolutionDiscovering.getInstance().getOldDiscoverRelations() + .get(fieldType_O.getID()) == null) { + AlloyOtherSolutionDiscovering.getInstance().getOldDiscoverRelations() + .put(fieldType_O.getID(), new ArrayList<>(Arrays.asList(tupleType))); + } else { + AlloyOtherSolutionDiscovering.getInstance().getOldDiscoverRelations() + .get(fieldType_O.getID()).add(tupleType); + } + + AlloyUtilities.writeDocumentRoot(documentRootOriginal); // W + } + } + } + + final String discoveringAtomMessage = + "Discovering on atoms successfully completed.\nDiscovered atom count: " + + discoveredAtomCount; + final String discoveringRelationMessage = + "Discovering on relations successfully completed.\nDiscovered relation count: " + + discoveredRelationCount; + + JOptionPane.showMessageDialog(null, discoveringAtomMessage + "\n" + discoveringRelationMessage, + "Discovering Atom", JOptionPane.INFORMATION_MESSAGE); + } + + private AtomType getOriginalAtomType(final DocumentRoot documentRootOriginal, + final String name_R) { + final String name = name_R.substring(0, name_R.lastIndexOf("_")); + final int id = + Integer.parseInt(name_R.substring(name_R.lastIndexOf("_") + 1, name_R.lastIndexOf("$"))); + + + for (final SigType sigType : documentRootOriginal.getAlloy().getInstance().getSig()) { + String label = sigType.getLabel(); + label = label.substring(label.lastIndexOf("/") + 1); + if (label.equals(name)) { + return sigType.getAtom().get(id); + } + } + return null; + // return + // AlloyUtilities.getSigTypeById(AlloyUtilities.getSigTypeIdByName(name)).getAtom().get(id); + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/discovery/AlloyOtherSolutionDiscovering.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/discovery/AlloyOtherSolutionDiscovering.java new file mode 100644 index 00000000..a2270285 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/discovery/AlloyOtherSolutionDiscovering.java @@ -0,0 +1,462 @@ +package eu.modelwriter.configuration.alloy.discovery; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.swing.JOptionPane; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.URI; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.traceability.core.persistence.AtomType; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; +import eu.modelwriter.traceability.core.persistence.FieldType; +import eu.modelwriter.traceability.core.persistence.SigType; +import eu.modelwriter.traceability.core.persistence.TupleType; +import eu.modelwriter.traceability.core.persistence.TypesType; +import eu.modelwriter.traceability.core.persistence.persistenceFactory; +import eu.modelwriter.traceability.core.persistence.internal.ModelIO; + +public class AlloyOtherSolutionDiscovering { + + private static Map discoverSigs; + private static AlloyOtherSolutionDiscovering instance; + private Map> oldDiscoverSigs; + private Map> oldDiscoverRelations; + String xmlFileLoc = InstanceTranslatorDiscovering.baseFileDirectory + "discovering.xml"; + private static List solutions; + private int currentSolutionIndex; + + public static AlloyOtherSolutionDiscovering getInstance() { + if (AlloyOtherSolutionDiscovering.instance == null) { + AlloyOtherSolutionDiscovering.instance = new AlloyOtherSolutionDiscovering(); + AlloyOtherSolutionDiscovering.instance.oldDiscoverSigs = new HashMap<>(); + AlloyOtherSolutionDiscovering.instance.oldDiscoverRelations = new HashMap<>(); + AlloyOtherSolutionDiscovering.solutions = new ArrayList<>(); + AlloyOtherSolutionDiscovering.discoverSigs = new HashMap<>(); + } + + return AlloyOtherSolutionDiscovering.instance; + } + + public boolean next() throws Err { + A4Solution ans; + if (AlloyOtherSolutionDiscovering.solutions.size() <= currentSolutionIndex + 1) { + ans = AlloyOtherSolutionDiscovering.solutions.get(currentSolutionIndex).next(); + if (ans.equals(AlloyOtherSolutionDiscovering.solutions.get(currentSolutionIndex))) { + return false; + } + AlloyOtherSolutionDiscovering.solutions.add(ans); + currentSolutionIndex++; + } else { + ans = AlloyOtherSolutionDiscovering.solutions.get(currentSolutionIndex + 1); + currentSolutionIndex++; + } + + if (AlloyOtherSolutionDiscovering.discoverSigs.isEmpty()) { + return false; + } + + if (ans.satisfiable()) { + ans.writeXML(xmlFileLoc); + if (!parse()) { + return false; + } + } else { + return false; + } + + removeOldDiscovering(); + return discovering(); + } + + public boolean previous() throws Err { + A4Solution ans; + if (currentSolutionIndex - 1 < 0) { + return false; + } else { + ans = AlloyOtherSolutionDiscovering.solutions.get(currentSolutionIndex - 1); + currentSolutionIndex--; + } + + if (AlloyOtherSolutionDiscovering.discoverSigs.isEmpty()) { + return false; + } + + if (ans.satisfiable()) { + ans.writeXML(xmlFileLoc); + if (!parse()) { + return false; + } + } else { + return false; + } + + removeOldDiscovering(); + return discovering(); + } + + private boolean parse() { + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder; + try { + builder = factory.newDocumentBuilder(); + final File file = new File(xmlFileLoc); + final Document document = builder.parse(file); + final Node instance = document.getElementsByTagName("instance").item(0); + instance.getAttributes().removeNamedItem("command"); + + Transformer transformer; + try { + transformer = TransformerFactory.newInstance().newTransformer(); + final DOMSource source = new DOMSource(document); + final StreamResult result = new StreamResult(file); + transformer.transform(source, result); + } catch (final Exception e) { + } + + return true; + } catch (ParserConfigurationException | SAXException | IOException e) { + e.printStackTrace(); + } + return false; + } + + private void removeOldDiscovering() { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + + final Iterator>> oldDiscoverAtomsIterator = + oldDiscoverSigs.entrySet().iterator(); + final EList sigTypes = documentRoot.getAlloy().getInstance().getSig(); + while (oldDiscoverAtomsIterator.hasNext()) { + final Entry> entry = oldDiscoverAtomsIterator.next(); + for (final SigType sigType : sigTypes) { + if (sigType.getID() == entry.getKey()) { + for (final AtomType oldAtomType : entry.getValue()) { + final Iterator atomIter = sigType.getAtom().iterator(); + while (atomIter.hasNext()) { + final AtomType atomType = atomIter.next(); + if (atomType.isReasoned()) { + if (oldAtomType.getLabel().equals(atomType.getLabel())) { + atomIter.remove(); + } + } + } + } + } + } + } + + final Iterator>> oldDiscoverRelationsIterator = + oldDiscoverRelations.entrySet().iterator(); + final EList fieldTypes = documentRoot.getAlloy().getInstance().getField(); + while (oldDiscoverRelationsIterator.hasNext()) { + final Entry> entry = oldDiscoverRelationsIterator.next(); + for (final FieldType fieldType : fieldTypes) { + if (fieldType.getID() == entry.getKey()) { + for (final TupleType oldTupleType : entry.getValue()) { + final Iterator tupleIter = fieldType.getTuple().iterator(); + final AtomType oldAtomType0 = oldTupleType.getAtom().get(0); + final AtomType oldAtomType1 = oldTupleType.getAtom().get(1); + while (tupleIter.hasNext()) { + final TupleType tupleType = tupleIter.next(); + if (tupleType.isReasoned()) { + final AtomType atomType0 = tupleType.getAtom().get(0); + final AtomType atomType1 = tupleType.getAtom().get(1); + if (oldAtomType0.getLabel().equals(atomType0.getLabel()) + && oldAtomType1.getLabel().equals(atomType1.getLabel())) { + tupleIter.remove(); + } + } + } + } + } + } + } + + AlloyUtilities.writeDocumentRoot(documentRoot); + + oldDiscoverRelations.clear(); + oldDiscoverSigs.clear(); + } + + public void finish() { + AlloyOtherSolutionDiscovering.solutions.clear(); + } + + public DocumentRoot getDocumentRoot() { + @SuppressWarnings("rawtypes") + final ModelIO modelIO = new ModelIO<>(); + @SuppressWarnings("rawtypes") + List list = null; + try { + list = modelIO.read(URI.createFileURI(xmlFileLoc)); + } catch (final IOException e) { + return null; + } + if (list == null || list.isEmpty()) { + return null; + } + final DocumentRoot documentRoot = (DocumentRoot) list.get(0); + return documentRoot; + } + + public A4Solution getCurrentSolution() { + return AlloyOtherSolutionDiscovering.solutions.isEmpty() ? null + : AlloyOtherSolutionDiscovering.solutions.get(currentSolutionIndex); + } + + public Map> getOldDiscoverSigs() { + return oldDiscoverSigs; + } + + public Map> getOldDiscoverRelations() { + return oldDiscoverRelations; + } + + public void setDiscoverSigs(final Map discoverSigs) { + AlloyOtherSolutionDiscovering.discoverSigs = discoverSigs; + } + + private boolean discovering() { + final DocumentRoot documentRootDiscovering = getDocumentRoot(); + final DocumentRoot documentRootOriginal = AlloyUtilities.getDocumentRoot(); + if (documentRootDiscovering == null) { + return false; + } + + discover(documentRootOriginal, documentRootDiscovering); + + return true; + } + + private void discover(DocumentRoot documentRootOriginal, + final DocumentRoot documentRootDiscovering) { + int discoveredAtomCount = 0; + int discoveredRelationCount = 0; + + final String moduleName = AlloyUtilities.getOriginalModuleName(); + + final Map reasonedTuples_D = new HashMap<>(); + final Map discoveredAtoms_D = new HashMap<>(); + + for (final SigType sigType_D : documentRootDiscovering.getAlloy().getInstance().getSig()) { + if (!sigType_D.getLabel().contains(moduleName)) { + continue; + } + final String label = sigType_D.getLabel(); + final String sigName = label.substring(label.lastIndexOf("/") + 1); + if (!AlloyOtherSolutionDiscovering.discoverSigs.containsKey(sigName)) { + continue; + } + + final int discoveredAtomSize = sigType_D.getAtom().size(); + discoveredAtomCount += discoveredAtomSize; + for (int i = 0; i < discoveredAtomSize; i++) { + discoveredAtoms_D.put(sigType_D.getAtom().get(i), sigName); + } + + final int id = sigType_D.getID(); + final ArrayList allParentIds = + AlloyUtilities.getAllParentIds(id, documentRootDiscovering); + + for (final FieldType fieldType_D : documentRootDiscovering.getAlloy().getInstance() + .getField()) { + for (final TypesType typesType_D : fieldType_D.getTypes()) { + for (int i = 0; i < typesType_D.getType().size(); i++) { + if (allParentIds.contains(typesType_D.getType().get(i).getID())) { + for (final TupleType tupleType_D : fieldType_D.getTuple()) { + for (final AtomType atomType : tupleType_D.getAtom()) { + if (atomType.getLabel().contains(moduleName)) { + reasonedTuples_D.put(tupleType_D, fieldType_D); + break; + } + } + } + } + } + } + } + } + + final Map label2AtomIndex = new HashMap<>(); + for (final Entry entry : discoveredAtoms_D.entrySet()) { + final AtomType atomType_D = entry.getKey(); + final String sigName = entry.getValue(); + final int index = addStrayedAtom2Sig(documentRootOriginal, entry.getValue()); // W + documentRootOriginal = AlloyUtilities.getDocumentRoot(); // R + + final SigType sigType = + AlloyUtilities.getSigTypeById(AlloyUtilities.getSigTypeIdByName(sigName)); + if (AlloyOtherSolutionDiscovering.getInstance().getOldDiscoverSigs() + .get(sigType.getID()) == null) { + AlloyOtherSolutionDiscovering.getInstance().getOldDiscoverSigs().put(sigType.getID(), + new ArrayList<>(Arrays.asList(sigType.getAtom().get(index)))); + } else { + AlloyOtherSolutionDiscovering.getInstance().getOldDiscoverSigs().get(sigType.getID()) + .add(sigType.getAtom().get(index)); + } + + label2AtomIndex.put(atomType_D.getLabel(), index); + } + + for (final Entry entry : reasonedTuples_D.entrySet()) { + documentRootOriginal = AlloyUtilities.getDocumentRoot(); // R + + final TupleType tupleType_D = entry.getKey(); + final FieldType fieldType_D = entry.getValue(); + final String fieldName = fieldType_D.getLabel(); + + final EList fieldTypesList = + documentRootOriginal.getAlloy().getInstance().getField(); + for (final FieldType fieldType_O : fieldTypesList) { + documentRootOriginal = AlloyUtilities.getDocumentRoot(); // R + + final String originalParentName = AlloyUtilities.getSigNameById(fieldType_O.getParentID()); + final String discoverParentName = + AlloyUtilities.getSigNameById(fieldType_D.getParentID(), documentRootDiscovering); + + if (originalParentName.equals(discoverParentName) + && fieldType_O.getLabel().equals(fieldName)) { + + final String sourceAtomLabel = tupleType_D.getAtom().get(0).getLabel(); + String sourceAtomType = sourceAtomLabel.substring(sourceAtomLabel.lastIndexOf("/") + 1); + sourceAtomType = sourceAtomType.substring(0, sourceAtomType.indexOf("$")); + final Integer sourceAtomIndex = label2AtomIndex.get(sourceAtomLabel); + AtomType atomType_OS = sourceAtomIndex == null + ? getOriginalAtomType(documentRootOriginal, sourceAtomLabel) : null; + + final String targetAtomLabel = tupleType_D.getAtom().get(1).getLabel(); + String targetAtomType = targetAtomLabel.substring(targetAtomLabel.lastIndexOf("/") + 1); + targetAtomType = targetAtomType.substring(0, targetAtomType.indexOf("$")); + final Integer targetAtomIndex = label2AtomIndex.get(targetAtomLabel); + AtomType atomType_OT = targetAtomIndex == null + ? getOriginalAtomType(documentRootOriginal, targetAtomLabel) : null; + + final EList sigTypes = documentRootOriginal.getAlloy().getInstance().getSig(); + for (final SigType sigType : sigTypes) { + String label = sigType.getLabel(); + label = label.substring(label.lastIndexOf("/") + 1); + if (sourceAtomType.equals(label)) { + if (sourceAtomIndex != null) { + atomType_OS = sigType.getAtom().get(sourceAtomIndex); + } + } + if (targetAtomType.equals(label)) { + if (targetAtomIndex != null) { + atomType_OT = sigType.getAtom().get(targetAtomIndex); + } + } + } + + final TupleType tupleType = persistenceFactory.eINSTANCE.createTupleType(); + if (atomType_OS.equals(atomType_OT)) { + atomType_OS = AlloyUtilities.cloneAtomType(atomType_OS); + } + tupleType.getAtom().add(atomType_OS); + tupleType.getAtom().add(atomType_OT); + tupleType.setReasoned(true); + discoveredRelationCount++; + + documentRootOriginal = AlloyUtilities.getDocumentRoot(); // R + for (final FieldType fieldType : documentRootOriginal.getAlloy().getInstance() + .getField()) { + if (fieldType.getID() == fieldType_O.getID()) { + fieldType.getTuple().add(tupleType); + break; + } + } + + if (AlloyOtherSolutionDiscovering.getInstance().getOldDiscoverRelations() + .get(fieldType_O.getID()) == null) { + AlloyOtherSolutionDiscovering.getInstance().getOldDiscoverRelations() + .put(fieldType_O.getID(), new ArrayList<>(Arrays.asList(tupleType))); + } else { + AlloyOtherSolutionDiscovering.getInstance().getOldDiscoverRelations() + .get(fieldType_O.getID()).add(tupleType); + } + + AlloyUtilities.writeDocumentRoot(documentRootOriginal); // W + } + } + } + + final String discoveringAtomMessage = + "Discovering on atoms successfully completed.\nDiscovered atom count: " + + discoveredAtomCount; + final String discoveringRelationMessage = + "Discovering on relations successfully completed.\nDiscovered relation count: " + + discoveredRelationCount; + + JOptionPane.showMessageDialog(null, discoveringAtomMessage + "\n" + discoveringRelationMessage, + "Discovering Atom", JOptionPane.INFORMATION_MESSAGE); + } + + private AtomType getOriginalAtomType(final DocumentRoot documentRootOriginal, + final String name_R) { + final String name = name_R.substring(0, name_R.lastIndexOf("_")); + final int id = + Integer.parseInt(name_R.substring(name_R.lastIndexOf("_") + 1, name_R.lastIndexOf("$"))); + + for (final SigType sigType : documentRootOriginal.getAlloy().getInstance().getSig()) { + String label = sigType.getLabel(); + label = label.substring(label.lastIndexOf("/") + 1); + if (label.equals(name)) { + return sigType.getAtom().get(id); + } + } + return null; + // return + // AlloyUtilities.getSigTypeById(AlloyUtilities.getSigTypeIdByName(name)).getAtom().get(id); + } + + private int addStrayedAtom2Sig(final DocumentRoot documentRoot, final String sigName) { + int count = 0; + final String id = MarkerFactory.generateId(documentRoot); + + final AtomType atomType = persistenceFactory.eINSTANCE.createAtomType(); + atomType.setLabel(id); + atomType.setReasoned(true); + + for (final SigType sigType : documentRoot.getAlloy().getInstance().getSig()) { + String label = sigType.getLabel(); + label = label.substring(sigType.getLabel().lastIndexOf("/") + 1); + if (label.equals(sigName)) { + sigType.getAtom().add(atomType); + count = sigType.getAtom().size(); + break; + } + } + + AlloyUtilities.writeDocumentRoot(documentRoot); + + return count - 1; + } + + public void setFirstAns(final A4Solution ans) { + AlloyOtherSolutionDiscovering.solutions.clear(); + AlloyOtherSolutionDiscovering.solutions.add(ans); + currentSolutionIndex = 0; + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/discovery/AlloyParserForDiscovering.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/discovery/AlloyParserForDiscovering.java new file mode 100644 index 00000000..fdc67f3d --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/discovery/AlloyParserForDiscovering.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.configuration.alloy.discovery; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.eclipse.emf.common.util.URI; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; +import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Options; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.TranslateAlloyToKodkod; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; +import eu.modelwriter.traceability.core.persistence.internal.ModelIO; + +public class AlloyParserForDiscovering { + + private final String filename; + String xmlFileLoc = InstanceTranslatorDiscovering.baseFileDirectory + "discovering.xml"; + + public AlloyParserForDiscovering(final String filename) { + this.filename = filename; + } + + public DocumentRoot getDocumentRoot() { + @SuppressWarnings("rawtypes") + final ModelIO modelIO = new ModelIO<>(); + @SuppressWarnings("rawtypes") + List list = null; + try { + list = modelIO.read(URI.createFileURI(xmlFileLoc)); + } catch (final IOException e) { + return null; + } + if (list == null || list.isEmpty()) { + return null; + } + final DocumentRoot documentRoot = (DocumentRoot) list.get(0); + return documentRoot; + } + + protected DocumentRoot parse() { + Module world; + A4Solution ans = null; + try { + final A4Reporter rep = new A4Reporter() { + @Override + public void warning(final ErrorWarning msg) { + System.out.print("Relevance Warning:\n" + msg.toString().trim() + "\n\n"); + System.out.flush(); + } + }; + + world = CompUtil.parseEverything_fromFile(rep, null, filename); + + final A4Options options = new A4Options(); + options.solver = A4Options.SatSolver.SAT4J; + + for (final Command command : world.getAllCommands()) { + + ans = TranslateAlloyToKodkod.execute_command(rep, world.getAllReachableSigs(), command, + options); + + if (ans.satisfiable()) { + AlloyOtherSolutionDiscovering.getInstance().setFirstAns(ans); + + ans.writeXML(xmlFileLoc); + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder; + try { + builder = factory.newDocumentBuilder(); + final File file = new File(xmlFileLoc); + final Document document = builder.parse(file); + final Node instance = document.getElementsByTagName("instance").item(0); + instance.getAttributes().removeNamedItem("command"); + + Transformer transformer; + try { + transformer = TransformerFactory.newInstance().newTransformer(); + final DOMSource source = new DOMSource(document); + final StreamResult result = new StreamResult(file); + transformer.transform(source, result); + } catch (final Exception e) { + } + + } catch (ParserConfigurationException | SAXException | IOException e) { + e.printStackTrace(); + } + + break; + } + } + + } catch (final Err e) { + e.printStackTrace(); + } + + final DocumentRoot documentRoot = getDocumentRoot(); + + return documentRoot; + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/discovery/AlloyValidatorDiscovering.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/discovery/AlloyValidatorDiscovering.java new file mode 100644 index 00000000..208a22c7 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/discovery/AlloyValidatorDiscovering.java @@ -0,0 +1,57 @@ +package eu.modelwriter.configuration.alloy.discovery; + +import java.util.Map; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; +import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Options; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.TranslateAlloyToKodkod; + +public class AlloyValidatorDiscovering { + public static Map discoverSigs; + + public static boolean validate() { + final InstanceTranslatorDiscovering instanceTranslator = new InstanceTranslatorDiscovering(); + instanceTranslator.translate(); + AlloyValidatorDiscovering.discoverSigs = instanceTranslator.getDiscoverSig2ExpectValue(); + + final String filename = instanceTranslator.getBaseFileDirectory() + "discovering.als"; + + try { + final A4Reporter rep = new A4Reporter() { + @Override + public void warning(final ErrorWarning msg) { + System.out.print("Relevance Warning:\n" + msg.toString().trim() + "\n\n"); + System.out.flush(); + } + }; + Module world = null; + + world = CompUtil.parseEverything_fromFile(rep, null, filename); + + final A4Options options = new A4Options(); + options.solver = A4Options.SatSolver.SAT4J; + + for (final Command command : world.getAllCommands()) { + A4Solution ans = null; + ans = TranslateAlloyToKodkod.execute_command(rep, world.getAllReachableSigs(), command, + options); + + if (ans.satisfiable()) { + return true; + } + } + + } catch (final Err e) { + e.printStackTrace(); + } + + return false; + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/discovery/InstanceTranslatorDiscovering.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/discovery/InstanceTranslatorDiscovering.java new file mode 100644 index 00000000..575543f8 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/discovery/InstanceTranslatorDiscovering.java @@ -0,0 +1,305 @@ +package eu.modelwriter.configuration.alloy.discovery; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.emf.common.util.EList; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.traceability.core.persistence.AlloyType; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; +import eu.modelwriter.traceability.core.persistence.FieldType; +import eu.modelwriter.traceability.core.persistence.SigType; +import eu.modelwriter.traceability.core.persistence.SourceType; +import eu.modelwriter.traceability.core.persistence.TupleType; +import eu.modelwriter.traceability.core.persistence.TypeType; +import eu.modelwriter.traceability.core.persistence.TypesType; + +public class InstanceTranslatorDiscovering { + + // public static void main(final String[] args) { + // final String txt = "-- Discover@ContractRequirement expect 2"; + // + // final String re1 = "(-)"; // Any Single Character 1 + // final String re2 = "(-)"; // Any Single Character 2 + // final String re3 = "(\\s*)"; // White Space 1 + // final String re4 = "(Discover|discover)"; // Word 1 + // final String re5 = "(@)"; // Any Single Character 3 + // final String re6 = "((?:[a-z0-9_]+))"; // Word 2 + // final String re7 = "(\\s*)"; // White Space 2 + // final String re8 = "(expect|Expect|exactly|Exactly)"; // Word 3 + // final String re9 = "(\\s*)"; // White Space 3 + // final String re10 = "(\\d+)"; // Integer Number 1 + // final String re11 = "(\\s*)"; // White Space 4 + // + // final Pattern p = + // Pattern.compile(re1 + re2 + re3 + re4 + re5 + re6 + re7 + re8 + re9 + + // re10 + re11, + // Pattern.CASE_INSENSITIVE | Pattern.DOTALL); + // final Matcher m = p.matcher(txt); + // if (m.find()) { + // final String c1 = m.group(1); + // final String c2 = m.group(2); + // final String ws1 = m.group(3); + // final String word1 = m.group(4); + // final String c3 = m.group(5); + // final String word2 = m.group(6); + // final String ws2 = m.group(7); + // final String word3 = m.group(8); + // final String ws3 = m.group(9); + // final String int1 = m.group(10); + // final String ws4 = m.group(11); + // System.out.print("(" + c1.toString() + ")" + "(" + c2.toString() + ")" + + // "(" + ws1.toString() + // + ")" + "(" + word1.toString() + ")" + "(" + c3.toString() + ")" + "(" + + // word2.toString() + // + ")" + "(" + ws2.toString() + ")" + "(" + word3.toString() + ")" + "(" + + // ws3.toString() + // + ")" + "(" + int1.toString() + ")" + "(" + ws4.toString() + ")" + "\n"); + // } + // } + + public static String baseFileDirectory = ResourcesPlugin.getWorkspace().getRoot().getLocation() + + " .modelwriter discovering ".replace(" ", System.getProperty("file.separator")); + + private final Map sig2oldValue = new HashMap<>(); + private final Map discoverSig2ExpectValue = new HashMap<>(); + + private final StringBuilder builder; + + public InstanceTranslatorDiscovering() { + builder = new StringBuilder(); + } + + private void createFactPart(final DocumentRoot documentRoot, final List fields) { + builder.append("fact {\n"); + + final Map> discoverFields = new HashMap<>(); + final Map> allParents = new HashMap<>(); + + final Iterator iterator = discoverSig2ExpectValue.keySet().iterator(); + while (iterator.hasNext()) { + final String sigName = iterator.next(); + allParents.put(sigName, new ArrayList<>()); + final int id = AlloyUtilities.getSigTypeIdByName(sigName); + final ArrayList allParentIds = AlloyUtilities.getAllParentIds(id); + for (final Integer parentId : allParentIds) { + final String parentName = AlloyUtilities.getSigNameById(parentId); + allParents.get(sigName).add(parentName); + } + + for (final FieldType fieldType : fields) { + for (final TypesType typesType : fieldType.getTypes()) { + for (final TypeType typeType : typesType.getType()) { + String label = AlloyUtilities.getSigTypeById(typeType.getID()).getLabel(); + label = label.substring(label.lastIndexOf("/") + 1); + if (label.equals(sigName) || allParents.get(sigName).contains(label)) { + if (discoverFields.containsKey(sigName)) { + discoverFields.get(sigName).add(fieldType.getLabel()); + } else { + discoverFields.put(sigName, new ArrayList<>(Arrays.asList(fieldType.getLabel()))); + } + break; + } + } + } + } + } + + for (final FieldType fieldType : fields) { + final String fieldName = fieldType.getLabel(); + + final List allSources = new ArrayList<>(); + final List allTargets = new ArrayList<>(); + for (final TypesType typesType : fieldType.getTypes()) { + final EList typeType = typesType.getType(); + allSources.addAll(AlloyUtilities.getAllChildNames(typeType.get(0).getID())); + allTargets.addAll(AlloyUtilities.getAllChildNames(typeType.get(1).getID())); + } + + boolean accept = false; + for (final Entry> entry : discoverFields.entrySet()) { + final String discoverSig = entry.getKey(); + final List discoverFieldsOfSig = entry.getValue(); + if (discoverFieldsOfSig.contains(fieldName) + && (allSources.contains(discoverSig) || allTargets.contains(discoverSig))) { + accept = true; + break; + } + } + + String parentSigName = AlloyUtilities.getSigTypeById(fieldType.getParentID()).getLabel(); + parentSigName = parentSigName.substring(parentSigName.lastIndexOf("/") + 1); + + final EList tuples = fieldType.getTuple(); + for (int i = 0; i < tuples.size(); i++) { + + final String sigName1 = AlloyUtilities + .getAtomNameById(tuples.get(i).getAtom().get(0).getLabel()).replace("$", "_"); + final String sigName2 = AlloyUtilities + .getAtomNameById(tuples.get(i).getAtom().get(1).getLabel()).replace("$", "_"); + + builder.append(sigName1 + "->" + sigName2); + + if (i + 1 != tuples.size()) { + builder.append(" +\n"); + } else if (accept) { + builder.append(" in " + parentSigName + "<:" + fieldName + "\n"); + } else { + builder.append(" = " + parentSigName + "<:" + fieldName + "\n"); + } + } + + final List allRelations = new ArrayList<>(); + for (final List value : discoverFields.values()) { + allRelations.addAll(value); + } + + if (fieldType.getTuple().size() == 0 && !accept) { + builder.append(parentSigName + "." + fieldName + " = none\n"); + } + } + + builder.append("}\n"); + } + + private File createFile(final String filePath) { + File file = null; + try { + file = new File(filePath); + + if (!file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + // if file doesn't exists, then create it + if (!file.exists()) { + file.createNewFile(); + } + } catch (final IOException e) { + e.printStackTrace(); + } + return file; + } + + private void createSigPart(final List sigs) { + for (final SigType sig : sigs) { + final String sigName = sig.getLabel().substring(sig.getLabel().lastIndexOf("/") + 1); + for (int i = 0; i < sig.getAtom().size(); i++) { + builder.append("one sig " + sigName + "_" + i + " extends " + sigName + "{ } \n"); + } + } + } + + private void createSourceFiles(final EList sources) { + boolean isFirst = false; + for (final SourceType source : sources) { + final String sourceFilePath = source.getFilename(); + final String fileName = sourceFilePath.substring( + sourceFilePath.lastIndexOf(System.getProperty("file.separator")) + 1, + sourceFilePath.lastIndexOf(".")); + if (!isFirst) { + builder.append("open " + fileName + "\n"); + isFirst = true; + } + final String newFilePath = + InstanceTranslatorDiscovering.baseFileDirectory + fileName + ".als"; + + final String content = removeDiscoveringParts(source.getContent()); + writeContentToFile(newFilePath, content); + } + } + + public String getBaseFileDirectory() { + return InstanceTranslatorDiscovering.baseFileDirectory; + } + + public Map getDiscoverSig2ExpectValue() { + return discoverSig2ExpectValue; + } + + private String removeDiscoveringParts(final String content) { + final List lines = Arrays.asList(content.split("\n")); + + final Pattern p = + Pattern.compile("(-)(-)(\\s*)(Discover|discover)(@)((?:[a-z0-9_]+))(\\s*)(\\d+)(\\s*)", + Pattern.CASE_INSENSITIVE | Pattern.DOTALL); + + for (final String line : lines) { + final Matcher matcher = p.matcher(line); + + if (!matcher.find()) { + continue; + } else { + final String discoveredSig = matcher.group(6); // it gets ((?:[a-z]+)) group + final int value = Integer.valueOf(matcher.group(8));// it gets (\\d+) group + + discoverSig2ExpectValue.put(discoveredSig, value); + } + } + + return content; + } + + public void translate() { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + final AlloyType alloy = documentRoot.getAlloy(); + + calcOldSigValues(alloy.getInstance().getSig()); + createSourceFiles(alloy.getSource()); + createSigPart(alloy.getInstance().getSig()); + createFactPart(documentRoot, alloy.getInstance().getField()); + createRunPart(); + + writeContentToFile(InstanceTranslatorDiscovering.baseFileDirectory + "discovering.als", + builder.toString()); + } + + private void createRunPart() { + builder.append("pred show{}\n"); + builder.append("run show for"); + + for (final Entry oldEntry : sig2oldValue.entrySet()) { + int value = oldEntry.getValue(); + + if (discoverSig2ExpectValue.containsKey(oldEntry.getKey())) { + final int discoverSigExpectValue = discoverSig2ExpectValue.get(oldEntry.getKey()); + value += discoverSigExpectValue; + } + builder.append("\n" + "exactly " + value + " " + oldEntry.getKey() + ","); + } + + builder.replace(0, builder.length(), builder.substring(0, builder.length() - 1)); // to delete + // last ',' + } + + private void calcOldSigValues(final EList sigTypes) { + for (final SigType sigType : sigTypes) { + final String sigName = sigType.getLabel().substring(sigType.getLabel().lastIndexOf("/") + 1); + if (sigType.getID() > 3) { + sig2oldValue.put(sigName, sigType.getAbstract() != null ? 0 : sigType.getAtom().size()); + } + } + } + + private void writeContentToFile(final String filePath, final String content) { + try { + final File file = createFile(filePath); + final FileOutputStream out = new FileOutputStream(file); + out.write(content.getBytes()); + out.close(); + } catch (final IOException e) { + e.printStackTrace(); + } + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/evaluator/Evaluator.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/evaluator/Evaluator.java new file mode 100644 index 00000000..a05e17f6 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/evaluator/Evaluator.java @@ -0,0 +1,201 @@ +package eu.modelwriter.configuration.alloy.evaluator; + +import java.io.File; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.prefs.Preferences; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.Computer; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.Util.BooleanPref; +import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.alloy4.XMLNode; +import edu.mit.csail.sdg.alloy4compiler.ast.Expr; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil; +import edu.mit.csail.sdg.alloy4compiler.sim.SimInstance; +import edu.mit.csail.sdg.alloy4compiler.sim.SimTuple; +import edu.mit.csail.sdg.alloy4compiler.sim.SimTupleset; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.A4SolutionReader; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Tuple; +import edu.mit.csail.sdg.alloy4compiler.translator.A4TupleSet; +import kodkod.engine.fol2sat.HigherOrderDeclException; + +public class Evaluator implements Computer { + private String filename = null; + /** True if Alloy Analyzer should enable the new Implicit This name resolution. */ + private static final BooleanPref ImplicitThis = new BooleanPref("ImplicitThis"); + + /** This enum defines the set of possible message verbosity levels. */ + private enum Verbosity { + /** Level 0. */ + DEFAULT("0", "low"), + /** Level 1. */ + VERBOSE("1", "medium"), + /** Level 2. */ + DEBUG("2", "high"), + /** Level 3. */ + FULLDEBUG("3", "debug only"); + /** Returns true if it is greater than or equal to "other". */ + public boolean geq(final Verbosity other) { + return ordinal() >= other.ordinal(); + } + + /** This is a unique String for this value; it should be kept consistent in future versions. */ + private final String id; + /** This is the label that the toString() method will return. */ + private final String label; + + /** Constructs a new Verbosity value with the given id and label. */ + private Verbosity(final String id, final String label) { + this.id = id; + this.label = label; + } + + /** + * Given an id, return the enum value corresponding to it (if there's no match, then return + * DEFAULT). + */ + private static Verbosity parse(final String id) { + for (final Verbosity vb : Verbosity.values()) { + if (vb.id.equals(id)) { + return vb; + } + } + return DEFAULT; + } + + /** Returns the human-readable label for this enum value. */ + @Override + public final String toString() { + return label; + } + + /** Saves this value into the Java preference object. */ + private void set() { + Preferences.userNodeForPackage(Util.class).put("Verbosity", id); + } + + /** + * Reads the current value of the Java preference object (if it's not set, then return DEFAULT). + */ + private static Verbosity get() { + return Verbosity.parse(Preferences.userNodeForPackage(Util.class).get("Verbosity", "")); + } + }; + + @Override + public final String compute(final Object input) throws Exception { + if (input instanceof File) { + filename = ((File) input).getAbsolutePath(); + return ""; + } + if (!(input instanceof String)) { + return ""; + } + final String str = (String) input; + if (str.trim().length() == 0) { + return ""; // Empty line + } + Module root = null; + A4Solution ans = null; + try { + final Map fc = new LinkedHashMap<>(); + final XMLNode x = new XMLNode(new File(filename)); + if (!x.is("alloy")) { + throw new Exception(); + } + String mainname = null; + for (final XMLNode sub : x) { + if (sub.is("instance")) { + mainname = sub.getAttribute("filename"); + break; + } + } + if (mainname == null) { + throw new Exception(); + } + for (final XMLNode sub : x) { + if (sub.is("source")) { + final String name = sub.getAttribute("filename"); + final String content = sub.getAttribute("content"); + fc.put(name, content); + } + } + root = CompUtil.parseEverything_fromFile(A4Reporter.NOP, fc, mainname, + Version.experimental && Evaluator.ImplicitThis.get() ? 2 : 1); + ans = A4SolutionReader.read(root.getAllReachableSigs(), x); + for (final ExprVar a : ans.getAllAtoms()) { + root.addGlobal(a.label, a); + } + for (final ExprVar a : ans.getAllSkolems()) { + root.addGlobal(a.label, a); + } + } catch (final Throwable ex) { + throw new ErrorFatal("Failed to read or parse the XML file."); + } + try { + final Expr e = CompUtil.parseOneExpression_fromString(root, str); + if ("yes".equals(System.getProperty("debug")) && Verbosity.get() == Verbosity.FULLDEBUG) { + final SimInstance simInst = Evaluator.convert(root, ans); + return simInst.visitThis(e).toString() + (simInst.wasOverflow() ? " (OF)" : ""); + } else { + return ans.eval(e).toString(); + } + } catch (final HigherOrderDeclException ex) { + throw new ErrorType("Higher-order quantification is not allowed in the evaluator."); + } + } + + /** Converts an A4Solution into a SimInstance object. */ + private static SimInstance convert(final Module root, final A4Solution ans) throws Err { + final SimInstance ct = new SimInstance(root, ans.getBitwidth(), ans.getMaxSeq()); + for (final Sig s : ans.getAllReachableSigs()) { + if (!s.builtin) { + ct.init(s, Evaluator.convert(ans.eval(s))); + } + for (final edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field f : s.getFields()) { + if (!f.defined) { + ct.init(f, Evaluator.convert(ans.eval(f))); + } + } + } + for (final ExprVar a : ans.getAllAtoms()) { + ct.init(a, Evaluator.convert(ans.eval(a))); + } + for (final ExprVar a : ans.getAllSkolems()) { + ct.init(a, Evaluator.convert(ans.eval(a))); + } + return ct; + } + + /** Converts an A4TupleSet into a SimTupleset object. */ + private static SimTupleset convert(final Object object) throws Err { + if (!(object instanceof A4TupleSet)) { + throw new ErrorFatal("Unexpected type error: expecting an A4TupleSet."); + } + final A4TupleSet s = (A4TupleSet) object; + if (s.size() == 0) { + return SimTupleset.EMPTY; + } + final List list = new ArrayList<>(s.size()); + final int arity = s.arity(); + for (final A4Tuple t : s) { + final String[] array = new String[arity]; + for (int i = 0; i < t.arity(); i++) { + array[i] = t.atom(i); + } + list.add(SimTuple.make(array)); + } + return SimTupleset.make(list); + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/reasoning/AlloyOtherSolutionReasoning.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/reasoning/AlloyOtherSolutionReasoning.java new file mode 100644 index 00000000..4157e254 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/reasoning/AlloyOtherSolutionReasoning.java @@ -0,0 +1,322 @@ +package eu.modelwriter.configuration.alloy.reasoning; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.swing.JOptionPane; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.URI; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.traceability.core.persistence.AtomType; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; +import eu.modelwriter.traceability.core.persistence.FieldType; +import eu.modelwriter.traceability.core.persistence.TupleType; +import eu.modelwriter.traceability.core.persistence.persistenceFactory; +import eu.modelwriter.traceability.core.persistence.internal.ModelIO; + +public class AlloyOtherSolutionReasoning { + + private static Map> reasonRelations; + private static AlloyOtherSolutionReasoning instance; + private Map> oldReasons; + String xmlFileLoc = InstanceTranslatorReasoning.baseFileDirectory + "reasoning.xml"; + private static List solutions; + private int currentSolutionIndex; + + public static AlloyOtherSolutionReasoning getInstance() { + if (AlloyOtherSolutionReasoning.instance == null) { + AlloyOtherSolutionReasoning.instance = new AlloyOtherSolutionReasoning(); + AlloyOtherSolutionReasoning.instance.oldReasons = new HashMap<>(); + AlloyOtherSolutionReasoning.solutions = new ArrayList<>(); + AlloyOtherSolutionReasoning.reasonRelations = new HashMap<>(); + } + + return AlloyOtherSolutionReasoning.instance; + } + + public boolean next() throws Err { + A4Solution ans; + if (AlloyOtherSolutionReasoning.solutions.size() <= currentSolutionIndex + 1) { + ans = AlloyOtherSolutionReasoning.solutions.get(currentSolutionIndex).next(); + if (ans.equals(AlloyOtherSolutionReasoning.solutions.get(currentSolutionIndex))) { + return false; + } + AlloyOtherSolutionReasoning.solutions.add(ans); + currentSolutionIndex++; + } else { + ans = AlloyOtherSolutionReasoning.solutions.get(currentSolutionIndex + 1); + currentSolutionIndex++; + } + + if (AlloyOtherSolutionReasoning.reasonRelations.isEmpty()) { + return false; + } + + if (ans.satisfiable()) { + ans.writeXML(xmlFileLoc); + if (!parse()) { + return false; + } + } else { + return false; + } + + removeOldReasoning(); + return reasoning(); + } + + public boolean previous() throws Err { + A4Solution ans; + if (currentSolutionIndex - 1 < 0) { + return false; + } else { + ans = AlloyOtherSolutionReasoning.solutions.get(currentSolutionIndex - 1); + currentSolutionIndex--; + } + + if (AlloyOtherSolutionReasoning.reasonRelations.isEmpty()) { + return false; + } + + if (ans.satisfiable()) { + ans.writeXML(xmlFileLoc); + if (!parse()) { + return false; + } + } else { + return false; + } + + removeOldReasoning(); + return reasoning(); + } + + private boolean parse() { + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder; + try { + builder = factory.newDocumentBuilder(); + final File file = new File(xmlFileLoc); + final Document document = builder.parse(file); + final Node instance = document.getElementsByTagName("instance").item(0); + instance.getAttributes().removeNamedItem("command"); + + Transformer transformer; + try { + transformer = TransformerFactory.newInstance().newTransformer(); + final DOMSource source = new DOMSource(document); + final StreamResult result = new StreamResult(file); + transformer.transform(source, result); + } catch (final Exception e) { + } + + return true; + } catch (ParserConfigurationException | SAXException | IOException e) { + e.printStackTrace(); + } + return false; + } + + private void removeOldReasoning() { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + + final Iterator>> iterator = oldReasons.entrySet().iterator(); + final EList fieldTypes = documentRoot.getAlloy().getInstance().getField(); + while (iterator.hasNext()) { + final Entry> entry = iterator.next(); + for (final FieldType fieldType : fieldTypes) { + if (fieldType.getID() == entry.getKey()) { + for (final TupleType oldTupleType : entry.getValue()) { + final Iterator tupleIter = fieldType.getTuple().iterator(); + final AtomType oldAtomType0 = oldTupleType.getAtom().get(0); + final AtomType oldAtomType1 = oldTupleType.getAtom().get(1); + while (tupleIter.hasNext()) { + final TupleType tupleType = tupleIter.next(); + if (tupleType.isReasoned()) { + final AtomType atomType0 = tupleType.getAtom().get(0); + final AtomType atomType1 = tupleType.getAtom().get(1); + if (oldAtomType0.getLabel().equals(atomType0.getLabel()) + && oldAtomType1.getLabel().equals(atomType1.getLabel())) { + tupleIter.remove(); + } + } + } + } + } + } + } + + AlloyUtilities.writeDocumentRoot(documentRoot); + + oldReasons.clear(); + } + + public void finish() { + AlloyOtherSolutionReasoning.solutions.clear(); + currentSolutionIndex = 0; + AlloyOtherSolutionReasoning.reasonRelations.clear(); + } + + public DocumentRoot getDocumentRoot() { + @SuppressWarnings("rawtypes") + final ModelIO modelIO = new ModelIO<>(); + @SuppressWarnings("rawtypes") + List list = null; + try { + list = modelIO.read(URI.createFileURI(xmlFileLoc)); + } catch (final IOException e) { + return null; + } + if (list == null || list.isEmpty()) { + return null; + } + final DocumentRoot documentRoot = (DocumentRoot) list.get(0); + return documentRoot; + } + + public A4Solution getCurrentSolution() { + return AlloyOtherSolutionReasoning.solutions.isEmpty() ? null + : AlloyOtherSolutionReasoning.solutions.get(currentSolutionIndex); + } + + public Map> getOldReasons() { + return oldReasons; + } + + public void setReasonRelations(final Map> reasonRelations) { + AlloyOtherSolutionReasoning.reasonRelations = reasonRelations; + } + + private boolean reasoning() { + final DocumentRoot documentRootReasoning = getDocumentRoot(); + final DocumentRoot documentRootOriginal = AlloyUtilities.getDocumentRoot(); + if (documentRootReasoning == null) { + return false; + } + + reason(documentRootOriginal, documentRootReasoning); + + return true; + } + + private void reason(final DocumentRoot documentRootOriginal, + final DocumentRoot documentRootReasoning) { + int discoveredRelationCount = 0; + for (final FieldType fieldType_R : documentRootReasoning.getAlloy().getInstance().getField()) { + for (final FieldType fieldType_O : documentRootOriginal.getAlloy().getInstance().getField()) { + if (!fieldType_R.getLabel().equals(fieldType_O.getLabel())) { + continue; + } + + final int sourceId_R = fieldType_R.getParentID(); + final String sourceSigName_R = + AlloyUtilities.getSigNameById(sourceId_R, documentRootReasoning); + if (!AlloyOtherSolutionReasoning.reasonRelations.containsKey(sourceSigName_R) + || !AlloyOtherSolutionReasoning.reasonRelations.get(sourceSigName_R).contains(fieldType_R.getLabel())) { + continue; + } + + final int sourceId_O = fieldType_O.getParentID(); + final String sourceSigName_O = + AlloyUtilities.getSigNameById(sourceId_O, documentRootOriginal); + if (!AlloyOtherSolutionReasoning.reasonRelations.containsKey(sourceSigName_O) + || !AlloyOtherSolutionReasoning.reasonRelations.get(sourceSigName_O).contains(fieldType_O.getLabel())) { + continue; + } + + if (!sourceSigName_O.equals(sourceSigName_R)) { + continue; + } + + if (fieldType_O.getTuple().size() == fieldType_R.getTuple().size()) { + continue; + } + + for (final TupleType tuple_R : fieldType_R.getTuple()) { + AtomType atomType0_R = getOriginalAtomType(tuple_R.getAtom().get(0).getLabel()); + final AtomType atomType1_R = getOriginalAtomType(tuple_R.getAtom().get(1).getLabel()); + + if (atomType0_R == null || atomType1_R == null) { + continue; + } + + boolean exists = false; + for (final TupleType tuple_O : fieldType_O.getTuple()) { + if (atomType0_R.getLabel().equals(tuple_O.getAtom().get(0).getLabel()) + && atomType1_R.getLabel().equals(tuple_O.getAtom().get(1).getLabel())) { + exists = true; + break; + } + } + + if (!exists || fieldType_O.getTuple().size() == 0) { + final TupleType tupleType = persistenceFactory.eINSTANCE.createTupleType(); + if (atomType0_R.equals(atomType1_R)) { + atomType0_R = AlloyUtilities.cloneAtomType(atomType0_R); + } + tupleType.getAtom().add(atomType0_R); + tupleType.getAtom().add(atomType1_R); + tupleType.setReasoned(true); + + if (AlloyOtherSolutionReasoning.getInstance().getOldReasons() + .get(fieldType_O.getID()) == null) { + AlloyOtherSolutionReasoning.getInstance().getOldReasons().put(fieldType_O.getID(), + new ArrayList<>(Arrays.asList(tupleType))); + } else { + AlloyOtherSolutionReasoning.getInstance().getOldReasons().get(fieldType_O.getID()) + .add(tupleType); + } + + discoveredRelationCount++; + fieldType_O.getTuple().add(tupleType); + } + } + } + } + + AlloyUtilities.writeDocumentRoot(documentRootOriginal); + + JOptionPane.showMessageDialog(null, + "Discovering on relations successfully completed.\nDiscovered relation count: " + + discoveredRelationCount, + "Discovering on Relations", JOptionPane.WARNING_MESSAGE); + } + + private AtomType getOriginalAtomType(final String name_R) { + if (name_R.contains("/")) { + return null; + } + final String name = name_R.substring(0, name_R.lastIndexOf("_")); + final int id = + Integer.parseInt(name_R.substring(name_R.lastIndexOf("_") + 1, name_R.lastIndexOf("$"))); + + return AlloyUtilities.getSigTypeById(AlloyUtilities.getSigTypeIdByName(name)).getAtom().get(id); + } + + public void setFirstAns(final A4Solution ans) { + AlloyOtherSolutionReasoning.solutions.clear(); + AlloyOtherSolutionReasoning.solutions.add(ans); + currentSolutionIndex = 0; + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/reasoning/AlloyParserForReasoning.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/reasoning/AlloyParserForReasoning.java new file mode 100644 index 00000000..ecc4153f --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/reasoning/AlloyParserForReasoning.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.configuration.alloy.reasoning; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.eclipse.emf.common.util.URI; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; +import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Options; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.TranslateAlloyToKodkod; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; +import eu.modelwriter.traceability.core.persistence.internal.ModelIO; + +public class AlloyParserForReasoning { + + private final String filename; + String xmlFileLoc = InstanceTranslatorReasoning.baseFileDirectory + "reasoning.xml"; + + public AlloyParserForReasoning(final String filename) { + this.filename = filename; + } + + public DocumentRoot getDocumentRoot() { + @SuppressWarnings("rawtypes") + final ModelIO modelIO = new ModelIO<>(); + @SuppressWarnings("rawtypes") + List list = null; + try { + list = modelIO.read(URI.createFileURI(xmlFileLoc)); + } catch (final IOException e) { + return null; + } + if (list == null || list.isEmpty()) { + return null; + } + final DocumentRoot documentRoot = (DocumentRoot) list.get(0); + return documentRoot; + } + + protected DocumentRoot parse() { + Module world; + A4Solution ans = null; + try { + final A4Reporter rep = new A4Reporter() { + @Override + public void warning(final ErrorWarning msg) { + System.out.print("Relevance Warning:\n" + msg.toString().trim() + "\n\n"); + System.out.flush(); + } + }; + + world = CompUtil.parseEverything_fromFile(rep, null, filename); + + final A4Options options = new A4Options(); + options.solver = A4Options.SatSolver.SAT4J; + + for (final Command command : world.getAllCommands()) { + + ans = TranslateAlloyToKodkod.execute_command(rep, world.getAllReachableSigs(), command, + options); + + if (ans.satisfiable()) { + AlloyOtherSolutionReasoning.getInstance().setFirstAns(ans); + + ans.writeXML(xmlFileLoc); + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder; + try { + builder = factory.newDocumentBuilder(); + final File file = new File(xmlFileLoc); + final Document document = builder.parse(file); + final Node instance = document.getElementsByTagName("instance").item(0); + instance.getAttributes().removeNamedItem("command"); + + Transformer transformer; + try { + transformer = TransformerFactory.newInstance().newTransformer(); + final DOMSource source = new DOMSource(document); + final StreamResult result = new StreamResult(file); + transformer.transform(source, result); + } catch (final Exception e) { + } + + } catch (ParserConfigurationException | SAXException | IOException e) { + e.printStackTrace(); + } + + break; + } + } + + } catch (final Err e) { + e.printStackTrace(); + } + + final DocumentRoot documentRoot = getDocumentRoot(); + + return documentRoot; + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/reasoning/AlloyReasoning.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/reasoning/AlloyReasoning.java new file mode 100644 index 00000000..808dffa2 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/reasoning/AlloyReasoning.java @@ -0,0 +1,150 @@ +package eu.modelwriter.configuration.alloy.reasoning; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import javax.swing.JOptionPane; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.traceability.core.persistence.AtomType; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; +import eu.modelwriter.traceability.core.persistence.FieldType; +import eu.modelwriter.traceability.core.persistence.TupleType; +import eu.modelwriter.traceability.core.persistence.persistenceFactory; + +public class AlloyReasoning { + + private final String alsPath = + InstanceTranslatorReasoning.baseFileDirectory + "reasoning.als"; + + private final String xmlPath = + InstanceTranslatorReasoning.baseFileDirectory + "reasoning.xml"; + + public boolean reasoning() { + final File reasoningXml = new File(xmlPath); + if (reasoningXml.exists()) { + reasoningXml.delete(); + } + final File reasoningAls = new File(alsPath); + if (reasoningAls.exists()) { + reasoningAls.delete(); + } + + if (!AlloyValidatorReasoning.validate()) { + return false; + } + + final AlloyParserForReasoning parser = new AlloyParserForReasoning(alsPath); + + AlloyOtherSolutionReasoning.getInstance() + .setReasonRelations(AlloyValidatorReasoning.reasonRelations); + + final DocumentRoot documentRootReasoning = parser.parse(); + final DocumentRoot documentRootOriginal = AlloyUtilities.getDocumentRoot(); + if (documentRootReasoning == null) { + return false; + } + + reason(documentRootOriginal, documentRootReasoning); + + return true; + } + + private void reason(final DocumentRoot documentRootOriginal, + final DocumentRoot documentRootReasoning) { + final Map> reasonRelations = AlloyValidatorReasoning.reasonRelations; + int discoveredRelationCount = 0; + for (final FieldType fieldType_R : documentRootReasoning.getAlloy().getInstance().getField()) { + for (final FieldType fieldType_O : documentRootOriginal.getAlloy().getInstance().getField()) { + if (!fieldType_R.getLabel().equals(fieldType_O.getLabel())) { + continue; + } + + final int sourceId_R = fieldType_R.getParentID(); + final String sourceSigName_R = + AlloyUtilities.getSigNameById(sourceId_R, documentRootReasoning); + if (!reasonRelations.containsKey(sourceSigName_R) + || !reasonRelations.get(sourceSigName_R).contains(fieldType_R.getLabel())) { + continue; + } + + final int sourceId_O = fieldType_O.getParentID(); + final String sourceSigName_O = + AlloyUtilities.getSigNameById(sourceId_O, documentRootOriginal); + if (!reasonRelations.containsKey(sourceSigName_O) + || !reasonRelations.get(sourceSigName_O).contains(fieldType_O.getLabel())) { + continue; + } + + if (!sourceSigName_O.equals(sourceSigName_R)) { + continue; + } + + if (fieldType_O.getTuple().size() == fieldType_R.getTuple().size()) { + continue; + } + + for (final TupleType tuple_R : fieldType_R.getTuple()) { + AtomType atomType0_R = getOriginalAtomType(tuple_R.getAtom().get(0).getLabel()); + final AtomType atomType1_R = getOriginalAtomType(tuple_R.getAtom().get(1).getLabel()); + + if (atomType0_R == null || atomType1_R == null) { + continue; + } + + boolean exists = false; + for (final TupleType tuple_O : fieldType_O.getTuple()) { + if (atomType0_R.getLabel().equals(tuple_O.getAtom().get(0).getLabel()) + && atomType1_R.getLabel().equals(tuple_O.getAtom().get(1).getLabel())) { + exists = true; + break; + } + } + + if (!exists || fieldType_O.getTuple().size() == 0) { + final TupleType tupleType = persistenceFactory.eINSTANCE.createTupleType(); + if (atomType0_R.equals(atomType1_R)) { + atomType0_R = AlloyUtilities.cloneAtomType(atomType0_R); + } + tupleType.getAtom().add(atomType0_R); + tupleType.getAtom().add(atomType1_R); + tupleType.setReasoned(true); + + if (AlloyOtherSolutionReasoning.getInstance().getOldReasons() + .get(fieldType_O.getID()) == null) { + AlloyOtherSolutionReasoning.getInstance().getOldReasons().put(fieldType_O.getID(), + new ArrayList<>(Arrays.asList(tupleType))); + } else { + AlloyOtherSolutionReasoning.getInstance().getOldReasons().get(fieldType_O.getID()) + .add(tupleType); + } + + discoveredRelationCount++; + fieldType_O.getTuple().add(tupleType); + } + } + } + } + + AlloyUtilities.writeDocumentRoot(documentRootOriginal); + + JOptionPane.showMessageDialog(null, + "Discovering on relations successfully completed.\nDiscovered relation count: " + + discoveredRelationCount, + "Discovering on Relations", JOptionPane.WARNING_MESSAGE); + } + + private AtomType getOriginalAtomType(final String name_R) { + if (name_R.contains("/")) { + return null; + } + final String name = name_R.substring(0, name_R.lastIndexOf("_")); + final int id = + Integer.parseInt(name_R.substring(name_R.lastIndexOf("_") + 1, name_R.lastIndexOf("$"))); + + return AlloyUtilities.getSigTypeById(AlloyUtilities.getSigTypeIdByName(name)).getAtom().get(id); + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/reasoning/AlloyValidatorReasoning.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/reasoning/AlloyValidatorReasoning.java new file mode 100644 index 00000000..53eab744 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/reasoning/AlloyValidatorReasoning.java @@ -0,0 +1,59 @@ +package eu.modelwriter.configuration.alloy.reasoning; + +import java.util.List; +import java.util.Map; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; +import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Options; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.TranslateAlloyToKodkod; + +public class AlloyValidatorReasoning { + public static Map> reasonRelations; + + public static boolean validate() { + final InstanceTranslatorReasoning instanceTranslator = new InstanceTranslatorReasoning(); + instanceTranslator.translate(); + AlloyValidatorReasoning.reasonRelations = instanceTranslator.getReasonRelations(); + + final String filename = instanceTranslator.getBaseFileDirectory() + "reasoning.als"; + + try { + final A4Reporter rep = new A4Reporter() { + @Override + public void warning(final ErrorWarning msg) { + System.out.print("Relevance Warning:\n" + msg.toString().trim() + "\n\n"); + System.out.flush(); + } + }; + Module world = null; + + world = CompUtil.parseEverything_fromFile(rep, null, filename); + + final A4Options options = new A4Options(); + options.solver = A4Options.SatSolver.SAT4J; + + for (final Command command : world.getAllCommands()) { + A4Solution ans = null; + ans = TranslateAlloyToKodkod.execute_command(rep, world.getAllReachableSigs(), command, + options); + + if (ans.satisfiable()) { + return true; + } + } + + } catch (final Err e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return false; + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/reasoning/InstanceTranslatorReasoning.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/reasoning/InstanceTranslatorReasoning.java new file mode 100644 index 00000000..76450b4a --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/reasoning/InstanceTranslatorReasoning.java @@ -0,0 +1,268 @@ +package eu.modelwriter.configuration.alloy.reasoning; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.emf.common.util.EList; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.traceability.core.persistence.AlloyType; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; +import eu.modelwriter.traceability.core.persistence.FieldType; +import eu.modelwriter.traceability.core.persistence.SigType; +import eu.modelwriter.traceability.core.persistence.SourceType; +import eu.modelwriter.traceability.core.persistence.TupleType; +import eu.modelwriter.traceability.core.persistence.TypeType; +import eu.modelwriter.traceability.core.persistence.TypesType; + +public class InstanceTranslatorReasoning { + + // public static void main(final String[] args) { + // final String txt = "--Reason@contents.ad"; + // + // final String re1 = "(-)"; // Any Single Character 1 + // final String re2 = "(-)"; // Any Single Character 2 + // final String re3 = "(\\s*)"; // White Space 1 + // final String re4 = "(Reason|reason)"; // Word 1 + // final String re5 = "(@)"; // Any Single Character 3 + // final String re6 = "((?:[a-z0-9_]+))"; // Word 2 + // final String re7 = "(\\.)"; + // final String re8 = "((?:[a-z0-9_]+))"; // Word 2 + // final String re9 = "(\\s*)"; // White Space 2 + // + // final Pattern p = Pattern.compile(re1 + re2 + re3 + re4 + re5 + re6 + re7 + // + re8 + re9, + // Pattern.CASE_INSENSITIVE | Pattern.DOTALL); + // final Matcher m = p.matcher(txt); + // if (m.find()) { + // final String c1 = m.group(1); + // final String c2 = m.group(2); + // final String ws1 = m.group(3); + // final String word1 = m.group(4); + // final String c3 = m.group(5); + // final String word2 = m.group(6); + // final String dot1 = m.group(7); + // final String word3 = m.group(8); + // final String ws2 = m.group(9); + // System.out.print("(" + c1.toString() + ")" + "(" + c2.toString() + ")" + + // "(" + ws1.toString() + // + ")" + "(" + word1.toString() + ")" + "(" + c3.toString() + ")" + "(" + + // word2.toString() + // + ")" + "(" + dot1.toString() + ")" + "(" + word3.toString() + ")" + "(" + // + ws2.toString() + // + ")" + "\n"); + // } + // } + + public static String baseFileDirectory = ResourcesPlugin.getWorkspace().getRoot().getLocation() + + " .modelwriter reasoning ".replace(" ", System.getProperty("file.separator")); + + private final Map> reasonRelations = new HashMap<>(); + + private final StringBuilder builder; + + private final Map sig2oldValue = new HashMap<>(); + + public InstanceTranslatorReasoning() { + builder = new StringBuilder(); + } + + private void createFactPart(final DocumentRoot documentRoot, final List fields) { + builder.append("fact {\n"); + + for (final FieldType field : fields) { + final String fieldName = field.getLabel(); + + final List allSources = new ArrayList<>(); + for (final TypesType typesType : field.getTypes()) { + final EList typeType = typesType.getType(); + allSources.addAll(AlloyUtilities.getAllChildNames(typeType.get(0).getID())); + } + + boolean accept = false; + for (final Entry> entry : reasonRelations.entrySet()) { + final String discoverSig = entry.getKey(); + final List discoverFieldsOfSig = entry.getValue(); + if (discoverFieldsOfSig.contains(fieldName) && allSources.contains(discoverSig)) { + accept = true; + break; + } + } + + int tupleCount = 0; + + String parentSigName = AlloyUtilities.getSigTypeById(field.getParentID()).getLabel(); + parentSigName = parentSigName.substring(parentSigName.indexOf("/") + 1); + + for (final TupleType tuple : field.getTuple()) { + tupleCount++; + + final String sigName1 = + AlloyUtilities.getAtomNameById(tuple.getAtom().get(0).getLabel()).replace("$", "_"); + final String sigName2 = + AlloyUtilities.getAtomNameById(tuple.getAtom().get(1).getLabel()).replace("$", "_"); + + builder.append(sigName1 + "->" + sigName2); + + if (tupleCount != field.getTuple().size()) { + builder.append(" +\n"); + } else if (accept) { + builder.append(" in " + parentSigName + "<:" + fieldName + "\n"); + } else { + builder.append(" = " + parentSigName + "<:" + fieldName + "\n"); + } + + } + + final List allRelations = new ArrayList<>(); + for (final List value : reasonRelations.values()) { + allRelations.addAll(value); + } + + if (field.getTuple().size() == 0 && !accept) { + builder.append(parentSigName + "." + fieldName + " = none\n"); + } + } + + builder.append("}\n"); + } + + private File createFile(final String filePath) { + File file = null; + try { + file = new File(filePath); + + if (!file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + // if file doesn't exists, then create it + if (!file.exists()) { + file.createNewFile(); + } + } catch (final IOException e) { + e.printStackTrace(); + } + return file; + } + + private void createSigPart(final List sigs) { + for (final SigType sig : sigs) { + final String sigName = sig.getLabel().substring(sig.getLabel().lastIndexOf("/") + 1); + for (int i = 0; i < sig.getAtom().size(); i++) { + builder.append("one sig " + sigName + "_" + i + " extends " + sigName + "{ } \n"); + } + } + } + + private void createSourceFiles(final EList sources) { + boolean isFirst = false; + for (final SourceType source : sources) { + final String sourceFilePath = source.getFilename(); + final String fileName = sourceFilePath.substring( + sourceFilePath.lastIndexOf(System.getProperty("file.separator")) + 1, + sourceFilePath.lastIndexOf(".")); + if (!isFirst) { + builder.append("open " + fileName + "\n"); + isFirst = true; + } + final String newFilePath = InstanceTranslatorReasoning.baseFileDirectory + fileName + ".als"; + + final String content = removeReasoningParts(source.getContent()); + writeContentToFile(newFilePath, content); + } + } + + public String getBaseFileDirectory() { + return InstanceTranslatorReasoning.baseFileDirectory; + } + + public Map> getReasonRelations() { + return reasonRelations; + } + + private String removeReasoningParts(final String content) { + final List lines = Arrays.asList(content.split("\n")); + + final Pattern p = + Pattern.compile("(-)(-)(\\s*)(Reason|reason)(@)((?:[a-z0-9_]+))(\\.)((?:[a-z0-9_]+))(\\s*)", + Pattern.CASE_INSENSITIVE | Pattern.DOTALL); + + for (final String line : lines) { + final Matcher matcher = p.matcher(line); + + if (!matcher.find()) { + continue; + } else { + final String sig = matcher.group(6); // it gets ((?:[a-z]+)) + // group + final String relation = matcher.group(8); + if (reasonRelations.containsKey(sig)) { + if (!reasonRelations.get(sig).contains(relation)) { + reasonRelations.get(sig).add(relation); + } + } else { + reasonRelations.put(sig, new ArrayList<>(Arrays.asList(relation))); + } + } + } + + return content; + } + + public void translate() { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + final AlloyType alloy = documentRoot.getAlloy(); + + calcOldSigValues(alloy.getInstance().getSig()); + createSourceFiles(alloy.getSource()); + createSigPart(alloy.getInstance().getSig()); + createFactPart(documentRoot, alloy.getInstance().getField()); + createRunPart(); + + writeContentToFile(InstanceTranslatorReasoning.baseFileDirectory + "reasoning.als", + builder.toString()); + } + + private void createRunPart() { + builder.append("pred show{}\n"); + builder.append("run show for"); + + for (final Entry oldEntry : sig2oldValue.entrySet()) { + final int value = oldEntry.getValue(); + builder.append("\nexactly " + value + " " + oldEntry.getKey() + ","); + } + + builder.replace(0, builder.length(), builder.substring(0, builder.length() - 1)); // to delete + // last ',' + } + + private void writeContentToFile(final String filePath, final String content) { + try { + final File file = createFile(filePath); + final FileOutputStream out = new FileOutputStream(file); + out.write(content.getBytes()); + out.close(); + } catch (final IOException e) { + e.printStackTrace(); + } + } + + private void calcOldSigValues(final EList sigTypes) { + for (final SigType sigType : sigTypes) { + final String sigName = sigType.getLabel().substring(sigType.getLabel().lastIndexOf("/") + 1); + if (sigType.getID() > 3) { + sig2oldValue.put(sigName, sigType.getAbstract() != null ? 0 : sigType.getAtom().size()); + } + } + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/trace/LoadItem.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/trace/LoadItem.java new file mode 100644 index 00000000..7ce539d6 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/trace/LoadItem.java @@ -0,0 +1,119 @@ +package eu.modelwriter.configuration.alloy.trace; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.resources.IFile; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EClassifier; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.resource.Resource; + +import eu.modelwriter.configuration.internal.EcoreUtilities; +import eu.modelwriter.configuration.internal.Utilities; + +public class LoadItem { + /** + * alias from -- loadAlias + */ + private String alias; + /** + * Paths from -- loadModel & -- loadInstace + */ + private IFile modelFile, instanceFile; + /** + * Root EObjects + */ + private EObject modelRoot = null, instanceRoot = null; + + private Resource instanceResource = null; + + private Map allEClasses; + + public LoadItem(String alias, String modelFilePath, String instanceFilePath) + throws TraceException, NullPointerException { + this.alias = alias; + allEClasses = new HashMap<>(); + try { + modelFile = Utilities.getIFileFromPath(modelFilePath); + modelRoot = EcoreUtilities.getRootObject(modelFile.getFullPath().toString()); + } catch (IOException | IllegalArgumentException e) { + System.err.println("Tarski: EMF Model file can't loaded, load alias: " + alias); + } + try { + instanceFile = Utilities.getIFileFromPath(instanceFilePath); + instanceResource = EcoreUtilities.loadInstanceModel(instanceFile.getFullPath().toString()); + instanceRoot = instanceResource.getContents().get(0); + for (Object pack : instanceResource.getResourceSet().getPackageRegistry().values()) { + loadEClasses((EPackage) pack); + } + } catch (IOException | IllegalArgumentException e) { + System.err.println("Tarski: EMF Instance file can't loaded, load alias: " + alias); + } + + if (modelRoot == null && instanceRoot == null) { + throw new TraceException("Both model and instace files can't loaded for alias " + alias); + } + } + + + private void loadEClasses(EPackage packageee) { + for (EClassifier classifier : packageee.getEClassifiers()) { + allEClasses.put(classifier.getName(), (EClass) classifier); + } + for (EPackage subPackage : packageee.getESubpackages()) { + loadEClasses(subPackage); + } + } + + public String getAlias() { + return alias; + } + + public void setAlias(String alias) { + this.alias = alias; + } + + public IFile getModelFile() { + return modelFile; + } + + public void setModelFile(IFile modelFile) { + this.modelFile = modelFile; + } + + public IFile getInstanceFile() { + return instanceFile; + } + + public void setInstanceFile(IFile instanceFile) { + this.instanceFile = instanceFile; + } + + public EObject getModelRoot() { + return modelRoot; + } + + public void setModelRoot(EObject modelRoot) { + this.modelRoot = modelRoot; + } + + public EObject getInstanceRoot() { + return instanceRoot; + } + + public void setInstanceRoot(EObject instanceRoot) { + this.instanceRoot = instanceRoot; + } + + public Map getAllEClasses() { + return allEClasses; + } + + public EClass getEClass(String eClassName) { + return allEClasses.get(eClassName); + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/trace/RelationTrace.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/trace/RelationTrace.java new file mode 100644 index 00000000..fc2a7d81 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/trace/RelationTrace.java @@ -0,0 +1,66 @@ +package eu.modelwriter.configuration.alloy.trace; + +public class RelationTrace extends Trace { + private String relationName; + private String referenceName; + private String className; + private SigTrace source = null; + private SigTrace target = null; + + public RelationTrace(String alias, String className, String relationName, String referenceName) { + super(alias); + this.className = className; + this.relationName = relationName; + this.referenceName = referenceName; + } + + public RelationTrace(String alias, String relationName, String referenceName, SigTrace source, + SigTrace target) { + super(alias); + setRelationName(relationName); + setReferenceName(referenceName); + setSource(source); + setTarget(target); + } + + public String getRelationName() { + return relationName; + } + + public void setRelationName(String relationName) { + this.relationName = relationName; + } + + public String getReferenceName() { + return referenceName; + } + + public void setReferenceName(String referenceName) { + this.referenceName = referenceName; + } + + public SigTrace getSource() { + return source; + } + + public void setSource(SigTrace source) { + this.source = source; + } + + public SigTrace getTarget() { + return target; + } + + public void setTarget(SigTrace target) { + this.target = target; + } + + public String getClassName() { + return className; + } + + public void setClassName(String className) { + this.className = className; + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/trace/SigTrace.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/trace/SigTrace.java new file mode 100644 index 00000000..3e90190c --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/trace/SigTrace.java @@ -0,0 +1,57 @@ +package eu.modelwriter.configuration.alloy.trace; + +import org.eclipse.emf.ecore.EClass; + +public class SigTrace extends Trace { + private String sigType; + private String className; + private LoadItem load; + private EClass eClass; + + public SigTrace(String alias, String sigName, String className) { + super(alias); + setSigType(sigName); + setClassName(className); + } + + public SigTrace(String alias, String sigType, String className, LoadItem load, EClass eClass) { + super(alias); + this.sigType = sigType; + this.className = className; + this.load = load; + this.eClass = eClass; + } + + public String getClassName() { + return className; + } + + public EClass getEClass() { + return eClass; + } + + public LoadItem getLoad() { + return load; + } + + public String getSigType() { + return sigType; + } + + public void setClassName(String className) { + this.className = className; + } + + public void seteClass(EClass eClass) { + this.eClass = eClass; + } + + public void setLoad(LoadItem load) { + this.load = load; + } + + public void setSigType(String sigType) { + this.sigType = sigType; + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/trace/Trace.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/trace/Trace.java new file mode 100644 index 00000000..e7249607 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/trace/Trace.java @@ -0,0 +1,17 @@ +package eu.modelwriter.configuration.alloy.trace; + +public abstract class Trace { + private String alias; + + public Trace(String alias) { + setAlias(alias); + } + + public String getAlias() { + return alias; + } + + public void setAlias(String alias) { + this.alias = alias; + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/trace/TraceException.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/trace/TraceException.java new file mode 100644 index 00000000..1ae8ea9b --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/trace/TraceException.java @@ -0,0 +1,20 @@ +package eu.modelwriter.configuration.alloy.trace; + +public class TraceException extends Exception { + + /** + * + */ + private static final long serialVersionUID = -4595785190626648593L; + + private final String message; + + public TraceException(String message) { + this.message = message; + } + + @Override + public String getMessage() { + return message; + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/trace/TraceManager.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/trace/TraceManager.java new file mode 100644 index 00000000..1a33f0ec --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/trace/TraceManager.java @@ -0,0 +1,373 @@ +package eu.modelwriter.configuration.alloy.trace; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Scanner; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.util.EcoreUtil; + +import eu.modelwriter.configuration.internal.EcoreUtilities; +import eu.modelwriter.configuration.internal.Utilities; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class TraceManager { + + private static TraceManager instance = null; + + private String alloyPath; + + private final List sigTraces = new ArrayList(); + private final List relationTraces = new ArrayList(); + private final List loads = new ArrayList(); + + /** + * + * @return @TraceManager instance + */ + public static TraceManager get() { + if (instance == null) + instance = new TraceManager(); + return instance; + } + + private TraceManager() {} + + /** + * Loads traces from given path + * + * @param alloyPath Path to load alloy file + * @throws TraceException on any error + */ + public void loadSpec(String alloyPath) throws TraceException { + this.alloyPath = alloyPath; + loads.clear(); + sigTraces.clear(); + relationTraces.clear(); + scanFile(alloyPath, true); + } + + public void reload() throws TraceException { + if (!alloyPath.isEmpty()) + loadSpec(alloyPath); + else + throw new TraceException("Alloy file is not set!"); + } + + public boolean hasTraces() { + return !sigTraces.isEmpty() && !relationTraces.isEmpty(); + } + + public boolean hasInstance() { + for (LoadItem loadItem : loads) { + if (loadItem.getInstanceRoot() != null) + return true; + } + return false; + } + + public boolean hasSigTrace(String sigTypeName) { + try { + return getSigTraceByType(sigTypeName).getLoad().getInstanceRoot() != null; + } catch (TraceException e) { + return false; + } + } + + public List getLoads() { + return loads; + } + + private void scanFile(String alloyPath, boolean scanTraces) throws TraceException { + final Pattern sigTracePattern = Pattern.compile( + "(\\s*)(-)(-)(\\s*)(Trace|trace)(@)((?:[a-z0-9_]+))(\\.)((?:[a-z0-9_]+))(\\s*)", + Pattern.CASE_INSENSITIVE | Pattern.DOTALL); + final Pattern relationTracePattern = Pattern.compile( + "(\\s*)(-)(-)(\\s*)(Trace|trace)(@)((?:[a-z0-9_]+))(\\.)((?:[a-z0-9_]+))(\\.)((?:[a-z0-9_]+))(\\s*)", + Pattern.CASE_INSENSITIVE | Pattern.DOTALL); + + Scanner scanner = null; + try { + final File file = new File(alloyPath); + scanner = new Scanner(file); + } catch (final FileNotFoundException e) { + throw new TraceException("File not found. Path: " + alloyPath); + } + + while (scanner.hasNextLine()) { + String line = Utilities.getNextLine(scanner); + + if (line.toLowerCase().startsWith("--loadalias") + || line.toLowerCase().startsWith("-- loadalias")) { + findLoads(scanner, line); + } + + if (scanTraces) { + final Matcher sigTrace = sigTracePattern.matcher(line); + final Matcher relationTrace = relationTracePattern.matcher(line); + + if (relationTrace.find()) { + findRelationTrace(scanner, line, relationTrace); + } else if (sigTrace.find()) { + findSigTrace(scanner, line, sigTrace); + } + } + } + scanner.close(); + } + + private void findSigTrace(Scanner scanner, String line, Matcher sigTraceMatcher) + throws TraceException { + String traceAlias = sigTraceMatcher.group(7); + String className = sigTraceMatcher.group(9); + do { + line = Utilities.getNextLine(scanner); + } while (!line.contains("sig ")); + + if (line.contains("sig ")) { + final int start = line.indexOf("sig ") + 4; + int stop = line.indexOf(" ", start); + stop = stop == -1 ? line.indexOf("{", start) : stop; + stop = stop == -1 ? line.indexOf("\n", start) : stop; + final String sigType = line.substring(start, stop).trim(); + LoadItem loadItem = getLoadByAlias(traceAlias); + if (loadItem == null) + throw new TraceException("Load traces must be above than other traces!"); + SigTrace sigTrace = + new SigTrace(traceAlias, sigType, className, loadItem, loadItem.getEClass(className)); + sigTraces.add(sigTrace); + } + } + + private void findRelationTrace(Scanner scanner, String line, Matcher relationTraceMatcher) + throws TraceException { + String traceAlias = relationTraceMatcher.group(7); + String traceClass = relationTraceMatcher.group(9); + String traceReference = relationTraceMatcher.group(11); + + do { + line = Utilities.getNextLine(scanner); + } while (!line.contains(":")); + + if (line.contains(":")) { + final String[] strings = line.split(" "); + final String relation = strings[0].replaceAll(":", "").trim(); + @SuppressWarnings("unused") + final String targetSig = + strings[strings.length - 1].replaceAll(",", "").replaceAll("}", "").trim(); + RelationTrace relationTrace = + new RelationTrace(traceAlias, traceClass, relation, traceReference); + relationTrace.setSource(getSigTraceByClassName(traceClass)); + relationTraces.add(relationTrace); + } + } + + private void findLoads(Scanner scanner, String line) throws TraceException { + String alias = "", modelFilePath = "", instanceFilePath = ""; + alias = line.substring(line.indexOf("@") + 1).trim(); + for (int i = 0; i < 2; i++) { + String nextLine = Utilities.getNextLine(scanner); + if (nextLine.toLowerCase().contains("loadmodel@")) { + modelFilePath = nextLine.substring(nextLine.indexOf("@") + 1); + } else if (nextLine.toLowerCase().contains("loadinstance@")) { + instanceFilePath = nextLine.substring(nextLine.indexOf("@") + 1); + } + } + if (!alias.isEmpty() /* && !modelFilePath.isEmpty() && !instanceFilePath.isEmpty() */) { + loads.add(new LoadItem(alias, modelFilePath, instanceFilePath)); + } else { + throw new TraceException("Can't load EMF models!"); + } + } + + public SigTrace getSigTraceByType(String type) throws TraceException { + return sigTraces.stream().filter(sigTrace -> sigTrace.getSigType().equals(type)).findFirst() + .orElseThrow(() -> new TraceException("There is no trace for the sig: " + type)); + } + + public SigTrace getSigTraceByClassName(String name) throws TraceException { + return sigTraces.stream().filter(sigTrace -> sigTrace.getClassName().equals(name)).findFirst() + .orElseThrow(() -> new TraceException("There is no trace for the EClass: " + name)); + } + + public RelationTrace getRelationTraceByReferenceName(String reference) { + return relationTraces.stream().filter(rt -> rt.getReferenceName().equals(reference)).findFirst() + .orElse(null); + } + + public RelationTrace getRelationTrace(String className, String refName) { + return relationTraces.stream() + .filter( + rt -> (rt.getClassName().equals(className) && rt.getReferenceName().equals(refName))) + .findFirst().orElse(null); + } + + public RelationTrace getRelationTrace2(String className, String relName) { + return relationTraces.stream() + .filter(rt -> (rt.getClassName().equals(className) && rt.getRelationName().equals(relName))) + .findFirst().orElse(null); + } + + @SuppressWarnings("unused") + private RelationTrace getRelationTraceBySigType(String sourceSigType, String relationName) { + return relationTraces.stream().filter(t -> (t.getSource().getSigType().equals(sourceSigType) + && t.getRelationName().equals(relationName))).findFirst().orElse(null); + } + + public RelationTrace getRelationTraceByRelationName(String rel) { + return relationTraces.stream().filter(rt -> rt.getRelationName().equals(rel)).findFirst() + .orElse(null); + } + + public LoadItem getLoadByAlias(String alias) { + return loads.stream().filter(load -> load.getAlias().equals(alias)).findFirst().orElse(null); + } + + public LoadItem getLoadByInstance(EObject instance) { + return loads.stream().filter(load -> load.getInstanceRoot().equals(instance)).findFirst() + .orElse(null); + } + + public boolean deleteEObject(String sigType, String relativeObjectURI) + throws IOException, TraceException { + EObject eObject = findEObject(sigType, relativeObjectURI); + if (eObject != null) { + Resource eResource = eObject.eResource(); + EcoreUtil.delete(eObject); + eResource.save(null); + return true; + } + return false; + } + + private EObject findEObject(String sigTypeName, String relativeObjectURI) throws TraceException { + if (relativeObjectURI != null && sigTypeName != null) { + SigTrace trace = getSigTraceByType(sigTypeName); + return EcoreUtil.getEObject(trace.getLoad().getInstanceRoot(), relativeObjectURI); + } + return null; + } + + public EObject findEObject(IMarker marker) throws TraceException { + if (marker == null) + return null; + String relURI = marker.getAttribute(MarkUtilities.RELATIVE_URI, ""); + String sigTypeName = marker.getAttribute(MarkUtilities.MARKER_TYPE, ""); + return findEObject(sigTypeName, relURI); + } + + @SuppressWarnings("unused") + private EObject findEObject(String uri) { + String rootURI = uri.split("#")[0]; + String relURI = uri.split("#")[1]; + EObject root = findInstanceRootByURI(rootURI); + + return EcoreUtil.getEObject(root, relURI); + } + + private EObject findInstanceRootByURI(String rootURI) { + for (LoadItem loadItem : loads) { + if (loadItem.getInstanceRoot().eResource().getURI().toString().equals(rootURI)) { + return loadItem.getInstanceRoot(); + } + } + return null; + } + + public EObject createEObject(String sigTypeName, String atomName, IMarker source) + throws TraceException { + SigTrace trace = getSigTraceByType(sigTypeName); + EClass eClass = trace.getEClass(); + EObject eObject = EcoreUtil.create(eClass); + EcoreUtilities.eSetAttributeByName(eObject, "name", atomName); + EcoreUtilities.putIntoContainer( + source == null ? trace.getLoad().getInstanceRoot() : findEObject(source), eObject); + EcoreUtilities.saveResource(trace.getLoad().getInstanceRoot()); + return eObject; + } + + public IMarker createMarkerForEObject(EObject eObject) throws TraceException { + SigTrace trace = getSigTraceByClassName(eObject.eClass().getName()); + return MarkerFactory.createInstanceMarker(eObject, trace.getLoad().getInstanceFile(), + trace.getSigType()); + } + + public Set getContainerSigTypes(String sigTypeName) { + try { + SigTrace trace = getSigTraceByType(sigTypeName); + return findContainers(trace.getLoad().getAllEClasses().values(), sigTypeName); + } catch (TraceException e) { + return new HashSet(); + } + } + + public String getContainmentRelation(IMarker fromMarker, IMarker toMarker) throws TraceException { + EObject source = findEObject(fromMarker); + EObject target = findEObject(toMarker); + EReference eReference = EcoreUtilities.getContainmentEReference(source, target); + if (eReference != null) + return getRelationTrace(((EClass) eReference.eContainer()).getName(), eReference.getName()) + .getRelationName(); + return null; + } + + public void createReference(IMarker fromMarker, IMarker toMarker, String relationName) + throws TraceException { + EObject source = findEObject(fromMarker); + EObject target = findEObject(toMarker); + EReference ref = null; + for (EReference eReference : source.eClass().getEAllReferences()) { + RelationTrace relationTrace = + getRelationTrace(((EClass) eReference.eContainer()).getName(), eReference.getName()); + if (relationTrace != null && relationTrace.getRelationName().equals(relationName)) { + ref = eReference; + break; + } + } + if (ref != null) { + EcoreUtilities.eSetReferenceByName(source, ref.getName(), target); + EcoreUtilities.saveResource(source); + } + } + + public Set findContainers(Collection collection, String selectedType) { + Set result = new HashSet(); + SigTrace typeTrace; + try { + typeTrace = getSigTraceByType(selectedType); + } catch (TraceException e1) { + return result; + } + EList superTypes = typeTrace.getEClass().getEAllSuperTypes(); + for (EClass eClass : collection) { + for (EReference eReference : eClass.getEAllReferences()) { + if (eReference.isContainment()) { + try { + if (superTypes.stream() + .anyMatch(s -> s.getName().equals(eReference.getEReferenceType().getName()))) { + result.add(getSigTraceByClassName(eClass.getName()).getSigType()); + } + } catch (TraceException e) { + // no need to handle + } + } + } + } + return result; + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/validation/AlloyValidator.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/validation/AlloyValidator.java new file mode 100644 index 00000000..ffaf67e3 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/validation/AlloyValidator.java @@ -0,0 +1,52 @@ +package eu.modelwriter.configuration.alloy.validation; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; +import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Options; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.TranslateAlloyToKodkod; + +public class AlloyValidator { + public static boolean isCanceled = false; + + public static boolean validate() { + AlloyValidator.isCanceled = false; + final InstanceTranslator instanceTranslator = new InstanceTranslator(); + instanceTranslator.translate(); + + final String filename = instanceTranslator.getBaseFileDirectory() + "validation.als"; + + try { + final A4Reporter rep = new A4Reporter() { + @Override + public void warning(final ErrorWarning msg) { + System.out.print("Relevance Warning:\n" + msg.toString().trim() + "\n\n"); + System.out.flush(); + } + }; + Module world = null; + + world = CompUtil.parseEverything_fromFile(rep, null, filename); + + final A4Options options = new A4Options(); + options.solver = A4Options.SatSolver.SAT4J; + + for (final Command command : world.getAllCommands()) { + A4Solution ans = null; + ans = TranslateAlloyToKodkod.execute_command(rep, world.getAllReachableSigs(), command, + options); + if (ans.satisfiable()) { + return true; + } + } + + } catch (final Err e) { + e.printStackTrace(); + } + return false; + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/validation/InstanceTranslator.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/validation/InstanceTranslator.java new file mode 100644 index 00000000..2be57be9 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy/validation/InstanceTranslator.java @@ -0,0 +1,191 @@ +package eu.modelwriter.configuration.alloy.validation; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.emf.common.util.EList; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.traceability.core.persistence.AlloyType; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; +import eu.modelwriter.traceability.core.persistence.FieldType; +import eu.modelwriter.traceability.core.persistence.SigType; +import eu.modelwriter.traceability.core.persistence.SourceType; +import eu.modelwriter.traceability.core.persistence.TupleType; + +public class InstanceTranslator { + + public static String baseFileDirectory = ResourcesPlugin.getWorkspace().getRoot().getLocation() + + " .modelwriter validation ".replace(" ", System.getProperty("file.separator")); + + private final StringBuilder builder; + + private final Map sig2oldValue = new HashMap<>(); + + public InstanceTranslator() { + builder = new StringBuilder(); + } + + private void createFactPart(final DocumentRoot documentRoot, final List fields) { + builder.append("fact {\n"); + + for (final FieldType field : fields) { + final String fieldName = field.getLabel(); + int tupleCount = 0; + + String parentSigName = AlloyUtilities.getSigTypeById(field.getParentID()).getLabel(); + parentSigName = parentSigName.substring(parentSigName.indexOf("/") + 1); + + for (final TupleType tuple : field.getTuple()) { + tupleCount++; + + final String sigName1 = + AlloyUtilities.getAtomNameById(tuple.getAtom().get(0).getLabel()).replace("$", ""); + final String sigName2 = + AlloyUtilities.getAtomNameById(tuple.getAtom().get(1).getLabel()).replace("$", ""); + + builder.append(sigName1 + "->" + sigName2); + + if (tupleCount != field.getTuple().size()) { + builder.append(" +\n"); + } else { + builder.append(" = " + parentSigName + "<:" + fieldName + "\n"); + } + } + + if (field.getTuple().size() == 0) { + builder.append(parentSigName + "." + fieldName + " = none\n"); + } + } + + builder.append("}\n"); + } + + private File createFile(final String filePath) { + File file = null; + try { + file = new File(filePath); + + if (!file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + // if file doesn't exists, then create it + if (!file.exists()) { + file.createNewFile(); + } + } catch (final IOException e) { + e.printStackTrace(); + } + return file; + } + + private void createSigPart(final List sigs) { + for (final SigType sig : sigs) { + final String sigName = sig.getLabel().substring(sig.getLabel().indexOf("/") + 1); + for (int i = 0; i < sig.getAtom().size(); i++) { + builder.append("one sig " + sigName + i + " extends " + sigName + "{ } \n"); + } + } + } + + private void createSourceFiles(final EList sources) { + boolean isFirst = false; + for (final SourceType source : sources) { + final String sourceFilePath = source.getFilename(); + final String fileName = sourceFilePath.substring( + sourceFilePath.lastIndexOf(System.getProperty("file.separator")) + 1, + sourceFilePath.lastIndexOf(".")); + if (!isFirst) { + builder.append("open " + fileName + "\n"); + isFirst = true; + } + final String newFilePath = InstanceTranslator.baseFileDirectory + fileName + ".als"; + + final String newContent = removeReasoningParts(source.getContent()); + writeContentToFile(newFilePath, newContent); + } + } + + public String getBaseFileDirectory() { + return InstanceTranslator.baseFileDirectory; + } + + private String removeReasoningParts(final String content) { + String newContent = ""; + + final List lines = Arrays.asList(content.split("\n")); + + final Pattern p = + Pattern.compile("(-)(-)(\\s*)(Reason|reason)(@)((?:[a-z0-9_]+))(\\.)((?:[a-z0-9_]+))(\\s*)", + Pattern.CASE_INSENSITIVE | Pattern.DOTALL); + + boolean isRemoveFact = false; + for (final String line : lines) { + final Matcher matcher = p.matcher(line); + if (matcher.find()) { + isRemoveFact = true; + } else if (!isRemoveFact) { + newContent += line + "\n"; + } else if (line.contains("}")) { + isRemoveFact = false; + } + } + + return newContent; + } + + public void translate() { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + final AlloyType alloy = documentRoot.getAlloy(); + + calcOldSigValues(alloy.getInstance().getSig()); + createSourceFiles(alloy.getSource()); + createSigPart(alloy.getInstance().getSig()); + createFactPart(documentRoot, alloy.getInstance().getField()); + createRunPart(); + + writeContentToFile(InstanceTranslator.baseFileDirectory + "validation.als", builder.toString()); + } + + private void createRunPart() { + builder.append("pred show{}\n"); + builder.append("run show for"); + + for (final Entry oldEntry : sig2oldValue.entrySet()) { + final int value = oldEntry.getValue(); + builder.append("\nexactly " + value + " " + oldEntry.getKey() + ","); + } + + builder.replace(0, builder.length(), builder.substring(0, builder.length() - 1)); // to delete + // last ',' + } + + private void writeContentToFile(final String filePath, final String content) { + try { + final File file = createFile(filePath); + final FileOutputStream out = new FileOutputStream(file); + out.write(content.getBytes()); + out.close(); + } catch (final IOException e) { + e.printStackTrace(); + } + } + + private void calcOldSigValues(final EList sigTypes) { + for (final SigType sigType : sigTypes) { + final String sigName = sigType.getLabel().substring(sigType.getLabel().lastIndexOf("/") + 1); + if (sigType.getID() > 3) { + sig2oldValue.put(sigName, sigType.getAbstract() != null ? 0 : sigType.getAtom().size()); + } + } + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/AlloyRunCommandsPage.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/AlloyRunCommandsPage.java new file mode 100644 index 00000000..b5acde7c --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/AlloyRunCommandsPage.java @@ -0,0 +1,78 @@ +package eu.modelwriter.configuration.alloy2emf; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.List; + +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import eu.modelwriter.configuration.alloy.trace.TraceException; + +public class AlloyRunCommandsPage extends AlloyToEMFWizardPage { + + private final ConstList commandList; + private List list; + + public AlloyRunCommandsPage(final ConstList commands) { + super("Run Commands"); + setTitle("Select Run Command"); + resetMessage(); + commandList = commands; + } + + private void resetMessage() { + setDescription("Select a command to start."); + } + + @Override + public void createControl(final Composite parent) { + final Composite container = new Composite(parent, SWT.NULL); + container.setLayout(new FillLayout(SWT.HORIZONTAL)); + + list = new org.eclipse.swt.widgets.List(container, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); + + for (final Command command : commandList) { + if (!command.check) + list.add("run " + command.label); + } + + list.add("Create new run"); + list.setSelection(0); + list.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + setPageComplete(true); + resetMessage(); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + + } + }); + setControl(container); + } + + @Override + public boolean nextPressed() throws TraceException { + + getAlloyToEMF().setSelectedCommand(getSelection()); + BoundSelectionPage nextPage = (BoundSelectionPage) getNextPage(); + nextPage.setSelectedCommand(getSelection()); + + return true; + } + + public Command getSelection() { + // Create new run command + if (list.getSelectionIndex() == commandList.size()) + return null; + + return commandList.get(list.getSelectionIndex()); + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/AlloySolutionSelectionPage.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/AlloySolutionSelectionPage.java new file mode 100644 index 00000000..9cc9eba6 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/AlloySolutionSelectionPage.java @@ -0,0 +1,244 @@ +package eu.modelwriter.configuration.alloy2emf; + +import java.awt.Frame; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.JPanel; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.swt.SWT; +import org.eclipse.swt.awt.SWT_AWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; + +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4viz.AlloyInstance; +import edu.mit.csail.sdg.alloy4viz.StaticInstanceReader; +import edu.mit.csail.sdg.alloy4viz.VizGraphPanel; +import edu.mit.csail.sdg.alloy4viz.VizState; +import eu.modelwriter.configuration.internal.AlloyUtilities; + +public class AlloySolutionSelectionPage extends AlloyToEMFWizardPage { + + private List solutions = new ArrayList(); + private int currentSolutionIndex = 0; + + private static VizState myState = null; + private static VizGraphPanel graph; + private static Frame frame; + private static File f = null; + public static Composite container; + private static String xmlFileLocation = + ".modelwriter alloy_example_output0.xml".replace(" ", System.getProperty("file.separator")); + + public AlloySolutionSelectionPage() { + this("AlloySolutionSelectionPage"); + } + + private static String getLocation() { + return ResourcesPlugin.getWorkspace().getRoot().getLocation() + "/" + xmlFileLocation; + } + + protected AlloySolutionSelectionPage(String pageName) { + super(pageName); + setTitle("Alloy Solutions"); + // setDescription("Select a Alloy solution to continue"); + } + + @Override + public void createControl(Composite parent) { + final Composite container = new Composite(parent, SWT.NULL); + container.setLayout(new GridLayout(1, false)); + container.setLayoutData(new GridData(SWT.FILL)); + + AlloySolutionSelectionPage.container = + new Composite(container, SWT.EMBEDDED | SWT.NO_BACKGROUND); + AlloySolutionSelectionPage.container + .setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true)); + AlloySolutionSelectionPage.frame = null; + AlloySolutionSelectionPage.f = null; + AlloySolutionSelectionPage.graph = null; + AlloySolutionSelectionPage.myState = null; + + final Composite buttonContainer = new Composite(container, SWT.NULL); + buttonContainer.setLayout(new GridLayout(3, false)); + buttonContainer.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false, 1, 1)); + + Button prevButton = new Button(buttonContainer, SWT.PUSH); + prevButton.setText("Previous Solution"); + prevButton.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + if (currentSolutionIndex > 0) { + currentSolutionIndex = currentSolutionIndex - 1; + showSolution(); + } + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) {} + }); + + Button nextButton = new Button(buttonContainer, SWT.PUSH); + nextButton.setText("Next Solution"); + nextButton.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + try { + A4Solution nextSol = currentSolution().next(); + if (nextSol.satisfiable()) { + solutions.add(nextSol); + currentSolutionIndex = currentSolutionIndex < (solutions.size() - 1) + ? currentSolutionIndex + 1 : (solutions.size() - 1); + showSolution(); + } + } catch (Err e1) { + e1.printStackTrace(); + setErrorMessage("An error has occured while getting next solution."); + } + + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) {} + }); + + setControl(container); + if (!solutions.isEmpty()) { + showSolution(); + } + } + + private void showViz() { + if (AlloySolutionSelectionPage.container == null) { + return; + } + + if (!AlloyUtilities.isExists()) { + if (AlloySolutionSelectionPage.frame != null) { + if (AlloySolutionSelectionPage.frame.getComponentCount() > 0) { + AlloySolutionSelectionPage.frame.removeAll(); + } + AlloySolutionSelectionPage.frame.add(new JPanel()); + } else if (AlloySolutionSelectionPage.frame == null) { + AlloySolutionSelectionPage.frame = SWT_AWT.new_Frame(AlloySolutionSelectionPage.container); + AlloySolutionSelectionPage.frame.add(new JPanel()); + } + return; + } + AlloySolutionSelectionPage.f = new File(getLocation()); + try { + if (!AlloySolutionSelectionPage.f.exists()) { + throw new IOException("File " + getLocation() + " does not exist."); + } + final AlloyInstance instance = + StaticInstanceReader.parseInstance(AlloySolutionSelectionPage.f); + + AlloyUtilities.setAllImpactsAndChanges(instance); + + AlloySolutionSelectionPage.myState = new VizState(instance); + + // FE + AlloySolutionSelectionPage.myState.mergeArrows.put(null, false); + + if (AlloySolutionSelectionPage.frame == null) { + AlloySolutionSelectionPage.frame = SWT_AWT.new_Frame(AlloySolutionSelectionPage.container); + } + + if (AlloySolutionSelectionPage.graph != null + && AlloySolutionSelectionPage.frame.getComponent(0) != null) { + AlloySolutionSelectionPage.frame.remove(AlloySolutionSelectionPage.graph); + } + + try { + /* + * TODO BUG + * + * A Fatal Error occurs while setting GTK look and feel on Ubuntu 16.04 + * (com.sun.java.swing.plaf.gtk.GTKLookAndFeel). + * + */ + final String LaF = UIManager.getSystemLookAndFeelClassName(); + if ("com.sun.java.swing.plaf.gtk.GTKLookAndFeel".equals(LaF)) { + UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); + } else { + UIManager.setLookAndFeel(LaF); + } + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException + | UnsupportedLookAndFeelException e1) { + e1.printStackTrace(); + } + AlloySolutionSelectionPage.graph = + new VizGraphPanel(AlloySolutionSelectionPage.myState, false); + AlloySolutionSelectionPage.frame.removeAll(); + AlloySolutionSelectionPage.frame.add(AlloySolutionSelectionPage.graph); + AlloySolutionSelectionPage.frame.setVisible(true); + AlloySolutionSelectionPage.frame.setAlwaysOnTop(true); + AlloySolutionSelectionPage.graph.alloyGetViewer().alloyRepaint(); + + } catch (final Err | IOException e) { + e.printStackTrace(); + setErrorMessage("An error has occured while Alloy visualization."); + } + } + + @Override + public void dispose() { + container = null; + super.dispose(); + } + + public void setFirstSolution(A4Solution firstSolution) { + if (solutions.isEmpty()) { + solutions.add(firstSolution); + currentSolutionIndex = 0; + showSolution(); + } else { + solutions.clear(); + solutions.add(firstSolution); + currentSolutionIndex = 0; + showSolution(); + } + } + + public A4Solution currentSolution() { + return solutions.get(currentSolutionIndex); + } + + public void showSolution() { + try { + setDescription("Current solution: " + currentSolutionIndex + "\n"); + currentSolution().writeXML(getLocation()); + showViz(); + } catch (final Err e) { + e.printStackTrace(); + } + } + + @Override + public boolean backPressed() { + solutions.clear(); + currentSolutionIndex = 0; + return true; + } + + @Override + public boolean nextPressed() throws Exception { + AlloyToEMFWizard wizard = (AlloyToEMFWizard) getWizard(); + wizard.getAlloyToEmf().setSolution(currentSolution()); + return super.nextPressed(); + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/AlloyToEMF.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/AlloyToEMF.java new file mode 100644 index 00000000..34b64285 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/AlloyToEMF.java @@ -0,0 +1,450 @@ +package eu.modelwriter.configuration.alloy2emf; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Scanner; +import java.util.Set; +import java.util.regex.Pattern; + +import org.eclipse.core.resources.IFile; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.jface.dialogs.MessageDialog; + +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.SafeList; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.ExprVar; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig.Field; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Tuple; +import eu.modelwriter.configuration.alloy.trace.LoadItem; +import eu.modelwriter.configuration.alloy.trace.RelationTrace; +import eu.modelwriter.configuration.alloy.trace.SigTrace; +import eu.modelwriter.configuration.alloy.trace.TraceException; +import eu.modelwriter.configuration.alloy.trace.TraceManager; +import eu.modelwriter.configuration.generation.AbstractGeneration; +import eu.modelwriter.configuration.generation.GenerationWizardDialog; +import eu.modelwriter.configuration.internal.AlloyExecuter; +import eu.modelwriter.configuration.internal.EcoreUtilities; +import eu.modelwriter.configuration.internal.Utilities; +import eu.modelwriter.configuration.synthesis.AutomatedTraceCreator; + + +class AlloyToEMFItem { + String saveLocation = null; + String containerClassName; + EObject container; + EObject modelRoot; +} + + +public class AlloyToEMF extends AbstractGeneration { + + private final String alloyFilePath; + private A4Solution solution = null; + private Command selectedCommand = null; + private AlloyToEMFWizard alloyToEMFWizard; + private GenerationWizardDialog dialog; + private AlloyExecuter alloyExecuter; + + private final HashMap alias2Item = new HashMap<>(); + private final HashMap atom2EClass = new HashMap<>(); + + public AlloyToEMF(String alloyFilePath) { + this.alloyFilePath = alloyFilePath; + } + + /** + * Starts the process + * + * @throws TraceException + * + */ + public void start() throws TraceException { + if (!TraceManager.get().hasTraces()) + throw new TraceException("No trace has been found."); + + for (LoadItem load : TraceManager.get().getLoads()) { + if (load.getModelRoot() == null) { + throw new TraceException("There is no loaded model for alias: " + load.getAlias()); + } + AlloyToEMFItem alloyToEMFItem = new AlloyToEMFItem(); + alloyToEMFItem.modelRoot = load.getModelRoot(); + alias2Item.put(load.getAlias(), alloyToEMFItem); + } + + try { + alloyExecuter = new AlloyExecuter(alloyFilePath); + } catch (Err e) { + throw new TraceException(e.getMessage()); + } + + alloyToEMFWizard = new AlloyToEMFWizard(this, "Alloy To EMF"); + dialog = new GenerationWizardDialog(null, alloyToEMFWizard); + dialog.open(); + } + + /** + * + * @return list of executable commands + */ + public ConstList getRunCommands() { + return alloyExecuter.getRunCommands(); + } + + /** + * Disposes wizard + */ + public void closeWizard() { + alloyToEMFWizard.performCancel(); + } + + /** + * + * @param emfAlias alias to find emf model + * @param selectedClass class name to create a instance + */ + public void setSelectedEClass(String emfAlias, String selectedClass) { + alias2Item.get(emfAlias).containerClassName = selectedClass; + } + + /** + * + * @param emfAlias + * @return list of EClass names + */ + public List getEClasses(String emfAlias) { + return EcoreUtilities.getAllEClassNames(alias2Item.get(emfAlias).modelRoot); + } + + public Set getAliases() { + return alias2Item.keySet(); + } + + public SafeList getCurrentSigs() { + return alloyExecuter.getWorld().getAllSigs(); + } + + public String getAlloyFilePath() { + return alloyFilePath; + } + + /** + * Real job + * + * @throws TraceException + */ + public boolean run() throws TraceException { + setState(RUNNING); + atom2EClass.clear(); + + for (String alias : alias2Item.keySet()) { + EObject eObject = alias2Item.get(alias).modelRoot; + if (eObject instanceof EPackage) { + EPackage ePackage = (EPackage) eObject; + final String selectedClass = alias2Item.get(alias).containerClassName; + EClass refClass = EcoreUtilities.findEClass(alias2Item.get(alias).modelRoot, selectedClass); + if (refClass != null) { + EObject container = ePackage.getEFactoryInstance().create(refClass); + alias2Item.get(alias).container = container; + } + } + } + createEClassesFromAtoms(); + createEReferencesFromSigs(); + setState(FINISHED); + return true; + } + + private void createEReferencesFromSigs() throws TraceException { + for (Sig sig : solution.getAllReachableSigs()) { + for (Field field : sig.getFields()) { + final String relName = field.label; + SigTrace sigTrace = TraceManager.get().getSigTraceByType(sig.label.replace("this/", "")); + RelationTrace relTrace = + TraceManager.get().getRelationTrace2(sigTrace.getClassName(), relName); + if (relTrace != null) { + String refName = relTrace.getReferenceName(); + for (A4Tuple a4Tuple : solution.eval(field)) { + String fromAtom = a4Tuple.atom(0); + String toAtom = a4Tuple.atom(1); + createEReferenceByAtoms(refName, fromAtom, toAtom); + } + } else { + closeWizard(); + throw new TraceException("No trace has been found for the relation: " + relName); + } + } + } + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private void createEReferenceByAtoms(String refName, String fromAtom, String toAtom) + throws TraceException { + EObject sourceAtom = atom2EClass.get(fromAtom); + EObject targetAtom = atom2EClass.get(toAtom); + for (EReference eReference : sourceAtom.eClass().getEAllReferences()) { + if (eReference.getName().equals(refName)) { + if (eReference.isMany()) { + ((List) sourceAtom.eGet(eReference)).add(targetAtom); + } else { + sourceAtom.eSet(eReference, targetAtom); + } + break; + } + } + } + + private void createEClassesFromAtoms() throws TraceException { + Iterator it = solution.getAllAtoms().iterator(); + while (it.hasNext()) { + ExprVar atom = it.next(); + String sigName = atom.label.substring(0, atom.label.indexOf("$")); + SigTrace sigTrace = TraceManager.get().getSigTraceByType(sigName); + if (sigTrace != null) { + EClass refClass = EcoreUtilities.findEClass(alias2Item.get(sigTrace.getAlias()).modelRoot, + sigTrace.getClassName()); + EObject atomObject = refClass.getEPackage().getEFactoryInstance().create(refClass); + EcoreUtilities.eSetAttributeByName(atomObject, "name", atom.label); + putIntoContainer(alias2Item.get(sigTrace.getAlias()).container, atomObject); + atom2EClass.put(atom.label, atomObject); + } else { + closeWizard(); + throw new TraceException("There is no trace for the sig: " + sigName); + } + } + } + + /** + * Puts given dynamic EObject to corresponding container + * + * @param container + * @param eObject + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + public static void putIntoContainer(EObject container, EObject eObject) { + for (EReference eReference : container.eClass().getEAllReferences()) { + if (eObject.eClass().getName().equals(eReference.getEReferenceType().getName())) { + if (eReference.isMany()) + ((List) container.eGet(eReference)).add(eObject); + else + container.eSet(eReference, eObject); + break; + } + } + } + + public void setSolution(A4Solution solution) { + this.solution = solution; + } + + public A4Solution getSolution() { + return solution; + } + + public void onException(TraceException e) { + final MessageDialog warningdialog = new MessageDialog(null, "Alloy To EMF", null, + e.getMessage(), MessageDialog.WARNING, new String[] {"OK"}, 0); + warningdialog.open(); + } + + public void setSaveLocation(String alias, String selectedPath) { + alias2Item.get(alias).saveLocation = selectedPath; + } + + public boolean isAllLocationsSelected() { + for (AlloyToEMFItem alloyToEMFItem : alias2Item.values()) { + if (alloyToEMFItem.saveLocation == null) + return false; + } + return true; + } + + public boolean performFinish(boolean appendChecked, boolean startATC) { + for (AlloyToEMFItem item : alias2Item.values()) { + EcoreUtilities.saveResource(item.container, URI.createPlatformResourceURI(item.saveLocation, true)); + } + if (appendChecked) { + appendNewInstances(); + } + if (startATC) { + hideWizard(); + runATC(); + } + return true; + } + + public void runATC() { + try { + // TODO: Load the spec + TraceManager.get().loadSpec(alloyFilePath); + AutomatedTraceCreator automatedTraceCreator = new AutomatedTraceCreator(); + automatedTraceCreator.setUser(true); + automatedTraceCreator.schedule(); + } catch (TraceException e) { + // TODO: Delete created markers + } + } + + private void hideWizard() { + dialog.getShell().setAlpha(0); + } + + private void appendNewInstances() { + Pattern instanceRegex = Pattern.compile("^-- loadinstance@", Pattern.CASE_INSENSITIVE); + try { + File f = new File(alloyFilePath); + List fileContent = + new ArrayList<>(Files.readAllLines(Paths.get(f.toURI()), StandardCharsets.UTF_8)); + for (String alias : alias2Item.keySet()) { + Pattern aliasRegex = Pattern.compile("^-- loadalias@" + alias, Pattern.CASE_INSENSITIVE); + for (int i = 0; i < fileContent.size(); i++) { + String line = fileContent.get(i); + if (aliasRegex.matcher(line.trim()).find()) { + IFile iFile = Utilities.getIFileFromPath(alias2Item.get(alias).saveLocation); + String path = + iFile == null ? alias2Item.get(alias).saveLocation : iFile.getFullPath().toString(); + if (instanceRegex.matcher(fileContent.get(i + 2).trim()).find()) + fileContent.remove(i + 2); + fileContent.add(i + 2, "-- loadInstance@" + path); + } + } + } + Files.write(Paths.get(f.toURI()), fileContent, StandardCharsets.UTF_8); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void resetRun() { + atom2EClass.clear(); + setState(NOT_STARTED); + } + + public boolean executeCommand(Command selection) { + try { + A4Solution sol = alloyExecuter.executeCommand(selection); + if (sol != null) { + solution = sol; + return true; + } + } catch (Err e) { + e.printStackTrace(); + } + return false; + } + + @Override + public void onException(Exception e) { + + } + + public EObject getEMFModel(String alias) { + return alias2Item.get(alias).modelRoot; + } + + public void setSelectedCommand(Command selection) { + selectedCommand = selection; + } + + public Command getSelectedCommand() { + return selectedCommand; + } + + public List getPredLines(String label) { + List predLines = new ArrayList<>(); + Scanner scanner; + try { + scanner = new Scanner(new File(alloyFilePath)); + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + if (line.trim().equals("pred " + label + " {")) { + while (!line.contains("}") && scanner.hasNextLine()) { + line = scanner.nextLine(); + predLines.add(line.trim()); + } + } + } + scanner.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + return predLines; + } + + public boolean replacePred(String filePath, String predName, String predAndRun) + throws IOException { + File f = new File(filePath); + // FIXME possible charset problem + List fileContent = + new ArrayList<>(Files.readAllLines(Paths.get(f.toURI()), StandardCharsets.UTF_8)); + String[] lines = predAndRun.split(BoundSelectionPage.NEW_LINE); + int predIndex = -1; + + for (int i = 0; i < fileContent.size(); i++) { + if (fileContent.get(i).equals("//" + predName)) { + predIndex = i; + break; + } + } + if (predIndex == -1) + return false; + + int x = predIndex; + while (!fileContent.get(x).equals("//end")) + fileContent.remove(x); + fileContent.remove(x); + + for (int i = 0; i < lines.length; i++) { + fileContent.add(predIndex++, lines[i]); + } + Files.write(Paths.get(f.toURI()), fileContent, StandardCharsets.UTF_8); + return true; + } + + public A4Solution executePred(String predName, String predAndRun, boolean saveToFile) { + File tempFile = null; + try { + tempFile = File.createTempFile("temp_tarski_pred", ".mw"); + Utilities.copyFileContent(alloyFilePath, tempFile.getAbsolutePath()); + if (!replacePred(tempFile.getAbsolutePath(), predName, predAndRun)) + Utilities.appendToFile(tempFile.getAbsolutePath(), predAndRun); + alloyExecuter.parse(tempFile.getAbsolutePath()); + + if (saveToFile) + Utilities.copyFileContent(tempFile.getAbsolutePath(), alloyFilePath); + + for (Command command : alloyExecuter.getRunCommands()) { + if (command.label.equals(predName)) { + A4Solution sol = alloyExecuter.executeCommand(command); + if (sol != null) { + setSolution(sol); + return sol; + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } catch (Err e) { + e.printStackTrace(); + } finally { + if (tempFile != null && tempFile.exists()) + tempFile.delete(); + } + return null; + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/AlloyToEMFWizard.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/AlloyToEMFWizard.java new file mode 100644 index 00000000..e2ec8dda --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/AlloyToEMFWizard.java @@ -0,0 +1,74 @@ +package eu.modelwriter.configuration.alloy2emf; + +import org.eclipse.jface.wizard.IWizardPage; + +import eu.modelwriter.configuration.alloy.trace.TraceException; +import eu.modelwriter.configuration.generation.AbstractGeneration; +import eu.modelwriter.configuration.generation.GenerationWizard; + +public class AlloyToEMFWizard extends GenerationWizard { + + private AlloyRunCommandsPage alloyRunCommandsPage; + private FinishPage finishPage; + + public AlloyToEMFWizard(AbstractGeneration converter, String title) { + super(converter, title); + } + + public AlloyToEMF getAlloyToEmf() { + return getConverter(); + } + + @Override + public AlloyToEMF getConverter() { + return (AlloyToEMF) super.getConverter(); + } + + @Override + public void addPages() { + super.addPages(); + alloyRunCommandsPage = new AlloyRunCommandsPage(getAlloyToEmf().getRunCommands()); + addPage(alloyRunCommandsPage); + for (String alias : getAlloyToEmf().getAliases()) { + addPage(new BoundSelectionPage(getAlloyToEmf().getEMFModel(alias), + getAlloyToEmf().getCurrentSigs())); + } + addPage(new AlloySolutionSelectionPage()); + for (String alias : getAlloyToEmf().getAliases()) { + addPage(new EMFContainerSelectionPage(alias, getAlloyToEmf().getEClasses(alias))); + } + finishPage = new FinishPage(); + addPage(finishPage); + finishPage.updateConverter(); + } + + @Override + public boolean performFinish() { + return getAlloyToEmf().performFinish(finishPage.appendToFileChecked(), finishPage.startATC()); + } + + @Override + public boolean canFinish() { + IWizardPage page = getContainer().getCurrentPage(); + boolean canFinish = false; + boolean isLastPage = page.getName().equals("lastpage"); + if (isLastPage && getAlloyToEmf().getState() == AbstractGeneration.NOT_STARTED) { + FinishPage finishPage = (FinishPage) page; + try { + getAlloyToEmf().run(); + finishPage.success(); + canFinish = getAlloyToEmf().isAllLocationsSelected(); + } catch (TraceException e) { + canFinish = false; + finishPage.fail(); + getAlloyToEmf().onException(e); + } + } else { + if (isLastPage && getAlloyToEmf().getState() == AbstractGeneration.FINISHED) { + canFinish = getAlloyToEmf().isAllLocationsSelected(); + } + } + return canFinish; + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/AlloyToEMFWizardPage.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/AlloyToEMFWizardPage.java new file mode 100644 index 00000000..d0deb41c --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/AlloyToEMFWizardPage.java @@ -0,0 +1,25 @@ +package eu.modelwriter.configuration.alloy2emf; + +import org.eclipse.jface.wizard.IWizard; + +import eu.modelwriter.configuration.generation.GenerationWizardPage; + +public class AlloyToEMFWizardPage extends GenerationWizardPage { + + protected AlloyToEMF alloyToEMF = null; + + protected AlloyToEMFWizardPage(String pageName) { + super(pageName); + } + + @Override + public void setWizard(IWizard newWizard) { + super.setWizard(newWizard); + alloyToEMF = (AlloyToEMF) getConverter(); + } + + public AlloyToEMF getAlloyToEMF() { + return alloyToEMF; + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/BoundSelectionPage.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/BoundSelectionPage.java new file mode 100644 index 00000000..1966df85 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/BoundSelectionPage.java @@ -0,0 +1,571 @@ +package eu.modelwriter.configuration.alloy2emf; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Frame; +import java.awt.GridLayout; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSpinner; +import javax.swing.SpinnerNumberModel; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.awt.SWT_AWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Text; + +import edu.mit.csail.sdg.alloy4.SafeList; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.Sig; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import eu.modelwriter.configuration.internal.EcoreUtilities; + +public class BoundSelectionPage extends AlloyToEMFWizardPage { + + class BoundItem { + String sigName; + private int initLower, lower; + private int initUpper, upper; + EClass eClass; + private JSpinner lowerSpinner; + private JSpinner upperSpinner; + + public BoundItem(String sigName, int initLower, int initUpper) { + this.sigName = sigName; + this.initLower = initLower; + this.initUpper = initUpper; + setLower(initLower); + setUpper(initUpper); + } + + public EClass getEClass() { + return eClass; + } + + public void setEClass(EClass eClass) { + this.eClass = eClass; + } + + public int getLower() { + return lower;// lowerSpinner == null ? lower : (int) lowerSpinner.getValue(); + } + + public int getUpper() { + return upper; // upperSpinner == null ? upper : (int) upperSpinner.getValue(); + } + + public int getSpinnerLower() { + return lowerSpinner == null ? lower : (int) lowerSpinner.getValue(); + } + + public int getSpinnerUpper() { + return upperSpinner == null ? upper : (int) upperSpinner.getValue(); + } + + + public void setLower(int lower) { + this.lower = lower; + } + + void setUpper(int upper) { + this.upper = upper; + } + + public void reset() { + setUpper(initUpper); + setLower(initLower); + } + + JSpinner getLowerSpinner() { + return lowerSpinner; + } + + void setLowerSpinner(JSpinner lowerModel) { + lowerSpinner = lowerModel; + lowerModel.setValue(lower); + } + + JSpinner getUpperSpinner() { + return upperSpinner; + } + + void setUpperSpinner(JSpinner upperModel) { + upperSpinner = upperModel; + upperModel.setValue(upper); + } + + void updateValues() { + upperSpinner.setValue(upper); + lowerSpinner.setValue(lower); + } + } + + public static final String NEW_LINE = System.getProperty("line.separator"); + private static final int DEFAULT_UPPER = 3; + private static final String PRED_FORMAT = "\t#%s >= %d && #%s <= %d" + NEW_LINE; + private static final String BOUND_PRED_REGEX = "#(.*) >= (\\d*) && #(.*) <= (\\d*)"; + + private EObject modelRoot; + private SafeList sigs; + private boolean analyzeEnabled; + private boolean saveEnabled; + private int intPower = 1; + private Text predText; + private Button saveCheck; + private Map sig2item = new HashMap<>(); + private Map traceCache = new HashMap<>(); + private Composite buttonContainer; + private Text scopeSize; + private Button scopeCheck; + private Composite boundContainer; + private Frame frame; + private JPanel panel; + + protected BoundSelectionPage(EObject modelRoot, SafeList sigs) { + super("SelectEMFContainer"); + this.modelRoot = modelRoot; + this.sigs = sigs; + setTitle("Bound Selection"); + setDescription("Enter sig bounds"); + initSigBounds(); + } + + private void initSigBounds() { + for (Sig sig : sigs) { + String sigName = sig.label.replace("this/", ""); + int lower = 0, upper = DEFAULT_UPPER; + if (sig.isOne != null) { + lower = upper = 1; + } else if (sig.isLone != null) { + lower = 0; + upper = 1; + } else if (sig.isSome != null) { + lower = 1; + upper = DEFAULT_UPPER; + } + EClass sigClass = EcoreUtilities.findEClass(modelRoot, sigName); + if (sigClass != null && !sigClass.isAbstract()) { + BoundItem item = new BoundItem(sigName, lower, upper); + item.setEClass(sigClass); + sig2item.put(sigName, item); + traceCache.put(sigClass.getName(), sigName); + } + } + } + + @Override + public void createControl(Composite parent) { + final Composite topContainer = new Composite(parent, SWT.NONE); + topContainer.setLayout(new org.eclipse.swt.layout.GridLayout(1, false)); + // Checkbox: save this pred + saveCheck = new Button(topContainer, SWT.CHECK); + saveCheck.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + saveCheck.setText("Save this bounds as"); + saveCheck.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + saveEnabled = saveCheck.getSelection(); + predText.setEnabled(saveEnabled); + } + }); + saveCheck.setSelection(false); + + // Textbox: pred name + predText = new Text(topContainer, SWT.BORDER); + predText.setMessage("Enter a name"); + predText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + predText.setEnabled(false); + predText.addModifyListener(new ModifyListener() { + + @Override + public void modifyText(ModifyEvent e) { + setPageComplete(true); + } + }); + scopeCheck = new Button(topContainer, SWT.CHECK); + scopeCheck.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + scopeCheck.setText("A generic model for number of elements:"); + scopeCheck.setSelection(false); + scopeSize = new Text(topContainer, SWT.BORDER); + scopeSize.setMessage("Enter number of elements"); + scopeSize.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + scopeSize.setEnabled(false); + + // Append the grid + makeSigTable(topContainer); + makeBottomButtons(topContainer); + + scopeCheck.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + scopeSize.setEnabled(scopeCheck.getSelection()); + boolean enabled = !scopeCheck.getSelection(); + setEnabledRecursive(panel, enabled); + setEnabledRecursive(buttonContainer, enabled); + } + + }); + setControl(topContainer); + } + + public static void setEnabledRecursive(final Composite composite, final boolean enabled) { + Control[] children = composite.getChildren(); + for (int i = 0; i < children.length; i++) { + if (children[i] instanceof Composite) { + setEnabledRecursive((Composite) children[i], enabled); + } else { + children[i].setEnabled(enabled); + } + } + composite.setEnabled(enabled); + } + + public static void setEnabledRecursive(final Container container, final boolean enabled) { + Component[] children = container.getComponents(); + for (int i = 0; i < children.length; i++) { + if (children[i] instanceof Container) { + setEnabledRecursive((Container) children[i], enabled); + } else { + children[i].setEnabled(enabled); + } + } + container.setEnabled(enabled); + } + + private void makeBottomButtons(Composite container) { + buttonContainer = new Composite(container, SWT.NONE); + buttonContainer.setLayout(new org.eclipse.swt.layout.GridLayout(3, false)); + Button restoreButton = new Button(buttonContainer, SWT.PUSH); + // restoreButton.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + restoreButton.setText("Restore Lower Bounds"); + restoreButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + for (BoundItem boundItem : sig2item.values()) { + boundItem.setLower(boundItem.initLower); + boundItem.setUpper(boundItem.initUpper); + boundItem.updateValues(); + } + } + }); + + Button incButton = new Button(buttonContainer, SWT.PUSH); + // incButton.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + incButton.setText("Increment Lower Bounds"); + incButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + for (BoundItem boundItem : sig2item.values()) { + boundItem.setLower(boundItem.getLower() + 1); + boundItem.updateValues(); + } + } + }); + + Button decButton = new Button(buttonContainer, SWT.PUSH); + // decButton.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + decButton.setText("Decrement Lower Bounds"); + decButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + for (BoundItem boundItem : sig2item.values()) { + boundItem.setLower(boundItem.getLower() - 1); + boundItem.updateValues(); + } + } + }); + Button restoreUpperButton = new Button(buttonContainer, SWT.PUSH); + // restoreButton.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + restoreUpperButton.setText("Restore Upper Bounds"); + restoreUpperButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + for (BoundItem boundItem : sig2item.values()) { + boundItem.setLower(boundItem.initLower); + boundItem.setUpper(boundItem.initUpper); + boundItem.updateValues(); + } + } + }); + + Button incUpperButton = new Button(buttonContainer, SWT.PUSH); + // incButton.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + incUpperButton.setText("Increment Upper Bounds"); + incUpperButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + for (BoundItem boundItem : sig2item.values()) { + boundItem.setUpper(boundItem.getUpper() + 1); + boundItem.updateValues(); + } + } + }); + + Button decUpperButton = new Button(buttonContainer, SWT.PUSH); + // decButton.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + decUpperButton.setText("Decrement Upper Bounds"); + decUpperButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + for (BoundItem boundItem : sig2item.values()) { + boundItem.setUpper(boundItem.getUpper() - 1); + boundItem.updateValues(); + } + } + }); + } + + private void makeSigTable(final Composite topContainer) { + boundContainer = new Composite(topContainer, SWT.EMBEDDED | SWT.NO_BACKGROUND); + boundContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + boundContainer.setLayout(new FillLayout()); + setTheme(); + frame = SWT_AWT.new_Frame(boundContainer); + frame.setBackground(null); + GridLayout layout = new GridLayout(0, 3); + panel = new JPanel(layout); + JLabel labelSig = new JLabel("Sig"); + JLabel labelLower = new JLabel("Lower Bound"); + JLabel labelUpper = new JLabel("Upper Bound"); + panel.add(labelSig); + panel.add(labelLower); + panel.add(labelUpper); + for (Entry entry : sig2item.entrySet()) { + BoundItem boundItem = entry.getValue(); + String sigName = entry.getKey(); + JLabel sigLabel = new JLabel(sigName); + SpinnerNumberModel lowerModel = + new SpinnerNumberModel(boundItem.getLower(), boundItem.initLower, 1000, 1); + SpinnerNumberModel upperModel = + new SpinnerNumberModel(boundItem.getUpper(), boundItem.initLower, 1000, 1); + JSpinner upper = new JSpinner(upperModel); + JSpinner lower = new JSpinner(lowerModel); + panel.add(sigLabel); + panel.add(lower); + panel.add(upper); + lowerModel.addChangeListener(new ChangeListener() { + int prevValue = boundItem.initLower; + + @Override + public void stateChanged(ChangeEvent e) { + int l = (int) lower.getValue(); + if (l > (int) upper.getValue()) { + lowerModel.setValue(--l); + return; + } + if (analyzeEnabled) + analyzeBounds(sigName, l - prevValue, true); + prevValue = l; + } + }); + upperModel.addChangeListener(new ChangeListener() { + int prevValue = boundItem.initUpper; + + @Override + public void stateChanged(ChangeEvent e) { + int u = (int) upper.getValue(); + if (u < (int) lower.getValue()) { + upperModel.setValue(++u); + return; + } + updateInt(u); + if (analyzeEnabled) + analyzeBounds(sigName, u - prevValue, false); + prevValue = u; + } + }); + boundItem.setLowerSpinner(lower); + boundItem.setUpperSpinner(upper); + } + frame.add(panel, BorderLayout.CENTER); + } + + private void analyzeBounds(String sigName, int inc, boolean lowerChanged) { + BoundItem item = sig2item.get(sigName); + if (item == null || inc == 0) + return; + + for (EReference eRef : item.getEClass().getEReferences()) { + String relSigName = traceCache.get(eRef.getEReferenceType().getName()); + BoundItem relBoundItem = sig2item.get(relSigName); + int newUpper = relBoundItem.getUpper(); + int newLower = relBoundItem.getLower(); + + if (lowerChanged && eRef.getLowerBound() > 0) { + int change = eRef.getLowerBound() * inc; + newLower = relBoundItem.getLower() + change; + // TODO check this + // if (relBoundItem.getLower() < (eRef.getLowerBound() * item.getSpinnerLower())) { + // if (eRef.isContainment()) { + // relBoundItem.setUpper(item.getSpinnerUpper() * inc + // * (eRef.getUpperBound() < 1 ? 1 : eRef.getUpperBound())); + // relBoundItem.setLower(item.getSpinnerLower() * change); + // } else { + // relBoundItem.setUpper(relBoundItem.getUpper() + change); + // relBoundItem.setLower(relBoundItem.getLower() + change); + // } + // } + } else if (!lowerChanged) { + int change = eRef.getUpperBound() < 1 ? 1 : eRef.getUpperBound() * inc; + newUpper = relBoundItem.getUpper() + change; + // relBoundItem.setUpper(relBoundItem.getUpper() + change); + } + relBoundItem.setUpper(newUpper); + relBoundItem.setLower(newLower); + relBoundItem.updateValues(); + } + } + + private void updateInt(int upperBound) { + if (upperBound > Math.pow(2, intPower) - 1) { + intPower = 32 - Integer.numberOfLeadingZeros(upperBound - 1); + } + } + + private void setTheme() { + try { + /* + * TODO BUG + * + * A Fatal Error occurs while setting GTK look and feel on Ubuntu 16.04 + * (com.sun.java.swing.plaf.gtk.GTKLookAndFeel). + * + */ + final String LaF = UIManager.getSystemLookAndFeelClassName(); + if ("com.sun.java.swing.plaf.gtk.GTKLookAndFeel".equals(LaF)) { + UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); + } else { + UIManager.setLookAndFeel(LaF); + } + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException + | UnsupportedLookAndFeelException e1) { + e1.printStackTrace(); + } + } + + public void setSelectedCommand(Command selectedCommand) { + final Pattern boundPredPattern = Pattern.compile(BOUND_PRED_REGEX, Pattern.CASE_INSENSITIVE); + predText.setText(""); + if (selectedCommand == null) + return; + + predText.setText(selectedCommand.label); + // saveCheck.setSelection(true); + // saveEnabled = true; + List pred = getAlloyToEMF().getPredLines(selectedCommand.label); + for (String line : pred) { + Matcher matcher = boundPredPattern.matcher(line); + if (matcher.matches() && matcher.group(1).equals(matcher.group(3))) { + int lower = -1, upper = -1; + String sigName = matcher.group(1); + lower = Integer.parseInt(matcher.group(2)); + upper = Integer.parseInt(matcher.group(4)); + BoundItem item = sig2item.get(sigName); + if (item != null) { + item.setLower(lower); + item.setUpper(upper); + } + } + } + } + + public String generatePredAndRun(String predName) { + StringBuilder sb = new StringBuilder(); + sb.append("//" + predName + NEW_LINE); + sb.append("pred " + predName + " {" + NEW_LINE); + String scope = ""; + if (!scopeCheck.getSelection()) { + for (Entry entry : sig2item.entrySet()) { + BoundItem boundItem = entry.getValue(); + if (boundItem.getLower() != boundItem.initLower + || boundItem.getUpper() != boundItem.initUpper) { + sb.append(String.format(PRED_FORMAT, boundItem.sigName, boundItem.getLower(), + boundItem.sigName, boundItem.getUpper())); + if (boundItem.getUpper() > DEFAULT_UPPER) { + if (!scope.isEmpty()) + scope += ", "; + scope += boundItem.getUpper() + " " + boundItem.sigName; + } + } + } + } + sb.append("}" + NEW_LINE); + if (!scopeCheck.getSelection()) + sb.append("run " + predName + " for " + DEFAULT_UPPER); + else + sb.append("run " + predName + " for " + Integer.parseInt(scopeSize.getText())); + + if (!scope.isEmpty()) { + sb.append(" but " + scope); + if (intPower > 1) + sb.append(" ," + intPower + " Int"); + } + sb.append(NEW_LINE + "//end" + NEW_LINE); + return sb.toString(); + } + + @Override + public boolean backPressed() { + for (Entry entry : sig2item.entrySet()) { + entry.getValue().reset(); + } + return super.backPressed(); + } + + @Override + public boolean nextPressed() throws Exception { + // if save enabled, make sure pred has a name that not starts with number + if (saveEnabled && (Character.isDigit(getPredName().charAt(0)) || getPredName().isEmpty())) { + predText.forceFocus(); + return false; + } + + String predName = getPredName(); + if (!saveEnabled) + predName = "temp_pred_name"; + + A4Solution solution = + getAlloyToEMF().executePred(predName, generatePredAndRun(predName), saveEnabled); + if (solution != null) { + AlloySolutionSelectionPage nextPage = (AlloySolutionSelectionPage) getNextPage(); + nextPage.setFirstSolution(solution); + return true; + } else { + MessageDialog messageDialog = new MessageDialog(getShell(), "Error", null, + "No instance found, try changing the bounds.", MessageDialog.INFORMATION, 0, + new String[] {"OK"}); + messageDialog.open(); + return false; + } + } + + private String getPredName() { + return predText.getText(); + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/EMFContainerSelectionPage.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/EMFContainerSelectionPage.java new file mode 100644 index 00000000..ca86727b --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/EMFContainerSelectionPage.java @@ -0,0 +1,72 @@ +package eu.modelwriter.configuration.alloy2emf; + +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; + +import eu.modelwriter.configuration.alloy.trace.TraceException; + +public class EMFContainerSelectionPage extends AlloyToEMFWizardPage { + + private org.eclipse.swt.widgets.List classList; + private List emfClasses; + private String emfAlias; + + protected EMFContainerSelectionPage(String emfAlias, List classes) { + super("Select EMF Container"); + this.emfAlias = emfAlias; + emfClasses = classes; + setTitle("Select EMF Class"); + setDescription("Select a class to create a \"" + emfAlias + "\" EMF instace"); + } + + @Override + public void createControl(Composite parent) { + final Composite container = new Composite(parent, SWT.NULL); + container.setLayout(new FillLayout(SWT.HORIZONTAL)); + + classList = + new org.eclipse.swt.widgets.List(container, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); + + for (String clazz : emfClasses) { + classList.add(clazz); + } + classList.setSelection(0); + classList.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + setPageComplete(true); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + + } + }); + setControl(container); + } + + + @Override + public boolean nextPressed() throws TraceException { + ((AlloyToEMF) getConverter()).setSelectedEClass(emfAlias, getSelectedClass()); + return true; + } + + public String getEmfAlias() { + return emfAlias; + } + + public void setEmfAlias(String emfAlias) { + this.emfAlias = emfAlias; + } + + public String getSelectedClass() { + return emfClasses.get(classList.getSelectionIndex()); + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/FinishPage.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/FinishPage.java new file mode 100644 index 00000000..0eb3a32d --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/alloy2emf/FinishPage.java @@ -0,0 +1,125 @@ +package eu.modelwriter.configuration.alloy2emf; + +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; + +import eu.modelwriter.configuration.internal.Utilities; + +public class FinishPage extends AlloyToEMFWizardPage { + + private boolean backButtonEnabled = true; + private Composite container; + private Button checkbox; + private Button atcCheckbox; + + protected FinishPage() { + super("lastpage"); + setTitle("Finish"); + } + + @Override + public void createControl(Composite parent) { + container = new Composite(parent, SWT.NULL); + container.setLayout(new GridLayout(2, false)); + for (String alias : alloyToEMF.getAliases()) { + Label label = new Label(container, SWT.NONE); + label.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + label.setText("Select save location for " + alias + " \n"); + Button button = new Button(container, SWT.PUSH); + button.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, true, false)); + button.setText("Browse"); + button.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + FileDialog fd = new FileDialog(button.getShell(), SWT.SAVE); + fd.setText("Save"); + fd.setFileName(alias + ".xmi"); + String path = alloyToEMF.getAlloyFilePath().substring(0, + alloyToEMF.getAlloyFilePath().lastIndexOf(Utilities.FILE_SEPERATOR)); + fd.setFilterPath(path); + String selectedPath = fd.open(); + if (selectedPath != null) { + String message = ("Select save location for " + alias + " \n\"" + selectedPath + "\""); + label.setText(message.length() >= 70 ? (message.substring(0, 70) + "...") : message); + label.setToolTipText(selectedPath); + label.getParent().layout(); + alloyToEMF.setSaveLocation(alias, selectedPath); + getContainer().updateButtons(); + } + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) {} + }); + } + Composite checksCon = new Composite(container, SWT.NULL); + checksCon.setLayout(new GridLayout(1, false)); + checkbox = new Button(checksCon, SWT.CHECK); + checkbox.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + checkbox.setText("Add trace of this instance to alloy specification"); + checkbox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) {} + }); + atcCheckbox = new Button(checksCon, SWT.CHECK); + atcCheckbox.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + atcCheckbox.setText("Start 'Automated Trace Creation'"); + atcCheckbox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + + } + }); + + setControl(container); + } + + public void setBackButtonEnabled(boolean enabled) { + backButtonEnabled = enabled; + getContainer().updateButtons(); + } + + @Override + public IWizardPage getPreviousPage() { + if (!backButtonEnabled) { + return null; + } + return super.getPreviousPage(); + } + + @Override + public boolean backPressed() { + alloyToEMF.resetRun(); + return true; + } + + public void success() { + setMessage("Operation succeed without any error."); + } + + public void fail() { + setErrorMessage("Something went wrong!"); + } + + public boolean appendToFileChecked() { + return checkbox.getSelection(); + } + + public boolean startATC() { + return atcCheckbox.getSelection(); + } + + public void updateConverter() { + alloyToEMF = (AlloyToEMF) getConverter(); + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/emf2alloy/AliasSelectionPage.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/emf2alloy/AliasSelectionPage.java new file mode 100644 index 00000000..dec6d710 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/emf2alloy/AliasSelectionPage.java @@ -0,0 +1,47 @@ +package eu.modelwriter.configuration.emf2alloy; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +public class AliasSelectionPage extends EMFToAlloyWizardPage { + + private String alias; + private Text text; + + public AliasSelectionPage(String alias) { + super("SelectAliasPage"); + this.alias = alias; + setTitle("Alias"); + setDescription("Select an alias for Ecore file"); + } + + + @Override + public void createControl(Composite parent) { + Composite container = new Composite(parent, SWT.NULL); + container.setLayout(new GridLayout(2, false)); + Label label = new Label(container, SWT.NONE); + label.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false)); + label.setText("Select an alias for Ecore file "); + text = new Text(container, SWT.BORDER); + text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + text.setText(alias); + setControl(container); + } + + public String getAlias() { + alias = text.getText(); + return alias; + } + + @Override + public boolean nextPressed() throws Exception { + emfToAlloy.setAlias(alias); + return super.nextPressed(); + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/emf2alloy/ContainerSelectionPage.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/emf2alloy/ContainerSelectionPage.java new file mode 100644 index 00000000..d3c63e6a --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/emf2alloy/ContainerSelectionPage.java @@ -0,0 +1,90 @@ +package eu.modelwriter.configuration.emf2alloy; + +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; + +public class ContainerSelectionPage extends EMFToAlloyWizardPage { + + private org.eclipse.swt.widgets.List classList; + private List emfClasses; + private String emfAlias; + private Button checkbox; + + protected ContainerSelectionPage(String emfAlias, List classes) { + super("SelectEMFContainer"); + this.emfAlias = emfAlias; + emfClasses = classes; + setTitle("Select EMF Class"); + setDescription("Select the container class to continue"); + } + + @Override + public void createControl(Composite parent) { + final Composite container = new Composite(parent, SWT.NULL); + container.setLayout(new GridLayout(1, true)); + container.setLayoutData(new GridData(SWT.FILL)); + + classList = + new org.eclipse.swt.widgets.List(container, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); + classList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + + for (String clazz : emfClasses) { + classList.add(clazz); + } + classList.setSelection(0); + classList.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + setPageComplete(true); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + + } + }); + checkbox = new Button(container, SWT.CHECK); + checkbox.setLayoutData(new GridData(SWT.BEGINNING, SWT.TOP, true, false)); + checkbox.setText("Don't include container class."); + checkbox.setSelection(true); + setControl(container); + } + + public List getEmfClasses() { + return emfClasses; + } + + public void setEmfClasses(List emfClasses) { + this.emfClasses = emfClasses; + for (String clazz : emfClasses) { + classList.add(clazz); + } + } + + public String getEmfAlias() { + return emfAlias; + } + + public void setEmfAlias(String emfAlias) { + this.emfAlias = emfAlias; + } + + public String getSelectedClass() { + return emfClasses.get(classList.getSelectionIndex()); + } + + @Override + public boolean nextPressed() throws Exception { + getEmfToAlloy().setContainerClass(getSelectedClass(), checkbox.getSelection()); + return super.nextPressed(); + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/emf2alloy/EMFToAlloy.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/emf2alloy/EMFToAlloy.java new file mode 100644 index 00000000..c350ee9e --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/emf2alloy/EMFToAlloy.java @@ -0,0 +1,318 @@ +package eu.modelwriter.configuration.emf2alloy; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; + +import eu.modelwriter.configuration.alloy.trace.TraceException; +import eu.modelwriter.configuration.alloy.trace.TraceManager; +import eu.modelwriter.configuration.alloy2emf.AlloyToEMF; +import eu.modelwriter.configuration.generation.AbstractGeneration; +import eu.modelwriter.configuration.generation.GenerationWizardDialog; +import eu.modelwriter.configuration.internal.EcoreUtilities; +import eu.modelwriter.configuration.internal.Utilities; + +public class EMFToAlloy extends AbstractGeneration { + + class ContainmentFact { + String sig; + char shortName; + List conRels = new ArrayList<>(); + + public ContainmentFact(String sig) { + this.sig = sig; + shortName = sig.toLowerCase().charAt(0); + } + + public void addConRel(String domainName, String relName) { + conRels.add(domainName + "<:(" + shortName + ".~" + relName + ")"); + } + + public String getFact() { + String result = ""; + result += "all " + shortName + ":" + sig + " | "; + result += "one " + getUnionSet(conRels); + return result; + } + + public String getUnionSet(List rels) { + String result = "("; + for (Iterator it = rels.iterator(); it.hasNext();) { + result += it.next(); + if (it.hasNext()) + result += " + "; + } + result += ")"; + return result; + } + } + + private IFile ecoreFile = null; + private EObject ecoreRoot = null; + private StringBuilder builder; + private String saveLocation = null; + private String alias = null; + private String containerClassName; + private boolean ignoreContainer; + private boolean startEmfInstanceGeneration; + private GenerationWizardDialog dialog; + private EClass containerClass = null; + private List facts = new ArrayList<>(); + private int intPower = 1; + private HashMap containmentFacts = new HashMap<>(); + private String existingInstancePath; + + public EMFToAlloy(IFile ecoreFile) { + this.ecoreFile = ecoreFile; + } + + public void start() throws IOException { + try { + ecoreRoot = EcoreUtilities.getRootObject(ecoreFile.getFullPath().toString()); + } catch (IOException e) { + e.printStackTrace(); + throw new IOException("Error while loading Ecore file."); + } + builder = new StringBuilder(); + dialog = new GenerationWizardDialog(null, new EMFToAlloyWizard(this, "EMF to Alloy")); + dialog.open(); + } + + public void run() { + setState(RUNNING); + if (ecoreRoot != null) { + // appendModuleAndLoad(alias); + List contents = EcoreUtilities.getAllEClass(ecoreRoot); + for (EClass eClass : contents) { + appendSig(alias, eClass); + } + appendFacts(); + appendPredAndRun(); + } + setState(FINISHED); + } + + public String getModelFilePath() { + return ecoreFile.getLocation().toOSString(); + } + + private void appendFacts() { + for (ContainmentFact fact : containmentFacts.values()) { + builder.append("fact {\n"); + builder.append("\t" + fact.getFact()); + builder.append("\n}\n\n"); + } + for (String fact : facts) { + builder.append("fact {\n"); + builder.append("\t" + fact); + builder.append("\n}\n\n"); + } + } + + private void appendPredAndRun() { + builder.append("pred show{}\n"); + builder.append("run show"); + + if (intPower > 1) + builder.append(" for " + (intPower + 1) + " Int"); + + builder.append("\n"); + } + + @SuppressWarnings("unused") + private void appendModuleAndLoad(String alias) { + builder.append("module " + getFileName() + "\n\n"); + builder.append("-- loadAlias@" + alias); + builder.append("\n"); + builder.append("-- loadModel@" + ecoreFile.getFullPath().toString()); + builder.append("\n\n"); + } + + private String generateModuleAndLoad(String alias, String instancePath) { + StringBuilder builder = new StringBuilder(); + builder.append("module " + getFileName() + "\n\n"); + builder.append("-- loadAlias@" + alias); + builder.append("\n"); + builder.append("-- loadModel@" + ecoreFile.getFullPath().toString()); + if (instancePath != null) + builder.append("\n-- loadInstance@" + instancePath); + builder.append("\n\n"); + return builder.toString(); + } + + private void appendSig(String alias, EClass eClass) { + if (eClass.getName().equals(containerClassName) && ignoreContainer) + return; + + // append sig trace + builder.append("-- trace@" + alias + "." + eClass.getName() + "\n"); + + EReference containerRef = getRefToContainer(eClass); + if (containerRef != null) { + String mul = getMultiplicity(containerRef); + if ("set ".equals(mul)) + mul = ""; + builder.append(mul); + } + + // append sig + if (eClass.isAbstract()) { + builder.append("abstract sig " + eClass.getName()); + } else { + builder.append("sig " + eClass.getName()); + } + + // extends parts + if (!eClass.getESuperTypes().isEmpty()) { + builder.append(" extends "); + } + for (Iterator it = eClass.getESuperTypes().iterator(); it.hasNext();) { + EClass superClass = it.next(); + builder.append(superClass.getName()); + if (it.hasNext()) + builder.append(", "); + } + builder.append(" {\n"); + + // relations + for (Iterator iterator = eClass.getEReferences().iterator(); iterator.hasNext();) { + EReference eReference = iterator.next(); + + String sig = eReference.getEType().getName(); + if (eReference.isContainment()) { + if (containmentFacts.get(sig) == null) + containmentFacts.put(sig, new ContainmentFact(sig)); + containmentFacts.get(sig).addConRel(eClass.getName(), eReference.getName()); + } + + String multiplicity = getMultiplicity(eReference); + if (multiplicity.isEmpty()) { + multiplicity = "set "; + char c = eClass.getName().toLowerCase().charAt(0); + String fact = "all " + c + ":" + eClass.getName() + " | "; + if (eReference.getLowerBound() != -1) + fact += "#" + c + "." + eReference.getName() + " >= " + eReference.getLowerBound(); + if (eReference.getUpperBound() != -1) { + fact += " and #" + c + "." + eReference.getName() + " <= " + eReference.getUpperBound(); + } + facts.add(fact); + updateInt(Math.max(eReference.getLowerBound(), eReference.getUpperBound())); + } + + // append trace + builder.append( + "\t-- trace@" + alias + "." + eClass.getName() + "." + eReference.getName() + "\n"); + + // append relation + builder.append( + "\t" + eReference.getName() + ": " + multiplicity + eReference.getEType().getName()); + if (iterator.hasNext()) + builder.append(","); + builder.append("\n"); + } + builder.append("}\n\n"); + } + + private void updateInt(int upperBound) { + if (upperBound > Math.pow(2, intPower) - 1) { + intPower = 32 - Integer.numberOfLeadingZeros(upperBound - 1); + } + } + + private EReference getRefToContainer(EClass eClass) { + for (EReference eReference : containerClass.getEReferences()) { + if (eReference.getEReferenceType().getName().equals(eClass.getName())) + return eReference; + } + return null; + } + + private String getMultiplicity(EReference eReference) { + int l = eReference.getLowerBound(); + int u = eReference.getUpperBound(); + if (l == 0 && u == 1) + return "lone "; + if (l == 0 && u == -1) + return "set "; + if (l == 1 && u == 1) + return "one "; + if (l == 1 && u == -1) + return "some "; + + return ""; + } + + public void save(String selectedPath) { + saveLocation = selectedPath; + } + + public boolean isSaveLocationSet() { + return saveLocation != null; + } + + public String getFileName() { + return ecoreFile.getName().substring(0, ecoreFile.getName().indexOf(".")); + } + + public void performFinish() { + try { + builder.insert(0, generateModuleAndLoad(alias, existingInstancePath)); + Utilities.writeToFile(saveLocation, builder); + + if (startEmfInstanceGeneration) { + hideWizard(); + TraceManager.get().loadSpec(saveLocation); + AlloyToEMF alloyToEMF = new AlloyToEMF(saveLocation); + alloyToEMF.start(); + } + } catch (TraceException e) { + e.printStackTrace(); + } + } + + private void hideWizard() { + dialog.getShell().setAlpha(0); + } + + public void setAlias(String alias) { + this.alias = alias; + } + + public String getAlias() { + return alias; + } + + public EObject getEcoreRoot() { + return ecoreRoot; + } + + public void setContainerClass(String selectedClass, boolean ignore) { + containerClassName = selectedClass; + ignoreContainer = ignore; + containerClass = EcoreUtilities.findEClass(ecoreRoot, selectedClass); + } + + public void setEmfInstanceStarter(boolean selection) { + startEmfInstanceGeneration = selection; + } + + public void reset() { + setState(NOT_STARTED); + } + + @Override + public void onException(Exception e) { + + } + + public void existingInstancePath(String existingInstancePath) { + this.existingInstancePath = existingInstancePath; + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/emf2alloy/EMFToAlloyWizard.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/emf2alloy/EMFToAlloyWizard.java new file mode 100644 index 00000000..d40808d8 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/emf2alloy/EMFToAlloyWizard.java @@ -0,0 +1,49 @@ +package eu.modelwriter.configuration.emf2alloy; + +import org.eclipse.jface.wizard.IWizardPage; + +import eu.modelwriter.configuration.generation.AbstractGeneration; +import eu.modelwriter.configuration.generation.GenerationWizard; +import eu.modelwriter.configuration.internal.EcoreUtilities; + +public class EMFToAlloyWizard extends GenerationWizard { + + public EMFToAlloyWizard(AbstractGeneration converter, String title) { + super(converter, title); + } + + @Override + public void addPages() { + super.addPages(); + addPage(new AliasSelectionPage(getConverter().getFileName())); + addPage(new ContainerSelectionPage(getConverter().getAlias(), + EcoreUtilities.getAllEClassNames(getConverter().getEcoreRoot()))); + addPage(new FinishPage()); + } + + @Override + public boolean performFinish() { + getConverter().performFinish(); + return true; + } + + @Override + public boolean canFinish() { + IWizardPage page = getContainer().getCurrentPage(); + boolean isLastPage = page.getName().equals("lastpage"); + if (isLastPage && getConverter().getState() == AbstractGeneration.NOT_STARTED) { + getConverter().run(); + return false; + } + if (isLastPage && getConverter().getState() == AbstractGeneration.FINISHED) { + return getConverter().isSaveLocationSet(); + } + return false; + } + + @Override + public EMFToAlloy getConverter() { + return (EMFToAlloy) super.getConverter(); + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/emf2alloy/EMFToAlloyWizardPage.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/emf2alloy/EMFToAlloyWizardPage.java new file mode 100644 index 00000000..d31a4d27 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/emf2alloy/EMFToAlloyWizardPage.java @@ -0,0 +1,24 @@ +package eu.modelwriter.configuration.emf2alloy; + +import org.eclipse.jface.wizard.IWizard; + +import eu.modelwriter.configuration.generation.GenerationWizardPage; + +public class EMFToAlloyWizardPage extends GenerationWizardPage { + + protected EMFToAlloy emfToAlloy = null; + + protected EMFToAlloyWizardPage(String pageName) { + super(pageName); + } + + @Override + public void setWizard(IWizard newWizard) { + super.setWizard(newWizard); + emfToAlloy = (EMFToAlloy) getConverter(); + } + + public EMFToAlloy getEmfToAlloy() { + return emfToAlloy; + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/emf2alloy/FinishPage.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/emf2alloy/FinishPage.java new file mode 100644 index 00000000..b5fe76ad --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/emf2alloy/FinishPage.java @@ -0,0 +1,131 @@ +package eu.modelwriter.configuration.emf2alloy; + +import org.eclipse.core.resources.IFile; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; + +import eu.modelwriter.configuration.internal.Utilities; + +public class FinishPage extends EMFToAlloyWizardPage { + + private boolean backButtonEnabled = true; + private Composite container; + private Button checkbox; + + protected FinishPage() { + super("lastpage"); + setTitle("Finish"); + setDescription("Save the file"); + } + + @Override + public void createControl(Composite parent) { + container = new Composite(parent, SWT.NULL); + container.setLayout(new GridLayout(2, false)); + Label label = new Label(container, SWT.NONE); + label.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + label.setText("Select save location \n"); + Button button = new Button(container, SWT.PUSH); + button.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, true, false)); + button.setText("Browse"); + button.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + FileDialog fd = new FileDialog(button.getShell(), SWT.SAVE); + fd.setText("Save"); + fd.setFileName(getEmfToAlloy().getFileName() + ".mw"); + String path = emfToAlloy.getModelFilePath().substring(0, + emfToAlloy.getModelFilePath().lastIndexOf(Utilities.FILE_SEPERATOR)); + fd.setFilterPath(path); + String selectedPath = fd.open(); + if (selectedPath != null) { + String message = ("Select save location for \n\"" + selectedPath + "\""); + label.setText(message.length() >= 70 ? (message.substring(0, 70) + "...") : message); + label.setToolTipText(selectedPath); + label.getParent().layout(); + getEmfToAlloy().save(selectedPath); + getContainer().updateButtons(); + } + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) {} + }); + checkbox = new Button(container, SWT.CHECK); + checkbox.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + checkbox.setText("Start EMF Instance generation"); + + checkbox.setSelection(false); + new Label(container, SWT.NO).setVisible(false); + Button browseInstanceCheck = new Button(container, SWT.CHECK); + browseInstanceCheck.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + browseInstanceCheck.setText("Load an existing instance file"); + final Button browseButton = new Button(container, SWT.PUSH); + browseButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, true, false)); + browseButton.setText("Browse for Instance"); + browseButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + FileDialog fd = new FileDialog(button.getShell(), SWT.SAVE); + fd.setText("Select"); + String path = emfToAlloy.getModelFilePath().substring(0, + emfToAlloy.getModelFilePath().lastIndexOf(Utilities.FILE_SEPERATOR)); + fd.setFilterPath(path); + String selectedPath = fd.open(); + if (selectedPath != null) { + IFile iFile = Utilities.getIFileFromPath(selectedPath); + getEmfToAlloy() + .existingInstancePath(iFile == null ? selectedPath : iFile.getFullPath().toString()); + getContainer().updateButtons(); + } + } + }); + browseInstanceCheck.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + browseButton.setEnabled(browseInstanceCheck.getSelection()); + checkbox.setEnabled(!browseInstanceCheck.getSelection()); + } + }); + browseInstanceCheck.setSelection(false); + browseButton.setEnabled(false); + checkbox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + getEmfToAlloy().setEmfInstanceStarter(checkbox.getSelection()); + browseInstanceCheck.setEnabled(!checkbox.getSelection()); + } + }); + setControl(container); + } + + public void setBackButtonEnabled(boolean enabled) { + backButtonEnabled = enabled; + getContainer().updateButtons(); + } + + @Override + public IWizardPage getPreviousPage() { + if (!backButtonEnabled) { + return null; + } + return super.getPreviousPage(); + } + + @Override + public boolean backPressed() { + getEmfToAlloy().reset(); + return super.backPressed(); + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/generation/AbstractGeneration.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/generation/AbstractGeneration.java new file mode 100644 index 00000000..df023924 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/generation/AbstractGeneration.java @@ -0,0 +1,19 @@ +package eu.modelwriter.configuration.generation; + +public abstract class AbstractGeneration { + + // states + public static final int RUNNING = 1, NOT_STARTED = 0, FINISHED = 2; + private int state = NOT_STARTED; + + public int getState() { + return state; + } + + public void setState(int state) { + this.state = state; + } + + abstract public void onException(Exception e); + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/generation/GenerationWizard.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/generation/GenerationWizard.java new file mode 100644 index 00000000..4523da7b --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/generation/GenerationWizard.java @@ -0,0 +1,24 @@ +package eu.modelwriter.configuration.generation; + +import org.eclipse.jface.wizard.Wizard; + +public class GenerationWizard extends Wizard { + + private AbstractGeneration converter; + + public GenerationWizard(AbstractGeneration converter, String title) { + super(); + this.converter = converter; + setWindowTitle(title); + } + + @Override + public boolean performFinish() { + return true; + } + + public AbstractGeneration getConverter() { + return converter; + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/generation/GenerationWizardDialog.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/generation/GenerationWizardDialog.java new file mode 100644 index 00000000..3689980c --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/generation/GenerationWizardDialog.java @@ -0,0 +1,42 @@ +package eu.modelwriter.configuration.generation; + +import org.eclipse.jface.wizard.IWizard; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.swt.widgets.Shell; + +public class GenerationWizardDialog extends WizardDialog { + + public GenerationWizardDialog(Shell parentShell, IWizard newWizard) { + super(parentShell, newWizard); + } + + @Override + protected void backPressed() { + IWizardPage currentActivePage = getCurrentPage(); + + /* notify current page if it wants to do any validation on input */ + if (!((GenerationWizardPage) currentActivePage).backPressed()) + return; + + /* delegate backPressed processing to super */ + super.backPressed(); + } + + @Override + protected void nextPressed() { + IWizardPage currentActivePage = getCurrentPage(); + + /* notify current page if it wants to do any validation on input */ + try { + if (!((GenerationWizardPage) currentActivePage).nextPressed()) + return; + } catch (Exception e) { + GenerationWizard wizard = (GenerationWizard) getWizard(); + wizard.getConverter().onException(e); + } + + /* delegate nextPressed processing to super */ + super.nextPressed(); + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/generation/GenerationWizardPage.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/generation/GenerationWizardPage.java new file mode 100644 index 00000000..0f542135 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/generation/GenerationWizardPage.java @@ -0,0 +1,57 @@ +package eu.modelwriter.configuration.generation; + +import org.eclipse.jface.wizard.IWizard; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.widgets.Composite; + +import eu.modelwriter.configuration.alloy.trace.TraceException; + +public class GenerationWizardPage extends WizardPage { + + private AbstractGeneration converter = null; + + protected GenerationWizardPage(String pageName) { + super(pageName); + } + + /** + * This triggers when next button clicked + * + * @return true to go next page + * @throws TraceException + * @throws Exception + */ + public boolean nextPressed() throws Exception { + return true; + } + + /** + * This triggers when back button clicked + * + * @return true to go previous page + */ + public boolean backPressed() { + return true; + } + + @Override + public void createControl(Composite parent) { + setControl(parent); + } + + @Override + public void setWizard(IWizard newWizard) { + super.setWizard(newWizard); + try { + GenerationWizard wizard = (GenerationWizard) newWizard; + converter = wizard.getConverter(); + } catch (ClassCastException e) { + e.printStackTrace(); + } + } + + public AbstractGeneration getConverter() { + return converter; + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/internal/AlloyExecuter.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/internal/AlloyExecuter.java new file mode 100644 index 00000000..ccbe41ee --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/internal/AlloyExecuter.java @@ -0,0 +1,83 @@ +package eu.modelwriter.configuration.internal; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.parser.CompModule; +import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Options; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.TranslateAlloyToKodkod; + +public class AlloyExecuter { + + private CompModule world = null; + private A4Reporter rep = null; + + /** + * + * @param filePath alloy file path to parse + * @return + * @throws Err + */ + public AlloyExecuter(String filePath) throws Err { + rep = new A4Reporter() { + @Override + public void warning(final ErrorWarning msg) { + System.out.println("Relevance Warning:\n" + msg.toString().trim() + "\n\n"); + } + }; + parse(filePath); + } + + public AlloyExecuter() { + rep = new A4Reporter() { + @Override + public void warning(final ErrorWarning msg) { + System.out.println("Relevance Warning:\n" + msg.toString().trim() + "\n\n"); + } + }; + } + + public void parse(String filePath) throws Err { + world = CompUtil.parseEverything_fromFile(rep, null, filePath); + } + + /** + * Executes given command + * + * @param command to run + * @return solution if it is satisfiable else null + * @throws Err + */ + public A4Solution executeCommand(Command command) throws Err { + if (world == null) + return null; + + final A4Options options = new A4Options(); + options.solver = A4Options.SatSolver.SAT4J; + A4Solution solution = + TranslateAlloyToKodkod.execute_command(rep, world.getAllReachableSigs(), command, options); + if (solution.satisfiable()) { + return solution; + } + + return null; + } + + /** + * + * @return list of executable commands + */ + public ConstList getRunCommands() { + if (world == null) + return null; + return world.getAllCommands(); + } + + public CompModule getWorld() { + return world; + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/internal/AlloyUtilities.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/internal/AlloyUtilities.java new file mode 100644 index 00000000..363fb25d --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/internal/AlloyUtilities.java @@ -0,0 +1,1675 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.configuration.internal; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.stream.Collectors; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.Path; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.URI; + +import edu.mit.csail.sdg.alloy4viz.AlloyAtom; +import edu.mit.csail.sdg.alloy4viz.AlloyInstance; +import edu.mit.csail.sdg.alloy4viz.AlloyRelation; +import edu.mit.csail.sdg.alloy4viz.AlloyTuple; +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.traceability.core.persistence.AlloyType; +import eu.modelwriter.traceability.core.persistence.AtomType; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; +import eu.modelwriter.traceability.core.persistence.EntryType; +import eu.modelwriter.traceability.core.persistence.FieldType; +import eu.modelwriter.traceability.core.persistence.ItemType; +import eu.modelwriter.traceability.core.persistence.RelationType; +import eu.modelwriter.traceability.core.persistence.SigType; +import eu.modelwriter.traceability.core.persistence.SourceType; +import eu.modelwriter.traceability.core.persistence.TupleType; +import eu.modelwriter.traceability.core.persistence.TypeType; +import eu.modelwriter.traceability.core.persistence.TypesType; +import eu.modelwriter.traceability.core.persistence.persistenceFactory; +import eu.modelwriter.traceability.core.persistence.internal.ModelIO; + +public class AlloyUtilities { + + final public static String GROUP_ID = "groupId"; + final public static String LEADER_ID = "leaderId"; + final public static String MARKER_URI = "uri"; + final public static String OFFSET = "offset"; + final public static String RESOURCE = "resource"; + final public static String TEXT = "text"; + + public static Map typeHashMap = new HashMap<>(); + public static String xmlFileLocation = + ".modelwriter persistence.xml".replace(" ", System.getProperty("file.separator")); + + public static int getTotalTargetCount(final IMarker marker) { + final Map fieldsTargets = AlloyUtilities.getRelationsOfFirstSideMarker(marker); + final ArrayList relationsTargets = + AlloyUtilities.getTargetsOfMarkerAtRelations(marker); + + return fieldsTargets.size() + relationsTargets.size(); + } + + public static void addMapping2RelationType(IMarker fromMarker, IMarker toMarker) { + fromMarker = MarkUtilities.getLeaderOfMarker(fromMarker); + toMarker = MarkUtilities.getLeaderOfMarker(toMarker); + + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + + final RelationType relationType = documentRoot.getAlloy().getRelation(); + + final TupleType tupleType = persistenceFactory.eINSTANCE.createTupleType(); + relationType.getTuple().add(tupleType); + + final AtomType fromAtom = persistenceFactory.eINSTANCE.createAtomType(); + tupleType.getAtom().add(fromAtom); + fromAtom.setLabel(MarkUtilities.getSourceId(fromMarker)); + + final AtomType toAtom = persistenceFactory.eINSTANCE.createAtomType(); + tupleType.getAtom().add(toAtom); + toAtom.setLabel(MarkUtilities.getSourceId(toMarker)); + + AlloyUtilities.writeDocumentRoot(documentRoot); + } + + public static void addMarkerToRepository(final IMarker marker) { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + + if (AlloyUtilities.findItemTypeInRepository(marker) == -1) { + final ItemType itemType = persistenceFactory.eINSTANCE.createItemType(); + documentRoot.getAlloy().getRepository().getItem().add(itemType); + itemType.setId(MarkUtilities.getSourceId(marker)); + + AlloyUtilities.setEntries(itemType, marker); + } + AlloyUtilities.writeDocumentRoot(documentRoot); + } + + public static void addRelation2Markers(IMarker fromMarker, IMarker toMarker, + final String relation) { + fromMarker = MarkUtilities.getLeaderOfMarker(fromMarker); + toMarker = MarkUtilities.getLeaderOfMarker(toMarker); + + final ArrayList allParentIdsOfFromMarkerType = AlloyUtilities + .getAllParentIds(AlloyUtilities.getSigTypeIdByName(MarkUtilities.getType(fromMarker))); + final ArrayList allParentIdsOfToMarkerType = AlloyUtilities + .getAllParentIds(AlloyUtilities.getSigTypeIdByName(MarkUtilities.getType(toMarker))); + + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + + final AtomType fromAtom = persistenceFactory.eINSTANCE.createAtomType(); + fromAtom.setLabel(MarkUtilities.getSourceId(fromMarker)); + + final AtomType toAtom = persistenceFactory.eINSTANCE.createAtomType(); + toAtom.setLabel(MarkUtilities.getSourceId(toMarker)); + + final TupleType tuple = persistenceFactory.eINSTANCE.createTupleType(); + tuple.getAtom().add(fromAtom); + tuple.getAtom().add(toAtom); + + final EList fields = documentRoot.getAlloy().getInstance().getField(); + + for (final FieldType fieldType : fields) { + if (!fieldType.getLabel().equals(relation)) { + continue; + } + for (final TypesType typesType : fieldType.getTypes()) { + if (allParentIdsOfFromMarkerType.contains(typesType.getType().get(0).getID()) + && allParentIdsOfToMarkerType.contains(typesType.getType().get(1).getID())) { + if (!AlloyUtilities.isContainTuple(fieldType, tuple)) { + fieldType.getTuple().add(tuple); + } + break; + } + } + } + + AlloyUtilities.writeDocumentRoot(documentRoot); + } + + public static void addRelation2Markers(IMarker selectedMarker, final Object[] checkedMarkers, + final Map relationMap) { + selectedMarker = MarkUtilities.getLeaderOfMarker(selectedMarker); + + for (final Object object : checkedMarkers) { + if (object instanceof IMarker) { + IMarker marker = (IMarker) object; + marker = MarkUtilities.getLeaderOfMarker(marker); + final String relationName = relationMap.get(marker); + AlloyUtilities.addRelation2Markers(selectedMarker, marker, relationName); + } + } + AnnotationFactory.convertAnnotationType(selectedMarker, false, false, + AlloyUtilities.getTotalTargetCount(selectedMarker)); + } + + public static AtomType addStrayedAtom2Sig(final String sigName) { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + + final String id = MarkerFactory.generateId(); + + final ItemType itemType = persistenceFactory.eINSTANCE.createItemType(); + itemType.setId(id); + documentRoot.getAlloy().getRepository().getItem().add(itemType); + + final AtomType atomType = persistenceFactory.eINSTANCE.createAtomType(); + atomType.setLabel(id); + atomType.setReasoned(true); + + for (final SigType sigType : documentRoot.getAlloy().getInstance().getSig()) { + String label = sigType.getLabel(); + label = label.substring(sigType.getLabel().indexOf("/") + 1); + if (label.equals(sigName)) { + sigType.getAtom().add(atomType); + } + } + + AlloyUtilities.writeDocumentRoot(documentRoot); + + return atomType; + } + + public static AtomType addNewAtom2Sig(final String sigName) { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + + final String id = MarkerFactory.generateId(); + + final ItemType itemType = persistenceFactory.eINSTANCE.createItemType(); + itemType.setId(id); + documentRoot.getAlloy().getRepository().getItem().add(itemType); + + final AtomType atomType = persistenceFactory.eINSTANCE.createAtomType(); + atomType.setLabel(id); + atomType.setReasoned(false); + + for (final SigType sigType : documentRoot.getAlloy().getInstance().getSig()) { + String label = sigType.getLabel(); + label = label.substring(sigType.getLabel().indexOf("/") + 1); + if (label.equals(sigName)) { + sigType.getAtom().add(atomType); + } + } + + AlloyUtilities.writeDocumentRoot(documentRoot); + + return atomType; + } + + public static void addTypeToMarker(final IMarker marker) { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + + final AtomType atom = persistenceFactory.eINSTANCE.createAtomType(); + + atom.setLabel(MarkUtilities.getSourceId(marker)); + + final String type = MarkUtilities.getType(marker); + + final EList sigs = documentRoot.getAlloy().getInstance().getSig(); + + final int idOfTypeSigInSigType = AlloyUtilities.isTypeInSig(type); + + for (final SigType sigType : sigs) { + if (type.equals(sigType.getLabel().substring(sigType.getLabel().indexOf("/") + 1))) { + sigType.getAtom().add(atom); + } else if (idOfTypeSigInSigType != -1 && sigType.getID() == idOfTypeSigInSigType) { + final AtomType typeAtom = persistenceFactory.eINSTANCE.createAtomType(); + typeAtom.setLabel(MarkUtilities.getSourceId(marker)); + sigType.getAtom().add(typeAtom); + } + } + + AlloyUtilities.writeDocumentRoot(documentRoot); + } + + public static void assignMarker2Atom(final IMarker marker, final AlloyAtom atom) { + final String atomName = atom.getOriginalName(); + final String sigName = atom.getType().getName(); + final int index = Integer.valueOf(atomName.substring(atomName.indexOf("$") + 1)); + + final SigType sigType = + AlloyUtilities.getSigTypeById(AlloyUtilities.getSigTypeIdByName(sigName)); + final String id = sigType.getAtom().get(index).getLabel(); + + final int itemITypeIndex = AlloyUtilities.findItemTypeInRepository(marker); + + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + documentRoot.getAlloy().getRepository().getItem().get(itemITypeIndex).setId(id); + MarkUtilities.setSourceId(marker, id); + AlloyUtilities.writeDocumentRoot(documentRoot); + } + + public static void bindAtomToMarker(final String sigTypeName, final int index, + final IMarker selectedMarker) { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + String atomId = null; + + final EList sigs = documentRoot.getAlloy().getInstance().getSig(); + final EList fields = documentRoot.getAlloy().getInstance().getField(); + final EList items = documentRoot.getAlloy().getRepository().getItem(); + + for (final SigType sigType : sigs) { + String label = sigType.getLabel(); + label = label.substring(label.indexOf("/") + 1); + if (label.equals(sigTypeName)) { + final AtomType atomType = sigType.getAtom().get(index); + atomType.setReasoned(false); + atomId = atomType.getLabel(); + break; + } + } + + for (final FieldType fieldType : fields) { + for (final TupleType tupleType : fieldType.getTuple()) { + for (final AtomType atomType : tupleType.getAtom()) { + if (atomType.getLabel().equals(atomId)) { + atomType.setReasoned(false); + } + } + } + } + + final String id = MarkUtilities.getSourceId(selectedMarker); + + for (final ItemType itemType : items) { + if (itemType.getId().equals(id)) { + itemType.setId(atomId); + break; + } + } + MarkUtilities.setSourceId(selectedMarker, atomId); + MarkUtilities.setType(selectedMarker, sigTypeName); + + AlloyUtilities.writeDocumentRoot(documentRoot); + } + + public static void clearAllReasonedTuplesAndAtoms() { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + + final EList fieldTypes = documentRoot.getAlloy().getInstance().getField(); + + for (final FieldType fieldType : fieldTypes) { + final Iterator tupleIter = fieldType.getTuple().iterator(); + + while (tupleIter.hasNext()) { + final TupleType tupleType = tupleIter.next(); + if (tupleType.isReasoned()) { + tupleIter.remove(); + } + } + } + + final EList sigTypes = documentRoot.getAlloy().getInstance().getSig(); + + for (final SigType sigType : sigTypes) { + final Iterator atomIter = sigType.getAtom().iterator(); + while (atomIter.hasNext()) { + final AtomType atomType = atomIter.next(); + if (atomType.isReasoned()) { + atomIter.remove(); + } + } + } + + AlloyUtilities.writeDocumentRoot(documentRoot); + } + + public static void clearFields() { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + for (final FieldType fieldType : documentRoot.getAlloy().getInstance().getField()) { + fieldType.getTuple().clear(); + } + AlloyUtilities.writeDocumentRoot(documentRoot); + } + + public static void clearRelation() { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + documentRoot.getAlloy().getRelation().getTuple().clear(); + AlloyUtilities.writeDocumentRoot(documentRoot); + } + + public static void clearRepository() { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + documentRoot.getAlloy().getRepository().getItem().clear(); + AlloyUtilities.writeDocumentRoot(documentRoot); + } + + public static void clearSigs() { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + for (final SigType sigType : documentRoot.getAlloy().getInstance().getSig()) { + sigType.getAtom().clear(); + } + AlloyUtilities.writeDocumentRoot(documentRoot); + } + + public static List getAllReasonedAtoms() { + List result = new ArrayList(); + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + final EList sigTypes = documentRoot.getAlloy().getInstance().getSig(); + + for (final SigType sigType : sigTypes) { + final Iterator atomIter = sigType.getAtom().iterator(); + while (atomIter.hasNext()) { + final AtomType atomType = atomIter.next(); + if (atomType.isReasoned()) { + result.add(AlloyUtilities.getAtomNameById(atomType.getLabel())); + } + } + } + return result; + } + + public static HashMap getAllReasonedTuples() { + HashMap result = new HashMap(); + final EList fieldList = AlloyUtilities.getFieldTypes(); + for (final FieldType fieldType : fieldList) { + final EList tupleList = fieldType.getTuple(); + + for (final TupleType tupleType : tupleList) { + if (tupleType.isReasoned()) { + result.put(tupleType, fieldType.getLabel()); + } + } + } + return result; + } + + public static int findItemTypeInRepository(final IMarker marker) { + final String markerId = MarkUtilities.getSourceId(marker); + + final EList itemTypes = AlloyUtilities.getItemtypes(); + + int itemTypeIndex = 0; + + for (final ItemType itemType : itemTypes) { + if (markerId.equals(itemType.getId())) { + return itemTypeIndex; + } + itemTypeIndex++; + } + + return -1; + } + + public static IMarker findMarkerByID(final String markerId) { + final ItemType itemType = AlloyUtilities.getItemById(markerId); + + if (itemType == null) { + return null; + } + + final String path = AlloyUtilities.getValueOfEntry(itemType, AlloyUtilities.RESOURCE); + + if (path == null) { + return null; + } + + final IMarker marker = MarkUtilities.getiMarker(markerId, path); + + return marker; + } + + public static IMarker findMarker(final String sigTypeName, final int index) { + final SigType sigType = + AlloyUtilities.getSigTypeById(AlloyUtilities.getSigTypeIdByName(sigTypeName)); + final EList atoms = sigType.getAtom(); + + final String markerId = atoms.get(index).getLabel(); + + final ItemType itemType = AlloyUtilities.getItemById(markerId); + + if (itemType == null) { + return null; + } + + final String path = AlloyUtilities.getValueOfEntry(itemType, AlloyUtilities.RESOURCE); + + if (path == null) { + return null; + } + + final IMarker marker = MarkUtilities.getiMarker(markerId, path); + + return marker; + } + + public static ArrayList getAllChildNames(final int id) { + return (ArrayList) AlloyUtilities.getAllChildIds(id).stream() + .map(p -> AlloyUtilities.getSigNameById(p.intValue())).collect(Collectors.toList()); + } + + public static ArrayList getAllChildIds(final int id) { + final ArrayList ids = new ArrayList<>(); + + final ArrayList sigTypes = AlloyUtilities.getSigTypeListByParentId(id); + + for (final SigType sigType : sigTypes) { + ids.addAll(AlloyUtilities.getAllChildIds(sigType.getID())); + } + + ids.add(id); + + return ids; + } + + public static ArrayList getAllParentNames(final int id) { + return (ArrayList) AlloyUtilities.getAllParentIds(id).stream() + .map(p -> AlloyUtilities.getSigNameById(p.intValue())).collect(Collectors.toList()); + } + + public static ArrayList getAllParentIds(int id) { + final ArrayList ids = new ArrayList<>(); + + do { + ids.add(id); + final SigType sigType = AlloyUtilities.getSigTypeById(id); + if (sigType.getType().size() == 0) { + id = sigType.getParentID(); + } else { + id = sigType.getType().get(0).getID(); + } + } while (id != 0); + + return ids; + } + + public static ArrayList getAllParentIds(int id, final DocumentRoot documentRoot) { + final ArrayList ids = new ArrayList<>(); + + do { + ids.add(id); + final SigType sigType = AlloyUtilities.getSigTypeById(id, documentRoot); + if (sigType.getType().size() == 0) { + id = sigType.getParentID(); + } else { + id = sigType.getType().get(0).getID(); + } + } while (id != 0); + + return ids; + } + + public static SigType getAncestorOfSig(final int id) { + SigType sigType = AlloyUtilities.getSigTypeById(id); + while (sigType.getParentID() != 2) { + sigType = AlloyUtilities.getSigTypeById(sigType.getParentID()); + } + + return sigType; + } + + public static String getAtomNameById(final String id) { + final EList sigList = AlloyUtilities.getSigTypes(AlloyUtilities.getDocumentRoot()); + + for (final SigType sigType : sigList) { + final EList atoms = sigType.getAtom(); + int index = 0; + final String sigLabel = sigType.getLabel().substring(sigType.getLabel().indexOf("/") + 1); + + for (final AtomType atomType : atoms) { + if (atomType.getLabel().equals(id)) { + return sigLabel + "$" + index; + } + index++; + } + } + return null; + } + + public static AtomType getAtomTypeBySourceIdFromSig(final DocumentRoot documentRoot, + final String sourceId) { + final AlloyType alloyType = documentRoot.getAlloy(); + + final EList listOfSigs = alloyType.getInstance().getSig(); + for (final SigType sigType : listOfSigs) { + final EList atoms = sigType.getAtom(); + for (final AtomType atomType : atoms) { + if (atomType.getLabel().equals(sourceId)) { + return atomType; + } + } + } + return null; + } + + public static ArrayList getChangedAtoms() { + final EList sigList = AlloyUtilities.getSigTypes(AlloyUtilities.getDocumentRoot()); + final ArrayList changedAtoms = new ArrayList<>(); + + for (final SigType sigType : sigList) { + final EList atoms = sigType.getAtom(); + int index = 0; + final String sigLabel = sigType.getLabel().substring(sigType.getLabel().indexOf("/") + 1); + + for (final AtomType atomType : atoms) { + if (atomType.getChanged() != null && atomType.getChanged()) { + changedAtoms.add(sigLabel + "$" + index); + } + index++; + } + } + return changedAtoms; + } + + public static DocumentRoot getDocumentRoot() { + @SuppressWarnings("rawtypes") + final ModelIO modelIO = new ModelIO<>(); + @SuppressWarnings("rawtypes") + final List list; + try { + list = modelIO.read(AlloyUtilities.getUri()); + } catch (final IOException e) { + return null; + } + if (list.isEmpty()) { + return null; + } + final DocumentRoot documentRoot = (DocumentRoot) list.get(0); + return documentRoot; + } + + public static DocumentRoot getDocumentRootForMetaModel(final String filename) { + @SuppressWarnings("rawtypes") + final ModelIO modelIO = new ModelIO<>(); + @SuppressWarnings("rawtypes") + List list = null; + try { + list = modelIO.read(URI.createFileURI(AlloyUtilities.getLocationForMetamodel(filename))); + } catch (final IOException e) { + return null; + } + if (list.isEmpty()) { + return null; + } + final DocumentRoot documentRoot = (DocumentRoot) list.get(0); + return documentRoot; + } + + public static FieldType getFieldTypeByName(final String label) { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + + for (final FieldType fieldType : documentRoot.getAlloy().getInstance().getField()) { + if (fieldType.getLabel().equals(label)) { + return fieldType; + } + } + return null; + } + + public static EList getFieldTypes() { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + + return documentRoot.getAlloy().getInstance().getField(); + } + + /** + * @param typeName + * @param side if true, return FieldType List according left side type + * @return + */ + public static ArrayList getFieldTypesList(final String typeName, final boolean side) { + final EList fields = AlloyUtilities.getFieldTypes(); + final ArrayList foundFieldTypes = new ArrayList<>(); + + final int id = AlloyUtilities.getSigTypeIdByName(typeName); + + final ArrayList idList = AlloyUtilities.getAllParentIds(id); + + for (final Integer typeId : idList) { + for (final FieldType fieldType : fields) { + final EList typesTypes = fieldType.getTypes(); + for (final TypesType typesType : typesTypes) { + final EList typeTypes = typesType.getType(); + if (side && typeTypes.get(0).getID() == typeId) { + foundFieldTypes.add(fieldType); + break; + } else if (!side && typeTypes.get(1).getID() == typeId) { + foundFieldTypes.add(fieldType); + break; + } + } + } + } + return foundFieldTypes; + } + + public static ArrayList> getImpactedAtoms() { + final EList fieldList = AlloyUtilities.getFieldTypes(); + final ArrayList> impactedAtoms = new ArrayList<>(); + + for (final FieldType fieldType : fieldList) { + final EList tupleList = fieldType.getTuple(); + + for (final TupleType tupleType : tupleList) { + if (tupleType.getAtom().get(1).getImpact() != null + && tupleType.getAtom().get(1).getImpact()) { + final AtomType atom = AlloyUtilities.getAtomTypeBySourceIdFromSig( + AlloyUtilities.getDocumentRoot(), tupleType.getAtom().get(1).getLabel()); + final AtomType changedAtom = AlloyUtilities.getAtomTypeBySourceIdFromSig( + AlloyUtilities.getDocumentRoot(), tupleType.getAtom().get(0).getLabel()); + final ArrayList impactedRelations = new ArrayList<>(); + impactedRelations.add(AlloyUtilities.getAtomNameById(atom.getLabel())); + impactedRelations.add(AlloyUtilities.getAtomNameById(changedAtom.getLabel())); + impactedAtoms.add(impactedRelations); + } + } + } + return impactedAtoms; + } + + public static ItemType getItemById(final String id) { + final EList itemTypes = AlloyUtilities.getItemtypes(); + + for (final ItemType itemType : itemTypes) { + if (id.equals(itemType.getId())) { + return itemType; + } + } + + return null; + } + + public static EList getItemtypes() { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + + return documentRoot.getAlloy().getRepository().getItem(); + } + + public static String getLocation() { + return ResourcesPlugin.getWorkspace().getRoot().getLocation() + "/" + + AlloyUtilities.xmlFileLocation; + } + + public static String getLocationForMetamodel(final String filename) { + return ResourcesPlugin.getWorkspace().getRoot().getLocation() + + System.getProperty("file.separator") + ".modelwriter" + + System.getProperty("file.separator") + filename + System.getProperty("file.separator") + + ".xml"; + } + + public static String getOriginalModuleName() { + final String filePath = + AlloyUtilities.getDocumentRoot().getAlloy().getSource().get(0).getFilename(); + return filePath.substring(filePath.lastIndexOf(System.getProperty("file.separator")) + 1, + filePath.lastIndexOf(".")); + } + + private static ArrayList getReasonedAtoms() { + final EList sigList = AlloyUtilities.getSigTypes(AlloyUtilities.getDocumentRoot()); + final ArrayList reasonedAtoms = new ArrayList<>(); + + for (final SigType sigType : sigList) { + final EList atoms = sigType.getAtom(); + int index = 0; + final String sigLabel = sigType.getLabel().substring(sigType.getLabel().indexOf("/") + 1); + + for (final AtomType atomType : atoms) { + if (atomType.isReasoned()) { + reasonedAtoms.add(sigLabel + "$" + index); + } + index++; + } + } + return reasonedAtoms; + + } + + public static Map getRelationsOfFirstSideMarker(IMarker selectedMarker) { + selectedMarker = MarkUtilities.getLeaderOfMarker(selectedMarker); + + final Map relationsOfMarker = new HashMap<>(); + if (MarkUtilities.getType(selectedMarker) == null) { + return relationsOfMarker; + } + final ArrayList fieldTypesOfSelectedMarkerType = + AlloyUtilities.getFieldTypesList(MarkUtilities.getType(selectedMarker), true); + final String selectedMarkerId = MarkUtilities.getSourceId(selectedMarker); + + for (final FieldType fieldType : fieldTypesOfSelectedMarkerType) { + final EList tupleTypes = fieldType.getTuple(); + for (final TupleType tupleType : tupleTypes) { + final EList atoms = tupleType.getAtom(); + final AtomType firstAtomType = atoms.get(0); + if (firstAtomType.getLabel().equals(selectedMarkerId)) { + final AtomType secondAtomType = atoms.get(1); + final ItemType itemTypeOfAtom = AlloyUtilities.getItemById(secondAtomType.getLabel()); + if (itemTypeOfAtom == null) + continue; + final IMarker toMarker = MarkUtilities.getiMarker(secondAtomType.getLabel(), + AlloyUtilities.getValueOfEntry(itemTypeOfAtom, AlloyUtilities.RESOURCE)); + relationsOfMarker.put(toMarker, fieldType.getLabel()); + } + } + } + + return relationsOfMarker; + } + + + public static String getAtomId(final String sigTypeName, final int index) { + final SigType sigType = + AlloyUtilities.getSigTypeById(AlloyUtilities.getSigTypeIdByName(sigTypeName)); + final EList atoms = sigType.getAtom(); + return atoms.get(index).getLabel(); + } + + public static Map getReasonedRelationsOfFSAtom(final String sigTypeName, + final int index) { + final String id = AlloyUtilities.getAtomId(sigTypeName, index); + final Map relationsOfMarker = new HashMap<>(); + final ArrayList fieldTypesOfSelectedMarkerType = + AlloyUtilities.getFieldTypesList(sigTypeName, true); + + for (final FieldType fieldType : fieldTypesOfSelectedMarkerType) { + final EList tupleTypes = fieldType.getTuple(); + for (final TupleType tupleType : tupleTypes) { + final EList atoms = tupleType.getAtom(); + final AtomType firstAtomType = atoms.get(0); + if (firstAtomType.getLabel().equals(id) && tupleType.isReasoned()) { + final AtomType secondAtomType = atoms.get(1); + Object key = null; + if (!secondAtomType.isReasoned()) { + final ItemType itemTypeOfAtom = AlloyUtilities.getItemById(secondAtomType.getLabel()); + key = MarkUtilities.getiMarker(secondAtomType.getLabel(), + AlloyUtilities.getValueOfEntry(itemTypeOfAtom, AlloyUtilities.RESOURCE)); + } else + key = AlloyUtilities.getAtomNameById(secondAtomType.getLabel()); + relationsOfMarker.put(key, fieldType.getLabel()); + } + } + } + return relationsOfMarker; + } + + public static Map getReasonedRelationsOfSSAtom(final String sigTypeName, + final int index) { + final String id = AlloyUtilities.getAtomId(sigTypeName, index); + + final Map relationsOfMarker = new HashMap<>(); + final ArrayList fieldTypesOfSelectedMarkerType = + AlloyUtilities.getFieldTypesList(sigTypeName, false); + + for (final FieldType fieldType : fieldTypesOfSelectedMarkerType) { + final EList tupleTypes = fieldType.getTuple(); + for (final TupleType tupleType : tupleTypes) { + final EList atoms = tupleType.getAtom(); + final AtomType secondAtomType = atoms.get(1); + if (secondAtomType.getLabel().equals(id) && tupleType.isReasoned()) { + final AtomType firstAtomType = atoms.get(0); + Object key = null; + if (!firstAtomType.isReasoned()) { + final ItemType itemTypeOfAtom = AlloyUtilities.getItemById(firstAtomType.getLabel()); + key = MarkUtilities.getiMarker(firstAtomType.getLabel(), + AlloyUtilities.getValueOfEntry(itemTypeOfAtom, AlloyUtilities.RESOURCE)); + } else + key = AlloyUtilities.getAtomNameById(firstAtomType.getLabel()); + relationsOfMarker.put(key, fieldType.getLabel()); + } + } + } + return relationsOfMarker; + } + + public static Map getRelationsOfSecondSideMarker(IMarker selectedMarker) { + selectedMarker = MarkUtilities.getLeaderOfMarker(selectedMarker); + + final Map relationsOfMarker = new HashMap<>(); + if (MarkUtilities.getType(selectedMarker) == null) { + return relationsOfMarker; + } + final ArrayList fieldTypesOfSelectedMarkerType = + AlloyUtilities.getFieldTypesList(MarkUtilities.getType(selectedMarker), false); + final String selectedMarkerId = MarkUtilities.getSourceId(selectedMarker); + + for (final FieldType fieldType : fieldTypesOfSelectedMarkerType) { + final EList tupleTypes = fieldType.getTuple(); + for (final TupleType tupleType : tupleTypes) { + final EList atoms = tupleType.getAtom(); + final AtomType firstAtomType = atoms.get(1); + if (firstAtomType.getLabel().equals(selectedMarkerId)) { + final AtomType secondAtomType = atoms.get(0); + final ItemType itemTypeOfAtom = AlloyUtilities.getItemById(secondAtomType.getLabel()); + if (itemTypeOfAtom == null) + continue; + final IMarker toMarker = MarkUtilities.getiMarker(secondAtomType.getLabel(), + AlloyUtilities.getValueOfEntry(itemTypeOfAtom, AlloyUtilities.RESOURCE)); + relationsOfMarker.put(toMarker, fieldType.getLabel()); + } + } + } + + return relationsOfMarker; + } + + /** + * This method is used to get Relations + * + * @return + */ + public static RelationType getRelationType(final DocumentRoot documentRoot) { + return documentRoot.getAlloy().getRelation(); + } + + public static ArrayList getRelationTypesForFirstSide(final String typeName) { + final ArrayList relationTypeNames = new ArrayList<>(); + + final int typeId = AlloyUtilities.getSigTypeIdByName(typeName); + + if (typeId == -1) { + return null; + } + + final ArrayList parentIds = AlloyUtilities.getAllParentIds(typeId); + + final EList fieldTypes = AlloyUtilities.getFieldTypes(); + + for (final FieldType fieldType : fieldTypes) { + for (final Integer parentId : parentIds) { + if (fieldType.getParentID() == parentId) { + relationTypeNames.add(fieldType.getLabel()); + break; + } + } + } + + return relationTypeNames; + } + + public static ArrayList getSecondSideAtomsBySourceIdOfFirstSide( + final DocumentRoot documentRoot, final String sourceId) { + final AlloyType alloyType = documentRoot.getAlloy(); + final ArrayList atoms = new ArrayList<>(); + + final EList listOfField = alloyType.getInstance().getField(); + for (final FieldType fieldType : listOfField) { + final EList tuples = fieldType.getTuple(); + for (final TupleType tupleType : tuples) { + if (tupleType.getAtom().get(0).getLabel().equals(sourceId)) { + atoms.add(tupleType.getAtom().get(1)); + } + } + } + return atoms; + } + + public static ArrayList getSecondSideMarkerIdsByMarkerAndRelation(IMarker marker, + final String relation) { + marker = MarkUtilities.getLeaderOfMarker(marker); + + final EList fieldTypes = AlloyUtilities.getFieldTypes(); + + final String markerId = MarkUtilities.getSourceId(marker); + + final ArrayList suitableMarkers = new ArrayList<>(); + + for (final FieldType fieldType : fieldTypes) { + if (fieldType.getLabel().equals(relation)) { + final EList tuples = fieldType.getTuple(); + for (final TupleType tupleType : tuples) { + final EList atoms = tupleType.getAtom(); + if (atoms.get(0).getLabel().equals(markerId)) { + final ItemType itemType = AlloyUtilities.getItemById(atoms.get(1).getLabel()); + final IMarker suitableMarker = MarkUtilities.getiMarker(itemType.getId(), + AlloyUtilities.getValueOfEntry(itemType, AlloyUtilities.RESOURCE)); + suitableMarkers.add(suitableMarker); + } + } + break; + } + } + + return suitableMarkers; + } + + /** + * This method is used to get Target List of iMarker. Also iMarker doesn't contain any marker + * type. + * + * @param iMarker + * @return + */ + public static ArrayList getSecondSideMarkerIdsByMarkerAndRelationV2(IMarker iMarker) { + iMarker = MarkUtilities.getLeaderOfMarker(iMarker); + + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + + final RelationType relationType = AlloyUtilities.getRelationType(documentRoot); + final EList tupleTypes = relationType.getTuple(); + + final String markerId = MarkUtilities.getSourceId(iMarker); + + final ArrayList suitableMarkers = new ArrayList<>(); + + for (final TupleType tupleType : tupleTypes) { + final EList atoms = tupleType.getAtom(); + if (atoms.get(0).getLabel().equals(markerId)) { + final ItemType itemType = AlloyUtilities.getItemById(atoms.get(1).getLabel()); + final IMarker suitableMarker = MarkUtilities.getiMarker(itemType.getId(), + AlloyUtilities.getValueOfEntry(itemType, AlloyUtilities.RESOURCE)); + suitableMarkers.add(suitableMarker); + } + } + + return suitableMarkers; + } + + public static String getSigNameById(final int id) { + final SigType sigType = AlloyUtilities.getSigTypeById(id); + return sigType.getLabel().substring(sigType.getLabel().indexOf("/") + 1); + } + + public static String getSigNameById(final int id, final DocumentRoot documentRoot) { + final SigType sigType = AlloyUtilities.getSigTypeById(id, documentRoot); + return sigType.getLabel().substring(sigType.getLabel().indexOf("/") + 1); + } + + public static SigType getSigTypeById(final int id) { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + final EList sigTypes = AlloyUtilities.getSigTypes(documentRoot); + + for (final SigType sigType : sigTypes) { + if (id == sigType.getID()) { + return sigType; + } + } + return null; + } + + public static SigType getSigTypeById(final int id, final DocumentRoot documentRoot) { + final EList sigTypes = AlloyUtilities.getSigTypes(documentRoot); + + for (final SigType sigType : sigTypes) { + if (id == sigType.getID()) { + return sigType; + } + } + return null; + } + + public static int getSigTypeIdByName(final String typeName) { + int id = -1; + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + final EList sigTypes = AlloyUtilities.getSigTypes(documentRoot); + + for (final SigType sigType : sigTypes) { + if (typeName.equals(sigType.getLabel().substring(sigType.getLabel().indexOf("/") + 1))) { + id = sigType.getID(); + break; + } + } + return id; + } + + public static int getSigTypeIdByName(final String typeName, final DocumentRoot documentRoot) { + int id = -1; + final EList sigTypes = AlloyUtilities.getSigTypes(documentRoot); + + for (final SigType sigType : sigTypes) { + if (typeName.equals(sigType.getLabel().substring(sigType.getLabel().indexOf("/") + 1))) { + id = sigType.getID(); + break; + } + } + return id; + } + + public static ArrayList getSigTypeListByParentId(final int id) { + final ArrayList suitableSigTypes = new ArrayList<>(); + + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + final EList sigTypes = AlloyUtilities.getSigTypes(documentRoot); + + for (final SigType sigType : sigTypes) { + if (sigType.getParentID() == id) { + suitableSigTypes.add(sigType); + } + } + + return suitableSigTypes; + } + + public static EList getSigTypes(final DocumentRoot documentRoot) { + return documentRoot.getAlloy().getInstance().getSig(); + } + + /** + * This method is used to get source marker list of iMarker. Also iMarker doesn't contain any + * marker type. + * + * @param iMarker + * @return + */ + public static ArrayList getSourcesOfMarkerAtRelations(IMarker iMarker) { + iMarker = MarkUtilities.getLeaderOfMarker(iMarker); + + final ArrayList sources = new ArrayList<>(); + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + + final RelationType relationType = AlloyUtilities.getRelationType(documentRoot); + final String selectedMarkerId = MarkUtilities.getSourceId(iMarker); + + final EList tupleTypes = relationType.getTuple(); + for (final TupleType tupleType : tupleTypes) { + final EList atoms = tupleType.getAtom(); + final AtomType firstAtomType = atoms.get(0); + final AtomType secondAtomType = atoms.get(1); + if (secondAtomType.getLabel().equals(selectedMarkerId)) { + final ItemType itemTypeOfAtom = AlloyUtilities.getItemById(firstAtomType.getLabel()); + final IMarker toMarker = MarkUtilities.getiMarker(firstAtomType.getLabel(), + AlloyUtilities.getValueOfEntry(itemTypeOfAtom, AlloyUtilities.RESOURCE)); + sources.add(toMarker); + } + } + return sources; + } + + public static ArrayList getSuitableSecondSideTypesOfRelation(final String relationName, + final String firstSideType) { + final EList fields = AlloyUtilities.getFieldTypes(); + + final ArrayList suitableRelationNames = new ArrayList<>(); + + final int firstSideTypeId = AlloyUtilities.getSigTypeIdByName(firstSideType); + final ArrayList parentIdsOfFirstSideType = + AlloyUtilities.getAllParentIds(firstSideTypeId); + + final ArrayList secondSideTypeIds = new ArrayList<>(); + for (final FieldType fieldType : fields) { + if (fieldType.getLabel().equals(relationName) && parentIdsOfFirstSideType + .contains(fieldType.getTypes().get(0).getType().get(0).getID())) { + secondSideTypeIds.add(fieldType.getTypes().get(0).getType().get(1).getID()); + } + } + + final ArrayList suitableIds = new ArrayList<>(); + for (final Integer secondSideTypeId : secondSideTypeIds) { + suitableIds.addAll(AlloyUtilities.getAllChildIds(secondSideTypeId)); + } + + for (final Integer suitableId : suitableIds) { + suitableRelationNames.add(AlloyUtilities.getSigTypeById(suitableId).getLabel()); + } + + return suitableRelationNames; + } + + /** + * This method is used to when iMarker has marker type and we want to find it's sources both have + * marker type or not. + * + * @param iMarker + * @return + */ + public static ArrayList getSumSources(IMarker iMarker) { + iMarker = MarkUtilities.getLeaderOfMarker(iMarker); + + final Map sourcesMap = AlloyUtilities.getRelationsOfSecondSideMarker(iMarker); + final ArrayList sourcesList = AlloyUtilities.getSourcesOfMarkerAtRelations(iMarker); + + final ArrayList resultList = new ArrayList<>(sourcesList); + + final Set sourceMarkers = sourcesMap.keySet(); + final Iterator iter = sourceMarkers.iterator(); + while (iter.hasNext()) { + final IMarker iMarkerSet = iter.next(); + if (!sourcesList.contains(iMarkerSet)) { + resultList.add(iMarkerSet); + } + } + return resultList; + } + + /** + * This method is used to get target marker list of iMarker. Also iMarker doesn't contain any + * marker type. + * + * @param iMarker + * @return + */ + public static ArrayList getTargetsOfMarkerAtRelations(IMarker iMarker) { + iMarker = MarkUtilities.getLeaderOfMarker(iMarker); + + final ArrayList targets = new ArrayList<>(); + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + + final RelationType relationType = AlloyUtilities.getRelationType(documentRoot); + final String selectedMarkerId = MarkUtilities.getSourceId(iMarker); + + final EList tupleTypes = relationType.getTuple(); + for (final TupleType tupleType : tupleTypes) { + final EList atoms = tupleType.getAtom(); + final AtomType firstAtomType = atoms.get(0); + if (firstAtomType.getLabel().equals(selectedMarkerId)) { + final AtomType secondAtomType = atoms.get(1); + final ItemType itemTypeOfAtom = AlloyUtilities.getItemById(secondAtomType.getLabel()); + final IMarker toMarker = MarkUtilities.getiMarker(secondAtomType.getLabel(), + AlloyUtilities.getValueOfEntry(itemTypeOfAtom, AlloyUtilities.RESOURCE)); + targets.add(toMarker); + } + } + + return targets; + } + + public static URI getUri() { + return URI.createFileURI(AlloyUtilities.getLocation()); + } + + public static String getValueOfEntry(final ItemType itemType, final String key) { + String value = null; + final EList entries = itemType.getEntry(); + + for (final EntryType entryType : entries) { + if (key.equals(entryType.getKey())) { + value = entryType.getValue(); + break; + } + } + return value; + } + + public static boolean isAnyReasoned() { + + for (final FieldType fieldType : AlloyUtilities.getFieldTypes()) { + for (final TupleType tupleType : fieldType.getTuple()) { + if (tupleType.isReasoned()) { + return true; + } + } + } + + return false; + } + + public static boolean isContainTuple(final FieldType fieldType, + final TupleType searchedTupleType) { + final EList tuples = fieldType.getTuple(); + final EList searchedAtoms = searchedTupleType.getAtom(); + for (final TupleType tupleType : tuples) { + final EList atoms = tupleType.getAtom(); + if (atoms.get(0).getLabel().equals(searchedAtoms.get(0).getLabel()) + && atoms.get(1).getLabel().equals(searchedAtoms.get(1).getLabel())) { + return true; + } + } + return false; + } + + /** + * @return true if Alloy file parsed and XML file is constructed , false if doesn't. + */ + public static boolean isExists() { + final Path path = new Path(AlloyUtilities.getLocation()); + return path.toFile().exists() ? true : false; + } + + public static int isTypeInSig(final String sigTypeName) { + + final SigType sigType = + AlloyUtilities.getSigTypeById(AlloyUtilities.getSigTypeIdByName(sigTypeName)); + + return sigType.getType().isEmpty() ? -1 : sigType.getType().get(0).getID(); + } + + public static void removeAllRelationsOfMarker(IMarker marker) { + marker = MarkUtilities.getLeaderOfMarker(marker); + + if (marker != null) { + Iterator> iter; + final Map relationsOfFirstSide = + AlloyUtilities.getRelationsOfFirstSideMarker(marker); + iter = relationsOfFirstSide.entrySet().iterator(); + + while (iter.hasNext()) { + @SuppressWarnings("rawtypes") + final Map.Entry pair = iter.next(); + AlloyUtilities.removeFieldOfMarkers(marker, (IMarker) pair.getKey(), + (String) pair.getValue()); + } + + final Map relationsOfSecondSide = + AlloyUtilities.getRelationsOfSecondSideMarker(marker); + iter = relationsOfSecondSide.entrySet().iterator(); + + while (iter.hasNext()) { + @SuppressWarnings("rawtypes") + final Map.Entry pair = iter.next(); + AlloyUtilities.removeFieldOfMarkers((IMarker) pair.getKey(), marker, + (String) pair.getValue()); + } + } + } + + public static void removeFieldOfMarkers(IMarker fromMarker, IMarker toMarker, + final String relationName) { + fromMarker = MarkUtilities.getLeaderOfMarker(fromMarker); + toMarker = MarkUtilities.getLeaderOfMarker(toMarker); + + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + final EList fieldTypes = documentRoot.getAlloy().getInstance().getField(); + + final String fromMarkerId = MarkUtilities.getSourceId(fromMarker); + final String toMarkerId = MarkUtilities.getSourceId(toMarker); + + for (final FieldType fieldType : fieldTypes) { + if (fieldType.getLabel().equals(relationName)) { + final Iterator tupleTypesIter = fieldType.getTuple().iterator(); + while (tupleTypesIter.hasNext()) { + final EList atoms = tupleTypesIter.next().getAtom(); + if (atoms.get(0).getLabel().equals(fromMarkerId) + && atoms.get(1).getLabel().equals(toMarkerId)) { + tupleTypesIter.remove(); + AlloyUtilities.writeDocumentRoot(documentRoot); + return; + } + } + } + } + } + + /** + * This method is used to when fromMarker doesn't map toMarker any more. + * + * @param fromMarker + * @param toMarker + */ + public static void removeMappingFromRelationType(IMarker fromMarker, IMarker toMarker) { + fromMarker = MarkUtilities.getLeaderOfMarker(fromMarker); + toMarker = MarkUtilities.getLeaderOfMarker(toMarker); + + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + final RelationType relationType = AlloyUtilities.getRelationType(documentRoot); + + final String fromMarkerId = MarkUtilities.getSourceId(fromMarker); + final String toMarkerId = MarkUtilities.getSourceId(toMarker); + + final Iterator iter = relationType.getTuple().iterator(); + while (iter.hasNext()) { + final EList atoms = iter.next().getAtom(); + if (atoms.get(0).getLabel().equals(fromMarkerId) + && atoms.get(1).getLabel().equals(toMarkerId)) { + iter.remove(); + AlloyUtilities.writeDocumentRoot(documentRoot); + return; + } + } + } + + public static void removeMarkerFromRepository(final IMarker marker) { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + + final int itemTypeIndex = AlloyUtilities.findItemTypeInRepository(marker); + if (itemTypeIndex == -1) { + return; + } + documentRoot.getAlloy().getRepository().getItem().remove(itemTypeIndex); + + AlloyUtilities.writeDocumentRoot(documentRoot); + } + + /** + * Removes relation of given marker + * + * @param marker which will be deleted relation of + */ + public static void removeRelationOfMarker(IMarker marker) { + marker = MarkUtilities.getLeaderOfMarker(marker); + + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + + final String id = MarkUtilities.getSourceId(marker); + final EList tupleTypes = AlloyUtilities.getRelationType(documentRoot).getTuple(); + final Iterator iter = tupleTypes.iterator(); + while (iter.hasNext()) { + final TupleType tupleType = iter.next(); + final AtomType firstSideAtom = tupleType.getAtom().get(0); + final AtomType secondSideAtom = tupleType.getAtom().get(1); + if (firstSideAtom.getLabel().equals(id) || secondSideAtom.getLabel().equals(id)) { + iter.remove(); + } + } + AlloyUtilities.writeDocumentRoot(documentRoot); + } + + public static void removeTypeFromMarker(final IMarker marker) { + if (MarkUtilities.compare(marker, MarkUtilities.getLeaderOfMarker(marker))) { + AlloyUtilities.removeAllRelationsOfMarker(marker); + } + + if (MarkUtilities.getType(marker) == null || MarkUtilities.getType(marker).isEmpty()) { + return; + } + + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + + final String type = MarkUtilities.getType(marker); + + final String markerId = MarkUtilities.getSourceId(marker); + + final int idOfTypeSigInSigType = AlloyUtilities.isTypeInSig(type); + + final EList sigs = documentRoot.getAlloy().getInstance().getSig(); + + for (final SigType sigType : sigs) { + if (type.equals(sigType.getLabel().substring(sigType.getLabel().indexOf("/") + 1)) + || idOfTypeSigInSigType != -1 && sigType.getID() == idOfTypeSigInSigType) { + final Iterator atomsIter = sigType.getAtom().iterator(); + while (atomsIter.hasNext()) { + final AtomType atomType = atomsIter.next(); + if (atomType.getLabel().equals(markerId)) { + atomsIter.remove(); + break; + } + } + } + } + + AlloyUtilities.writeDocumentRoot(documentRoot); + } + + public static void resetReasoned(IMarker fromMarker, IMarker toMarker, + final String relationName) { + fromMarker = MarkUtilities.getLeaderOfMarker(fromMarker); + toMarker = MarkUtilities.getLeaderOfMarker(toMarker); + + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + final EList fieldTypes = documentRoot.getAlloy().getInstance().getField(); + + final String fromMarkerId = MarkUtilities.getSourceId(fromMarker); + final String toMarkerId = MarkUtilities.getSourceId(toMarker); + + for (final FieldType fieldType : fieldTypes) { + if (fieldType.getLabel().equals(relationName)) { + final Iterator tupleTypesIter = fieldType.getTuple().iterator(); + while (tupleTypesIter.hasNext()) { + final TupleType tupleType = tupleTypesIter.next(); + final EList atoms = tupleType.getAtom(); + if (atoms.get(0).getLabel().equals(fromMarkerId) + && atoms.get(1).getLabel().equals(toMarkerId)) { + tupleType.setReasoned(false); + AlloyUtilities.writeDocumentRoot(documentRoot); + return; + } + } + } + } + } + + public static void setAllImpactsAndChanges(final AlloyInstance instance) { + final Iterator iter = instance.atom2sets.keySet().iterator(); + + final ArrayList changedAtoms = AlloyUtilities.getChangedAtoms(); + final ArrayList> impactedAtoms = AlloyUtilities.getImpactedAtoms(); + while (iter.hasNext()) { + final AlloyAtom alloyAtom = iter.next(); + final String alloyAtomName = alloyAtom.getOriginalName(); + if (changedAtoms.contains(alloyAtomName)) { + alloyAtom.changed = true; + } + for (final ArrayList impactedAtom : impactedAtoms) { + if (impactedAtom.get(0).equals(alloyAtomName)) { + alloyAtom.impacted.add(impactedAtom.get(1)); + } + } + } + } + + public static void setAllReasonedAtoms(final AlloyInstance instance) { + final Iterator iter = instance.atom2sets.keySet().iterator(); + + final ArrayList reasonedAtoms = AlloyUtilities.getReasonedAtoms(); + while (iter.hasNext()) { + final AlloyAtom alloyAtom = iter.next(); + final String alloyAtomName = alloyAtom.getOriginalName(); + if (reasonedAtoms.contains(alloyAtomName)) { + alloyAtom.isDashed = true; + } + } + } + + public static void setAllReasonedTuples(final AlloyInstance instance) { + final EList fieldList = AlloyUtilities.getFieldTypes(); + final Map reasonedTuplesInFields = new HashMap<>(); + + for (final FieldType fieldType : fieldList) { + final EList tuples = fieldType.getTuple(); + for (final TupleType tupleType : tuples) { + if (tupleType.isReasoned()) { + reasonedTuplesInFields.put(tupleType, fieldType); + } + } + } + + for (final Entry reasonedEntry : reasonedTuplesInFields.entrySet()) { + final TupleType tupleType = reasonedEntry.getKey(); + final FieldType fieldType = reasonedEntry.getValue(); + for (final Entry> entry : instance.rel2tuples.entrySet()) { + if (entry.getKey().getName().equals(fieldType.getLabel())) { + final Iterator tupleSetIter = entry.getValue().iterator(); + while (tupleSetIter.hasNext()) { + final AlloyTuple alloyTuple = tupleSetIter.next(); + boolean tuplesREqual = true; + for (int i = 0; i < tupleType.getAtom().size(); i++) { + if (!AlloyUtilities.getAtomNameById(tupleType.getAtom().get(i).getLabel()) + .equals(alloyTuple.getAtoms().get(i).getOriginalName())) { + tuplesREqual = false; + break; + } + } + if (tuplesREqual) { + alloyTuple.isDashed = true; + } + } + } + } + } + } + + private static void setEntries(final ItemType itemType, final IMarker marker) { + if (MarkUtilities.getPath(marker) != null) { + final EntryType resourceEntry = persistenceFactory.eINSTANCE.createEntryType(); + resourceEntry.setKey(AlloyUtilities.RESOURCE); + resourceEntry.setValue(MarkUtilities.getPath(marker)); + itemType.getEntry().add(resourceEntry); + } + if (MarkUtilities.getStart(marker) != -1) { + final EntryType offsetEntry = persistenceFactory.eINSTANCE.createEntryType(); + offsetEntry.setKey(AlloyUtilities.OFFSET); + offsetEntry.setValue(Integer.toString(MarkUtilities.getStart(marker))); + itemType.getEntry().add(offsetEntry); + } + if (MarkUtilities.getText(marker) != null) { + final EntryType textEntry = persistenceFactory.eINSTANCE.createEntryType(); + textEntry.setKey(AlloyUtilities.TEXT); + textEntry.setValue(MarkUtilities.getText(marker)); + itemType.getEntry().add(textEntry); + } + if (MarkUtilities.getUri(marker) != null) { + final EntryType uriEntry = persistenceFactory.eINSTANCE.createEntryType(); + uriEntry.setKey(AlloyUtilities.MARKER_URI); + uriEntry.setValue(MarkUtilities.getUri(marker)); + itemType.getEntry().add(uriEntry); + } + if (MarkUtilities.getLeaderId(marker) != null) { + final EntryType leaderIdEntry = persistenceFactory.eINSTANCE.createEntryType(); + leaderIdEntry.setKey(AlloyUtilities.LEADER_ID); + leaderIdEntry.setValue(MarkUtilities.getLeaderId(marker)); + itemType.getEntry().add(leaderIdEntry); + } + if (MarkUtilities.getGroupId(marker) != null) { + final EntryType groupIdEntry = persistenceFactory.eINSTANCE.createEntryType(); + groupIdEntry.setKey(AlloyUtilities.GROUP_ID); + groupIdEntry.setValue(MarkUtilities.getGroupId(marker)); + itemType.getEntry().add(groupIdEntry); + } + } + + public static void setImpactAndChanged(final IMarker marker) { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + final AlloyType alloyType = documentRoot.getAlloy(); + + if (MarkUtilities.getType(marker) != null) { + final EList listOfSigs = alloyType.getInstance().getSig(); + for (final SigType sigType : listOfSigs) { + final EList atoms = sigType.getAtom(); + for (final AtomType atomType : atoms) { + if (atomType.getLabel().equals(MarkUtilities.getSourceId(marker))) { + atomType.setChanged(true); + } + } + } + final EList listOfField = alloyType.getInstance().getField(); + for (final FieldType fieldType : listOfField) { + final EList tuples = fieldType.getTuple(); + for (final TupleType tupleType : tuples) { + if (tupleType.getAtom().get(0).getLabel().equals(MarkUtilities.getSourceId(marker))) { + tupleType.getAtom().get(1).setImpact(true); + } + } + } + AlloyUtilities.writeDocumentRoot(documentRoot); + } + } + + public static void setMetamodel(final String filename, final boolean state) { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRootForMetaModel(filename); + if (state == true) { + documentRoot.getAlloy().getInstance().setMetamodel("yes"); + } else { + documentRoot.getAlloy().getInstance().setMetamodel(null); + } + + AlloyUtilities.writeDocumentRoot(documentRoot); + + } + + public static void unsetChanged(final IMarker fromMarker) { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + final String sourceIdOfFromMarker = MarkUtilities.getSourceId(fromMarker); + final AtomType atom = + AlloyUtilities.getAtomTypeBySourceIdFromSig(documentRoot, sourceIdOfFromMarker); + atom.setChanged(null); + AlloyUtilities.writeDocumentRoot(documentRoot); + } + + public static void unsetChangedAndAllImpacted(final IMarker changedMarker) { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + final String sourceIdOfChangedMarker = MarkUtilities.getSourceId(changedMarker); + + final AtomType atom = + AlloyUtilities.getAtomTypeBySourceIdFromSig(documentRoot, sourceIdOfChangedMarker); + final ArrayList secondSideAtoms = AlloyUtilities + .getSecondSideAtomsBySourceIdOfFirstSide(documentRoot, sourceIdOfChangedMarker); + + for (final AtomType atomType : secondSideAtoms) { + if (atomType.getImpact() != null && atomType.getImpact()) { + atomType.setImpact(null); + } + } + + atom.setChanged(null); + + AlloyUtilities.writeDocumentRoot(documentRoot); + } + + public static void unsetImpactAndChanged(final IMarker fromMarker, final IMarker toMarker) { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + final String sourceIdOfFromMarker = MarkUtilities.getSourceId(fromMarker); + final String sourceIdOfToMarker = MarkUtilities.getSourceId(toMarker); + + final AtomType atom = + AlloyUtilities.getAtomTypeBySourceIdFromSig(documentRoot, sourceIdOfFromMarker); + final ArrayList secondSideAtoms = + AlloyUtilities.getSecondSideAtomsBySourceIdOfFirstSide(documentRoot, sourceIdOfFromMarker); + + int impactCount = 0; + for (final AtomType atomType : secondSideAtoms) { + if (atomType.getImpact() != null) { + impactCount++; + if (atomType.getLabel().equals(sourceIdOfToMarker)) { + atomType.setImpact(null); + } + } + } + if (impactCount == 1) { + atom.setChanged(null); + } + + AlloyUtilities.writeDocumentRoot(documentRoot); + } + + /** + * This method doesn't change the sig and relation definitions, also doesn't change actual atoms + * status. + * + * @param file + * @param content + */ + public static void updateSpec(final String file, final String content) { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + final EList sources = documentRoot.getAlloy().getSource(); + for (final SourceType sourceType : sources) { + if (sourceType.getFilename().equals(file)) { + sourceType.setContent(content); + AlloyUtilities.writeDocumentRoot(documentRoot); + return; + } + } + } + + @SuppressWarnings("unchecked") + public static void writeDocumentRoot(final DocumentRoot documentRoot) { + @SuppressWarnings("rawtypes") + final ModelIO modelIO = new ModelIO<>(); + modelIO.write(AlloyUtilities.getUri(), documentRoot); + } + + @SuppressWarnings("unchecked") + public static void writeDocumentRootForMetamodel(final DocumentRoot documentRoot, + final String filename) { + @SuppressWarnings("rawtypes") + final ModelIO modelIO = new ModelIO<>(); + modelIO.write(URI.createFileURI(AlloyUtilities.getLocationForMetamodel(filename)), + documentRoot); + } + + public static AtomType cloneAtomType(final AtomType atomType) { + final AtomType clone = persistenceFactory.eINSTANCE.createAtomType(); + clone.setBound(atomType.getBound()); + clone.setChanged(atomType.getChanged()); + clone.setImpact(atomType.getImpact()); + clone.setLabel(atomType.getLabel()); + clone.setReasoned(atomType.isReasoned()); + clone.setValue(atomType.getValue()); + return clone; + } + + public static String getSigNameByAtomId(final String atomId, final DocumentRoot documentRoot) { + for (final SigType sigType : documentRoot.getAlloy().getInstance().getSig()) { + for (final AtomType atomType : sigType.getAtom()) { + if (atomType.getLabel().equals(atomId)) { + return sigType.getLabel().substring(sigType.getLabel().indexOf("/") + 1); + } + } + } + return null; + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/internal/CreateMarkerWithType.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/internal/CreateMarkerWithType.java new file mode 100644 index 00000000..256d2b4b --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/internal/CreateMarkerWithType.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.configuration.internal; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ITreeSelection; + +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class CreateMarkerWithType { + + public static IMarker createMarker(IResource resource, ISelection selection, String type) { + IMarker marker = null; + if (selection instanceof ITextSelection) { + marker = MarkerFactory.createMarker(resource, (ITextSelection) selection); + } else if (selection instanceof ITreeSelection) { + marker = MarkerFactory.createMarker(resource, (ITreeSelection) selection); + } + + MarkUtilities.setType(marker, type); + + AlloyUtilities.addTypeToMarker(marker); + AlloyUtilities.addMarkerToRepository(marker); + + return marker; + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/internal/EcoreUtilities.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/internal/EcoreUtilities.java new file mode 100644 index 00000000..6f0e7e47 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/internal/EcoreUtilities.java @@ -0,0 +1,313 @@ +package eu.modelwriter.configuration.internal; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EClassifier; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.ecore.xmi.XMLResource; +import org.eclipse.emf.ecore.xmi.XMLSave; +import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl; + +public class EcoreUtilities { + + public static final String EOBJECT_URI = "relative_eobject_uri"; + public static final String ROOT_URI = "relative_ecore_root_uri"; + + public static XMLSave.XMLTypeInfo noTypeInfo; + + static { + EcoreUtilities.noTypeInfo = new XMLSave.XMLTypeInfo() { + + @Override + public boolean shouldSaveType(final EClass objectType, final EClass featureType, + final EStructuralFeature feature) { + return false; + } + + @Override + public boolean shouldSaveType(final EClass objectType, final EClassifier featureType, + final EStructuralFeature feature) { + return false; + } + }; + } + + /** + * Gets root EObject of given xmi file path + * + * @param xmiFileFullPath file path of xmi file + * @return root @EObject + * @throws IOException + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + public static Resource loadInstanceModel(final String xmiFileFullPath) throws IOException { + final Map options = new HashMap(); + options.put(XMLResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE); + + final ResourceSetImpl resourceSet = new ResourceSetImpl(); + resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap() + .put(Resource.Factory.Registry.DEFAULT_EXTENSION, new XMIResourceFactoryImpl()); + Resource resource = + resourceSet.getResource(URI.createPlatformResourceURI(xmiFileFullPath, true), true); + if (resource == null) { + resource = resourceSet.getResource(URI.createFileURI(xmiFileFullPath), true); + if (resource == null) { + resource = + resourceSet.getResource(URI.createPlatformPluginURI(xmiFileFullPath, true), true); + if (resource == null) { + resource = resourceSet.getResource(URI.createURI(xmiFileFullPath), true); + } + } + } + resource.load(options); + if (resource.isLoaded()) { + return resource; + } + return null; + } + + /** + * + * @param eObject possibly the package to find all @EClass's under it + * @return @List of @EClass names + */ + public static List getAllEClassNames(final EObject eObject) { + final List classes = new ArrayList<>(); + EcoreUtilities.recursiveGetEClasses(eObject, classes); + final List classNames = new ArrayList<>(); + for (final EClass eClass : classes) { + classNames.add(eClass.getName()); + } + return classNames; + } + + /** + * + * @param eObject possibly the package to find all @EClass under it + * @return @List of all @EClass + */ + public static List getAllEClass(final EObject eObject) { + final List classes = new ArrayList<>(); + EcoreUtilities.recursiveGetEClasses(eObject, classes); + return classes; + } + + private static void recursiveGetEClasses(final EObject object, final List classes) { + for (final EObject eObject : object.eContents()) { + if (eObject instanceof EClass) { + classes.add((EClass) eObject); + } else if (eObject instanceof EPackage) { + EcoreUtilities.recursiveGetEClasses(eObject, classes); + } + } + } + + /** + * + * @param @EObject object to be set + * @param name reference name + * @param newVal new value + */ + public static void eSetAttributeByName(final EObject eObject, final String name, + final Object newVal) { + for (final EAttribute eAttribute : eObject.eClass().getEAllAttributes()) { + if (eAttribute.getName().equals(name)) { + eObject.eSet(eAttribute, newVal); + break; + } + } + } + + /** + * + * @param @EObject object to be set + * @param name reference name + * @param newVal new value + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + public static void eSetReferenceByName(final EObject eObject, final String name, + final Object newVal) { + for (final EReference eReference : eObject.eClass().getEAllReferences()) { + if (eReference.getName().equals(name)) { + if (eReference.isMany()) { + ((List) eObject.eGet(eReference)).add(newVal); + } else { + eObject.eSet(eReference, newVal); + } + break; + } + } + } + + /** + * + * @param root @EObject + * @param className class name to be find + * @return + */ + public static EClass findEClass(final EObject root, final String className) { + final List allEClass = EcoreUtilities.getAllEClass(root); + return allEClass.stream().filter(c -> c.getName().equals(className)).findFirst().orElse(null); + } + + /** + * + * @param container + * @param eObject + * @return + */ + public static EReference getContainmentEReference(final EObject container, + final EObject eObject) { + for (final EReference eReference : container.eClass().getEAllReferences()) { + if ((eObject.eClass().getName().equals(eReference.getEReferenceType().getName()) + || eObject.eClass().getEAllSuperTypes().stream() + .anyMatch(s -> s.getName().equals(eReference.getEReferenceType().getName()))) + && eReference.isContainment()) { + return eReference; + } + } + return null; + } + + /** + * Puts given dynamic EObject to container + * + * @param container + * @param eObject + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + public static void putIntoContainer(final EObject container, final EObject eObject) { + final EReference eReference = EcoreUtilities.getContainmentEReference(container, eObject); + if (eReference != null) { + if (eReference.isMany()) { + ((List) container.eGet(eReference)).add(eObject); + } else { + container.eSet(eReference, eObject); + } + } + } + + public static EClass findEClass(final List allEClasses, final String className) { + return allEClasses.stream().filter(c -> c.getName().equals(className)).findFirst().orElse(null); + } + + /** + * Gets first root EObject (index = 0) of given uri + * + * @param uri + * @return root @EObject + * @throws IOException + */ + public static EObject getRootObject(final URI uri) throws IOException { + final List models = EcoreUtilities.loadMetaModel(uri); + return models == null ? null : models.get(0); + } + + /** + * Loads EMF Metamodel via given @URI + * + * @param uri Metamodel's @URI + * @return List of @EModelElement + * @throws IOException + */ + public static List loadMetaModel(final URI uri) throws IOException { + List list = null; + try { + final ModelIO modelIO = new ModelIO<>(); + list = modelIO.read(uri); + } catch (final Exception e) { + return null; + } + return list; + } + + /** + * Gets first root EObject (index = 0) of any given path + * + * @param anyPath + * @return root @EObject + * @throws IOException + */ + public static EObject getRootObject(final String anyPath) throws IOException { + final List elems = EcoreUtilities.loadMetaModel(anyPath); + return elems != null ? elems.get(0) : null; + } + + /** + * Loads EMF Metamodel via given path + * + * @param anyPath + * @return root @EObject + * @throws IOException + */ + public static List loadMetaModel(final String anyPath) throws IOException { + List elems = + EcoreUtilities.loadMetaModel(URI.createPlatformResourceURI(anyPath, true)); + if (elems == null) { + elems = EcoreUtilities.loadMetaModel(URI.createFileURI(anyPath)); + if (elems == null) { + elems = EcoreUtilities.loadMetaModel(URI.createPlatformPluginURI(anyPath, true)); + if (elems == null) { + elems = EcoreUtilities.loadMetaModel(URI.createURI(anyPath)); + } + } + } + return elems; + } + + /** + * Saves given @EObject to its resource. + * + * @param root @EObject + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + public static void saveResource(final EObject root) { + final Map options = new HashMap(); + options.put(XMLResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE); + // options.put(XMLResource.OPTION_SAVE_TYPE_INFORMATION, noTypeInfo); + + try { + root.eResource().save(options); + } catch (final IOException e) { + e.printStackTrace(); + } + } + + public static void saveResource(final EObject root, final URI uri) { + final List roots = new ArrayList<>(); + roots.add(root); + EcoreUtilities.saveResources(roots, uri); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + public static void saveResources(final List root, final URI uri) { + final ResourceSet resourceSet = new ResourceSetImpl(); + resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap() + .put(Resource.Factory.Registry.DEFAULT_EXTENSION, new XMLResourceFactoryImpl()); + final Resource resource = resourceSet.createResource(uri); + resource.getContents().addAll(root); + + final Map options = new HashMap(); + options.put(XMLResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE); + try { + resource.save(options); + } catch (final IOException e) { + e.printStackTrace(); + } + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/internal/ModelIO.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/internal/ModelIO.java new file mode 100644 index 00000000..d55d70db --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/internal/ModelIO.java @@ -0,0 +1,82 @@ +package eu.modelwriter.configuration.internal; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl; + +public class ModelIO { + private ResourceSet resourceSet; + + public ResourceSet getResourceSet() { + if (this.resourceSet == null) { + this.resourceSet = new ResourceSetImpl(); + this.resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap() + .put(Resource.Factory.Registry.DEFAULT_EXTENSION, new EcoreResourceFactoryImpl()); + this.registerPackages(this.resourceSet.getPackageRegistry()); + } + + return this.resourceSet; + } + + @SuppressWarnings("unchecked") + public List read(final URI uri) throws IOException { + final Resource res = this.getResourceSet().createResource(uri); + + try { + res.load(null); + } catch (final IOException e) { + throw new IOException(); + } + final EList contents = res.getContents(); + + final List list = new ArrayList(); + for (final EObject content : contents) { + + try { + list.add((T) content); + } catch (final Exception e) { + throw new RuntimeException("Unexpected resource type."); + } + } + + return list; + } + + /** + * ResourceSet'e paket kayit eder. + * + *
+ *
+ * Ornegin;
+ * packageRegistry.put(ContentPackage.eNS_URI, ContentPackage.eINSTANCE);
+ *
+ * Kendi modellerinizi kullanacaksaniz bu methodu gerceklestiriniz ve kendi paket arayuzunuzu + * kayit ediniz. EMF metamodelleri kullanacaksaniz varsayilan gerceklestirim yeterlidir. + * + * @param packageRegistry ResourceSet'a ait paket kayitcisi. + */ + protected void registerPackages(final EPackage.Registry packageRegistry) {} + + public void write(final URI uri, final T obj) { + final Resource resource = this.getResourceSet().createResource(uri); + + resource.getContents().add(obj); + + final HashMap options = new HashMap<>(); + try { + resource.save(options); + } catch (final IOException e) { + e.printStackTrace(); + } + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/internal/Utilities.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/internal/Utilities.java new file mode 100644 index 00000000..90559fcf --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/internal/Utilities.java @@ -0,0 +1,166 @@ +package eu.modelwriter.configuration.internal; + +import java.io.BufferedWriter; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.util.Scanner; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.widgets.Display; + +import eu.modelwriter.configuration.Activator; + +public class Utilities { + + public static final String FILE_SEPERATOR = System.getProperty("file.separator"); + + public static boolean appendToFile(final String filePath, final String textToAppend) { + try (FileWriter fw = new FileWriter(filePath, true)) { + fw.write(textToAppend); + fw.close(); + return true; + } catch (final Exception e) { + return false; + } + } + + public static boolean copyFileContent(final String sourcePath, final String targetPath) { + FileInputStream fr = null; + FileOutputStream fw = null; + try { + fr = new FileInputStream(sourcePath); + fw = new FileOutputStream(targetPath); + final FileChannel src = fr.getChannel(); + final FileChannel dest = fw.getChannel(); + dest.transferFrom(src, 0, src.size()); + return true; + } catch (final Exception e) { + return false; + } finally { + try { + fr.close(); + fw.close(); + } catch (final Exception e) { + return false; + } + } + } + + public static void writeToFile(final String fileName, final StringBuilder builder) { + try (BufferedWriter bw = new BufferedWriter(new FileWriter(fileName))) { + final int aLength = builder.length(); + final int aChunk = 1024;// 1 kb buffer to read data from + final char[] aChars = new char[aChunk]; + + for (int aPosStart = 0; aPosStart < aLength; aPosStart += aChunk) { + final int aPosEnd = Math.min(aPosStart + aChunk, aLength); + builder.getChars(aPosStart, aPosEnd, aChars, 0); // Create no new buffer + bw.write(aChars, 0, aPosEnd - aPosStart);// This is faster than just copying one byte at the + // time + } + bw.flush(); + } catch (final IOException e) { + e.printStackTrace(); + } + } + + public static IFile getIFileFromPath(final String path) { + final Path filePath = new Path(path); + // for absolute paths + IFile iFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(filePath); + // might be relative path? + if (iFile == null) { + iFile = ResourcesPlugin.getWorkspace().getRoot().getFile(filePath); + } + return iFile; + } + + /** + * Skips comment lines + * + * @param scanner + * @return comment free line + */ + public static String getNextLine(final Scanner scanner) { + while (scanner.hasNextLine()) { + String line = scanner.nextLine().trim(); + if (line.startsWith("//")) { + continue; // Its single comment line, skip + } + + if (line.startsWith("/*")) { // multi line comment + String skipLine = line; + while (scanner.hasNextLine() && !skipLine.contains("*/")) { // skip until close tag + skipLine = scanner.nextLine(); + } + // in case there is data after comment close tag + line = skipLine.substring(skipLine.indexOf("*/") + 2); + if (line.isEmpty()) { + continue; + } + } + return line; + } + return ""; + } + + /** + * Displays a message dialog on ui thread. (async) + * + * @param title dialog's title + * @param message dialog's message + * @param type dialog's type image constant, see @MessageDialog + */ + public static void showOKDialog(final int type, final String title, final String message) { + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + final MessageDialog warningdialog = new MessageDialog(Activator.getShell(), title, null, + message, type, new String[] {"OK"}, 0); + warningdialog.open(); + } + }); + } + + private final static String whitespace_chars = "" /* dummy empty string for homogeneity */ + + "\\u0009" // CHARACTER TABULATION + + "\\u000A" // LINE FEED (LF) + + "\\u000B" // LINE TABULATION + + "\\u000C" // FORM FEED (FF) + + "\\u000D" // CARRIAGE RETURN (CR) + + "\\u0020" // SPACE + + "\\u0085" // NEXT LINE (NEL) + + "\\u00A0" // NO-BREAK SPACE + + "\\u1680" // OGHAM SPACE MARK + + "\\u180E" // MONGOLIAN VOWEL SEPARATOR + + "\\u2000" // EN QUAD + + "\\u2001" // EM QUAD + + "\\u2002" // EN SPACE + + "\\u2003" // EM SPACE + + "\\u2004" // THREE-PER-EM SPACE + + "\\u2005" // FOUR-PER-EM SPACE + + "\\u2006" // SIX-PER-EM SPACE + + "\\u2007" // FIGURE SPACE + + "\\u2008" // PUNCTUATION SPACE + + "\\u2009" // THIN SPACE + + "\\u200A" // HAIR SPACE + + "\\u2028" // LINE SEPARATOR + + "\\u2029" // PARAGRAPH SEPARATOR + + "\\u202F" // NARROW NO-BREAK SPACE + + "\\u205F" // MEDIUM MATHEMATICAL SPACE + + "\\u3000" // IDEOGRAPHIC SPACE + ; + /* A \s that actually works for Java’s native character set: Unicode */ + private final static String whitespace_charclass = "[" + Utilities.whitespace_chars + "]"; + + public static String removeAllWhiteSpaces(final String str) { + return str.replaceAll(Utilities.whitespace_charclass, ""); + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/specificreasoning/AlloyOtherSolutionReasoningForAtom.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/specificreasoning/AlloyOtherSolutionReasoningForAtom.java new file mode 100644 index 00000000..799bec81 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/specificreasoning/AlloyOtherSolutionReasoningForAtom.java @@ -0,0 +1,331 @@ +package eu.modelwriter.configuration.specificreasoning; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.swing.JOptionPane; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.URI; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.traceability.core.persistence.AtomType; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; +import eu.modelwriter.traceability.core.persistence.FieldType; +import eu.modelwriter.traceability.core.persistence.TupleType; +import eu.modelwriter.traceability.core.persistence.persistenceFactory; +import eu.modelwriter.traceability.core.persistence.internal.ModelIO; + +public class AlloyOtherSolutionReasoningForAtom { + + private static Map> reasonRelations; + private static AlloyOtherSolutionReasoningForAtom instance; + private Map> oldReasons; + String xmlFileLoc = InstanceTranslatorReasoningForAtom.baseFileDirectory + "reasoningForAtom.xml"; + private String atomName; + private static List solutions; + private int currentSolutionIndex; + + public static AlloyOtherSolutionReasoningForAtom getInstance() { + if (AlloyOtherSolutionReasoningForAtom.instance == null) { + AlloyOtherSolutionReasoningForAtom.instance = new AlloyOtherSolutionReasoningForAtom(); + AlloyOtherSolutionReasoningForAtom.instance.oldReasons = new HashMap<>(); + AlloyOtherSolutionReasoningForAtom.solutions = new ArrayList<>(); + AlloyOtherSolutionReasoningForAtom.reasonRelations = new HashMap<>(); + } + + return AlloyOtherSolutionReasoningForAtom.instance; + } + + public boolean next() throws Err { + A4Solution ans; + if (AlloyOtherSolutionReasoningForAtom.solutions.size() <= currentSolutionIndex + 1) { + ans = AlloyOtherSolutionReasoningForAtom.solutions.get(currentSolutionIndex).next(); + if (ans.equals(AlloyOtherSolutionReasoningForAtom.solutions.get(currentSolutionIndex))) { + return false; + } + AlloyOtherSolutionReasoningForAtom.solutions.add(ans); + currentSolutionIndex++; + } else { + ans = AlloyOtherSolutionReasoningForAtom.solutions.get(currentSolutionIndex + 1); + currentSolutionIndex++; + } + + if (AlloyOtherSolutionReasoningForAtom.reasonRelations.isEmpty()) { + return false; + } + + if (ans.satisfiable()) { + ans.writeXML(xmlFileLoc); + if (!parse()) { + return false; + } + } else { + return false; + } + + removeOldReasoning(); + return reasoning(); + } + + public boolean previous() throws Err { + A4Solution ans; + if (currentSolutionIndex - 1 < 0) { + return false; + } else { + ans = AlloyOtherSolutionReasoningForAtom.solutions.get(currentSolutionIndex - 1); + currentSolutionIndex--; + } + + if (AlloyOtherSolutionReasoningForAtom.reasonRelations.isEmpty()) { + return false; + } + + if (ans.satisfiable()) { + ans.writeXML(xmlFileLoc); + if (!parse()) { + return false; + } + } else { + return false; + } + + removeOldReasoning(); + return reasoning(); + } + + private boolean parse() { + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder; + try { + builder = factory.newDocumentBuilder(); + final File file = new File(xmlFileLoc); + final Document document = builder.parse(file); + final Node instance = document.getElementsByTagName("instance").item(0); + instance.getAttributes().removeNamedItem("command"); + + Transformer transformer; + try { + transformer = TransformerFactory.newInstance().newTransformer(); + final DOMSource source = new DOMSource(document); + final StreamResult result = new StreamResult(file); + transformer.transform(source, result); + } catch (final Exception e) { + } + + return true; + } catch (ParserConfigurationException | SAXException | IOException e) { + e.printStackTrace(); + } + return false; + } + + private void removeOldReasoning() { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + + final Iterator>> iterator = oldReasons.entrySet().iterator(); + final EList fieldTypes = documentRoot.getAlloy().getInstance().getField(); + while (iterator.hasNext()) { + final Entry> entry = iterator.next(); + for (final FieldType fieldType : fieldTypes) { + if (fieldType.getID() == entry.getKey()) { + for (final TupleType oldTupleType : entry.getValue()) { + final Iterator tupleIter = fieldType.getTuple().iterator(); + final AtomType oldAtomType0 = oldTupleType.getAtom().get(0); + final AtomType oldAtomType1 = oldTupleType.getAtom().get(1); + while (tupleIter.hasNext()) { + final TupleType tupleType = tupleIter.next(); + if (tupleType.isReasoned()) { + final AtomType atomType0 = tupleType.getAtom().get(0); + final AtomType atomType1 = tupleType.getAtom().get(1); + if (oldAtomType0.getLabel().equals(atomType0.getLabel()) + && oldAtomType1.getLabel().equals(atomType1.getLabel())) { + tupleIter.remove(); + } + } + } + } + } + } + } + + AlloyUtilities.writeDocumentRoot(documentRoot); + + oldReasons.clear(); + } + + public void finish() { + AlloyOtherSolutionReasoningForAtom.solutions.clear(); + } + + public DocumentRoot getDocumentRoot() { + @SuppressWarnings("rawtypes") + final ModelIO modelIO = new ModelIO<>(); + @SuppressWarnings("rawtypes") + List list = null; + try { + list = modelIO.read(URI.createFileURI(xmlFileLoc)); + } catch (final IOException e) { + return null; + } + if (list == null || list.isEmpty()) { + return null; + } + final DocumentRoot documentRoot = (DocumentRoot) list.get(0); + return documentRoot; + } + + public A4Solution getAns() { + return AlloyOtherSolutionReasoningForAtom.solutions.get(currentSolutionIndex); + } + + public Map> getOldReasons() { + return oldReasons; + } + + public void setReasonRelations(final Map> reasonRelations) { + AlloyOtherSolutionReasoningForAtom.reasonRelations = reasonRelations; + } + + private boolean reasoning() { + final DocumentRoot documentRootReasoning = getDocumentRoot(); + final DocumentRoot documentRootOriginal = AlloyUtilities.getDocumentRoot(); + if (documentRootReasoning == null) { + return false; + } + + reason(documentRootOriginal, documentRootReasoning, atomName); + + return true; + } + + private void reason(final DocumentRoot documentRootOriginal, + final DocumentRoot documentRootReasoning, final String atomName) { + int discoveredRelationCount = 0; + for (final FieldType fieldType_R : documentRootReasoning.getAlloy().getInstance().getField()) { + for (final FieldType fieldType_O : documentRootOriginal.getAlloy().getInstance().getField()) { + if (!fieldType_R.getLabel().equals(fieldType_O.getLabel())) { + continue; + } + + final int sourceId_R = fieldType_R.getParentID(); + final String sourceSigName_R = + AlloyUtilities.getSigNameById(sourceId_R, documentRootReasoning); + if (!AlloyOtherSolutionReasoningForAtom.reasonRelations.containsKey(sourceSigName_R) + || !AlloyOtherSolutionReasoningForAtom.reasonRelations.get(sourceSigName_R).contains(fieldType_R.getLabel())) { + continue; + } + + final int sourceId_O = fieldType_O.getParentID(); + final String sourceSigName_O = + AlloyUtilities.getSigNameById(sourceId_O, documentRootOriginal); + if (!AlloyOtherSolutionReasoningForAtom.reasonRelations.containsKey(sourceSigName_O) + || !AlloyOtherSolutionReasoningForAtom.reasonRelations.get(sourceSigName_O).contains(fieldType_O.getLabel())) { + continue; + } + + if (!sourceSigName_O.equals(sourceSigName_R)) { + continue; + } + + if (fieldType_O.getTuple().size() == fieldType_R.getTuple().size()) { + continue; + } + + for (final TupleType tuple_R : fieldType_R.getTuple()) { + AtomType atomType0_R = getOriginalAtomType(tuple_R.getAtom().get(0).getLabel()); + final AtomType atomType1_R = getOriginalAtomType(tuple_R.getAtom().get(1).getLabel()); + + if (atomType0_R == null || atomType1_R == null) { + continue; + } + + boolean exists = false; + for (final TupleType tuple_O : fieldType_O.getTuple()) { + if (atomType0_R.getLabel().equals(tuple_O.getAtom().get(0).getLabel()) + && atomType1_R.getLabel().equals(tuple_O.getAtom().get(1).getLabel())) { + exists = true; + break; + } + } + + if (!exists || fieldType_O.getTuple().size() == 0) { + final TupleType tupleType = persistenceFactory.eINSTANCE.createTupleType(); + if (atomType0_R.equals(atomType1_R)) { + atomType0_R = AlloyUtilities.cloneAtomType(atomType0_R); + } + tupleType.getAtom().add(atomType0_R); + tupleType.getAtom().add(atomType1_R); + tupleType.setReasoned(true); + + if (!AlloyUtilities.getAtomNameById(atomType0_R.getLabel()).replace("$", "") + .equals(atomName) + && !AlloyUtilities.getAtomNameById(atomType1_R.getLabel()).replace("$", "") + .equals(atomName)) { + continue; + } + + if (AlloyOtherSolutionReasoningForAtom.getInstance().getOldReasons() + .get(fieldType_O.getID()) == null) { + AlloyOtherSolutionReasoningForAtom.getInstance().getOldReasons() + .put(fieldType_O.getID(), new ArrayList<>(Arrays.asList(tupleType))); + } else { + AlloyOtherSolutionReasoningForAtom.getInstance().getOldReasons() + .get(fieldType_O.getID()).add(tupleType); + } + + discoveredRelationCount++; + fieldType_O.getTuple().add(tupleType); + } + } + } + } + + AlloyUtilities.writeDocumentRoot(documentRootOriginal); + + JOptionPane.showMessageDialog(null, + "Discovering on relations successfully completed.\nDiscovered relation count: " + + discoveredRelationCount, + "Discovering on Relations", JOptionPane.WARNING_MESSAGE); + } + + private AtomType getOriginalAtomType(final String name_R) { + if (name_R.contains("/")) { + return null; + } + final String name = name_R.substring(0, name_R.lastIndexOf("_")); + final int id = + Integer.parseInt(name_R.substring(name_R.lastIndexOf("_") + 1, name_R.lastIndexOf("$"))); + + return AlloyUtilities.getSigTypeById(AlloyUtilities.getSigTypeIdByName(name)).getAtom().get(id); + } + + public void setAtomName(final String atomName) { + this.atomName = atomName; + } + + public void setFirstAns(final A4Solution ans) { + AlloyOtherSolutionReasoningForAtom.solutions.clear(); + AlloyOtherSolutionReasoningForAtom.solutions.add(ans); + currentSolutionIndex = 0; + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/specificreasoning/AlloyParserForReasoningForAtom.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/specificreasoning/AlloyParserForReasoningForAtom.java new file mode 100644 index 00000000..3780b07d --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/specificreasoning/AlloyParserForReasoningForAtom.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.configuration.specificreasoning; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.eclipse.emf.common.util.URI; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; +import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Options; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.TranslateAlloyToKodkod; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; +import eu.modelwriter.traceability.core.persistence.internal.ModelIO; + +public class AlloyParserForReasoningForAtom { + + private final String filename; + String xmlFileLoc = InstanceTranslatorReasoningForAtom.baseFileDirectory + "reasoningForAtom.xml"; + + public AlloyParserForReasoningForAtom(final String filename) { + this.filename = filename; + } + + public DocumentRoot getDocumentRoot() { + @SuppressWarnings("rawtypes") + final ModelIO modelIO = new ModelIO<>(); + @SuppressWarnings("rawtypes") + List list = null; + try { + list = modelIO.read(URI.createFileURI(xmlFileLoc)); + } catch (final IOException e) { + return null; + } + if (list == null || list.isEmpty()) { + return null; + } + final DocumentRoot documentRoot = (DocumentRoot) list.get(0); + return documentRoot; + } + + public DocumentRoot parse() { + Module world; + A4Solution ans = null; + try { + final A4Reporter rep = new A4Reporter() { + @Override + public void warning(final ErrorWarning msg) { + System.out.print("Relevance Warning:\n" + msg.toString().trim() + "\n\n"); + System.out.flush(); + } + }; + + world = CompUtil.parseEverything_fromFile(rep, null, filename); + + final A4Options options = new A4Options(); + options.solver = A4Options.SatSolver.SAT4J; + + for (final Command command : world.getAllCommands()) { + + ans = TranslateAlloyToKodkod.execute_command(rep, world.getAllReachableSigs(), command, + options); + + if (ans.satisfiable()) { + AlloyOtherSolutionReasoningForAtom.getInstance().setFirstAns(ans); + + ans.writeXML(xmlFileLoc); + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder; + try { + builder = factory.newDocumentBuilder(); + final File file = new File(xmlFileLoc); + final Document document = builder.parse(file); + final Node instance = document.getElementsByTagName("instance").item(0); + instance.getAttributes().removeNamedItem("command"); + + Transformer transformer; + try { + transformer = TransformerFactory.newInstance().newTransformer(); + final DOMSource source = new DOMSource(document); + final StreamResult result = new StreamResult(file); + transformer.transform(source, result); + } catch (final Exception e) { + } + + } catch (ParserConfigurationException | SAXException | IOException e) { + e.printStackTrace(); + } + + break; + } + } + + } catch (final Err e) { + e.printStackTrace(); + } + + final DocumentRoot documentRoot = getDocumentRoot(); + + return documentRoot; + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/specificreasoning/AlloyReasoningForAtom.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/specificreasoning/AlloyReasoningForAtom.java new file mode 100644 index 00000000..761e00bd --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/specificreasoning/AlloyReasoningForAtom.java @@ -0,0 +1,159 @@ +package eu.modelwriter.configuration.specificreasoning; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import javax.swing.JOptionPane; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.traceability.core.persistence.AtomType; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; +import eu.modelwriter.traceability.core.persistence.FieldType; +import eu.modelwriter.traceability.core.persistence.TupleType; +import eu.modelwriter.traceability.core.persistence.persistenceFactory; + +public class AlloyReasoningForAtom { + + private final String alsPath = + InstanceTranslatorReasoningForAtom.baseFileDirectory + "reasoningForAtom.als"; + + private final String xmlPath = + InstanceTranslatorReasoningForAtom.baseFileDirectory + "reasoningForAtom.xml"; + + public boolean reasoning(final String atomName, final String atomType) { + final File reasoningForAtomXml = new File(xmlPath); + if (reasoningForAtomXml.exists()) { + reasoningForAtomXml.delete(); + } + final File reasoningForAtomAls = new File(alsPath); + if (reasoningForAtomAls.exists()) { + reasoningForAtomAls.delete(); + } + + if (!AlloyValidatorReasoningForAtom.validate(atomType)) { + return false; + } + + final AlloyParserForReasoningForAtom parser = new AlloyParserForReasoningForAtom(alsPath); + + AlloyOtherSolutionReasoningForAtom.getInstance() + .setReasonRelations(AlloyValidatorReasoningForAtom.reasonRelations); + AlloyOtherSolutionReasoningForAtom.getInstance().setAtomName(atomName); + + final DocumentRoot documentRootReasoning = parser.parse(); + final DocumentRoot documentRootOriginal = AlloyUtilities.getDocumentRoot(); + if (documentRootReasoning == null) { + return false; + } + + reason(documentRootOriginal, documentRootReasoning, atomName); + + return true; + } + + private void reason(final DocumentRoot documentRootOriginal, + final DocumentRoot documentRootReasoning, final String atomName) { + final Map> reasonRelations = + AlloyValidatorReasoningForAtom.reasonRelations; + int discoveredRelationCount = 0; + for (final FieldType fieldType_R : documentRootReasoning.getAlloy().getInstance().getField()) { + for (final FieldType fieldType_O : documentRootOriginal.getAlloy().getInstance().getField()) { + if (!fieldType_R.getLabel().equals(fieldType_O.getLabel())) { + continue; + } + + final int sourceId_R = fieldType_R.getParentID(); + final String sourceSigName_R = + AlloyUtilities.getSigNameById(sourceId_R, documentRootReasoning); + if (!reasonRelations.containsKey(sourceSigName_R) + || !reasonRelations.get(sourceSigName_R).contains(fieldType_R.getLabel())) { + continue; + } + + final int sourceId_O = fieldType_O.getParentID(); + final String sourceSigName_O = + AlloyUtilities.getSigNameById(sourceId_O, documentRootOriginal); + if (!reasonRelations.containsKey(sourceSigName_O) + || !reasonRelations.get(sourceSigName_O).contains(fieldType_O.getLabel())) { + continue; + } + + if (!sourceSigName_O.equals(sourceSigName_R)) { + continue; + } + + if (fieldType_O.getTuple().size() == fieldType_R.getTuple().size()) { + continue; + } + + for (final TupleType tuple_R : fieldType_R.getTuple()) { + AtomType atomType0_R = getOriginalAtomType(tuple_R.getAtom().get(0).getLabel()); + final AtomType atomType1_R = getOriginalAtomType(tuple_R.getAtom().get(1).getLabel()); + + if (atomType0_R == null || atomType1_R == null) { + continue; + } + + boolean exists = false; + for (final TupleType tuple_O : fieldType_O.getTuple()) { + if (atomType0_R.getLabel().equals(tuple_O.getAtom().get(0).getLabel()) + && atomType1_R.getLabel().equals(tuple_O.getAtom().get(1).getLabel())) { + exists = true; + break; + } + } + + if (!exists || fieldType_O.getTuple().size() == 0) { + final TupleType tupleType = persistenceFactory.eINSTANCE.createTupleType(); + if (atomType0_R.equals(atomType1_R)) { + atomType0_R = AlloyUtilities.cloneAtomType(atomType0_R); + } + tupleType.getAtom().add(atomType0_R); + tupleType.getAtom().add(atomType1_R); + tupleType.setReasoned(true); + + if (!AlloyUtilities.getAtomNameById(atomType0_R.getLabel()).replace("$", "") + .equals(atomName) + && !AlloyUtilities.getAtomNameById(atomType1_R.getLabel()).replace("$", "") + .equals(atomName)) { + continue; + } + + if (AlloyOtherSolutionReasoningForAtom.getInstance().getOldReasons() + .get(fieldType_O.getID()) == null) { + AlloyOtherSolutionReasoningForAtom.getInstance().getOldReasons() + .put(fieldType_O.getID(), new ArrayList<>(Arrays.asList(tupleType))); + } else { + AlloyOtherSolutionReasoningForAtom.getInstance().getOldReasons() + .get(fieldType_O.getID()).add(tupleType); + } + + discoveredRelationCount++; + fieldType_O.getTuple().add(tupleType); + } + } + } + } + + AlloyUtilities.writeDocumentRoot(documentRootOriginal); + + JOptionPane.showMessageDialog(null, + "Discovering on relations successfully completed.\nDiscovered relation count: " + + discoveredRelationCount, + "Discovering on Relations", JOptionPane.WARNING_MESSAGE); + } + + private AtomType getOriginalAtomType(final String name_R) { + if (name_R.contains("/")) { + return null; + } + final String name = name_R.substring(0, name_R.lastIndexOf("_")); + final int id = + Integer.parseInt(name_R.substring(name_R.lastIndexOf("_") + 1, name_R.lastIndexOf("$"))); + + return AlloyUtilities.getSigTypeById(AlloyUtilities.getSigTypeIdByName(name)).getAtom().get(id); + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/specificreasoning/AlloyValidatorReasoningForAtom.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/specificreasoning/AlloyValidatorReasoningForAtom.java new file mode 100644 index 00000000..8d150e34 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/specificreasoning/AlloyValidatorReasoningForAtom.java @@ -0,0 +1,60 @@ +package eu.modelwriter.configuration.specificreasoning; + +import java.util.List; +import java.util.Map; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.ast.Module; +import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Options; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import edu.mit.csail.sdg.alloy4compiler.translator.TranslateAlloyToKodkod; + +public class AlloyValidatorReasoningForAtom { + public static Map> reasonRelations; + + public static boolean validate(final String atomType) { + final InstanceTranslatorReasoningForAtom instanceTranslator = + new InstanceTranslatorReasoningForAtom(atomType); + instanceTranslator.translate(); + AlloyValidatorReasoningForAtom.reasonRelations = instanceTranslator.getReasonRelations(); + + final String filename = instanceTranslator.getBaseFileDirectory() + "reasoningForAtom.als"; + + try { + final A4Reporter rep = new A4Reporter() { + @Override + public void warning(final ErrorWarning msg) { + System.out.print("Relevance Warning:\n" + msg.toString().trim() + "\n\n"); + System.out.flush(); + } + }; + Module world = null; + + world = CompUtil.parseEverything_fromFile(rep, null, filename); + + final A4Options options = new A4Options(); + options.solver = A4Options.SatSolver.SAT4J; + + for (final Command command : world.getAllCommands()) { + A4Solution ans = null; + ans = TranslateAlloyToKodkod.execute_command(rep, world.getAllReachableSigs(), command, + options); + + if (ans.satisfiable()) { + return true; + } + } + + } catch (final Err e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return false; + } + +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/specificreasoning/InstanceTranslatorReasoningForAtom.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/specificreasoning/InstanceTranslatorReasoningForAtom.java new file mode 100644 index 00000000..5c5262b0 --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/specificreasoning/InstanceTranslatorReasoningForAtom.java @@ -0,0 +1,291 @@ +package eu.modelwriter.configuration.specificreasoning; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.emf.common.util.EList; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.traceability.core.persistence.AlloyType; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; +import eu.modelwriter.traceability.core.persistence.FieldType; +import eu.modelwriter.traceability.core.persistence.SigType; +import eu.modelwriter.traceability.core.persistence.SourceType; +import eu.modelwriter.traceability.core.persistence.TupleType; +import eu.modelwriter.traceability.core.persistence.TypeType; +import eu.modelwriter.traceability.core.persistence.TypesType; + +public class InstanceTranslatorReasoningForAtom { + + // public static void main(final String[] args) { + // final String txt = "--Reason@contents.ad"; + // + // final String re1 = "(-)"; // Any Single Character 1 + // final String re2 = "(-)"; // Any Single Character 2 + // final String re3 = "(\\s*)"; // White Space 1 + // final String re4 = "(Reason|reason)"; // Word 1 + // final String re5 = "(@)"; // Any Single Character 3 + // final String re6 = "((?:[a-z0-9_]+))"; // Word 2 + // final String re7 = "(\\.)"; + // final String re8 = "((?:[a-z0-9_]+))"; // Word 2 + // final String re9 = "(\\s*)"; // White Space 2 + // + // final Pattern p = Pattern.compile(re1 + re2 + re3 + re4 + re5 + re6 + re7 + // + re8 + re9, + // Pattern.CASE_INSENSITIVE | Pattern.DOTALL); + // final Matcher m = p.matcher(txt); + // if (m.find()) { + // final String c1 = m.group(1); + // final String c2 = m.group(2); + // final String ws1 = m.group(3); + // final String word1 = m.group(4); + // final String c3 = m.group(5); + // final String word2 = m.group(6); + // final String dot1 = m.group(7); + // final String word3 = m.group(8); + // final String ws2 = m.group(9); + // System.out.print("(" + c1.toString() + ")" + "(" + c2.toString() + ")" + + // "(" + ws1.toString() + // + ")" + "(" + word1.toString() + ")" + "(" + c3.toString() + ")" + "(" + + // word2.toString() + // + ")" + "(" + dot1.toString() + ")" + "(" + word3.toString() + ")" + "(" + // + ws2.toString() + // + ")" + "\n"); + // } + // } + + public static String baseFileDirectory = ResourcesPlugin.getWorkspace().getRoot().getLocation() + + " .modelwriter reasoningForAtom ".replace(" ", System.getProperty("file.separator")); + + private final StringBuilder builder; + + final Map> reasonRelations = new HashMap<>(); + + private final Map sig2oldValue = new HashMap<>(); + + private final String atomType; + + public InstanceTranslatorReasoningForAtom(final String atomType) { + this.atomType = atomType; + builder = new StringBuilder(); + } + + private void createFactPart(final DocumentRoot documentRoot, final List fields) { + builder.append("fact {\n"); + + final Map> discoverFields = new HashMap<>(); + final Map> allParents = new HashMap<>(); + + final String sigName = atomType; + allParents.put(sigName, new ArrayList<>()); + final int id = AlloyUtilities.getSigTypeIdByName(sigName); + final ArrayList allParentIds = AlloyUtilities.getAllParentIds(id); + for (final Integer parentId : allParentIds) { + final String parentName = AlloyUtilities.getSigNameById(parentId); + allParents.get(sigName).add(parentName); + } + + for (final FieldType fieldType : fields) { + for (final TypesType typesType : fieldType.getTypes()) { + for (final TypeType typeType : typesType.getType()) { + String label = AlloyUtilities.getSigTypeById(typeType.getID()).getLabel(); + label = label.substring(label.lastIndexOf("/") + 1); + if (label.equals(sigName) || allParents.get(sigName).contains(label)) { + if (discoverFields.containsKey(sigName)) { + discoverFields.get(sigName).add(fieldType.getLabel()); + } else { + discoverFields.put(sigName, new ArrayList<>(Arrays.asList(fieldType.getLabel()))); + } + break; + } + } + } + } + + for (final FieldType fieldType : fields) { + for (final TypesType typesType : fieldType.getTypes()) { + String sourceLabel = + AlloyUtilities.getSigTypeById(typesType.getType().get(0).getID()).getLabel(); + sourceLabel = sourceLabel.substring(sourceLabel.lastIndexOf("/") + 1); + String targetLabel = + AlloyUtilities.getSigTypeById(typesType.getType().get(1).getID()).getLabel(); + targetLabel = targetLabel.substring(targetLabel.lastIndexOf("/") + 1); + + if (sourceLabel.equals(sigName) || allParents.get(sigName).contains(sourceLabel) + || targetLabel.equals(sigName) || allParents.get(sigName).contains(targetLabel)) { + if (reasonRelations.containsKey(sourceLabel)) { + reasonRelations.get(sourceLabel).add(fieldType.getLabel()); + } else { + reasonRelations.put(sourceLabel, new ArrayList<>(Arrays.asList(fieldType.getLabel()))); + } + } + } + } + + for (final FieldType fieldType : fields) { + final String fieldName = fieldType.getLabel(); + + final List allSources = new ArrayList<>(); + final List allTargets = new ArrayList<>(); + for (final TypesType typesType : fieldType.getTypes()) { + final EList typeType = typesType.getType(); + allSources.addAll(AlloyUtilities.getAllChildNames(typeType.get(0).getID())); + allTargets.addAll(AlloyUtilities.getAllChildNames(typeType.get(1).getID())); + } + + boolean accept = false; + for (final Entry> entry : discoverFields.entrySet()) { + final String discoverSig = entry.getKey(); + final List discoverFieldsOfSig = entry.getValue(); + if (discoverFieldsOfSig.contains(fieldName) + && (allSources.contains(discoverSig) || allTargets.contains(discoverSig))) { + accept = true; + break; + } + } + + String parentSigName = AlloyUtilities.getSigTypeById(fieldType.getParentID()).getLabel(); + parentSigName = parentSigName.substring(parentSigName.lastIndexOf("/") + 1); + + final EList tuples = fieldType.getTuple(); + for (int i = 0; i < tuples.size(); i++) { + + final String sigName1 = AlloyUtilities + .getAtomNameById(tuples.get(i).getAtom().get(0).getLabel()).replace("$", "_"); + final String sigName2 = AlloyUtilities + .getAtomNameById(tuples.get(i).getAtom().get(1).getLabel()).replace("$", "_"); + + builder.append(sigName1 + "->" + sigName2); + + if (i + 1 != tuples.size()) { + builder.append(" +\n"); + } else if (accept) { + builder.append(" in " + parentSigName + "<:" + fieldName + "\n"); + } else { + builder.append(" = " + parentSigName + "<:" + fieldName + "\n"); + } + } + + final List allRelations = new ArrayList<>(); + for (final List value : discoverFields.values()) { + allRelations.addAll(value); + } + + if (fieldType.getTuple().size() == 0 && !accept) { + builder.append(parentSigName + "." + fieldName + " = none\n"); + } + } + + builder.append("}\n"); + } + + private File createFile(final String filePath) { + File file = null; + try { + file = new File(filePath); + + if (!file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + // if file doesn't exists, then create it + if (!file.exists()) { + file.createNewFile(); + } + } catch (final IOException e) { + e.printStackTrace(); + } + return file; + } + + private void createSigPart(final List sigs) { + for (final SigType sig : sigs) { + final String sigName = sig.getLabel().substring(sig.getLabel().lastIndexOf("/") + 1); + for (int i = 0; i < sig.getAtom().size(); i++) { + builder.append("one sig " + sigName + "_" + i + " extends " + sigName + "{ } \n"); + } + } + } + + private void createSourceFiles(final EList sources) { + boolean isFirst = false; + for (final SourceType source : sources) { + final String sourceFilePath = source.getFilename(); + final String fileName = sourceFilePath.substring( + sourceFilePath.lastIndexOf(System.getProperty("file.separator")) + 1, + sourceFilePath.lastIndexOf(".")); + if (!isFirst) { + builder.append("open " + fileName + "\n"); + isFirst = true; + } + final String newFilePath = + InstanceTranslatorReasoningForAtom.baseFileDirectory + fileName + ".als"; + + final String content = source.getContent(); + writeContentToFile(newFilePath, content); + } + } + + public String getBaseFileDirectory() { + return InstanceTranslatorReasoningForAtom.baseFileDirectory; + } + + public void translate() { + final DocumentRoot documentRoot = AlloyUtilities.getDocumentRoot(); + final AlloyType alloy = documentRoot.getAlloy(); + + calcOldSigValues(alloy.getInstance().getSig()); + createSourceFiles(alloy.getSource()); + createSigPart(alloy.getInstance().getSig()); + createFactPart(documentRoot, alloy.getInstance().getField()); + createRunPart(); + + writeContentToFile( + InstanceTranslatorReasoningForAtom.baseFileDirectory + "reasoningForAtom.als", + builder.toString()); + } + + private void createRunPart() { + builder.append("pred show{}\n"); + builder.append("run show for"); + + for (final Entry oldEntry : sig2oldValue.entrySet()) { + final int value = oldEntry.getValue(); + builder.append("\nexactly " + value + " " + oldEntry.getKey() + ","); + } + + builder.replace(0, builder.length(), builder.substring(0, builder.length() - 1)); // to delete + // last ',' + } + + private void writeContentToFile(final String filePath, final String content) { + try { + final File file = createFile(filePath); + final FileOutputStream out = new FileOutputStream(file); + out.write(content.getBytes()); + out.close(); + } catch (final IOException e) { + e.printStackTrace(); + } + } + + private void calcOldSigValues(final EList sigTypes) { + for (final SigType sigType : sigTypes) { + final String sigName = sigType.getLabel().substring(sigType.getLabel().lastIndexOf("/") + 1); + if (sigType.getID() > 3) { + sig2oldValue.put(sigName, sigType.getAbstract() != null ? 0 : sigType.getAtom().size()); + } + } + } + + public Map> getReasonRelations() { + return reasonRelations; + } +} diff --git a/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/synthesis/AutomatedTraceCreator.java b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/synthesis/AutomatedTraceCreator.java new file mode 100644 index 00000000..5798bb0f --- /dev/null +++ b/Source/eu.modelwriter.configuration/src/eu/modelwriter/configuration/synthesis/AutomatedTraceCreator.java @@ -0,0 +1,148 @@ +package eu.modelwriter.configuration.synthesis; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.jface.dialogs.MessageDialog; + +import eu.modelwriter.configuration.alloy.trace.LoadItem; +import eu.modelwriter.configuration.alloy.trace.RelationTrace; +import eu.modelwriter.configuration.alloy.trace.SigTrace; +import eu.modelwriter.configuration.alloy.trace.TraceException; +import eu.modelwriter.configuration.alloy.trace.TraceManager; +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.configuration.internal.Utilities; +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class AutomatedTraceCreator extends Job { + + private final static String TITLE = "Automated Trace Creation"; + private final HashMap eObject2Marker = new HashMap<>(); + + + public AutomatedTraceCreator() { + super(TITLE); + } + + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + monitor.beginTask(getName(), 5); + automate(monitor); + } catch (final TraceException e) { + e.printStackTrace(); + Utilities.showOKDialog(MessageDialog.WARNING, TITLE, e.getMessage()); + return Status.CANCEL_STATUS; + } catch (NullPointerException e) { + Utilities.showOKDialog(MessageDialog.WARNING, TITLE, "Load the specification first."); + } finally { + monitor.done(); + } + return Status.OK_STATUS; + } + + private void automate(IProgressMonitor monitor) throws TraceException { + final List allEObjects = new ArrayList<>(); + for (LoadItem load : TraceManager.get().getLoads()) { + if (load.getInstanceRoot() == null) { + throw new TraceException("Check alias: " + load.getAlias() + + "\nYou must define the ecore instance location to create the traces.\n" + + "\n e.g. -- loadInstance@/path/to/your.xmi"); + } + findAllEObjects(allEObjects, load.getInstanceRoot()); + allEObjects.remove(load.getInstanceRoot()); + } + monitor.worked(1); + createMarkers(allEObjects); + monitor.worked(2); + createRelations(); + monitor.worked(2); + } + + private void findAllEObjects(List allEObjects, EObject root) { + allEObjects.add(root); + for (EObject object : root.eContents()) { + findAllEObjects(allEObjects, object); + } + } + + private void createMarkers(List allEObjects) throws TraceException { + for (EObject eObject : allEObjects) { + final String className = eObject.eClass().getName(); + final SigTrace sigTrace = TraceManager.get().getSigTraceByClassName(className); + if (sigTrace != null) { + LoadItem load = TraceManager.get().getLoadByAlias(sigTrace.getAlias()); + IMarker marker = createMarker(eObject, load.getInstanceFile(), sigTrace.getSigType()); + if (marker != null) { + eObject2Marker.put(eObject, marker); + } + } else { + throw new TraceException("There is no sig trace for EClass " + className); + } + } + } + + @SuppressWarnings({"unchecked"}) + private void createRelations() { + for (EObject sourceObject : eObject2Marker.keySet()) { + final IMarker sourceMarker = eObject2Marker.get(sourceObject); + for (EReference eRef : sourceObject.eClass().getEAllReferences()) { + if (eRef.isMany()) { + List refs = (List) sourceObject.eGet(eRef); + for (EObject ref : refs) { + IMarker targetMarker = eObject2Marker.get(ref); + RelationTrace relTrace; + EClass _super = sourceObject.eClass(); + + do { + relTrace = TraceManager.get().getRelationTrace(_super.getName(), eRef.getName()); + if (relTrace == null) + _super = _super.getESuperTypes().get(0); + } while (_super != null && relTrace == null); + + if (sourceMarker != null && targetMarker != null && !eRef.isVolatile() + && relTrace != null) { + AlloyUtilities.addRelation2Markers(sourceMarker, targetMarker, + relTrace.getRelationName()); + } + } + } else { + EObject ref = (EObject) sourceObject.eGet(eRef); + IMarker targetMarker = eObject2Marker.get(ref); + if (sourceMarker != null && targetMarker != null && !eRef.isVolatile()) + AlloyUtilities.addRelation2Markers(sourceMarker, targetMarker, TraceManager.get() + .getRelationTraceByReferenceName(eRef.getName()).getRelationName()); + } + } + if (sourceMarker != null) { + IMarker newSourceMarker = AnnotationFactory.convertAnnotationType(sourceMarker, false, + false, AlloyUtilities.getTotalTargetCount(sourceMarker)); + eObject2Marker.put(sourceObject, newSourceMarker); + } + + } + } + + public static IMarker createMarker(EObject eObject, IFile iFile, String sigType) { + final IMarker marker = MarkerFactory.createInstanceMarker(eObject, iFile, sigType); + + if (marker == null) + return null; + + AlloyUtilities.addTypeToMarker(marker); + AlloyUtilities.addMarkerToRepository(marker); + return marker; + } +} + diff --git a/Source/eu.modelwriter.configuration/traffic lights.als b/Source/eu.modelwriter.configuration/traffic lights.als new file mode 100644 index 00000000..72749e06 --- /dev/null +++ b/Source/eu.modelwriter.configuration/traffic lights.als @@ -0,0 +1,103 @@ +/* +All clafers: 21 | Abstract: 5 | Concrete: 14 | References: 2 +Constraints: 3 +Goals: 0 +Global scope: 1..* +Can skip resolver: False +*/ + +pred show {} +run show for 1 but 2 c0_Library, 2 c0_List, 6 c0_NamedElement, 2 c0_Type, 2 c0_Web, 2 c0_contentTypes, 6 c0_name, 2 c0_ownedList, 2 c1_List + +abstract sig c0_NamedElement +{ r_c0_name : one c0_name } + +sig c0_name +{ ref : one Int } +{ one @r_c0_name.this } + +abstract sig c0_Web extends c0_NamedElement +{ r_c0_ownedList : set c0_ownedList +, r_c0_ownedWeb : set c0_ownedWeb } + +sig c0_ownedList extends c0_List +{} +{ one @r_c0_ownedList.this } + +sig c0_ownedWeb extends c0_Web +{} +{ one @r_c0_ownedWeb.this } + +abstract sig c0_List extends c0_NamedElement +{ r_c0_contentTypes : set c0_contentTypes +, r_c0_Type : one c0_Type } +{ all disj x, y : this.@r_c0_contentTypes | (x.@ref) != (y.@ref) } + +sig c0_contentTypes +{ ref : one c0_ContentType } +{ one @r_c0_contentTypes.this } + +sig c0_Type +{ r_c0_Library : lone c0_Library +, r_c1_List : lone c1_List } +{ one @r_c0_Type.this + let children = (r_c0_Library + r_c1_List) | one children } + +sig c0_Library +{} +{ one @r_c0_Library.this } + +sig c1_List +{} +{ one @r_c1_List.this } + +fact { #c0_ContentType = 0 } +abstract sig c0_ContentType extends c0_NamedElement +{ r_c0_isAbstract : lone c0_isAbstract +, r_c0_ownedField : set c0_ownedField } + +sig c0_isAbstract +{ ref : one Int } +{ one @r_c0_isAbstract.this } + +sig c0_ownedField extends c0_Field +{} +{ one @r_c0_ownedField.this } + +fact { #c0_Field = 0 } +abstract sig c0_Field extends c0_NamedElement +{ r_c1_Type : one c1_Type } + +sig c1_Type +{ r_c0_Number : lone c0_Number +, r_c0_Boolean : lone c0_Boolean +, r_c0_Text : lone c0_Text +, r_c0_Reference : lone c0_Reference } +{ one @r_c1_Type.this + let children = (r_c0_Number + r_c0_Boolean + r_c0_Text + r_c0_Reference) | one children } + +sig c0_Number +{} +{ one @r_c0_Number.this } + +sig c0_Boolean +{} +{ one @r_c0_Boolean.this } + +sig c0_Text +{} +{ one @r_c0_Text.this } + +sig c0_Reference +{ r_c0_contentType : one c0_contentType } +{ one @r_c0_Reference.this + all disj x, y : this.@r_c0_contentType | (x.@ref) != (y.@ref) } + +sig c0_contentType +{ ref : one c0_ContentType } +{ one @r_c0_contentType.this } + +one sig c0_ConferenceLibrary extends c0_Web +{} +{ (this.(@r_c0_name.@ref)) = 0 } + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/.classpath b/Source/eu.modelwriter.core.alloyinecore.mapping/.classpath new file mode 100644 index 00000000..86c585ea --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/.classpath @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/.gitignore b/Source/eu.modelwriter.core.alloyinecore.mapping/.gitignore new file mode 100644 index 00000000..ae3c1726 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/.project b/Source/eu.modelwriter.core.alloyinecore.mapping/.project new file mode 100644 index 00000000..51df26d3 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/.project @@ -0,0 +1,28 @@ + + + eu.modelwriter.core.alloyinecore.mapping + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/.settings/org.eclipse.jdt.core.prefs b/Source/eu.modelwriter.core.alloyinecore.mapping/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..0c68a61d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/GenericsTest.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/GenericsTest.ecore new file mode 100644 index 00000000..85bd9676 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/GenericsTest.ecore @@ -0,0 +1,53 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/Instance.requirements b/Source/eu.modelwriter.core.alloyinecore.mapping/Instance.requirements new file mode 100644 index 00000000..28481839 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/Instance.requirements @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/META-INF/MANIFEST.MF b/Source/eu.modelwriter.core.alloyinecore.mapping/META-INF/MANIFEST.MF new file mode 100644 index 00000000..88078794 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/META-INF/MANIFEST.MF @@ -0,0 +1,16 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Mapping +Bundle-SymbolicName: eu.modelwriter.core.alloyinecore.mapping +Bundle-Version: 1.0.0.qualifier +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: org.eclipse.emf.ecore, + org.junit, + eu.modelwriter.configuration, + org.eclipse.emf.ecore.xmi;bundle-version="2.12.0" +Export-Package: eu.modelwriter.core.alloyinecore.ui.mapping.as2cs, + eu.modelwriter.core.alloyinecore.ui.mapping.cs2as +Bundle-ClassPath: ., + lib/antlr-4.6-complete.jar, + lib/eu.modelwriter.core.alloyinecore.jar, + lib/ST-4.0.8.jar diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/Model.xmi b/Source/eu.modelwriter.core.alloyinecore.mapping/Model.xmi new file mode 100644 index 00000000..e156fb2e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/Model.xmi @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/Requirements.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/Requirements.ecore new file mode 100644 index 00000000..9a0eb188 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/Requirements.ecore @@ -0,0 +1,76 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/Tutorial.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/Tutorial.ecore new file mode 100644 index 00000000..8acbea77 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/Tutorial.ecore @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/Tutorial.xmi b/Source/eu.modelwriter.core.alloyinecore.mapping/Tutorial.xmi new file mode 100644 index 00000000..66c148ff --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/Tutorial.xmi @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/build.properties b/Source/eu.modelwriter.core.alloyinecore.mapping/build.properties new file mode 100644 index 00000000..38c53db2 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/build.properties @@ -0,0 +1,7 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + lib/antlr-4.6-complete.jar,\ + lib/eu.modelwriter.core.alloyinecore.jar,\ + lib/ST-4.0.8.jar diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/lib/ST-4.0.8.jar b/Source/eu.modelwriter.core.alloyinecore.mapping/lib/ST-4.0.8.jar new file mode 100644 index 00000000..ef879198 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.mapping/lib/ST-4.0.8.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/lib/antlr-4.6-complete.jar b/Source/eu.modelwriter.core.alloyinecore.mapping/lib/antlr-4.6-complete.jar new file mode 100644 index 00000000..b488881e Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.mapping/lib/antlr-4.6-complete.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/lib/eu.modelwriter.core.alloyinecore.jar b/Source/eu.modelwriter.core.alloyinecore.mapping/lib/eu.modelwriter.core.alloyinecore.jar new file mode 100644 index 00000000..10450243 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.mapping/lib/eu.modelwriter.core.alloyinecore.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/mappingTest/tutorial.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/mappingTest/tutorial.ecore new file mode 100644 index 00000000..efc491a7 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/mappingTest/tutorial.ecore @@ -0,0 +1,86 @@ + + + +
+
+
+ + + + + + + + + + + +
+
+
+ + +
+ + + + +
+ + + +
+
+ + +
+ + + + + + + + + + + + + + + +
+
+
+ + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/mappingTest/tutorial.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/mappingTest/tutorial.recore new file mode 100644 index 00000000..86d7bd86 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/mappingTest/tutorial.recore @@ -0,0 +1,73 @@ +import ecore : 'http://www.eclipse.org/emf/2002/Ecore' ; import extlib : '/eu.modelwriter.core.alloyinecore/docs/extlibrary.ecore' ; + +package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' +{ + invariant x: expr; + package Organization : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization' + { + abstract class Librarian extends Employee + { + property workOn : tutorial::Library[1]; + } + abstract class Employee extends tutorial::Library + { + property RefOutsideEcore : extlib::Item[+]; + } + datatype JavaPackage : 'java.lang.Package' { serializable }; + enum Type + { + literal type1; + literal type2; + } + } + abstract class Library { interface } + { + attribute name : String[1] { id }; + property books#library : Book[*] { composes }; + property loans : Loan[*] { composes }; + property members#library : Member[*] { composes }; + } + class Book + { + operation isAvailable() : Boolean[?] + { + precondition:; + precondition test:; + precondition; + body test: expr; + body: expr; + body; + } + attribute name : String[1]; + attribute copies : Integer[1]; + property library#books : Library[?]; + property loans : Loan[*] { derived volatile } + { + initial: expr; + } + invariant SufficientCopies: expr; + invariant; + } + class Member + { + attribute name : String[1]; + property library#members : Library[?]; + property loans : Loan[*] { derived volatile } + { + initial: expr; + derivation: expr; + } + property books : Book[*] { !unique derived volatile } + { + initial: expr; + } + invariant AtMostTwoLoans: expr; + invariant UniqueLoans: expr; + } + class Loan + { + property book : Book[1]; + property member : Member[1]; + attribute date : ecore::EDate[?]; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/mappingTest/tutorialExtended.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/mappingTest/tutorialExtended.ecore new file mode 100644 index 00000000..9758ce8e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/mappingTest/tutorialExtended.ecore @@ -0,0 +1,76 @@ + + + + + + + + + + + + +
+
+
+ + + + +
+ + +
+
+ + +
+ + + + + + + + + + + + + + +
+
+
+ + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/mappingTest/tutorialExtended.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/mappingTest/tutorialExtended.recore new file mode 100644 index 00000000..5ca5a9b9 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/mappingTest/tutorialExtended.recore @@ -0,0 +1,69 @@ +import ecore : 'http://www.eclipse.org/emf/2002/Ecore' ; import extlib : '/eu.modelwriter.core.alloyinecore/docs/extlibrary.ecore' ; + +package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' +{ + package Organization : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization' + { + abstract class Librarian extends Employee + { + property workOn : tutorial::Library[1]; + } + abstract class Employee extends tutorial::Library + { + property RefOutsideEcore : extlib::Item[+]; + } + datatype JavaPackage : 'java.lang.Package' { serializable }; + enum Type + { + literal type1; + literal type2; + } + } + abstract class Library { interface } + { + attribute name : String[1] { id }; + property books#library : Book[*] { composes }; + property loans : Loan[*] { composes }; + property members#library : Member[*] { composes }; + } + class Book + { + operation isAvailable() : Boolean[?] + { + precondition:; + precondition test:; + body test: expr; + body: expr; + } + attribute name : String[1]; + attribute copies : Integer[1]; + property library#books : Library[?]; + property loans : Loan[*] { derived volatile } + { + initial: expr; + } + invariant SufficientCopies: expr; + } + class Member + { + attribute name : String[1]; + property library#members : Library[?]; + property loans : Loan[*] { derived volatile } + { + initial: expr; + derivation: expr; + } + property books : Book[*] { !unique derived volatile } + { + initial: expr; + } + invariant AtMostTwoLoans: expr; + invariant UniqueLoans: expr; + } + class Loan + { + property book : Book[1]; + property member : Member[1]; + attribute date : ecore::EDate[?]; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/nullnull.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/nullnull.ecore new file mode 100644 index 00000000..d45b9af6 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/nullnull.ecore @@ -0,0 +1,412 @@ + + + + +
+ + + + + + +
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + +
+
+ + + + + + +
+ + + + + + + +
+
+ + + + + + +
+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + + + + + + +
+ + + + + + + + + +
+
+ + + + +
+
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+
+ + + + +
+ + + + +
+ + + + +
+
+ + + + + +
+
+ + + + + + +
+ + + + +
+
+ + + + + + + + +
+ + + + +
+
+ + + + +
+ + + + +
+
+ + + + + + +
+ + + + +
+
+ + + + + + + +
+ + + + +
+
+ + + + +
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/AIEConstants.java b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/AIEConstants.java new file mode 100644 index 00000000..f875cce6 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/AIEConstants.java @@ -0,0 +1,47 @@ +package eu.modelwriter.core.alloyinecore.ui.mapping; + +public enum AIEConstants { + VISIBILITY, + INTERFACE, + STATIC, + PRIMITIVE, + SERIALIZABLE, + CALLABLE, + MESSAGE, + FORMULA, + EXPRESSION, + MODEL, + GHOST, + NAME, + DERIVED, + NOT_DERIVED, + ORDERED, + NOT_ORDERED, + UNIQUE, + NOT_UNIQUE, + ID, + NOT_ID, + READONLY, + TRANSIENT, + UNSETTABLE, + NOT_UNSETTABLE, + VOLATILE, + COMPOSES, + NOT_COMPOSES, + NULLABLE, + RESOLVE, + NOT_RESOLVE, + NOT_SERIALIZABLE, + SOURCE; + + public static final String SEPARATOR = "::"; + + @Override + public String toString() { + return super.toString().toLowerCase().replaceAll("not_", "!"); + } + + public static AIEConstants getValue(final String arg0) { + return AIEConstants.valueOf(arg0.replaceAll("!", "not_").toUpperCase()); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/AIEImport.java b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/AIEImport.java new file mode 100644 index 00000000..9d0ad59d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/AIEImport.java @@ -0,0 +1,69 @@ +package eu.modelwriter.core.alloyinecore.ui.mapping; + +import java.util.List; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; + +public class AIEImport { + public static final String Ecore = "http://www.eclipse.org/emf/2002/Ecore"; + private String name; + private String path; + private Resource resource; + + public static AIEImport newInstance() { + return new AIEImport(); + } + + public String getName() { + return name; + } + + public AIEImport setName(final String name) { + this.name = name; + return this; + } + + public String getPath() { + return path; + } + + public AIEImport setPath(final String path) { + this.path = path; + return this; + } + + public Resource getResource() { + return resource; + } + + public AIEImport setResource(final Resource resource) { + this.resource = resource; + return this; + } + + public EObject getRootObject() { + return resource.getContents().get(0); + } + + /** + * + * @param relativePathFragments !!! we have root element, so we don't need root name. + * @return + */ + public EObject getElement(final List relativePathFragments) { + EObject result = null; + try { + final String rootFragment = resource.getURIFragment(getRootObject()); + relativePathFragments.add(0, rootFragment); + result = resource.getEObject(String.join("/", relativePathFragments)); + if (result == null) { + throw new Exception(); + } + } catch (final Exception e) { + relativePathFragments.remove(0); + result = resource.getEObject(String.join("/", relativePathFragments)); + } + return result; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/AnnotationSources.java b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/AnnotationSources.java new file mode 100644 index 00000000..6e27b78c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/AnnotationSources.java @@ -0,0 +1,121 @@ +package eu.modelwriter.core.alloyinecore.ui.mapping; + +import java.util.List; +import java.util.stream.Collectors; + +import org.eclipse.emf.ecore.EAnnotation; +import org.eclipse.emf.ecore.EDataType; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.ETypedElement; + +public interface AnnotationSources { + + public final static String BASE = "http://www.modelwriter.eu/alloyinecore"; + public final static String IMPORT = AnnotationSources.BASE + "/import"; + public static final String MODULE = AnnotationSources.BASE + "/module"; + public static final String OPTIONS = AnnotationSources.BASE + "/options"; + public static final String SOURCE = AnnotationSources.BASE + "/source"; + + public final static String VISIBILITY = AnnotationSources.BASE + "/visibility"; + public final static String STATIC = AnnotationSources.BASE + "/static"; + public final static String QUALIFIER = AnnotationSources.BASE + "/qualifier"; + public final static String NULLABLE = AnnotationSources.BASE + "/nullable"; + public final static String MODEL = AnnotationSources.BASE + "/model"; + public final static String GHOST = AnnotationSources.BASE + "/ghost"; + + public final static String ATTR_EXPRESSIONS = AnnotationSources.BASE + "/attribute/expressions"; + public final static String REF_EXPRESSIONS = AnnotationSources.BASE + "/reference/expressions"; + + public final static String INVARIANT = AnnotationSources.BASE + "/expression/invariant"; + public static final String INITIAL = AnnotationSources.BASE + "/expression/initial"; + public static final String DERIVATION = AnnotationSources.BASE + "/expression/derivation"; + + public final static String PRECONDITION = AnnotationSources.BASE + "/operation/precondition"; + public final static String POSTCONDITION = AnnotationSources.BASE + "/operation/postcondition"; + public final static String BODY = AnnotationSources.BASE + "/operation/body"; + + public final static String DATATYPE_PRIMITIVE = AnnotationSources.BASE + "/datatype/primitive"; + + public static boolean isStatic(final EModelElement element) { + return element.getEAnnotation(AnnotationSources.STATIC) != null; + } + + public static boolean isPrimitive(final EDataType dataType) { + return dataType.getEAnnotation(AnnotationSources.DATATYPE_PRIMITIVE) != null; + } + + public static boolean isNullable(final ETypedElement element) { + boolean canBe = element.getUpperBound() == -1 || element.getUpperBound() > 1; + return canBe && element.getEAnnotation(AnnotationSources.NULLABLE) != null; + } + + /** + * + * @param element @EModelElement to get annotations from + * @return Filtered annotations of AlloyInEcore + */ + public static List filterAnnotations(final EModelElement element, + final String filter) { + return element.getEAnnotations().stream().filter(anno -> filter.equals(anno.getSource())) + .collect(Collectors.toList()); + } + + /** + * + * @param element @EModelElement to get annotations from + * @return Invariant annotations of AlloyInEcore + */ + public static List getInvariants(final EModelElement element) { + return AnnotationSources.filterAnnotations(element, AnnotationSources.INVARIANT); + } + + /** + * + * @param element @EModelElement to get annotations from + * @return Derivation annotations of AlloyInEcore + */ + public static List getDerivation(final EModelElement element) { + return AnnotationSources.filterAnnotations(element, AnnotationSources.DERIVATION); + } + + /** + * + * @param element @EModelElement to get annotations from + * @return Initial annotations of AlloyInEcore + */ + public static List getInitial(final EModelElement element) { + return AnnotationSources.filterAnnotations(element, AnnotationSources.INITIAL); + } + + /** + * + * @param element @EModelElement to get annotations from + * @return The Import annotations + */ + public static List getImports(final EModelElement element) { + return AnnotationSources.filterAnnotations(element, AnnotationSources.IMPORT); + } + + /** + * + * @param element @EModelElement to get annotations from + * @return The annotations other than AlloyInEcore + */ + public static List getAnnotations(final EModelElement element) { + return element.getEAnnotations().stream().filter( + anno -> anno.getSource() == null || !anno.getSource().startsWith(AnnotationSources.BASE)) + .collect(Collectors.toList()); + } + + public static List getPostconditions(final EModelElement element) { + return AnnotationSources.filterAnnotations(element, AnnotationSources.POSTCONDITION); + } + + public static List getPreconditions(final EModelElement element) { + return AnnotationSources.filterAnnotations(element, AnnotationSources.PRECONDITION); + } + + public static List getBodyExpressions(final EModelElement element) { + return AnnotationSources.filterAnnotations(element, AnnotationSources.BODY); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/as2cs/EcoreInstanceTranslator.java b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/as2cs/EcoreInstanceTranslator.java new file mode 100644 index 00000000..82282d0e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/as2cs/EcoreInstanceTranslator.java @@ -0,0 +1,267 @@ +package eu.modelwriter.core.alloyinecore.ui.mapping.as2cs; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EEnumLiteral; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.impl.EPackageImpl; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.stringtemplate.v4.ST; +import org.stringtemplate.v4.STGroupFile; + +import eu.modelwriter.core.alloyinecore.structure.base.Repository; + +public class EcoreInstanceTranslator { + + private STGroupFile templateGroup; + private final Map imports = new HashMap<>(); + private EObject root; + + public EcoreInstanceTranslator() { + templateGroup = new STGroupFile("stringtemplate/EcoreInstance.stg"); + } + + public String translate(String pathToFile) throws IOException { + Repository repository = new Repository(); + Resource resource = repository.loadResource(pathToFile); + if (resource != null && !resource.getContents().isEmpty()) + return translate(resource.getContents().get(0)); + return ""; + } + + public String translate(EObject root) { + this.root = root; + StringBuilder builder = new StringBuilder(); + builder.append(getModelToString(root)); + builder.append(eObjectToString(root)); + builder.insert(0, importsToString()); + return builder.toString(); + } + + private String importsToString() { + StringBuilder importsBuilder = new StringBuilder(); + imports.entrySet().forEach(entry -> { + ST template = templateGroup.getInstanceOf("load"); + template.add("name", entry.getValue()); + template.add("path", entry.getKey()); + importsBuilder.append(template.render().trim()); + importsBuilder.append("\n"); + }); + if (importsBuilder.length() > 0) + importsBuilder.append("\n"); + return importsBuilder.toString(); + } + + private String getModelToString(EObject eObject) { + ST template = templateGroup.getInstanceOf("model"); + EPackageImpl eContainer = (EPackageImpl) eObject.eClass().eContainer(); + template.add("name", eContainer.getName()); + template.add("nsPrefix", eContainer.getNsPrefix()); + template.add("nsURI", eContainer.getNsURI()); + template.add("path", getLocation(eContainer.eResource().getURI())); + return template.render(); + } + + private String eObjectToString(EObject eObject) { + ST template = templateGroup.getInstanceOf("eObject"); + template.add("className", getClassName(eObject)); + EClass eClass = eObject.eClass(); + EAttribute idAttr = eClass.getEIDAttribute(); + if (idAttr != null) { + Object eGet = eObject.eGet(idAttr); + template.add("id", objectToString(eGet)); + } + // Append Attributes + for (EAttribute eAttribute : eClass.getEAllAttributes()) { + Object value = eObject.eGet(eAttribute); + if (value != null && !eAttribute.isID()) + template.add("content", attrToString(eAttribute, value)); + } + // Append References + for (EReference eReference : eClass.getEAllReferences()) { + Object value = eObject.eGet(eReference); + if (value != null) { + template.add("content", eReference.isContainment() ? conRefToString(eReference, value) + : refToString(eReference, value)); + } + } + return template.render(); + } + + /** + * Converts containment reference to string + * + * @param eReference + * @param value + * @return + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + private String conRefToString(EReference eReference, Object value) { + if (value instanceof EList && ((EList) value).isEmpty()) + return null; + ST template = templateGroup.getInstanceOf("containmentRef"); + template.add("name", eReference.getName()); + if (value instanceof EList) { + EList list = (EList) value; + list.forEach(eObj -> { + template.add("content", eObjectToString(eObj)); + }); + } else if (value instanceof EObject) { + template.add("content", eObjectToString((EObject) value)); + } + return template.render(); + } + + @SuppressWarnings("rawtypes") + private String attrToString(EAttribute attr, Object value) { + if (value instanceof EList && ((EList) value).isEmpty()) + return null; + return attr.getName() + ": " + objectToString(value); + } + + /** + * Converts non-containment reference to string + * + * @param eReference + * @param value + * @return + */ + @SuppressWarnings("rawtypes") + private String refToString(EReference ref, Object value) { + if (value instanceof EList && ((EList) value).isEmpty()) + return null; + return ref.getName() + ": " + objectToString(value); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private String objectToString(Object obj) { + if (obj instanceof EList) { + EList list = (EList) obj; + StringBuilder builder = new StringBuilder(); + if (list.size() > 1) + builder.append("["); + for (Object eObj : list) { + builder.append(objectToString(eObj)); + builder.append(", "); + } + if (builder.length() > 1) + builder.delete(builder.length() - 2, builder.length()); + if (list.size() > 1) + builder.append("]"); + return builder.toString(); + } + if (obj instanceof Number || obj instanceof Boolean || obj instanceof EEnumLiteral) + return obj.toString(); + + if (obj instanceof Character) + return "\'" + obj.toString() + "\'"; + + if (obj instanceof EObject) { + return getEObjectRefString((EObject) obj); + } + // Return as string + return "\"" + obj.toString().replaceAll("\"", "\\\\\"").replaceAll("\'", "\\\\\'") + "\""; + } + + /** + * Get DynamicEObjectImpl's EClass name with package information + * + * @param eObject + * @return + */ + private String getClassName(EObject eObject) { + return getPackageName(root.eClass(), eObject.eClass()) + getURIString(eObject.eClass()); + } + + /** + * Get an EObject's path with package information + * + * @param eObject + * @return + */ + private String getEObjectRefString(EObject eObject) { + return getPackageName(root, eObject) + getURIString(eObject); + } + + private String getURIString(EObject eObject) { + return EcoreUtil.getURI(eObject).fragment().replaceAll("//", "").replaceAll("@", "") + .replaceAll("/", "::"); + } + + /** + * Returns root package name of given EObject. If EObject directly inside of root returns empty + * string. Also if given EObject is part of another EMF file imports that file and returns + * import's name. + * + * @param root + * @param eObject + * @return + */ + private String getPackageName(EObject root, EObject eObject) { + URI eObjectURI = EcoreUtil.getURI(eObject); + URI rootURI = EcoreUtil.getURI(root); + + if (!rootURI.trimFragment().equals(eObjectURI.trimFragment())) { + String fileLocation = getLocation(eObject); + // Check if its already imported + String importName = imports.get(fileLocation); + if (importName == null) { + importName = handleImportName(eObjectURI.trimFileExtension().lastSegment()); + imports.put(fileLocation, importName); + } + return importName + "::"; + } + return ""; + + } + + /** + * Configures import names. If given name already in imports map, adds numbers as suffix until the + * name becomes unique + * + * @param baseName + * @return + */ + private String handleImportName(String baseName) { + if (imports.values().contains(baseName)) { + // Gotta find new name for this + int suffix = 1; + while (imports.get(baseName + ++suffix) != null); + return baseName + suffix; + } + return baseName; + } + + /** + * Get EObject's file location relative to root object. + * + * @param eObject + * @return + */ + private String getLocation(EObject eObject) { + return getLocation(EcoreUtil.getURI(eObject)); + } + + /** + * Get EObject's file location relative to root object. + * + * @param eObject + * @return + */ + private String getLocation(URI uri) { + URI rootURI = EcoreUtil.getURI(root).trimFragment(); + URI deresolvedUri = uri.trimFragment().deresolve(rootURI, true, true, true); + if (deresolvedUri.isFile()) + return deresolvedUri.toFileString(); + else + return deresolvedUri.toString(); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/as2cs/EcoreTranslator.java b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/as2cs/EcoreTranslator.java new file mode 100644 index 00000000..806f517e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/as2cs/EcoreTranslator.java @@ -0,0 +1,619 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.ui.mapping.as2cs; + +import eu.modelwriter.core.alloyinecore.internal.AIEConstants; +import eu.modelwriter.core.alloyinecore.internal.AnnotationSources; +import eu.modelwriter.core.alloyinecore.structure.base.Repository; +import org.eclipse.emf.common.util.EMap; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.*; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.stringtemplate.v4.ST; +import org.stringtemplate.v4.STGroup; +import org.stringtemplate.v4.STGroupFile; + +import java.io.IOException; +import java.util.*; +import java.util.Map.Entry; + +public class EcoreTranslator implements AnnotationSources { + + private final Map imports = new HashMap<>(); + private final Map primitives = new HashMap<>(); + private final STGroup templateGroup; + + private EModelElement root; + + private Repository repository = new Repository(); + + public EcoreTranslator() { + templateGroup = new STGroupFile("AlloyInEcore.stg"); + primitives.put("Ecore::EString", "String"); + primitives.put("Ecore::EBoolean", "Boolean"); + primitives.put("Ecore::EBigDecimal", "Real"); + primitives.put("Ecore::EInt", "Integer"); + primitives.put("Ecore::EBigInteger", "UnlimitedNatural"); + } + + public EcoreTranslator(Repository repository) { + this(); + this.repository = repository; + } + + public String translate(String pathToEcore) throws IOException { + if (repository.loadResource(pathToEcore) != null) { + Resource resource = repository.loadResource(pathToEcore); + assert resource != null; + EObject eObject = resource.getEObject("/"); + if ( eObject instanceof EModelElement) + return translate((EModelElement)eObject); + } + return null; + } + + public String translate(EModelElement element) { + if (element.getEAnnotation(AnnotationSources.SOURCE) != null) { + EAnnotation sourceAnno = element.getEAnnotation(AnnotationSources.SOURCE); + String source = sourceAnno.getDetails().get(AIEConstants.SOURCE.toString()); + if (source != null) + return source; + } + // If there is no source annotation, translate it. + imports.clear(); + StringBuilder builder = new StringBuilder(); + if (element != null) { + root = element; + collectImports(element); + builder.append(eObjectToString(element)); + builder.insert(0, importsToString()); + builder.insert(0, modelToString(element)); + } + return builder.toString(); + } + + private void collectImports(EModelElement element) { + AnnotationSources.getImports(element).forEach(anno -> { + if (!anno.getDetails().isEmpty()) { + String name = anno.getDetails().get(0).getKey(); + String ns = anno.getDetails().get(0).getValue(); + imports.put(ns, name); + } + }); + } + + private String eObjectToString(EObject eObject) { + if (eObject instanceof EPackage) + return packageToString((EPackage) eObject); + if (eObject instanceof EClassifier) + return classifierToString((EClassifier) eObject); + if (eObject instanceof EAttribute) + return attrToString((EAttribute) eObject); + if (eObject instanceof EReference) + return referenceToString((EReference) eObject); + if (eObject instanceof EOperation) + return operationToString((EOperation) eObject); + return ""; + } + + private String classifierToString(EClassifier eClassifier) { + if (eClassifier instanceof EEnum) + return enumToString((EEnum) eClassifier); + if (eClassifier instanceof EClass) + return classToString((EClass) eClassifier); + if (eClassifier instanceof EDataType) + return datatypeToString((EDataType) eClassifier); + return ""; + } + + private String modelToString(EModelElement element) { + ST template = templateGroup.getInstanceOf("model"); + EAnnotation options = element.getEAnnotation(AnnotationSources.OPTIONS); + if (options != null && !options.getDetails().isEmpty()) { + options.getDetails().forEach(entry -> template.add("option", entry.getKey() + " : " + entry.getValue())); + } + EAnnotation model = element.getEAnnotation(AnnotationSources.MODULE); + if (model != null && model.getDetails().get("name") != null) { + template.add("modelName", model.getDetails().get("name")); + } + return template.render(); + } + + private void addAnnotations(ST template, EModelElement element) { + AnnotationSources.getAnnotations(element).forEach(anno -> template.add("subElement", annoToString(anno).trim())); + } + + private Object invariantToString(EAnnotation invAnno) { + ST template = templateGroup.getInstanceOf("inv"); + EMap details = invAnno.getDetails(); + template.add("isCallable", Boolean.parseBoolean(AIEConstants.CALLABLE.toString())); + template.add("name", details.get(AIEConstants.NAME.toString())); + template.add("message", details.get(AIEConstants.MESSAGE.toString())); + template.add("formula", details.get(AIEConstants.FORMULA.toString())); + return template.render().trim(); + } + + private String packageToString(EPackage ePackage) { + ST template = templateGroup.getInstanceOf("package"); + template.add("visibility", getVisibility(ePackage)); + template.add("name", ePackage.getName()); + template.add("prefix", ePackage.getNsPrefix()); + template.add("namespace", ePackage.getNsURI()); + for (EClassifier eClassifier : ePackage.getEClassifiers()) { + template.add("subElement", classifierToString(eClassifier)); + } + for (EPackage subPackage : ePackage.getESubpackages()) { + template.add("subElement", packageToString(subPackage)); + } + AnnotationSources.getInvariants(ePackage).forEach(invAnno -> { + template.add("subElement", invariantToString(invAnno)); + }); + addAnnotations(template, ePackage); + return template.render().trim(); + } + + private String datatypeToString(EDataType eDataType) { + ST template = templateGroup.getInstanceOf("datatype"); + template.add("visibility", getVisibility(eDataType)); + template.add("isPrimitive", AnnotationSources.isPrimitive(eDataType)); + // template.add("nullable", AnnotationSources.isNullable(eDataType)); + template.add("name", eDataType.getName()); + for (ETypeParameter typeParameter : eDataType.getETypeParameters()) { + template.add("typeParameter", typeParameterToString(typeParameter)); + } + template.add("instanceName", eDataType.getInstanceClassName()); + if (!eDataType.isSerializable()) + template.add("isSerializable", AIEConstants.NOT_SERIALIZABLE.toString()); + AnnotationSources.getInvariants(eDataType).forEach(invAnno -> { + template.add("subElement", invariantToString(invAnno)); + }); + addAnnotations(template, eDataType); + return template.render().trim(); + } + + private String enumToString(EEnum eEnum) { + ST template = templateGroup.getInstanceOf("enum"); + template.add("visibility", getVisibility(eEnum)); + template.add("name", eEnum.getName()); + for (ETypeParameter typeParameter : eEnum.getETypeParameters()) { + template.add("typeParameter", typeParameterToString(typeParameter)); + } + template.add("instanceName", eEnum.getInstanceClassName()); + if (!eEnum.isSerializable()) + template.add("isSerializable", AIEConstants.NOT_SERIALIZABLE.toString()); + AnnotationSources.getInvariants(eEnum).forEach(invAnno -> { + template.add("subElement", invariantToString(invAnno)); + }); + for (EEnumLiteral eEnumLiteral : eEnum.getELiterals()) { + template.add("subElement", enumLiteralToString(eEnumLiteral)); + } + addAnnotations(template, eEnum); + return template.render().trim(); + } + + private String enumLiteralToString(EEnumLiteral literal) { + ST template = templateGroup.getInstanceOf("enumLiteral"); + template.add("name", literal.getName()); + template.add("enumValue", literal.getValue()); + addAnnotations(template, literal); + return template.render().trim(); + } + + private String classToString(EClass eClass) { + ST template = templateGroup.getInstanceOf("class"); + template.add("visibility", getVisibility(eClass)); + template.add("isAbstract", eClass.isAbstract()); + template.add("isInterface", eClass.isInterface()); + template.add("name", eClass.getName()); + for (ETypeParameter typeParameter : eClass.getETypeParameters()) { + template.add("typeParameter", typeParameterToString(typeParameter)); + } + template.add("instanceName", eClass.getInstanceClassName()); + for (EGenericType genericSuperClass : eClass.getEGenericSuperTypes()) { + template.add("superClass", genericTypeToString(genericSuperClass)); + } + eClass.getEAttributes().forEach(attr -> template.add("subElement", attrToString(attr))); + eClass.getEReferences().forEach(eRef -> template.add("subElement", referenceToString(eRef))); + eClass.getEOperations().forEach(op -> template.add("subElement", operationToString(op))); + AnnotationSources.getInvariants(eClass).forEach(invAnno -> template.add("subElement", invariantToString(invAnno))); + addAnnotations(template, eClass); + return template.render().trim(); + } + + private Object typeParameterToString(ETypeParameter typeParameter) { + ST template = templateGroup.getInstanceOf("typeParameter"); + template.add("name", typeParameter.getName()); + for (EGenericType genericType : typeParameter.getEBounds()) { + template.add("eBound", genericTypeToString(genericType)); + } + return template.render().trim(); + } + + private String genericTypeToString(EGenericType genericType) { + ST template = templateGroup.getInstanceOf("genericType"); + + if (genericType.getEClassifier() != null) { + template.add("classifier", getTypeName(genericType, genericType.getEClassifier())); + } else if (genericType.getETypeParameter() != null) { + template.add("typeParameter", genericType.getETypeParameter().getName()); + } else { + if (genericType.getEUpperBound() != null) { + template.add("upperBound", genericTypeToString(genericType.getEUpperBound())); + } else if (genericType.getELowerBound() != null) { + template.add("lowerBound", genericTypeToString(genericType.getELowerBound())); + } + } + for (EGenericType eTypeArgument : genericType.getETypeArguments()) { + template.add("typeArgument", genericTypeToString(eTypeArgument)); + } + + return template.render().trim(); + } + + private String operationToString(EOperation op) { + ST template = templateGroup.getInstanceOf("op"); + template.add("visibility", getVisibility(op)); + template.add("isStatic", AnnotationSources.isStatic(op)); + // template.add("nullable", AnnotationSources.isNullable(op)); + for (ETypeParameter typeParameter : op.getETypeParameters()) { + template.add("typeParameter", typeParameterToString(typeParameter)); + } + template.add("name", op.getName()); + if (op.getEGenericType() != null) { + template.add("type", genericTypeToString(op.getEGenericType())); + template.add("multiplicity", getMultiplicity(op)); + template.add("qualifier", getQualifiers(op)); + } + op.getEGenericExceptions().forEach(eGenericException -> template.add("throws", genericTypeToString(eGenericException))); + op.getEParameters().forEach(param -> template.add("params", paramToString(param))); + + AnnotationSources.getPreconditions(op).forEach(anno -> template.add("subElement", preconditionToString(anno))); + AnnotationSources.getBodyExpressions(op).forEach(anno -> template.add("subElement", bodyToString(anno))); + AnnotationSources.getPostconditions(op).forEach(anno -> template.add("subElement", postconditionToString(anno))); + + addAnnotations(template, op); + return template.render().trim(); + } + + private String paramToString(EParameter param) { + ST template = templateGroup.getInstanceOf("opParameter"); + // template.add("nullable", AnnotationSources.isNullable(param)); + template.add("name", param.getName()); + if (param.getEGenericType() != null) { + template.add("type", genericTypeToString(param.getEGenericType())); + template.add("multiplicity", getMultiplicity(param)); + } + template.add("qualifier", getQualifiers(param)); + addAnnotations(template, param); + return template.render(); + } + + private String postconditionToString(EAnnotation eAnnotation) { + ST template = templateGroup.getInstanceOf("postcondition"); + EMap details = eAnnotation.getDetails(); + template.add("name", details.get(AIEConstants.NAME.toString())); + template.add("message", details.get(AIEConstants.MESSAGE.toString())); + template.add("formula", details.get(AIEConstants.FORMULA.toString())); + return template.render().trim(); + } + + private Object bodyToString(EAnnotation eAnnotation) { + ST template = templateGroup.getInstanceOf("body"); + EMap details = eAnnotation.getDetails(); + template.add("name", details.get(AIEConstants.NAME.toString())); + template.add("expression", details.get(AIEConstants.EXPRESSION.toString())); + return template.render().replace(" ", ""); + } + + private String preconditionToString(EAnnotation invAnno) { + ST template = templateGroup.getInstanceOf("precondition"); + EMap details = invAnno.getDetails(); + template.add("name", details.get(AIEConstants.NAME.toString())); + template.add("message", details.get(AIEConstants.MESSAGE.toString())); + template.add("formula", details.get(AIEConstants.FORMULA.toString())); + return template.render().trim(); + } + + private String referenceToString(EReference eRef) { + ST template = templateGroup.getInstanceOf("ref"); + template.add("visibility", getVisibility(eRef)); + template.add("isStatic", AnnotationSources.isStatic(eRef)); + template.add("transient", eRef.isTransient()); + template.add("volatile", eRef.isVolatile()); + template.add("model", eRef.getEAnnotation(AnnotationSources.MODEL) != null); + template.add("ghost", eRef.getEAnnotation(AnnotationSources.GHOST) != null); + // template.add("nullable", AnnotationSources.isNullable(eRef)); + template.add("readonly", !eRef.isChangeable()); + template.add("name", eRef.getName()); + if (eRef.getEOpposite() != null) + template.add("opposite", eRef.getEOpposite().getName()); + template.add("defaultValue", eRef.getDefaultValueLiteral()); + if (eRef.getEGenericType() != null) { + template.add("type", genericTypeToString(eRef.getEGenericType())); + template.add("multiplicity", getMultiplicity(eRef)); + } + template.add("qualifier", getQualifiers(eRef)); + addAnnotations(template, eRef); + addReferenceKeys(template, eRef); + addSFExpressions(template, eRef); + return template.render().trim(); + } + + private void addReferenceKeys(ST refTemplate, EReference eRef) { + if (eRef.getEKeys().isEmpty()) + return; + ST template = templateGroup.getInstanceOf("referenceKey"); + eRef.getEKeys().forEach(attr -> template.add("referredKeys", attr.getName())); + refTemplate.add("subElement", template.render()); + } + + private void addSFExpressions(ST template, EStructuralFeature sf) { + EAnnotation derivationAnno = sf.getEAnnotation(AnnotationSources.DERIVATION); + if (derivationAnno != null && !derivationAnno.getDetails().isEmpty()) + template.add("subElement", derivationToString(derivationAnno)); + else { + EAnnotation initialAnno = sf.getEAnnotation(AnnotationSources.INITIAL); + if (initialAnno != null && !initialAnno.getDetails().isEmpty()) + template.add("subElement", initialToString(initialAnno)); + } + } + + private Object initialToString(EAnnotation eAnnotation) { + ST template = templateGroup.getInstanceOf("initial"); + template.add("name", eAnnotation.getDetails().get("name")); + template.add("expression", eAnnotation.getDetails().get("expression")); + return template.render(); + } + + private String derivationToString(EAnnotation eAnnotation) { + ST template = templateGroup.getInstanceOf("derivation"); + template.add("name", eAnnotation.getDetails().get("name")); + template.add("expression", eAnnotation.getDetails().get("expression")); + return template.render(); + } + + private String attrToString(EAttribute eAttr) { + ST template = templateGroup.getInstanceOf("attr"); + template.add("visibility", getVisibility(eAttr)); + template.add("isStatic", AnnotationSources.isStatic(eAttr)); + template.add("transient", eAttr.isTransient()); + template.add("volatile", eAttr.isVolatile()); + template.add("model", eAttr.getEAnnotation(AnnotationSources.MODEL) != null); + template.add("ghost", eAttr.getEAnnotation(AnnotationSources.GHOST) != null); + // template.add("nullable", AnnotationSources.isNullable(eAttr)); + template.add("readonly", !eAttr.isChangeable()); + template.add("name", eAttr.getName()); + if (eAttr.getEGenericType() != null) { + template.add("type", genericTypeToString(eAttr.getEGenericType())); + template.add("multiplicity", getMultiplicity(eAttr)); + template.add("defaultValue", eAttr.getDefaultValueLiteral()); + } + template.add("qualifier", getQualifiers(eAttr)); + addAnnotations(template, eAttr); + addSFExpressions(template, eAttr); + return template.render().trim(); + } + + private String annoToString(EAnnotation eAnnotation) { + ST template = templateGroup.getInstanceOf("anno"); + template.add("name", eAnnotation.getSource()); + eAnnotation.getDetails().forEach(entry -> template.add("detail", edetailToString(entry.getKey(), entry.getValue()))); + eAnnotation.getReferences().forEach(ref -> { + if (!(ref instanceof EAnnotation)) + template.add("subElement", "reference " + getQualifiedName(eAnnotation, ref) + ";"); + }); + eAnnotation.getContents().forEach(eObject -> { + String subElement = eObjectToString(eObject); + template.add("subElement", subElement); + }); + addAnnotations(template, eAnnotation); + return template.render().trim(); + } + + + private String edetailToString(String name, String value) { + ST template = templateGroup.getInstanceOf("edetail"); + template.add("name", name); + template.add("val", value); + return template.render(); + } + + private String importsToString() { + StringBuilder importsBuilder = new StringBuilder(); + imports.entrySet().forEach(entry -> { + ST template = templateGroup.getInstanceOf("load"); + template.add("namespace", entry.getKey()); + template.add("name", entry.getValue()); + importsBuilder.append(template.render().trim()); + importsBuilder.append("\n"); + }); + if (importsBuilder.length() > 0) + importsBuilder.append("\n"); + return importsBuilder.toString(); + } + + private boolean isInSamePackage(EObject obj1, EObject obj2) { + EPackage pac1 = getContainerPackage(obj1); + EPackage pac2 = getContainerPackage(obj2); + return pac1 != null && pac2 != null && pac1.equals(pac2); + } + + private EPackage getContainerPackage(EObject obj) { + try { + EObject container = obj; + while (container.eContainer() != null && !(container instanceof EPackage)) { + container = container.eContainer(); + } + return (EPackage) container; + } catch (ClassCastException e) { + return null; + } + } + + private String getQualifiedName(EObject rel, EObject eObject) { + if (eObject == null && !(eObject instanceof ENamedElement)) // No annotation allowed + return ""; + + if (!root.equals(EcoreUtil.getRootContainer(eObject, true))) + return getImportedQualifiedName(eObject); + + // Annotation references must be fully qualified + boolean relative = isInSamePackage(rel, eObject) && !(rel instanceof EAnnotation); + ENamedElement element = (ENamedElement) eObject; + EPackage relPackage = getContainerPackage(rel); + + String qualifiedName; + ENamedElement container = (ENamedElement) eObject.eContainer(); + List containerNames = new ArrayList<>(); + + while (container != null) { + if (relative && container.equals(relPackage)) + break; + containerNames.add(container.getName()); + container = (ENamedElement) container.eContainer(); + } + + Collections.reverse(containerNames); + qualifiedName = String.join(AIEConstants.SEPARATOR, containerNames); + + String lastSeparator = getSeparator(eObject); + qualifiedName += + qualifiedName.isEmpty() ? element.getName() : lastSeparator + element.getName(); + + return qualifiedName; + } + + private String getImportedQualifiedName(EObject eObject) { + // Use file name + String packageName = imports.computeIfAbsent(getLocation(eObject), k -> EcoreUtil.getURI(eObject).trimFileExtension().lastSegment()); + return packageName + AIEConstants.SEPARATOR + + EcoreUtil.getURI(eObject).fragment().replace("//", "") + .replaceAll("/([^/]*)$", getSeparator(eObject) + "$1") + .replaceAll("/", AIEConstants.SEPARATOR); + } + + private String getSeparator(EObject eObject) { + // if (eObject instanceof EStructuralFeature) + // return AIEConstants.SEPARATOR; + // if (eObject instanceof EOperation) + // return AIEConstants.SEPARATOR; + // if (eObject instanceof EClassifier) + // return AIEConstants.SEPARATOR; + return AIEConstants.SEPARATOR; + } + + private String getLocation(EObject eObject) { + URI rootURI = EcoreUtil.getURI(root).trimFragment(); + URI uri = EcoreUtil.getURI(eObject).trimFragment().deresolve(rootURI, true, true, true); + if (uri.isFile()) + return uri.toFileString(); + else + return uri.toString(); + } + + private String getTypeName(EObject rel, EClassifier eClassifier) { + String type = getQualifiedName(rel, eClassifier); + if (type != null) { + for (Entry e : primitives.entrySet()) { + if (type.equals(e.getKey())) { + return e.getValue(); + } + } + } + return type; + } + + private String getMultiplicity(ETypedElement eTypedElement) { + int l = eTypedElement.getLowerBound(); + int u = eTypedElement.getUpperBound(); + String mul = null; + if (l == 0 && u == 1) + mul = "?"; + else if (l == 0 && u == -1) + mul = "*"; + else if (l == 1 && u == -1) + mul = "+"; + else if (l == u && l != 1) + mul = l + ""; + else if (!(l == 1 && u == 1)) + mul = l + ".." + u; + + if (mul != null && AnnotationSources.isNullable(eTypedElement)) + mul += "|?"; + + // If EAttribure is ID, its bounds must be 1 + if (eTypedElement instanceof EAttribute && ((EAttribute) eTypedElement).isID()) { + // Since 1 is default multiplicity, return empty + return "1"; + } + + return mul != null ? mul.replace("-1", "*") : mul; + } + + private String getVisibility(ENamedElement element) { + String visibility = ""; + EAnnotation visibilityAnno = element.getEAnnotation(VISIBILITY); + if (visibilityAnno != null && !visibilityAnno.getDetails().isEmpty()) + visibility = visibilityAnno.getDetails().get(AIEConstants.VISIBILITY.toString()); + return visibility; + } + + private String getQualifiers(ETypedElement element) { + StringBuilder builder = new StringBuilder(); + if (!element.isUnique() && (element.getUpperBound() > 1 || element.getUpperBound() == -1)) + builder.append(AIEConstants.NOT_UNIQUE + " "); + if (element.isOrdered() && (element.getUpperBound() > 1 || element.getUpperBound() == -1)) + builder.append(AIEConstants.ORDERED + " "); + + if (element instanceof EStructuralFeature) + appendSFQualifiers(builder, (EStructuralFeature) element); + + // Wrap with curly bracket + if (builder.length() > 0) { + builder.insert(0, " { "); + builder.append("}"); + } + return builder.toString(); + } + + private void appendSFQualifiers(StringBuilder builder, EStructuralFeature eStructuralFeature) { + if (eStructuralFeature.isDerived()) + builder.append(AIEConstants.DERIVED + " "); + if (eStructuralFeature.isUnsettable()) + builder.append(AIEConstants.UNSETTABLE + " "); + + if (eStructuralFeature instanceof EAttribute && ((EAttribute) eStructuralFeature).isID()) + builder.append(AIEConstants.ID + " "); + + if (eStructuralFeature instanceof EReference) { + if (!((EReference) eStructuralFeature).isResolveProxies()) + builder.append(AIEConstants.NOT_RESOLVE + " "); + if (((EReference) eStructuralFeature).isContainment()) + builder.append(AIEConstants.COMPOSES + " "); + } + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/cs2as/CS2ASInitializer.java b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/cs2as/CS2ASInitializer.java new file mode 100644 index 00000000..46521552 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/cs2as/CS2ASInitializer.java @@ -0,0 +1,293 @@ +package eu.modelwriter.core.alloyinecore.ui.mapping.cs2as; + +import java.util.List; +import java.util.Stack; +import java.util.stream.Collectors; + +import org.antlr.v4.runtime.tree.ParseTree; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EClassifier; +import org.eclipse.emf.ecore.EDataType; +import org.eclipse.emf.ecore.EEnum; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EOperation; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.ETypeParameter; +import org.eclipse.emf.ecore.resource.Resource; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreBaseVisitor; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EAttributeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EClassContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EClassifierContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EDataTypeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EEnumContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EOperationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EPackageContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EReferenceContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EStructuralFeatureContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ETypeParameterContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.PackageImportContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.TemplateSignatureContext; +import eu.modelwriter.core.alloyinecore.ui.mapping.AIEImport; + +public class CS2ASInitializer extends AlloyInEcoreBaseVisitor { + + private final Stack qualifiedNameStack; + private final CS2ASRepository repository; + + public CS2ASInitializer(final CS2ASRepository repository) { + qualifiedNameStack = new Stack<>(); + this.repository = repository; + } + + public void initialize(final ParseTree tree) { + visit(tree); + } + + @Override + public Object visitPackageImport(final PackageImportContext ctx) { + String path = null; + if (ctx.ownedPathName != null) { + path = ctx.ownedPathName.getText().replace("'", ""); + } + + final Resource resource = repository.loadResource(path); + + final String name = ctx.name != null ? ctx.name.getText() + : resource.getContents().get(0) instanceof ENamedElement + ? ((ENamedElement) resource.getContents().get(0)).getName() : null; + + final AIEImport aieImport = + AIEImport.newInstance().setName(name).setPath(path).setResource(resource); + repository.name2Import.put(name, aieImport); + return null; + } + + boolean isRoot = true; + private int pc = 0; + + @Override + public EPackage visitEPackage(final EPackageContext ctx) { + final EPackage ePackage = repository.factory.createEPackage(); + + String name = "package" + ++pc; + if (ctx.name != null) { + name = ctx.name.getText(); + } + ePackage.setName(name); + + if (isRoot) { + repository.aieResource.getContents().add(ePackage); + repository.name2Import.put(name, new AIEImport().setName(name).setPath(ctx.nsURI.getText()) + .setResource(repository.aieResource)); + isRoot = false; + } + + qualifiedNameStack.push(name); + + ctx.eSubPackages.forEach(sp -> { + final EPackage subPackage = visitEPackage(sp); + ePackage.getESubpackages().add(subPackage); + }); + + ctx.eClassifiers.forEach(c -> { + final EClassifier classifier = visitEClassifier(c); + ePackage.getEClassifiers().add(classifier); + }); + + qualifiedNameStack.pop(); + + // TODO if there is any annotation which has OwnedContent (EModelElement), it need to be + // initialized with super.visitEPackage and need to has a (complex) qualified name + + return ePackage; + } + + @Override + public EClassifier visitEClassifier(final EClassifierContext ctx) { + return (EClassifier) super.visitEClassifier(ctx); + } + + private int cc = 0; + + @Override + public EClass visitEClass(final EClassContext ctx) { + final EClass eClass = repository.factory.createEClass(); + + String name = "class" + ++cc; + if (ctx.name != null) { + name = ctx.name.getText(); + } + eClass.setName(name); + + qualifiedNameStack.push(name); + + if (ctx.ownedSignature != null) { + final List eTypeParameters = visitTemplateSignature(ctx.ownedSignature); + eClass.getETypeParameters().addAll(eTypeParameters); + } + + ctx.eStructuralFeatures.forEach(esf -> { + final EStructuralFeature eStructuralFeature = visitEStructuralFeature(esf); + eClass.getEStructuralFeatures().add(eStructuralFeature); + // TODO is it required to add eStructuralFeature to eClass.getEReferences() or to + // eClass.getEAttributes() ? Discuss. + }); + + ctx.eOperations.forEach(eo -> { + final EOperation eOperation = visitEOperation(eo); + eClass.getEOperations().add(eOperation); + }); + + qualifiedNameStack.pop(); + + // TODO if there is any annotation which has OwnedContent (EModelElement), it need to be + // initialized with super.visitEClass and need to has a (complex) qualified name + + return eClass; + } + + private int dtc = 0; + + @Override + public EDataType visitEDataType(final EDataTypeContext ctx) { + final EDataType eDataType = repository.factory.createEDataType(); + + String name = "datatype" + ++dtc; + if (ctx.name != null) { + name = ctx.name.getText(); + } + eDataType.setName(name); + + if (ctx.ownedSignature != null) { + final List eTypeParameters = visitTemplateSignature(ctx.ownedSignature); + eDataType.getETypeParameters().addAll(eTypeParameters); + } + + // qualifiedNameStack.push(name); + // TODO if there is any annotation which has OwnedContent (EModelElement), it need to be + // initialized with super.visitEDataType and need to has a (complex) qualified name + // qualifiedNameStack.pop(); + + return eDataType; + } + + private int ec = 0; + + @Override + public EEnum visitEEnum(final EEnumContext ctx) { + final EEnum eEnum = repository.factory.createEEnum(); + + String name = "enum" + ++ec; + if (ctx.name != null) { + name = ctx.name.getText(); + } + eEnum.setName(name); + + if (ctx.ownedSignature != null) { + final List eTypeParameters = visitTemplateSignature(ctx.ownedSignature); + eEnum.getETypeParameters().addAll(eTypeParameters); + } + + // qualifiedNameStack.push(name); + // TODO if there is any annotation which has OwnedContent (EModelElement), it need to be + // initialized with super.visitEEnum and need to has a (complex) qualified name + // qualifiedNameStack.pop(); + + return eEnum; + } + + @Override + public EStructuralFeature visitEStructuralFeature(final EStructuralFeatureContext ctx) { + return (EStructuralFeature) super.visitEStructuralFeature(ctx); + } + + private int rc = 0; + + @Override + public EReference visitEReference(final EReferenceContext ctx) { + final EReference eReference = repository.factory.createEReference(); + + String name = "reference" + ++rc; + if (ctx.name != null) { + name = ctx.name.getText(); + } + eReference.setName(name); + + // qualifiedNameStack.push(name); + // TODO if there is any annotation which has OwnedContent (EModelElement), it need to be + // initialized with super.visitEReference and need to has a (complex) qualified name + // qualifiedNameStack.pop(); + + return eReference; + } + + private int ac = 0; + + @Override + public EAttribute visitEAttribute(final EAttributeContext ctx) { + final EAttribute eAttribute = repository.factory.createEAttribute(); + + String name = "attribute" + ++ac; + if (ctx.name != null) { + name = ctx.name.getText(); + } + eAttribute.setName(name); + + // qualifiedNameStack.push(name); + // TODO if there is any annotation which has OwnedContent (EModelElement), it need to be + // initialized with super.visitEAttribute and need to has a (complex) qualified name + // qualifiedNameStack.pop(); + + return eAttribute; + } + + private int oc = 0; + + @Override + public EOperation visitEOperation(final EOperationContext ctx) { + final EOperation eOperation = repository.factory.createEOperation(); + + String name = "operation" + ++oc; + if (ctx.name != null) { + name = ctx.name.getText(); + } + eOperation.setName(name); + + if (ctx.ownedSignature != null) { + final List eTypeParameters = visitTemplateSignature(ctx.ownedSignature); + eOperation.getETypeParameters().addAll(eTypeParameters); + } + + // qualifiedNameStack.push(name); + // TODO if there is any annotation which has OwnedContent (EModelElement), it need to be + // initialized with super.visitEOperation and need to has a (complex) qualified name + // qualifiedNameStack.pop(); + + return eOperation; + } + + @Override + public List visitTemplateSignature(final TemplateSignatureContext ctx) { + return ctx.ownedTypeParameters.stream().map(op -> visitETypeParameter(op)) + .collect(Collectors.toList()); + } + + private int tpc = 0; + + @Override + public ETypeParameter visitETypeParameter(final ETypeParameterContext ctx) { + final ETypeParameter eTypeParameter = repository.factory.createETypeParameter(); + + String name = "typeparameter" + ++tpc; + if (ctx.name != null) { + name = ctx.name.getText(); + } + eTypeParameter.setName(name); + + return eTypeParameter; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/cs2as/CS2ASMapping.java b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/cs2as/CS2ASMapping.java new file mode 100644 index 00000000..63abd675 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/cs2as/CS2ASMapping.java @@ -0,0 +1,1549 @@ +package eu.modelwriter.core.alloyinecore.ui.mapping.cs2as; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Stack; +import java.util.stream.Collectors; + +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.BaseErrorListener; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.Recognizer; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.tree.ParseTree; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EAnnotation; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EClassifier; +import org.eclipse.emf.ecore.EDataType; +import org.eclipse.emf.ecore.EEnum; +import org.eclipse.emf.ecore.EEnumLiteral; +import org.eclipse.emf.ecore.EGenericType; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EOperation; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EParameter; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.ETypeParameter; +import org.eclipse.emf.ecore.ETypedElement; +import org.eclipse.emf.ecore.EcorePackage; +import org.eclipse.emf.ecore.util.EcoreUtil; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreBaseVisitor; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.BodyContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.DerivationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EAnnotationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EAttributeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EClassContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EClassifierContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EDataTypeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EEnumContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EEnumLiteralContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericElementTypeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericExceptionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericSuperTypeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericTypeArgumentContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericTypeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericWildcardContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EModelElementContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EModelElementRefContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EMultiplicityContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ENamedElementContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EOperationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EPackageContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EParameterContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EPrimitiveTypeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EReferenceContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EStructuralFeatureContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ETypeParameterContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ETypedElementContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ExpressionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.FormulaContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.InitialContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.InvariantContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ModelContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.OptionsContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.PackageImportContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.PathNameContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.PostconditionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.PreconditionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.TemplateSignatureContext; +import eu.modelwriter.core.alloyinecore.ui.mapping.AIEConstants; +import eu.modelwriter.core.alloyinecore.ui.mapping.AnnotationSources; + +public class CS2ASMapping extends AlloyInEcoreBaseVisitor { + + private Stack qualifiedNameStack; + private CS2ASRepository repository; + private CS2ASInitializer initializer; + private String fileInput; + private boolean anySyntacticError; + + private void init() { + qualifiedNameStack = new Stack<>(); + repository = new CS2ASRepository(); + initializer = new CS2ASInitializer(repository); + pc = 0; + cc = 0; + ac = 0; + rc = 0; + oc = 0; + dtc = 0; + ec = 0; + tpc = 0; + } + + /** + * + * @param fileInput : alloy in ecore program input. + * @param savePath : save location for ecore file. + */ + public void parseAndSave(final String fileInput, final URI saveURI) { + init(); + + this.fileInput = fileInput; + anySyntacticError = false; + + final ANTLRInputStream inputStream = new ANTLRInputStream(fileInput); + final AlloyInEcoreLexer lexer = new AlloyInEcoreLexer(inputStream); + final CommonTokenStream tokens = new CommonTokenStream(lexer); + final AlloyInEcoreParser parser = new AlloyInEcoreParser(tokens, saveURI); + parser.addErrorListener(new BaseErrorListener() { + @Override + public void syntaxError(final Recognizer recognizer, final Object offendingSymbol, + final int line, final int charPositionInLine, final String msg, + final RecognitionException e) { + anySyntacticError = true; + } + }); + final ParseTree tree = parser.model(); + + // load old ecore root. + final EModelElement oldRoot = (EModelElement) repository.loadAndClearAIEResource(saveURI); + + initializer.initialize(tree); + try { + visit(tree); + + if (anySyntacticError) { + throw new Exception(); + } + + // if there is not any parse error, + // then remove old source annotation and finally save ecore. + repository.getRootPackage().getEAnnotations() + .removeIf(ea -> ea.getSource().equals(AnnotationSources.SOURCE)); + + repository.saveResource(repository.getRootPackage(), saveURI); + } catch (final Exception e) { + // if there exists any parse error, + // then save aie source as annotation. + + // first remove old source annotation from old ecore root. + oldRoot.getEAnnotations().removeIf(ea -> ea.getSource().equals(AnnotationSources.SOURCE)); + + // add new source annotation to old ecore root and finally save old ecore. + final EAnnotation sourceAnnotation = createEAnnotation(AnnotationSources.SOURCE); + sourceAnnotation.getDetails().put(AIEConstants.SOURCE.toString(), fileInput); + oldRoot.getEAnnotations().add(sourceAnnotation); + + repository.saveResource(oldRoot, saveURI); + } + } + + @Override + public Object visitModel(final ModelContext ctx) { + final List importAnnotations = new ArrayList<>(); + ctx.ownedPackageImport.forEach(opi -> { + final EAnnotation importAnnotation = visitPackageImport(opi); + importAnnotations.add(importAnnotation); + }); + + if (ctx.ownedPackage != null) { + visitEPackage(ctx.ownedPackage); + } + + if (ctx.options() != null) { + final EAnnotation optionsAnnotation = visitOptions(ctx.options()); + repository.getRootPackage().getEAnnotations().add(optionsAnnotation); + } + + if (ctx.identifier() != null) { + final EAnnotation moduleAnnotation = createEAnnotation(AnnotationSources.MODULE); + if (ctx.name != null) { + moduleAnnotation.getDetails().put(AIEConstants.NAME.toString(), ctx.name.getText()); + } + repository.getRootPackage().getEAnnotations().add(moduleAnnotation); + } + + repository.getRootPackage().getEAnnotations().addAll(importAnnotations); + + // final Diagnostic diagnostic = Diagnostician.INSTANCE.validate(repository.getRootPackage()); + // visitDiagnostic(diagnostic); + + return null; + } + + // private int level = 0; + + // public void visitDiagnostic(final Diagnostic diagnostic) throws Exception { + // level++; + // if (diagnostic.getSeverity() == Diagnostic.ERROR) { + // System.err.println("(lvl:" + level + ")source : " + diagnostic.getSource()); + // System.err.println("(lvl:" + level + ")message: " + diagnostic.getMessage()); + // diagnostic.getData().forEach(d -> { + // System.err.println(d.toString()); + // }); + // } + // diagnostic.getChildren().forEach(c -> { + // visitDiagnostic(c); + // }); + // level--; + // } + + @Override + public EAnnotation visitOptions(final OptionsContext ctx) { + final EAnnotation optionsAnnotation = createEAnnotation(AnnotationSources.OPTIONS); + if (ctx.option() != null) { + ctx.option().forEach(o -> { + String key = null; // key of option + if (o.getChild(0) != null) { + key = o.getChild(0).getText(); + } + String value = null; // value of option + if (o.getChild(2) != null) { + value = o.getChild(2).getText(); + } + optionsAnnotation.getDetails().put(key, value); + }); + } + + return optionsAnnotation; + } + + @Override + public EAnnotation visitPackageImport(final PackageImportContext ctx) { + String name = null; + if (ctx.name != null) { + name = ctx.name.getText(); + } + String path = null; + if (ctx.ownedPathName != null) { + path = ctx.ownedPathName.getText().replace("'", ""); + } + + final EAnnotation importAnnotation = createEAnnotation(AnnotationSources.IMPORT); + importAnnotation.getDetails().put(name, path); + + return importAnnotation; + } + + private int pc = 0; + + @Override + public EPackage visitEPackage(final EPackageContext ctx) { + String name = "package" + ++pc; + if (ctx.name != null) { + name = ctx.name.getText(); + } + qualifiedNameStack.push(name); + final EPackage ePackage = (EPackage) repository.getEObject(qualifiedNameStack); + + if (ctx.visibility != null) { + final EAnnotation visibilityAnnotation = createEAnnotation(AnnotationSources.VISIBILITY); + visibilityAnnotation.getDetails().put(AIEConstants.VISIBILITY.toString(), + ctx.visibility.getText()); + ePackage.getEAnnotations().add(visibilityAnnotation); + } // DEFAULT PACKAGE + + if (ctx.nsPrefix != null) { + final String nsPrefix = ctx.nsPrefix.getText(); + ePackage.setNsPrefix(nsPrefix); + } + + if (ctx.nsURI != null) { + final String nsURI = ctx.nsURI.getText().replace("'", ""); + ePackage.setNsURI(nsURI); + } + + if (ctx.ownedAnnotations != null) { + ctx.ownedAnnotations.forEach(oa -> { + final EAnnotation eAnnotation = visitEAnnotation(oa); + ePackage.getEAnnotations().add(eAnnotation); + }); + } + + if (ctx.eSubPackages != null) { + ctx.eSubPackages.forEach(esp -> { + visitEPackage(esp); + }); + } + + if (ctx.eClassifiers != null) { + ctx.eClassifiers.forEach(ec -> { + visitEClassifier(ec); + }); + } + + if (ctx.eConstraints != null) { + ctx.eConstraints.forEach(ec -> { + final EAnnotation invariantAnnotation = visitInvariant(ec); + ePackage.getEAnnotations().add(invariantAnnotation); + }); + } + + if (ctx.name == null) { + ePackage.setName(null); + } + + qualifiedNameStack.pop(); + return ePackage; + } + + @Override + public EClassifier visitEClassifier(final EClassifierContext ctx) { + if (ctx.eClass != null) { + return visitEClass(ctx.eClass); + } + if (ctx.eDataType != null) { + return visitEDataType(ctx.eDataType); + } + if (ctx.eEnum != null) { + return visitEEnum(ctx.eEnum); + } + return null; + } + + private int cc = 0; + + @Override + public EClass visitEClass(final EClassContext ctx) { + String name = "class" + ++cc; + if (ctx.name != null) { + name = ctx.name.getText(); + } + qualifiedNameStack.push(name); + final EClass eClass = (EClass) repository.getEObject(qualifiedNameStack); + + if (ctx.visibility != null) { + final EAnnotation visibilityAnnotation = createEAnnotation(AnnotationSources.VISIBILITY); + visibilityAnnotation.getDetails().put(AIEConstants.VISIBILITY.toString(), + ctx.visibility.getText()); + eClass.getEAnnotations().add(visibilityAnnotation); + } // DEFAULT PACKAGE + + final boolean isInterface = ctx.isInterface != null ? true : false; + // DEFAULT FALSE + eClass.setInterface(isInterface); + + final boolean isAbstract = ctx.isAbstract != null ? true : isInterface ? true : false; + // DEFAULT FALSE + eClass.setAbstract(isAbstract); + + if (ctx.ownedSignature != null) { + final List eTypeParameters = visitTemplateSignature(ctx.ownedSignature); + eClass.getETypeParameters().addAll(eTypeParameters); + } + + if (ctx.eSuperTypes != null) { + ctx.eSuperTypes.forEach(est -> { + final EGenericType superType = visitEGenericSuperType(est); + if (superType != null) { + eClass.getEGenericSuperTypes().add(superType); + } + }); + } + + if (ctx.instanceClassName != null) { + final String instanceClassName = ctx.instanceClassName.getText().replace("'", ""); + eClass.setInstanceClassName(instanceClassName); + } + + if (ctx.ownedAnnotations != null) { + ctx.ownedAnnotations.forEach(oa -> { + final EAnnotation eAnnotation = visitEAnnotation(oa); + eClass.getEAnnotations().add(eAnnotation); + }); + } + + if (ctx.eOperations != null) { + ctx.eOperations.forEach(eo -> { + final EOperation eOperation = visitEOperation(eo); + if (eOperation != null) { + final Iterator iterator = eClass.getEOperations().iterator(); + while (iterator.hasNext()) { + final EOperation o = iterator.next(); + if (EcoreUtil.equals(o, eOperation)) { + iterator.remove(); + // we create operation in OperationInitializer. So we should replace with new one. + break; + } + } + eClass.getEOperations().add(eOperation); + } + }); + } + + if (ctx.eStructuralFeatures != null) { + ctx.eStructuralFeatures.forEach(esf -> { + visitEStructuralFeature(esf); + }); + } + + if (ctx.eConstraints != null) { + ctx.eConstraints.forEach(ec -> { + final EAnnotation invariantAnnotation = visitInvariant(ec); + eClass.getEAnnotations().add(invariantAnnotation); + }); + } + + if (ctx.name == null) { + eClass.setName(null); + } + + qualifiedNameStack.pop(); + return eClass; + } + + @Override + public EStructuralFeature visitEStructuralFeature(final EStructuralFeatureContext ctx) { + if (ctx.eAttribute != null) { + return visitEAttribute(ctx.eAttribute); + } + if (ctx.eReference != null) { + return visitEReference(ctx.eReference); + } + return null; + } + + private int ac = 0; + + @Override + public EAttribute visitEAttribute(final EAttributeContext ctx) { + String name = "attribute" + ++ac; + if (ctx.name != null) { + name = ctx.name.getText(); + } + qualifiedNameStack.push(name); + final EAttribute eAttribute = (EAttribute) repository.getEObject(qualifiedNameStack); + qualifiedNameStack.pop(); + + if (ctx.visibility != null) { + final EAnnotation visibilityAnnotation = createEAnnotation(AnnotationSources.VISIBILITY); + visibilityAnnotation.getDetails().put(AIEConstants.VISIBILITY.toString(), + ctx.visibility.getText()); + eAttribute.getEAnnotations().add(visibilityAnnotation); + } // DEFAULT PACKAGE + + if (ctx.eAttributeType != null) { + final EGenericType eGenericType = visitEGenericElementType(ctx.eAttributeType); + if (eGenericType != null) { + eAttribute.setEGenericType(eGenericType); + } + } + + if (ctx.ownedMultiplicity != null) { + final int[] multiplicity = visitEMultiplicity(ctx.ownedMultiplicity); + eAttribute.setLowerBound(multiplicity[0]); + eAttribute.setUpperBound(multiplicity[1]); + if (isCollection(eAttribute, ctx.ownedMultiplicity)) { + final EAnnotation nullableAnnotation = createEAnnotation(AnnotationSources.NULLABLE); + // DEFAULT NULL + eAttribute.getEAnnotations().add(nullableAnnotation); + } + } else { // DEFAULT 1..1 + eAttribute.setLowerBound(1); + eAttribute.setUpperBound(1); + } + + if (ctx.defaultValue != null) { + final String defaultValue = ctx.defaultValue.getText().replace("'", ""); + eAttribute.setDefaultValueLiteral(defaultValue); + } // DEFAULT NULL + + if (ctx.ownedAnnotations != null) { + ctx.ownedAnnotations.forEach(oa -> { + final EAnnotation eAnnotation = visitEAnnotation(oa); + eAttribute.getEAnnotations().add(eAnnotation); + }); + } + + if (ctx.ownedInitial != null) { + final EAnnotation initialAnnotation = visitInitial(ctx.ownedInitial); + eAttribute.getEAnnotations().add(initialAnnotation); + } + + if (ctx.ownedDerivation != null) { + final EAnnotation derivedAnnotation = visitDerivation(ctx.ownedDerivation); + eAttribute.getEAnnotations().add(derivedAnnotation); + } + + eAttribute.setOrdered(false); + if (ctx.qualifier != null) { + for (final String q : ctx.qualifier.stream().map(Token::getText).distinct() + .collect(Collectors.toList())) { + switch (AIEConstants.getValue(q)) { + case STATIC: + final EAnnotation staticAnnotation = createEAnnotation(AnnotationSources.STATIC); + // DEFAULT NULL + eAttribute.getEAnnotations().add(staticAnnotation); + break; + case MODEL: + final EAnnotation modelAnnotation = createEAnnotation(AnnotationSources.MODEL); + // DEFAULT NULL + eAttribute.getEAnnotations().add(modelAnnotation); + break; + case GHOST: + final EAnnotation ghostAnnotation = createEAnnotation(AnnotationSources.GHOST); + // DEFAULT NULL + eAttribute.getEAnnotations().add(ghostAnnotation); + break; + case TRANSIENT: + // DEFAULT FALSE + eAttribute.setTransient(true); + break; + case VOLATILE: + // DEFAULT FALSE + eAttribute.setVolatile(true); + break; + case READONLY: + // DEFAULT FALSE + // readonly is opposite of changeable. so reverse the logic. + eAttribute.setChangeable(false); + break; + case DERIVED: + // DEFAULT FALSE + eAttribute.setDerived(true); + break; + case ORDERED: + int u = eAttribute.getUpperBound(); + if (u > 1 || u == -1) { + // DEFAULT FALSE + eAttribute.setOrdered(true); + } + break; + case NOT_UNIQUE: + u = eAttribute.getUpperBound(); + if (u > 1 || u == -1) { + // DEFAULT TRUE + eAttribute.setUnique(false); + } + break; + case UNSETTABLE: + // DEFAULT FALSE + eAttribute.setUnsettable(true); + break; + case ID: + // DEFAULT FALSE + eAttribute.setID(true); + break; + default: + break; + } + } + } + + if (ctx.name == null) { + eAttribute.setName(null); + } + + return eAttribute; + } + + private int rc = 0; + + @Override + public EReference visitEReference(final EReferenceContext ctx) { + String name = "reference" + ++rc; + if (ctx.name != null) { + name = ctx.name.getText(); + } + qualifiedNameStack.push(name); + final EReference eReference = (EReference) repository.getEObject(qualifiedNameStack); + qualifiedNameStack.pop(); + + if (ctx.visibility != null) { + final EAnnotation visibilityAnnotation = createEAnnotation(AnnotationSources.VISIBILITY); + visibilityAnnotation.getDetails().put(AIEConstants.VISIBILITY.toString(), + ctx.visibility.getText()); + eReference.getEAnnotations().add(visibilityAnnotation); + } // DEFAULT PACKAGE + + if (ctx.eReferenceType != null) { + final EGenericType eGenericType = visitEGenericElementType(ctx.eReferenceType); + // TODO should be visitEGenericType(ctx.eReferenceType)! + if (eGenericType != null) { + eReference.setEGenericType(eGenericType); + } + } + + if (ctx.ownedMultiplicity != null) { + final int[] multiplicity = visitEMultiplicity(ctx.ownedMultiplicity); + eReference.setLowerBound(multiplicity[0]); + eReference.setUpperBound(multiplicity[1]); + if (isCollection(eReference, ctx.ownedMultiplicity)) { + final EAnnotation nullableAnnotation = createEAnnotation(AnnotationSources.NULLABLE); + // DEFAULT NULL + eReference.getEAnnotations().add(nullableAnnotation); + } + } else { // DEFAULT 1..1 + eReference.setLowerBound(1); + eReference.setUpperBound(1); + } + + final EClassifier eType = eReference.getEType(); + if (ctx.eOpposite != null) { + final String oppositeName = ctx.eOpposite.getText(); + final EReference eOpposite = (EReference) EcoreUtil.getEObject(eType, oppositeName); + if (eOpposite != null) { + eReference.setEOpposite(eOpposite); + eOpposite.setEOpposite(eReference); + } + } + + if (ctx.defaultValue != null) { + final String defaultValue = ctx.defaultValue.getText().replace("'", ""); + eReference.setDefaultValueLiteral(defaultValue); + } // DEFAULT NULL + + if (ctx.referredKeys != null) { + ctx.referredKeys.forEach(rk -> { + final String attributeName = rk.getText(); + final EAttribute eAttribute = (EAttribute) EcoreUtil.getEObject(eType, attributeName); + if (eAttribute != null) { + eReference.getEKeys().add(eAttribute); + } + }); + } + + if (ctx.ownedAnnotations != null) { + ctx.ownedAnnotations.forEach(oa -> { + final EAnnotation eAnnotation = visitEAnnotation(oa); + eReference.getEAnnotations().add(eAnnotation); + }); + } + + if (ctx.ownedInitial != null) { + final EAnnotation initialAnnotation = visitInitial(ctx.ownedInitial); + eReference.getEAnnotations().add(initialAnnotation); + } + + if (ctx.ownedDerivation != null) { + final EAnnotation derivedAnnotation = visitDerivation(ctx.ownedDerivation); + eReference.getEAnnotations().add(derivedAnnotation); + } + + eReference.setOrdered(false); + if (ctx.qualifier != null) { + for (final String q : ctx.qualifier.stream().map(Token::getText).distinct() + .collect(Collectors.toList())) { + switch (AIEConstants.getValue(q)) { + case STATIC: + final EAnnotation staticAnnotation = createEAnnotation(AnnotationSources.STATIC); + // DEFAULT NULL + eReference.getEAnnotations().add(staticAnnotation); + break; + case MODEL: + final EAnnotation modelAnnotation = createEAnnotation(AnnotationSources.MODEL); + // DEFAULT NULL + eReference.getEAnnotations().add(modelAnnotation); + break; + case GHOST: + final EAnnotation ghostAnnotation = createEAnnotation(AnnotationSources.GHOST); + // DEFAULT NULL + eReference.getEAnnotations().add(ghostAnnotation); + break; + case TRANSIENT: + // DEFAULT FALSE + eReference.setTransient(true); + break; + case VOLATILE: + // DEFAULT FALSE + eReference.setVolatile(true); + break; + case READONLY: + // DEFAULT FALSE + // readonly is opposite of changeable. so reverse the logic. + eReference.setChangeable(false); + break; + case DERIVED: + // DEFAULT FALSE + eReference.setDerived(true); + break; + case ORDERED: + int u = eReference.getUpperBound(); + if (u > 1 || u == -1) { + // DEFAULT FALSE + eReference.setOrdered(true); + } + break; + case NOT_UNIQUE: + u = eReference.getUpperBound(); + if (u > 1 || u == -1) { + // DEFAULT TRUE + eReference.setUnique(false); + } + break; + case COMPOSES: + // DEFAULT FALSE + eReference.setContainment(true); + break; + case NOT_RESOLVE: + // DEFAULT TRUE + eReference.setResolveProxies(false); + break; + case UNSETTABLE: + // DEFAULT FALSE + eReference.setUnsettable(true); + break; + default: + break; + } + } + } + + if (ctx.name == null) { + eReference.setName(null); + } + + return eReference; + } + + private int oc = 0; + + @Override + public EOperation visitEOperation(final EOperationContext ctx) { + String name = "operation" + ++oc; + if (ctx.name != null) { + name = ctx.name.getText(); + } + qualifiedNameStack.push(name); + final EOperation eOperation = (EOperation) repository.getEObject(qualifiedNameStack); + + if (ctx.ownedSignature != null) { + final List eTypeParameters = visitTemplateSignature(ctx.ownedSignature); + eOperation.getETypeParameters().addAll(eTypeParameters); + } + + qualifiedNameStack.pop(); + + if (ctx.visibility != null) { + final EAnnotation visibilityAnnotation = createEAnnotation(AnnotationSources.VISIBILITY); + visibilityAnnotation.getDetails().put(AIEConstants.VISIBILITY.toString(), + ctx.visibility.getText()); + eOperation.getEAnnotations().add(visibilityAnnotation); + } // DEFAULT PACKAGE + + if (ctx.eParameters != null) { + ctx.eParameters.forEach(ep -> { + final EParameter eParameter = visitEParameter(ep); + eOperation.getEParameters().add(eParameter); + }); + } + + if (ctx.ownedMultiplicity != null) { + final int[] multiplicity = visitEMultiplicity(ctx.ownedMultiplicity); + eOperation.setLowerBound(multiplicity[0]); + eOperation.setUpperBound(multiplicity[1]); + if (isCollection(eOperation, ctx.ownedMultiplicity)) { + final EAnnotation nullableAnnotation = createEAnnotation(AnnotationSources.NULLABLE); + // DEFAULT NULL + eOperation.getEAnnotations().add(nullableAnnotation); + } + } else { // DEFAULT 1..1 + eOperation.setLowerBound(1); + eOperation.setUpperBound(1); + } + + if (ctx.eReturnType != null) { + final EGenericType eGenericType = visitEGenericElementType(ctx.eReturnType); + if (eGenericType != null) { + eOperation.setEGenericType(eGenericType); + } + } + + if (ctx.ownedException != null) { + ctx.ownedException.forEach(oe -> { + final EGenericType eException = visitEGenericException(oe); + if (eException != null) { + eOperation.getEGenericExceptions().add(eException); + } + }); + } + + if (ctx.ownedAnnotations != null) { + ctx.ownedAnnotations.forEach(oa -> { + final EAnnotation eAnnotation = visitEAnnotation(oa); + eOperation.getEAnnotations().add(eAnnotation); + }); + } + + if (ctx.ownedPreconditions != null) { + ctx.ownedPreconditions.forEach(opc -> { + final EAnnotation preconditionAnnotation = visitPrecondition(opc); + eOperation.getEAnnotations().add(preconditionAnnotation); + }); + } + + if (ctx.ownedBodyExpression != null) { + ctx.ownedBodyExpression.forEach(obe -> { + final EAnnotation bodyAnnotation = visitBody(obe); + eOperation.getEAnnotations().add(bodyAnnotation); + }); + } + + if (ctx.ownedPostconditions != null) { + ctx.ownedPostconditions.forEach(opc -> { + final EAnnotation postconditionAnnotation = visitPostcondition(opc); + eOperation.getEAnnotations().add(postconditionAnnotation); + }); + } + + eOperation.setOrdered(false); + if (ctx.eReturnType != null) { + if (ctx.qualifier != null) { + for (final String q : ctx.qualifier.stream().map(Token::getText).distinct() + .collect(Collectors.toList())) { + switch (AIEConstants.getValue(q)) { + case STATIC: + final EAnnotation staticAnnotation = createEAnnotation(AnnotationSources.STATIC); + // DEFAULT NULL + eOperation.getEAnnotations().add(staticAnnotation); + break; + case ORDERED: + int u = eOperation.getUpperBound(); + if (u > 1 || u == -1) { + // DEFAULT FALSE + eOperation.setOrdered(true); + } + break; + case NOT_UNIQUE: + u = eOperation.getUpperBound(); + if (u > 1 || u == -1) { + // DEFAULT TRUE + eOperation.setUnique(false); + } + break; + default: + break; + } + } + } + } + + if (ctx.name == null) { + eOperation.setName(null); + } + + return eOperation; + } + + @Override + public EGenericType visitEGenericException(final EGenericExceptionContext ctx) { + if (ctx.eGenericType != null) { + return visitEGenericType(ctx.eGenericType); + } + return null; + } + + @Override + public EGenericType visitEGenericSuperType(final EGenericSuperTypeContext ctx) { + if (ctx.eGenericType != null) { + return visitEGenericType(ctx.eGenericType); + } + return null; + } + + @Override + public EParameter visitEParameter(final EParameterContext ctx) { + final EParameter eParameter = repository.factory.createEParameter(); + + if (ctx.name != null) { + final String name = ctx.name.getText(); + eParameter.setName(name); + } + + if (ctx.eParameterType != null) { + final EGenericType eGenericType = visitEGenericElementType(ctx.eParameterType); + if (eGenericType != null) { + eParameter.setEGenericType(eGenericType); + } + } + + if (ctx.ownedMultiplicity != null) { + final int[] multiplicity = visitEMultiplicity(ctx.ownedMultiplicity); + eParameter.setLowerBound(multiplicity[0]); + eParameter.setUpperBound(multiplicity[1]); + if (isCollection(eParameter, ctx.ownedMultiplicity)) { + final EAnnotation nullableAnnotation = createEAnnotation(AnnotationSources.NULLABLE); + // DEFAULT NULL + eParameter.getEAnnotations().add(nullableAnnotation); + } + } else { // DEFAULT 1..1 + eParameter.setLowerBound(1); + eParameter.setUpperBound(1); + } + + if (ctx.ownedAnnotations != null) { + ctx.ownedAnnotations.forEach(oa -> { + final EAnnotation eAnnotation = visitEAnnotation(oa); + eParameter.getEAnnotations().add(eAnnotation); + }); + } + + eParameter.setOrdered(false); + if (ctx.qualifier != null) { + for (final String q : ctx.qualifier.stream().map(Token::getText).distinct() + .collect(Collectors.toList())) { + switch (AIEConstants.getValue(q)) { + case ORDERED: + int u = eParameter.getUpperBound(); + if (u > 1 || u == -1) { + // DEFAULT FALSE + eParameter.setOrdered(true); + } + break; + case NOT_UNIQUE: + u = eParameter.getUpperBound(); + if (u > 1 || u == -1) { + // DEFAULT TRUE + eParameter.setUnique(false); + } + break; + default: + break; + } + } + } + + return eParameter; + } + + @Override + public int[] visitEMultiplicity(final EMultiplicityContext ctx) { + int lower = 1; + int upper = 1; + if (ctx.stringBound != null) { + final String stringBound = ctx.stringBound.getText(); + switch (stringBound) { + case "*": + lower = 0; + upper = -1; + break; + case "+": + lower = 1; + upper = -1; + break; + case "?": + lower = 0; + upper = 1; + break; + default: + break; + } + } else { + if (ctx.lowerBound != null) { + lower = Integer.valueOf(ctx.lowerBound.getText()); + } + if (ctx.upperBound != null) { + if (ctx.upperBound.getText().equals("*")) { + upper = -1; + } else { + upper = Integer.valueOf(ctx.upperBound.getText()); + } + } else { + upper = lower; + } + } + // TODO ('|?' | isNullFree= '|1')? nullfree annotation will be added. + return new int[] {lower, upper}; + } + + private int dtc = 0; + + @Override + public EDataType visitEDataType(final EDataTypeContext ctx) { + String name = "datatype" + ++dtc; + if (ctx.name != null) { + name = ctx.name.getText(); + } + qualifiedNameStack.push(name); + final EDataType eDataType = (EDataType) repository.getEObject(qualifiedNameStack); + + if (ctx.visibility != null) { + final EAnnotation visibilityAnnotation = createEAnnotation(AnnotationSources.VISIBILITY); + visibilityAnnotation.getDetails().put(AIEConstants.VISIBILITY.toString(), + ctx.visibility.getText()); + eDataType.getEAnnotations().add(visibilityAnnotation); + } // DEFAULT PACKAGE + + if (ctx.ownedSignature != null) { + final List eTypeParameters = visitTemplateSignature(ctx.ownedSignature); + eDataType.getETypeParameters().addAll(eTypeParameters); + } + + if (ctx.instanceClassName != null) { + final String instanceClassName = ctx.instanceClassName.getText().replace("'", ""); + eDataType.setInstanceClassName(instanceClassName); + } + + if (ctx.ownedAnnotations != null) { + ctx.ownedAnnotations.forEach(oa -> { + final EAnnotation eAnnotation = visitEAnnotation(oa); + eDataType.getEAnnotations().add(eAnnotation); + }); + } + + if (ctx.ownedConstraints != null) { + ctx.ownedConstraints.forEach(oc -> { + final EAnnotation invariantAnnotation = visitInvariant(oc); + eDataType.getEAnnotations().add(invariantAnnotation); + }); + } + + if (ctx.qualifier != null) { + for (final String q : ctx.qualifier.stream().map(Token::getText).distinct() + .collect(Collectors.toList())) { + switch (AIEConstants.getValue(q)) { + case PRIMITIVE: + final EAnnotation primitiveAnnotation = + createEAnnotation(AnnotationSources.DATATYPE_PRIMITIVE); + // DEFAULT NULL + eDataType.getEAnnotations().add(primitiveAnnotation); + break; + case NOT_SERIALIZABLE: + // DEFAULT TRUE. + eDataType.setSerializable(false); + break; + default: + break; + } + } + } + + if (ctx.name == null) { + eDataType.setName(null); + } + + qualifiedNameStack.pop(); + return eDataType; + } + + private int ec = 0; + + @Override + public EEnum visitEEnum(final EEnumContext ctx) { + String name = "enum" + ++ec; + if (ctx.name != null) { + name = ctx.name.getText(); + } + qualifiedNameStack.push(name); + final EEnum eEnum = (EEnum) repository.getEObject(qualifiedNameStack); + + if (ctx.visibility != null) { + final EAnnotation visibilityAnnotation = createEAnnotation(AnnotationSources.VISIBILITY); + visibilityAnnotation.getDetails().put(AIEConstants.VISIBILITY.toString(), + ctx.visibility.getText()); + eEnum.getEAnnotations().add(visibilityAnnotation); + } // DEFAULT PACKAGE + + if (ctx.ownedSignature != null) { + final List eTypeParameters = visitTemplateSignature(ctx.ownedSignature); + eEnum.getETypeParameters().addAll(eTypeParameters); + } + + if (ctx.instanceClassName != null) { + final String instanceClassName = ctx.instanceClassName.getText().replace("'", ""); + eEnum.setInstanceClassName(instanceClassName); + } + + if (ctx.ownedAnnotations != null) { + ctx.ownedAnnotations.forEach(oa -> { + final EAnnotation eAnnotation = visitEAnnotation(oa); + eEnum.getEAnnotations().add(eAnnotation); + }); + } + + if (ctx.ownedLiteral != null) { + ctx.ownedLiteral.forEach(l -> { + final EEnumLiteral eEnumLiteral = visitEEnumLiteral(l); + eEnum.getELiterals().add(eEnumLiteral); + }); + } + + if (ctx.ownedConstraint != null) { + ctx.ownedConstraint.forEach(oc -> { + final EAnnotation invariantAnnotation = visitInvariant(oc); + eEnum.getEAnnotations().add(invariantAnnotation); + }); + } + + if (ctx.qualifier != null) { + for (final String q : ctx.qualifier.stream().map(Token::getText).distinct() + .collect(Collectors.toList())) { + switch (AIEConstants.getValue(q)) { + case NOT_SERIALIZABLE: + // DEFAULT TRUE. + eEnum.setSerializable(false); + break; + default: + break; + } + } + } + + if (ctx.name == null) { + eEnum.setName(null); + } + + qualifiedNameStack.pop(); + return eEnum; + } + + @Override + public EEnumLiteral visitEEnumLiteral(final EEnumLiteralContext ctx) { + final EEnumLiteral eEnumLiteral = repository.factory.createEEnumLiteral(); + + if (ctx.name != null) { + final String name = ctx.name.getText(); + eEnumLiteral.setName(name); + } + + if (ctx.value != null) { + final int value = Integer.parseInt(ctx.value.getText()); + eEnumLiteral.setValue(value); + } + + if (ctx.ownedAnnotations != null) { + ctx.ownedAnnotations.forEach(oa -> { + final EAnnotation eAnnotation = visitEAnnotation(oa); + eEnumLiteral.getEAnnotations().add(eAnnotation); + }); + } + + return eEnumLiteral; + } + + @Override + public EAnnotation visitEAnnotation(final EAnnotationContext ctx) { + final String source = ctx.source != null ? ctx.source.getText().replace("'", "") : null; + final EAnnotation eAnnotation = createEAnnotation(source); + + if (ctx.ownedDetails != null) { + ctx.ownedDetails.forEach(od -> { + final String key = od.key != null ? od.key.getText().replace("'", "") : null; + final String value = od.value != null ? od.value.getText().replace("'", "") : null; + eAnnotation.getDetails().put(key, value); + }); + } + + if (ctx.ownedAnnotations != null) { + ctx.ownedAnnotations.forEach(oa -> { + final EAnnotation ownedAnnoation = visitEAnnotation(oa); + eAnnotation.getEAnnotations().add(ownedAnnoation); + }); + } + + if (ctx.ownedContents != null) { + ctx.ownedContents.forEach(oc -> { + final EModelElement eModelElement = visitEModelElement(oc); + eAnnotation.getContents().add(eModelElement); + }); + } + + if (ctx.ownedReferences != null) { + ctx.ownedReferences.forEach(or -> { + final EObject eModelElementRef = visitEModelElementRef(or); + if (eModelElementRef != null) { + eAnnotation.getReferences().add(eModelElementRef); + } + }); + } + + return eAnnotation; + } + + private EAnnotation createEAnnotation(final String source) { + final EAnnotation eAnnotation = repository.factory.createEAnnotation(); + + eAnnotation.setSource(source); + + return eAnnotation; + } + + @Override + public EModelElement visitEModelElement(final EModelElementContext ctx) { + if (ctx.eAnnotation != null) { + return visitEAnnotation(ctx.eAnnotation); + } + if (ctx.eNamedElement != null) { + return visitENamedElement(ctx.eNamedElement); + } + return null; + } + + @Override + public ENamedElement visitENamedElement(final ENamedElementContext ctx) { + if (ctx.eTypedElement != null) { + return visitETypedElement(ctx.eTypedElement); + } + if (ctx.eClassifier != null) { + return visitEClassifier(ctx.eClassifier); + } + if (ctx.ePackage != null) { + return visitEPackage(ctx.ePackage); + } + if (ctx.eEnumLiteral != null) { + return visitEEnumLiteral(ctx.eEnumLiteral); + } + return null; + } + + @Override + public ETypedElement visitETypedElement(final ETypedElementContext ctx) { + if (ctx.eOperation != null) { + return visitEOperation(ctx.eOperation); + } + if (ctx.eParameter != null) { + return visitEParameter(ctx.eParameter); + } + if (ctx.eStructuralFeature != null) { + return visitEStructuralFeature(ctx.eStructuralFeature); + } + return null; + } + + @Override + public EObject visitEModelElementRef(final EModelElementRefContext ctx) { + if (ctx.ownedPathName == null) { + return null; + } + return visitPathName(ctx.ownedPathName); + } + + @Override + public List visitTemplateSignature(final TemplateSignatureContext ctx) { + if (ctx.ownedTypeParameters == null) { + return new ArrayList<>(); + } + return ctx.ownedTypeParameters.stream().map(op -> visitETypeParameter(op)) + .collect(Collectors.toList()); + } + + private int tpc = 0; + + @Override + public ETypeParameter visitETypeParameter(final ETypeParameterContext ctx) { + String name = "typeparameter" + ++tpc; + if (ctx.name != null) { + name = ctx.name.getText(); + } + qualifiedNameStack.push(name); + final ETypeParameter eTypeParameter = + (ETypeParameter) repository.getEObject(qualifiedNameStack); + qualifiedNameStack.pop(); + + if (ctx.ownedEBounds != null) { + ctx.ownedEBounds.forEach(oe -> { + final EGenericType eBound = visitEGenericType(oe); + if (eBound != null) { + eTypeParameter.getEBounds().add(eBound); + } + }); + } + + if (ctx.name == null) { + eTypeParameter.setName(null); + } + + return eTypeParameter; + } + + @Override + public EGenericType visitEGenericTypeArgument(final EGenericTypeArgumentContext ctx) { + if (ctx.eGenericType != null) { + return visitEGenericType(ctx.eGenericType); + } + if (ctx.eGenericWildcard != null) { + return visitEGenericWildcard(ctx.eGenericWildcard); + } + return null; + } + + @Override + public EGenericType visitEGenericType(final EGenericTypeContext ctx) { + final EGenericType eGenericType = repository.factory.createEGenericType(); + + if (ctx.ownedPathName == null) { + return null; + } + + final EObject object = visitPathName(ctx.ownedPathName); + if (object instanceof EClassifier) { + eGenericType.setEClassifier((EClassifier) object); + } else if (object instanceof ETypeParameter) { + eGenericType.setETypeParameter((ETypeParameter) object); + } else { + return null; + } + + if (ctx.ownedETypeArguments != null) { + if (object instanceof EClassifier) { + ctx.ownedETypeArguments.forEach(eta -> { + final EGenericType eGenericTypeArgument = visitEGenericTypeArgument(eta); + if (eGenericTypeArgument != null) { + eGenericType.getETypeArguments().add(eGenericTypeArgument); + } + }); + } + } + + return eGenericType; + } + + @Override + public EGenericType visitEGenericElementType(final EGenericElementTypeContext ctx) { + if (ctx.eGenericType != null) { + return visitEGenericType(ctx.eGenericType); + } + if (ctx.ePrimitiveType != null) { + return visitEPrimitiveType(ctx.ePrimitiveType); + } + return null; + } + + @Override + public EGenericType visitEGenericWildcard(final EGenericWildcardContext ctx) { + final EGenericType eGenericType = repository.factory.createEGenericType(); + + if (ctx.ownedExtend != null) { + final EGenericType boundType = visitEGenericType(ctx.ownedExtend); + if (boundType != null) { + if (ctx.bound != null) { + if (ctx.bound.getText().equals("extends")) { + eGenericType.setEUpperBound(boundType); + } else if (ctx.bound.getText().equals("super")) { + eGenericType.setELowerBound(boundType); + } + } + } + } + + return eGenericType; + } + + @Override + public EObject visitPathName(final PathNameContext ctx) { + String rootElementName; + final List relativePathFragments = + new ArrayList<>(Arrays.asList(ctx.getText().split(AIEConstants.SEPARATOR))); + + if (repository.name2Import.containsKey(ctx.firstSegment.getText())) { // full path + rootElementName = ctx.firstSegment.getText(); + relativePathFragments.remove(0); // root is unnecessary. + + return repository.getEObject(rootElementName, relativePathFragments); + } else { // relative path + rootElementName = repository.getRootPackage().getName(); + + final List complementPathFragments = + qualifiedNameStack.stream().collect(Collectors.toList()); + complementPathFragments.remove(0); // root is unnecessary. + + // 1. trying to find inner reference (like reference to TypeParameter): + final List tempFragments = new ArrayList<>(relativePathFragments); + tempFragments.addAll(0, complementPathFragments); + final EObject result = repository.getEObject(rootElementName, tempFragments); + if (result != null) { + return result; + } + + // 2. trying to find outer reference (like reference to sibling et cetera.) + complementPathFragments.remove(complementPathFragments.size() - 1); + // first remove reference holder (last item of qualified name stack.). + relativePathFragments.addAll(0, complementPathFragments); + return repository.getEObject(rootElementName, relativePathFragments); + } + } + + @Override + public EGenericType visitEPrimitiveType(final EPrimitiveTypeContext ctx) { + EGenericType eGenericType = repository.factory.createEGenericType(); + switch (ctx.getText()) { + case "Boolean": // EBoolean + eGenericType.setEClassifier(EcorePackage.eINSTANCE.getEBoolean()); + break; + case "Integer": // EBigInteger + eGenericType.setEClassifier(EcorePackage.eINSTANCE.getEInt()); + break; + case "String": // EString + eGenericType.setEClassifier(EcorePackage.eINSTANCE.getEString()); + break; + case "Real": // EBigDecimal + eGenericType.setEClassifier(EcorePackage.eINSTANCE.getEBigDecimal()); + break; + case "UnlimitedNatural": // EBigInteger + eGenericType.setEClassifier(EcorePackage.eINSTANCE.getEBigInteger()); + break; + default: + eGenericType = null; + break; + } + return eGenericType; + } + + @Override + public EAnnotation visitBody(final BodyContext ctx) { + final String source = AnnotationSources.BODY; + final EAnnotation eAnnotation = createEAnnotation(source); + + if (ctx.name != null) { + final String name = ctx.name.getText(); + eAnnotation.getDetails().put(AIEConstants.NAME.toString(), name); + } + + if (ctx.ownedExpression != null) { + final String expression = visitExpression(ctx.ownedExpression); + eAnnotation.getDetails().put(AIEConstants.EXPRESSION.toString(), expression); + } + + return eAnnotation; + } + + @Override + public EAnnotation visitInvariant(final InvariantContext ctx) { + final String source = AnnotationSources.INVARIANT; + final EAnnotation eAnnotation = createEAnnotation(source); + + final Boolean isCallable = ctx.isCallable != null ? true : false; + eAnnotation.getDetails().put(AIEConstants.CALLABLE.toString(), isCallable.toString()); + + if (ctx.name != null) { + final String name = ctx.name.getText(); + eAnnotation.getDetails().put(AIEConstants.NAME.toString(), name); + } + + if (ctx.message != null) { + final String message = ctx.message.getText().replace("\"", ""); + eAnnotation.getDetails().put(AIEConstants.MESSAGE.toString(), message); + } + + if (ctx.ownedSpecification != null) { + final String formula = visitFormula(ctx.ownedSpecification); + eAnnotation.getDetails().put(AIEConstants.FORMULA.toString(), formula); + } + + return eAnnotation; + } + + @Override + public EAnnotation visitPrecondition(final PreconditionContext ctx) { + final String source = AnnotationSources.PRECONDITION; + final EAnnotation eAnnotation = createEAnnotation(source); + + if (ctx.name != null) { + final String name = ctx.name.getText(); + eAnnotation.getDetails().put(AIEConstants.NAME.toString(), name); + } + + if (ctx.message != null) { + final String message = ctx.message.getText().replace("\"", ""); + eAnnotation.getDetails().put(AIEConstants.MESSAGE.toString(), message); + } + + if (ctx.ownedSpecification != null) { + final String formula = visitFormula(ctx.ownedSpecification); + eAnnotation.getDetails().put(AIEConstants.FORMULA.toString(), formula); + } + + return eAnnotation; + } + + @Override + public EAnnotation visitPostcondition(final PostconditionContext ctx) { + final String source = AnnotationSources.POSTCONDITION; + final EAnnotation eAnnotation = createEAnnotation(source); + + if (ctx.name != null) { + final String name = ctx.name.getText(); + eAnnotation.getDetails().put(AIEConstants.NAME.toString(), name); + } + + if (ctx.message != null) { + final String message = ctx.message.getText().replace("\"", ""); + eAnnotation.getDetails().put(AIEConstants.MESSAGE.toString(), message); + } + + if (ctx.ownedSpecification != null) { + final String formula = visitFormula(ctx.ownedSpecification); + eAnnotation.getDetails().put(AIEConstants.FORMULA.toString(), formula); + } + + return eAnnotation; + } + + @Override + public EAnnotation visitInitial(final InitialContext ctx) { + final EAnnotation initialAnnotation = createEAnnotation(AnnotationSources.INITIAL); + + if (ctx.name != null) { + final String name = ctx.name.getText(); + initialAnnotation.getDetails().put(AIEConstants.NAME.toString(), name); + } + + if (ctx.ownedExpression != null) { + final String expression = visitExpression(ctx.ownedExpression); + initialAnnotation.getDetails().put(AIEConstants.EXPRESSION.toString(), expression); + } + + return initialAnnotation; + } + + @Override + public EAnnotation visitDerivation(final DerivationContext ctx) { + final EAnnotation derivedAnnotation = createEAnnotation(AnnotationSources.DERIVATION); + + if (ctx.name != null) { + final String name = ctx.name.getText(); + derivedAnnotation.getDetails().put(AIEConstants.NAME.toString(), name); + } + + if (ctx.ownedExpression != null) { + final String expression = visitExpression(ctx.ownedExpression); + derivedAnnotation.getDetails().put(AIEConstants.EXPRESSION.toString(), expression); + } + + return derivedAnnotation; + } + + public String visitExpression(final ExpressionContext ctx) { + if (ctx.start == null || ctx.stop == null) { + return ""; + } + return getTokenString(ctx.start.getStartIndex(), ctx.stop.getStopIndex() + 1); + } + + public String visitFormula(final FormulaContext ctx) { + if (ctx.start == null || ctx.stop == null) { + return ""; + } + return getTokenString(ctx.start.getStartIndex(), ctx.stop.getStopIndex() + 1); + } + + private String getTokenString(final int start, final int end) { + return fileInput.substring(start, end); + } + + private boolean isCollection(final ETypedElement element, final EMultiplicityContext ctx) { + return (element.getUpperBound() > 1 || element.getUpperBound() == -1) && ctx.nullable != null; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/cs2as/CS2ASRepository.java b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/cs2as/CS2ASRepository.java new file mode 100644 index 00000000..158a90b0 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/cs2as/CS2ASRepository.java @@ -0,0 +1,178 @@ +package eu.modelwriter.core.alloyinecore.ui.mapping.cs2as; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; +import java.util.stream.Collectors; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EcoreFactory; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; + +import eu.modelwriter.core.alloyinecore.ui.mapping.AIEImport; + +public class CS2ASRepository { + public final Map name2Import; + public final EcoreFactory factory; + public ResourceSetImpl resourceSet; + public Resource aieResource; + + /** + * folder path segments of {@link aieResource} + */ + private List relativeComplementerSegments; + + public CS2ASRepository() { + name2Import = new HashMap<>(); + factory = EcoreFactory.eINSTANCE; + resourceSet = new ResourceSetImpl(); + resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap() + .put(Resource.Factory.Registry.DEFAULT_EXTENSION, new XMIResourceFactoryImpl()); + } + + public EObject loadAndClearAIEResource(final URI uri) { + // try to get folder path of aieResource + relativeComplementerSegments = new ArrayList(uri.segmentsList()); + relativeComplementerSegments.remove(relativeComplementerSegments.size() - 1); + if (uri.scheme() != null && uri.scheme().equals("platform")) { + relativeComplementerSegments.remove(0); + } + + aieResource = resourceSet.createResource(uri); + try { + aieResource.load(null); + EObject rootElement = null; + if (!aieResource.getContents().isEmpty()) { + rootElement = aieResource.getContents().get(0); + } + aieResource.getContents().clear(); + return rootElement; + } catch (final IOException e) { + return null; + } + } + + /** + * if load resource is called recursively to try to complete relative path, it is true. else it is + * false. see {@link loadResource(String path)} + * + */ + private boolean isRelativePass = false; + + public Resource loadResource(String path) { + while (path.startsWith("../") && relativeComplementerSegments.size() > 0) { + // remove from path if starts with '../', and go up one directory + path = path.substring(3, path.length()); + relativeComplementerSegments.remove(relativeComplementerSegments.size() - 1); + } + while (path.startsWith("./")) { + // remove from path if starts with './' + path = path.substring(2, path.length()); + } + while (path.startsWith("/")) { + // remove from path if starts with '/' + path = path.substring(1, path.length()); + } + + Resource resource; + try { + // try to load with default URI + resource = resourceSet.getResource(URI.createURI(path, true), true); + if (resource.getContents().isEmpty()) { + throw new Exception(); + } + return resource; + } catch (final Exception e1) { + try { + // try to load with platform resource URI + resource = resourceSet.getResource(URI.createPlatformResourceURI(path, true), true); + if (resource.getContents().isEmpty()) { + throw new Exception(); + } + return resource; + } catch (final Exception e2) { + try { + // try to load with platform plugin URI + resource = resourceSet.getResource(URI.createPlatformPluginURI(path, true), true); + if (resource.getContents().isEmpty()) { + throw new Exception(); + } + return resource; + } catch (final Exception e3) { + try { + // try to load with file URI + resource = resourceSet.getResource(URI.createFileURI(path), true); + if (resource.getContents().isEmpty()) { + throw new Exception(); + } + return resource; + } catch (final Exception e4) { + try { + // if any URI that created from path couldn't be loaded + // then we could think that is it relative path? + // so, add 'folder path of aieResource' to beginning of the 'path' + // and complete relative 'path' to full 'path' + final List completedRelativePath = + new ArrayList(relativeComplementerSegments); + completedRelativePath.add(path); + // now we have full 'path' + // we can try to load resource again. + if (!isRelativePass) { + isRelativePass = true; + resource = loadResource(String.join("/", completedRelativePath)); + if (resource.getContents().isEmpty()) { + throw new Exception(); + } + isRelativePass = false; + return resource; + } else { + isRelativePass = false; + throw new Exception(); + } + } catch (final Exception e5) { + // path could not be loaded anyway. + return null; + } + } + } + } + } + } + + public void saveResource(final EObject root, final URI saveURI) { + final Resource resource = resourceSet.getResource(saveURI, true); + resource.getContents().clear(); + resource.getContents().add(root); + try { + resource.save(null); + } catch (final IOException e) { + e.printStackTrace(); + } + } + + public EObject getEObject(final Stack qualifiedNameStack) { + final List relativePathFragments = + qualifiedNameStack.stream().collect(Collectors.toList()); + relativePathFragments.remove(0); + + final String importName = qualifiedNameStack.get(0); + final AIEImport aIEImport = name2Import.get(importName); + return aIEImport.getElement(relativePathFragments); + } + + public EObject getEObject(final String importName, final List relativePathFragments) { + final AIEImport aIEImport = name2Import.get(importName); + return aIEImport.getElement(relativePathFragments); + } + + public EPackage getRootPackage() { + return (EPackage) aieResource.getContents().get(0); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/test/CS2ASMappingTest.java b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/test/CS2ASMappingTest.java new file mode 100644 index 00000000..615054d7 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/test/CS2ASMappingTest.java @@ -0,0 +1,163 @@ +package eu.modelwriter.core.alloyinecore.ui.mapping.test; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import eu.modelwriter.core.alloyinecore.ui.mapping.cs2as.CS2ASMapping; +import eu.modelwriter.core.alloyinecore.ui.mapping.cs2as.CS2ASRepository; + +public class CS2ASMappingTest { + + private CS2ASMapping mapper; + private CS2ASRepository repository; + + @Before + public void before() { + mapper = new CS2ASMapping(); + repository = new CS2ASRepository(); + } + + @Test + public void annotationTest() throws IOException { + final long millis = System.currentTimeMillis(); + + mapper.parseAndSave(getString("test/AnnotationTest.recore"), + URI.createFileURI("testTemp/AnnotationTestTemp.ecore")); + final EObject generated = loadResource("testTemp/AnnotationTestTemp.ecore"); + final EObject expected = loadResource("test/AnnotationTest.ecore"); + + Assert.assertTrue( + "AnnotationTest.ecore is not OK: " + (System.currentTimeMillis() - millis) + "ms.", + EcoreUtil.equals(generated, expected)); + } + + @Test + public void attributeTest() throws IOException { + final long millis = System.currentTimeMillis(); + + mapper.parseAndSave(getString("test/AttrTest.recore"), + URI.createFileURI("testTemp/AttrTestTemp.ecore")); + final EObject generated = loadResource("testTemp/AttrTestTemp.ecore"); + final EObject expected = loadResource("test/AttrTest.ecore"); + + Assert.assertTrue("AttrTest.ecore is not OK: " + (System.currentTimeMillis() - millis) + "ms.", + EcoreUtil.equals(generated, expected)); + } + + @Test + public void classifierTest() throws IOException { + final long millis = System.currentTimeMillis(); + + mapper.parseAndSave(getString("test/ClassifierTest.recore"), + URI.createFileURI("testTemp/ClassifierTestTemp.ecore")); + final EObject generated = loadResource("testTemp/ClassifierTestTemp.ecore"); + final EObject expected = loadResource("test/ClassifierTest.ecore"); + + Assert.assertTrue( + "ClassifierTest.ecore is not OK: " + (System.currentTimeMillis() - millis) + "ms.", + EcoreUtil.equals(generated, expected)); + } + + @Test + public void operationTest() throws IOException { + final long millis = System.currentTimeMillis(); + + mapper.parseAndSave(getString("test/OperationTest.recore"), + URI.createFileURI("testTemp/OperationTestTemp.ecore")); + final EObject generated = loadResource("testTemp/OperationTestTemp.ecore"); + final EObject expected = loadResource("test/OperationTest.ecore"); + + Assert.assertTrue( + "OperationTest.ecore is not OK: " + (System.currentTimeMillis() - millis) + "ms.", + EcoreUtil.equals(generated, expected)); + } + + @Test + public void packageTest() throws IOException { + final long millis = System.currentTimeMillis(); + + mapper.parseAndSave(getString("test/PackageTest.recore"), + URI.createFileURI("testTemp/PackageTestTemp.ecore")); + final EObject generated = loadResource("testTemp/PackageTestTemp.ecore"); + final EObject expected = loadResource("test/PackageTest.ecore"); + + Assert.assertTrue( + "PackageTest.ecore is not OK: " + (System.currentTimeMillis() - millis) + "ms.", + EcoreUtil.equals(generated, expected)); + } + + @Test + public void referenceTest() throws IOException { + final long millis = System.currentTimeMillis(); + + mapper.parseAndSave(getString("test/ReferenceTest.recore"), + URI.createFileURI("testTemp/ReferenceTestTemp.ecore")); + final EObject generated = loadResource("testTemp/ReferenceTestTemp.ecore"); + final EObject expected = loadResource("test/ReferenceTest.ecore"); + + Assert.assertTrue( + "ReferenceTest.ecore is not OK: " + (System.currentTimeMillis() - millis) + "ms.", + EcoreUtil.equals(generated, expected)); + } + + @Test + public void testTest() throws NullPointerException, IOException { + final long millis = System.currentTimeMillis(); + + mapper.parseAndSave(getString("test/Test.recore"), + URI.createFileURI("testTemp/TestTemp.ecore")); + final EObject generated = loadResource("testTemp/TestTemp.ecore"); + final EObject expected = loadResource("test/Test.ecore"); + + Assert.assertTrue("Test.ecore is not OK: " + (System.currentTimeMillis() - millis) + "ms.", + EcoreUtil.equals(generated, expected)); + } + + @Test + public void genericsTest() throws NullPointerException, IOException { + final long millis = System.currentTimeMillis(); + + mapper.parseAndSave(getString("test/GenericsTest.recore"), + URI.createFileURI("testTemp/GenericsTestTemp.ecore")); + final EObject generated = loadResource("testTemp/GenericsTestTemp.ecore"); + final EObject expected = loadResource("test/GenericsTest.ecore"); + + Assert.assertTrue("Test.ecore is not OK: " + (System.currentTimeMillis() - millis) + "ms.", + EcoreUtil.equals(generated, expected)); + } + + @Test + public void ecoreTest() throws NullPointerException, IOException { + final long millis = System.currentTimeMillis(); + + mapper.parseAndSave(getString("test/Ecore.recore"), + URI.createFileURI("testTemp/EcoreTemp.ecore")); + final EObject generated = loadResource("testTemp/EcoreTemp.ecore"); + final EObject expected = loadResource("test/Ecore.ecore"); + + Assert.assertTrue("Test.ecore is not OK: " + (System.currentTimeMillis() - millis) + "ms.", + EcoreUtil.equals(generated, expected)); + } + + private String getString(final String fileName) throws IOException { + return new String(Files.readAllBytes(Paths.get(fileName)), StandardCharsets.UTF_8); + } + + /** + * @param path + * @return + * + */ + private EObject loadResource(final String path) { + return repository.loadResource(path).getContents().get(0); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/test/EcoreInstanceTranslatorTest.java b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/test/EcoreInstanceTranslatorTest.java new file mode 100644 index 00000000..81bcdbe3 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/test/EcoreInstanceTranslatorTest.java @@ -0,0 +1,28 @@ +package eu.modelwriter.core.alloyinecore.ui.mapping.test; + +import java.io.IOException; + +import org.junit.Before; +import org.junit.Test; + +import eu.modelwriter.core.alloyinecore.ui.mapping.as2cs.EcoreInstanceTranslator; + +public class EcoreInstanceTranslatorTest { + private EcoreInstanceTranslator translator; + + @Before + public void before() { + translator = new EcoreInstanceTranslator(); + } + + @Test + public void translatorTest() throws IOException { + long millis = System.currentTimeMillis(); + // String actual = translator.translate("Model.xmi"); + // String actual = translator.translate("Tutorial.xmi"); + String actual = translator.translate("Instance.requirements"); + System.out.println("Time ellapsed: " + (System.currentTimeMillis() - millis)); + System.out.println(actual); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/test/EcoreTranslatorTest.java b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/test/EcoreTranslatorTest.java new file mode 100644 index 00000000..894e9339 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/src/eu/modelwriter/core/alloyinecore/ui/mapping/test/EcoreTranslatorTest.java @@ -0,0 +1,113 @@ +package eu.modelwriter.core.alloyinecore.ui.mapping.test; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; + +import org.junit.Before; +import org.junit.Test; + +import eu.modelwriter.configuration.internal.Utilities; +import eu.modelwriter.core.alloyinecore.ui.mapping.as2cs.EcoreTranslator; + +public class EcoreTranslatorTest { + + private EcoreTranslator translator; + + @Before + public void before() { + translator = new EcoreTranslator(); + } + + @Test + public void translatorTest() throws NullPointerException, IOException { + long millis = System.currentTimeMillis(); + String actual = translator.translate("test/Test.ecore"); + writeString("testTemp/TestTemp.recore", actual); + String expected = getString("test/Test.recore"); + assertEquals(Utilities.removeAllWhiteSpaces(expected), Utilities.removeAllWhiteSpaces(actual)); + System.out.println("Time ellapsed: " + (System.currentTimeMillis() - millis)); + System.out.println(actual); + } + + @Test + public void packageTranslate() throws IOException { + String actual = translator.translate("test/PackageTest.ecore"); + writeString("testTemp/PackageTestTemp.recore", actual); + String expected = getString("test/PackageTest.recore"); + assertEquals(Utilities.removeAllWhiteSpaces(expected), Utilities.removeAllWhiteSpaces(actual)); + } + + @Test + public void classifierTranslate() throws IOException { + String actual = translator.translate("test/ClassifierTest.ecore"); + writeString("testTemp/ClassifierTestTemp.recore", actual); + String expected = getString("test/ClassifierTest.recore"); + assertEquals(Utilities.removeAllWhiteSpaces(expected), Utilities.removeAllWhiteSpaces(actual)); + } + + @Test + public void attributeTranslate() throws IOException { + // TODO cover all cases + String actual = translator.translate("test/AttrTest.ecore"); + writeString("testTemp/AttrTestTemp.recore", actual); + String expected = getString("test/AttrTest.recore"); + assertEquals(Utilities.removeAllWhiteSpaces(expected), Utilities.removeAllWhiteSpaces(actual)); + } + + @Test + public void referenceTranslate() throws IOException { + // TODO cover all cases + String actual = translator.translate("test/ReferenceTest.ecore"); + writeString("testTemp/ReferenceTestTemp.recore", actual); + String expected = getString("test/ReferenceTest.recore"); + assertEquals(Utilities.removeAllWhiteSpaces(expected), Utilities.removeAllWhiteSpaces(actual)); + } + + @Test + public void operationTranslate() throws IOException { + // TODO cover all cases + String actual = translator.translate("test/OperationTest.ecore"); + writeString("testTemp/OperationTestTemp.recore", actual); + String expected = getString("test/OperationTest.recore"); + assertEquals(Utilities.removeAllWhiteSpaces(expected), Utilities.removeAllWhiteSpaces(actual)); + } + + @Test + public void annotationTranslate() throws IOException { + // TODO cover all cases + String actual = translator.translate("test/AnnotationTest.ecore"); + writeString("testTemp/AnnotationTestTemp.recore", actual); + String expected = getString("test/AnnotationTest.recore"); + assertEquals(Utilities.removeAllWhiteSpaces(expected), Utilities.removeAllWhiteSpaces(actual)); + } + + @Test + public void genericsTranslate() throws IOException { + // TODO cover all cases + String actual = translator.translate("test/GenericsTest.ecore"); + writeString("testTemp/GenericsTestTemp.recore", actual); + String expected = getString("test/GenericsTest.recore"); + assertEquals(Utilities.removeAllWhiteSpaces(expected), Utilities.removeAllWhiteSpaces(actual)); + } + + @Test + public void ecoreTranslate() throws IOException { + // TODO cover all cases + String actual = translator.translate("test/Ecore.ecore"); + writeString("testTemp/EcoreTemp.recore", actual); + String expected = getString("test/Ecore.recore"); + assertEquals(Utilities.removeAllWhiteSpaces(expected), Utilities.removeAllWhiteSpaces(actual)); + } + + private String getString(String fileName) throws IOException { + return new String(Files.readAllBytes(Paths.get(fileName)), StandardCharsets.UTF_8); + } + + private void writeString(String fileName, String content) { + Utilities.writeToFile(fileName, new StringBuilder(content)); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/stringtemplate/AlloyInEcore.stg b/Source/eu.modelwriter.core.alloyinecore.mapping/stringtemplate/AlloyInEcore.stg new file mode 100644 index 00000000..0ebcf640 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/stringtemplate/AlloyInEcore.stg @@ -0,0 +1,147 @@ +model(options, modelName) ::= +<< +<\n><\u007B> + +<\u007D><\n> +model ;<\n><\n> +>> + +load(name, namespace) ::= +<< +import : ; +>> + +package(visibility, name, prefix, namespace, subElement) ::= +<< +package : = <\n><\u007B>; + +<\u007D><\n> +>> + +enum(visibility, name, typeParameter, instanceName, isSerializable, subElement)::= +<< +enum <\u003C><\u003E><\n><\u007B>; + +<\u007D><\n> +>> + +enumLiteral(name, enumValue, subElement) ::= +<< +literal = <\n><\u007B>; + +<\u007D><\n> +>> + +datatype(visibility, isPrimitive, nullable, name, typeParameter, instanceName, isSerializable, subElement)::= +<< +primitive nullable datatype <\u003C><\u003E><(instanceName:singleQuote()):semicolon():ls()><\n><\u007B>; + +<\u007D><\n> +>> + +class(visibility, isAbstract, name, typeParameter, superClass, instanceName, isInterface, subElement) ::= +<< +interfaceabstract class<\u003C><\u003E> extends <\n><\u007B>; + +<\u007D><\n> +>> + +attr(visibility, isStatic, model,ghost, transient, volatile, nullable, readonly, name, defaultValue, type, multiplicity, qualifier, subElement)::= +<< +static model ghost transient volatile nullable readonly attribute<\n><\u007B>; + +<\u007D><\n> +>> + +ref(visibility, isStatic, model,ghost, transient, volatile, nullable, readonly, name, opposite, defaultValue, type, multiplicity, qualifier, subElement)::= +<< +static model ghost transient volatile nullable readonly property<\n><\u007B>; + +<\u007D><\n> +>> + +op(visibility, isStatic, nullable, name, typeParameter, params, throws, type, multiplicity, qualifier, subElement) ::= +<< +static nullable operation <\u003C><\u003E>() throws <\n><\u007B>; + +<\u007D><\n> +>> + +opParameter(nullable, name, type, multiplicity, qualifier, subElement) ::= +<< +nullable +>> + +anno(name, detail, subElement)::= +<< +annotation; +( + +); +<\u007B> + +<\u007D><\n> +>> + +edetail(name, val)::= +<< + = +>> + +inv(isCallable, name, message, formula)::= +<< +callable invariant; +>> + +precondition(name, message, formula)::= +<< +requires; +>> + +postcondition(name, message, formula)::= +<< +ensures; +>> + +body(name, expression)::= +<< +body; +>> + +derivation(name, expression) ::= +<< +derivation; +>> + +initial(name, expression) ::= +<< +initial; +>> + +referenceKey(referredKeys) ::= +<< +key ; +>> + +typeParameter(name, eBound) ::= +<< + extends +>> + +genericType(classifier, typeParameter, typeArgument, upperBound, lowerBound) ::= +<< +?<\u003C><\u003E> extends super +>> + +ds(x) ::= " " +ls(x) ::= "<\ >" +rs(x) ::= " " +throw(x)::=" throws " +parenthesis(x) ::= "()" +sharp(x) ::= "#" +equals(x) ::= "= " +bracket(x) ::= "[]" +semicolon(x) ::=": " +curlyBracket(x) ::="<\u007B> <\u007D>" +singleQuote(x)::="''" +doubleQuote(x)::="\"\"" \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/stringtemplate/EcoreInstance.stg b/Source/eu.modelwriter.core.alloyinecore.mapping/stringtemplate/EcoreInstance.stg new file mode 100644 index 00000000..8e7d03f9 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/stringtemplate/EcoreInstance.stg @@ -0,0 +1,34 @@ +load(name, path) ::= +<< +import : ; +>> + +model(name, nsPrefix, nsURI, path) ::= +<< +model : ;<\n><\n> +>> + +eObject(className, id, content) ::= +<< +<\n>{; + +} +>> + +containmentRef(name, content) ::= +<< +: <\n>{; + +} +>> + +ds(x) ::= " " +ls(x) ::= "<\ >" +rs(x) ::= " " +throw(x)::=" throws " +parenthesis(x) ::= "()" +bracket(x) ::= "[]" +semicolon(x) ::=": " +curlyBracket(x) ::="{ }" +singleQuote(x)::="''" +doubleQuote(x)::="\"\"" \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/AnnotationTest.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/AnnotationTest.ecore new file mode 100644 index 00000000..bcc02d6f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/AnnotationTest.ecore @@ -0,0 +1,57 @@ + + + + +
+ +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/AnnotationTest.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/AnnotationTest.recore new file mode 100644 index 00000000..4101a6f6 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/AnnotationTest.recore @@ -0,0 +1,72 @@ +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package TestPackage : tp = 'www.testpackage.org' +{ + class TestClass : 'TCname' + { + attribute testAttr : Boolean[?] = 'false' + { + annotation 'www.annotation.test'; + } + operation testOp() + { + annotation 'www.annotation.test'; + } + property testRef : TestPackage::SubPackage::SubTestClass[?] + { + annotation 'www.annotation.test'; + } + annotation 'www.annotation.test' + { + annotation 'www.sub.annotation.test' + { + reference TestPackage::TestDataType; + } + } + } + enum TestEnum : 'TEname' { !serializable } + { + annotation 'www.annotation.test'; + } + primitive datatype TestDataType : 'TDTname' { !serializable } + { + annotation 'www.annotation.test'; + } + package SubPackage : sp = 'www.sub.testpackage.org' + { + class SubTestClass + { + annotation 'www.annotation.test'; + } + interface SubTestInterface + { + annotation 'www.annotation.test'; + } + enum SubTestEnum + { + annotation 'www.annotation.test'; + } + datatype SubTestDataType : 'STDTname' + { + annotation 'www.annotation.test' + { + annotation 'www.sub.annotation.test'; + } + } + annotation 'www.annotation.test'; + } + annotation 'www.annotation.test' + ( + 'testKey' = 'testValue', + 'testKey2' = 'testValue2' + ) + { + annotation 'www.sub.annotation.test' + ( + 'testKey' = 'testValue' + ) + { + reference TestPackage::SubPackage::SubTestClass; + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/AttrTest.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/AttrTest.ecore new file mode 100644 index 00000000..146808f6 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/AttrTest.ecore @@ -0,0 +1,107 @@ + + + +
+ + + +
+ + + +
+ + +
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/AttrTest.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/AttrTest.recore new file mode 100644 index 00000000..0a6bea27 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/AttrTest.recore @@ -0,0 +1,44 @@ +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package TestPackage : tp = 'www.testpackage.org' +{ + private class TestClass extends SuperClass, UberClass : 'TCname' + { + private static model transient volatile readonly attribute testAttr : Ecore::EDate[1] = '2017-01-01' { derived unsettable id } + { + derivation : ~testAttr; + } + model attribute testStringAttr : String[?] = ''; + ghost attribute testRealAttr : Real[?] = '0.0'; + transient volatile attribute testBooleanAttr : Boolean[?] = 'false'; + private transient attribute testIntAttr : Integer[?] = '1'; + attribute testAttr1 : Integer = '1'; + attribute testAttr2 : Integer[+] = '1' { ordered }; + attribute testAttr3 : Integer[*] = '1' { ordered }; + attribute testAttr4 : Integer[2..5] = '1' { ordered }; + attribute testAttr5 : Integer[?] = '1'; + attribute testUnlimitedNaturalAttr : UnlimitedNatural[?] = '1'; + attribute testAttr6 : Integer[*|?] = '1' { ordered }; + attribute testAttr7 : Integer[+|?] = '1' { ordered }; + attribute testAttr8 : Integer[2..5|?] = '1' { ordered }; + } + interface TestInterface extends SuperClass : 'TIname'; + enum TestEnum : 'TEname' { !serializable }; + primitive datatype TestDataType : 'TDTname' { !serializable }; + abstract class SuperClass; + abstract class UberClass; + package SubPackage : sp = 'www.sub.testpackage.org' + { + class SubTestClass + { + attribute testIntAttr : Integer[?] = '0'; + attribute testStringAttr : String[?] = ''; + attribute testRealAttr : Real[?] = '0'; + transient volatile attribute testBooleanAttr : Boolean[?] = 'false'; + transient attribute testAttr : Ecore::EDate[?] = '2016-09-09'; + } + interface SubTestInterface; + enum SubTestEnum; + datatype SubTestDataType : 'STDTname'; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/ClassifierTest.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/ClassifierTest.ecore new file mode 100644 index 00000000..cebdc453 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/ClassifierTest.ecore @@ -0,0 +1,29 @@ + + + + +
+ + + + +
+ + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/ClassifierTest.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/ClassifierTest.recore new file mode 100644 index 00000000..0b91c53b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/ClassifierTest.recore @@ -0,0 +1,16 @@ +package TestPackage : tp = 'www.testpackage.org' +{ + private class TestClass extends SuperClass, UberClass : 'TCCname'; + public interface TestInterface extends SuperClass : 'TIname'; + enum TestEnum : 'TEname' { !serializable }; + datatype TestDataType : 'TDTname' { !serializable }; + abstract class SuperClass; + abstract class UberClass; + package SubPackage : sp = 'www.sub.testpackage.org' + { + class SubTestClass; + interface SubTestInterface; + enum SubTestEnum; + datatype SubTestDataType : 'STDTname'; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/Ecore.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/Ecore.ecore new file mode 100644 index 00000000..12543aea --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/Ecore.ecore @@ -0,0 +1,526 @@ + + + + +
+ + + + + + +
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + +
+
+ + + + + + +
+ + + + + + + +
+
+ + + + + + + + + + +
+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + +
+
+ + + + +
+
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+
+ + + + +
+ + + + +
+ + + + +
+
+ + + + + +
+
+ + + + + + +
+ + + + +
+
+ + + + + + + + + + +
+ + + + +
+
+ + + + +
+ + + + +
+
+ + + + + + + + +
+ + + + +
+
+ + + + + + + + + + +
+ + + + +
+
+ + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/Ecore.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/Ecore.recore new file mode 100644 index 00000000..bc1149ad --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/Ecore.recore @@ -0,0 +1,443 @@ +package ecore : ecore = 'http://www.eclipse.org/emf/2002/Ecore' +{ + class EAttribute extends EStructuralFeature + { + attribute iD : EBoolean[?]; + transient volatile readonly property eAttributeType : EDataType { derived }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ConsistentTransient' + ); + } + class EAnnotation extends EModelElement + { + attribute source : EString[?]; + property details : EStringToStringMapEntry[*] { ordered !resolve composes }; + transient property eModelElement#eAnnotations : EModelElement[?] { !resolve }; + property contents : EObject[*] { ordered !resolve composes }; + property references : EObject[*] { ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedSourceURI' + ); + } + class EClass extends EClassifier + { + attribute abstract : EBoolean[?]; + attribute interface : EBoolean[?]; + operation isSuperTypeOf(someClass : EClass[?]) : EBoolean[?]; + operation getFeatureCount() : EInt[?]; + operation getEStructuralFeature(featureID : EInt[?]) : EStructuralFeature[?]; + operation getFeatureID(feature : EStructuralFeature[?]) : EInt[?]; + operation getEStructuralFeature(featureName : EString[?]) : EStructuralFeature[?]; + operation getOperationCount() : EInt[?]; + operation getEOperation(operationID : EInt[?]) : EOperation[?]; + operation getOperationID(operation : EOperation[?]) : EInt[?]; + operation getOverride(operation : EOperation[?]) : EOperation[?]; + operation getFeatureType(feature : EStructuralFeature[?]) : EGenericType[?]; + property eSuperTypes : EClass[*] { ordered unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + property eOperations#eContainingClass : EOperation[*] { ordered !resolve composes }; + transient volatile readonly property eAllAttributes : EAttribute[*] { ordered derived }; + transient volatile readonly property eAllReferences : EReference[*] { ordered derived }; + transient volatile readonly property eReferences : EReference[*] { ordered derived }; + transient volatile readonly property eAttributes : EAttribute[*] { ordered derived }; + transient volatile readonly property eAllContainments : EReference[*] { ordered derived }; + transient volatile readonly property eAllOperations : EOperation[*] { ordered derived }; + transient volatile readonly property eAllStructuralFeatures : EStructuralFeature[*] { ordered derived }; + transient volatile readonly property eAllSuperTypes : EClass[*] { ordered derived }; + transient volatile readonly property eIDAttribute : EAttribute[?] { derived !resolve }; + property eStructuralFeatures#eContainingClass : EStructuralFeature[*] { ordered !resolve composes }; + property eGenericSuperTypes : EGenericType[*] { ordered unsettable !resolve composes } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + transient volatile readonly property eAllGenericSuperTypes : EGenericType[*] { ordered derived }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'InterfaceIsAbstract AtMostOneID UniqueFeatureNames UniqueOperationSignatures NoCircularSuperTypes WellFormedMapEntryClass ConsistentSuperTypes DisjointFeatureAndOperationSignatures' + ); + } + abstract class EClassifier extends ENamedElement + { + volatile attribute instanceClassName : EString[?] { unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + transient volatile readonly attribute instanceClass : EJavaClass[?] { derived }; + transient volatile readonly attribute defaultValue : EJavaObject[?] { derived }; + volatile attribute instanceTypeName : EString[?] { unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + operation isInstance(object : EJavaObject[?]) : EBoolean[?]; + operation getClassifierID() : EInt[?]; + transient readonly property ePackage#eClassifiers : EPackage[?]; + property eTypeParameters : ETypeParameter[*] { ordered composes }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedInstanceTypeName UniqueTypeParameterNames' + ); + } + class EDataType extends EClassifier + { + attribute serializable : EBoolean[?] = 'true'; + } + class EEnum extends EDataType + { + operation getEEnumLiteral(name : EString[?]) : EEnumLiteral[?]; + operation getEEnumLiteral(value : EInt[?]) : EEnumLiteral[?]; + operation getEEnumLiteralByLiteral(literal : EString[?]) : EEnumLiteral[?]; + property eLiterals#eEnum : EEnumLiteral[*] { ordered !resolve composes }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'UniqueEnumeratorNames UniqueEnumeratorLiterals' + ); + } + class EEnumLiteral extends ENamedElement + { + attribute value : EInt[?]; + transient attribute instance : EEnumerator[?]; + attribute literal : EString[?]; + transient readonly property eEnum#eLiterals : EEnum[?] { !resolve }; + } + class EFactory extends EModelElement + { + operation create(eClass : EClass[?]) : EObject[?]; + operation createFromString(eDataType : EDataType[?], literalValue : EString[?]) : EJavaObject[?]; + operation convertToString(eDataType : EDataType[?], instanceValue : EJavaObject[?]) : EString[?]; + transient property ePackage#eFactoryInstance : EPackage { !resolve }; + } + abstract class EModelElement + { + operation getEAnnotation(source : EString[?]) : EAnnotation[?]; + property eAnnotations#eModelElement : EAnnotation[*] { ordered !resolve composes }; + } + abstract class ENamedElement extends EModelElement + { + attribute name : EString[?]; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedName' + ); + } + class EObject + { + operation eClass() : EClass[?]; + operation eIsProxy() : EBoolean[?]; + operation eResource() : EResource[?]; + operation eContainer() : EObject[?]; + operation eContainingFeature() : EStructuralFeature[?]; + operation eContainmentFeature() : EReference[?]; + operation eContents() : EEList[?]; + operation eAllContents() : ETreeIterator[?]; + operation eCrossReferences() : EEList[?]; + operation eGet(feature : EStructuralFeature[?]) : EJavaObject[?]; + operation eGet(feature : EStructuralFeature[?], resolve : EBoolean[?]) : EJavaObject[?]; + operation eSet(feature : EStructuralFeature[?], newValue : EJavaObject[?]); + operation eIsSet(feature : EStructuralFeature[?]) : EBoolean[?]; + operation eUnset(feature : EStructuralFeature[?]); + operation eInvoke(operation : EOperation[?], arguments : EEList[?]) : EJavaObject[?] throws EInvocationTargetException; + } + class EOperation extends ETypedElement + { + operation getOperationID() : EInt[?]; + operation isOverrideOf(someOperation : EOperation[?]) : EBoolean[?]; + transient readonly property eContainingClass#eOperations : EClass[?] { !resolve }; + property eTypeParameters : ETypeParameter[*] { ordered composes }; + property eParameters#eOperation : EParameter[*] { ordered !resolve composes }; + property eExceptions : EClassifier[*] { ordered unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + property eGenericExceptions : EGenericType[*] { ordered unsettable !resolve composes } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'UniqueParameterNames UniqueTypeParameterNames NoRepeatingVoid' + ); + } + class EPackage extends ENamedElement + { + attribute nsURI : EString[?]; + attribute nsPrefix : EString[?]; + operation getEClassifier(name : EString[?]) : EClassifier[?]; + transient property eFactoryInstance#ePackage : EFactory { !resolve }; + property eClassifiers#ePackage : EClassifier[*] { ordered composes }; + property eSubpackages#eSuperPackage : EPackage[*] { ordered composes }; + transient readonly property eSuperPackage#eSubpackages : EPackage[?]; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedNsURI WellFormedNsPrefix UniqueSubpackageNames UniqueClassifierNames UniqueNsURIs' + ); + } + class EParameter extends ETypedElement + { + transient readonly property eOperation#eParameters : EOperation[?] { !resolve }; + } + class EReference extends EStructuralFeature + { + attribute containment : EBoolean[?]; + transient volatile readonly attribute container : EBoolean[?] { derived }; + attribute resolveProxies : EBoolean[?] = 'true'; + property eOpposite : EReference[?]; + transient volatile readonly property eReferenceType : EClass { derived }; + property eKeys : EAttribute[*] { ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ConsistentOpposite SingleContainer ConsistentKeys ConsistentUnique ConsistentContainer' + ); + } + abstract class EStructuralFeature extends ETypedElement + { + attribute changeable : EBoolean[?] = 'true'; + attribute volatile : EBoolean[?]; + attribute transient : EBoolean[?]; + attribute defaultValueLiteral : EString[?]; + transient volatile readonly attribute defaultValue : EJavaObject[?] { derived }; + attribute unsettable : EBoolean[?]; + attribute derived : EBoolean[?]; + operation getFeatureID() : EInt[?]; + operation getContainerClass() : EJavaClass[?]; + transient readonly property eContainingClass#eStructuralFeatures : EClass[?] { !resolve }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ValidDefaultValueLiteral' + ); + } + abstract class ETypedElement extends ENamedElement + { + attribute ordered : EBoolean[?] = 'true'; + attribute unique : EBoolean[?] = 'true'; + attribute lowerBound : EInt[?]; + attribute upperBound : EInt[?] = '1'; + transient volatile readonly attribute many : EBoolean[?] { derived }; + transient volatile readonly attribute required : EBoolean[?] { derived }; + volatile property eType : EClassifier[?] { unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + volatile property eGenericType : EGenericType[?] { unsettable !resolve composes } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ValidLowerBound ValidUpperBound ConsistentBounds ValidType' + ); + } + datatype EBigDecimal : 'java.math.BigDecimal' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#decimal' + ); + } + datatype EBigInteger : 'java.math.BigInteger' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#integer' + ); + } + datatype EBoolean : 'boolean' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#boolean' + ); + } + datatype EBooleanObject : 'java.lang.Boolean' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EBoolean', + 'name' = 'EBoolean:Object' + ); + } + datatype EByte : 'byte' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#byte' + ); + } + datatype EByteArray : 'byte[]' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#hexBinary' + ); + } + datatype EByteObject : 'java.lang.Byte' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EByte', + 'name' = 'EByte:Object' + ); + } + datatype EChar : 'char'; + datatype ECharacterObject : 'java.lang.Character' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EChar', + 'name' = 'EChar:Object' + ); + } + datatype EDate : 'java.util.Date'; + datatype EDiagnosticChain : 'org.eclipse.emf.common.util.DiagnosticChain' { !serializable }; + datatype EDouble : 'double' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#double' + ); + } + datatype EDoubleObject : 'java.lang.Double' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EDouble', + 'name' = 'EDouble:Object' + ); + } + datatype EEList : 'org.eclipse.emf.common.util.EList' { !serializable }; + datatype EEnumerator : 'org.eclipse.emf.common.util.Enumerator' { !serializable }; + datatype EFeatureMap : 'org.eclipse.emf.ecore.util.FeatureMap' { !serializable }; + datatype EFeatureMapEntry : 'org.eclipse.emf.ecore.util.FeatureMap$Entry' { !serializable }; + datatype EFloat : 'float' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#float' + ); + } + datatype EFloatObject : 'java.lang.Float' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EFloat', + 'name' = 'EFloat:Object' + ); + } + datatype EInt : 'int' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#int' + ); + } + datatype EIntegerObject : 'java.lang.Integer' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EInt', + 'name' = 'EInt:Object' + ); + } + datatype EJavaClass : 'java.lang.Class'; + datatype EJavaObject : 'java.lang.Object'; + datatype ELong : 'long' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#long' + ); + } + datatype ELongObject : 'java.lang.Long' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'ELong', + 'name' = 'ELong:Object' + ); + } + datatype EMap : 'java.util.Map' { !serializable }; + datatype EResource : 'org.eclipse.emf.ecore.resource.Resource' { !serializable }; + datatype EResourceSet : 'org.eclipse.emf.ecore.resource.ResourceSet' { !serializable }; + datatype EShort : 'short' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#short' + ); + } + datatype EShortObject : 'java.lang.Short' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EShort', + 'name' = 'EShort:Object' + ); + } + datatype EString : 'java.lang.String' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#string' + ); + } + class EStringToStringMapEntry : 'java.util.Map$Entry' + { + attribute key : EString[?]; + attribute value : EString[?]; + } + datatype ETreeIterator : 'org.eclipse.emf.common.util.TreeIterator' { !serializable }; + class EGenericType + { + operation isInstance(object : EJavaObject[?]) : EBoolean[?]; + property eUpperBound : EGenericType[?] { !resolve composes }; + property eTypeArguments : EGenericType[*] { ordered !resolve composes }; + transient readonly property eRawType : EClassifier { derived }; + property eLowerBound : EGenericType[?] { !resolve composes }; + property eTypeParameter : ETypeParameter[?] { !resolve }; + property eClassifier : EClassifier[?]; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ConsistentType ConsistentBounds ConsistentArguments' + ); + } + class ETypeParameter extends ENamedElement + { + property eBounds : EGenericType[*] { ordered !resolve composes }; + } + datatype EInvocationTargetException : 'java.lang.reflect.InvocationTargetException' { !serializable }; +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/FordOtosan.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/FordOtosan.ecore new file mode 100644 index 00000000..de785a89 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/FordOtosan.ecore @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/GenericsTest.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/GenericsTest.ecore new file mode 100644 index 00000000..a09b5595 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/GenericsTest.ecore @@ -0,0 +1,71 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/GenericsTest.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/GenericsTest.recore new file mode 100644 index 00000000..af28250a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/GenericsTest.recore @@ -0,0 +1,23 @@ +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package generics : gns = 'eu.modelwriter.generics' +{ + abstract class List + { + operation add(element : E); + operation iterator() : Iterator[?]; + } + class Iterator + { + operation next() : E[?]; + operation hasNext() : Boolean; + } + class ArrayList extends List; + class Car; + abstract class Person; + class Owner, ?>>>>> extends ArrayList + { + property cars : ArrayList[?] { !resolve }; + property attr1 : K[?] { !resolve }; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/My.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/My.ecore new file mode 100644 index 00000000..9b45e2f8 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/My.ecore @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/OperationTest.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/OperationTest.ecore new file mode 100644 index 00000000..ce024f34 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/OperationTest.ecore @@ -0,0 +1,115 @@ + + + +
+ + + +
+ + + +
+ + +
+
+
+ + +
+
+ + +
+
+
+ + + + + + + + + + + + +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+
+ + + + + + + + + + + + + +
+ + +
+
+
+ + +
+
+ + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/OperationTest.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/OperationTest.recore new file mode 100644 index 00000000..36971f7d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/OperationTest.recore @@ -0,0 +1,47 @@ +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package TestPackage : tp = 'www.testpackage.org' +{ + private class TestClass extends SuperClass, UberClass : 'TCname' + { + private static operation testOp(testParam : Boolean[?], testParam2 : Ecore::EChar[+] { ordered }) : String[?] throws TestPackage::SubPackage::SubTestInterface, TestPackage::SubPackage::SubTestClass + { + requires testPre ("Hey!") : lone testOp; + body testPre : testOp; + ensures testPost ("Hey!") : one testOp; + } + operation testOp1() : TestDataType[?]; + operation testOp2() : TestDataType; + operation testOp3() : TestDataType[*] { ordered }; + operation testOp4() : TestDataType[+] { ordered }; + operation testOp5() : TestDataType[3..6] { ordered }; + operation testVoidOp() + { + requires testPre ("Hey!") : lone testOp; + body testBody : testOp; + ensures testPost ("Hey!") : one testOp; + ensures testPost2 ("Hey!") : one testOp; + } + operation testOp6() : TestDataType[*|?] { ordered }; + operation testOp7() : TestDataType[+|?] { ordered }; + operation testOp8() : TestDataType[3..6|?] { ordered }; + private static operation testOp9(testParam : Boolean[+|?] { ordered }, testParam2 : Ecore::EChar[2|?] { ordered }) : String[?] throws TestPackage::SubPackage::SubTestInterface, TestPackage::SubPackage::SubTestClass + { + requires testPre ("Hey!") : lone testOp; + body testPre : testOp; + ensures testPost ("Hey!") : one testOp; + } + } + interface TestInterface extends SuperClass : 'TIname'; + enum TestEnum : 'TEname' { !serializable }; + primitive datatype TestDataType : 'TDTname' { !serializable }; + abstract class SuperClass; + abstract class UberClass; + package SubPackage : sp = 'www.sub.testpackage.org' + { + class SubTestClass; + interface SubTestInterface; + enum SubTestEnum; + datatype SubTestDataType : 'STDTname'; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/PackageTest.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/PackageTest.ecore new file mode 100644 index 00000000..3c5ed977 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/PackageTest.ecore @@ -0,0 +1,15 @@ + + + + +
+ + + +
+ + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/PackageTest.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/PackageTest.recore new file mode 100644 index 00000000..cf1e0dbe --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/PackageTest.recore @@ -0,0 +1,8 @@ +package TestPackage : tp = 'www.testpackage.org' +{ + public package SubPackage1 : sp1 = 'www.sub1.testpackage.org' + { + private package SubSubPackage : ssp = 'www.sub.sub1.testpackage.org'; + } + package SubPackage2 : sp2 = 'www.sub2.testpackage.org'; +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/ReferenceTest.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/ReferenceTest.ecore new file mode 100644 index 00000000..0a8f2975 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/ReferenceTest.ecore @@ -0,0 +1,72 @@ + + + + +
+ + + +
+ + +
+
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/ReferenceTest.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/ReferenceTest.recore new file mode 100644 index 00000000..e1a30f55 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/ReferenceTest.recore @@ -0,0 +1,41 @@ +package TestPackage : tp = 'www.testpackage.org' +{ + private class TestClass extends SuperClass, UberClass : 'TCname' + { + private static model transient volatile readonly property testRef : TestPackage::SubPackage::SubTestClass[?] { derived unsettable composes } + { + derivation testDerivation : ~testRef; + } + property testRef2 : TestInterface[?] { !resolve }; + property testRef3 : TestInterface { !resolve }; + property testRef4 : TestInterface[*] { !resolve }; + property testRef5 : TestInterface[1..5]; + property testRef6 : TestInterface[+] { !resolve }; + property testRefWithExp : TestInterface[?] { !resolve } + { + initial : ~testRef; + } + property testRefWithKey : TestInterface[?] { !resolve } + { + key testAttr; + } + property testRef7 : TestInterface[*|?] { !resolve }; + property testRef8 : TestInterface[1..5|?]; + property testRef9 : TestInterface[+|?] { !resolve }; + } + interface TestInterface extends SuperClass : 'TIname' + { + attribute testAttr : TestDataType[?]; + } + enum TestEnum : 'TEname'; + primitive datatype TestDataType : 'TDTname'; + abstract class SuperClass; + abstract class UberClass; + package SubPackage : sp = 'www.sub.testpackage.org' + { + class SubTestClass; + interface SubTestInterface; + enum SubTestEnum { !serializable }; + datatype SubTestDataType : 'STDTname' { !serializable }; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/Test.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/Test.ecore new file mode 100644 index 00000000..6c5897b9 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/Test.ecore @@ -0,0 +1,117 @@ + + + +
+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + + + + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/Test.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/Test.recore new file mode 100644 index 00000000..c9b38c81 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/Test.recore @@ -0,0 +1,100 @@ +import FordOtosan : 'FordOtosan.ecore'; +import extlibrary : 'extlibrary.ecore'; +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' +{ + public class Library + { + attribute name : String + { + annotation; + } + property books#library : Book[*] { composes } + { + annotation 'sadasdas'; + } + static property loans : Loan[*] { composes }; + property members#library : Member[*] { composes }; + } + class Book + { + attribute name : String; + attribute copies : UnlimitedNatural; + operation isAvailable(param1 : Boolean[?], param2 : Book[?]) : Boolean[?] + { + body; + ensures sup ("this is a precondition"); + } + property library#books : Library[?]; + volatile property loans : Loan[*] { derived } + { + derivation : library.loans->select; + } + invariant importantConstraint ("multi + lined + message"); + } + class Member + { + attribute name : String; + operation tespOP(); + property library#members : Library[?]; + volatile property loans : Loan[*] { derived } + { + derivation : library.loans->select; + } + volatile property books : Book[*] { !unique derived } + { + derivation : loans->collect; + } + } + class Loan + { + attribute date : Ecore::EDate[?]; + property book : tutorial::Organization::SubOrg1::sb1C; + property member : Member; + annotation + { + reference tutorial::Organization::Librarian::orgOpp; + } + } + package Organization : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization' + { + enum Type { !serializable } + { + literal asd = 0; + } + datatype JavaPackage : 'java.lang.Package' { !serializable }; + class Librarian extends extlibrary::Employee + { + operation orgOpp() : Ecore::ELong[?]; + property workOn : tutorial::Organization::SubOrg2::sb2C[?]; + } + class Ref extends tutorial::Library + { + property RefOutsideEcore : extlibrary::Item[?]; + } + package SubOrg1 : sb = 'suborg1' + { + class sb1C; + } + package SubOrg2 : sb2 = 'SubOrg2' + { + class sb2C; + } + annotation 'extAnno' + { + reference extlibrary::Item; + reference extlibrary::Item::publicationDate; + reference FordOtosan::Container::vehicle; + reference FordOtosan::Vehicle::ElectricalPowerSupplySystem::ElectricalPowerSupplySystem::electricalPowerSupplySystemPart; + } + } + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'invocationDelegates' = 'http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot', + 'settingDelegates' = 'http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot', + 'validationDelegates' = 'http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot' + ); +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/test/extlibrary.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/test/extlibrary.ecore new file mode 100644 index 00000000..4d637438 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/test/extlibrary.ecore @@ -0,0 +1,107 @@ + + + + + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/AnnotationTestTemp.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/AnnotationTestTemp.ecore new file mode 100644 index 00000000..fcc04dea --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/AnnotationTestTemp.ecore @@ -0,0 +1,52 @@ + + + + +
+ +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/AnnotationTestTemp.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/AnnotationTestTemp.recore new file mode 100644 index 00000000..4101a6f6 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/AnnotationTestTemp.recore @@ -0,0 +1,72 @@ +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package TestPackage : tp = 'www.testpackage.org' +{ + class TestClass : 'TCname' + { + attribute testAttr : Boolean[?] = 'false' + { + annotation 'www.annotation.test'; + } + operation testOp() + { + annotation 'www.annotation.test'; + } + property testRef : TestPackage::SubPackage::SubTestClass[?] + { + annotation 'www.annotation.test'; + } + annotation 'www.annotation.test' + { + annotation 'www.sub.annotation.test' + { + reference TestPackage::TestDataType; + } + } + } + enum TestEnum : 'TEname' { !serializable } + { + annotation 'www.annotation.test'; + } + primitive datatype TestDataType : 'TDTname' { !serializable } + { + annotation 'www.annotation.test'; + } + package SubPackage : sp = 'www.sub.testpackage.org' + { + class SubTestClass + { + annotation 'www.annotation.test'; + } + interface SubTestInterface + { + annotation 'www.annotation.test'; + } + enum SubTestEnum + { + annotation 'www.annotation.test'; + } + datatype SubTestDataType : 'STDTname' + { + annotation 'www.annotation.test' + { + annotation 'www.sub.annotation.test'; + } + } + annotation 'www.annotation.test'; + } + annotation 'www.annotation.test' + ( + 'testKey' = 'testValue', + 'testKey2' = 'testValue2' + ) + { + annotation 'www.sub.annotation.test' + ( + 'testKey' = 'testValue' + ) + { + reference TestPackage::SubPackage::SubTestClass; + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/AttrTestTemp.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/AttrTestTemp.ecore new file mode 100644 index 00000000..0403763b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/AttrTestTemp.ecore @@ -0,0 +1,98 @@ + + + +
+ + + +
+ + + +
+ + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/AttrTestTemp.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/AttrTestTemp.recore new file mode 100644 index 00000000..0a6bea27 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/AttrTestTemp.recore @@ -0,0 +1,44 @@ +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package TestPackage : tp = 'www.testpackage.org' +{ + private class TestClass extends SuperClass, UberClass : 'TCname' + { + private static model transient volatile readonly attribute testAttr : Ecore::EDate[1] = '2017-01-01' { derived unsettable id } + { + derivation : ~testAttr; + } + model attribute testStringAttr : String[?] = ''; + ghost attribute testRealAttr : Real[?] = '0.0'; + transient volatile attribute testBooleanAttr : Boolean[?] = 'false'; + private transient attribute testIntAttr : Integer[?] = '1'; + attribute testAttr1 : Integer = '1'; + attribute testAttr2 : Integer[+] = '1' { ordered }; + attribute testAttr3 : Integer[*] = '1' { ordered }; + attribute testAttr4 : Integer[2..5] = '1' { ordered }; + attribute testAttr5 : Integer[?] = '1'; + attribute testUnlimitedNaturalAttr : UnlimitedNatural[?] = '1'; + attribute testAttr6 : Integer[*|?] = '1' { ordered }; + attribute testAttr7 : Integer[+|?] = '1' { ordered }; + attribute testAttr8 : Integer[2..5|?] = '1' { ordered }; + } + interface TestInterface extends SuperClass : 'TIname'; + enum TestEnum : 'TEname' { !serializable }; + primitive datatype TestDataType : 'TDTname' { !serializable }; + abstract class SuperClass; + abstract class UberClass; + package SubPackage : sp = 'www.sub.testpackage.org' + { + class SubTestClass + { + attribute testIntAttr : Integer[?] = '0'; + attribute testStringAttr : String[?] = ''; + attribute testRealAttr : Real[?] = '0'; + transient volatile attribute testBooleanAttr : Boolean[?] = 'false'; + transient attribute testAttr : Ecore::EDate[?] = '2016-09-09'; + } + interface SubTestInterface; + enum SubTestEnum; + datatype SubTestDataType : 'STDTname'; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/ClassifierTestTemp.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/ClassifierTestTemp.ecore new file mode 100644 index 00000000..364905aa --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/ClassifierTestTemp.ecore @@ -0,0 +1,23 @@ + + + + +
+ + + + +
+ + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/ClassifierTestTemp.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/ClassifierTestTemp.recore new file mode 100644 index 00000000..0b91c53b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/ClassifierTestTemp.recore @@ -0,0 +1,16 @@ +package TestPackage : tp = 'www.testpackage.org' +{ + private class TestClass extends SuperClass, UberClass : 'TCCname'; + public interface TestInterface extends SuperClass : 'TIname'; + enum TestEnum : 'TEname' { !serializable }; + datatype TestDataType : 'TDTname' { !serializable }; + abstract class SuperClass; + abstract class UberClass; + package SubPackage : sp = 'www.sub.testpackage.org' + { + class SubTestClass; + interface SubTestInterface; + enum SubTestEnum; + datatype SubTestDataType : 'STDTname'; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/EcoreTemp.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/EcoreTemp.ecore new file mode 100644 index 00000000..bfd3d523 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/EcoreTemp.ecore @@ -0,0 +1,445 @@ + + + + +
+ + + + + + +
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + +
+
+ + + + + + +
+ + + + + + + +
+
+ + + + + + + + + + +
+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + +
+
+ + + + +
+
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+
+ + + + +
+ + + + +
+ + + + +
+
+ + + + + +
+
+ + + + + + +
+ + + + +
+
+ + + + + + + + + + +
+ + + + +
+
+ + + + +
+ + + + +
+
+ + + + + + + + +
+ + + + +
+
+ + + + + + + + + + +
+ + + + +
+
+ + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/EcoreTemp.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/EcoreTemp.recore new file mode 100644 index 00000000..bc1149ad --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/EcoreTemp.recore @@ -0,0 +1,443 @@ +package ecore : ecore = 'http://www.eclipse.org/emf/2002/Ecore' +{ + class EAttribute extends EStructuralFeature + { + attribute iD : EBoolean[?]; + transient volatile readonly property eAttributeType : EDataType { derived }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ConsistentTransient' + ); + } + class EAnnotation extends EModelElement + { + attribute source : EString[?]; + property details : EStringToStringMapEntry[*] { ordered !resolve composes }; + transient property eModelElement#eAnnotations : EModelElement[?] { !resolve }; + property contents : EObject[*] { ordered !resolve composes }; + property references : EObject[*] { ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedSourceURI' + ); + } + class EClass extends EClassifier + { + attribute abstract : EBoolean[?]; + attribute interface : EBoolean[?]; + operation isSuperTypeOf(someClass : EClass[?]) : EBoolean[?]; + operation getFeatureCount() : EInt[?]; + operation getEStructuralFeature(featureID : EInt[?]) : EStructuralFeature[?]; + operation getFeatureID(feature : EStructuralFeature[?]) : EInt[?]; + operation getEStructuralFeature(featureName : EString[?]) : EStructuralFeature[?]; + operation getOperationCount() : EInt[?]; + operation getEOperation(operationID : EInt[?]) : EOperation[?]; + operation getOperationID(operation : EOperation[?]) : EInt[?]; + operation getOverride(operation : EOperation[?]) : EOperation[?]; + operation getFeatureType(feature : EStructuralFeature[?]) : EGenericType[?]; + property eSuperTypes : EClass[*] { ordered unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + property eOperations#eContainingClass : EOperation[*] { ordered !resolve composes }; + transient volatile readonly property eAllAttributes : EAttribute[*] { ordered derived }; + transient volatile readonly property eAllReferences : EReference[*] { ordered derived }; + transient volatile readonly property eReferences : EReference[*] { ordered derived }; + transient volatile readonly property eAttributes : EAttribute[*] { ordered derived }; + transient volatile readonly property eAllContainments : EReference[*] { ordered derived }; + transient volatile readonly property eAllOperations : EOperation[*] { ordered derived }; + transient volatile readonly property eAllStructuralFeatures : EStructuralFeature[*] { ordered derived }; + transient volatile readonly property eAllSuperTypes : EClass[*] { ordered derived }; + transient volatile readonly property eIDAttribute : EAttribute[?] { derived !resolve }; + property eStructuralFeatures#eContainingClass : EStructuralFeature[*] { ordered !resolve composes }; + property eGenericSuperTypes : EGenericType[*] { ordered unsettable !resolve composes } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + transient volatile readonly property eAllGenericSuperTypes : EGenericType[*] { ordered derived }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'InterfaceIsAbstract AtMostOneID UniqueFeatureNames UniqueOperationSignatures NoCircularSuperTypes WellFormedMapEntryClass ConsistentSuperTypes DisjointFeatureAndOperationSignatures' + ); + } + abstract class EClassifier extends ENamedElement + { + volatile attribute instanceClassName : EString[?] { unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + transient volatile readonly attribute instanceClass : EJavaClass[?] { derived }; + transient volatile readonly attribute defaultValue : EJavaObject[?] { derived }; + volatile attribute instanceTypeName : EString[?] { unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + operation isInstance(object : EJavaObject[?]) : EBoolean[?]; + operation getClassifierID() : EInt[?]; + transient readonly property ePackage#eClassifiers : EPackage[?]; + property eTypeParameters : ETypeParameter[*] { ordered composes }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedInstanceTypeName UniqueTypeParameterNames' + ); + } + class EDataType extends EClassifier + { + attribute serializable : EBoolean[?] = 'true'; + } + class EEnum extends EDataType + { + operation getEEnumLiteral(name : EString[?]) : EEnumLiteral[?]; + operation getEEnumLiteral(value : EInt[?]) : EEnumLiteral[?]; + operation getEEnumLiteralByLiteral(literal : EString[?]) : EEnumLiteral[?]; + property eLiterals#eEnum : EEnumLiteral[*] { ordered !resolve composes }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'UniqueEnumeratorNames UniqueEnumeratorLiterals' + ); + } + class EEnumLiteral extends ENamedElement + { + attribute value : EInt[?]; + transient attribute instance : EEnumerator[?]; + attribute literal : EString[?]; + transient readonly property eEnum#eLiterals : EEnum[?] { !resolve }; + } + class EFactory extends EModelElement + { + operation create(eClass : EClass[?]) : EObject[?]; + operation createFromString(eDataType : EDataType[?], literalValue : EString[?]) : EJavaObject[?]; + operation convertToString(eDataType : EDataType[?], instanceValue : EJavaObject[?]) : EString[?]; + transient property ePackage#eFactoryInstance : EPackage { !resolve }; + } + abstract class EModelElement + { + operation getEAnnotation(source : EString[?]) : EAnnotation[?]; + property eAnnotations#eModelElement : EAnnotation[*] { ordered !resolve composes }; + } + abstract class ENamedElement extends EModelElement + { + attribute name : EString[?]; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedName' + ); + } + class EObject + { + operation eClass() : EClass[?]; + operation eIsProxy() : EBoolean[?]; + operation eResource() : EResource[?]; + operation eContainer() : EObject[?]; + operation eContainingFeature() : EStructuralFeature[?]; + operation eContainmentFeature() : EReference[?]; + operation eContents() : EEList[?]; + operation eAllContents() : ETreeIterator[?]; + operation eCrossReferences() : EEList[?]; + operation eGet(feature : EStructuralFeature[?]) : EJavaObject[?]; + operation eGet(feature : EStructuralFeature[?], resolve : EBoolean[?]) : EJavaObject[?]; + operation eSet(feature : EStructuralFeature[?], newValue : EJavaObject[?]); + operation eIsSet(feature : EStructuralFeature[?]) : EBoolean[?]; + operation eUnset(feature : EStructuralFeature[?]); + operation eInvoke(operation : EOperation[?], arguments : EEList[?]) : EJavaObject[?] throws EInvocationTargetException; + } + class EOperation extends ETypedElement + { + operation getOperationID() : EInt[?]; + operation isOverrideOf(someOperation : EOperation[?]) : EBoolean[?]; + transient readonly property eContainingClass#eOperations : EClass[?] { !resolve }; + property eTypeParameters : ETypeParameter[*] { ordered composes }; + property eParameters#eOperation : EParameter[*] { ordered !resolve composes }; + property eExceptions : EClassifier[*] { ordered unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + property eGenericExceptions : EGenericType[*] { ordered unsettable !resolve composes } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'UniqueParameterNames UniqueTypeParameterNames NoRepeatingVoid' + ); + } + class EPackage extends ENamedElement + { + attribute nsURI : EString[?]; + attribute nsPrefix : EString[?]; + operation getEClassifier(name : EString[?]) : EClassifier[?]; + transient property eFactoryInstance#ePackage : EFactory { !resolve }; + property eClassifiers#ePackage : EClassifier[*] { ordered composes }; + property eSubpackages#eSuperPackage : EPackage[*] { ordered composes }; + transient readonly property eSuperPackage#eSubpackages : EPackage[?]; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedNsURI WellFormedNsPrefix UniqueSubpackageNames UniqueClassifierNames UniqueNsURIs' + ); + } + class EParameter extends ETypedElement + { + transient readonly property eOperation#eParameters : EOperation[?] { !resolve }; + } + class EReference extends EStructuralFeature + { + attribute containment : EBoolean[?]; + transient volatile readonly attribute container : EBoolean[?] { derived }; + attribute resolveProxies : EBoolean[?] = 'true'; + property eOpposite : EReference[?]; + transient volatile readonly property eReferenceType : EClass { derived }; + property eKeys : EAttribute[*] { ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ConsistentOpposite SingleContainer ConsistentKeys ConsistentUnique ConsistentContainer' + ); + } + abstract class EStructuralFeature extends ETypedElement + { + attribute changeable : EBoolean[?] = 'true'; + attribute volatile : EBoolean[?]; + attribute transient : EBoolean[?]; + attribute defaultValueLiteral : EString[?]; + transient volatile readonly attribute defaultValue : EJavaObject[?] { derived }; + attribute unsettable : EBoolean[?]; + attribute derived : EBoolean[?]; + operation getFeatureID() : EInt[?]; + operation getContainerClass() : EJavaClass[?]; + transient readonly property eContainingClass#eStructuralFeatures : EClass[?] { !resolve }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ValidDefaultValueLiteral' + ); + } + abstract class ETypedElement extends ENamedElement + { + attribute ordered : EBoolean[?] = 'true'; + attribute unique : EBoolean[?] = 'true'; + attribute lowerBound : EInt[?]; + attribute upperBound : EInt[?] = '1'; + transient volatile readonly attribute many : EBoolean[?] { derived }; + transient volatile readonly attribute required : EBoolean[?] { derived }; + volatile property eType : EClassifier[?] { unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + volatile property eGenericType : EGenericType[?] { unsettable !resolve composes } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ValidLowerBound ValidUpperBound ConsistentBounds ValidType' + ); + } + datatype EBigDecimal : 'java.math.BigDecimal' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#decimal' + ); + } + datatype EBigInteger : 'java.math.BigInteger' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#integer' + ); + } + datatype EBoolean : 'boolean' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#boolean' + ); + } + datatype EBooleanObject : 'java.lang.Boolean' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EBoolean', + 'name' = 'EBoolean:Object' + ); + } + datatype EByte : 'byte' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#byte' + ); + } + datatype EByteArray : 'byte[]' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#hexBinary' + ); + } + datatype EByteObject : 'java.lang.Byte' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EByte', + 'name' = 'EByte:Object' + ); + } + datatype EChar : 'char'; + datatype ECharacterObject : 'java.lang.Character' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EChar', + 'name' = 'EChar:Object' + ); + } + datatype EDate : 'java.util.Date'; + datatype EDiagnosticChain : 'org.eclipse.emf.common.util.DiagnosticChain' { !serializable }; + datatype EDouble : 'double' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#double' + ); + } + datatype EDoubleObject : 'java.lang.Double' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EDouble', + 'name' = 'EDouble:Object' + ); + } + datatype EEList : 'org.eclipse.emf.common.util.EList' { !serializable }; + datatype EEnumerator : 'org.eclipse.emf.common.util.Enumerator' { !serializable }; + datatype EFeatureMap : 'org.eclipse.emf.ecore.util.FeatureMap' { !serializable }; + datatype EFeatureMapEntry : 'org.eclipse.emf.ecore.util.FeatureMap$Entry' { !serializable }; + datatype EFloat : 'float' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#float' + ); + } + datatype EFloatObject : 'java.lang.Float' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EFloat', + 'name' = 'EFloat:Object' + ); + } + datatype EInt : 'int' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#int' + ); + } + datatype EIntegerObject : 'java.lang.Integer' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EInt', + 'name' = 'EInt:Object' + ); + } + datatype EJavaClass : 'java.lang.Class'; + datatype EJavaObject : 'java.lang.Object'; + datatype ELong : 'long' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#long' + ); + } + datatype ELongObject : 'java.lang.Long' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'ELong', + 'name' = 'ELong:Object' + ); + } + datatype EMap : 'java.util.Map' { !serializable }; + datatype EResource : 'org.eclipse.emf.ecore.resource.Resource' { !serializable }; + datatype EResourceSet : 'org.eclipse.emf.ecore.resource.ResourceSet' { !serializable }; + datatype EShort : 'short' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#short' + ); + } + datatype EShortObject : 'java.lang.Short' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EShort', + 'name' = 'EShort:Object' + ); + } + datatype EString : 'java.lang.String' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#string' + ); + } + class EStringToStringMapEntry : 'java.util.Map$Entry' + { + attribute key : EString[?]; + attribute value : EString[?]; + } + datatype ETreeIterator : 'org.eclipse.emf.common.util.TreeIterator' { !serializable }; + class EGenericType + { + operation isInstance(object : EJavaObject[?]) : EBoolean[?]; + property eUpperBound : EGenericType[?] { !resolve composes }; + property eTypeArguments : EGenericType[*] { ordered !resolve composes }; + transient readonly property eRawType : EClassifier { derived }; + property eLowerBound : EGenericType[?] { !resolve composes }; + property eTypeParameter : ETypeParameter[?] { !resolve }; + property eClassifier : EClassifier[?]; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ConsistentType ConsistentBounds ConsistentArguments' + ); + } + class ETypeParameter extends ENamedElement + { + property eBounds : EGenericType[*] { ordered !resolve composes }; + } + datatype EInvocationTargetException : 'java.lang.reflect.InvocationTargetException' { !serializable }; +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/GenericsTestTemp.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/GenericsTestTemp.ecore new file mode 100644 index 00000000..f312d0c5 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/GenericsTestTemp.ecore @@ -0,0 +1,73 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/GenericsTestTemp.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/GenericsTestTemp.recore new file mode 100644 index 00000000..af28250a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/GenericsTestTemp.recore @@ -0,0 +1,23 @@ +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package generics : gns = 'eu.modelwriter.generics' +{ + abstract class List + { + operation add(element : E); + operation iterator() : Iterator[?]; + } + class Iterator + { + operation next() : E[?]; + operation hasNext() : Boolean; + } + class ArrayList extends List; + class Car; + abstract class Person; + class Owner, ?>>>>> extends ArrayList + { + property cars : ArrayList[?] { !resolve }; + property attr1 : K[?] { !resolve }; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/OperationTestTemp.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/OperationTestTemp.ecore new file mode 100644 index 00000000..c4d873f2 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/OperationTestTemp.ecore @@ -0,0 +1,115 @@ + + + +
+ + + +
+ + + +
+ + +
+
+
+ + +
+
+ + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+
+ + + + + + + + + + + + + +
+ + +
+
+
+ + +
+
+ + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/OperationTestTemp.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/OperationTestTemp.recore new file mode 100644 index 00000000..36971f7d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/OperationTestTemp.recore @@ -0,0 +1,47 @@ +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package TestPackage : tp = 'www.testpackage.org' +{ + private class TestClass extends SuperClass, UberClass : 'TCname' + { + private static operation testOp(testParam : Boolean[?], testParam2 : Ecore::EChar[+] { ordered }) : String[?] throws TestPackage::SubPackage::SubTestInterface, TestPackage::SubPackage::SubTestClass + { + requires testPre ("Hey!") : lone testOp; + body testPre : testOp; + ensures testPost ("Hey!") : one testOp; + } + operation testOp1() : TestDataType[?]; + operation testOp2() : TestDataType; + operation testOp3() : TestDataType[*] { ordered }; + operation testOp4() : TestDataType[+] { ordered }; + operation testOp5() : TestDataType[3..6] { ordered }; + operation testVoidOp() + { + requires testPre ("Hey!") : lone testOp; + body testBody : testOp; + ensures testPost ("Hey!") : one testOp; + ensures testPost2 ("Hey!") : one testOp; + } + operation testOp6() : TestDataType[*|?] { ordered }; + operation testOp7() : TestDataType[+|?] { ordered }; + operation testOp8() : TestDataType[3..6|?] { ordered }; + private static operation testOp9(testParam : Boolean[+|?] { ordered }, testParam2 : Ecore::EChar[2|?] { ordered }) : String[?] throws TestPackage::SubPackage::SubTestInterface, TestPackage::SubPackage::SubTestClass + { + requires testPre ("Hey!") : lone testOp; + body testPre : testOp; + ensures testPost ("Hey!") : one testOp; + } + } + interface TestInterface extends SuperClass : 'TIname'; + enum TestEnum : 'TEname' { !serializable }; + primitive datatype TestDataType : 'TDTname' { !serializable }; + abstract class SuperClass; + abstract class UberClass; + package SubPackage : sp = 'www.sub.testpackage.org' + { + class SubTestClass; + interface SubTestInterface; + enum SubTestEnum; + datatype SubTestDataType : 'STDTname'; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/PackageTestTemp.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/PackageTestTemp.ecore new file mode 100644 index 00000000..8b3d088a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/PackageTestTemp.ecore @@ -0,0 +1,14 @@ + + + + +
+ + + +
+ + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/PackageTestTemp.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/PackageTestTemp.recore new file mode 100644 index 00000000..cf1e0dbe --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/PackageTestTemp.recore @@ -0,0 +1,8 @@ +package TestPackage : tp = 'www.testpackage.org' +{ + public package SubPackage1 : sp1 = 'www.sub1.testpackage.org' + { + private package SubSubPackage : ssp = 'www.sub.sub1.testpackage.org'; + } + package SubPackage2 : sp2 = 'www.sub2.testpackage.org'; +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/ReferenceTestTemp.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/ReferenceTestTemp.ecore new file mode 100644 index 00000000..60c7c537 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/ReferenceTestTemp.ecore @@ -0,0 +1,54 @@ + + + + +
+ + + +
+ + +
+
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/ReferenceTestTemp.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/ReferenceTestTemp.recore new file mode 100644 index 00000000..e1a30f55 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/ReferenceTestTemp.recore @@ -0,0 +1,41 @@ +package TestPackage : tp = 'www.testpackage.org' +{ + private class TestClass extends SuperClass, UberClass : 'TCname' + { + private static model transient volatile readonly property testRef : TestPackage::SubPackage::SubTestClass[?] { derived unsettable composes } + { + derivation testDerivation : ~testRef; + } + property testRef2 : TestInterface[?] { !resolve }; + property testRef3 : TestInterface { !resolve }; + property testRef4 : TestInterface[*] { !resolve }; + property testRef5 : TestInterface[1..5]; + property testRef6 : TestInterface[+] { !resolve }; + property testRefWithExp : TestInterface[?] { !resolve } + { + initial : ~testRef; + } + property testRefWithKey : TestInterface[?] { !resolve } + { + key testAttr; + } + property testRef7 : TestInterface[*|?] { !resolve }; + property testRef8 : TestInterface[1..5|?]; + property testRef9 : TestInterface[+|?] { !resolve }; + } + interface TestInterface extends SuperClass : 'TIname' + { + attribute testAttr : TestDataType[?]; + } + enum TestEnum : 'TEname'; + primitive datatype TestDataType : 'TDTname'; + abstract class SuperClass; + abstract class UberClass; + package SubPackage : sp = 'www.sub.testpackage.org' + { + class SubTestClass; + interface SubTestInterface; + enum SubTestEnum { !serializable }; + datatype SubTestDataType : 'STDTname' { !serializable }; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/TestTemp.ecore b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/TestTemp.ecore new file mode 100644 index 00000000..769be836 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/TestTemp.ecore @@ -0,0 +1,111 @@ + + + +
+
+
+ + +
+ + +
+ + +
+ + + +
+ + + + + + + + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/TestTemp.recore b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/TestTemp.recore new file mode 100644 index 00000000..63c730f1 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.mapping/testTemp/TestTemp.recore @@ -0,0 +1,100 @@ +import FordOtosan : 'FordOtosan.ecore'; +import extlibrary : 'extlibrary.ecore'; +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' +{ + public class Library + { + attribute name : String + { + annotation; + } + property books#library : Book[*] { composes } + { + annotation 'sadasdas'; + } + static property loans : Loan[*] { composes }; + property members#library : Member[*] { composes }; + } + class Book + { + attribute name : String; + attribute copies : UnlimitedNatural; + operation isAvailable(param1 : Boolean[?], param2 : Book[?]) : Boolean[?] + { + body; + ensures sup ("this is a precondition"); + } + property library#books : Library[?]; + volatile property loans : Loan[*] { derived } + { + derivation : library.loans->select; + } + invariant importantConstraint ("multi + lined + message"); + } + class Member + { + attribute name : String; + operation tespOP(); + property library#members : Library[?]; + volatile property loans : Loan[*] { derived } + { + derivation : library.loans->select; + } + volatile property books : Book[*] { !unique derived } + { + derivation : loans->collect; + } + } + class Loan + { + attribute date : Ecore::EDate[?]; + property book : tutorial::Organization::SubOrg1::sb1C; + property member : Member; + annotation + { + reference tutorial::Organization::Librarian::orgOpp; + } + } + package Organization : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization' + { + enum Type { !serializable } + { + literal asd = 0; + } + datatype JavaPackage : 'java.lang.Package' { !serializable }; + class Librarian extends extlibrary::Employee + { + operation orgOpp() : Ecore::ELong[?]; + property workOn : tutorial::Organization::SubOrg2::sb2C[?]; + } + class Ref extends tutorial::Library + { + property RefOutsideEcore : extlibrary::Item[?]; + } + package SubOrg1 : sb = 'suborg1' + { + class sb1C; + } + package SubOrg2 : sb2 = 'SubOrg2' + { + class sb2C; + } + annotation 'extAnno' + { + reference extlibrary::Item; + reference extlibrary::Item::publicationDate; + reference FordOtosan::Container::vehicle; + reference FordOtosan::Vehicle::ElectricalPowerSupplySystem::ElectricalPowerSupplySystem::electricalPowerSupplySystemPart; + } + } + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'invocationDelegates' = 'http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot', + 'settingDelegates' = 'http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot', + 'validationDelegates' = 'http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot' + ); +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/.classpath b/Source/eu.modelwriter.core.alloyinecore.ui/.classpath new file mode 100644 index 00000000..6b644f8e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/.gitignore b/Source/eu.modelwriter.core.alloyinecore.ui/.gitignore new file mode 100644 index 00000000..14dc313e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/testTemp \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/.project b/Source/eu.modelwriter.core.alloyinecore.ui/.project new file mode 100644 index 00000000..90eaaf4a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/.project @@ -0,0 +1,34 @@ + + + eu.modelwriter.core.alloyinecore.ui + + + + + + net.certiv.stdt.core.builder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + net.certiv.stdt.core.nature + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/.settings/org.eclipse.jdt.core.prefs b/Source/eu.modelwriter.core.alloyinecore.ui/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..0c68a61d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/META-INF/MANIFEST.MF b/Source/eu.modelwriter.core.alloyinecore.ui/META-INF/MANIFEST.MF new file mode 100644 index 00000000..81387854 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/META-INF/MANIFEST.MF @@ -0,0 +1,24 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Ui +Bundle-SymbolicName: eu.modelwriter.core.alloyinecore.ui;singleton:=true +Bundle-Version: 1.0.0.qualifier +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.ui, + org.eclipse.jface.text, + org.eclipse.ui.editors, + eu.modelwriter.configuration;bundle-version="1.0.0", + org.eclipse.ui.workbench, + org.eclipse.ui.ide;bundle-version="3.12.0", + eu.modelwriter.core.alloyinecore.mapping, + org.eclipse.emf.ecore.xmi;bundle-version="2.12.0", + org.eclipse.emf.ecore.editor +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Import-Package: org.eclipse.core.resources, + org.eclipse.ui.texteditor.rulers, + org.eclipse.ui.views.contentoutline +Bundle-ClassPath: lib/eu.modelwriter.core.alloyinecore.jar, + lib/antlr-4.6-complete.jar, + . +Bundle-Activator: eu.modelwriter.core.alloyinecore.ui.Activator +Bundle-ActivationPolicy: lazy diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/build.properties b/Source/eu.modelwriter.core.alloyinecore.ui/build.properties new file mode 100644 index 00000000..8f12959a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/build.properties @@ -0,0 +1,7 @@ +source.. = src/ +output.. = bin/ +bin.includes = plugin.xml,\ + META-INF/,\ + .,\ + icons/,\ + lib/ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/And.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/And.png new file mode 100644 index 00000000..58d9be49 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/And.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Brackets.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Brackets.png new file mode 100644 index 00000000..27d5e495 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Brackets.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Closure.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Closure.png new file mode 100644 index 00000000..d942c3f8 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Closure.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Count.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Count.png new file mode 100644 index 00000000..0c9f8f82 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Count.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Difference.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Difference.png new file mode 100644 index 00000000..c21fd85b Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Difference.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Divide.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Divide.png new file mode 100644 index 00000000..4952b6f8 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Divide.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Equal.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Equal.png new file mode 100644 index 00000000..171f8b65 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Equal.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/False.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/False.png new file mode 100644 index 00000000..b2e520dc Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/False.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/ForAll.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/ForAll.png new file mode 100644 index 00000000..8a77087b Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/ForAll.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/ForLone.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/ForLone.png new file mode 100644 index 00000000..4bba5add Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/ForLone.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/ForNo.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/ForNo.png new file mode 100644 index 00000000..fec530dd Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/ForNo.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/ForOne.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/ForOne.png new file mode 100644 index 00000000..4bba5add Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/ForOne.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/ForSome.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/ForSome.png new file mode 100644 index 00000000..bcfb0897 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/ForSome.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Function.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Function.png new file mode 100644 index 00000000..fcd303a9 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Function.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Gte.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Gte.png new file mode 100644 index 00000000..5c257d65 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Gte.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Iden.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Iden.png new file mode 100644 index 00000000..2cedef88 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Iden.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Identical.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Identical.png new file mode 100644 index 00000000..ed51a95b Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Identical.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Iff.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Iff.png new file mode 100644 index 00000000..ae72948d Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Iff.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Implies.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Implies.png new file mode 100644 index 00000000..e8f33770 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Implies.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/In.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/In.png new file mode 100644 index 00000000..55a6a067 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/In.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/IntConstant.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/IntConstant.png new file mode 100644 index 00000000..d7d547d3 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/IntConstant.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Intersection.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Intersection.png new file mode 100644 index 00000000..97e484fb Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Intersection.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Ints.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Ints.png new file mode 100644 index 00000000..5ea4488a Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Ints.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Join.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Join.png new file mode 100644 index 00000000..5dc199d9 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Join.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Lone.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Lone.png new file mode 100644 index 00000000..e801e08e Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Lone.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/LoneOf.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/LoneOf.png new file mode 100644 index 00000000..ad336ba6 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/LoneOf.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Lt.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Lt.png new file mode 100644 index 00000000..7ce7cce6 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Lt.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Lte.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Lte.png new file mode 100644 index 00000000..fe5b9c93 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Lte.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Minus.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Minus.png new file mode 100644 index 00000000..50f19adb Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Minus.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Modulo.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Modulo.png new file mode 100644 index 00000000..bfa343cc Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Modulo.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Multiply.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Multiply.png new file mode 100644 index 00000000..2a70a87c Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Multiply.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/None.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/None.png new file mode 100644 index 00000000..334d3091 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/None.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Not.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Not.png new file mode 100644 index 00000000..ca12b030 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Not.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotEqual.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotEqual.png new file mode 100644 index 00000000..d95afd32 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotEqual.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotGt.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotGt.png new file mode 100644 index 00000000..a3102463 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotGt.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotGte.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotGte.png new file mode 100644 index 00000000..9b92b237 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotGte.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotIdentical.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotIdentical.png new file mode 100644 index 00000000..e76f65ca Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotIdentical.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotIn.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotIn.png new file mode 100644 index 00000000..de80cd96 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotIn.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotLt.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotLt.png new file mode 100644 index 00000000..c916cc13 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotLt.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotLte.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotLte.png new file mode 100644 index 00000000..02cab15a Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/NotLte.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/One.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/One.png new file mode 100644 index 00000000..8de0b9f4 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/One.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/OneOf.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/OneOf.png new file mode 100644 index 00000000..ad336ba6 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/OneOf.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Or.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Or.png new file mode 100644 index 00000000..aaac855d Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Or.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/PartialFunction.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/PartialFunction.png new file mode 100644 index 00000000..74d9691f Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/PartialFunction.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Plus.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Plus.png new file mode 100644 index 00000000..72eab27b Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Plus.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Product.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Product.png new file mode 100644 index 00000000..86c0526e Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Product.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/QuantifierDeclaration.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/QuantifierDeclaration.png new file mode 100644 index 00000000..ad336ba6 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/QuantifierDeclaration.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Reason.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Reason.png new file mode 100644 index 00000000..4bbd63bf Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Reason.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Reflexive.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Reflexive.png new file mode 100644 index 00000000..7111b5b0 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Reflexive.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Relation.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Relation.png new file mode 100644 index 00000000..d1bfd3e7 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Relation.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/SetComprehension.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/SetComprehension.png new file mode 100644 index 00000000..55d12fb2 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/SetComprehension.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/SetOf.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/SetOf.png new file mode 100644 index 00000000..ad336ba6 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/SetOf.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Some.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Some.png new file mode 100644 index 00000000..84f3f498 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Some.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/SomeOf.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/SomeOf.png new file mode 100644 index 00000000..ad336ba6 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/SomeOf.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/SumDeclaration.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/SumDeclaration.png new file mode 100644 index 00000000..5327455e Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/SumDeclaration.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Tranpose.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Tranpose.png new file mode 100644 index 00000000..810ad0d6 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Tranpose.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/True.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/True.png new file mode 100644 index 00000000..e46c5ba7 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/True.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Union.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Union.png new file mode 100644 index 00000000..eeefcbfd Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Union.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Univ.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Univ.png new file mode 100644 index 00000000..be810fd2 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Univ.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Variable.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Variable.png new file mode 100644 index 00000000..b90fee8a Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/Variable.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/no.png b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/no.png new file mode 100644 index 00000000..cf35c42b Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16-png/no.png differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/And.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/And.svg new file mode 100644 index 00000000..7619a283 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/And.svg @@ -0,0 +1,53 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Binding.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Binding.svg new file mode 100644 index 00000000..7ae93bd5 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Binding.svg @@ -0,0 +1,61 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Brackets.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Brackets.svg new file mode 100644 index 00000000..1811e024 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Brackets.svg @@ -0,0 +1,101 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Closure.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Closure.svg new file mode 100644 index 00000000..1c4f4ab1 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Closure.svg @@ -0,0 +1,53 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Count.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Count.svg new file mode 100644 index 00000000..91d8244e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Count.svg @@ -0,0 +1,97 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Difference.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Difference.svg new file mode 100644 index 00000000..400ca533 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Difference.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Divide.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Divide.svg new file mode 100644 index 00000000..8bf6aade --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Divide.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Equal.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Equal.svg new file mode 100644 index 00000000..dd91eefe --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Equal.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/False.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/False.svg new file mode 100644 index 00000000..c6defdd3 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/False.svg @@ -0,0 +1,53 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/ForAll.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/ForAll.svg new file mode 100644 index 00000000..17fba10d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/ForAll.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/ForLone.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/ForLone.svg new file mode 100644 index 00000000..efdb0d75 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/ForLone.svg @@ -0,0 +1,61 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/ForNo.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/ForNo.svg new file mode 100644 index 00000000..434ce27b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/ForNo.svg @@ -0,0 +1,60 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/ForOne.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/ForOne.svg new file mode 100644 index 00000000..efdb0d75 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/ForOne.svg @@ -0,0 +1,61 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/ForSome.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/ForSome.svg new file mode 100644 index 00000000..af76c588 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/ForSome.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Function.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Function.svg new file mode 100644 index 00000000..87529232 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Function.svg @@ -0,0 +1,64 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Gte.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Gte.svg new file mode 100644 index 00000000..f83547a3 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Gte.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Iden.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Iden.svg new file mode 100644 index 00000000..67ce5e01 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Iden.svg @@ -0,0 +1,48 @@ + + + + + + + image/svg+xml + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Identical.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Identical.svg new file mode 100644 index 00000000..d6eccc4f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Identical.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Iff.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Iff.svg new file mode 100644 index 00000000..e8efb834 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Iff.svg @@ -0,0 +1,53 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Implies.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Implies.svg new file mode 100644 index 00000000..abbcb5f7 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Implies.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/In.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/In.svg new file mode 100644 index 00000000..33c2dad7 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/In.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/IntConstant.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/IntConstant.svg new file mode 100644 index 00000000..a3ce66be --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/IntConstant.svg @@ -0,0 +1,43 @@ + + + + + + + image/svg+xml + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Intersection.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Intersection.svg new file mode 100644 index 00000000..03386b78 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Intersection.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Ints.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Ints.svg new file mode 100644 index 00000000..48ecb70f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Ints.svg @@ -0,0 +1,37 @@ + + + + + + + image/svg+xml + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Join.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Join.svg new file mode 100644 index 00000000..50bee454 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Join.svg @@ -0,0 +1,70 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Lone.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Lone.svg new file mode 100644 index 00000000..fefe1cb7 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Lone.svg @@ -0,0 +1,48 @@ + + + + + + + image/svg+xml + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/LoneOf.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/LoneOf.svg new file mode 100644 index 00000000..2907cb3b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/LoneOf.svg @@ -0,0 +1,52 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Lt.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Lt.svg new file mode 100644 index 00000000..82e5bd74 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Lt.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Lte.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Lte.svg new file mode 100644 index 00000000..88bcc02f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Lte.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Minus.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Minus.svg new file mode 100644 index 00000000..e6828ae0 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Minus.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Modulo.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Modulo.svg new file mode 100644 index 00000000..b98b0428 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Modulo.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Multiply.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Multiply.svg new file mode 100644 index 00000000..4dd6d80e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Multiply.svg @@ -0,0 +1,51 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/None.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/None.svg new file mode 100644 index 00000000..fe8f17ca --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/None.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Not.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Not.svg new file mode 100644 index 00000000..19fbc34e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Not.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotEqual.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotEqual.svg new file mode 100644 index 00000000..a39a0ab9 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotEqual.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotGt.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotGt.svg new file mode 100644 index 00000000..a8a6e98d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotGt.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotGte.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotGte.svg new file mode 100644 index 00000000..3cc9f464 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotGte.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotIdentical.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotIdentical.svg new file mode 100644 index 00000000..811f420d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotIdentical.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotIn.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotIn.svg new file mode 100644 index 00000000..309992f2 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotIn.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotLt.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotLt.svg new file mode 100644 index 00000000..917b09cf --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotLt.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotLte.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotLte.svg new file mode 100644 index 00000000..3153e2b5 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/NotLte.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/One.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/One.svg new file mode 100644 index 00000000..1dfded3e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/One.svg @@ -0,0 +1,44 @@ + + + + + + + image/svg+xml + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/OneOf.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/OneOf.svg new file mode 100644 index 00000000..2907cb3b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/OneOf.svg @@ -0,0 +1,52 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Or.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Or.svg new file mode 100644 index 00000000..6dbea796 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Or.svg @@ -0,0 +1,54 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/PartialFunction.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/PartialFunction.svg new file mode 100644 index 00000000..bf014c65 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/PartialFunction.svg @@ -0,0 +1,58 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Plus.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Plus.svg new file mode 100644 index 00000000..6d487741 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Plus.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Product.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Product.svg new file mode 100644 index 00000000..fd718871 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Product.svg @@ -0,0 +1,52 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Reason.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Reason.svg new file mode 100644 index 00000000..4bd2b081 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Reason.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Reflexive.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Reflexive.svg new file mode 100644 index 00000000..2193b1e1 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Reflexive.svg @@ -0,0 +1,59 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Relation.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Relation.svg new file mode 100644 index 00000000..8759ba56 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Relation.svg @@ -0,0 +1,57 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/SetComprehension.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/SetComprehension.svg new file mode 100644 index 00000000..a36bb413 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/SetComprehension.svg @@ -0,0 +1,110 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/SetOf.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/SetOf.svg new file mode 100644 index 00000000..2907cb3b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/SetOf.svg @@ -0,0 +1,52 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Some.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Some.svg new file mode 100644 index 00000000..8447784e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Some.svg @@ -0,0 +1,48 @@ + + + + + + + image/svg+xml + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/SomeOf.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/SomeOf.svg new file mode 100644 index 00000000..2907cb3b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/SomeOf.svg @@ -0,0 +1,52 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/SumDeclaration.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/SumDeclaration.svg new file mode 100644 index 00000000..28173fce --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/SumDeclaration.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Tranpose.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Tranpose.svg new file mode 100644 index 00000000..93d9e02d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Tranpose.svg @@ -0,0 +1,53 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/True.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/True.svg new file mode 100644 index 00000000..e8936e26 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/True.svg @@ -0,0 +1,53 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Union.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Union.svg new file mode 100644 index 00000000..89b540ac --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Union.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Univ.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Univ.svg new file mode 100644 index 00000000..3b67c546 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Univ.svg @@ -0,0 +1,48 @@ + + + + + + + image/svg+xml + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Variable.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Variable.svg new file mode 100644 index 00000000..7ae93bd5 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/Variable.svg @@ -0,0 +1,61 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/no.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/no.svg new file mode 100644 index 00000000..330c77a4 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/exp16/no.svg @@ -0,0 +1,40 @@ + + + + + + + image/svg+xml + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Annotation.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Annotation.gif new file mode 100644 index 00000000..0df81a30 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Annotation.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/AnnotationDetail.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/AnnotationDetail.gif new file mode 100644 index 00000000..97aad290 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/AnnotationDetail.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/AnnotationReference.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/AnnotationReference.gif new file mode 100644 index 00000000..94c29f7a Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/AnnotationReference.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Attribute.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Attribute.gif new file mode 100644 index 00000000..99b7fa68 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Attribute.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Body.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Body.gif new file mode 100644 index 00000000..6f47c932 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Body.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/BooleanValue.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/BooleanValue.gif new file mode 100644 index 00000000..656797fe Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/BooleanValue.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Class.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Class.gif new file mode 100644 index 00000000..7c33c76a Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Class.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Comment.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Comment.gif new file mode 100644 index 00000000..c495731c Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Comment.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/DataType.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/DataType.gif new file mode 100644 index 00000000..b4337de6 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/DataType.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Derivation.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Derivation.gif new file mode 100644 index 00000000..58e21289 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Derivation.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Detail.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Detail.gif new file mode 100644 index 00000000..97aad290 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Detail.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/EObject.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/EObject.gif new file mode 100644 index 00000000..c06911ab Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/EObject.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/EcoreImport.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/EcoreImport.gif new file mode 100644 index 00000000..4b5f91e7 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/EcoreImport.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ElementImport.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ElementImport.gif new file mode 100644 index 00000000..dd39064b Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ElementImport.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Enum.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Enum.gif new file mode 100644 index 00000000..c7573bde Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Enum.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/EnumLiteral.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/EnumLiteral.gif new file mode 100644 index 00000000..4967b569 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/EnumLiteral.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/GenericElementType.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/GenericElementType.gif new file mode 100644 index 00000000..64cb00bb Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/GenericElementType.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/GenericException.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/GenericException.gif new file mode 100644 index 00000000..c5bd8803 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/GenericException.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/GenericSuperType.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/GenericSuperType.gif new file mode 100644 index 00000000..ee656d64 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/GenericSuperType.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/GenericType.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/GenericType.gif new file mode 100644 index 00000000..d85b06b9 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/GenericType.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/GenericTypeArgument.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/GenericTypeArgument.gif new file mode 100644 index 00000000..3eb5e02a Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/GenericTypeArgument.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/GenericWildcard.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/GenericWildcard.gif new file mode 100644 index 00000000..da2f5771 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/GenericWildcard.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Import.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Import.gif new file mode 100644 index 00000000..4b5f91e7 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Import.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ImportedClass.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ImportedClass.gif new file mode 100644 index 00000000..7c33c76a Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ImportedClass.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ImportedDataType.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ImportedDataType.gif new file mode 100644 index 00000000..b4337de6 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ImportedDataType.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ImportedEnum.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ImportedEnum.gif new file mode 100644 index 00000000..c7573bde Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ImportedEnum.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ImportedInterface.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ImportedInterface.gif new file mode 100644 index 00000000..8032f5e4 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ImportedInterface.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ImportedPackage.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ImportedPackage.gif new file mode 100644 index 00000000..f844ade1 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ImportedPackage.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Initial.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Initial.gif new file mode 100644 index 00000000..6f2c4134 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Initial.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Instance.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Instance.gif new file mode 100644 index 00000000..36a276db Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Instance.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/IntegerValue.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/IntegerValue.gif new file mode 100644 index 00000000..3bd99b38 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/IntegerValue.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Interface.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Interface.gif new file mode 100644 index 00000000..8032f5e4 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Interface.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Invariant.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Invariant.gif new file mode 100644 index 00000000..855596e7 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Invariant.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Model.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Model.gif new file mode 100644 index 00000000..36a276db Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Model.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ModelImport.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ModelImport.gif new file mode 100644 index 00000000..4b7c2ffb Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ModelImport.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Multiplicity.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Multiplicity.gif new file mode 100644 index 00000000..24def025 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Multiplicity.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/NullValue.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/NullValue.gif new file mode 100644 index 00000000..d28f9ccf Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/NullValue.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Object.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Object.gif new file mode 100644 index 00000000..c06911ab Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Object.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ObjectValue.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ObjectValue.gif new file mode 100644 index 00000000..b821b12e Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/ObjectValue.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Operation.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Operation.gif new file mode 100644 index 00000000..482a4d51 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Operation.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Package.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Package.gif new file mode 100644 index 00000000..f844ade1 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Package.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Parameter.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Parameter.gif new file mode 100644 index 00000000..b156d849 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Parameter.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/PostCondition.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/PostCondition.gif new file mode 100644 index 00000000..2cf653b0 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/PostCondition.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/PreCondition.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/PreCondition.gif new file mode 100644 index 00000000..7f8a3faa Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/PreCondition.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/PrimitiveType.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/PrimitiveType.gif new file mode 100644 index 00000000..f516ab33 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/PrimitiveType.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/RealValue.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/RealValue.gif new file mode 100644 index 00000000..8bbd7227 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/RealValue.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Reference.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Reference.gif new file mode 100644 index 00000000..99b7fa68 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Reference.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/RootPackage.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/RootPackage.gif new file mode 100644 index 00000000..f844ade1 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/RootPackage.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Slot.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Slot.gif new file mode 100644 index 00000000..c7ebf6aa Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/Slot.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/StringValue.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/StringValue.gif new file mode 100644 index 00000000..ef367ef6 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/StringValue.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/TypeParameter.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/TypeParameter.gif new file mode 100644 index 00000000..e59fabc4 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/TypeParameter.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/UnlimitedNaturalValue.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/UnlimitedNaturalValue.gif new file mode 100644 index 00000000..f1f01953 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/obj16/UnlimitedNaturalValue.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/And.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/And.svg new file mode 100644 index 00000000..5201c018 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/And.svg @@ -0,0 +1,66 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Brackets.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Brackets.svg new file mode 100644 index 00000000..7adc75b4 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Brackets.svg @@ -0,0 +1,131 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Closure.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Closure.svg new file mode 100644 index 00000000..c526de6f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Closure.svg @@ -0,0 +1,67 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Count.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Count.svg new file mode 100644 index 00000000..312e07a9 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Count.svg @@ -0,0 +1,111 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Difference.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Difference.svg new file mode 100644 index 00000000..f9721dca --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Difference.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Divide.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Divide.svg new file mode 100644 index 00000000..f2493395 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Divide.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Equal.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Equal.svg new file mode 100644 index 00000000..f104e195 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Equal.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/False.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/False.svg new file mode 100644 index 00000000..61799de1 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/False.svg @@ -0,0 +1,65 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/ForAll.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/ForAll.svg new file mode 100644 index 00000000..5ea5fa40 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/ForAll.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/ForLone.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/ForLone.svg new file mode 100644 index 00000000..08b0bc50 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/ForLone.svg @@ -0,0 +1,75 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/ForNo.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/ForNo.svg new file mode 100644 index 00000000..60a5b94f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/ForNo.svg @@ -0,0 +1,73 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/ForOne.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/ForOne.svg new file mode 100644 index 00000000..08b0bc50 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/ForOne.svg @@ -0,0 +1,75 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/ForSome.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/ForSome.svg new file mode 100644 index 00000000..59948561 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/ForSome.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Function.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Function.svg new file mode 100644 index 00000000..bbd93a0b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Function.svg @@ -0,0 +1,93 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Gte.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Gte.svg new file mode 100644 index 00000000..da1fc543 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Gte.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Iden.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Iden.svg new file mode 100644 index 00000000..104d9298 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Iden.svg @@ -0,0 +1,65 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Identical.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Identical.svg new file mode 100644 index 00000000..22049dae --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Identical.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Iff.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Iff.svg new file mode 100644 index 00000000..bee00e98 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Iff.svg @@ -0,0 +1,66 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Implies.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Implies.svg new file mode 100644 index 00000000..6638ce2f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Implies.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/In.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/In.svg new file mode 100644 index 00000000..78e0c62f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/In.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/IntConstant.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/IntConstant.svg new file mode 100644 index 00000000..bf857dfc --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/IntConstant.svg @@ -0,0 +1,58 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Intersection.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Intersection.svg new file mode 100644 index 00000000..3cab5d6a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Intersection.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Ints.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Ints.svg new file mode 100644 index 00000000..ebde0f74 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Ints.svg @@ -0,0 +1,51 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Join.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Join.svg new file mode 100644 index 00000000..32e4d6fd --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Join.svg @@ -0,0 +1,84 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Lone.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Lone.svg new file mode 100644 index 00000000..f6eb541f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Lone.svg @@ -0,0 +1,65 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/LoneOf.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/LoneOf.svg new file mode 100644 index 00000000..257e0f3c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/LoneOf.svg @@ -0,0 +1,66 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Lt.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Lt.svg new file mode 100644 index 00000000..6acec89e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Lt.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Lte.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Lte.svg new file mode 100644 index 00000000..df6c40c7 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Lte.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Minus.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Minus.svg new file mode 100644 index 00000000..7478ac27 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Minus.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Modulo.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Modulo.svg new file mode 100644 index 00000000..d1309f1d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Modulo.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Multiply.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Multiply.svg new file mode 100644 index 00000000..9a07a466 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Multiply.svg @@ -0,0 +1,63 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/None.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/None.svg new file mode 100644 index 00000000..afa32f06 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/None.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Not.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Not.svg new file mode 100644 index 00000000..ef421b82 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Not.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotEqual.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotEqual.svg new file mode 100644 index 00000000..9a5a13bf --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotEqual.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotGt.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotGt.svg new file mode 100644 index 00000000..5059f4b4 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotGt.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotGte.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotGte.svg new file mode 100644 index 00000000..1e7ea329 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotGte.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotIdentical.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotIdentical.svg new file mode 100644 index 00000000..f1f5eb3e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotIdentical.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotIn.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotIn.svg new file mode 100644 index 00000000..15adb227 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotIn.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotLt.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotLt.svg new file mode 100644 index 00000000..4350a5da --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotLt.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotLte.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotLte.svg new file mode 100644 index 00000000..d08f9d6c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/NotLte.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/One.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/One.svg new file mode 100644 index 00000000..4f92f840 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/One.svg @@ -0,0 +1,60 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/OneOf.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/OneOf.svg new file mode 100644 index 00000000..257e0f3c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/OneOf.svg @@ -0,0 +1,66 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Or.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Or.svg new file mode 100644 index 00000000..9bed6dba --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Or.svg @@ -0,0 +1,66 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/PartialFunction.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/PartialFunction.svg new file mode 100644 index 00000000..272ab4ed --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/PartialFunction.svg @@ -0,0 +1,87 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Plus.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Plus.svg new file mode 100644 index 00000000..c60f491e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Plus.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Product.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Product.svg new file mode 100644 index 00000000..023e6657 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Product.svg @@ -0,0 +1,65 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/QuantifierDeclaration.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/QuantifierDeclaration.svg new file mode 100644 index 00000000..257e0f3c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/QuantifierDeclaration.svg @@ -0,0 +1,66 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Reason.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Reason.svg new file mode 100644 index 00000000..3f38db50 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Reason.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Reflexive.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Reflexive.svg new file mode 100644 index 00000000..31b5c796 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Reflexive.svg @@ -0,0 +1,72 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Relation.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Relation.svg new file mode 100644 index 00000000..2b61806c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Relation.svg @@ -0,0 +1,70 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/SetComprehension.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/SetComprehension.svg new file mode 100644 index 00000000..acdb4c02 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/SetComprehension.svg @@ -0,0 +1,139 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/SetOf.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/SetOf.svg new file mode 100644 index 00000000..257e0f3c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/SetOf.svg @@ -0,0 +1,66 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Some.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Some.svg new file mode 100644 index 00000000..05d9d7a4 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Some.svg @@ -0,0 +1,65 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/SomeOf.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/SomeOf.svg new file mode 100644 index 00000000..257e0f3c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/SomeOf.svg @@ -0,0 +1,66 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/SumDeclaration.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/SumDeclaration.svg new file mode 100644 index 00000000..9dedc32a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/SumDeclaration.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Tranpose.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Tranpose.svg new file mode 100644 index 00000000..b68816fa --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Tranpose.svg @@ -0,0 +1,67 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/True.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/True.svg new file mode 100644 index 00000000..544612a3 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/True.svg @@ -0,0 +1,66 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Union.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Union.svg new file mode 100644 index 00000000..d1686b66 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Union.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Univ.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Univ.svg new file mode 100644 index 00000000..2703839f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Univ.svg @@ -0,0 +1,65 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Variable.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Variable.svg new file mode 100644 index 00000000..621cf2f8 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/Variable.svg @@ -0,0 +1,76 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/no.svg b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/no.svg new file mode 100644 index 00000000..c612d09b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/original/no.svg @@ -0,0 +1,55 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceN.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceN.gif new file mode 100644 index 00000000..bf79f7cc Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceN.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceNToM.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceNToM.gif new file mode 100644 index 00000000..42b40982 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceNToM.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceNToUnbounded.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceNToUnbounded.gif new file mode 100644 index 00000000..d9247204 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceNToUnbounded.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceNToUnspecified.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceNToUnspecified.gif new file mode 100644 index 00000000..1e6cec4b Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceNToUnspecified.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceOne.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceOne.gif new file mode 100644 index 00000000..d0cf1b15 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceOne.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceOneToM.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceOneToM.gif new file mode 100644 index 00000000..3ae4f341 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceOneToM.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceOneToUnbounded.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceOneToUnbounded.gif new file mode 100644 index 00000000..6b409d6f Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceOneToUnbounded.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceOneToUnspecified.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceOneToUnspecified.gif new file mode 100644 index 00000000..89297745 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceOneToUnspecified.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceZero.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceZero.gif new file mode 100644 index 00000000..4c405a7b Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceZero.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceZeroToM.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceZeroToM.gif new file mode 100644 index 00000000..f339c94d Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceZeroToM.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceZeroToOne.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceZeroToOne.gif new file mode 100644 index 00000000..5fce60b5 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceZeroToOne.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceZeroToUnbounded.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceZeroToUnbounded.gif new file mode 100644 index 00000000..533dad7a Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceZeroToUnbounded.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceZeroToUnspecified.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceZeroToUnspecified.gif new file mode 100644 index 00000000..6a9da752 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/EOccurrenceZeroToUnspecified.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/PACKAGE.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/PACKAGE.gif new file mode 100644 index 00000000..bc65fd7f Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/PACKAGE.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/PRIVATE.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/PRIVATE.gif new file mode 100644 index 00000000..9b038d67 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/PRIVATE.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/PROTECTED.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/PROTECTED.gif new file mode 100644 index 00000000..62441064 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/PROTECTED.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/PUBLIC.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/PUBLIC.gif new file mode 100644 index 00000000..76035b99 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/full/ovr16/PUBLIC.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/icons/sample.gif b/Source/eu.modelwriter.core.alloyinecore.ui/icons/sample.gif new file mode 100644 index 00000000..34fb3c9d Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/icons/sample.gif differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/lib/antlr-4.6-complete.jar b/Source/eu.modelwriter.core.alloyinecore.ui/lib/antlr-4.6-complete.jar new file mode 100644 index 00000000..b488881e Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/lib/antlr-4.6-complete.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/lib/eu.modelwriter.core.alloyinecore.jar b/Source/eu.modelwriter.core.alloyinecore.ui/lib/eu.modelwriter.core.alloyinecore.jar new file mode 100644 index 00000000..10450243 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore.ui/lib/eu.modelwriter.core.alloyinecore.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/plugin.xml b/Source/eu.modelwriter.core.alloyinecore.ui/plugin.xml new file mode 100644 index 00000000..e7f7c04a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/plugin.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/ASTChangeListener.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/ASTChangeListener.java new file mode 100644 index 00000000..8363f8ef --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/ASTChangeListener.java @@ -0,0 +1,9 @@ +package eu.modelwriter.core.alloyinecore.ui; + +import eu.modelwriter.core.alloyinecore.structure.base.Element; + +public interface ASTChangeListener { + @SuppressWarnings("rawtypes") + void onASTChange(Element element); + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/ASTErrorListener.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/ASTErrorListener.java new file mode 100644 index 00000000..90d0eb42 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/ASTErrorListener.java @@ -0,0 +1,13 @@ +package eu.modelwriter.core.alloyinecore.ui; + +import java.util.Set; + +import org.antlr.v4.runtime.Token; + +public interface ASTErrorListener { + void onSyntaxError(Token offendingSymbol, String msg); + + void onTypeError(String message, Set relatedElements); + + void onTypeWarning(String message, Set relatedElements); +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/ASTInstanceManager.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/ASTInstanceManager.java new file mode 100644 index 00000000..79315012 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/ASTInstanceManager.java @@ -0,0 +1,21 @@ +package eu.modelwriter.core.alloyinecore.ui; + +import org.eclipse.emf.common.util.URI; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser; +import eu.modelwriter.core.alloyinecore.structure.base.Element; + +public class ASTInstanceManager extends ASTManager { + + public ASTInstanceManager() {} + + @SuppressWarnings("rawtypes") + @Override + public Element parseString(String text, URI uri) throws Exception { + hasSyntaxError = false; + AlloyInEcoreParser parser = createParser(text, uri); + parser.instance(null); + changeListeners.forEach(l -> l.onASTChange(parser.instance)); + return parser.instance; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/ASTManager.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/ASTManager.java new file mode 100644 index 00000000..ec919f3c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/ASTManager.java @@ -0,0 +1,83 @@ +package eu.modelwriter.core.alloyinecore.ui; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.BaseErrorListener; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.Recognizer; +import org.antlr.v4.runtime.Token; +import org.eclipse.emf.common.util.URI; +import org.eclipse.jface.text.IDocument; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser; +import eu.modelwriter.core.alloyinecore.structure.base.Element; + +public abstract class ASTManager { + + protected Set changeListeners = new HashSet<>(); + protected Set errorListeners = new HashSet<>(); + protected boolean hasSyntaxError = false; + + public ASTManager() {} + + public void addChangeListener(ASTChangeListener listener) { + changeListeners.add(listener); + } + + public void removeChangeListener(ASTChangeListener listener) { + changeListeners.remove(listener); + } + + public void addErrorListener(ASTErrorListener listener) { + errorListeners.add(listener); + } + + public void removeErrorListener(ASTErrorListener listener) { + errorListeners.remove(listener); + } + + /** + * Parses the given document's text. + * + * @param document + * @param errorListener + * @return Parsed {@linkplain eu.modelwriter.core.alloyinecore.structure.Module} object + * @throws Exception + */ + @SuppressWarnings("rawtypes") + public Element parseDocument(final IDocument document, final URI uri) throws Exception { + return parseString(document.get(), uri); + } + + /** + * Parses the given text. + * + * @param text + * @param errorListener + * @return Parsed {@link eu.modelwriter.core.alloyinecore.structure.Module} object + * @throws Exception + */ + @SuppressWarnings("rawtypes") + public abstract Element parseString(final String text, final URI uri) throws Exception; + + public AlloyInEcoreParser createParser(final String text, final URI uri) { + final AlloyInEcoreLexer lexer = new AlloyInEcoreLexer(new ANTLRInputStream(text)); + final CommonTokenStream tokens = new CommonTokenStream(lexer); + final AlloyInEcoreParser parser = new AlloyInEcoreParser(tokens, uri); + parser.removeErrorListeners(); + parser.addErrorListener(new BaseErrorListener() { + + @Override + public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, + int charPositionInLine, String msg, RecognitionException e) { + hasSyntaxError = true; + errorListeners.forEach(l -> l.onSyntaxError((Token) offendingSymbol, msg)); + } + }); + return parser; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/ASTModelManager.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/ASTModelManager.java new file mode 100644 index 00000000..c78de6c9 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/ASTModelManager.java @@ -0,0 +1,42 @@ +package eu.modelwriter.core.alloyinecore.ui; + +import java.util.Set; + +import org.antlr.v4.runtime.Token; +import org.eclipse.emf.common.util.URI; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.typechecking.TypeChecker; +import eu.modelwriter.core.alloyinecore.typechecking.TypeErrorListener; + +public class ASTModelManager extends ASTManager { + + public ASTModelManager() {} + + @SuppressWarnings("rawtypes") + @Override + public Element parseString(String text, URI uri) throws Exception { + hasSyntaxError = false; + AlloyInEcoreParser parser = createParser(text, uri); + parser.model(); + changeListeners.forEach(l -> l.onASTChange(parser.model)); + if (!hasSyntaxError) { + TypeChecker checker = new TypeChecker(); + checker.addErrorListener(new TypeErrorListener() { + + @Override + public void onTypeWarning(String message, Set relatedElements) { + errorListeners.forEach(l -> l.onTypeWarning(message, relatedElements)); + } + + @Override + public void onTypeError(String message, Set relatedElements) { + errorListeners.forEach(l -> l.onTypeError(message, relatedElements)); + } + }); + checker.check(parser.model); + } + return parser.model; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/Activator.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/Activator.java new file mode 100644 index 00000000..75c04960 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/Activator.java @@ -0,0 +1,95 @@ +package eu.modelwriter.core.alloyinecore.ui; + +import java.io.File; +import java.net.URL; +import java.util.Enumeration; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +public class Activator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "eu.modelwriter.core.alloyinecore.ui"; //$NON-NLS-1$ + + // The shared instance + private static Activator plugin; + + private ASTManager modelManager; + private ASTManager instanceManager; + + public Activator() {} + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework. BundleContext) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + modelManager = new ASTModelManager(); + instanceManager = new ASTInstanceManager(); + getImageRegistry(); + } + + public ASTManager getModelManager() { + return modelManager; + } + + public ASTManager getInstanceManager() { + return instanceManager; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework. BundleContext) + */ + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + + public static Shell getShell() { + return getActiveWorkbenchWindow().getShell(); + } + + public static IWorkbenchWindow getActiveWorkbenchWindow() { + return PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + } + + @Override + protected void initializeImageRegistry(ImageRegistry reg) { + loadImages(reg, "/icons/full/obj16"); + loadImages(reg, "/icons/full/exp16"); + loadImages(reg, "/icons/full/ovr16"); + } + + private void loadImages(ImageRegistry reg, String folderPath) { + Enumeration files = plugin.getBundle().getEntryPaths(folderPath); + while (files.hasMoreElements()) { + String path = files.nextElement(); + URL entry = plugin.getBundle().getEntry(path); + ImageDescriptor desc = ImageDescriptor.createFromURL(entry); + reg.put(new File(path).getName().replace(".gif", "").replace(".svg", "").replace(".png", ""), + desc); + } + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/AIEEditor.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/AIEEditor.java new file mode 100644 index 00000000..483d59c7 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/AIEEditor.java @@ -0,0 +1,246 @@ +package eu.modelwriter.core.alloyinecore.ui.editor; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.antlr.v4.runtime.CommonToken; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.presentation.EcoreEditor; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.IVerticalRuler; +import org.eclipse.jface.text.source.projection.ProjectionAnnotation; +import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel; +import org.eclipse.jface.text.source.projection.ProjectionViewer; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.WorkbenchException; +import org.eclipse.ui.editors.text.TextEditor; +import org.eclipse.ui.views.contentoutline.IContentOutlinePage; + +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.ui.ASTChangeListener; +import eu.modelwriter.core.alloyinecore.ui.ASTManager; +import eu.modelwriter.core.alloyinecore.ui.Activator; +import eu.modelwriter.core.alloyinecore.ui.editor.color.AIEColorManager; +import eu.modelwriter.core.alloyinecore.ui.editor.document.AIEDocument; +import eu.modelwriter.core.alloyinecore.ui.editor.document.AIEDocumentProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.outline.AIEContentOutlinePage; +import eu.modelwriter.core.alloyinecore.ui.editor.partition.IAIEPartitions; +import eu.modelwriter.core.alloyinecore.ui.editor.util.EditorUtils; + +public class AIEEditor extends TextEditor implements ASTChangeListener { + + public static final String editorID = + "eu.modelwriter.core.alloyinecore.ui.editors.AlloyInEcoreEditor"; + + public static final String PARSER_ERROR_ANNOTATION = + "eu.modelwriter.core.alloyinecore.ui.editor.parsererror"; + public static final String TYPE_ERROR_ANNOTATION = + "eu.modelwriter.core.alloyinecore.ui.editor.typererror"; + public static final String TYPE_WARNING_ANNOTATION = + "eu.modelwriter.core.alloyinecore.ui.editor.typewarning"; + public static final String PARSER_ERROR_MARKER = + "eu.modelwriter.core.alloyinecore.ui.editor.parseerrormarker"; + + @SuppressWarnings("rawtypes") + protected Element rootElement; + protected AIEColorManager aIEColorManager; + private AIEContentOutlinePage outlinePage; + private ProjectionAnnotationModel annotationModel; + private Annotation[] oldAnnotations; + protected HashMap projectionAnnotations = + new HashMap(); + @SuppressWarnings("rawtypes") + private HashMap element2anno = + new HashMap(); + + public AIEEditor() { + aIEColorManager = new AIEColorManager(); + getManagerForEditor().addChangeListener(this); + initEditor(); + } + + protected void initEditor() { + setSourceViewerConfiguration( + new AIESourceViewerConfiguration(aIEColorManager, this, IAIEPartitions.AIE_PARTITIONING)); + setDocumentProvider(new AIEDocumentProvider()); + } + + @SuppressWarnings("rawtypes") + public Element getRootElement() { + return rootElement; + } + + @Override + protected ISourceViewer createSourceViewer(final Composite parent, final IVerticalRuler ruler, + final int styles) { + final ISourceViewer viewer = + new ProjectionViewer(parent, ruler, getOverviewRuler(), isOverviewRulerVisible(), styles); + // ensure decoration support has been created and configured. + getSourceViewerDecorationSupport(viewer); + return viewer; + } + + @Override + public void createPartControl(final Composite parent) { + super.createPartControl(parent); + final ProjectionViewer projectionViewer = (ProjectionViewer) getSourceViewer(); + + // final ProjectionSupport projectionSupport = + // new ProjectionSupport(projectionViewer, getAnnotationAccess(), getSharedColors()); + // projectionSupport.install(); + + // turn projection mode on + // projectionViewer.doOperation(ProjectionViewer.TOGGLE); + + annotationModel = projectionViewer.getProjectionAnnotationModel(); + } + + @Override + protected void handleCursorPositionChanged() { + super.handleCursorPositionChanged(); + try { + final String[] cursorPosition = getCursorPosition().split(" : "); + final int line = Integer.parseInt(cursorPosition[0]) - 1; + final int column = Integer.parseInt(cursorPosition[1]) - 1; + final int offset = + getDocumentProvider().getDocument(getEditorInput()).getLineOffset(line) + column; + if (outlinePage != null && offset != outlinePage.getSelectionOffset()) { + outlinePage.selectElement(findElement(line + 1, offset)); + } + } catch (final NumberFormatException | ArrayIndexOutOfBoundsException e) { + e.printStackTrace(); + } catch (final BadLocationException e) { + e.printStackTrace(); + } + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + protected void calculateFoldingPositions(final Element element) { + List ownedElements = element.getOwnedElements(); + for (Element ownedElement : ownedElements) { + Position position = getFoldablePosition(ownedElement); + if (position != null) { + ProjectionAnnotation prevAnno = element2anno.get(ownedElement); + ProjectionAnnotation annotation = new ProjectionAnnotation(); + if (prevAnno != null && prevAnno.isCollapsed()) { + annotation.markCollapsed(); + } + projectionAnnotations.put(annotation, position); + element2anno.put(ownedElement, annotation); + } + calculateFoldingPositions(ownedElement); + } + } + + @SuppressWarnings("rawtypes") + private Position getFoldablePosition(final Element element) { + int startIndex = element.getContext().getStart().getStartIndex(); + // find last token + CommonToken lastToken = null; + for (int i = element.getContext().getChildCount() - 1; i >= 0; i--) { + if (element.getContext().getChild(i).getPayload() instanceof CommonToken) { + lastToken = (CommonToken) element.getContext().getChild(i).getPayload(); + break; + } + } + try { + if (lastToken != null && lastToken.getLine() != element.getLine()) { + IDocument document = getDocumentProvider().getDocument(getEditorInput()); + int stopLine = document.getLineOfOffset(lastToken.getStopIndex()); + int lineSize = document.getNumberOfLines() - 1; + int lenght = document.getLineOffset(lineSize > (stopLine + 1) ? (stopLine + 1) : stopLine) + - startIndex; + return new Position(startIndex, lenght); + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + return null; + } + + public void updateFoldingStructure() { + final Annotation[] annotations = projectionAnnotations.keySet().toArray(new Annotation[0]); + annotationModel.modifyAnnotations(oldAnnotations, projectionAnnotations, null); + oldAnnotations = annotations; + } + + @Override + public void dispose() { + aIEColorManager.dispose(); + super.dispose(); + } + + @SuppressWarnings("unchecked") + @Override + public T getAdapter(final Class adapter) { + if (IContentOutlinePage.class.equals(adapter)) { + if (outlinePage == null) { + outlinePage = new AIEContentOutlinePage(getDocumentProvider(), this, getManagerForEditor()); + if (rootElement != null) { + outlinePage.refresh(rootElement); + } + } + return (T) outlinePage; + } + return super.getAdapter(adapter); + } + + protected ASTManager getManagerForEditor() { + return Activator.getDefault().getModelManager(); + } + + @SuppressWarnings({"rawtypes"}) + public Element findElement(final int line, final int offset) { + return EditorUtils.findElement(rootElement, line, offset); + } + + public EcoreEditor openEcoreEditor() { + try { + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + if (page != null) { + return (EcoreEditor) page.openEditor(getEditorInput(), + "org.eclipse.emf.ecore.presentation.EcoreEditorID", true, + IWorkbenchPage.MATCH_ID | IWorkbenchPage.MATCH_INPUT); + } + } catch (WorkbenchException e) { + e.printStackTrace(); + } + return null; + } + + public void openEcoreEditorAndReveal(EObject eObject) { + AIEDocument document = (AIEDocument) getDocumentProvider().getDocument(getEditorInput()); + EObject realEObject = EcoreUtil.getEObject(document.getEcoreRoot(), + EcoreUtil.getURI(eObject).fragment().replace("//", "")); + EcoreEditor ecoreEditor = openEcoreEditor(); + + if (ecoreEditor != null) { + ArrayList arrayList = new ArrayList<>(); + arrayList.add(realEObject); + ecoreEditor.setSelectionToViewer(arrayList); + } + } + + @SuppressWarnings("rawtypes") + @Override + public void onASTChange(Element model) { + this.rootElement = model; + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + // Update folding positions + projectionAnnotations.clear(); + } + }); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/AIEKeywords.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/AIEKeywords.java new file mode 100644 index 00000000..49126398 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/AIEKeywords.java @@ -0,0 +1,40 @@ +package eu.modelwriter.core.alloyinecore.ui.editor; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +public interface AIEKeywords { + + public static final String[] KEYWORDS = + new String[] {"package", "class", "import", "abstract", "interface", "attribute", "operation", + "enum", "annotation", "datatype", "reference", "literal", "#", "property", "throws"}; + + public static final String[] PRIMITIVES = + new String[] {"Boolean", "Integer", "String", "Real", "UnlimitedNatural"}; + + public static final String[] AIE = new String[] {"module", "body", "requires", "precondition", + "ensures", "postcondition", "invariant", "ghost", "model", "initial", "derivation", "no", + "lone", "some", "one", "not", "in", "acyclic", "ord", "function", "and", "or", "if", "iff", + "implies", "all", "let", "true", "false", "iden", "none", "univ", "ints", "plus", "minus", + "then", "else", "modulo", "div", "mul", "sum", "disj", "set"}; + + public static final String[] VISIBILITY = new String[] {"public", "private", "protected"}; + + public static final String[] QUALIFIERS = + new String[] {"static", "extends", "super", "readonly", "!readonly", "composes", "!composes", + "nullable", "!nullable", "transient", "!transient", "volatile", "!volatile", "resolve", + "!resolve", "ordered", "!ordered", "callable", "!callable", "unsettable", "!unsettable", + "derived", "!derived", "unique", "!unique", "id", "!id", "serializable", "!serializable"}; + + public static final Set ALL_BUT_AIE = AIEKeywords.getAll(AIEKeywords.KEYWORDS, + AIEKeywords.VISIBILITY, AIEKeywords.QUALIFIERS, AIEKeywords.PRIMITIVES); + + public static Set getAll(final String[]... arrays) { + final Set hashSet = new HashSet<>(); + for (int i = 0; i < arrays.length; i++) { + hashSet.addAll(Arrays.asList(arrays[i])); + } + return hashSet; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/AIESourceViewerConfiguration.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/AIESourceViewerConfiguration.java new file mode 100644 index 00000000..97400b37 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/AIESourceViewerConfiguration.java @@ -0,0 +1,225 @@ +package eu.modelwriter.core.alloyinecore.ui.editor; + +import java.util.Map; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.jface.text.DefaultTextHover; +import org.eclipse.jface.text.IAutoEditStrategy; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextHover; +import org.eclipse.jface.text.contentassist.ContentAssistant; +import org.eclipse.jface.text.contentassist.IContentAssistant; +import org.eclipse.jface.text.hyperlink.IHyperlinkDetector; +import org.eclipse.jface.text.hyperlink.URLHyperlinkDetector; +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.presentation.PresentationReconciler; +import org.eclipse.jface.text.reconciler.IReconciler; +import org.eclipse.jface.text.reconciler.Reconciler; +import org.eclipse.jface.text.rules.DefaultDamagerRepairer; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.DefaultAnnotationHover; +import org.eclipse.jface.text.source.IAnnotationHover; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.ui.editors.text.TextSourceViewerConfiguration; +import org.eclipse.ui.texteditor.ITextEditor; + +import eu.modelwriter.core.alloyinecore.ui.editor.autoedit.AIEAutoEditStrategy; +import eu.modelwriter.core.alloyinecore.ui.editor.color.IColorManager; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.AIECompletionProcessor; +import eu.modelwriter.core.alloyinecore.ui.editor.hyperlink.AIEHyperlinkDetector; +import eu.modelwriter.core.alloyinecore.ui.editor.partition.IAIEPartitions; +import eu.modelwriter.core.alloyinecore.ui.editor.reconciling.AIESyntacticReconcilingStrategy; +import eu.modelwriter.core.alloyinecore.ui.editor.scanner.AIECodeScanner; + +public class AIESourceViewerConfiguration extends TextSourceViewerConfiguration { + private final ITextEditor fTextEditor; + private final IColorManager fColorManager; + private final String fDocumentPartitioning; + private AIECodeScanner fCodeScanner; + + /** + * Creates a new AlloyInEcore source viewer configuration for viewers in the given editor using + * the given the color manager and the specified document partitioning. + * + * @param colorManager the color manager + * @param editor the editor in which the configured viewer(s) will reside, or null if + * none + * @param partitioning the document partitioning for this configuration, or null for + * the default partitioning + */ + public AIESourceViewerConfiguration(final IColorManager colorManager, final ITextEditor editor, + final String partitioning) { + fColorManager = colorManager; + fTextEditor = editor; + fDocumentPartitioning = partitioning; + initializeScanners(); + } + + /** + * Initializes the scanners. + */ + protected void initializeScanners() { + fCodeScanner = new AIECodeScanner(getColorManager()); + } + + /** + * Returns the color manager for this configuration. + * + * @return the color manager + */ + protected IColorManager getColorManager() { + return fColorManager; + } + + /** + * Returns the editor in which the configured viewer(s) will reside. + * + * @return the enclosing editor + */ + protected ITextEditor getEditor() { + return fTextEditor; + } + + @Override + public IHyperlinkDetector[] getHyperlinkDetectors(final ISourceViewer sourceViewer) { + return new IHyperlinkDetector[] { + new AIEHyperlinkDetector(sourceViewer, (AIEEditor) fTextEditor), + new URLHyperlinkDetector()}; + } + + /* + * @see SourceViewerConfiguration#getPresentationReconciler(ISourceViewer) + */ + @Override + public IPresentationReconciler getPresentationReconciler(final ISourceViewer sourceViewer) { + + final PresentationReconciler reconciler = new PresentationReconciler(); + reconciler.setDocumentPartitioning(IAIEPartitions.AIE_PARTITIONING); + + for (final String partition : IAIEPartitions.ALL_PARTITIONS) { + final DefaultDamagerRepairer dr = new DefaultDamagerRepairer(getCodeScanner()); + reconciler.setDamager(dr, partition); + reconciler.setRepairer(dr, partition); + } + + return reconciler; + } + + /** + * Returns the AlloyInEcore source code scanner for this configuration. + * + * @return the AlloyInEcore source code scanner + */ + protected AIECodeScanner getCodeScanner() { + return fCodeScanner; + } + + /* + * @see SourceViewerConfiguration#getDefaultPrefixes(ISourceViewer, String) + * + * @since 2.0 + */ + @Override + public String[] getDefaultPrefixes(final ISourceViewer sourceViewer, final String contentType) { + return new String[] {"//", ""}; + } + + /* + * @see SourceViewerConfiguration#getConfiguredContentTypes(ISourceViewer) + */ + @Override + public String[] getConfiguredContentTypes(final ISourceViewer sourceViewer) { + return IAIEPartitions.ALL_PARTITIONS; + } + + /* + * @see org.eclipse.jface.text.source.SourceViewerConfiguration# + * getConfiguredDocumentPartitioning(org. eclipse.jface.text.source.ISourceViewer) + */ + @Override + public String getConfiguredDocumentPartitioning(final ISourceViewer sourceViewer) { + if (fDocumentPartitioning != null) { + return fDocumentPartitioning; + } + return super.getConfiguredDocumentPartitioning(sourceViewer); + } + + /* + * @see org.eclipse.jface.text.source.SourceViewerConfiguration# + * getHyperlinkDetectorTargets(org.eclipse .jface.text.source.ISourceViewer) + */ + @Override + protected Map getHyperlinkDetectorTargets(final ISourceViewer sourceViewer) { + final Map targets = super.getHyperlinkDetectorTargets(sourceViewer); + targets.put(AIEEditor.editorID, fTextEditor); + return targets; + } + + @Override + public ITextHover getTextHover(final ISourceViewer sourceViewer, final String contentType) { + return new DefaultTextHover(sourceViewer) { + @Override + protected boolean isIncluded(final Annotation annotation) { + return AIEEditor.PARSER_ERROR_ANNOTATION.equals(annotation.getType()) + || AIEEditor.TYPE_ERROR_ANNOTATION.equals(annotation.getType()) + || AIEEditor.TYPE_WARNING_ANNOTATION.equals(annotation.getType()); + } + }; + } + + @Override + public IAnnotationHover getOverviewRulerAnnotationHover(final ISourceViewer sourceViewer) { + return new DefaultAnnotationHover(); + } + + @Override + public IAnnotationHover getAnnotationHover(final ISourceViewer sourceViewer) { + return new DefaultAnnotationHover(); + } + + /* + * @see SourceViewerConfiguration#getReconciler(ISourceViewer) + */ + @Override + public IReconciler getReconciler(final ISourceViewer sourceViewer) { + final ITextEditor editor = getEditor(); + if (editor != null && editor.isEditable()) { + final Reconciler reconciler = new Reconciler(); + final AIESyntacticReconcilingStrategy strategy = + new AIESyntacticReconcilingStrategy(sourceViewer, editor); + for (final String partition : IAIEPartitions.ALL_PARTITIONS) { + reconciler.setReconcilingStrategy(strategy, partition); + } + reconciler.setDocumentPartitioning(IAIEPartitions.AIE_PARTITIONING); + reconciler.setDelay(500); + reconciler.setProgressMonitor(new NullProgressMonitor()); + return reconciler; + } + return null; + } + + /* + * @see / org.eclipse.jface.text.source.SourceViewerConfiguration# + * getAutoEditStrategies(org.eclipse. jface.text.source.ISourceViewer, / java.lang.String) + */ + @Override + public IAutoEditStrategy[] getAutoEditStrategies(final ISourceViewer sourceViewer, + final String contentType) { + return new IAutoEditStrategy[] {new AIEAutoEditStrategy()}; + } + + @Override + public IContentAssistant getContentAssistant(final ISourceViewer sourceViewer) { + final ContentAssistant assistant = new ContentAssistant(); + assistant.setContentAssistProcessor(new AIECompletionProcessor(), + IDocument.DEFAULT_CONTENT_TYPE); + assistant.setAutoActivationDelay(500); + assistant.enableAutoActivation(true); + assistant.enableAutoInsert(true); + assistant.setProposalPopupOrientation(IContentAssistant.PROPOSAL_OVERLAY); + assistant.setContextInformationPopupOrientation(IContentAssistant.CONTEXT_INFO_ABOVE); + + return assistant; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/autoedit/AIEAutoEditStrategy.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/autoedit/AIEAutoEditStrategy.java new file mode 100644 index 00000000..4b6e07cd --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/autoedit/AIEAutoEditStrategy.java @@ -0,0 +1,55 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.autoedit; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DocumentCommand; +import org.eclipse.jface.text.IAutoEditStrategy; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; + +public class AIEAutoEditStrategy implements IAutoEditStrategy { + + private void configureCaret(final DocumentCommand command, int caretInc) { + command.caretOffset = command.offset + caretInc; + command.shiftsCaret = false; + } + + @Override + public void customizeDocumentCommand(final IDocument document, final DocumentCommand command) { + if (command.text.equals("(")) { + command.text = "()"; + configureCaret(command, 1); + } else if (command.text.equals("[")) { + command.text = "[]"; + configureCaret(command, 1); + } else if (command.text.equals("'")) { + command.text = "''"; + configureCaret(command, 1); + } else if (command.text.equals("\"")) { + command.text = "\"\""; + configureCaret(command, 1); + } else if (command.text.equals("{")) { + String indent = getIndent(document, command); + command.text = "\n" + indent + "{\n" + indent + " \n" + indent + "}"; + configureCaret(command, 3 + indent.length() * 2 + 4); + } + } + + private String getIndent(IDocument document, DocumentCommand command) { + String result = ""; + try { + IRegion info = document.getLineInformationOfOffset(command.offset); + String text = document.get(info.getOffset(), info.getLength()); + Matcher matcher = Pattern.compile("^(\\s)*(\\w)").matcher(text); + if (matcher.find()) { + int indexOf = text.indexOf(matcher.group(2)); + result = text.substring(0, indexOf); + } + } catch (BadLocationException e) { + result = ""; + } + return result; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/color/AIEColorManager.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/color/AIEColorManager.java new file mode 100644 index 00000000..2afc4c1d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/color/AIEColorManager.java @@ -0,0 +1,141 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.color; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Display; + +public class AIEColorManager implements IColorManager, IColorManagerExtension { + + protected Map fKeyTable = new HashMap<>(10); + protected Map> fDisplayTable = new HashMap<>(2); + + /** + * Flag which tells if the colors are automatically disposed when the current display gets + * disposed. + */ + private final boolean fAutoDisposeOnDisplayDispose; + + + /** + * Creates a new AlloyInEcore color manager which automatically disposes the allocated colors when + * the current display gets disposed. + */ + public AIEColorManager() { + this(true); + // TODO bind color truly later. + bindColor(IAIEColorConstants.AIE_MULTI_LINE_COMMENT, new RGB(0, 128, 0)); + bindColor(IAIEColorConstants.AIE_SINGLE_LINE_COMMENT, new RGB(0, 128, 0)); + bindColor(IAIEColorConstants.AIE_STRING, new RGB(0, 0, 128)); + bindColor(IAIEColorConstants.KEYWORD, new RGB(128, 0, 0)); + bindColor(IAIEColorConstants.AIE_DEFAULT, new RGB(0, 0, 0)); + bindColor(IAIEColorConstants.AIE_KEYWORD, new RGB(0, 90, 255)); + bindColor(IAIEColorConstants.AIE_INSTANCE_SF_KEYWORD, new RGB(0, 0, 0)); + } + + /** + * Creates a new AlloyInEcore color manager. + * + * @param autoDisposeOnDisplayDispose if true the color manager automatically + * disposes all managed colors when the current display gets disposed and all calls to + * {@link org.eclipse.jface.text.source.ISharedTextColors#dispose()} are ignored. + */ + public AIEColorManager(final boolean autoDisposeOnDisplayDispose) { + fAutoDisposeOnDisplayDispose = autoDisposeOnDisplayDispose; + } + + public void dispose(final Display display) { + final Map colorTable = fDisplayTable.get(display); + if (colorTable != null) { + final Iterator e = colorTable.values().iterator(); + while (e.hasNext()) { + final Color color = e.next(); + if (color != null && !color.isDisposed()) { + color.dispose(); + } + } + } + } + + /* + * @see IColorManager#getColor(RGB) + */ + @Override + public Color getColor(final RGB rgb) { + + if (rgb == null) { + return null; + } + + final Display display = Display.getCurrent(); + Map colorTable = fDisplayTable.get(display); + if (colorTable == null) { + colorTable = new HashMap<>(10); + fDisplayTable.put(display, colorTable); + if (fAutoDisposeOnDisplayDispose) { + display.disposeExec(new Runnable() { + @Override + public void run() { + dispose(display); + } + }); + } + } + + Color color = colorTable.get(rgb); + if (color == null) { + color = new Color(Display.getCurrent(), rgb); + colorTable.put(rgb, color); + } + + return color; + } + + /* + * @see IColorManager#dispose + */ + @Override + public void dispose() { + if (!fAutoDisposeOnDisplayDispose) { + dispose(Display.getCurrent()); + } + } + + /* + * @see IColorManager#getColor(String) + */ + @Override + public Color getColor(final String key) { + + if (key == null) { + return null; + } + + final RGB rgb = fKeyTable.get(key); + return getColor(rgb); + } + + /* + * @see IColorManagerExtension#bindColor(String, RGB) + */ + @Override + public void bindColor(final String key, final RGB rgb) { + final Object value = fKeyTable.get(key); + if (value != null) { + throw new UnsupportedOperationException(); + } + + fKeyTable.put(key, rgb); + } + + /* + * @see IColorManagerExtension#unbindColor(String) + */ + @Override + public void unbindColor(final String key) { + fKeyTable.remove(key); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/color/IAIEColorConstants.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/color/IAIEColorConstants.java new file mode 100644 index 00000000..ff419070 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/color/IAIEColorConstants.java @@ -0,0 +1,79 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.color; + +/** + * Color keys used for syntax highlighting AlloyInEcore code and comments. A + * IColorManager is responsible for mapping concrete colors to these keys. + *

+ * This interface declares static final fields only; it is not intended to be implemented. + *

+ * + * @see eu.modelwriter.core.alloyinecore.ui.editor.color.jdt.ui.text.IColorManager + * @see eu.modelwriter.core.alloyinecore.ui.editor.color.jdt.ui.text.IColorManagerExtension + * + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. + */ +public interface IAIEColorConstants { + + /** + * Note: This constant is for internal use only. Clients should not use this constant. The prefix + * all color constants start with (value "aie_"). + */ + String PREFIX = "aie_"; + + /** + * The color key for multi-line comments in AlloyInEcore code (value + * "aie_multi_line_comment"). + */ + String AIE_MULTI_LINE_COMMENT = "aie_multi_line_comment"; + + /** + * The color key for single-line comments in AlloyInEcore code (value + * "aie_single_line_comment"). + */ + String AIE_SINGLE_LINE_COMMENT = "aie_single_line_comment"; + + /** + * The color key for keywords in AlloyInEcore code (value "keyword"). + */ + String KEYWORD = "keyword"; + + /** + * The color key for AlloyInEcore keywords in AlloyInEcore code (value + * "aie_keyword"). + */ + String AIE_KEYWORD = "aie_keyword"; + + /** + * The color key for AlloyInEcore keywords in AlloyInEcore code (value + * "aie_keyword"). + */ + String AIE_INSTANCE_SF_KEYWORD = "aie_instance_sf_keyword"; + + /** + * The color key for string and character literals in AlloyInEcore code (value + * "aie_string"). + */ + String AIE_STRING = "aie_string"; + + /** + * The color key for operators in AlloyInEcore code (value "aie_operator"). + */ + String AIE_OPERATOR = "aie_operator"; + + /** + * The color key for brackets in AlloyInEcore code (value "aie_bracket"). + */ + String AIE_BRACKET = "aie_bracket"; + + /** + * The color key for everything in AlloyInEcore code for which no other color is specified (value + * "aie_default"). + */ + String AIE_DEFAULT = "aie_default"; + + /** + * The color key for annotations (value "aie_annotation"). + */ + String AIE_ANNOTATION = "aie_annotation"; +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/color/IColorManager.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/color/IColorManager.java new file mode 100644 index 00000000..fb71918d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/color/IColorManager.java @@ -0,0 +1,17 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.color; + +import org.eclipse.jface.text.source.ISharedTextColors; +import org.eclipse.swt.graphics.Color; + + +public interface IColorManager extends ISharedTextColors { + + /** + * Returns a color object for the given key. The color objects are remembered internally; the same + * color object is returned for equal keys. + * + * @param key the color key + * @return the color object for the given key + */ + Color getColor(String key); +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/color/IColorManagerExtension.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/color/IColorManagerExtension.java new file mode 100644 index 00000000..f81351cf --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/color/IColorManagerExtension.java @@ -0,0 +1,27 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.color; + +import org.eclipse.swt.graphics.RGB; + + +/** + * Extends {@link eu.modelwriter.core.alloyinecore.ui.editor.color.IColorManager} with the ability to bind + * and un-bind colors. + */ +public interface IColorManagerExtension { + + /** + * Remembers the given color specification under the given key. + * + * @param key the color key + * @param rgb the color specification + */ + void bindColor(String key, RGB rgb); + + + /** + * Forgets the color specification remembered under the given key. + * + * @param key the color key + */ + void unbindColor(String key); +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/AIECompletionProcessor.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/AIECompletionProcessor.java new file mode 100644 index 00000000..ad8a9f2f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/AIECompletionProcessor.java @@ -0,0 +1,106 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.contentassist.CompletionProposal; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.IContentAssistProcessor; +import org.eclipse.jface.text.contentassist.IContextInformation; +import org.eclipse.jface.text.contentassist.IContextInformationValidator; + +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AIECompletionUtil; + +public class AIECompletionProcessor implements IContentAssistProcessor { + + private final char[] activationChars = new char[] {'c'}; + + @Override + public ICompletionProposal[] computeCompletionProposals(final ITextViewer viewer, + final int offset) { + final List proposals = new ArrayList<>(); + + final IDocument document = viewer.getDocument(); + + final AIECompletionUtil completionUtil = new AIECompletionUtil(document, offset); + + List completionWords; + try { + completionWords = completionUtil.getProposals(); + } catch (final BadLocationException e1) { + return new ICompletionProposal[0]; + } + + Character c = null; + try { + c = document.getChar(offset - 1); + } catch (final BadLocationException e) { + e.printStackTrace(); + } + int temp = offset - 1; + StringBuilder builder = new StringBuilder(); + + if (Character.isAlphabetic(c)) { + while (Character.isAlphabetic(c)) { + builder.append(c); + temp--; + try { + c = document.getChar(temp); + } catch (final BadLocationException e) { + } + } + builder = builder.reverse(); + + for (final String word : completionWords) { + if (word.toLowerCase().startsWith(builder.toString().toLowerCase())) { + proposals.add(new CompletionProposal(word, temp + 1, builder.length(), word.length())); + } + } + } else { + for (int i = 0; i < activationChars.length; i++) { + // if (activationChars[i] == c) { + for (final String word : completionWords) { + proposals.add(new CompletionProposal(word, temp + 1, builder.length(), word.length())); + } + // } + } + } + + final ICompletionProposal[] result = new ICompletionProposal[proposals.size()]; + proposals.toArray(result); + return result; + } + + @Override + public char[] getCompletionProposalAutoActivationCharacters() { + return activationChars; + } + + private final IContextInformation[] NO_CONTEXTS = {}; + + @Override + public IContextInformation[] computeContextInformation(final ITextViewer viewer, + final int offset) { + return NO_CONTEXTS; + } + + @Override + public char[] getContextInformationAutoActivationCharacters() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getErrorMessage() { + return "No completions available."; + } + + @Override + public IContextInformationValidator getContextInformationValidator() { + // TODO Auto-generated method stub + return null; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/AIEExpressionSuggestionProviderFactory.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/AIEExpressionSuggestionProviderFactory.java new file mode 100644 index 00000000..ecb8e6a5 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/AIEExpressionSuggestionProviderFactory.java @@ -0,0 +1,38 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.expression; + +import java.util.ArrayList; +import java.util.List; + +import eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.provider.ClosureSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.provider.ExpressionSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.provider.ReflexiveSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.provider.TransposeSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AIESuggestionProvider; + +public class AIEExpressionSuggestionProviderFactory { + + public AIESuggestionProvider expressionSP() { + return new ExpressionSuggestionProvider(); + } + + public AIESuggestionProvider transposeSP() { + return new TransposeSuggestionProvider(); + } + + public AIESuggestionProvider closureSP() { + return new ClosureSuggestionProvider(); + } + + public AIESuggestionProvider reflexiveSP() { + return new ReflexiveSuggestionProvider(); + } + + public List allSuggestionProviders() { + final List all = new ArrayList<>(); + all.add(expressionSP()); + all.add(transposeSP()); + all.add(closureSP()); + all.add(reflexiveSP()); + return all; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/ExpressionCompletionTokens.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/ExpressionCompletionTokens.java new file mode 100644 index 00000000..df6f7b92 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/ExpressionCompletionTokens.java @@ -0,0 +1,48 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.expression; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public interface ExpressionCompletionTokens { + String _transpose = "~"; + String _closure = "^"; + String _reflexive = "*"; + String _union = "+"; + String _intersection = "&"; + String _difference = "-"; + String _join = "."; + String _leftBracket = "["; + String _rightBracket = "]"; + String _product = "->"; + String _override = "++"; + String _comprehension = "|"; + List _if = new ArrayList<>(Arrays.asList("if", "=>")); + String _then = "then"; + String _else = "else"; + String _iden = "iden"; + String _none = "none"; + String _univ = "univ"; + String _ints = "ints"; + String _leftParenthesis = "("; + String _rightParenthesis = ")"; + String _sum = "sum"; + String _count = "#"; + List _plus = new ArrayList<>(Arrays.asList("plus", "+")); + List _minus = new ArrayList<>(Arrays.asList("minus", "-")); + List _multiply = new ArrayList<>(Arrays.asList("mul", "*")); + List _divide = new ArrayList<>(Arrays.asList("div", "/")); + List _modulo = new ArrayList<>(Arrays.asList("modulo", "%")); + String _negative = "-"; + String _comma = ","; + String _disj = "disj"; + String _colon = ":"; + String _one = "one"; + String _lone = "lone"; + String _some = "some"; + String _set = "set"; + List _mult = new ArrayList<>( + Arrays.asList(ExpressionCompletionTokens._set, ExpressionCompletionTokens._one, + ExpressionCompletionTokens._lone, ExpressionCompletionTokens._some)); + String _equals = "="; +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/BoxJoinSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/BoxJoinSuggestionProvider.java new file mode 100644 index 00000000..745b9eca --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/BoxJoinSuggestionProvider.java @@ -0,0 +1,63 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.BoxJoinContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ExpressionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnionContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.ExpressionCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class BoxJoinSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + return new HashSet<>(); + } + + @Override + protected void initParentProviders() { + parents.add(spFactory.expressionSP()); + } + + @Override + protected void initChildProviders() { + children.add(spFactory.expressionSP()); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof ExpressionContext) { + if (((UnionContext) context).right != null + && ((UnionContext) context).right.equals(lastToken)) { + suggestions.add(ExpressionCompletionTokens._leftBracket); + } else if (((UnionContext) context).left != null + && ((UnionContext) context).left.equals(lastToken)) { + suggestions.add(ExpressionCompletionTokens._rightBracket); + } + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ExpressionCompletionTokens._leftBracket)) { + suggestions.addAll(spFactory.expressionSP().getStartSuggestions()); + } else if (lastToken.getText().equals(ExpressionCompletionTokens._rightBracket)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof BoxJoinContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/ClosureSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/ClosureSuggestionProvider.java new file mode 100644 index 00000000..a24b5c98 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/ClosureSuggestionProvider.java @@ -0,0 +1,56 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ClosureContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ExpressionContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.ExpressionCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class ClosureSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.add(ExpressionCompletionTokens._closure); + return startSuggestions; + } + + @Override + protected void initParentProviders() { + parents.add(spFactory.expressionSP()); + } + + @Override + protected void initChildProviders() { + children.add(spFactory.expressionSP()); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof ExpressionContext) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ExpressionCompletionTokens._closure)) { + suggestions.addAll(spFactory.expressionSP().getStartSuggestions()); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof ClosureContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/DifferenceSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/DifferenceSuggestionProvider.java new file mode 100644 index 00000000..62486ccc --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/DifferenceSuggestionProvider.java @@ -0,0 +1,61 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.DifferenceContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ExpressionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnionContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.ExpressionCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class DifferenceSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + return new HashSet<>(); + } + + @Override + protected void initParentProviders() { + parents.add(spFactory.expressionSP()); + } + + @Override + protected void initChildProviders() { + children.add(spFactory.expressionSP()); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof ExpressionContext) { + if (((UnionContext) context).left != null + && ((UnionContext) context).left.equals(lastToken)) { + suggestions.add(ExpressionCompletionTokens._difference); + } else if (((UnionContext) context).right != null + && ((UnionContext) context).right.equals(lastToken)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ExpressionCompletionTokens._difference)) { + suggestions.addAll(spFactory.expressionSP().getStartSuggestions()); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof DifferenceContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/ExpressionSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/ExpressionSuggestionProvider.java new file mode 100644 index 00000000..c23f0743 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/ExpressionSuggestionProvider.java @@ -0,0 +1,60 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericTypeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ExpressionContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class ExpressionSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + // startSuggestions.add(ModelCompletionTokens._question); + return startSuggestions; + } + + @Override + protected void initParentProviders() { + // parents.add(spFactory.SP()); + } + + @Override + protected void initChildProviders() { + // children.add(spFactory.SP()); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof EGenericTypeContext) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._question)) { + suggestions.add(ModelCompletionTokens._extends); + suggestions.add(ModelCompletionTokens._super); + } else if (lastToken.getText().equals(ModelCompletionTokens._extends) + || lastToken.getText().equals(ModelCompletionTokens._super)) { + suggestions.addAll(spFactory.eGenericTypeSP().getStartSuggestions()); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof ExpressionContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/IntersectionSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/IntersectionSuggestionProvider.java new file mode 100644 index 00000000..1ba578d9 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/IntersectionSuggestionProvider.java @@ -0,0 +1,61 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ExpressionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.IntersectionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnionContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.ExpressionCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class IntersectionSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + return new HashSet<>(); + } + + @Override + protected void initParentProviders() { + parents.add(spFactory.expressionSP()); + } + + @Override + protected void initChildProviders() { + children.add(spFactory.expressionSP()); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof ExpressionContext) { + if (((UnionContext) context).left != null + && ((UnionContext) context).left.equals(lastToken)) { + suggestions.add(ExpressionCompletionTokens._intersection); + } else if (((UnionContext) context).right != null + && ((UnionContext) context).right.equals(lastToken)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ExpressionCompletionTokens._intersection)) { + suggestions.addAll(spFactory.expressionSP().getStartSuggestions()); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof IntersectionContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/JoinSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/JoinSuggestionProvider.java new file mode 100644 index 00000000..e459d227 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/JoinSuggestionProvider.java @@ -0,0 +1,61 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ExpressionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.JoinContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnionContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.ExpressionCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class JoinSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + return new HashSet<>(); + } + + @Override + protected void initParentProviders() { + parents.add(spFactory.expressionSP()); + } + + @Override + protected void initChildProviders() { + children.add(spFactory.expressionSP()); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof ExpressionContext) { + if (((UnionContext) context).left != null + && ((UnionContext) context).left.equals(lastToken)) { + suggestions.add(ExpressionCompletionTokens._join); + } else if (((UnionContext) context).right != null + && ((UnionContext) context).right.equals(lastToken)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ExpressionCompletionTokens._join)) { + suggestions.addAll(spFactory.expressionSP().getStartSuggestions()); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof JoinContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/OverrideSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/OverrideSuggestionProvider.java new file mode 100644 index 00000000..6d19dd11 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/OverrideSuggestionProvider.java @@ -0,0 +1,61 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ExpressionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.OverrideContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnionContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.ExpressionCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class OverrideSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + return new HashSet<>(); + } + + @Override + protected void initParentProviders() { + parents.add(spFactory.expressionSP()); + } + + @Override + protected void initChildProviders() { + children.add(spFactory.expressionSP()); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof ExpressionContext) { + if (((UnionContext) context).left != null + && ((UnionContext) context).left.equals(lastToken)) { + suggestions.add(ExpressionCompletionTokens._override); + } else if (((UnionContext) context).right != null + && ((UnionContext) context).right.equals(lastToken)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ExpressionCompletionTokens._override)) { + suggestions.addAll(spFactory.expressionSP().getStartSuggestions()); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof OverrideContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/ProductSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/ProductSuggestionProvider.java new file mode 100644 index 00000000..03533664 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/ProductSuggestionProvider.java @@ -0,0 +1,71 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ExpressionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.MultContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ProductContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.ExpressionCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class ProductSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + return new HashSet<>(); + } + + @Override + protected void initParentProviders() { + parents.add(spFactory.expressionSP()); + } + + @Override + protected void initChildProviders() { + children.add(spFactory.expressionSP()); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof ExpressionContext) { + if (((ProductContext) context).left != null + && ((ProductContext) context).left.equals(lastToken)) { + suggestions.addAll(ExpressionCompletionTokens._mult); + suggestions.add(ExpressionCompletionTokens._product); + } else if (((ProductContext) context).right != null + && ((ProductContext) context).right.equals(lastToken)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + } else if (lastToken instanceof MultContext) { + if (((ProductContext) context).leftMult != null + && ((ProductContext) context).leftMult.equals(lastToken)) { + suggestions.add(ExpressionCompletionTokens._product); + } else if (((ProductContext) context).rightMult != null + && ((ProductContext) context).rightMult.equals(lastToken)) { + suggestions.addAll(spFactory.expressionSP().getStartSuggestions()); + } + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ExpressionCompletionTokens._product)) { + suggestions.addAll(ExpressionCompletionTokens._mult); + suggestions.addAll(spFactory.expressionSP().getStartSuggestions()); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof ProductContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/ReflexiveSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/ReflexiveSuggestionProvider.java new file mode 100644 index 00000000..9c877dc1 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/ReflexiveSuggestionProvider.java @@ -0,0 +1,56 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ExpressionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ReflexiveContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.ExpressionCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class ReflexiveSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.add(ExpressionCompletionTokens._reflexive); + return startSuggestions; + } + + @Override + protected void initParentProviders() { + parents.add(spFactory.expressionSP()); + } + + @Override + protected void initChildProviders() { + children.add(spFactory.expressionSP()); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof ExpressionContext) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ExpressionCompletionTokens._reflexive)) { + suggestions.addAll(spFactory.expressionSP().getStartSuggestions()); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof ReflexiveContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/TransposeSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/TransposeSuggestionProvider.java new file mode 100644 index 00000000..f751d984 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/TransposeSuggestionProvider.java @@ -0,0 +1,56 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ExpressionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.TransposeContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.ExpressionCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class TransposeSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.add(ExpressionCompletionTokens._transpose); + return startSuggestions; + } + + @Override + protected void initParentProviders() { + parents.add(spFactory.expressionSP()); + } + + @Override + protected void initChildProviders() { + children.add(spFactory.expressionSP()); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof ExpressionContext) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ExpressionCompletionTokens._transpose)) { + suggestions.addAll(spFactory.expressionSP().getStartSuggestions()); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof TransposeContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/UnionSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/UnionSuggestionProvider.java new file mode 100644 index 00000000..9133fdc2 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/expression/provider/UnionSuggestionProvider.java @@ -0,0 +1,60 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ExpressionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnionContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.ExpressionCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class UnionSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + return new HashSet<>(); + } + + @Override + protected void initParentProviders() { + parents.add(spFactory.expressionSP()); + } + + @Override + protected void initChildProviders() { + children.add(spFactory.expressionSP()); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof ExpressionContext) { + if (((UnionContext) context).left != null + && ((UnionContext) context).left.equals(lastToken)) { + suggestions.add(ExpressionCompletionTokens._union); + } else if (((UnionContext) context).right != null + && ((UnionContext) context).right.equals(lastToken)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ExpressionCompletionTokens._union)) { + suggestions.addAll(spFactory.expressionSP().getStartSuggestions()); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof UnionContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/AIEModelSuggestionProviderFactory.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/AIEModelSuggestionProviderFactory.java new file mode 100644 index 00000000..ea6cc13c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/AIEModelSuggestionProviderFactory.java @@ -0,0 +1,289 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model; + +import java.util.ArrayList; +import java.util.List; + +import eu.modelwriter.core.alloyinecore.ui.editor.completion.expression.provider.ExpressionSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.BodySuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.DerivationSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EAnnotationSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EAttributeSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EClassSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EClassifierSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EDataTypeSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EDetailSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EEnumLiteralSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EEnumSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EGenericElementTypeSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EGenericExceptionSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EGenericSuperTypeSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EGenericTypeArgumentSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EGenericTypeSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EGenericWildcardSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EModelElementRefSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EModelElementSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EMultiplicitySuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.ENamedElementSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EOperationSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EPackageSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EParameterSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EPrimitiveTypeSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EReferenceSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.EStructuralFeatureSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.ETypeParameterSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.ETypedElementSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.FormulaSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.IdentifierSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.InitialSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.InvariantSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.LowerSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.ModelSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.OptionSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.OptionsSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.PackageImportSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.PathNameSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.PostconditionSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.PreconditionSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.SegmentSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.TemplateSignatureSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.UnrestrictedNameSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.UpperSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider.VisibilityKindSuggestionProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AIESuggestionProvider; + +public class AIEModelSuggestionProviderFactory { + + public AIESuggestionProvider bodySP() { + return new BodySuggestionProvider(); + } + + public AIESuggestionProvider derivationSP() { + return new DerivationSuggestionProvider(); + } + + public AIESuggestionProvider eAnnotationSP() { + return new EAnnotationSuggestionProvider(); + } + + public AIESuggestionProvider eAttributeSP() { + return new EAttributeSuggestionProvider(); + } + + public AIESuggestionProvider eClassifierSP() { + return new EClassifierSuggestionProvider(); + } + + public AIESuggestionProvider eClassSP() { + return new EClassSuggestionProvider(); + } + + public AIESuggestionProvider eDatatypeSP() { + return new EDataTypeSuggestionProvider(); + } + + public AIESuggestionProvider eDetailSP() { + return new EDetailSuggestionProvider(); + } + + public AIESuggestionProvider eEnumSP() { + return new EEnumSuggestionProvider(); + } + + public AIESuggestionProvider eEnumliteralSP() { + return new EEnumLiteralSuggestionProvider(); + } + + public AIESuggestionProvider eModelElementRefSP() { + return new EModelElementRefSuggestionProvider(); + } + + public AIESuggestionProvider eModelElementSP() { + return new EModelElementSuggestionProvider(); + } + + public AIESuggestionProvider eNamedElementSP() { + return new ENamedElementSuggestionProvider(); + } + + public AIESuggestionProvider eOperationSP() { + return new EOperationSuggestionProvider(); + } + + public AIESuggestionProvider ePackageSP() { + return new EPackageSuggestionProvider(); + } + + public AIESuggestionProvider eParameterSP() { + return new EParameterSuggestionProvider(); + } + + public AIESuggestionProvider eReferenceSP() { + return new EReferenceSuggestionProvider(); + } + + public AIESuggestionProvider eStructuralFeatureSP() { + return new EStructuralFeatureSuggestionProvider(); + } + + public AIESuggestionProvider eTypedElementSP() { + return new ETypedElementSuggestionProvider(); + } + + public AIESuggestionProvider expressionSP() { + return new ExpressionSuggestionProvider(); + } + + public AIESuggestionProvider formulaSP() { + return new FormulaSuggestionProvider(); + } + + public AIESuggestionProvider indentifierSP() { + return new IdentifierSuggestionProvider(); + } + + public AIESuggestionProvider initialSP() { + return new InitialSuggestionProvider(); + } + + public AIESuggestionProvider invariantSP() { + return new InvariantSuggestionProvider(); + } + + public AIESuggestionProvider lowerSP() { + return new LowerSuggestionProvider(); + } + + public AIESuggestionProvider modelSP() { + return new ModelSuggestionProvider(); + } + + public AIESuggestionProvider multiplicitySP() { + return new EMultiplicitySuggestionProvider(); + } + + public AIESuggestionProvider optionsSP() { + return new OptionsSuggestionProvider(); + } + + public AIESuggestionProvider optionSP() { + return new OptionSuggestionProvider(); + } + + public AIESuggestionProvider packageImportSP() { + return new PackageImportSuggestionProvider(); + } + + public AIESuggestionProvider pathNameSP() { + return new PathNameSuggestionProvider(); + } + + public AIESuggestionProvider postconditionSP() { + return new PostconditionSuggestionProvider(); + } + + public AIESuggestionProvider preconditionSP() { + return new PreconditionSuggestionProvider(); + } + + public AIESuggestionProvider templateSignatureSP() { + return new TemplateSignatureSuggestionProvider(); + } + + public AIESuggestionProvider unrestrictedNameSP() { + return new UnrestrictedNameSuggestionProvider(); + } + + public AIESuggestionProvider upperSP() { + return new UpperSuggestionProvider(); + } + + public AIESuggestionProvider visibilityKindSP() { + return new VisibilityKindSuggestionProvider(); + } + + public AIESuggestionProvider eGenericExceptionSP() { + return new EGenericExceptionSuggestionProvider(); + } + + public AIESuggestionProvider eGenericSuperTypeSP() { + return new EGenericSuperTypeSuggestionProvider(); + } + + public AIESuggestionProvider eGenericTypeSP() { + return new EGenericTypeSuggestionProvider(); + } + + public AIESuggestionProvider eGenericTypeArgumentSP() { + return new EGenericTypeArgumentSuggestionProvider(); + } + + public AIESuggestionProvider ePrimitiveTypeSP() { + return new EPrimitiveTypeSuggestionProvider(); + } + + public AIESuggestionProvider eGenericElementTypeSP() { + return new EGenericElementTypeSuggestionProvider(); + } + + public AIESuggestionProvider eTypeParameterSP() { + return new ETypeParameterSuggestionProvider(); + } + + public AIESuggestionProvider eGenericWildcardSP() { + return new EGenericWildcardSuggestionProvider(); + } + + public AIESuggestionProvider segmentSP() { + return new SegmentSuggestionProvider(); + } + + public List allSuggestionProviders() { + final List all = new ArrayList<>(); + all.add(bodySP()); + all.add(derivationSP()); + all.add(eAnnotationSP()); + all.add(eAttributeSP()); + all.add(eClassifierSP()); + all.add(eClassSP()); + all.add(eDatatypeSP()); + all.add(eDetailSP()); + all.add(eEnumSP()); + all.add(eEnumliteralSP()); + all.add(eModelElementRefSP()); + all.add(eModelElementSP()); + all.add(eNamedElementSP()); + all.add(eOperationSP()); + all.add(ePackageSP()); + all.add(eParameterSP()); + all.add(eReferenceSP()); + all.add(eStructuralFeatureSP()); + all.add(eTypedElementSP()); + all.add(expressionSP()); + all.add(formulaSP()); + all.add(indentifierSP()); + all.add(initialSP()); + all.add(lowerSP()); + all.add(modelSP()); + all.add(multiplicitySP()); + all.add(optionsSP()); + all.add(optionSP()); + all.add(packageImportSP()); + all.add(pathNameSP()); + all.add(postconditionSP()); + all.add(preconditionSP()); + all.add(templateSignatureSP()); + all.add(unrestrictedNameSP()); + all.add(upperSP()); + all.add(visibilityKindSP()); + all.add(eGenericExceptionSP()); + all.add(eGenericSuperTypeSP()); + all.add(eGenericTypeSP()); + all.add(eGenericTypeArgumentSP()); + all.add(ePrimitiveTypeSP()); + all.add(eGenericElementTypeSP()); + all.add(eTypeParameterSP()); + all.add(eGenericWildcardSP()); + all.add(segmentSP()); + return all; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/ModelCompletionTokens.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/ModelCompletionTokens.java new file mode 100644 index 00000000..6b128168 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/ModelCompletionTokens.java @@ -0,0 +1,103 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public interface ModelCompletionTokens { + String _options = "options"; + String _symmetry_breaking = "symmetry_breaking"; + String _bit_width = "bit_width"; + String _skolem_depth = "skolem_depth"; + String _sharing = "sharing"; + List _option = new ArrayList<>(Arrays.asList(ModelCompletionTokens._symmetry_breaking, + ModelCompletionTokens._bit_width, ModelCompletionTokens._skolem_depth, ModelCompletionTokens._sharing)); + String _model = "model"; + String _import = "import"; + String _public = "public"; + String _protected = "protected"; + String _private = "private"; + List _visibility = new ArrayList<>(Arrays.asList(ModelCompletionTokens._public, + ModelCompletionTokens._protected, ModelCompletionTokens._private)); + String _package = "package"; + String _semicolon = ";"; + String _colon = ":"; + String _leftCurly = "{"; + String _rightCurly = "}"; + String _comma = ","; + String _singleQuote = "''"; + String _doubleQuote = "\"\""; + String _equals = "="; + String _abstract = "abstract"; + String _interface = "interface"; + String _class = "class"; + String _datatype = "datatype"; + String _enum = "enum"; + String _primitive = "primitive"; + String _callable = "callable"; + String _invariant = "invariant"; + String _annotation = "annotation"; + String _leftArrow = "<"; + String _rightArrow = ">"; + String _extends = "extends"; + String _super = "super"; + String _static = "static"; + String _operation = "operation"; + String _ghost = "ghost"; + String _transient = "transient"; + String _volatile = "volatile"; + String _readonly = "readonly"; + String _attribute = "attribute"; + String _property = "property"; + String _serializable = "serializable"; + String _notSerializable = "!" + ModelCompletionTokens._serializable; + String _literal = "literal"; + String _leftParenthesis = "("; + String _rightParenthesis = ")"; + String _reference = "reference"; + String _derivation = "derivation"; + String _initial = "initial"; + String _precondition = "precondition"; + String _requires = "requires"; + String _postcondition = "postcondition"; + String _ensures = "ensures"; + String _body = "body"; + String _leftBracket = "["; + String _rightBracket = "]"; + String _derived = "derived"; + String _id = "id"; + String _ordered = "ordered"; + String _notOrdered = "!" + ModelCompletionTokens._ordered; + String _unique = "unique"; + String _notUnique = "!" + ModelCompletionTokens._unique; + String _unsettable = "unsettable"; + String _notUnsettable = "!" + ModelCompletionTokens._unsettable; + String _ellipsis = ".."; + String _asterisk = "*"; + String _plus = "+"; + String _question = "?"; + List _stringBounds = new ArrayList<>(Arrays.asList(ModelCompletionTokens._asterisk, + ModelCompletionTokens._plus, ModelCompletionTokens._question)); + String _nullFree = "|1"; + String _nullAble = "|?"; + List _isnullable = + new ArrayList<>(Arrays.asList(ModelCompletionTokens._nullFree, ModelCompletionTokens._nullAble)); + String _sharp = "#"; + String _composes = "composes"; + String _resolve = "resolve"; + String _notResolve = "!" + ModelCompletionTokens._resolve; + String _key = "key"; + String _throws = "throws"; + String _boolean = "Boolean"; + String _integer = "Integer"; + String _string = "String"; + String _real = "Real"; + String _unlimitedNatural = "UnlimitedNatural"; + List _primitives = + new ArrayList<>(Arrays.asList(ModelCompletionTokens._boolean, ModelCompletionTokens._integer, + ModelCompletionTokens._string, ModelCompletionTokens._real, ModelCompletionTokens._unlimitedNatural)); + String _ampersand = "&"; + String _dot = "."; + String _doubleColon = "::"; + String _at = "@"; +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/BodySuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/BodySuggestionProvider.java new file mode 100644 index 00000000..78c8aaae --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/BodySuggestionProvider.java @@ -0,0 +1,68 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.BodyContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ExpressionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.IdentifierContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class BodySuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.add(ModelCompletionTokens._body); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof IdentifierContext) { + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof ExpressionContext) { + suggestions.add(ModelCompletionTokens._semicolon); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._body)) { + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._colon)) { + suggestions.addAll( + spFactory.expressionSP().getStartSuggestions()); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._semicolon)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof BodyContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eOperationSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.indentifierSP()); + addChild(spFactory.expressionSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/DerivationSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/DerivationSuggestionProvider.java new file mode 100644 index 00000000..474ce656 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/DerivationSuggestionProvider.java @@ -0,0 +1,70 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.DerivationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ExpressionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.IdentifierContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class DerivationSuggestionProvider extends AbstractAIESuggestionProvider { + + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.add(ModelCompletionTokens._derivation); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof IdentifierContext) { + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof ExpressionContext) { + suggestions.add(ModelCompletionTokens._semicolon); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._derivation)) { + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._colon)) { + suggestions.addAll( + spFactory.expressionSP().getStartSuggestions()); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._semicolon)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof DerivationContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eAttributeSP()); + addParent(spFactory.eReferenceSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.indentifierSP()); + addChild(spFactory.expressionSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EAnnotationSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EAnnotationSuggestionProvider.java new file mode 100644 index 00000000..e0299883 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EAnnotationSuggestionProvider.java @@ -0,0 +1,107 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EAnnotationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EDetailContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EModelElementContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EModelElementRefContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EAnnotationSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.add(ModelCompletionTokens._annotation); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof EDetailContext) { + suggestions.add(ModelCompletionTokens._comma); + suggestions.add(ModelCompletionTokens._rightParenthesis); + } else if (lastToken instanceof EAnnotationContext + || lastToken instanceof EModelElementContext + || lastToken instanceof EModelElementRefContext) { + suggestions.addAll( + spFactory.eAnnotationSP().getStartSuggestions()); + suggestions.addAll(spFactory.eModelElementSP() + .getStartSuggestions()); + suggestions.addAll(spFactory.eModelElementRefSP() + .getStartSuggestions()); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._annotation)) { + suggestions.add(ModelCompletionTokens._singleQuote); + suggestions.add(ModelCompletionTokens._leftParenthesis); + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (((TerminalNode) lastToken).getSymbol() + .getType() == AlloyInEcoreLexer.SINGLE_QUOTED_STRING) { + suggestions.add(ModelCompletionTokens._leftParenthesis); + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._leftParenthesis)) { + suggestions.add(ModelCompletionTokens._singleQuote); + } else if (lastToken.getText().equals(ModelCompletionTokens._comma)) { + suggestions.add(ModelCompletionTokens._singleQuote); + } else if (lastToken.getText().equals(ModelCompletionTokens._rightParenthesis)) { + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._leftCurly)) { + suggestions.addAll( + spFactory.eAnnotationSP().getStartSuggestions()); + suggestions.addAll(spFactory.eModelElementSP() + .getStartSuggestions()); + suggestions.addAll(spFactory.eModelElementRefSP() + .getStartSuggestions()); + } else if (lastToken.getText().equals(ModelCompletionTokens._rightCurly) + || lastToken.getText().equals(ModelCompletionTokens._semicolon)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EAnnotationContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.ePackageSP()); + addParent(spFactory.eClassSP()); + addParent(spFactory.eAttributeSP()); + addParent(spFactory.eReferenceSP()); + addParent(spFactory.eOperationSP()); + addParent(spFactory.eParameterSP()); + addParent(spFactory.eDatatypeSP()); + addParent(spFactory.eEnumSP()); + addParent(spFactory.eEnumliteralSP()); + addParent(spFactory.eAnnotationSP()); + addParent(spFactory.eModelElementSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.eDetailSP()); + addChild(spFactory.eAnnotationSP()); + addChild(spFactory.eModelElementSP()); + addChild(spFactory.eModelElementRefSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EAttributeSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EAttributeSuggestionProvider.java new file mode 100644 index 00000000..7f3944a6 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EAttributeSuggestionProvider.java @@ -0,0 +1,180 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.DerivationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EAnnotationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EAttributeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericElementTypeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EMultiplicityContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.InitialContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnrestrictedNameContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.VisibilityKindContext; +import eu.modelwriter.core.alloyinecore.structure.base.ITarget; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AIECompletionUtil; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EAttributeSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.addAll(spFactory.visibilityKindSP().getStartSuggestions()); + startSuggestions.add(ModelCompletionTokens._static); + startSuggestions.add(ModelCompletionTokens._model); + startSuggestions.add(ModelCompletionTokens._ghost); + startSuggestions.add(ModelCompletionTokens._transient); + startSuggestions.add(ModelCompletionTokens._volatile); + startSuggestions.add(ModelCompletionTokens._readonly); + startSuggestions.add(ModelCompletionTokens._attribute); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof VisibilityKindContext) { + suggestions.add(ModelCompletionTokens._static); + suggestions.add(ModelCompletionTokens._model); + suggestions.add(ModelCompletionTokens._ghost); + suggestions.add(ModelCompletionTokens._transient); + suggestions.add(ModelCompletionTokens._volatile); + suggestions.add(ModelCompletionTokens._readonly); + suggestions.add(ModelCompletionTokens._attribute); + } else if (lastToken instanceof UnrestrictedNameContext) { + suggestions.add(ModelCompletionTokens._colon); + } else if (lastToken instanceof EGenericElementTypeContext) { + suggestions.addAll(spFactory.multiplicitySP().getStartSuggestions()); + suggestions.add(ModelCompletionTokens._equals); + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof EMultiplicityContext) { + suggestions.add(ModelCompletionTokens._equals); + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof EAnnotationContext) { + suggestions.addAll(spFactory.eAnnotationSP().getStartSuggestions()); + suggestions.addAll(spFactory.derivationSP().getStartSuggestions()); + suggestions.addAll(spFactory.initialSP().getStartSuggestions()); + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof DerivationContext || lastToken instanceof InitialContext) { + suggestions.addAll(spFactory.eAnnotationSP().getStartSuggestions()); + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._static)) { + suggestions.add(ModelCompletionTokens._model); + suggestions.add(ModelCompletionTokens._ghost); + suggestions.add(ModelCompletionTokens._transient); + suggestions.add(ModelCompletionTokens._volatile); + suggestions.add(ModelCompletionTokens._readonly); + suggestions.add(ModelCompletionTokens._attribute); + } else if (lastToken.getText().equals(ModelCompletionTokens._model) + || lastToken.getText().equals(ModelCompletionTokens._ghost)) { + suggestions.add(ModelCompletionTokens._transient); + suggestions.add(ModelCompletionTokens._volatile); + suggestions.add(ModelCompletionTokens._readonly); + suggestions.add(ModelCompletionTokens._attribute); + } else if (lastToken.getText().equals(ModelCompletionTokens._transient)) { + suggestions.add(ModelCompletionTokens._volatile); + suggestions.add(ModelCompletionTokens._readonly); + suggestions.add(ModelCompletionTokens._attribute); + } else if (lastToken.getText().equals(ModelCompletionTokens._volatile)) { + suggestions.add(ModelCompletionTokens._readonly); + suggestions.add(ModelCompletionTokens._attribute); + } else if (lastToken.getText().equals(ModelCompletionTokens._readonly)) { + suggestions.add(ModelCompletionTokens._attribute); + } else if (lastToken.getText().equals(ModelCompletionTokens._attribute)) { + // attribute name + } else if (lastToken.getText().equals(ModelCompletionTokens._colon)) { + // attribute type + final EAttributeContext fullContext = + (EAttributeContext) AIECompletionUtil.getFullContext(context); + if (fullContext != null) { + final List targets = fullContext.current.getTargets().stream() + .map(e -> (ITarget) e).collect(Collectors.toList()); + for (final ITarget target : targets) { + suggestions.add(target.getRelativeSegment()); + } + } + } else if (lastToken.getText().equals(ModelCompletionTokens._equals)) { + suggestions.add(ModelCompletionTokens._singleQuote); + } else if (((TerminalNode) lastToken).getSymbol() + .getType() == AlloyInEcoreLexer.SINGLE_QUOTED_STRING) { + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._leftCurly)) { + suggestions.add(ModelCompletionTokens._derived); + suggestions.add(ModelCompletionTokens._id); + suggestions.add(ModelCompletionTokens._ordered); + suggestions.add(ModelCompletionTokens._notOrdered); + suggestions.add(ModelCompletionTokens._unique); + suggestions.add(ModelCompletionTokens._notUnique); + suggestions.add(ModelCompletionTokens._unsettable); + suggestions.add(ModelCompletionTokens._notUnsettable); + suggestions.addAll(spFactory.eAnnotationSP().getStartSuggestions()); + suggestions.addAll(spFactory.derivationSP().getStartSuggestions()); + suggestions.addAll(spFactory.initialSP().getStartSuggestions()); + } else if (lastToken.getText().equals(ModelCompletionTokens._comma)) { + suggestions.add(ModelCompletionTokens._derived); + suggestions.add(ModelCompletionTokens._id); + suggestions.add(ModelCompletionTokens._ordered); + suggestions.add(ModelCompletionTokens._notOrdered); + suggestions.add(ModelCompletionTokens._unique); + suggestions.add(ModelCompletionTokens._notUnique); + suggestions.add(ModelCompletionTokens._unsettable); + suggestions.add(ModelCompletionTokens._notUnsettable); + } else if (lastToken.getText().equals(ModelCompletionTokens._derived) + || lastToken.getText().equals(ModelCompletionTokens._id) + || lastToken.getText().equals(ModelCompletionTokens._ordered) + || lastToken.getText().equals(ModelCompletionTokens._notOrdered) + || lastToken.getText().equals(ModelCompletionTokens._unique) + || lastToken.getText().equals(ModelCompletionTokens._notUnique) + || lastToken.getText().equals(ModelCompletionTokens._unsettable) + || lastToken.getText().equals(ModelCompletionTokens._notUnsettable)) { + suggestions.add(ModelCompletionTokens._comma); + suggestions.add(ModelCompletionTokens._rightCurly); + } else if (lastToken.getText().equals(ModelCompletionTokens._rightCurly) + || lastToken.getText().equals(ModelCompletionTokens._semicolon)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EAttributeContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eStructuralFeatureSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.visibilityKindSP()); + addChild(spFactory.unrestrictedNameSP()); + addChild(spFactory.eGenericElementTypeSP()); + addChild(spFactory.multiplicitySP()); + addChild(spFactory.eAnnotationSP()); + addChild(spFactory.derivationSP()); + addChild(spFactory.initialSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EClassSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EClassSuggestionProvider.java new file mode 100644 index 00000000..17f7712e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EClassSuggestionProvider.java @@ -0,0 +1,134 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EAnnotationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EClassContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericSuperTypeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EOperationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EStructuralFeatureContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.InvariantContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.TemplateSignatureContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnrestrictedNameContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.VisibilityKindContext; +import eu.modelwriter.core.alloyinecore.structure.base.ITarget; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AIECompletionUtil; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EClassSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.addAll(spFactory.visibilityKindSP().getStartSuggestions()); + startSuggestions.add(ModelCompletionTokens._abstract); + startSuggestions.add(ModelCompletionTokens._class); + startSuggestions.add(ModelCompletionTokens._interface); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof VisibilityKindContext) { + suggestions.add(ModelCompletionTokens._abstract); + suggestions.add(ModelCompletionTokens._class); + suggestions.add(ModelCompletionTokens._interface); + } else if (lastToken instanceof UnrestrictedNameContext) { + suggestions.addAll(spFactory.templateSignatureSP().getStartSuggestions()); + suggestions.add(ModelCompletionTokens._extends); + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof TemplateSignatureContext) { + suggestions.add(ModelCompletionTokens._extends); + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof EGenericSuperTypeContext) { + suggestions.add(ModelCompletionTokens._comma); + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof EAnnotationContext || lastToken instanceof EOperationContext + || lastToken instanceof EStructuralFeatureContext + || lastToken instanceof InvariantContext) { + suggestions.addAll(spFactory.eAnnotationSP().getStartSuggestions()); + suggestions.addAll(spFactory.eOperationSP().getStartSuggestions()); + suggestions.addAll(spFactory.eStructuralFeatureSP().getStartSuggestions()); + suggestions.addAll(spFactory.invariantSP().getStartSuggestions()); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._abstract)) { + suggestions.add(ModelCompletionTokens._class); + } else if (lastToken.getText().equals(ModelCompletionTokens._extends)) { + // super type + final EClassContext fullContext = (EClassContext) AIECompletionUtil.getFullContext(context); + if (fullContext != null) { + final List targets = fullContext.current.getTargets().stream() + .map(e -> (ITarget) e).collect(Collectors.toList()); + for (final ITarget target : targets) { + suggestions.add(target.getRelativeSegment()); + } + } + } else if (lastToken.getText().equals(ModelCompletionTokens._comma)) { + // super type + final List targets = ((EClassContext) context).current.getTargets().stream() + .map(e -> (ITarget) e).collect(Collectors.toList()); + for (final ITarget target : targets) { + suggestions.add(target.getRelativeSegment()); + } + } else if (lastToken.getText().equals(ModelCompletionTokens._colon)) { + suggestions.add(ModelCompletionTokens._singleQuote); + } else if (((TerminalNode) lastToken).getSymbol() + .getType() == AlloyInEcoreLexer.SINGLE_QUOTED_STRING) { + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._leftCurly)) { + suggestions.addAll(spFactory.eAnnotationSP().getStartSuggestions()); + suggestions.addAll(spFactory.eOperationSP().getStartSuggestions()); + suggestions.addAll(spFactory.eStructuralFeatureSP().getStartSuggestions()); + suggestions.addAll(spFactory.invariantSP().getStartSuggestions()); + } else if (lastToken.getText().equals(ModelCompletionTokens._rightCurly) + || lastToken.getText().equals(ModelCompletionTokens._semicolon)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EClassContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eClassifierSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.visibilityKindSP()); + addChild(spFactory.unrestrictedNameSP()); + addChild(spFactory.templateSignatureSP()); + addChild(spFactory.eGenericSuperTypeSP()); + addChild(spFactory.eAnnotationSP()); + addChild(spFactory.eOperationSP()); + addChild(spFactory.eStructuralFeatureSP()); + addChild(spFactory.invariantSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EClassifierSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EClassifierSuggestionProvider.java new file mode 100644 index 00000000..48f3e432 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EClassifierSuggestionProvider.java @@ -0,0 +1,49 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EClassifierContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EClassifierSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions + .addAll(spFactory.eClassSP().getStartSuggestions()); + startSuggestions.addAll( + spFactory.eDatatypeSP().getStartSuggestions()); + startSuggestions + .addAll(spFactory.eEnumSP().getStartSuggestions()); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EClassifierContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.ePackageSP()); + addParent(spFactory.eNamedElementSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.eClassSP()); + addChild(spFactory.eDatatypeSP()); + addChild(spFactory.eEnumSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EDataTypeSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EDataTypeSuggestionProvider.java new file mode 100644 index 00000000..9082d167 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EDataTypeSuggestionProvider.java @@ -0,0 +1,103 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EAnnotationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EDataTypeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.InvariantContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.TemplateSignatureContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnrestrictedNameContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.VisibilityKindContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EDataTypeSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.addAll( + spFactory.visibilityKindSP().getStartSuggestions()); + startSuggestions.add(ModelCompletionTokens._primitive); + startSuggestions.add(ModelCompletionTokens._datatype); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof VisibilityKindContext) { + suggestions.add(ModelCompletionTokens._primitive); + suggestions.add(ModelCompletionTokens._datatype); + } else if (lastToken instanceof UnrestrictedNameContext) { + suggestions.addAll(spFactory.templateSignatureSP() + .getStartSuggestions()); + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof TemplateSignatureContext) { + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof EAnnotationContext || lastToken instanceof InvariantContext) { + suggestions.addAll( + spFactory.eAnnotationSP().getStartSuggestions()); + suggestions.addAll( + spFactory.invariantSP().getStartSuggestions()); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._primitive)) { + suggestions.add(ModelCompletionTokens._datatype); + } else if (lastToken.getText().equals(ModelCompletionTokens._colon)) { + suggestions.add(ModelCompletionTokens._singleQuote); + } else if (((TerminalNode) lastToken).getSymbol() + .getType() == AlloyInEcoreLexer.SINGLE_QUOTED_STRING) { + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._leftCurly)) { + suggestions.add(ModelCompletionTokens._serializable); + suggestions.add(ModelCompletionTokens._notSerializable); + suggestions.addAll( + spFactory.eAnnotationSP().getStartSuggestions()); + suggestions.addAll( + spFactory.invariantSP().getStartSuggestions()); + } else if (lastToken.getText().equals(ModelCompletionTokens._serializable) + || lastToken.getText().equals(ModelCompletionTokens._notSerializable)) { + suggestions.add(ModelCompletionTokens._rightCurly); + } else if (lastToken.getText().equals(ModelCompletionTokens._rightCurly) + || lastToken.getText().equals(ModelCompletionTokens._semicolon)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EDataTypeContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eClassifierSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.visibilityKindSP()); + addChild(spFactory.unrestrictedNameSP()); + addChild(spFactory.templateSignatureSP()); + addChild(spFactory.eAnnotationSP()); + addChild(spFactory.invariantSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EDetailSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EDetailSuggestionProvider.java new file mode 100644 index 00000000..e839f34d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EDetailSuggestionProvider.java @@ -0,0 +1,40 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EDetailContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EDetailSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + return new HashSet<>(); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EDetailContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eAnnotationSP()); + } + + @Override + protected void initChildProviders() { + // TODO Auto-generated method stub + + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EEnumLiteralSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EEnumLiteralSuggestionProvider.java new file mode 100644 index 00000000..7b58bc52 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EEnumLiteralSuggestionProvider.java @@ -0,0 +1,73 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EAnnotationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EEnumLiteralContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnrestrictedNameContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EEnumLiteralSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.add(ModelCompletionTokens._literal); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof UnrestrictedNameContext) { + suggestions.addAll(spFactory.templateSignatureSP() + .getStartSuggestions()); + suggestions.add(ModelCompletionTokens._equals); + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof EAnnotationContext) { + suggestions.add(ModelCompletionTokens._rightCurly); + } + } else if (lastToken instanceof TerminalNode) { + if (((TerminalNode) lastToken).getSymbol().getType() == AlloyInEcoreLexer.INT) { + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._leftCurly)) { + suggestions.addAll( + spFactory.eAnnotationSP().getStartSuggestions()); + } else if (lastToken.getText().equals(ModelCompletionTokens._rightCurly) + || lastToken.getText().equals(ModelCompletionTokens._semicolon)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EEnumLiteralContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eEnumSP()); + addParent(spFactory.eNamedElementSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.unrestrictedNameSP()); + addChild(spFactory.eAnnotationSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EEnumSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EEnumSuggestionProvider.java new file mode 100644 index 00000000..2bf424c9 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EEnumSuggestionProvider.java @@ -0,0 +1,106 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EAnnotationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EEnumContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EEnumLiteralContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.InvariantContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.TemplateSignatureContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnrestrictedNameContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.VisibilityKindContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EEnumSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.addAll( + spFactory.visibilityKindSP().getStartSuggestions()); + startSuggestions.add(ModelCompletionTokens._enum); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof VisibilityKindContext) { + suggestions.add(ModelCompletionTokens._enum); + } else if (lastToken instanceof UnrestrictedNameContext) { + suggestions.addAll(spFactory.templateSignatureSP() + .getStartSuggestions()); + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof TemplateSignatureContext) { + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof EAnnotationContext || lastToken instanceof EEnumLiteralContext + || lastToken instanceof InvariantContext) { + suggestions.addAll( + spFactory.eAnnotationSP().getStartSuggestions()); + suggestions.addAll(spFactory.eEnumliteralSP() + .getStartSuggestions()); + suggestions.addAll( + spFactory.invariantSP().getStartSuggestions()); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._colon)) { + suggestions.add(ModelCompletionTokens._singleQuote); + } else if (((TerminalNode) lastToken).getSymbol() + .getType() == AlloyInEcoreLexer.SINGLE_QUOTED_STRING) { + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._leftCurly)) { + suggestions.add(ModelCompletionTokens._serializable); + suggestions.add(ModelCompletionTokens._notSerializable); + suggestions.addAll( + spFactory.eAnnotationSP().getStartSuggestions()); + suggestions.addAll(spFactory.eEnumliteralSP() + .getStartSuggestions()); + suggestions.addAll( + spFactory.invariantSP().getStartSuggestions()); + } else if (lastToken.getText().equals(ModelCompletionTokens._serializable) + || lastToken.getText().equals(ModelCompletionTokens._notSerializable)) { + suggestions.add(ModelCompletionTokens._rightCurly); + } else if (lastToken.getText().equals(ModelCompletionTokens._rightCurly) + || lastToken.getText().equals(ModelCompletionTokens._semicolon)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EEnumContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eClassifierSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.visibilityKindSP()); + addChild(spFactory.unrestrictedNameSP()); + addChild(spFactory.templateSignatureSP()); + addChild(spFactory.eAnnotationSP()); + addChild(spFactory.eEnumliteralSP()); + addChild(spFactory.invariantSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EGenericElementTypeSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EGenericElementTypeSuggestionProvider.java new file mode 100644 index 00000000..1b206ab1 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EGenericElementTypeSuggestionProvider.java @@ -0,0 +1,48 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericElementTypeContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EGenericElementTypeSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.addAll( + spFactory.ePrimitiveTypeSP().getStartSuggestions()); + startSuggestions.addAll( + spFactory.eGenericTypeSP().getStartSuggestions()); + return startSuggestions; + } + + @Override + protected void initParentProviders() { + parents.add(spFactory.eAttributeSP()); + parents.add(spFactory.eReferenceSP()); + parents.add(spFactory.eOperationSP()); + parents.add(spFactory.eParameterSP()); + } + + @Override + protected void initChildProviders() { + children.add(spFactory.ePrimitiveTypeSP()); + children.add(spFactory.eGenericTypeSP()); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EGenericElementTypeContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EGenericExceptionSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EGenericExceptionSuggestionProvider.java new file mode 100644 index 00000000..f8076890 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EGenericExceptionSuggestionProvider.java @@ -0,0 +1,43 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericExceptionContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EGenericExceptionSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions + .addAll(spFactory.eGenericTypeSP() + .getStartSuggestions()); + return startSuggestions; + } + + @Override + protected void initParentProviders() { + parents.add(spFactory.eOperationSP()); + } + + @Override + protected void initChildProviders() { + children.add(spFactory.eGenericTypeSP()); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EGenericExceptionContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EGenericSuperTypeSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EGenericSuperTypeSuggestionProvider.java new file mode 100644 index 00000000..64e5fd6c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EGenericSuperTypeSuggestionProvider.java @@ -0,0 +1,42 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericSuperTypeContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EGenericSuperTypeSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.addAll( + spFactory.eGenericTypeSP().getStartSuggestions()); + return startSuggestions; + } + + @Override + protected void initParentProviders() { + parents.add(spFactory.eClassSP()); + } + + @Override + protected void initChildProviders() { + children.add(spFactory.eGenericTypeSP()); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EGenericSuperTypeContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EGenericTypeArgumentSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EGenericTypeArgumentSuggestionProvider.java new file mode 100644 index 00000000..b4c9896c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EGenericTypeArgumentSuggestionProvider.java @@ -0,0 +1,45 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericTypeArgumentContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EGenericTypeArgumentSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.addAll( + spFactory.eGenericTypeSP().getStartSuggestions()); + startSuggestions.addAll(spFactory.eGenericWildcardSP() + .getStartSuggestions()); + return startSuggestions; + } + + @Override + protected void initParentProviders() { + parents.add(spFactory.eGenericTypeSP()); + } + + @Override + protected void initChildProviders() { + children.add(spFactory.eGenericTypeSP()); + children.add(spFactory.eGenericWildcardSP()); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EGenericTypeArgumentContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EGenericTypeSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EGenericTypeSuggestionProvider.java new file mode 100644 index 00000000..769f7f84 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EGenericTypeSuggestionProvider.java @@ -0,0 +1,73 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericTypeArgumentContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericTypeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.PathNameContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EGenericTypeSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.addAll( + spFactory.pathNameSP().getStartSuggestions()); + return startSuggestions; + } + + @Override + protected void initParentProviders() { + parents.add(spFactory.eGenericExceptionSP()); + parents.add(spFactory.eGenericSuperTypeSP()); + parents.add(spFactory.eTypeParameterSP()); + parents.add(spFactory.eGenericTypeArgumentSP()); + parents.add(spFactory.eGenericElementTypeSP()); + parents.add(spFactory.eGenericWildcardSP()); + } + + @Override + protected void initChildProviders() { + children.add(spFactory.pathNameSP()); + children.add(spFactory.eGenericTypeArgumentSP()); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof PathNameContext) { + suggestions.add(ModelCompletionTokens._leftArrow); + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof EGenericTypeArgumentContext) { + suggestions.add(ModelCompletionTokens._comma); + suggestions.add(ModelCompletionTokens._rightArrow); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._leftArrow) + || lastToken.getText().equals(ModelCompletionTokens._comma)) { + suggestions.addAll(spFactory.eGenericTypeArgumentSP() + .getStartSuggestions()); + } else if (lastToken.getText().equals(ModelCompletionTokens._rightArrow)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EGenericTypeContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EGenericWildcardSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EGenericWildcardSuggestionProvider.java new file mode 100644 index 00000000..4578905e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EGenericWildcardSuggestionProvider.java @@ -0,0 +1,61 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericTypeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericWildcardContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EGenericWildcardSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.add(ModelCompletionTokens._question); + return startSuggestions; + } + + @Override + protected void initParentProviders() { + parents.add(spFactory.eGenericTypeArgumentSP()); + } + + @Override + protected void initChildProviders() { + children.add(spFactory.eGenericTypeSP()); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof EGenericTypeContext) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._question)) { + suggestions.add(ModelCompletionTokens._extends); + suggestions.add(ModelCompletionTokens._super); + } else if (lastToken.getText().equals(ModelCompletionTokens._extends) + || lastToken.getText().equals(ModelCompletionTokens._super)) { + suggestions.addAll(spFactory.eGenericTypeSP() + .getStartSuggestions()); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EGenericWildcardContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EModelElementRefSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EModelElementRefSuggestionProvider.java new file mode 100644 index 00000000..c24a6daa --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EModelElementRefSuggestionProvider.java @@ -0,0 +1,59 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EModelElementRefContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.PathNameContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EModelElementRefSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.add(ModelCompletionTokens._reference); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof PathNameContext) { + suggestions.add(ModelCompletionTokens._semicolon); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._reference)) { + suggestions.addAll( + spFactory.pathNameSP().getStartSuggestions()); + } else if (lastToken.getText().equals(ModelCompletionTokens._semicolon)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EModelElementRefContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eAnnotationSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.pathNameSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EModelElementSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EModelElementSuggestionProvider.java new file mode 100644 index 00000000..419b036c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EModelElementSuggestionProvider.java @@ -0,0 +1,45 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EModelElementContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EModelElementSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.addAll( + spFactory.eAnnotationSP().getStartSuggestions()); + startSuggestions.addAll( + spFactory.eNamedElementSP().getStartSuggestions()); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EModelElementContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eAnnotationSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.eAnnotationSP()); + addChild(spFactory.eNamedElementSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EMultiplicitySuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EMultiplicitySuggestionProvider.java new file mode 100644 index 00000000..8787809f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EMultiplicitySuggestionProvider.java @@ -0,0 +1,76 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EMultiplicityContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.LowerContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UpperContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EMultiplicitySuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.add(ModelCompletionTokens._leftBracket); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof LowerContext) { + suggestions.add(ModelCompletionTokens._ellipsis); + suggestions.addAll(ModelCompletionTokens._stringBounds); + suggestions.addAll(ModelCompletionTokens._isnullable); + suggestions.add(ModelCompletionTokens._rightBracket); + } else if (lastToken instanceof UpperContext) { + suggestions.addAll(ModelCompletionTokens._isnullable); + suggestions.add(ModelCompletionTokens._rightBracket); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._leftBracket)) { + // lower + } else if (lastToken.getText().equals(ModelCompletionTokens._ellipsis)) { + // upper + } else if (ModelCompletionTokens._stringBounds.contains(lastToken.getText())) { + suggestions.addAll(ModelCompletionTokens._isnullable); + suggestions.add(ModelCompletionTokens._rightBracket); + } else if (ModelCompletionTokens._isnullable.contains(lastToken.getText())) { + suggestions.add(ModelCompletionTokens._rightBracket); + } else if (lastToken.getText().equals(ModelCompletionTokens._rightBracket)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EMultiplicityContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eAttributeSP()); + addParent(spFactory.eReferenceSP()); + addParent(spFactory.eOperationSP()); + addParent(spFactory.eParameterSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.lowerSP()); + addChild(spFactory.upperSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/ENamedElementSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/ENamedElementSuggestionProvider.java new file mode 100644 index 00000000..8da7f563 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/ENamedElementSuggestionProvider.java @@ -0,0 +1,51 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ENamedElementContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class ENamedElementSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.addAll( + spFactory.eTypedElementSP().getStartSuggestions()); + startSuggestions.addAll( + spFactory.eClassifierSP().getStartSuggestions()); + startSuggestions.addAll( + spFactory.ePackageSP().getStartSuggestions()); + startSuggestions.addAll( + spFactory.eEnumliteralSP().getStartSuggestions()); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof ENamedElementContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eModelElementSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.eTypedElementSP()); + addChild(spFactory.eClassifierSP()); + addChild(spFactory.ePackageSP()); + addChild(spFactory.eEnumliteralSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EOperationSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EOperationSuggestionProvider.java new file mode 100644 index 00000000..a6fedc53 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EOperationSuggestionProvider.java @@ -0,0 +1,176 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.BodyContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EAnnotationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericElementTypeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericExceptionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EMultiplicityContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EOperationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EParameterContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.PostconditionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.PreconditionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.TemplateSignatureContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnrestrictedNameContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.VisibilityKindContext; +import eu.modelwriter.core.alloyinecore.structure.base.ITarget; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AIECompletionUtil; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EOperationSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.addAll( + spFactory.visibilityKindSP().getStartSuggestions()); + startSuggestions.add(ModelCompletionTokens._static); + startSuggestions.add(ModelCompletionTokens._operation); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof VisibilityKindContext) { + suggestions.add(ModelCompletionTokens._static); + suggestions.add(ModelCompletionTokens._operation); + } else if (lastToken instanceof TemplateSignatureContext) { + // operation name + } else if (lastToken instanceof UnrestrictedNameContext) { + suggestions.add(ModelCompletionTokens._leftParenthesis); + } else if (lastToken instanceof EParameterContext) { + suggestions.add(ModelCompletionTokens._comma); + suggestions.add(ModelCompletionTokens._rightParenthesis); + } else if (lastToken instanceof EGenericElementTypeContext) { + suggestions.addAll(spFactory.multiplicitySP() + .getStartSuggestions()); + suggestions.add(ModelCompletionTokens._throws); + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof EMultiplicityContext) { + suggestions.add(ModelCompletionTokens._throws); + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof EGenericExceptionContext) { + suggestions.add(ModelCompletionTokens._comma); + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof EAnnotationContext || lastToken instanceof PreconditionContext + || lastToken instanceof BodyContext || lastToken instanceof PostconditionContext) { + suggestions.addAll( + spFactory.eAnnotationSP().getStartSuggestions()); + suggestions.addAll(spFactory.preconditionSP() + .getStartSuggestions()); + suggestions.addAll( + spFactory.bodySP().getStartSuggestions()); + suggestions.addAll(spFactory.postconditionSP() + .getStartSuggestions()); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._static)) { + suggestions.add(ModelCompletionTokens._operation); + } else if (lastToken.getText().equals(ModelCompletionTokens._operation)) { + suggestions.addAll(spFactory.templateSignatureSP() + .getStartSuggestions()); + } else if (lastToken.getText().equals(ModelCompletionTokens._leftParenthesis)) { + suggestions.addAll( + spFactory.eParameterSP().getStartSuggestions()); + } else if (lastToken.getText().equals(ModelCompletionTokens._rightParenthesis)) { + suggestions.add(ModelCompletionTokens._colon); + } else if (lastToken.getText().equals(ModelCompletionTokens._colon)) { + // operation return type + final EOperationContext fullContext = + (EOperationContext) AIECompletionUtil.getFullContext(context); + if (fullContext != null) { + final List targets = fullContext.current.getTargets().stream() + .map(e -> (ITarget) e).collect(Collectors.toList()); + for (final ITarget target : targets) { + suggestions.add(target.getRelativeSegment()); + } + } + } else if (lastToken.getText().equals(ModelCompletionTokens._throws)) { + // exception type + final EOperationContext fullContext = + (EOperationContext) AIECompletionUtil.getFullContext(context); + if (fullContext != null) { + final List targets = fullContext.current.getTargets().stream() + .map(e -> (ITarget) e).collect(Collectors.toList()); + for (final ITarget target : targets) { + suggestions.add(target.getRelativeSegment()); + } + } + } else if (lastToken.getText().equals(ModelCompletionTokens._leftCurly)) { + suggestions.add(ModelCompletionTokens._ordered); + suggestions.add(ModelCompletionTokens._notOrdered); + suggestions.add(ModelCompletionTokens._unique); + suggestions.add(ModelCompletionTokens._notUnique); + suggestions.addAll( + spFactory.eAnnotationSP().getStartSuggestions()); + suggestions.addAll(spFactory.preconditionSP() + .getStartSuggestions()); + suggestions.addAll( + spFactory.bodySP().getStartSuggestions()); + suggestions.addAll(spFactory.postconditionSP() + .getStartSuggestions()); + } else if (lastToken.getText().equals(ModelCompletionTokens._comma)) { + suggestions.addAll( + spFactory.eParameterSP().getStartSuggestions()); + // exception types + suggestions.add(ModelCompletionTokens._ordered); + suggestions.add(ModelCompletionTokens._notOrdered); + suggestions.add(ModelCompletionTokens._unique); + suggestions.add(ModelCompletionTokens._notUnique); + } else if (lastToken.getText().equals(ModelCompletionTokens._ordered) + || lastToken.getText().equals(ModelCompletionTokens._notOrdered) + || lastToken.getText().equals(ModelCompletionTokens._unique) + || lastToken.getText().equals(ModelCompletionTokens._notUnique)) { + suggestions.add(ModelCompletionTokens._comma); + suggestions.add(ModelCompletionTokens._rightCurly); + } else if (lastToken.getText().equals(ModelCompletionTokens._rightCurly) + || lastToken.getText().equals(ModelCompletionTokens._semicolon)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EOperationContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eTypedElementSP()); + addParent(spFactory.eClassSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.visibilityKindSP()); + addChild(spFactory.templateSignatureSP()); + addChild(spFactory.unrestrictedNameSP()); + addChild(spFactory.eParameterSP()); + addChild(spFactory.eGenericElementTypeSP()); + addChild(spFactory.multiplicitySP()); + addChild(spFactory.eGenericExceptionSP()); + addChild(spFactory.eAnnotationSP()); + addChild(spFactory.preconditionSP()); + addChild(spFactory.bodySP()); + addChild(spFactory.postconditionSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EPackageSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EPackageSuggestionProvider.java new file mode 100644 index 00000000..f905154c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EPackageSuggestionProvider.java @@ -0,0 +1,102 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EAnnotationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EClassifierContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EPackageContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.IdentifierContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.InvariantContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnrestrictedNameContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.VisibilityKindContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EPackageSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.addAll( + spFactory.visibilityKindSP().getStartSuggestions()); + startSuggestions.add(ModelCompletionTokens._package); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof VisibilityKindContext) { + suggestions.add(ModelCompletionTokens._package); + } else if (lastToken instanceof UnrestrictedNameContext) { + suggestions.add(ModelCompletionTokens._colon); + } else if (lastToken instanceof IdentifierContext) { + suggestions.add(ModelCompletionTokens._equals); + } else if (lastToken instanceof EAnnotationContext || lastToken instanceof EPackageContext + || lastToken instanceof EClassifierContext || lastToken instanceof InvariantContext) { + suggestions.addAll( + spFactory.eAnnotationSP().getStartSuggestions()); + suggestions.addAll( + spFactory.ePackageSP().getStartSuggestions()); + suggestions.addAll( + spFactory.eClassifierSP().getStartSuggestions()); + suggestions.addAll( + spFactory.invariantSP().getStartSuggestions()); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._equals)) { + suggestions.add(ModelCompletionTokens._singleQuote); + } else if (((TerminalNode) lastToken).getSymbol() + .getType() == AlloyInEcoreLexer.SINGLE_QUOTED_STRING) { + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._leftCurly)) { + suggestions.addAll( + spFactory.eAnnotationSP().getStartSuggestions()); + suggestions.addAll( + spFactory.ePackageSP().getStartSuggestions()); + suggestions.addAll( + spFactory.eClassifierSP().getStartSuggestions()); + suggestions.addAll( + spFactory.invariantSP().getStartSuggestions()); + } else if (lastToken.getText().equals(ModelCompletionTokens._rightCurly) + || lastToken.getText().equals(ModelCompletionTokens._semicolon)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EPackageContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eNamedElementSP()); + addParent(spFactory.ePackageSP()); + addParent(spFactory.modelSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.visibilityKindSP()); + addChild(spFactory.unrestrictedNameSP()); + addChild(spFactory.indentifierSP()); + addChild(spFactory.eAnnotationSP()); + addChild(spFactory.ePackageSP()); + addChild(spFactory.eClassifierSP()); + addChild(spFactory.invariantSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EParameterSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EParameterSuggestionProvider.java new file mode 100644 index 00000000..b7366ff7 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EParameterSuggestionProvider.java @@ -0,0 +1,101 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericElementTypeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EMultiplicityContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EOperationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EParameterContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnrestrictedNameContext; +import eu.modelwriter.core.alloyinecore.structure.base.ITarget; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AIECompletionUtil; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EParameterSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + return new HashSet<>(); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof UnrestrictedNameContext) { + suggestions.add(ModelCompletionTokens._colon); + } else if (lastToken instanceof EGenericElementTypeContext) { + suggestions.addAll(spFactory.multiplicitySP().getStartSuggestions()); + suggestions.add(ModelCompletionTokens._leftCurly); + } else if (lastToken instanceof EMultiplicityContext) { + suggestions.add(ModelCompletionTokens._leftCurly); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._static)) { + suggestions.add(ModelCompletionTokens._operation); + } else if (lastToken.getText().equals(ModelCompletionTokens._colon)) { + // parameter type + final EOperationContext fullContext = + (EOperationContext) AIECompletionUtil.getFullContext(context.getParent()); + if (fullContext != null) { + final List targets = fullContext.current.getTargets().stream() + .map(e -> (ITarget) e).collect(Collectors.toList()); + for (final ITarget target : targets) { + suggestions.add(target.getRelativeSegment()); + } + } + } else if (lastToken.getText().equals(ModelCompletionTokens._leftCurly)) { + suggestions.add(ModelCompletionTokens._ordered); + suggestions.add(ModelCompletionTokens._notOrdered); + suggestions.add(ModelCompletionTokens._unique); + suggestions.add(ModelCompletionTokens._notUnique); + suggestions.addAll(spFactory.eAnnotationSP().getStartSuggestions()); + } else if (lastToken.getText().equals(ModelCompletionTokens._comma)) { + suggestions.add(ModelCompletionTokens._ordered); + suggestions.add(ModelCompletionTokens._notOrdered); + suggestions.add(ModelCompletionTokens._unique); + suggestions.add(ModelCompletionTokens._notUnique); + } else if (lastToken.getText().equals(ModelCompletionTokens._ordered) + || lastToken.getText().equals(ModelCompletionTokens._notOrdered) + || lastToken.getText().equals(ModelCompletionTokens._unique) + || lastToken.getText().equals(ModelCompletionTokens._notUnique)) { + suggestions.add(ModelCompletionTokens._comma); + suggestions.add(ModelCompletionTokens._rightCurly); + } else if (lastToken.getText().equals(ModelCompletionTokens._rightCurly) + || lastToken.getText().equals(ModelCompletionTokens._semicolon)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EParameterContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eTypedElementSP()); + addParent(spFactory.eOperationSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.unrestrictedNameSP()); + addChild(spFactory.eGenericElementTypeSP()); + addChild(spFactory.multiplicitySP()); + addChild(spFactory.eAnnotationSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EPrimitiveTypeSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EPrimitiveTypeSuggestionProvider.java new file mode 100644 index 00000000..51c1b6a9 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EPrimitiveTypeSuggestionProvider.java @@ -0,0 +1,43 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EPrimitiveTypeContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EPrimitiveTypeSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.addAll(ModelCompletionTokens._primitives); + return startSuggestions; + } + + @Override + protected void initParentProviders() { + parents.add(spFactory.eGenericElementTypeSP()); + } + + @Override + protected void initChildProviders() { + // TODO Auto-generated method stub + + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EPrimitiveTypeContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EReferenceSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EReferenceSuggestionProvider.java new file mode 100644 index 00000000..5f21b0e9 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EReferenceSuggestionProvider.java @@ -0,0 +1,202 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.DerivationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EAnnotationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericElementTypeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EMultiplicityContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EReferenceContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.InitialContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnrestrictedNameContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.VisibilityKindContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.base.ITarget; +import eu.modelwriter.core.alloyinecore.structure.model.GenericElementType; +import eu.modelwriter.core.alloyinecore.structure.model.Reference; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AIECompletionUtil; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EReferenceSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.addAll(spFactory.visibilityKindSP().getStartSuggestions()); + startSuggestions.add(ModelCompletionTokens._static); + startSuggestions.add(ModelCompletionTokens._model); + startSuggestions.add(ModelCompletionTokens._ghost); + startSuggestions.add(ModelCompletionTokens._transient); + startSuggestions.add(ModelCompletionTokens._volatile); + startSuggestions.add(ModelCompletionTokens._readonly); + startSuggestions.add(ModelCompletionTokens._property); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof VisibilityKindContext) { + suggestions.add(ModelCompletionTokens._static); + suggestions.add(ModelCompletionTokens._model); + suggestions.add(ModelCompletionTokens._ghost); + suggestions.add(ModelCompletionTokens._transient); + suggestions.add(ModelCompletionTokens._volatile); + suggestions.add(ModelCompletionTokens._readonly); + suggestions.add(ModelCompletionTokens._property); + } else if (lastToken instanceof UnrestrictedNameContext) { + suggestions.add(ModelCompletionTokens._sharp); + suggestions.add(ModelCompletionTokens._colon); + } else if (lastToken instanceof EGenericElementTypeContext) { + suggestions.addAll(spFactory.multiplicitySP().getStartSuggestions()); + suggestions.add(ModelCompletionTokens._equals); + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof EMultiplicityContext) { + suggestions.add(ModelCompletionTokens._equals); + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof EAnnotationContext) { + suggestions.addAll(spFactory.eAnnotationSP().getStartSuggestions()); + suggestions.addAll(spFactory.derivationSP().getStartSuggestions()); + suggestions.addAll(spFactory.initialSP().getStartSuggestions()); + } else if (lastToken instanceof DerivationContext || lastToken instanceof InitialContext) { + suggestions.addAll(spFactory.eAnnotationSP().getStartSuggestions()); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._static)) { + suggestions.add(ModelCompletionTokens._model); + suggestions.add(ModelCompletionTokens._ghost); + suggestions.add(ModelCompletionTokens._transient); + suggestions.add(ModelCompletionTokens._volatile); + suggestions.add(ModelCompletionTokens._readonly); + suggestions.add(ModelCompletionTokens._property); + } else if (lastToken.getText().equals(ModelCompletionTokens._model) + || lastToken.getText().equals(ModelCompletionTokens._ghost)) { + suggestions.add(ModelCompletionTokens._transient); + suggestions.add(ModelCompletionTokens._volatile); + suggestions.add(ModelCompletionTokens._readonly); + suggestions.add(ModelCompletionTokens._property); + } else if (lastToken.getText().equals(ModelCompletionTokens._transient)) { + suggestions.add(ModelCompletionTokens._volatile); + suggestions.add(ModelCompletionTokens._readonly); + suggestions.add(ModelCompletionTokens._property); + } else if (lastToken.getText().equals(ModelCompletionTokens._volatile)) { + suggestions.add(ModelCompletionTokens._readonly); + suggestions.add(ModelCompletionTokens._property); + } else if (lastToken.getText().equals(ModelCompletionTokens._readonly)) { + suggestions.add(ModelCompletionTokens._property); + } else if (lastToken.getText().equals(ModelCompletionTokens._property)) { + // property name + } else if (lastToken.getText().equals(ModelCompletionTokens._sharp)) { + // TODO opposite type + final EReferenceContext fullContext = + (EReferenceContext) AIECompletionUtil.getFullContext(context); + if (fullContext != null) { + if (fullContext.eReferenceType != null) { + final GenericElementType eReferenceType = fullContext.eReferenceType.current; + for (@SuppressWarnings("rawtypes") + final Element child : eReferenceType.getOwnedElements()) { + if (child instanceof Reference) { + suggestions.add(child.getUniqueName()); + } + } + } + } + } else if (lastToken.getText().equals(ModelCompletionTokens._colon)) { + // reference type + final EReferenceContext fullContext = + (EReferenceContext) AIECompletionUtil.getFullContext(context); + if (fullContext != null) { + final List targets = fullContext.current.getTargets().stream() + .map(e -> (ITarget) e).collect(Collectors.toList()); + for (final ITarget target : targets) { + suggestions.add(target.getRelativeSegment()); + } + } + } else if (lastToken.getText().equals(ModelCompletionTokens._equals)) { + suggestions.add(ModelCompletionTokens._singleQuote); + } else if (((TerminalNode) lastToken).getSymbol() + .getType() == AlloyInEcoreLexer.SINGLE_QUOTED_STRING) { + suggestions.add(ModelCompletionTokens._leftCurly); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._leftCurly)) { + suggestions.add(ModelCompletionTokens._key); + suggestions.add(ModelCompletionTokens._composes); + suggestions.add(ModelCompletionTokens._derived); + suggestions.add(ModelCompletionTokens._ordered); + suggestions.add(ModelCompletionTokens._notOrdered); + suggestions.add(ModelCompletionTokens._unique); + suggestions.add(ModelCompletionTokens._notUnique); + suggestions.add(ModelCompletionTokens._resolve); + suggestions.add(ModelCompletionTokens._notResolve); + suggestions.add(ModelCompletionTokens._unsettable); + suggestions.add(ModelCompletionTokens._notUnsettable); + suggestions.addAll(spFactory.eAnnotationSP().getStartSuggestions()); + suggestions.addAll(spFactory.derivationSP().getStartSuggestions()); + suggestions.addAll(spFactory.initialSP().getStartSuggestions()); + } else if (lastToken.getText().equals(ModelCompletionTokens._comma)) { + suggestions.add(ModelCompletionTokens._composes); + suggestions.add(ModelCompletionTokens._derived); + suggestions.add(ModelCompletionTokens._ordered); + suggestions.add(ModelCompletionTokens._notOrdered); + suggestions.add(ModelCompletionTokens._unique); + suggestions.add(ModelCompletionTokens._notUnique); + suggestions.add(ModelCompletionTokens._resolve); + suggestions.add(ModelCompletionTokens._notResolve); + suggestions.add(ModelCompletionTokens._unsettable); + suggestions.add(ModelCompletionTokens._notUnsettable); + } else if (lastToken.getText().equals(ModelCompletionTokens._composes) + || lastToken.getText().equals(ModelCompletionTokens._derived) + || lastToken.getText().equals(ModelCompletionTokens._ordered) + || lastToken.getText().equals(ModelCompletionTokens._notOrdered) + || lastToken.getText().equals(ModelCompletionTokens._unique) + || lastToken.getText().equals(ModelCompletionTokens._notUnique) + || lastToken.getText().equals(ModelCompletionTokens._resolve) + || lastToken.getText().equals(ModelCompletionTokens._notResolve) + || lastToken.getText().equals(ModelCompletionTokens._unsettable) + || lastToken.getText().equals(ModelCompletionTokens._notUnsettable)) { + suggestions.add(ModelCompletionTokens._comma); + suggestions.add(ModelCompletionTokens._rightCurly); + } else if (lastToken.getText().equals(ModelCompletionTokens._rightCurly) + || lastToken.getText().equals(ModelCompletionTokens._semicolon)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EReferenceContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eStructuralFeatureSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.visibilityKindSP()); + addChild(spFactory.unrestrictedNameSP()); + addChild(spFactory.eGenericElementTypeSP()); + addChild(spFactory.multiplicitySP()); + addChild(spFactory.eAnnotationSP()); + addChild(spFactory.derivationSP()); + addChild(spFactory.initialSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EStructuralFeatureSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EStructuralFeatureSuggestionProvider.java new file mode 100644 index 00000000..b74053f4 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/EStructuralFeatureSuggestionProvider.java @@ -0,0 +1,46 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EStructuralFeatureContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class EStructuralFeatureSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.addAll( + spFactory.eAttributeSP().getStartSuggestions()); + startSuggestions.addAll( + spFactory.eReferenceSP().getStartSuggestions()); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof EStructuralFeatureContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eTypedElementSP()); + addParent(spFactory.eClassSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.eAttributeSP()); + addChild(spFactory.eReferenceSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/ETypeParameterSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/ETypeParameterSuggestionProvider.java new file mode 100644 index 00000000..4fc74cae --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/ETypeParameterSuggestionProvider.java @@ -0,0 +1,63 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericTypeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ETypeParameterContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnrestrictedNameContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class ETypeParameterSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + return new HashSet<>(); + } + + @Override + protected void initParentProviders() { + parents.add(spFactory.templateSignatureSP()); + } + + @Override + protected void initChildProviders() { + children.add(spFactory.unrestrictedNameSP()); + children.add(spFactory.eGenericTypeSP()); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof UnrestrictedNameContext) { + suggestions.add(ModelCompletionTokens._extends); + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof EGenericTypeContext) { + suggestions.add(ModelCompletionTokens._ampersand); + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._extends) + || lastToken.getText().equals(ModelCompletionTokens._ampersand)) { + suggestions.addAll(spFactory.eGenericTypeSP() + .getStartSuggestions()); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof ETypeParameterContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/ETypedElementSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/ETypedElementSuggestionProvider.java new file mode 100644 index 00000000..118b8c5c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/ETypedElementSuggestionProvider.java @@ -0,0 +1,48 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ETypedElementContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class ETypedElementSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.addAll( + spFactory.eOperationSP().getStartSuggestions()); + startSuggestions.addAll( + spFactory.eParameterSP().getStartSuggestions()); + startSuggestions.addAll(spFactory.eStructuralFeatureSP() + .getStartSuggestions()); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof ETypedElementContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eNamedElementSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.eOperationSP()); + addChild(spFactory.eParameterSP()); + addChild(spFactory.eStructuralFeatureSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/FormulaSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/FormulaSuggestionProvider.java new file mode 100644 index 00000000..c080007a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/FormulaSuggestionProvider.java @@ -0,0 +1,42 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.FormulaContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class FormulaSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + return new HashSet<>(); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + // TODO Auto-generated method stub + + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof FormulaContext; + } + + @Override + protected void initParentProviders() { + // TODO Auto-generated method stub + + } + + @Override + protected void initChildProviders() { + // TODO Auto-generated method stub + + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/IdentifierSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/IdentifierSuggestionProvider.java new file mode 100644 index 00000000..912590c6 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/IdentifierSuggestionProvider.java @@ -0,0 +1,49 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.IdentifierContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class IdentifierSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + return new HashSet<>(); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof IdentifierContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.modelSP()); + addParent(spFactory.packageImportSP()); + addParent(spFactory.ePackageSP()); + addParent(spFactory.bodySP()); + addParent(spFactory.invariantSP()); + addParent(spFactory.preconditionSP()); + addParent(spFactory.postconditionSP()); + addParent(spFactory.initialSP()); + addParent(spFactory.derivationSP()); + addParent(spFactory.unrestrictedNameSP()); + } + + @Override + protected void initChildProviders() { + // TODO Auto-generated method stub + + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/InitialSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/InitialSuggestionProvider.java new file mode 100644 index 00000000..9703087a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/InitialSuggestionProvider.java @@ -0,0 +1,69 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ExpressionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.IdentifierContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.InitialContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class InitialSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.add(ModelCompletionTokens._initial); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof IdentifierContext) { + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof ExpressionContext) { + suggestions.add(ModelCompletionTokens._semicolon); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._initial)) { + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._colon)) { + suggestions.addAll( + spFactory.expressionSP().getStartSuggestions()); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._semicolon)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof InitialContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eAttributeSP()); + addParent(spFactory.eReferenceSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.indentifierSP()); + addChild(spFactory.expressionSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/InvariantSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/InvariantSuggestionProvider.java new file mode 100644 index 00000000..c66db61a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/InvariantSuggestionProvider.java @@ -0,0 +1,84 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.FormulaContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.IdentifierContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.InvariantContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class InvariantSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.add(ModelCompletionTokens._callable); + startSuggestions.add(ModelCompletionTokens._invariant); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof IdentifierContext) { + suggestions.add(ModelCompletionTokens._leftParenthesis); + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof FormulaContext) { + suggestions.add(ModelCompletionTokens._semicolon); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._callable)) { + suggestions.add(ModelCompletionTokens._invariant); + } else if (lastToken.getText().equals(ModelCompletionTokens._invariant)) { + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._leftParenthesis)) { + suggestions.add(ModelCompletionTokens._doubleQuote); + } else if (((TerminalNode) lastToken).getSymbol() + .getType() == AlloyInEcoreLexer.DOUBLE_QUOTED_STRING) { + suggestions.add(ModelCompletionTokens._rightParenthesis); + } else if (lastToken.getText().equals(ModelCompletionTokens._rightParenthesis)) { + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._colon)) { + suggestions.addAll( + spFactory.formulaSP().getStartSuggestions()); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._semicolon)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof InvariantContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.ePackageSP()); + addParent(spFactory.eClassSP()); + addParent(spFactory.eDatatypeSP()); + addParent(spFactory.eEnumSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.indentifierSP()); + addChild(spFactory.formulaSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/LowerSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/LowerSuggestionProvider.java new file mode 100644 index 00000000..38368e5c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/LowerSuggestionProvider.java @@ -0,0 +1,40 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.LowerContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class LowerSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + return new HashSet<>(); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof LowerContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.multiplicitySP()); + } + + @Override + protected void initChildProviders() { + // TODO Auto-generated method stub + + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/ModelSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/ModelSuggestionProvider.java new file mode 100644 index 00000000..e5eab9da --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/ModelSuggestionProvider.java @@ -0,0 +1,83 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.IdentifierContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ModelContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.OptionsContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.PackageImportContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class ModelSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions + .addAll(spFactory.optionsSP().getStartSuggestions()); + startSuggestions.add(ModelCompletionTokens._model); + startSuggestions.addAll( + spFactory.packageImportSP().getStartSuggestions()); + startSuggestions.addAll( + spFactory.ePackageSP().getStartSuggestions()); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (context == null) { + suggestions.addAll(getStartSuggestions()); + } else if (lastToken instanceof OptionsContext) { + suggestions.add(ModelCompletionTokens._model); + suggestions.addAll(spFactory.packageImportSP() + .getStartSuggestions()); + suggestions.addAll( + spFactory.ePackageSP().getStartSuggestions()); + } else if (lastToken instanceof IdentifierContext) { + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof PackageImportContext) { + suggestions.addAll(spFactory.packageImportSP() + .getStartSuggestions()); + suggestions.addAll( + spFactory.ePackageSP().getStartSuggestions()); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._semicolon)) { + suggestions.addAll(spFactory.packageImportSP() + .getStartSuggestions()); + suggestions.addAll( + spFactory.ePackageSP().getStartSuggestions()); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof ModelContext || context == null; + } + + @Override + protected void initParentProviders() { + // TODO Auto-generated method stub + + } + + @Override + protected void initChildProviders() { + addChild(spFactory.optionsSP()); + addChild(spFactory.indentifierSP()); + addChild(spFactory.packageImportSP()); + addChild(spFactory.ePackageSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/OptionSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/OptionSuggestionProvider.java new file mode 100644 index 00000000..f44a2751 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/OptionSuggestionProvider.java @@ -0,0 +1,57 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.OptionContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class OptionSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.addAll(ModelCompletionTokens._option); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + + } else if (lastToken instanceof TerminalNode) { + if (ModelCompletionTokens._option.contains(lastToken.getText())) { + suggestions.add(ModelCompletionTokens._colon); + } else if (((TerminalNode) lastToken).getSymbol().getType() == AlloyInEcoreLexer.INT) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof OptionContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.optionsSP()); + } + + @Override + protected void initChildProviders() { + // TODO Auto-generated method stub + + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/OptionsSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/OptionsSuggestionProvider.java new file mode 100644 index 00000000..b0d56c4a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/OptionsSuggestionProvider.java @@ -0,0 +1,63 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.OptionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.OptionsContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class OptionsSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.add(ModelCompletionTokens._options); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof OptionContext) { + suggestions.add(ModelCompletionTokens._comma); + suggestions.add(ModelCompletionTokens._rightCurly); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._options)) { + suggestions.add(ModelCompletionTokens._leftCurly); + } else if (lastToken.getText().equals(ModelCompletionTokens._leftCurly) + || lastToken.getText().equals(ModelCompletionTokens._comma)) { + suggestions.addAll( + spFactory.optionSP().getStartSuggestions()); + } else if (lastToken.getText().equals(ModelCompletionTokens._rightCurly)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof OptionsContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.modelSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.optionSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/PackageImportSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/PackageImportSuggestionProvider.java new file mode 100644 index 00000000..66add5c1 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/PackageImportSuggestionProvider.java @@ -0,0 +1,64 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.IdentifierContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.PackageImportContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider;; + +public class PackageImportSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.add(ModelCompletionTokens._import); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (context instanceof IdentifierContext) { + suggestions.add(ModelCompletionTokens._colon); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._import)) { + suggestions.add(ModelCompletionTokens._singleQuote); + } else if (lastToken.getText().equals(ModelCompletionTokens._colon)) { + suggestions.add(ModelCompletionTokens._singleQuote); + } else if (((TerminalNode) lastToken).getSymbol() + .getType() == AlloyInEcoreLexer.SINGLE_QUOTED_STRING) { + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._semicolon)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof PackageImportContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.modelSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.indentifierSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/PathNameSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/PathNameSuggestionProvider.java new file mode 100644 index 00000000..af9bd8d3 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/PathNameSuggestionProvider.java @@ -0,0 +1,68 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.PathNameContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.SegmentContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnrestrictedNameContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class PathNameSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + return new HashSet<>(); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof UnrestrictedNameContext) { + // suggestions.add(ExpressionCompletionTokens._dot); + // suggestions.addAll( + // spFactory.segmentSP().getStartSuggestions()); + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof SegmentContext) { + // suggestions.addAll( + // spFactory.segmentSP().getStartSuggestions()); + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + } else if (lastToken instanceof TerminalNode) { + if (((TerminalNode) lastToken).getSymbol().getType() == AlloyInEcoreLexer.INT) { + // suggestions.addAll( + // spFactory.segmentSP().getStartSuggestions()); + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof PathNameContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eModelElementRefSP()); + addParent(spFactory.eGenericTypeSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.unrestrictedNameSP()); + addChild(spFactory.segmentSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/PostconditionSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/PostconditionSuggestionProvider.java new file mode 100644 index 00000000..b581d148 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/PostconditionSuggestionProvider.java @@ -0,0 +1,80 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.FormulaContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.IdentifierContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.PostconditionContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class PostconditionSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.add(ModelCompletionTokens._postcondition); + startSuggestions.add(ModelCompletionTokens._ensures); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof IdentifierContext) { + suggestions.add(ModelCompletionTokens._leftParenthesis); + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof FormulaContext) { + suggestions.add(ModelCompletionTokens._semicolon); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._postcondition) + || lastToken.getText().equals(ModelCompletionTokens._ensures)) { + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._leftParenthesis)) { + suggestions.add(ModelCompletionTokens._doubleQuote); + } else if (((TerminalNode) lastToken).getSymbol() + .getType() == AlloyInEcoreLexer.DOUBLE_QUOTED_STRING) { + suggestions.add(ModelCompletionTokens._rightParenthesis); + } else if (lastToken.getText().equals(ModelCompletionTokens._rightParenthesis)) { + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._colon)) { + suggestions.addAll( + spFactory.formulaSP().getStartSuggestions()); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._semicolon)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof PostconditionContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eOperationSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.indentifierSP()); + addChild(spFactory.formulaSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/PreconditionSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/PreconditionSuggestionProvider.java new file mode 100644 index 00000000..544c7460 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/PreconditionSuggestionProvider.java @@ -0,0 +1,80 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.FormulaContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.IdentifierContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.PreconditionContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class PreconditionSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.add(ModelCompletionTokens._precondition); + startSuggestions.add(ModelCompletionTokens._requires); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof IdentifierContext) { + suggestions.add(ModelCompletionTokens._leftParenthesis); + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken instanceof FormulaContext) { + suggestions.add(ModelCompletionTokens._semicolon); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._precondition) + || lastToken.getText().equals(ModelCompletionTokens._requires)) { + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._leftParenthesis)) { + suggestions.add(ModelCompletionTokens._doubleQuote); + } else if (((TerminalNode) lastToken).getSymbol() + .getType() == AlloyInEcoreLexer.DOUBLE_QUOTED_STRING) { + suggestions.add(ModelCompletionTokens._rightParenthesis); + } else if (lastToken.getText().equals(ModelCompletionTokens._rightParenthesis)) { + suggestions.add(ModelCompletionTokens._colon); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._colon)) { + suggestions.addAll( + spFactory.formulaSP().getStartSuggestions()); + suggestions.add(ModelCompletionTokens._semicolon); + } else if (lastToken.getText().equals(ModelCompletionTokens._semicolon)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof PreconditionContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eOperationSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.indentifierSP()); + addChild(spFactory.formulaSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/SegmentSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/SegmentSuggestionProvider.java new file mode 100644 index 00000000..5361fcdb --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/SegmentSuggestionProvider.java @@ -0,0 +1,66 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.SegmentContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnrestrictedNameContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class SegmentSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.add(ModelCompletionTokens._doubleColon); + return startSuggestions; + } + + @Override + protected void initParentProviders() { + parents.add(spFactory.pathNameSP()); + } + + @Override + protected void initChildProviders() { + children.add(spFactory.unrestrictedNameSP()); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof UnrestrictedNameContext) { + suggestions.add(ModelCompletionTokens._dot); + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._doubleColon)) { + suggestions.add(ModelCompletionTokens._at); + suggestions.addAll(spFactory.unrestrictedNameSP() + .getStartSuggestions()); + } else if (lastToken.getText().equals(ModelCompletionTokens._at)) { + suggestions.addAll(spFactory.unrestrictedNameSP() + .getStartSuggestions()); + } else if (((TerminalNode) lastToken).getSymbol().getType() == AlloyInEcoreLexer.INT) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof SegmentContext; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/TemplateSignatureSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/TemplateSignatureSuggestionProvider.java new file mode 100644 index 00000000..c06c6fb4 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/TemplateSignatureSuggestionProvider.java @@ -0,0 +1,64 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ETypeParameterContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.TemplateSignatureContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class TemplateSignatureSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.add(ModelCompletionTokens._leftArrow); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + if (lastToken instanceof ParserRuleContext) { + if (lastToken instanceof ETypeParameterContext) { + suggestions.add(ModelCompletionTokens._comma); + suggestions.add(ModelCompletionTokens._rightArrow); + } + } else if (lastToken instanceof TerminalNode) { + if (lastToken.getText().equals(ModelCompletionTokens._leftArrow) + || lastToken.getText().equals(ModelCompletionTokens._comma)) { + suggestions.addAll(spFactory.eTypeParameterSP() + .getStartSuggestions()); + } else if (lastToken.getText().equals(ModelCompletionTokens._rightArrow)) { + // end of context. + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } else if (lastToken instanceof ErrorNode) { + // suggestions.addAll(getChildProviderSuggestions(context, lastToken)); + } + } + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof TemplateSignatureContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.eClassSP()); + addParent(spFactory.eOperationSP()); + addParent(spFactory.eDatatypeSP()); + addParent(spFactory.eEnumSP()); + } + + @Override + protected void initChildProviders() { + addChild(spFactory.eTypeParameterSP()); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/UnrestrictedNameSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/UnrestrictedNameSuggestionProvider.java new file mode 100644 index 00000000..9516666b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/UnrestrictedNameSuggestionProvider.java @@ -0,0 +1,51 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnrestrictedNameContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class UnrestrictedNameSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + return new HashSet<>(); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof UnrestrictedNameContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.ePackageSP()); + addParent(spFactory.eClassSP()); + addParent(spFactory.eAttributeSP()); + addParent(spFactory.eReferenceSP()); + addParent(spFactory.eOperationSP()); + addParent(spFactory.eParameterSP()); + addParent(spFactory.eDatatypeSP()); + addParent(spFactory.eEnumSP()); + addParent(spFactory.eEnumliteralSP()); + addParent(spFactory.eTypeParameterSP()); + addParent(spFactory.pathNameSP()); + addParent(spFactory.segmentSP()); + } + + @Override + protected void initChildProviders() { + // TODO Auto-generated method stub + + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/UpperSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/UpperSuggestionProvider.java new file mode 100644 index 00000000..70940f8c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/UpperSuggestionProvider.java @@ -0,0 +1,40 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UpperContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class UpperSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + return new HashSet<>(); + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof UpperContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.multiplicitySP()); + } + + @Override + protected void initChildProviders() { + // TODO Auto-generated method stub + + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/VisibilityKindSuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/VisibilityKindSuggestionProvider.java new file mode 100644 index 00000000..597070e7 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/model/provider/VisibilityKindSuggestionProvider.java @@ -0,0 +1,49 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.model.provider; + +import java.util.HashSet; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.VisibilityKindContext; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.ModelCompletionTokens; +import eu.modelwriter.core.alloyinecore.ui.editor.completion.util.AbstractAIESuggestionProvider; + +public class VisibilityKindSuggestionProvider extends AbstractAIESuggestionProvider { + + @Override + public Set getStartSuggestions() { + final Set startSuggestions = new HashSet<>(); + startSuggestions.addAll(ModelCompletionTokens._visibility); + return startSuggestions; + } + + @Override + protected void computeSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + suggestions.addAll(getParentProviderSuggestions(context, lastToken)); + } + + @Override + protected boolean isCompatibleWithContext(final ParserRuleContext context) { + return context instanceof VisibilityKindContext; + } + + @Override + protected void initParentProviders() { + addParent(spFactory.ePackageSP()); + addParent(spFactory.eClassSP()); + addParent(spFactory.eAttributeSP()); + addParent(spFactory.eReferenceSP()); + addParent(spFactory.eOperationSP()); + addParent(spFactory.eDatatypeSP()); + addParent(spFactory.eEnumSP()); + } + + @Override + protected void initChildProviders() { + // TODO Auto-generated method stub + + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/util/AIECompletionUtil.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/util/AIECompletionUtil.java new file mode 100644 index 00000000..82e4c9e9 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/util/AIECompletionUtil.java @@ -0,0 +1,149 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.util; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.Recognizer; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ModelContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; + +public class AIECompletionUtil { + private static IDocument document; + private final int offset; + + private AlloyInEcoreLexer cuttedDocLexer; + private CommonTokenStream cuttedDocTokens; + private AlloyInEcoreParser cuttedDocParser; + + private int minDistance = Integer.MAX_VALUE; + private ParseTree closerNode = null; + + public AIECompletionUtil(final IDocument document, final int offset) { + AIECompletionUtil.document = document; + this.offset = offset; + } + + public List getProposals() throws BadLocationException { + cuttedDocLexer = + new AlloyInEcoreLexer(new ANTLRInputStream(AIECompletionUtil.document.get(0, offset))); + cuttedDocTokens = new CommonTokenStream(cuttedDocLexer); + cuttedDocParser = new AlloyInEcoreParser(cuttedDocTokens); + + final ModelContext cuttedModelCtx = cuttedDocParser.model(); + + // TODO find context via AST. Only use AST. You will get true context and true location and then + // you will be able to put suggestions according to this location. + // If code below is not true, find true version in facebook message or mail box. + + findCloserNode(cuttedModelCtx); + + if (closerNode == null) { + closerNode = cuttedModelCtx; + } + + final ParserRuleContext parentOfCloserNode = (ParserRuleContext) closerNode.getParent(); + if (closerNode instanceof TerminalNode) { + } else if (closerNode instanceof ParserRuleContext) { + } + + final SuggestionDetector suggestionDetector = + new SuggestionDetector(AIECompletionUtil.document, offset, parentOfCloserNode, closerNode); + final Set detectedSuggestions = suggestionDetector.detect(); + final List allProposals = new ArrayList<>(); + allProposals.addAll(detectedSuggestions); + return allProposals; + } + + private void findCloserNode(final ParseTree root) { + if (root instanceof ParserRuleContext) { + if (((ParserRuleContext) root).getStart().getStartIndex() <= offset) { + final int distance = offset - ((ParserRuleContext) root).getStart().getStartIndex(); + if (distance <= minDistance + && ((ParserRuleContext) root).getStart().getType() != Recognizer.EOF) { + minDistance = distance; + closerNode = root; + } + if (root.getChildCount() > 0) { + final List ownedElements = ((ParserRuleContext) root).children; + for (int i = 0; i < ownedElements.size(); i++) { + final ParseTree element = ownedElements.get(i); + findCloserNode(element); + } + } + } + } else if (root instanceof TerminalNode) { + if (((TerminalNode) root).getSymbol().getStartIndex() <= offset) { + final int distance = offset - ((TerminalNode) root).getSymbol().getStartIndex(); + if (distance <= minDistance) { + if (!(root instanceof ErrorNode + && ((TerminalNode) root).getSymbol().getStopIndex() + 1 == offset)) { + minDistance = distance; + closerNode = root; + } + } + } + } + } + + public static ParserRuleContext getFullContext(final ParserRuleContext cuttedCtx) { + final AlloyInEcoreLexer lexer = + new AlloyInEcoreLexer(new ANTLRInputStream(AIECompletionUtil.document.get())); + final CommonTokenStream tokens = new CommonTokenStream(lexer); + final AlloyInEcoreParser parser = new AlloyInEcoreParser(tokens); + + final ModelContext modelContext = parser.model(); + + return AIECompletionUtil.findFullContext(modelContext, cuttedCtx); + } + + private static ParserRuleContext findFullContext(final ParserRuleContext fullCtx, + final ParserRuleContext cuttedCtx) { + if (fullCtx.getClass().equals(cuttedCtx.getClass())) { + try { + final Field currentElementFieldCuttedCtx = + cuttedCtx.getClass().getField("current"); + final Field currentElementFieldFullCtx = + fullCtx.getClass().getField("current"); + if (currentElementFieldCuttedCtx != null && currentElementFieldFullCtx != null) { + @SuppressWarnings("rawtypes") + final Element cuttedCtxElement = + (Element) currentElementFieldCuttedCtx.get(cuttedCtx); + @SuppressWarnings("rawtypes") + final Element fullCtxElement = + (Element) currentElementFieldFullCtx.get(fullCtx); + if (cuttedCtxElement.getFullLocation().equals(fullCtxElement.getFullLocation()) + && cuttedCtxElement.getUniqueName().equals(fullCtxElement.getUniqueName())) { + return fullCtx; + } + } + } catch (NoSuchFieldException | SecurityException | IllegalArgumentException + | IllegalAccessException e) { + e.printStackTrace(); + } + } else { + for (final ParseTree child : fullCtx.children) { + if (child instanceof ParserRuleContext) { + final ParserRuleContext context = + AIECompletionUtil.findFullContext((ParserRuleContext) child, cuttedCtx); + if (context != null) { + return context; + } + } + } + } + return null; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/util/AIESuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/util/AIESuggestionProvider.java new file mode 100644 index 00000000..faaddf19 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/util/AIESuggestionProvider.java @@ -0,0 +1,12 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.util; + +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; + +public interface AIESuggestionProvider { + Set getSuggestions(ParserRuleContext context, ParseTree lastToken); + + Set getStartSuggestions(); +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/util/AbstractAIESuggestionProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/util/AbstractAIESuggestionProvider.java new file mode 100644 index 00000000..93933538 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/util/AbstractAIESuggestionProvider.java @@ -0,0 +1,83 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.util; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.AIEModelSuggestionProviderFactory; + +public abstract class AbstractAIESuggestionProvider implements AIESuggestionProvider { + + protected List children; + protected List parents; + protected Set suggestions; + protected List allPossibleTokens; + + protected final AIEModelSuggestionProviderFactory spFactory; + + public AbstractAIESuggestionProvider() { + spFactory = new AIEModelSuggestionProviderFactory(); + } + + @Override + public Set getSuggestions(final ParserRuleContext context, final ParseTree lastToken) { + suggestions = new HashSet<>(); + if (isCompatibleWithContext(context)) { + initRelatedProviders(); + computeSuggestions(context, lastToken); + } + return suggestions; + } + + private void initRelatedProviders() { + children = new ArrayList<>(); + parents = new ArrayList<>(); + initParentProviders(); + initChildProviders(); + } + + public void addParent(final AIESuggestionProvider parent) { + parents.add(parent); + } + + public void addChild(final AIESuggestionProvider child) { + children.add(child); + } + + protected Set getChildProviderSuggestions(final ParserRuleContext context, + final ParseTree lastToken) { + final Set suggestions = new HashSet<>(); + for (final ParseTree childContext : context.children) { + if (childContext instanceof ParserRuleContext) { + for (final AIESuggestionProvider childProvider : children) { + suggestions + .addAll(childProvider.getSuggestions((ParserRuleContext) childContext, lastToken)); + } + } + } + return suggestions; + } + + protected Set getParentProviderSuggestions(ParserRuleContext context, + ParseTree lastToken) { + final Set suggestions = new HashSet<>(); + lastToken = context; + context = context.getParent(); + for (final AIESuggestionProvider parentProvider : parents) { + suggestions.addAll(parentProvider.getSuggestions(context, lastToken)); + } + return suggestions; + } + + protected abstract void initParentProviders(); + + protected abstract void initChildProviders(); + + protected abstract void computeSuggestions(ParserRuleContext context, ParseTree lastToken); + + protected abstract boolean isCompatibleWithContext(ParserRuleContext context); +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/util/SuggestionDetector.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/util/SuggestionDetector.java new file mode 100644 index 00000000..f357b633 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/completion/util/SuggestionDetector.java @@ -0,0 +1,48 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.completion.util; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; +import org.eclipse.jface.text.IDocument; + +import eu.modelwriter.core.alloyinecore.ui.editor.completion.model.AIEModelSuggestionProviderFactory; + +public class SuggestionDetector { + private final List suggestionProviders; + + private final IDocument document; + private final int offset; + private final ParserRuleContext parentOfCloserNode; + private final ParseTree closerNode; + + private final AIEModelSuggestionProviderFactory spFactory; + + public SuggestionDetector(final IDocument document, final int offset, + final ParserRuleContext parentOfCloserNode, final ParseTree closerNode) { + this.document = document; + this.offset = offset; + this.parentOfCloserNode = parentOfCloserNode; + this.closerNode = closerNode; + suggestionProviders = new ArrayList<>(); + + spFactory = new AIEModelSuggestionProviderFactory(); + initSuggestionProviders(); + } + + private void initSuggestionProviders() { + suggestionProviders + .addAll(spFactory.allSuggestionProviders()); + } + + public Set detect() { + final Set suggestions = new HashSet<>(); + for (final AIESuggestionProvider suggestionProvider : suggestionProviders) { + suggestions.addAll(suggestionProvider.getSuggestions(parentOfCloserNode, closerNode)); + } + return suggestions; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/document/AIEDocument.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/document/AIEDocument.java new file mode 100644 index 00000000..b3ea219f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/document/AIEDocument.java @@ -0,0 +1,68 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.document; + +import org.eclipse.core.resources.IFile; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.rules.FastPartitioner; +import org.eclipse.ui.part.FileEditorInput; + +import eu.modelwriter.core.alloyinecore.ui.editor.partition.IAIEPartitions; +import eu.modelwriter.core.alloyinecore.ui.editor.scanner.AIEPartitionScanner; +import eu.modelwriter.core.alloyinecore.ui.mapping.cs2as.CS2ASMapping; + +public class AIEDocument extends Document { + public static final String EDITOR_ID = "eu.modelwriter.core.alloyinecore.ui.editor"; + private EObject ecoreRoot; + private IFile iFile; + private final CS2ASMapping mapping; + private final FastPartitioner partitioner; + + public AIEDocument() { + mapping = new CS2ASMapping(); + partitioner = new FastPartitioner(new AIEPartitionScanner(), IAIEPartitions.ALL_PARTITIONS); + partitioner.connect(this); + this.setDocumentPartitioner(IAIEPartitions.AIE_PARTITIONING, partitioner); + } + + public void setEcoreRoot(final EObject ecoreRoot) { + this.ecoreRoot = ecoreRoot; + } + + /** + * + * @return current ecore object + */ + public EObject getEcoreRoot() { + return ecoreRoot; + } + + public IFile getiFile() { + return iFile; + } + + /** + * Saves editor input to current ecore file. + * + * @param overwrite + * @param element + * + * @return true if succeed. + */ + public boolean saveInEcore(final Object element, final boolean overwrite) { + if (overwrite) { // Save as + if (element instanceof FileEditorInput) { + mapping.parseAndSave(get(), + URI.createFileURI(((FileEditorInput) element).getFile().getFullPath().toString())); + } + } else { // Save + mapping.parseAndSave(get(), + URI.createPlatformResourceURI(iFile.getFullPath().toString(), true)); + } + return true; + } + + public void setFile(final IFile iFile) { + this.iFile = iFile; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/document/AIEDocumentProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/document/AIEDocumentProvider.java new file mode 100644 index 00000000..330b9850 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/document/AIEDocumentProvider.java @@ -0,0 +1,67 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.document; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.text.IDocument; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.editors.text.FileDocumentProvider; +import org.eclipse.ui.part.FileEditorInput; + +import eu.modelwriter.configuration.internal.EcoreUtilities; +import eu.modelwriter.core.alloyinecore.ui.mapping.as2cs.EcoreTranslator; + +public class AIEDocumentProvider extends FileDocumentProvider { + private final EcoreTranslator translator; + + public AIEDocumentProvider() { + translator = new EcoreTranslator(); + } + + @Override + protected IDocument createDocument(final Object element) throws CoreException { + final IDocument document = createEmptyDocument(); + if (document != null) { + setContent(document, (FileEditorInput) element); + } + return document; + } + + private void setContent(final IDocument document, final FileEditorInput editorInput) { + try { + final IFile iFile = editorInput.getFile(); + final EObject ecoreRoot = + EcoreUtilities.getRootObject(editorInput.getFile().getFullPath().toString()); + document.set(translator.translate((EModelElement) ecoreRoot)); + if (document instanceof AIEDocument) { + ((AIEDocument) document).setEcoreRoot(ecoreRoot); + ((AIEDocument) document).setFile(iFile); + } + } catch (final Exception e) { + e.printStackTrace(); + document.set(""); + } + } + + @Override + protected IDocument createEmptyDocument() { + return new AIEDocument(); + } + + @Override + protected boolean setDocumentContent(final IDocument document, final IEditorInput editorInput, + final String encoding) throws CoreException { + setContent(document, (FileEditorInput) editorInput); + return true; + } + + @Override + protected void doSaveDocument(final IProgressMonitor monitor, final Object element, + final IDocument document, final boolean overwrite) throws CoreException { + if (document instanceof AIEDocument) { + ((AIEDocument) document).saveInEcore(element, overwrite); + } + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/hyperlink/AIEHyperlink.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/hyperlink/AIEHyperlink.java new file mode 100644 index 00000000..21152590 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/hyperlink/AIEHyperlink.java @@ -0,0 +1,41 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.hyperlink; + +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.hyperlink.IHyperlink; +import org.eclipse.ui.editors.text.TextEditor; + +import eu.modelwriter.core.alloyinecore.ui.Activator; + +public class AIEHyperlink implements IHyperlink { + + private Region region; + + public AIEHyperlink(int start, int stop) { + region = new Region(start, stop - start + 1); + } + + @Override + public IRegion getHyperlinkRegion() { + return region; + } + + @Override + public String getTypeLabel() { + return "AIEHyperlink"; + } + + @Override + public String getHyperlinkText() { + return "Open declaration"; + } + + @Override + public void open() { + TextEditor editor = + (TextEditor) Activator.getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + editor.selectAndReveal(20, 2); + editor.setFocus(); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/hyperlink/AIEHyperlinkDetector.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/hyperlink/AIEHyperlinkDetector.java new file mode 100644 index 00000000..1f025946 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/hyperlink/AIEHyperlinkDetector.java @@ -0,0 +1,115 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.hyperlink; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.hyperlink.IHyperlink; +import org.eclipse.jface.text.hyperlink.IHyperlinkDetector; +import org.eclipse.jface.text.source.ISourceViewer; + +import eu.modelwriter.core.alloyinecore.structure.model.Class; +import eu.modelwriter.core.alloyinecore.structure.model.GenericElementType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericSuperType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericWildcard; +import eu.modelwriter.core.alloyinecore.ui.editor.AIEEditor; +import eu.modelwriter.core.alloyinecore.visitor.BaseVisitorImpl; + +public class AIEHyperlinkDetector implements IHyperlinkDetector { + + @SuppressWarnings("unused") + private ISourceViewer sourceViewer; + public AIEEditor editor; + private List hyperlinks = null; + + public AIEHyperlinkDetector(ISourceViewer sourceViewer, AIEEditor fTextEditor) { + this.sourceViewer = sourceViewer; + editor = fTextEditor; + } + + private void loadLinks() { + TypeVisitor typeVisitor = new TypeVisitor(editor); + typeVisitor.visit(editor.getRootElement()); + hyperlinks = typeVisitor.getLinks(); + } + + @Override + public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, + boolean canShowMultipleHyperlinks) { + if (hyperlinks == null) + loadLinks(); + + List result = new ArrayList<>(); + for (IHyperlink iHyperlink : hyperlinks) { + if (overlaps(iHyperlink.getHyperlinkRegion(), region)) + result.add(iHyperlink); + if (result.size() == 1 && !canShowMultipleHyperlinks) + break; + } + return result.toArray(new IHyperlink[0]); + } + + private boolean overlaps(IRegion r1, IRegion r2) { + int r1End = r1.getOffset() + r1.getLength(); + int r2End = r2.getOffset() + r2.getLength(); + return r2.getOffset() >= r1.getOffset() && r2End <= r1End; + } + + private static class TypeVisitor extends BaseVisitorImpl { + + private List links = new ArrayList<>(); + private AIEEditor editor; + + public TypeVisitor(AIEEditor fTextEditor) { + editor = fTextEditor; + } + + public List getLinks() { + return links; + } + + @Override + public Object visitClass(Class _class) { + EObjectHyperlink oHyperlink = + new EObjectHyperlink(_class.getStart(), _class.getStop(), _class.getEObject(), editor); + links.add(oHyperlink); + return super.visitClass(_class); + } + + @Override + public Object visitGenericElementType(GenericElementType genericElementType) { + addToLinks(genericElementType); + return super.visitGenericElementType(genericElementType); + } + + @Override + public Object visitGenericSuperType(GenericSuperType genericSuperType) { + addToLinks(genericSuperType); + return super.visitGenericSuperType(genericSuperType); + } + + @Override + public Object visitGenericWildcard(GenericWildcard genericWildcard) { + addToLinks(genericWildcard); + return super.visitGenericWildcard(genericWildcard); + } + + @Override + public Object visitGenericType(GenericType genericType) { + addToLinks(genericType); + return super.visitGenericType(genericType); + } + + @SuppressWarnings("rawtypes") + private void addToLinks(eu.modelwriter.core.alloyinecore.structure.base.Object element) { + AIEHyperlink aieHyperlink = new AIEHyperlink(element.getStart(), element.getStop()); + EObjectHyperlink oHyperlink = + new EObjectHyperlink(element.getStart(), element.getStop(), element.getEObject(), editor); + links.add(aieHyperlink); + links.add(oHyperlink); + } + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/hyperlink/EObjectHyperlink.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/hyperlink/EObjectHyperlink.java new file mode 100644 index 00000000..3d5b7082 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/hyperlink/EObjectHyperlink.java @@ -0,0 +1,45 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.hyperlink; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.hyperlink.IHyperlink; + +import eu.modelwriter.core.alloyinecore.ui.editor.AIEEditor; + +public class EObjectHyperlink implements IHyperlink { + + private Region region; + private EObject eObject; + private AIEEditor editor; + + public EObjectHyperlink(int start, int stop, EObject eObject, AIEEditor editor) { + this.eObject = eObject; + this.editor = editor; + region = new Region(start, stop - start + 1); + } + + @Override + public IRegion getHyperlinkRegion() { + return region; + } + + @Override + public String getTypeLabel() { + return "EObjectHyperlink"; + } + + @Override + public String getHyperlinkText() { + return "Open in Ecore Editor"; + } + + @Override + public void open() { + editor.openEcoreEditorAndReveal(eObject); + // EcoreEditor ecoreEditor = editor.openEcoreEditor(); + // URI uri = EcoreUtil.getURI(eObject); + // ecoreEditor.setSelection(new StructuredSelection(eObject)); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/AIEInstanceEditor.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/AIEInstanceEditor.java new file mode 100644 index 00000000..075de68f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/AIEInstanceEditor.java @@ -0,0 +1,42 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.instance; + +import java.util.Set; + +import eu.modelwriter.core.alloyinecore.ui.ASTManager; +import eu.modelwriter.core.alloyinecore.ui.Activator; +import eu.modelwriter.core.alloyinecore.ui.editor.AIEEditor; +import eu.modelwriter.core.alloyinecore.ui.editor.instance.document.AIEInstanceDocumentProvider; +import eu.modelwriter.core.alloyinecore.ui.editor.instance.scanner.AIEInstanceCodeScanner; +import eu.modelwriter.core.alloyinecore.ui.editor.instance.scanner.KeywordListener; +import eu.modelwriter.core.alloyinecore.ui.editor.partition.IAIEPartitions; + +public class AIEInstanceEditor extends AIEEditor { + + public static final String editorID = + "eu.modelwriter.core.alloyinecore.ui.editors.AlloyInEcoreInstanceEditor"; + + public AIEInstanceEditor() { + super(); + } + + @Override + protected void initEditor() { + AIEInstanceSourceViewerConfiguration configuration = new AIEInstanceSourceViewerConfiguration( + aIEColorManager, this, IAIEPartitions.AIE_PARTITIONING); + setSourceViewerConfiguration(configuration); + AIEInstanceDocumentProvider provider = new AIEInstanceDocumentProvider(); + provider.setKeywordListener(new KeywordListener() { + + @Override + public void onKeywordsCollected(Set keywords, Set sfKeywords) { + ((AIEInstanceCodeScanner) configuration.getCodeScanner()).updateRules(keywords, sfKeywords); + } + }); + setDocumentProvider(provider); + } + + @Override + protected ASTManager getManagerForEditor() { + return Activator.getDefault().getInstanceManager(); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/AIEInstanceSourceViewerConfiguration.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/AIEInstanceSourceViewerConfiguration.java new file mode 100644 index 00000000..b4d3bf93 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/AIEInstanceSourceViewerConfiguration.java @@ -0,0 +1,67 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.instance; + +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.jface.text.reconciler.IReconciler; +import org.eclipse.jface.text.reconciler.Reconciler; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.ui.texteditor.ITextEditor; + +import eu.modelwriter.core.alloyinecore.ui.editor.AIESourceViewerConfiguration; +import eu.modelwriter.core.alloyinecore.ui.editor.color.IColorManager; +import eu.modelwriter.core.alloyinecore.ui.editor.instance.reconciling.AIEInstanceSyntacticReconcilingStrategy; +import eu.modelwriter.core.alloyinecore.ui.editor.instance.scanner.AIEInstanceCodeScanner; +import eu.modelwriter.core.alloyinecore.ui.editor.partition.IAIEPartitions; +import eu.modelwriter.core.alloyinecore.ui.editor.scanner.AIECodeScanner; + +public class AIEInstanceSourceViewerConfiguration extends AIESourceViewerConfiguration { + private AIEInstanceCodeScanner fCodeScanner; + + /** + * Creates a new AlloyInEcore source viewer configuration for viewers in the given editor using + * the given the color manager and the specified document partitioning. + * + * @param colorManager the color manager + * @param editor the editor in which the configured viewer(s) will reside, or null if + * none + * @param partitioning the document partitioning for this configuration, or null for + * the default partitioning + */ + public AIEInstanceSourceViewerConfiguration(final IColorManager colorManager, + final ITextEditor editor, final String partitioning) { + super(colorManager, editor, partitioning); + } + + /** + * Initializes the scanners. + */ + @Override + protected void initializeScanners() { + fCodeScanner = new AIEInstanceCodeScanner(getColorManager()); + } + + @Override + protected AIECodeScanner getCodeScanner() { + return fCodeScanner; + } + + /* + * @see SourceViewerConfiguration#getReconciler(ISourceViewer) + */ + @Override + public IReconciler getReconciler(final ISourceViewer sourceViewer) { + final ITextEditor editor = getEditor(); + if (editor != null && editor.isEditable()) { + final Reconciler reconciler = new Reconciler(); + final AIEInstanceSyntacticReconcilingStrategy strategy = + new AIEInstanceSyntacticReconcilingStrategy(sourceViewer, editor); + for (final String partition : IAIEPartitions.ALL_PARTITIONS) { + reconciler.setReconcilingStrategy(strategy, partition); + } + reconciler.setDocumentPartitioning(IAIEPartitions.AIE_PARTITIONING); + reconciler.setDelay(500); + reconciler.setProgressMonitor(new NullProgressMonitor()); + return reconciler; + } + return null; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/document/AIEInstanceDocument.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/document/AIEInstanceDocument.java new file mode 100644 index 00000000..4d79189a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/document/AIEInstanceDocument.java @@ -0,0 +1,83 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.instance.document; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.core.resources.IFile; +import org.eclipse.emf.common.util.TreeIterator; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.rules.FastPartitioner; + +import eu.modelwriter.core.alloyinecore.ui.editor.instance.scanner.KeywordListener; +import eu.modelwriter.core.alloyinecore.ui.editor.partition.IAIEPartitions; +import eu.modelwriter.core.alloyinecore.ui.editor.scanner.AIEPartitionScanner; + +public class AIEInstanceDocument extends Document { + private EObject instanceRoot; + private IFile iFile; + private Set sfKeywords = new HashSet<>(); + private Set keywords = new HashSet<>(); + private final FastPartitioner partitioner; + + public AIEInstanceDocument() { + partitioner = new FastPartitioner(new AIEPartitionScanner(), IAIEPartitions.ALL_PARTITIONS); + partitioner.connect(this); + this.setDocumentPartitioner(IAIEPartitions.AIE_PARTITIONING, partitioner); + } + + public void setInstanceRoot(final EObject instanceRoot, KeywordListener keywordListener) { + this.instanceRoot = instanceRoot; + collectKeywords(instanceRoot); + keywordListener.onKeywordsCollected(keywords, sfKeywords); + } + + private void collectKeywords(EObject eObject) { + TreeIterator iterator = eObject.eAllContents(); + while (iterator.hasNext()) { + EObject next = iterator.next(); + keywords.add(next.eClass().getName()); + for (EStructuralFeature sf : next.eClass().getEAllStructuralFeatures()) { + sfKeywords.add(sf.getName()); + } + ENamedElement container = (ENamedElement) next.eClass().eContainer(); + if (container != null) + keywords.add(container.getName()); + } + keywords.add(eObject.eClass().getName()); + for (EStructuralFeature sf : eObject.eClass().getEAllStructuralFeatures()) { + sfKeywords.add(sf.getName()); + } + } + + /** + * + * @return current ecore object + */ + public EObject getEcoreRoot() { + return instanceRoot; + } + + public IFile getiFile() { + return iFile; + } + + /** + * Saves editor input to current ecore file. + * + * @param overwrite + * @param element + * + * @return true if succeed. + */ + public boolean saveInEcore(final Object element, final boolean overwrite) { + // Not Implemented + return true; + } + + public void setFile(final IFile iFile) { + this.iFile = iFile; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/document/AIEInstanceDocumentProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/document/AIEInstanceDocumentProvider.java new file mode 100644 index 00000000..948fe40a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/document/AIEInstanceDocumentProvider.java @@ -0,0 +1,76 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.instance.document; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.jface.text.IDocument; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.editors.text.FileDocumentProvider; +import org.eclipse.ui.part.FileEditorInput; + +import eu.modelwriter.core.alloyinecore.structure.base.Repository; +import eu.modelwriter.core.alloyinecore.ui.editor.instance.scanner.KeywordListener; +import eu.modelwriter.core.alloyinecore.ui.mapping.as2cs.EcoreInstanceTranslator; + +public class AIEInstanceDocumentProvider extends FileDocumentProvider { + private final EcoreInstanceTranslator translator; + private Repository repository; + private KeywordListener keywordListener; + + public AIEInstanceDocumentProvider() { + translator = new EcoreInstanceTranslator(); + repository = new Repository(); + } + + public void setKeywordListener(KeywordListener keywordListener) { + this.keywordListener = keywordListener; + } + + @Override + protected IDocument createDocument(final Object element) throws CoreException { + final IDocument document = createEmptyDocument(); + if (document != null) { + setContent(document, (FileEditorInput) element); + } + return document; + } + + private void setContent(final IDocument document, final FileEditorInput editorInput) { + try { + final IFile iFile = editorInput.getFile(); + Resource resource = repository.loadResource(editorInput.getFile().getFullPath().toString()); + if (resource != null && !resource.getContents().isEmpty()) { + final EObject instanceRoot = resource.getContents().get(0); + document.set(translator.translate(instanceRoot)); + if (document instanceof AIEInstanceDocument) { + ((AIEInstanceDocument) document).setInstanceRoot(instanceRoot, keywordListener); + ((AIEInstanceDocument) document).setFile(iFile); + } + } else + throw new Exception("Resource is null or empty. " + resource.getErrors()); + } catch (final Exception e) { + e.printStackTrace(); + document.set(""); + } + } + + @Override + protected IDocument createEmptyDocument() { + return new AIEInstanceDocument(); + } + + @Override + protected boolean setDocumentContent(final IDocument document, final IEditorInput editorInput, + final String encoding) throws CoreException { + setContent(document, (FileEditorInput) editorInput); + return true; + } + + @Override + protected void doSaveDocument(final IProgressMonitor monitor, final Object element, + final IDocument document, final boolean overwrite) throws CoreException { + // Not Implemented + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/reconciling/AIEInstanceSyntacticReconcilingStrategy.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/reconciling/AIEInstanceSyntacticReconcilingStrategy.java new file mode 100644 index 00000000..a54c92f2 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/reconciling/AIEInstanceSyntacticReconcilingStrategy.java @@ -0,0 +1,33 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.instance.reconciling; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.ui.texteditor.ITextEditor; + +import eu.modelwriter.core.alloyinecore.ui.Activator; +import eu.modelwriter.core.alloyinecore.ui.editor.reconciling.AIESyntacticReconcilingStrategy; + +public class AIEInstanceSyntacticReconcilingStrategy extends AIESyntacticReconcilingStrategy { + + public AIEInstanceSyntacticReconcilingStrategy(final ISourceViewer sourceViewer, + final ITextEditor editor) { + super(sourceViewer, editor); + } + + @Override + protected void attachErrorListener() { + Activator.getDefault().getInstanceManager().addErrorListener(this); + } + + @Override + public void reconcile(final IRegion partition) { + try { + URI uri = URI.createPlatformResourceURI(iFile.getFullPath().toString(), true); + removeOldAnnotations(); + Activator.getDefault().getInstanceManager().parseDocument(document, uri); + } catch (final Exception e1) { + e1.printStackTrace(); + } + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/scanner/AIEInstanceCodeScanner.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/scanner/AIEInstanceCodeScanner.java new file mode 100644 index 00000000..745a6b1f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/scanner/AIEInstanceCodeScanner.java @@ -0,0 +1,59 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.instance.scanner; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WordRule; +import org.eclipse.swt.SWT; + +import eu.modelwriter.core.alloyinecore.ui.editor.color.IAIEColorConstants; +import eu.modelwriter.core.alloyinecore.ui.editor.color.IColorManager; +import eu.modelwriter.core.alloyinecore.ui.editor.scanner.AIECodeScanner; + +public class AIEInstanceCodeScanner extends AIECodeScanner { + + protected IToken sfKeyword; + + public AIEInstanceCodeScanner(final IColorManager manager) { + super(manager); + sfKeyword = + new Token(new TextAttribute(manager.getColor(IAIEColorConstants.AIE_INSTANCE_SF_KEYWORD), + null, SWT.BOLD)); + } + + public void updateRules(Set keywords, Set sfKeywords) { + final List rules = new ArrayList(); + rules.addAll(getCommentRules()); + final WordRule keywordRule = new WordRule(new IWordDetector() { + + @Override + public boolean isWordPart(final char c) { + return Character.isLetter(c); + } + + @Override + public boolean isWordStart(final char c) { + return Character.isLetter(c); + } + }, defaultToken); + keywords.forEach(k -> { + keywordRule.addWord(k, keyword); + }); + sfKeywords.forEach(k -> { + keywordRule.addWord(k, sfKeyword); + }); + keywordRule.addWord("import", keyword); + keywordRule.addWord("model", keyword); + + rules.add(keywordRule); + final IRule[] result = new IRule[rules.size()]; + rules.toArray(result); + setRules(result); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/scanner/KeywordListener.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/scanner/KeywordListener.java new file mode 100644 index 00000000..9dcb3de5 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/instance/scanner/KeywordListener.java @@ -0,0 +1,7 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.instance.scanner; + +import java.util.Set; + +public interface KeywordListener { + void onKeywordsCollected(Set keywords, Set sfKeywords); +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/outline/AIEContentOutlinePage.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/outline/AIEContentOutlinePage.java new file mode 100644 index 00000000..a2c248e8 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/outline/AIEContentOutlinePage.java @@ -0,0 +1,117 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.outline; + +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.viewers.DecoratingStyledCellLabelProvider; +import org.eclipse.jface.viewers.ILabelDecorator; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.editors.text.TextEditor; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.views.contentoutline.ContentOutlinePage; + +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.model.Multiplicity; +import eu.modelwriter.core.alloyinecore.ui.ASTChangeListener; +import eu.modelwriter.core.alloyinecore.ui.ASTManager; + +public class AIEContentOutlinePage extends ContentOutlinePage implements ASTChangeListener { + + private final TextEditor aieEditor; + private TreeViewer viewer; + private StructuredSelection selection; + private int selectionOffset; + private final RootWrapper root = new RootWrapper(); + + public AIEContentOutlinePage(final IDocumentProvider documentProvider, + final TextEditor alloyInEcoreEditor, ASTManager manager) { + aieEditor = alloyInEcoreEditor; + manager.addChangeListener(this); + } + + @SuppressWarnings("rawtypes") + public void refresh(final Element parsedModule) { + root.setElement(parsedModule); + if (viewer != null) { + viewer.refresh(true); + } + } + + @SuppressWarnings("rawtypes") + public void selectElement(Element selectedElement) { + if (selectedElement instanceof Multiplicity) { + selectedElement = selectedElement.getOwner(); + } + selection = new StructuredSelection(selectedElement); + viewer.setSelection(selection, true); + } + + public int getSelectionOffset() { + return selectionOffset; + } + + @Override + public void createControl(final Composite parent) { + super.createControl(parent); + viewer = getTreeViewer(); + viewer.setContentProvider(new AIEContentProvider()); + final ILabelDecorator labelDecorator = + PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator(); + viewer.setLabelProvider( + new DecoratingStyledCellLabelProvider(new AIELabelProvider(), labelDecorator, null)); + viewer.addSelectionChangedListener(new ISelectionChangedListener() { + + @SuppressWarnings("rawtypes") + @Override + public void selectionChanged(final SelectionChangedEvent event) { + if (!event.getSelectionProvider().getSelection().equals(selection)) { + final ISelection selection = viewer.getSelection(); + if (selection instanceof IStructuredSelection) { + final Object item = ((IStructuredSelection) selection).getFirstElement(); + if (item instanceof Element) { + final Element element = (Element) item; + selectionOffset = element.getStart() + element.getStop() - element.getStart() + 1; + aieEditor.getSelectionProvider().setSelection(new TextSelection(element.getStart(), + element.getStop() - element.getStart() + 1)); + } + } + } + } + }); + viewer.setAutoExpandLevel(2); + viewer.setInput(root); + } + + public class RootWrapper { + @SuppressWarnings("rawtypes") + Element root; + + public RootWrapper() {} + + @SuppressWarnings("rawtypes") + public void setElement(final Element root) { + this.root = root; + } + } + + @SuppressWarnings("rawtypes") + @Override + public void onASTChange(Element model) { + root.setElement(model); + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + if (viewer != null) { + viewer.refresh(true); + } + } + }); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/outline/AIEContentProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/outline/AIEContentProvider.java new file mode 100644 index 00000000..02fd14eb --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/outline/AIEContentProvider.java @@ -0,0 +1,57 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.outline; + +import java.util.List; +import java.util.stream.Collectors; + +import org.eclipse.jface.viewers.ITreeContentProvider; + +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.model.Multiplicity; +import eu.modelwriter.core.alloyinecore.ui.editor.outline.AIEContentOutlinePage.RootWrapper; + +public class AIEContentProvider implements ITreeContentProvider { + + @Override + public Object[] getElements(final Object inputElement) { + if (inputElement instanceof Multiplicity) { + return new Object[0]; + } + + return getChildren(inputElement); + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + @Override + public Object[] getChildren(final Object parentElement) { + if (parentElement instanceof RootWrapper) { + if (((RootWrapper) parentElement).root == null) { + return new Object[0]; + } + return new Object[] {((RootWrapper) parentElement).root}; + } else if (parentElement != null) { + final Element parent = (Element) parentElement; + final List children = (List) parent.getOwnedElements().stream() + .filter(p -> !(p instanceof Multiplicity)).collect(Collectors.toList()); + return children.toArray(); + } + return null; + } + + @SuppressWarnings("rawtypes") + @Override + public Object getParent(final Object element) { + if (element != null && !(element instanceof Multiplicity)) { + return ((Element) element).getOwner(); + } + return null; + } + + @SuppressWarnings("rawtypes") + @Override + public boolean hasChildren(final Object element) { + if (element instanceof RootWrapper) { + return true; + } + return element != null && ((Element) element).hasOwnedElements(); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/outline/AIELabelDecorator.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/outline/AIELabelDecorator.java new file mode 100644 index 00000000..4713e942 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/outline/AIELabelDecorator.java @@ -0,0 +1,78 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.outline; + +import org.eclipse.emf.ecore.ETypedElement; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.IDecoration; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.ILightweightLabelDecorator; + +import eu.modelwriter.core.alloyinecore.structure.model.IVisibility; +import eu.modelwriter.core.alloyinecore.structure.model.Visibility; +import eu.modelwriter.core.alloyinecore.ui.Activator; + +public class AIELabelDecorator implements ILightweightLabelDecorator { + + @Override + public void addListener(final ILabelProviderListener listener) {} + + @Override + public void dispose() {} + + @Override + public boolean isLabelProperty(final Object element, final String property) { + return true; + } + + @Override + public void removeListener(final ILabelProviderListener listener) {} + + @Override + public void decorate(final Object element, final IDecoration decoration) { + // Add visibility overlay + if (element instanceof IVisibility) { + final Visibility visibility = ((IVisibility) element).getVisibility(); + final String overlayName = visibility.name().toString(); + decorate(decoration, overlayName, IDecoration.BOTTOM_RIGHT); + } + } + + private void decorate(final IDecoration decoration, final String overlayName, final int position) { + final ImageDescriptor overlayDesc = + Activator.getDefault().getImageRegistry().getDescriptor(overlayName); + if (overlayDesc != null) { + decoration.addOverlay(overlayDesc, IDecoration.BOTTOM_RIGHT); + } + } + + @SuppressWarnings("unused") + private String getOverlayName(final ETypedElement typedElement) { + String overlayName = "EOccurrence"; + String lower = ""; + String upper = ""; + if (typedElement.getLowerBound() == 0) { + lower = "Zero"; + } else if (typedElement.getLowerBound() == 1) { + lower = "One"; + } else if (typedElement.getLowerBound() != 0 && typedElement.getLowerBound() != 1) { + lower = "N"; + } + + if (typedElement.getUpperBound() == -1) { + upper = "Unbounded"; + } else if (typedElement.getUpperBound() == -2) { + upper = "Unspecified"; + } else if (typedElement.getUpperBound() == 1) { + upper = "One"; + } else if (typedElement.getUpperBound() != -1 && typedElement.getUpperBound() != 1 + && typedElement.getUpperBound() != -2) { + upper = "M"; + } + + if (typedElement.getLowerBound() == typedElement.getUpperBound()) { + overlayName += lower; + } else { + overlayName += lower + "To" + upper; + } + return overlayName; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/outline/AIELabelProvider.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/outline/AIELabelProvider.java new file mode 100644 index 00000000..1ce47ec6 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/outline/AIELabelProvider.java @@ -0,0 +1,43 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.outline; + +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider; +import org.eclipse.jface.viewers.IFontProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.StyledString; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; + +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.ui.Activator; + +public class AIELabelProvider extends LabelProvider implements IFontProvider, IStyledLabelProvider { + + @Override + public Image getImage(final Object element) { + return Activator.getDefault().getImageRegistry().get(element.getClass().getSimpleName()); + } + + @SuppressWarnings("rawtypes") + @Override + public String getText(final Object element) { + return ((Element) element).getLabel(); + } + + @Override + public Font getFont(final Object element) { + if (element instanceof eu.modelwriter.core.alloyinecore.structure.model.Class + && ((eu.modelwriter.core.alloyinecore.structure.model.Class) element).isAbstract()) { + return JFaceResources.getFontRegistry().getItalic(JFaceResources.DEFAULT_FONT); + } + return JFaceResources.getFontRegistry().get(JFaceResources.DEFAULT_FONT); + } + + @SuppressWarnings("rawtypes") + @Override + public StyledString getStyledText(final Object element) { + final StyledString styledString = new StyledString(getText(element)); + styledString.append(" " + ((Element) element).getSuffix(), StyledString.DECORATIONS_STYLER); + return styledString; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/partition/IAIEPartitions.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/partition/IAIEPartitions.java new file mode 100644 index 00000000..cb14c322 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/partition/IAIEPartitions.java @@ -0,0 +1,51 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.partition; + +import org.eclipse.jface.text.IDocument; + +/** + * Definition of AlloyInEcore partitioning and its partitions. + */ +public interface IAIEPartitions { + /** + * The identifier of the AlloyInEcore partitioning. + */ + String AIE_PARTITIONING = "___alloyinecore_partitioning"; + + /** + * The identifier of prefix for all partitions. + */ + String AIE_PREFIX = "__alloyinecore"; + + /** + * The identifier of the single-line (EndOfLineComment) end comment partition content type. + */ + String AIE_DEFAULT = IDocument.DEFAULT_CONTENT_TYPE; + + /** + * The identifier of the single-line (EndOfLineComment) end comment partition content type. + */ + String AIE_SINGLE_LINE_COMMENT = IAIEPartitions.AIE_PREFIX + "_singleline_comment"; + + /** + * The identifier multi-line (TraditionalComment) comment partition content type. + */ + String AIE_MULTI_LINE_COMMENT = IAIEPartitions.AIE_PREFIX + "_multiline_comment"; + + /** + * The identifier of the AlloyInEcore string partition content type. + */ + String AIE_DOUBLE_QUOTED_STRING = IAIEPartitions.AIE_PREFIX + "_single_quoted_string"; + + /** + * The identifier of the AlloyInEcore character partition content type. + */ + String AIE_SINGLE_QUOTED_STRING = IAIEPartitions.AIE_PREFIX + "_single_quoted_string"; + + /** + * The identifier of the AlloyInEcore module partition content type. + */ + + String[] ALL_PARTITIONS = new String[] {IAIEPartitions.AIE_DEFAULT, + IAIEPartitions.AIE_SINGLE_LINE_COMMENT, IAIEPartitions.AIE_MULTI_LINE_COMMENT, + IAIEPartitions.AIE_DOUBLE_QUOTED_STRING, IAIEPartitions.AIE_SINGLE_QUOTED_STRING}; +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/reconciling/AIESyntacticReconcilingStrategy.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/reconciling/AIESyntacticReconcilingStrategy.java new file mode 100644 index 00000000..c54675ac --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/reconciling/AIESyntacticReconcilingStrategy.java @@ -0,0 +1,153 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.reconciling; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.antlr.v4.runtime.Token; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.emf.common.util.URI; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.reconciler.DirtyRegion; +import org.eclipse.jface.text.reconciler.IReconcilingStrategy; +import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.ui.texteditor.ITextEditor; + +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.ui.ASTErrorListener; +import eu.modelwriter.core.alloyinecore.ui.Activator; +import eu.modelwriter.core.alloyinecore.ui.editor.AIEEditor; + +public class AIESyntacticReconcilingStrategy + implements IReconcilingStrategy, IReconcilingStrategyExtension, ASTErrorListener { + + private List annotations = new ArrayList<>(); + protected final ISourceViewer sourceViewer; + protected final ITextEditor editor; + protected IDocument document; + protected final IFile iFile; + protected boolean noErrors; + + + public AIESyntacticReconcilingStrategy(final ISourceViewer sourceViewer, + final ITextEditor editor) { + this.sourceViewer = sourceViewer; + this.editor = editor; + iFile = editor.getEditorInput().getAdapter(IFile.class); + attachErrorListener(); + } + + protected void attachErrorListener() { + Activator.getDefault().getModelManager().addErrorListener(this); + } + + protected IAnnotationModel getAnnotationModel() { + return sourceViewer.getAnnotationModel(); + } + + @Override + public void setProgressMonitor(final IProgressMonitor monitor) {} + + @Override + public void initialReconcile() { + if (document == null) { + return; + } + this.reconcile(new Region(0, document.getLength())); + } + + @Override + public void setDocument(final IDocument document) { + this.document = document; + } + + protected void createAnnotation(final Token offendingToken, final String msg, + final String annotationType) { + final Annotation annotation = new Annotation(annotationType, true, msg); + getAnnotationModel().connect(document); + getAnnotationModel().addAnnotation(annotation, new Position(offendingToken.getStartIndex(), + offendingToken.getStopIndex() - offendingToken.getStartIndex() + 1)); + getAnnotationModel().disconnect(document); + annotations.add(annotation); + } + + @SuppressWarnings("unused") + private void createErrorMarker(final Token offendingToken, final String message) { + try { + final IMarker m = iFile.createMarker(AIEEditor.PARSER_ERROR_MARKER); + m.setAttribute(IMarker.MESSAGE, message); + m.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_NORMAL); + m.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); + m.setAttribute(IMarker.LINE_NUMBER, offendingToken.getLine()); + m.setAttribute(IMarker.CHAR_START, offendingToken.getCharPositionInLine()); + m.setAttribute(IMarker.CHAR_END, offendingToken.getCharPositionInLine() + + offendingToken.getStopIndex() - offendingToken.getStartIndex() + 1); + } catch (final CoreException e) { + e.printStackTrace(); + } + } + + @Override + public void reconcile(final DirtyRegion dirtyRegion, final IRegion subRegion) { + if (document == null) { + return; + } + this.reconcile(subRegion); + } + + @Override + public void reconcile(final IRegion partition) { + try { + URI uri = URI.createPlatformResourceURI(iFile.getFullPath().toString(), true); + removeOldAnnotations(); + Activator.getDefault().getModelManager().parseDocument(document, uri); + } catch (final Exception e1) { + e1.printStackTrace(); + } + } + + protected void removeOldAnnotations() { + final IAnnotationModel annotationModel = getAnnotationModel(); + annotationModel.connect(document); + annotations.forEach(anno -> annotationModel.removeAnnotation(anno)); + annotationModel.disconnect(document); + annotations.clear(); + } + + @SuppressWarnings("unused") + private void removeOldMarkers() { + try { + iFile.deleteMarkers(AIEEditor.PARSER_ERROR_MARKER, true, IResource.DEPTH_INFINITE); + } catch (final CoreException e) { + e.printStackTrace(); + } + } + + @Override + public void onSyntaxError(Token offendingSymbol, String msg) { + createAnnotation((Token) offendingSymbol, msg, AIEEditor.PARSER_ERROR_ANNOTATION); + } + + @Override + public void onTypeError(String message, Set relatedElements) { + relatedElements + .forEach(e -> createAnnotation(e, message, AIEEditor.TYPE_ERROR_ANNOTATION)); + } + + @Override + public void onTypeWarning(String message, Set relatedElements) { + relatedElements + .forEach(e -> createAnnotation(e, message, AIEEditor.TYPE_WARNING_ANNOTATION)); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/scanner/AIECodeScanner.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/scanner/AIECodeScanner.java new file mode 100644 index 00000000..df8ca3ed --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/scanner/AIECodeScanner.java @@ -0,0 +1,97 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.scanner; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.rules.EndOfLineRule; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWhitespaceDetector; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.MultiLineRule; +import org.eclipse.jface.text.rules.RuleBasedScanner; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WhitespaceRule; +import org.eclipse.jface.text.rules.WordRule; +import org.eclipse.swt.SWT; + +import eu.modelwriter.core.alloyinecore.ui.editor.AIEKeywords; +import eu.modelwriter.core.alloyinecore.ui.editor.color.IAIEColorConstants; +import eu.modelwriter.core.alloyinecore.ui.editor.color.IColorManager; + +public class AIECodeScanner extends RuleBasedScanner { + + protected IToken defaultToken; + protected IToken keyword; + protected IToken stringToken; + protected IToken singlelineToken; + protected IToken multilineToken; + protected IToken aieKeyword; + + public AIECodeScanner(final IColorManager manager) { + defaultToken = new Token(new TextAttribute(manager.getColor(IAIEColorConstants.AIE_DEFAULT))); + aieKeyword = new Token( + new TextAttribute(manager.getColor(IAIEColorConstants.AIE_KEYWORD), null, SWT.BOLD)); + keyword = + new Token(new TextAttribute(manager.getColor(IAIEColorConstants.KEYWORD), null, SWT.BOLD)); + stringToken = new Token(new TextAttribute(manager.getColor(IAIEColorConstants.AIE_STRING))); + singlelineToken = + new Token(new TextAttribute(manager.getColor(IAIEColorConstants.AIE_SINGLE_LINE_COMMENT))); + multilineToken = + new Token(new TextAttribute(manager.getColor(IAIEColorConstants.AIE_MULTI_LINE_COMMENT))); + configureRules(); + } + + public void configureRules() { + final List rules = new ArrayList(); + rules.addAll(getCommentRules()); + final WordRule keywordRule = new WordRule(new IWordDetector() { + + @Override + public boolean isWordPart(final char c) { + return Character.isLetter(c); + } + + @Override + public boolean isWordStart(final char c) { + return Character.isLetter(c); + } + }, defaultToken); + + AIEKeywords.ALL_BUT_AIE.forEach(k -> { + keywordRule.addWord(k, keyword); + }); + + for (int i = 0; i < AIEKeywords.AIE.length; i++) { + keywordRule.addWord(AIEKeywords.AIE[i], aieKeyword); + } + rules.add(keywordRule); + + final IRule[] result = new IRule[rules.size()]; + rules.toArray(result); + setRules(result); + } + + protected List getCommentRules() { + final List rules = new ArrayList(); + + rules.add(new MultiLineRule("\"", "\"", stringToken, '\\')); + rules.add(new MultiLineRule("'", "'", stringToken, '\\')); + + // Add rules for multi-line comments. + rules.add(new MultiLineRule("/*", "*/", multilineToken)); + // Add rule for single line comments. + rules.add(new EndOfLineRule("--", singlelineToken)); + + // whitespace rule for skipping whitespaces. + rules.add(new WhitespaceRule(new IWhitespaceDetector() { + + @Override + public boolean isWhitespace(final char c) { + return Character.isWhitespace(c); + } + })); + return rules; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/scanner/AIEPartitionScanner.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/scanner/AIEPartitionScanner.java new file mode 100644 index 00000000..48ef08f4 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/scanner/AIEPartitionScanner.java @@ -0,0 +1,114 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.scanner; + + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.text.rules.EndOfLineRule; +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IPredicateRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.MultiLineRule; +import org.eclipse.jface.text.rules.RuleBasedPartitionScanner; +import org.eclipse.jface.text.rules.SingleLineRule; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WordRule; + +import eu.modelwriter.core.alloyinecore.ui.editor.partition.IAIEPartitions; + +public class AIEPartitionScanner extends RuleBasedPartitionScanner implements IAIEPartitions { + + /** + * Detector for empty comments. + */ + static class EmptyCommentDetector implements IWordDetector { + + /* + * @see IWordDetector#isWordStart + */ + @Override + public boolean isWordStart(final char c) { + return c == '/'; + } + + /* + * @see IWordDetector#isWordPart + */ + @Override + public boolean isWordPart(final char c) { + return c == '*' || c == '/'; + } + } + + /** + * Word rule for empty comments. + */ + static class EmptyCommentRule extends WordRule implements IPredicateRule { + + private final IToken fSuccessToken; + + /** + * Constructor for EmptyCommentRule. + * + * @param successToken + */ + public EmptyCommentRule(final IToken successToken) { + super(new EmptyCommentDetector()); + fSuccessToken = successToken; + addWord("/**/", fSuccessToken); + } + + /* + * @see IPredicateRule#evaluate(ICharacterScanner, boolean) + */ + @Override + public IToken evaluate(final ICharacterScanner scanner, final boolean resume) { + return evaluate(scanner); + } + + /* + * @see IPredicateRule#getSuccessToken() + */ + @Override + public IToken getSuccessToken() { + return fSuccessToken; + } + } + + /** + * Creates the partitioner and sets up the appropriate rules. + */ + public AIEPartitionScanner() { + super(); + final IToken dq_string = new Token(IAIEPartitions.AIE_DOUBLE_QUOTED_STRING); + final IToken sq_string = new Token(IAIEPartitions.AIE_SINGLE_QUOTED_STRING); + final IToken multiLineComment = new Token(IAIEPartitions.AIE_MULTI_LINE_COMMENT); + final IToken singleLineComment = new Token(IAIEPartitions.AIE_SINGLE_LINE_COMMENT); + + final List rules = new ArrayList<>(); + + // Add rule for single line comments. + rules.add(new EndOfLineRule("--", singleLineComment)); + + // Add rule for single line comments. + rules.add(new EndOfLineRule("//", singleLineComment)); + + // Add rule for double-quoted strings. + rules.add(new SingleLineRule("\"", "\"", dq_string, '\\')); + + // Add rule for single-quoted strings. + rules.add(new SingleLineRule("'", "'", sq_string, '\\')); + + // Add special case word rule. + final EmptyCommentRule wordRule = new EmptyCommentRule(multiLineComment); + rules.add(wordRule); + + // Add rules for multi-line comments. + rules.add(new MultiLineRule("/*", "*/", multiLineComment)); + + final IPredicateRule[] result = new IPredicateRule[rules.size()]; + rules.toArray(result); + setPredicateRules(result); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/util/EditorUtils.java b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/util/EditorUtils.java new file mode 100644 index 00000000..fd6335e0 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore.ui/src/eu/modelwriter/core/alloyinecore/ui/editor/util/EditorUtils.java @@ -0,0 +1,105 @@ +package eu.modelwriter.core.alloyinecore.ui.editor.util; + +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.BaseErrorListener; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.ParserRuleContext; +import org.eclipse.emf.common.util.URI; +import org.eclipse.jface.text.IDocument; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.instance.Instance; +import eu.modelwriter.core.alloyinecore.structure.model.Model; + +public final class EditorUtils { + + /** + * Parses the given document's text. + * + * @param document + * @param errorListener + * @return Parsed {@linkplain eu.modelwriter.core.alloyinecore.structure.Module} object + * @throws Exception + */ + public static Model parseDocument(final IDocument document, final URI uri, + final BaseErrorListener errorListener) throws Exception { + return EditorUtils.parseString(document.get(), uri, errorListener); + } + + /** + * Parses the given text. + * + * @param text + * @param errorListener + * @return Parsed {@link eu.modelwriter.core.alloyinecore.structure.Module} object + * @throws Exception + */ + public static Model parseString(final String text, final URI uri, + final BaseErrorListener errorListener) throws Exception { + final AlloyInEcoreLexer lexer = new AlloyInEcoreLexer(new ANTLRInputStream(text)); + final CommonTokenStream tokens = new CommonTokenStream(lexer); + final AlloyInEcoreParser parser = new AlloyInEcoreParser(tokens, uri); + parser.removeErrorListeners(); + parser.addErrorListener(errorListener); + parser.model(); + return parser.model; + } + + /** + * + * @param element Root element to start the search + * @param line + * @param offset + * @return + */ + @SuppressWarnings({"rawtypes"}) + public static Element findElement(final Element element, final int line, final int offset) { + for (final Object object : element.getOwnedElements()) { + if (EditorUtils.inContext(((Element) object).getContext(), offset)) { + return EditorUtils.findElement((Element) object, line, offset); + } else if (EditorUtils.isInSameLine(((Element) object).getContext(), line)) { + return (Element) object; + } + } + return element; + } + + /** + * + * @param context + * @param offset + * @return if given offset is in given context, true; otherwise false + */ + public static boolean inContext(final ParserRuleContext context, final int offset) { + return context.start.getStartIndex() <= offset && context.stop.getStopIndex() + 1 >= offset; + } + + public static boolean isInSameLine(final ParserRuleContext context, final int line) { + ParserRuleContext parent = context.getParent(); + // To get ride of wrappers + parent = parent != null && parent.start.getStartIndex() == context.start.getStartIndex() + ? parent.getParent() : parent; + // if its same line with context and + // context is not same line with its parent, 'cus we need parent if same line + return line >= context.start.getLine() && line <= context.stop.getLine() && parent != null + && parent.start.getLine() != context.start.getLine(); + } + + public static Instance parseInstanceDocument(IDocument document, URI uri, + BaseErrorListener baseErrorListener) { + return EditorUtils.parseInstanceString(document.get(), uri, baseErrorListener); + } + + private static Instance parseInstanceString(String text, URI uri, + BaseErrorListener baseErrorListener) { + final AlloyInEcoreLexer lexer = new AlloyInEcoreLexer(new ANTLRInputStream(text)); + final CommonTokenStream tokens = new CommonTokenStream(lexer); + final AlloyInEcoreParser parser = new AlloyInEcoreParser(tokens, uri); + parser.removeErrorListeners(); + parser.addErrorListener(baseErrorListener); + parser.instance(null); + return parser.instance; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/.gitignore b/Source/eu.modelwriter.core.alloyinecore/.gitignore new file mode 100644 index 00000000..c9c2f580 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/.gitignore @@ -0,0 +1,4 @@ +*.iml +.idea/ +target/ +.project \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/Instance.requirements b/Source/eu.modelwriter.core.alloyinecore/Instance.requirements new file mode 100644 index 00000000..4612a9b4 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/Instance.requirements @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/My.ecore b/Source/eu.modelwriter.core.alloyinecore/My.ecore new file mode 100644 index 00000000..af1525de --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/My.ecore @@ -0,0 +1,22 @@ + + + + +
+ + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/ReadMe.md b/Source/eu.modelwriter.core.alloyinecore/ReadMe.md new file mode 100644 index 00000000..f6fa091f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/ReadMe.md @@ -0,0 +1,133 @@ + Reasoning about Domain Specific Languages In Model-driven Architecture + ====================================================================== + * AlloyInECore Objectives + * Alloy and Java-like syntax + * Formal Language tailored to _EMF semantics_. + * Object Oriented features (OMG EMOF-based) + * _Formal Semantics_ is _First-order Relational Logic_ + * _Formal Verification_ by transforming to verification tools + * Able to transform specifications to OCL?, JML?, Viper??, Spec#?? + * KodKod back-end for _model-finding_, _instance generation_, and _model completion_ (repairing abstract data types in runtime) + * _Runtime checking_ of executable DSLs. + * Persistance of all language extensions into EAnnotations in XMI file in order to maintain portability. + * In the same file, OCLInEcore and AlloyInEcore can be transferred. + + Experiments + =========== + * Harel State Charts + * Choose a largest and most influential modeling language such as a language from UML or SysML + + + * Type System, adapted from ... Fig.3 in 'Featherweight OCL: A Proposal for a Machine-Checked Formal Semantics for OCL 2.5' + + EMF Semantic Errors + =================== + 1. Name Collisions of EClassifiers in EPackages. (ok) + 2. Name Collisions of EStructuralFeatures in Classes. (ok) + 3. Name Collisions of EStructuralFeatures after extending EClass. + 4. Circular Inheritance + 5. EType (in EAttribute, EReference, EOperation, EParameter) referenced to a missing EClassifiers and EReference (ok) + * Checking existence of qualified names which is used as a target in ETypes + 6. Conformance of EOpposites in two EReferences + * A.a = B && B.b = A + * check multiplicities as well??? + 7. Referenced Element but not Imported Package + 8. Collision of Root Package Name and Imported Package. + 9. Visibility Control in everywhere + 10. Type checking using Java compiler + + Editor Features + =============== + + Eclipse + ------- + 1. Syntax Highlighting with different colors for EMF keywords and AlloyInECore keywords + 2. Semantic Code Completion + 3. Error Annotations + 4. Serialization as EAnnotations in ECore file. + 5. Deserialization from ECore file + 6. Outline. + 7. Folding/Unfolding. + + Intellij + -------- + 1. Syntax Highlighting + 2. Semantic Code Completion + 3. Error Annotations + 4. Serialization as EAnnotations in ECore file. + 5. Deserialization from ECore file + 6. Structure + + If referenced element is in the same package, use relative path, do not use qualified name. + When annotation references, always use qualified name. + When editor is opened, at the background create "aie program file" for each imported ecore file. + If a package and a class are in the same package and if they have the same + + * Safe Navigations + * Declaring Null-free Collections in Ecore + * [http://help.eclipse.org/neon/index.jsp?topic=%2Forg.eclipse.ocl.doc%2Fhelp%2FSafeNavigationTutorial.html] + * Java Method Calls for string and integers + * KodKod TotalOrder Relation can be a remedy for ordered sets in ECore + + * [EMF Generics Semantics][http://www.eclipse.org/articles/article.php?file=Article-Defining-Generics-with-UML-Templates/index.html] + * (Set{1, 4, 7, 10}->symmetricDifference(Set{4, 5, 7})) = Set{1, 5, 10} + * ((Set{1, 4, 7, 10}) - Set{4, 7}) = Set{1, 10} + + * ((OrderedSet{12, 9, 6, 3}) - Set{1, 3, 2}) = OrderedSet{12, 9, 6} + * (OrderedSet{'a', 'b', 'c', 'd'}->insertAt(3, 'X')) = OrderedSet{'a', 'b', 'X', 'c', 'd'} + * (OrderedSet{'a', 'b', 'c', 'd'}->subOrderedSet(2, 3)) = OrderedSet{'b', 'c'} + + * (Sequence{'a', 'b', 'c', 'c', 'd', 'e'}->prepend('X')) = Sequence{'X', 'a', 'b', 'c', 'c', 'd', 'e'} + * (Sequence{'a', 'b', 'c', 'c', 'd', 'e'}->append('X')) = Sequence{'a', 'b', 'c', 'c', 'd', 'e', 'X'} + * (Sequence{'a', 'b', 'c', 'c', 'd', 'e'}->subSequence(3, 5)) = Sequence{'c', 'c', 'd'} + * (Sequence{'a', 'b', 'c', 'c', 'd', 'e'}->indexOf('c')) = 3 + + * `nullable` quantifier for eReferences, eAttribute + * inspired from this http://www.eecs.ucf.edu/~leavens/JML//refman/jmlrefman.pdf + * default is `non-null, !nullable` [Page 18] + * modifiers such as ghost??, `model`, instance?? + * `\old()` in `\result` postconditions + * contains and length for collections??? + * Object `Invariant` + * `invariant` must be: + * True at end of constructor. + * _Preserved by each method._ + * `requires` clause: + * Precondition. + * Obligation on callers, after parameter passing + * Assumed by implementor. + * `ensures` clause: + * Postcondition. + * Obligation on implementor, at return. + * Assumed by caller. + * `assignable`, `modifies`, `modifiable` + * Frame axiom. + * _Locations (fields) in pre-state_ + * New object fields not covered. + * Mostly checked statically. + * Assignable is a Shorthand + * `assignable gender; ensures gender.equals(g);` + * `ensures \only_assigned(gender) && gender.equals(g);` + * `assignable \nothing` = `pure` + * `pure` + * _No side effects._ + * Implies `assignable \nothing` + * _Allows method’s use in specifications._ + * Defaults: + * `invariant true;` + * `requires true;` + * `assignable \everything;` + * `ensures true;` + * Model Fields + * Just for specification + * Abstraction of Java Fields + * Value from `represents` + + + + * Field Specification + * Method Specification with `requires` and `ensures` + * inclusion of `assignable` + * `\nothing` + + * keyword `pure` diff --git a/Source/eu.modelwriter.core.alloyinecore/Requirements.ecore b/Source/eu.modelwriter.core.alloyinecore/Requirements.ecore new file mode 100644 index 00000000..8e9ba74d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/Requirements.ecore @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/eu.modelwriter.core.alloyinecore.iml b/Source/eu.modelwriter.core.alloyinecore/eu.modelwriter.core.alloyinecore.iml new file mode 100644 index 00000000..48f8785e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/eu.modelwriter.core.alloyinecore.iml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/ST4-4.0.8.jar b/Source/eu.modelwriter.core.alloyinecore/lib/ST4-4.0.8.jar new file mode 100644 index 00000000..144828ba Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/ST4-4.0.8.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/SatSolvers/libglucose.so b/Source/eu.modelwriter.core.alloyinecore/lib/SatSolvers/libglucose.so new file mode 100755 index 00000000..481ccf23 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/SatSolvers/libglucose.so differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/SatSolvers/liblingeling.so b/Source/eu.modelwriter.core.alloyinecore/lib/SatSolvers/liblingeling.so new file mode 100755 index 00000000..07e0881e Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/SatSolvers/liblingeling.so differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/SatSolvers/libminisat.so b/Source/eu.modelwriter.core.alloyinecore/lib/SatSolvers/libminisat.so new file mode 100755 index 00000000..501baf07 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/SatSolvers/libminisat.so differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/SatSolvers/libminisatprover.so b/Source/eu.modelwriter.core.alloyinecore/lib/SatSolvers/libminisatprover.so new file mode 100755 index 00000000..2f0d6e52 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/SatSolvers/libminisatprover.so differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/SatSolvers/plingeling b/Source/eu.modelwriter.core.alloyinecore/lib/SatSolvers/plingeling new file mode 100755 index 00000000..b9109f8c Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/SatSolvers/plingeling differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/antlr-4.6-complete.jar b/Source/eu.modelwriter.core.alloyinecore/lib/antlr-4.6-complete.jar new file mode 100644 index 00000000..b488881e Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/antlr-4.6-complete.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/antlr-runtime-3.5.2.jar b/Source/eu.modelwriter.core.alloyinecore/lib/antlr-runtime-3.5.2.jar new file mode 100644 index 00000000..d48e3e86 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/antlr-runtime-3.5.2.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/antlr4-4.6.jar b/Source/eu.modelwriter.core.alloyinecore/lib/antlr4-4.6.jar new file mode 100644 index 00000000..33a2b421 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/antlr4-4.6.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/antlr4-maven-plugin-4.6-javadoc.jar b/Source/eu.modelwriter.core.alloyinecore/lib/antlr4-maven-plugin-4.6-javadoc.jar new file mode 100644 index 00000000..c9f19f8f Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/antlr4-maven-plugin-4.6-javadoc.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/antlr4-maven-plugin-4.6.jar b/Source/eu.modelwriter.core.alloyinecore/lib/antlr4-maven-plugin-4.6.jar new file mode 100644 index 00000000..37fb543b Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/antlr4-maven-plugin-4.6.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/antlr4-runtime-4.6-javadoc.jar b/Source/eu.modelwriter.core.alloyinecore/lib/antlr4-runtime-4.6-javadoc.jar new file mode 100644 index 00000000..4625791e Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/antlr4-runtime-4.6-javadoc.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/antlr4-runtime-4.6.jar b/Source/eu.modelwriter.core.alloyinecore/lib/antlr4-runtime-4.6.jar new file mode 100644 index 00000000..3c670462 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/antlr4-runtime-4.6.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/backport-util-concurrent-3.1.jar b/Source/eu.modelwriter.core.alloyinecore/lib/backport-util-concurrent-3.1.jar new file mode 100644 index 00000000..3a4c2797 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/backport-util-concurrent-3.1.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/classworlds-1.1-alpha-2.jar b/Source/eu.modelwriter.core.alloyinecore/lib/classworlds-1.1-alpha-2.jar new file mode 100644 index 00000000..1208b481 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/classworlds-1.1-alpha-2.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/darwin_x86_64.zip b/Source/eu.modelwriter.core.alloyinecore/lib/darwin_x86_64.zip new file mode 100644 index 00000000..2120adc7 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/darwin_x86_64.zip differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/examples.jar b/Source/eu.modelwriter.core.alloyinecore/lib/examples.jar new file mode 100644 index 00000000..6116b08a Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/examples.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/guava-21.0-javadoc.jar b/Source/eu.modelwriter.core.alloyinecore/lib/guava-21.0-javadoc.jar new file mode 100644 index 00000000..b54313cb Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/guava-21.0-javadoc.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/guava-21.0.jar b/Source/eu.modelwriter.core.alloyinecore/lib/guava-21.0.jar new file mode 100644 index 00000000..06181959 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/guava-21.0.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/hamcrest-core-1.3.jar b/Source/eu.modelwriter.core.alloyinecore/lib/hamcrest-core-1.3.jar new file mode 100644 index 00000000..9d5fe16e Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/hamcrest-core-1.3.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/javax.json-1.0.4.jar b/Source/eu.modelwriter.core.alloyinecore/lib/javax.json-1.0.4.jar new file mode 100644 index 00000000..09967d81 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/javax.json-1.0.4.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/junit-3.8.1.jar b/Source/eu.modelwriter.core.alloyinecore/lib/junit-3.8.1.jar new file mode 100644 index 00000000..674d71e8 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/junit-3.8.1.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/junit-4.12-javadoc.jar b/Source/eu.modelwriter.core.alloyinecore/lib/junit-4.12-javadoc.jar new file mode 100644 index 00000000..f7bdb82a Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/junit-4.12-javadoc.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/junit-4.12.jar b/Source/eu.modelwriter.core.alloyinecore/lib/junit-4.12.jar new file mode 100644 index 00000000..3a7fc266 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/junit-4.12.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/kodkod-2.1.zip b/Source/eu.modelwriter.core.alloyinecore/lib/kodkod-2.1.zip new file mode 100644 index 00000000..e8acf03c Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/kodkod-2.1.zip differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/kodkod-javadoc.zip b/Source/eu.modelwriter.core.alloyinecore/lib/kodkod-javadoc.zip new file mode 100644 index 00000000..eb874f66 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/kodkod-javadoc.zip differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/kodkod.jar b/Source/eu.modelwriter.core.alloyinecore/lib/kodkod.jar new file mode 100644 index 00000000..4b1988c1 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/kodkod.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/kodkod.tar.gz b/Source/eu.modelwriter.core.alloyinecore/lib/kodkod.tar.gz new file mode 100644 index 00000000..1789238c Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/kodkod.tar.gz differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/maven-artifact-3.0.5.jar b/Source/eu.modelwriter.core.alloyinecore/lib/maven-artifact-3.0.5.jar new file mode 100644 index 00000000..4e0600cd Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/maven-artifact-3.0.5.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/maven-model-3.0.5.jar b/Source/eu.modelwriter.core.alloyinecore/lib/maven-model-3.0.5.jar new file mode 100644 index 00000000..e7191ec2 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/maven-model-3.0.5.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/maven-plugin-annotations-3.2.jar b/Source/eu.modelwriter.core.alloyinecore/lib/maven-plugin-annotations-3.2.jar new file mode 100644 index 00000000..acf6247c Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/maven-plugin-annotations-3.2.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/maven-plugin-api-3.0.5.jar b/Source/eu.modelwriter.core.alloyinecore/lib/maven-plugin-api-3.0.5.jar new file mode 100644 index 00000000..1570c2d0 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/maven-plugin-api-3.0.5.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/maven-plugin-registry-2.2.1.jar b/Source/eu.modelwriter.core.alloyinecore/lib/maven-plugin-registry-2.2.1.jar new file mode 100644 index 00000000..1b87d9a0 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/maven-plugin-registry-2.2.1.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/maven-profile-2.2.1.jar b/Source/eu.modelwriter.core.alloyinecore/lib/maven-profile-2.2.1.jar new file mode 100644 index 00000000..5394d323 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/maven-profile-2.2.1.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/maven-project-2.2.1.jar b/Source/eu.modelwriter.core.alloyinecore/lib/maven-project-2.2.1.jar new file mode 100644 index 00000000..63b9ebd6 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/maven-project-2.2.1.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/maven-repository-metadata-3.3.9.jar b/Source/eu.modelwriter.core.alloyinecore/lib/maven-repository-metadata-3.3.9.jar new file mode 100644 index 00000000..d1129e06 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/maven-repository-metadata-3.3.9.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/maven-settings-3.3.9.jar b/Source/eu.modelwriter.core.alloyinecore/lib/maven-settings-3.3.9.jar new file mode 100644 index 00000000..b3e2dc21 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/maven-settings-3.3.9.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/org.abego.treelayout.core-1.0.3.jar b/Source/eu.modelwriter.core.alloyinecore/lib/org.abego.treelayout.core-1.0.3.jar new file mode 100644 index 00000000..d78492b6 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/org.abego.treelayout.core-1.0.3.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/org.eclipse.emf.common.source_2.12.0.v20160420-0247.jar b/Source/eu.modelwriter.core.alloyinecore/lib/org.eclipse.emf.common.source_2.12.0.v20160420-0247.jar new file mode 100644 index 00000000..edd5f852 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/org.eclipse.emf.common.source_2.12.0.v20160420-0247.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/org.eclipse.emf.common_2.12.0.v20160420-0247.jar b/Source/eu.modelwriter.core.alloyinecore/lib/org.eclipse.emf.common_2.12.0.v20160420-0247.jar new file mode 100644 index 00000000..752bcacb Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/org.eclipse.emf.common_2.12.0.v20160420-0247.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/org.eclipse.emf.ecore.source_2.12.0.v20160420-0247.jar b/Source/eu.modelwriter.core.alloyinecore/lib/org.eclipse.emf.ecore.source_2.12.0.v20160420-0247.jar new file mode 100644 index 00000000..4484a465 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/org.eclipse.emf.ecore.source_2.12.0.v20160420-0247.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/org.eclipse.emf.ecore.xmi.source_2.12.0.v20160420-0247.jar b/Source/eu.modelwriter.core.alloyinecore/lib/org.eclipse.emf.ecore.xmi.source_2.12.0.v20160420-0247.jar new file mode 100644 index 00000000..9220123f Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/org.eclipse.emf.ecore.xmi.source_2.12.0.v20160420-0247.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/org.eclipse.emf.ecore.xmi_2.12.0.v20160420-0247.jar b/Source/eu.modelwriter.core.alloyinecore/lib/org.eclipse.emf.ecore.xmi_2.12.0.v20160420-0247.jar new file mode 100644 index 00000000..89e6f33f Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/org.eclipse.emf.ecore.xmi_2.12.0.v20160420-0247.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/org.eclipse.emf.ecore_2.12.0.v20160420-0247.jar b/Source/eu.modelwriter.core.alloyinecore/lib/org.eclipse.emf.ecore_2.12.0.v20160420-0247.jar new file mode 100644 index 00000000..34179a30 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/org.eclipse.emf.ecore_2.12.0.v20160420-0247.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/org.sat4j.core-2.3.1-javadoc.jar b/Source/eu.modelwriter.core.alloyinecore/lib/org.sat4j.core-2.3.1-javadoc.jar new file mode 100644 index 00000000..f2594396 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/org.sat4j.core-2.3.1-javadoc.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/org.sat4j.core-2.3.1.jar b/Source/eu.modelwriter.core.alloyinecore/lib/org.sat4j.core-2.3.1.jar new file mode 100644 index 00000000..60db98d6 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/org.sat4j.core-2.3.1.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/plexus-build-api-0.0.7.jar b/Source/eu.modelwriter.core.alloyinecore/lib/plexus-build-api-0.0.7.jar new file mode 100644 index 00000000..3a01264e Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/plexus-build-api-0.0.7.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/plexus-classworlds-2.5.2.jar b/Source/eu.modelwriter.core.alloyinecore/lib/plexus-classworlds-2.5.2.jar new file mode 100644 index 00000000..2560b3ff Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/plexus-classworlds-2.5.2.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/plexus-compiler-api-2.2.jar b/Source/eu.modelwriter.core.alloyinecore/lib/plexus-compiler-api-2.2.jar new file mode 100644 index 00000000..5f009ed0 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/plexus-compiler-api-2.2.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/plexus-component-annotations-1.6.jar b/Source/eu.modelwriter.core.alloyinecore/lib/plexus-component-annotations-1.6.jar new file mode 100644 index 00000000..22e433d9 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/plexus-component-annotations-1.6.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/plexus-container-default-1.0-alpha-9-stable-1.jar b/Source/eu.modelwriter.core.alloyinecore/lib/plexus-container-default-1.0-alpha-9-stable-1.jar new file mode 100644 index 00000000..d205236a Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/plexus-container-default-1.0-alpha-9-stable-1.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/plexus-interpolation-1.11.jar b/Source/eu.modelwriter.core.alloyinecore/lib/plexus-interpolation-1.11.jar new file mode 100644 index 00000000..c937688b Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/plexus-interpolation-1.11.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/plexus-utils-3.0.15.jar b/Source/eu.modelwriter.core.alloyinecore/lib/plexus-utils-3.0.15.jar new file mode 100644 index 00000000..feab196e Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/plexus-utils-3.0.15.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/sisu-guava-0.9.9.jar b/Source/eu.modelwriter.core.alloyinecore/lib/sisu-guava-0.9.9.jar new file mode 100644 index 00000000..460abed7 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/sisu-guava-0.9.9.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/sisu-guice-3.1.0-no_aop.jar b/Source/eu.modelwriter.core.alloyinecore/lib/sisu-guice-3.1.0-no_aop.jar new file mode 100644 index 00000000..4c84b3e1 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/sisu-guice-3.1.0-no_aop.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/sisu-inject-bean-2.3.0.jar b/Source/eu.modelwriter.core.alloyinecore/lib/sisu-inject-bean-2.3.0.jar new file mode 100644 index 00000000..ebf244bb Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/sisu-inject-bean-2.3.0.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/sisu-inject-plexus-2.3.0.jar b/Source/eu.modelwriter.core.alloyinecore/lib/sisu-inject-plexus-2.3.0.jar new file mode 100644 index 00000000..03950479 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/sisu-inject-plexus-2.3.0.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/lib/wagon-provider-api-2.10.jar b/Source/eu.modelwriter.core.alloyinecore/lib/wagon-provider-api-2.10.jar new file mode 100644 index 00000000..454d3cde Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/lib/wagon-provider-api-2.10.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/libglucose.so b/Source/eu.modelwriter.core.alloyinecore/libglucose.so new file mode 100755 index 00000000..481ccf23 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/libglucose.so differ diff --git a/Source/eu.modelwriter.core.alloyinecore/liblingeling.so b/Source/eu.modelwriter.core.alloyinecore/liblingeling.so new file mode 100755 index 00000000..07e0881e Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/liblingeling.so differ diff --git a/Source/eu.modelwriter.core.alloyinecore/libminisat.so b/Source/eu.modelwriter.core.alloyinecore/libminisat.so new file mode 100755 index 00000000..501baf07 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/libminisat.so differ diff --git a/Source/eu.modelwriter.core.alloyinecore/libminisatprover.so b/Source/eu.modelwriter.core.alloyinecore/libminisatprover.so new file mode 100755 index 00000000..2f0d6e52 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/libminisatprover.so differ diff --git a/Source/eu.modelwriter.core.alloyinecore/out/artifacts/My.ecore b/Source/eu.modelwriter.core.alloyinecore/out/artifacts/My.ecore new file mode 100644 index 00000000..96bf55a4 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/out/artifacts/My.ecore @@ -0,0 +1,16 @@ + + + +
+ + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/out/artifacts/antlr-4.6-complete.jar b/Source/eu.modelwriter.core.alloyinecore/out/artifacts/antlr-4.6-complete.jar new file mode 100644 index 00000000..b488881e Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/out/artifacts/antlr-4.6-complete.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/out/artifacts/eu.modelwriter.core.alloyinecore.jar b/Source/eu.modelwriter.core.alloyinecore/out/artifacts/eu.modelwriter.core.alloyinecore.jar new file mode 100644 index 00000000..10450243 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/out/artifacts/eu.modelwriter.core.alloyinecore.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/out/artifacts/guava-21.0.jar b/Source/eu.modelwriter.core.alloyinecore/out/artifacts/guava-21.0.jar new file mode 100644 index 00000000..06181959 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/out/artifacts/guava-21.0.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/out/artifacts/kodkod.jar b/Source/eu.modelwriter.core.alloyinecore/out/artifacts/kodkod.jar new file mode 100644 index 00000000..4b1988c1 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/out/artifacts/kodkod.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/out/artifacts/org.eclipse.emf.common_2.12.0.v20160420-0247.jar b/Source/eu.modelwriter.core.alloyinecore/out/artifacts/org.eclipse.emf.common_2.12.0.v20160420-0247.jar new file mode 100644 index 00000000..752bcacb Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/out/artifacts/org.eclipse.emf.common_2.12.0.v20160420-0247.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/out/artifacts/org.eclipse.emf.ecore.xmi_2.12.0.v20160420-0247.jar b/Source/eu.modelwriter.core.alloyinecore/out/artifacts/org.eclipse.emf.ecore.xmi_2.12.0.v20160420-0247.jar new file mode 100644 index 00000000..89e6f33f Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/out/artifacts/org.eclipse.emf.ecore.xmi_2.12.0.v20160420-0247.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/out/artifacts/org.eclipse.emf.ecore_2.12.0.v20160420-0247.jar b/Source/eu.modelwriter.core.alloyinecore/out/artifacts/org.eclipse.emf.ecore_2.12.0.v20160420-0247.jar new file mode 100644 index 00000000..34179a30 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/out/artifacts/org.eclipse.emf.ecore_2.12.0.v20160420-0247.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/out/artifacts/org.sat4j.core-2.3.1.jar b/Source/eu.modelwriter.core.alloyinecore/out/artifacts/org.sat4j.core-2.3.1.jar new file mode 100644 index 00000000..60db98d6 Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/out/artifacts/org.sat4j.core-2.3.1.jar differ diff --git a/Source/eu.modelwriter.core.alloyinecore/plingeling b/Source/eu.modelwriter.core.alloyinecore/plingeling new file mode 100755 index 00000000..b9109f8c Binary files /dev/null and b/Source/eu.modelwriter.core.alloyinecore/plingeling differ diff --git a/Source/eu.modelwriter.core.alloyinecore/pom.xml b/Source/eu.modelwriter.core.alloyinecore/pom.xml new file mode 100644 index 00000000..c083cb74 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/pom.xml @@ -0,0 +1,103 @@ + + + 4.0.0 + eu.modelwriter.core + alloyinecore + 1.0-SNAPSHOT + jar + AlloyInEcore + http://modelwriter.eu + + + junit + junit + 4.12 + test + + + com.google.guava + guava + 21.0 + compile + + + + + + + + + + + + + + + + + + + + + org.sat4j + org.sat4j.core + 2.3.1 + compile + + + + + + + + + org.antlr + antlr4 + 4.6 + compile + + + kodkod + kodkod + 2.1 + system + ${project.basedir}/lib/kodkod.jar + + + org.eclipse.emf + org.eclipse.emf.ecore + 2.12.0 + system + ${project.basedir}/lib/org.eclipse.emf.ecore_2.12.0.v20160420-0247.jar + + + org.eclipse.emf + org.eclipse.emf.common + 2.12.0 + system + ${project.basedir}/lib/org.eclipse.emf.common_2.12.0.v20160420-0247.jar + + + org.eclipse.emf + org.eclipse.emf.ecore.xmi + 2.12.0 + system + ${project.basedir}/lib/org.eclipse.emf.ecore.xmi_2.12.0.v20160420-0247.jar + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.0 + + 1.8 + 1.8 + + + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/AlloyInECoreFrontEnd_Test.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/AlloyInECoreFrontEnd_Test.java new file mode 100644 index 00000000..1aecc4b8 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/AlloyInECoreFrontEnd_Test.java @@ -0,0 +1,163 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore;/* + * The MIT License (MIT) + * + * Copyright (c) 2016, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser; +import eu.modelwriter.core.alloyinecore.recognizer.UnderlineErrorListener; +import eu.modelwriter.core.alloyinecore.typechecking.TypeChecker; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.atn.PredictionMode; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.List; + + +public class AlloyInECoreFrontEnd_Test { + + public static void main(final String[] args) { +// Model trySinglemodule = new Model("programs/AlloyInECore/Templates.recore"); +// Model tryECoreModule = new Model("http://www.eclipse.org/emf/2002/Ecore"); + + + ANTLRInputStream input = null; + final File file = new File("./src/test/resources/AlloyInECore/Generics1.recore"); + try { + input = new ANTLRFileStream(file.getAbsolutePath()); + } catch (final IOException e) { + e.printStackTrace(); + } + final AlloyInEcoreLexer lexer = new AlloyInEcoreLexer(input); + final CommonTokenStream tokens = new CommonTokenStream(lexer); + final AlloyInEcoreParser parser = new AlloyInEcoreParser(tokens); + + parser.removeErrorListeners(); + parser.addErrorListener(new UnderlineErrorListener()); + parser.setErrorHandler(new DefaultErrorStrategy()); + parser.getInterpreter().setPredictionMode(PredictionMode.LL); // try full LL(*) + parser.model(); +// parser.getInterpreter().setPredictionMode(PredictionMode.SLL); // try with simpler/faster SLL(*) +// // we don't want error messages or recovery during first try +// parser.removeErrorListeners(); +// parser.setErrorHandler(new BailErrorStrategy()); +// try { +// parser.model(); +// // if we get here, there was no syntax error and SLL(*) was enough; +// // there is no need to try full LL(*) +// } catch (RuntimeException ex) { +// if (ex.getClass() == RuntimeException.class && +// ex.getCause() instanceof RecognitionException) { +// // The BailErrorStrategy wraps the RecognitionExceptions in +// // RuntimeExceptions so we have to make sure we're detecting +// // a true RecognitionException not some other kind +// tokens.reset(); // rewind input stream +// // back to standard listeners/handlers +// parser.addErrorListener(new UnderlineErrorListener()); +// parser.setErrorHandler(new DefaultErrorStrategy()); +// parser.getInterpreter().setPredictionMode(PredictionMode.LL); // try full LL(*) +// parser.model(); +// } +// } + parser.saveResource(file.getName().substring(0, file.getName().indexOf(".")), "./src/test/resources/out/"); + + TypeChecker typeChecker = new TypeChecker(); + typeChecker.check(parser.model); + +// Utilities.showParseTree(parser, tree); + +// try { +// final KodkodTranslator translator = new KodkodTranslator(parser.bounds); +// final Formula f = (Formula) translator.visit(tree); +// final Solver solver = new Solver(); +// solver.options().setSolver(SATFactory.DefaultSAT4J); +// solver.options().setSymmetryBreaking(20); +// System.out.println("Symmetry Breaking is set to " + solver.options().symmetryBreaking()); +// System.out.println(PrettyPrinter.print(f, 2)); +// // final Solution s = solver.solve(f, parser.bounds); +// +// final Iterator solIter = solver.solveAll(f, parser.bounds); +// int i = 1; +// while (solIter.hasNext()) { +// System.out.println("**SOLUTION " + i + " **"); +// Solution sol = solIter.next(); +// System.out.println(sol); +// i++; +// } +// +// // System.out.println(s); +// } catch (HigherOrderDeclException e) { +// e.printStackTrace(); +// } catch (UnboundLeafException e) { +// e.printStackTrace(); +// } catch (AbortedException e) { +// e.printStackTrace(); +// } + + /***********************************/ + + + } + + public static class VerboseListener extends BaseErrorListener { + @Override + public void syntaxError(Recognizer recognizer, + Object offendingSymbol, + int line, int charPositionInLine, + String msg, + RecognitionException e) { + List stack = ((Parser) recognizer).getRuleInvocationStack(); + Collections.reverse(stack); + System.err.println("rule stack: " + stack); + System.err.println("line " + line + ":" + charPositionInLine + " at " + + offendingSymbol + ": " + msg); + } + } + + +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/AlloyInECoreImportsFrontEnd_Test.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/AlloyInECoreImportsFrontEnd_Test.java new file mode 100644 index 00000000..c6585371 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/AlloyInECoreImportsFrontEnd_Test.java @@ -0,0 +1,136 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore; + +import eu.modelwriter.core.alloyinecore.recognizer.imports.ImportsLexer; +import eu.modelwriter.core.alloyinecore.recognizer.imports.ImportsParser; +import eu.modelwriter.core.alloyinecore.recognizer.UnderlineErrorListener; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.atn.PredictionMode; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.List; + + +public class AlloyInECoreImportsFrontEnd_Test { + + public static class VerboseListener extends BaseErrorListener { + @Override + public void syntaxError(Recognizer recognizer, + Object offendingSymbol, + int line, int charPositionInLine, + String msg, + RecognitionException e) { + List stack = ((Parser)recognizer).getRuleInvocationStack(); + Collections.reverse(stack); + System.err.println("rule stack: "+stack); + System.err.println("line "+line+":"+charPositionInLine+" at "+ + offendingSymbol+": "+msg); + } + } + + + public static void main(final String[] args) { + + ANTLRInputStream input = null; + //"./src/test/resources/AlloyInECore/Generics1.recore" + final File file = new File("./src/main/resources/Ecore.recore"); + try { + input = new ANTLRFileStream(file.getAbsolutePath()); + } catch (final IOException e) { + e.printStackTrace(); + } + final ImportsLexer lexer = new ImportsLexer(input); + final CommonTokenStream tokens = new CommonTokenStream(lexer); + final ImportsParser parser = new ImportsParser(tokens); +// parser.removeErrorListeners(); +// parser.addErrorListener(new UnderlineErrorListener()); +// parser.importedFile(); + + parser.getInterpreter().setPredictionMode(PredictionMode.SLL); // try with simpler/faster SLL(*) +// we don't want error messages or recovery during first try + parser.removeErrorListeners(); + parser.setErrorHandler(new BailErrorStrategy()); + try { + parser.importModel(null); + // if we get here, there was no syntax error and SLL(*) was enough; +// there is no need to try full LL(*) + } + catch (RuntimeException ex) { + if (ex.getClass() == RuntimeException.class && + ex.getCause() instanceof RecognitionException) + { + // The BailErrorStrategy wraps the RecognitionExceptions in + // RuntimeExceptions so we have to make sure we're detecting + // a true RecognitionException not some other kind + tokens.reset(); // rewind input stream + // back to standard listeners/handlers + parser.addErrorListener(new UnderlineErrorListener()); + parser.setErrorHandler(new DefaultErrorStrategy()); + parser.getInterpreter().setPredictionMode(PredictionMode.LL); // try full LL(*) + parser.importModel(null); + } + } + + +// Utilities.showParseTree(parser, tree); + +// try { +// final KodkodTranslator translator = new KodkodTranslator(parser.bounds); +// final Formula f = (Formula) translator.visit(tree); +// final Solver solver = new Solver(); +// solver.options().setSolver(SATFactory.DefaultSAT4J); +// solver.options().setSymmetryBreaking(20); +// System.out.println("Symmetry Breaking is set to " + solver.options().symmetryBreaking()); +// System.out.println(PrettyPrinter.print(f, 2)); +// // final Solution s = solver.solve(f, parser.bounds); +// +// final Iterator solIter = solver.solveAll(f, parser.bounds); +// int i = 1; +// while (solIter.hasNext()) { +// System.out.println("**SOLUTION " + i + " **"); +// Solution sol = solIter.next(); +// System.out.println(sol); +// i++; +// } +// +// // System.out.println(s); +// } catch (HigherOrderDeclException e) { +// e.printStackTrace(); +// } catch (UnboundLeafException e) { +// e.printStackTrace(); +// } catch (AbortedException e) { +// e.printStackTrace(); +// } + + /***********************************/ + + + } + + +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/AlloyInECoreInstanceFrontEnd_Test.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/AlloyInECoreInstanceFrontEnd_Test.java new file mode 100644 index 00000000..90d0b26e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/AlloyInECoreInstanceFrontEnd_Test.java @@ -0,0 +1,160 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore;/* + * The MIT License (MIT) + * + * Copyright (c) 2016, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser; +import eu.modelwriter.core.alloyinecore.recognizer.UnderlineErrorListener; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.atn.PredictionMode; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.List; + + +public class AlloyInECoreInstanceFrontEnd_Test { + + public static void main(final String[] args) { +// Model trySinglemodule = new Model("programs/AlloyInECore/Templates.recore"); +// Model tryECoreModule = new Model("http://www.eclipse.org/emf/2002/Ecore"); + + + ANTLRInputStream input = null; + final File file = new File("./src/test/resources/InstanceTestFolder/Instance.requirement"); + try { + input = new ANTLRFileStream(file.getAbsolutePath()); + } catch (final IOException e) { + e.printStackTrace(); + } + final AlloyInEcoreLexer lexer = new AlloyInEcoreLexer(input); + final CommonTokenStream tokens = new CommonTokenStream(lexer); + final AlloyInEcoreParser parser = new AlloyInEcoreParser(tokens); + + parser.removeErrorListeners(); + parser.addErrorListener(new UnderlineErrorListener()); + parser.setErrorHandler(new DefaultErrorStrategy()); + parser.getInterpreter().setPredictionMode(PredictionMode.LL); // try full LL(*) + parser.instance(null); + +// parser.getInterpreter().setPredictionMode(PredictionMode.SLL); // try with simpler/faster SLL(*) +// // we don't want error messages or recovery during first try +// parser.removeErrorListeners(); +// parser.setErrorHandler(new BailErrorStrategy()); +// try { +// parser.model(); +// // if we get here, there was no syntax error and SLL(*) was enough; +// // there is no need to try full LL(*) +// } catch (RuntimeException ex) { +// if (ex.getClass() == RuntimeException.class && +// ex.getCause() instanceof RecognitionException) { +// // The BailErrorStrategy wraps the RecognitionExceptions in +// // RuntimeExceptions so we have to make sure we're detecting +// // a true RecognitionException not some other kind +// tokens.reset(); // rewind input stream +// // back to standard listeners/handlers +// parser.addErrorListener(new UnderlineErrorListener()); +// parser.setErrorHandler(new DefaultErrorStrategy()); +// parser.getInterpreter().setPredictionMode(PredictionMode.LL); // try full LL(*) +// parser.model(); +// } +// } +// parser.saveResource(file.getName().substring(0, file.getName().indexOf(".")), "./src/test/resources/out/"); + +// Utilities.showParseTree(parser, tree); + +// try { +// final KodkodTranslator translator = new KodkodTranslator(parser.bounds); +// final Formula f = (Formula) translator.visit(tree); +// final Solver solver = new Solver(); +// solver.options().setSolver(SATFactory.DefaultSAT4J); +// solver.options().setSymmetryBreaking(20); +// System.out.println("Symmetry Breaking is set to " + solver.options().symmetryBreaking()); +// System.out.println(PrettyPrinter.print(f, 2)); +// // final Solution s = solver.solve(f, parser.bounds); +// +// final Iterator solIter = solver.solveAll(f, parser.bounds); +// int i = 1; +// while (solIter.hasNext()) { +// System.out.println("**SOLUTION " + i + " **"); +// Solution sol = solIter.next(); +// System.out.println(sol); +// i++; +// } +// +// // System.out.println(s); +// } catch (HigherOrderDeclException e) { +// e.printStackTrace(); +// } catch (UnboundLeafException e) { +// e.printStackTrace(); +// } catch (AbortedException e) { +// e.printStackTrace(); +// } + + /***********************************/ + + + } + + public static class VerboseListener extends BaseErrorListener { + @Override + public void syntaxError(Recognizer recognizer, + Object offendingSymbol, + int line, int charPositionInLine, + String msg, + RecognitionException e) { + List stack = ((Parser) recognizer).getRuleInvocationStack(); + Collections.reverse(stack); + System.err.println("rule stack: " + stack); + System.err.println("line " + line + ":" + charPositionInLine + " at " + + offendingSymbol + ": " + msg); + } + } + + +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/KodKodFrontEnd_Test.jav b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/KodKodFrontEnd_Test.jav new file mode 100644 index 00000000..3f78de93 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/KodKodFrontEnd_Test.jav @@ -0,0 +1,149 @@ + +/* + * The MIT License (MIT) + * + * Copyright (c) 2016, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.interpreter; + +import Utilities; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser; +import kodkod.ast.Formula; +import kodkod.engine.AbortedException; +import kodkod.engine.Solution; +import kodkod.engine.Solver; +import kodkod.engine.fol2sat.HigherOrderDeclException; +import kodkod.engine.fol2sat.UnboundLeafException; +import kodkod.engine.satlab.SATFactory; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.tree.ParseTree; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + + +public class KodKodFrontEnd_Test { + + public static class VerboseListener extends BaseErrorListener { + @Override + public void syntaxError(Recognizer recognizer, + Object offendingSymbol, + int line, int charPositionInLine, + String msg, + RecognitionException e) { + List stack = ((Parser)recognizer).getRuleInvocationStack(); + Collections.reverse(stack); + System.err.println("rule stack: "+stack); + System.err.println("line "+line+":"+charPositionInLine+" at "+ + offendingSymbol+": "+msg); + } + } + + public static class UnderlineListener extends BaseErrorListener { + public void syntaxError(Recognizer recognizer, + Object offendingSymbol, + int line, int charPositionInLine, + String msg, + RecognitionException e) { + underlineError(recognizer, (Token) offendingSymbol, line, charPositionInLine, msg); + } + + protected void underlineError(Recognizer recognizer, + Token offendingToken, int line, + int charPositionInLine, String msg) { + CommonTokenStream tokens = (CommonTokenStream) recognizer.getInputStream(); + String input = tokens.getTokenSource().getInputStream().toString(); + String[] lines = input.split("\n"); + String errorLine = lines[line - 1]; + System.err.println("line " + line + ":" + charPositionInLine + " " + msg); + System.err.println(errorLine); + + + for (int i = 0; i < charPositionInLine; i++) System.err.print(" "); + + int start = offendingToken.getStartIndex(); + int stop = offendingToken.getStopIndex(); + + if (start >= 0 && stop >= 0) { + for (int i = start; i <= stop; i++) System.err.print("^"); + } + System.err.println(); + } + } + + + public static void main(final String[] args) { + ANTLRInputStream input = null; + final File file = new File("./src/test/resources/AlloyInECore/Filesystem.kodkod"); + try { + input = new ANTLRFileStream(file.getAbsolutePath()); + } catch (final IOException e) { + e.printStackTrace(); + } + final AlloyInEcoreLexer lexer = new AlloyInEcoreLexer(input); + final CommonTokenStream tokens = new CommonTokenStream(lexer); + final AlloyInEcoreParser parser = new AlloyInEcoreParser(tokens); + parser.removeErrorListeners(); // remove ConsoleErrorListener +// parser.addErrorListener(new VerboseListener()); + parser.addErrorListener(new UnderlineListener()); + final ParseTree tree = parser.problem(); + Utilities.showParseTree(parser, tree); + + try { + final KodkodTranslator translator = new KodkodTranslator(parser.bounds); + final Formula f = (Formula) translator.visit(tree); + final Solver solver = new Solver(); + solver.options().setSolver(SATFactory.MiniSat); + solver.options().setSymmetryBreaking(20); + System.out.println("Symmetry Breaking is set to " + solver.options().symmetryBreaking()); +// System.out.println(PrettyPrinter.print(f, 2)); + // final Solution s = solver.solve(f, parser.bounds); + + final Iterator solIter = solver.solveAll(f, parser.bounds); + int i = 1; + while (solIter.hasNext()) { + System.out.println("**SOLUTION " + i + " **"); + Solution sol = solIter.next(); + System.out.println(sol); + i++; + } + + // System.out.println(s); + } catch (HigherOrderDeclException e) { + e.printStackTrace(); + } catch (UnboundLeafException e) { + e.printStackTrace(); + } catch (AbortedException e) { + e.printStackTrace(); + } + + /***********************************/ + + + } + + +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/instanceImport/InstanceImport.g4 b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/instanceImport/InstanceImport.g4 new file mode 100644 index 00000000..2258e7c2 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/instanceImport/InstanceImport.g4 @@ -0,0 +1,98 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +grammar InstanceImport; + +instance : + .*? model (rootObject= eObject | ';') + ; + +model: + ('model') (name= unrestrictedName ':')? ownedPathName= SINGLE_QUOTED_STRING + ; + +eObject: + name= pathName id= value? ('{' slot+= content (',' slot+= content)* '}' | ';') ; + +content: + name= unrestrictedName (':' (dataValue | '{' eObject* '}' | objectReference))?; + +dataValue: value | multiValueData; + +multiValueData: '[' dataValue (',' dataValue)* ']' ; + +objectReference: pathName | ('[' pathName (',' pathName)* ']'); + +pathName: firstSegment= unrestrictedName ('.' index= INT)? (midSegments+= segment* lastSegment= segment)? ; + +segment:'::' '@'? name= unrestrictedName ('.' index= INT)?; + +value: + identifier + | numericValue + | stringValue + | charValue + | booleanValue + | nullValue + ; + +unrestrictedName: + identifier + | 'import' + | 'model' +; + +booleanValue: 'true' | 'false'; + +numericValue: ('+' | '-')? INT? '.'? INT ; + +identifier: IDENTIFIER; + +stringValue: DOUBLE_QUOTED_STRING; + +charValue: SINGLE_CHARACTER; + +nullValue: 'null'; + +INT : DIGIT+ ; + +IDENTIFIER : (UNDERSCORE | LETTER) (LETTER | APOSTROPHE | DIGIT | UNDERSCORE | DOLLAR)* ; +SINGLE_CHARACTER: '\'' ~['\\] '\''; +DOUBLE_QUOTED_STRING: '"' ( ESCAPED_CHARACTER | ~('\\' | '"' ) )* '"' ; +SINGLE_QUOTED_STRING: '\'' ( ESCAPED_CHARACTER | ~('\'' | '\\') )* '\'' ; + + +fragment LETTER: [a-zA-Z]; +fragment DIGITS : DIGIT+ ; +fragment DIGIT: [0-9]; +fragment ESCAPED_CHARACTER: '\\' ('b' | 't' | 'n' | 'f' | 'r' | 'u' | '"' | '\'' | '\\'); +fragment UNDERSCORE: '_'; +fragment APOSTROPHE: '\''; +fragment DOLLAR: '$'; +fragment MINUS: '-'; +ML_SINGLE_QUOTED_STRING : '\'' .*? '\'' -> skip; +MULTILINE_COMMENT : '/*' .*? '*/' -> skip; +SINGLELINE_COMMENT : '--' .*? '\r'? '\n' -> skip; + +WS : [ \r\t\n]+ -> skip ; \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/internal/AIEConstants.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/internal/AIEConstants.java new file mode 100644 index 00000000..11e55986 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/internal/AIEConstants.java @@ -0,0 +1,71 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.internal; + +public enum AIEConstants { + VISIBILITY, + INTERFACE, + STATIC, + PRIMITIVE, + SERIALIZABLE, + CALLABLE, + MESSAGE, + FORMULA, + EXPRESSION, + MODEL, + GHOST, + NAME, + DERIVED, + NOT_DERIVED, + ORDERED, + NOT_ORDERED, + UNIQUE, + NOT_UNIQUE, + ID, + NOT_ID, + READONLY, + TRANSIENT, + UNSETTABLE, + NOT_UNSETTABLE, + VOLATILE, + COMPOSES, + NOT_COMPOSES, + NULLABLE, + RESOLVE, + NOT_RESOLVE, + NOT_SERIALIZABLE, + SOURCE; + + public static final String SEPARATOR = "::"; + + @Override + public String toString() { + return super.toString().toLowerCase().replaceAll("not_", "!"); + } + + public static AIEConstants getValue(final String arg0) { + return AIEConstants.valueOf(arg0.replaceAll("!", "not_").toUpperCase()); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/internal/AnnotationSources.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/internal/AnnotationSources.java new file mode 100644 index 00000000..71a3acef --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/internal/AnnotationSources.java @@ -0,0 +1,145 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.internal; + +import java.util.List; +import java.util.stream.Collectors; + +import org.eclipse.emf.ecore.EAnnotation; +import org.eclipse.emf.ecore.EDataType; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.ETypedElement; + +public interface AnnotationSources { + + String BASE = "http://www.modelwriter.eu/alloyinecore"; + String IMPORT = AnnotationSources.BASE + "/import"; + String MODULE = AnnotationSources.BASE + "/model"; + String OPTIONS = AnnotationSources.BASE + "/options"; + String SOURCE = AnnotationSources.BASE + "/source"; + + String VISIBILITY = AnnotationSources.BASE + "/visibility"; + String STATIC = AnnotationSources.BASE + "/static"; + String QUALIFIER = AnnotationSources.BASE + "/qualifier"; + String NULLABLE = AnnotationSources.BASE + "/nullable"; + String MODEL = AnnotationSources.BASE + "/model"; + String GHOST = AnnotationSources.BASE + "/ghost"; + + String ATTR_EXPRESSIONS = AnnotationSources.BASE + "/attribute/expressions"; + String REF_EXPRESSIONS = AnnotationSources.BASE + "/reference/expressions"; + + String INVARIANT = AnnotationSources.BASE + "/expression/invariant"; + String INITIAL = AnnotationSources.BASE + "/expression/initial"; + String DERIVATION = AnnotationSources.BASE + "/expression/derivation"; + + String PRECONDITION = AnnotationSources.BASE + "/operation/precondition"; + String POSTCONDITION = AnnotationSources.BASE + "/operation/postcondition"; + String BODY = AnnotationSources.BASE + "/operation/body"; + + String DATATYPE_PRIMITIVE = AnnotationSources.BASE + "/datatype/primitive"; + + static boolean isStatic(final EModelElement element) { + return element.getEAnnotation(AnnotationSources.STATIC) != null; + } + + static boolean isPrimitive(final EDataType dataType) { + return dataType.getEAnnotation(AnnotationSources.DATATYPE_PRIMITIVE) != null; + } + + static boolean isNullable(final ETypedElement element) { + boolean canBe = element.getUpperBound() == -1 || element.getUpperBound() > 1; + return canBe && element.getEAnnotation(AnnotationSources.NULLABLE) != null; + } + + /** + * + * @param element @EModelElement to get annotations from + * @return Filtered annotations of AlloyInEcore + */ + static List filterAnnotations(final EModelElement element, + final String filter) { + return element.getEAnnotations().stream().filter(anno -> filter.equals(anno.getSource())) + .collect(Collectors.toList()); + } + + /** + * + * @param element @EModelElement to get annotations from + * @return Invariant annotations of AlloyInEcore + */ + static List getInvariants(final EModelElement element) { + return AnnotationSources.filterAnnotations(element, AnnotationSources.INVARIANT); + } + + /** + * + * @param element @EModelElement to get annotations from + * @return Derivation annotations of AlloyInEcore + */ + static List getDerivation(final EModelElement element) { + return AnnotationSources.filterAnnotations(element, AnnotationSources.DERIVATION); + } + + /** + * + * @param element @EModelElement to get annotations from + * @return Initial annotations of AlloyInEcore + */ + static List getInitial(final EModelElement element) { + return AnnotationSources.filterAnnotations(element, AnnotationSources.INITIAL); + } + + /** + * + * @param element @EModelElement to get annotations from + * @return The Import annotations + */ + static List getImports(final EModelElement element) { + return AnnotationSources.filterAnnotations(element, AnnotationSources.IMPORT); + } + + /** + * + * @param element @EModelElement to get annotations from + * @return The annotations other than AlloyInEcore + */ + static List getAnnotations(final EModelElement element) { + return element.getEAnnotations().stream().filter( + anno -> anno.getSource() == null || !anno.getSource().startsWith(AnnotationSources.BASE)) + .collect(Collectors.toList()); + } + + static List getPostconditions(final EModelElement element) { + return AnnotationSources.filterAnnotations(element, AnnotationSources.POSTCONDITION); + } + + static List getPreconditions(final EModelElement element) { + return AnnotationSources.filterAnnotations(element, AnnotationSources.PRECONDITION); + } + + static List getBodyExpressions(final EModelElement element) { + return AnnotationSources.filterAnnotations(element, AnnotationSources.BODY); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/internal/Console.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/internal/Console.java new file mode 100644 index 00000000..87c22f8e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/internal/Console.java @@ -0,0 +1,39 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.internal; + +public class Console { + public static final String RESET = "\u001B[0m"; + public static final String BOLD = "\u001B[1m"; + public static final String UNDERLINE = "\u001B[4m"; + public static final String BLACK = "\u001B[30m"; + public static final String RED = "\u001B[31m"; + public static final String GREEN = "\u001B[32m"; + public static final String YELLOW = "\u001B[33m"; + public static final String BLUE = "\u001B[34m"; + public static final String PURPLE = "\u001B[35m"; + public static final String CYAN = "\u001B[36m"; + public static final String WHITE = "\u001B[37m"; +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/interpreter/JavaTypeChecking b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/interpreter/JavaTypeChecking new file mode 100644 index 00000000..e69de29b diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/interpreter/KodkodInterpreter.jav b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/interpreter/KodkodInterpreter.jav new file mode 100644 index 00000000..d094072e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/interpreter/KodkodInterpreter.jav @@ -0,0 +1,1432 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.translator; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreBaseVisitor; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.*; +import kodkod.ast.Node; +import kodkod.ast.Variable; +import kodkod.util.nodes.PrettyPrinter; +import org.antlr.v4.runtime.ParserRuleContext; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * + */ +public class KodkodTranslator extends AlloyInEcoreBaseVisitor { + + public KodkodTranslator(kodkod.instance.Bounds bounds) { + super(); + this.bounds = bounds;; + for (kodkod.ast.Relation relation : bounds.relations()) { + this.relations.put(relation.name(), relation); + } + this.universe = bounds.universe(); + System.out.println(this.bounds); + } + + private java.util.Map relations = + new java.util.HashMap(); + private kodkod.instance.Universe universe = null; + private kodkod.instance.Bounds bounds = null; + private java.util.Map declarations = + new java.util.HashMap(); + private List> setOfDisjVars = + new ArrayList<>(); + + public kodkod.instance.Universe getUniverse() { + return universe; + } + + public kodkod.instance.Bounds getBounds() { + return bounds; + } + + public java.util.Map getRelations() { + return relations; + } + + private void reportError(ParserRuleContext ctx, String token, String text) { + System.err.println(text + ": '" + token + "' at line " + ctx.start.getLine() + " - position[" + + ctx.start.getStartIndex() + "," + ctx.start.getStopIndex() + "]"); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitProblem(ProblemContext ctx) { + final List formulas = new ArrayList(); + for (FormulaContext formula : ctx.formula()) { + if (!declarations.isEmpty()) + declarations.clear(); + if (!setOfDisjVars.isEmpty()) + setOfDisjVars.clear(); + kodkod.ast.Node node = this.visit(formula); + System.out.println("Declarations in the formula Context: " + declarations); + System.out.println(node); + formulas.add((kodkod.ast.Formula) node); + } + return kodkod.ast.Formula.and(formulas); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitUniverse(UniverseContext ctx) { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitRelations(RelationsContext ctx) { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitTupleSet(TupleSetContext ctx) { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitTuple(TupleContext ctx) { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitAtom(AtomContext ctx) { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitRelation(RelationContext ctx) { + kodkod.ast.Relation relation = null; + String name = ctx.getText(); + if (ctx.getParent() instanceof FunctionContext) { + if (relations.containsKey(name)) { + relation = relations.get(name); + return relation; + } + } + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitVariableId(VariableIdContext ctx) { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitInteger(IntegerContext ctx) { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitArity(ArityContext ctx) { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitNo(NoContext ctx) { + kodkod.ast.Expression expr = (kodkod.ast.Expression) this.visit(ctx.expression()); + return expr.no(); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitSome(SomeContext ctx) { + kodkod.ast.Expression expr = (kodkod.ast.Expression) this.visit(ctx.expression()); + return expr.some(); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitForOne(ForOneContext ctx) { + kodkod.ast.Decls decls = (kodkod.ast.Decls) this.visit(ctx.decls()); + Iterator iterator = ctx.formula().iterator(); + final java.util.Map variableReplacement = + new java.util.HashMap(); + kodkod.ast.Formula formula = null; + if (iterator.hasNext()) { + formula = (kodkod.ast.Formula) this.visit(iterator.next()); + while (iterator.hasNext()) { + formula = formula.and((kodkod.ast.Formula) this.visit(iterator.next())); + } + + kodkod.ast.Decls primedDecls = null; + List andFormulas = + new ArrayList(); + Iterator declIterator = decls.iterator(); + if (declIterator.hasNext()) { + kodkod.ast.Decl decl = declIterator.next(); + Variable x = Variable.unary(decl.variable().name() + "'"); + variableReplacement.put(decl.variable(), x); + // oneof? + primedDecls = x.oneOf(decl.expression()); + andFormulas.add(x.eq(decl.variable())); + while (declIterator.hasNext()) { + decl = declIterator.next(); + x = Variable.unary(decl.variable().name() + "'"); + primedDecls = primedDecls.and(x.oneOf(decl.expression())); + andFormulas.add(x.eq(decl.variable())); + } + } + + final kodkod.ast.visitor.AbstractReplacer replacer = + new kodkod.ast.visitor.AbstractReplacer(variableReplacement.keySet()) { + public kodkod.ast.Expression visit(Variable variable) { + System.out.println(PrettyPrinter.print(variable, 2)); + return variableReplacement.containsKey(variable) + ? (Variable) variableReplacement.get(variable) : variable; + } + }; + + formula = formula.accept(replacer).iff(kodkod.ast.Formula.and(andFormulas)) + .forAll(primedDecls).forSome(decls);; + + } + return formula; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitSumDeclaration(SumDeclarationContext ctx) { + // TODO visitSumDeclaration + return visitChildren(ctx); + } + + + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitLone(LoneContext ctx) { + kodkod.ast.Expression expr = (kodkod.ast.Expression) this.visit(ctx.expression()); + return expr.lone(); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitLt(LtContext ctx) { + kodkod.ast.IntExpression left = (kodkod.ast.IntExpression) this.visit(ctx.ileft); + kodkod.ast.IntExpression right = (kodkod.ast.IntExpression) this.visit(ctx.iright); + return ctx.not == null ? left.lt(right) : left.lt(right).not(); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitForSome(ForSomeContext ctx) { + kodkod.ast.Decls decls = (kodkod.ast.Decls) this.visit(ctx.decls()); + Iterator iterator = ctx.formula().iterator(); + kodkod.ast.Formula formula = null; + if (iterator.hasNext()) { + formula = (kodkod.ast.Formula) this.visit(iterator.next()); + while (iterator.hasNext()) { + formula = formula.and((kodkod.ast.Formula) this.visit(iterator.next())); + } + if (!setOfDisjVars.isEmpty()) + formula = implementDisjOperatorOverFormula().and(formula).forSome(decls); + else + formula = formula.forSome(decls); + } + return formula; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitNot(NotContext ctx) { + kodkod.ast.Formula formula = (kodkod.ast.Formula) this.visit(ctx.formula()); + return formula.not(); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitF_paranthesis(F_paranthesisContext ctx) { + return this.visit(ctx.formula()); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitAnd(AndContext ctx) { + kodkod.ast.Formula left = (kodkod.ast.Formula) this.visit(ctx.fleft); + kodkod.ast.Formula right = (kodkod.ast.Formula) this.visit(ctx.fright); + return left.and(right); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitFunction(FunctionContext ctx) { + kodkod.ast.Formula formula = null; + kodkod.ast.Relation relation = (kodkod.ast.Relation) this.visit(ctx.relationId()); + kodkod.ast.Expression domain = (kodkod.ast.Expression) this.visit(ctx.domain); + kodkod.ast.Expression range = (kodkod.ast.Expression) this.visit(ctx.range); + if (ctx.op.getText().equals("one")) { + formula = relation.function(domain, range); + } else if (ctx.op.getText().equals("lone")) { + formula = relation.partialFunction(domain, range); + } + return formula; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitGte(GteContext ctx) { + kodkod.ast.IntExpression left = (kodkod.ast.IntExpression) this.visit(ctx.ileft); + kodkod.ast.IntExpression right = (kodkod.ast.IntExpression) this.visit(ctx.iright); + return ctx.not == null ? left.gte(right) : left.gte(right).not(); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitAcyclic(AcyclicContext ctx) { + kodkod.ast.Relation rel = (kodkod.ast.Relation) this.visit(ctx.relationId()); + return rel.acyclic(); + } + + + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitLte(LteContext ctx) { + kodkod.ast.IntExpression left = (kodkod.ast.IntExpression) this.visit(ctx.ileft); + kodkod.ast.IntExpression right = (kodkod.ast.IntExpression) this.visit(ctx.iright); + return ctx.not == null ? left.lte(right) : left.lte(right).not(); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitOr(OrContext ctx) { + kodkod.ast.Formula left = (kodkod.ast.Formula) this.visit(ctx.fleft); + kodkod.ast.Formula right = (kodkod.ast.Formula) this.visit(ctx.fright); + return left.or(right); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitIn(InContext ctx) { + kodkod.ast.Expression left = (kodkod.ast.Expression) this.visit(ctx.left); + kodkod.ast.Expression right = (kodkod.ast.Expression) this.visit(ctx.right); + return ctx.not == null ? left.in(right) : left.in(right).not(); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitOne(OneContext ctx) { + kodkod.ast.Expression expr = (kodkod.ast.Expression) this.visit(ctx.expression()); + return expr.one(); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitFalse(FalseContext ctx) { + return kodkod.ast.Formula.FALSE; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitIff(IffContext ctx) { + kodkod.ast.Formula left = (kodkod.ast.Formula) this.visit(ctx.fleft); + kodkod.ast.Formula right = (kodkod.ast.Formula) this.visit(ctx.fright); + return left.iff(right); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitEq(EqContext ctx) { + kodkod.ast.IntExpression left = (kodkod.ast.IntExpression) this.visit(ctx.ileft); + kodkod.ast.IntExpression right = (kodkod.ast.IntExpression) this.visit(ctx.iright); + return ctx.not == null ? left.eq(right) : left.eq(right).not(); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitGt(GtContext ctx) { + kodkod.ast.IntExpression left = (kodkod.ast.IntExpression) this.visit(ctx.ileft); + kodkod.ast.IntExpression right = (kodkod.ast.IntExpression) this.visit(ctx.iright); + return ctx.not == null ? left.gt(right) : left.gt(right).not(); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitEqual(EqualContext ctx) { + kodkod.ast.Expression left = (kodkod.ast.Expression) this.visit(ctx.left); + kodkod.ast.Expression right = (kodkod.ast.Expression) this.visit(ctx.right); + return ctx.not == null ? left.eq(right) : left.eq(right).not(); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitForLone(ForLoneContext ctx) { + kodkod.ast.Decls decls = (kodkod.ast.Decls) this.visit(ctx.decls()); + Iterator iterator = ctx.formula().iterator(); + final java.util.Map variableReplacement = + new java.util.HashMap(); + kodkod.ast.Formula formula = null; + if (iterator.hasNext()) { + formula = (kodkod.ast.Formula) this.visit(iterator.next()); + while (iterator.hasNext()) { + formula = formula.and((kodkod.ast.Formula) this.visit(iterator.next())); + } + + kodkod.ast.Decls primedDecls = null; + List andFormulas = + new ArrayList(); + Iterator declIterator = decls.iterator(); + if (declIterator.hasNext()) { + kodkod.ast.Decl decl = declIterator.next(); + Variable x = Variable.unary(decl.variable().name() + "'"); + variableReplacement.put(decl.variable(), x); + // oneof? + primedDecls = x.oneOf(decl.expression()); + andFormulas.add(x.eq(decl.variable())); + while (declIterator.hasNext()) { + decl = declIterator.next(); + x = Variable.unary(decl.variable().name() + "'"); + primedDecls = primedDecls.and(x.oneOf(decl.expression())); + andFormulas.add(x.eq(decl.variable())); + } + } + + final kodkod.ast.visitor.AbstractReplacer replacer = + new kodkod.ast.visitor.AbstractReplacer(variableReplacement.keySet()) { + public kodkod.ast.Expression visit(Variable variable) { + System.out.println(PrettyPrinter.print(variable, 2)); + return variableReplacement.containsKey(variable) + ? (Variable) variableReplacement.get(variable) : variable; + } + }; + + formula = formula.and(formula.accept(replacer)).implies(kodkod.ast.Formula.and(andFormulas)) + .forAll(primedDecls).forAll(decls);; + + } + return formula; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitTotalOrder(TotalOrderContext ctx) { + kodkod.ast.Relation relation = (kodkod.ast.Relation) this.visit(ctx.rel); + kodkod.ast.Relation ordered = (kodkod.ast.Relation) this.visit(ctx.ordered); + kodkod.ast.Relation first = (kodkod.ast.Relation) this.visit(ctx.first); + kodkod.ast.Relation last = (kodkod.ast.Relation) this.visit(ctx.last); + return relation.totalOrder(ordered, first, last); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitTrue(TrueContext ctx) { + return kodkod.ast.Formula.TRUE; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + * + * no disj p1, p2: Pigeon | p1.hole = p2.hole + * + * @formatter:off + * final Variable p1 = Variable.unary("p1"); + * final Variable p2 = Variable.unary("p2"); + * return (p1.eq(p2).not(). + * implies(p1.join(hole).intersection(p2.join(hole)) + * .no())).forAll(p1.oneOf(Pigeon).and(p2.oneOf(Pigeon))); + * + * @formatter:on + *

+ */ + @Override + public kodkod.ast.Node visitForNo(ForNoContext ctx) { + kodkod.ast.Decls decls = (kodkod.ast.Decls) this.visit(ctx.decls()); + Iterator iterator = ctx.formula().iterator(); + kodkod.ast.Formula formula = null; + if (iterator.hasNext()) { + formula = (kodkod.ast.Formula) this.visit(iterator.next()); + while (iterator.hasNext()) { + formula = formula.and((kodkod.ast.Formula) this.visit(iterator.next())); + } + if (!setOfDisjVars.isEmpty()) + formula = implementDisjOperatorOverFormula().implies(formula.not()).forAll(decls); + else + formula = formula.not().forAll(decls); + } + return formula; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitImplies(ImpliesContext ctx) { + kodkod.ast.Formula left = (kodkod.ast.Formula) this.visit(ctx.fleft); + kodkod.ast.Formula right = (kodkod.ast.Formula) this.visit(ctx.fright); + return left.implies(right); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitProduct(ProductContext ctx) { + kodkod.ast.Expression left = (kodkod.ast.Expression) this.visit(ctx.left); + kodkod.ast.Expression right = (kodkod.ast.Expression) this.visit(ctx.right); + return left.product(right); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitNone(NoneContext ctx) { + return kodkod.ast.LeafExpression.NONE; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitUnion(UnionContext ctx) { + kodkod.ast.Expression left = (kodkod.ast.Expression) this.visit(ctx.left); + kodkod.ast.Expression right = (kodkod.ast.Expression) this.visit(ctx.right); + return left.union(right); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitBoxjoin(BoxjoinContext ctx) { + kodkod.ast.Expression left = (kodkod.ast.Expression) this.visit(ctx.left); + kodkod.ast.Expression right = (kodkod.ast.Expression) this.visit(ctx.right); + return left.join(right); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitComprehension(ComprehensionContext ctx) { + // TODO visitComprehension + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitUniv(UnivContext ctx) { + return kodkod.ast.LeafExpression.UNIV; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitReflexive(ReflexiveContext ctx) { + kodkod.ast.Expression expr = (kodkod.ast.Expression) this.visit(ctx.expression()); + return expr.reflexiveClosure(); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitE_paranthesis(E_paranthesisContext ctx) { + return this.visit(ctx.expression()); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitIden(IdenContext ctx) { + return kodkod.ast.LeafExpression.IDEN; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitInts(IntsContext ctx) { + return kodkod.ast.LeafExpression.INTS; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitIntersection(IntersectionContext ctx) { + kodkod.ast.Expression left = (kodkod.ast.Expression) this.visit(ctx.left); + kodkod.ast.Expression right = (kodkod.ast.Expression) this.visit(ctx.right); + return left.intersection(right); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitRel(RelContext ctx) { + String name = ctx.getText(); + kodkod.ast.Relation rel = null; + if (relations.containsKey(name)) + rel = relations.get(name); + else + reportError(ctx, name, "Relation is undefined"); + return rel; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitDifference(DifferenceContext ctx) { + kodkod.ast.Expression left = (kodkod.ast.Expression) this.visit(ctx.left); + kodkod.ast.Expression right = (kodkod.ast.Expression) this.visit(ctx.right); + return left.difference(right); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitTranspose(TransposeContext ctx) { + kodkod.ast.Expression expr = (kodkod.ast.Expression) this.visit(ctx.expression()); + return expr.transpose(); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitJoin(JoinContext ctx) { + kodkod.ast.Expression left = (kodkod.ast.Expression) this.visit(ctx.left); + kodkod.ast.Expression right = (kodkod.ast.Expression) this.visit(ctx.right); + return left.join(right); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitOverride(OverrideContext ctx) { + kodkod.ast.Expression left = (kodkod.ast.Expression) this.visit(ctx.left); + kodkod.ast.Expression right = (kodkod.ast.Expression) this.visit(ctx.right); + return left.override(right); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitIfExpression(IfExpressionContext ctx) { + kodkod.ast.Formula condition = (kodkod.ast.Formula) this.visit(ctx.condition); + kodkod.ast.Expression thenExpr = (kodkod.ast.Expression) this.visit(ctx.thenExpr); + kodkod.ast.Expression elseExpr = (kodkod.ast.Expression) this.visit(ctx.elseExpr); + return condition.thenElse(thenExpr, elseExpr); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitClosure(ClosureContext ctx) { + kodkod.ast.Expression expr = (kodkod.ast.Expression) this.visit(ctx.expression()); + return expr.closure(); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitMinus(MinusContext ctx) { + kodkod.ast.IntExpression left = (kodkod.ast.IntExpression) this.visit(ctx.ileft); + kodkod.ast.IntExpression right = (kodkod.ast.IntExpression) this.visit(ctx.iright); + return left.minus(right); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitIntConstant(IntConstantContext ctx) { + int integer = 0; + if (ctx.sign != null || !ctx.sign.getText().isEmpty()) + integer = Integer.valueOf(ctx.integer().getText()); + else + integer = Integer.valueOf("-" + ctx.integer().getText()); + return kodkod.ast.IntConstant.constant(integer); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitI_paranthesis(I_paranthesisContext ctx) { + return this.visit(ctx.intexpression()); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitIfIntExpression(IfIntExpressionContext ctx) { + kodkod.ast.Formula condition = (kodkod.ast.Formula) this.visit(ctx.condition); + kodkod.ast.IntExpression thenExpr = (kodkod.ast.IntExpression) this.visit(ctx.thenExpr); + kodkod.ast.IntExpression elseExpr = (kodkod.ast.IntExpression) this.visit(ctx.elseExpr); + return condition.thenElse(thenExpr, elseExpr); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitCount(CountContext ctx) { + kodkod.ast.Expression expr = (kodkod.ast.Expression) this.visit(ctx.expression()); + return expr.count(); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitSum(SumContext ctx) { + kodkod.ast.Expression expr = (kodkod.ast.Expression) this.visit(ctx.expression()); + return expr.sum(); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitDivide(DivideContext ctx) { + kodkod.ast.IntExpression left = (kodkod.ast.IntExpression) this.visit(ctx.ileft); + kodkod.ast.IntExpression right = (kodkod.ast.IntExpression) this.visit(ctx.iright); + return left.divide(right); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitMultiply(MultiplyContext ctx) { + kodkod.ast.IntExpression left = (kodkod.ast.IntExpression) this.visit(ctx.ileft); + kodkod.ast.IntExpression right = (kodkod.ast.IntExpression) this.visit(ctx.iright); + return left.multiply(right); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitModulo(ModuloContext ctx) { + kodkod.ast.IntExpression left = (kodkod.ast.IntExpression) this.visit(ctx.ileft); + kodkod.ast.IntExpression right = (kodkod.ast.IntExpression) this.visit(ctx.iright); + return left.modulo(right); + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitPlus(PlusContext ctx) { + kodkod.ast.IntExpression left = (kodkod.ast.IntExpression) this.visit(ctx.ileft); + kodkod.ast.IntExpression right = (kodkod.ast.IntExpression) this.visit(ctx.iright); + return left.plus(right); + } + + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitLet(LetContext ctx) { + this.visit(ctx.letDecls()); + kodkod.ast.Formula formula = null; + Iterator iterator = ctx.formula().iterator(); + if (iterator.hasNext()) { + formula = (kodkod.ast.Formula) this.visit(iterator.next()); + while (iterator.hasNext()) { + formula = formula.and((kodkod.ast.Formula) this.visit(iterator.next())); + } + } + return formula; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitLetDecls(LetDeclsContext ctx) { + Iterator iterator = ctx.letDecl().iterator(); + while (iterator.hasNext()) { + this.visit(iterator.next()); + } + return null; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitLetDecl(LetDeclContext ctx) { + kodkod.ast.Expression expression = (kodkod.ast.Expression) this.visit(ctx.expression()); + List variableContexts = ctx.variableId(); + for (VariableIdContext variableContext : variableContexts) { + String name = variableContext.getText(); + if (!declarations.containsKey(name)) + declarations.put(name, expression); + } + return null; + } + + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitVar(VarContext ctx) { + kodkod.ast.Node node = null; + String name = ctx.variableId().getText(); + if (declarations.containsKey(name)) { + if (declarations.get(name) instanceof Variable) { + node = (Variable) declarations.get(name); + } else if (declarations.get(name) instanceof kodkod.ast.Expression) + node = (kodkod.ast.Expression) declarations.get(name); + } else + reportError(ctx.variableId(), name, "Variable is not declared in the context"); + return node; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitForAll(ForAllContext ctx) { + kodkod.ast.Decls decls = (kodkod.ast.Decls) this.visit(ctx.decls()); + Iterator iterator = ctx.formula().iterator(); + kodkod.ast.Formula formula = null; + if (iterator.hasNext()) { + formula = (kodkod.ast.Formula) this.visit(iterator.next()); + while (iterator.hasNext()) { + formula = formula.and((kodkod.ast.Formula) this.visit(iterator.next())); + } + if (!setOfDisjVars.isEmpty()) + formula = implementDisjOperatorOverFormula().implies(formula).forAll(decls); + else + formula = formula.forAll(decls); + } + return formula; + } + + private kodkod.ast.Formula implementDisjOperatorOverFormula() { + + List listOfDisjFormulas = + new ArrayList(); + + for (List disjVars : setOfDisjVars) { + if (disjVars.size() > 1) { + Iterator iterator = disjVars.iterator(); + Variable var1 = iterator.next(); + Variable var2 = iterator.next(); + kodkod.ast.Formula formula = var1.eq(var2).not(); + while (iterator.hasNext()) { + Variable var3 = iterator.next(); + formula = formula.and(var2.eq(var3).not()); + var2 = var3; + } + listOfDisjFormulas.add(formula); + } + } + + kodkod.ast.Formula andOfDisjFormula = null; + if (!listOfDisjFormulas.isEmpty()) { + Iterator iterator = listOfDisjFormulas.iterator(); + if (iterator.hasNext()) { + andOfDisjFormula = iterator.next(); + while (iterator.hasNext()) { + andOfDisjFormula = andOfDisjFormula.and(iterator.next()); + } + } + } + return andOfDisjFormula; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitDecls(DeclsContext ctx) { + Iterator iterator = ctx.decl().iterator(); + kodkod.ast.Decls decls = null; + if (iterator.hasNext()) { + decls = (kodkod.ast.Decls) this.visit(iterator.next()); + while (iterator.hasNext()) { + decls = decls.and((kodkod.ast.Decls) this.visit(iterator.next())); + } + } + return decls; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitOneOf(OneOfContext ctx) { + kodkod.ast.Expression expression = (kodkod.ast.Expression) this.visit(ctx.expression()); + int arity = expression.arity(); + List disjVars = new ArrayList<>(); + boolean isDisj = ctx.disj != null ? true : false; + Iterator iterator = ctx.variableId().iterator(); + kodkod.ast.Decls decls = null; + if (iterator.hasNext()) { + String name = iterator.next().getText(); + Variable var = null; + if (arity == 1) + var = Variable.unary(name); + else + var = Variable.nary(name, arity); + decls = var.oneOf(expression); + if (isDisj) + disjVars.add(var); + if (!declarations.containsKey(name)) + declarations.put(name, var); + while (iterator.hasNext()) { + name = iterator.next().getText(); + if (arity == 1) + var = Variable.unary(name); + else + var = Variable.nary(name, arity); + decls = decls.and(var.oneOf(expression)); + if (isDisj) + disjVars.add(var); + if (!declarations.containsKey(name)) + declarations.put(name, var); + } + } + if (!disjVars.isEmpty()) + setOfDisjVars.add(disjVars); + return decls; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitLoneOf(LoneOfContext ctx) { + kodkod.ast.Expression expression = (kodkod.ast.Expression) this.visit(ctx.expression()); + int arity = expression.arity(); + List disjVars = new ArrayList<>(); + boolean isDisj = ctx.disj != null ? true : false; + Iterator iterator = ctx.variableId().iterator(); + kodkod.ast.Decls decls = null; + if (iterator.hasNext()) { + String name = iterator.next().getText(); + Variable var = null; + if (arity == 1) + var = Variable.unary(name); + else + var = Variable.nary(name, arity); + decls = var.oneOf(expression); + if (isDisj) + disjVars.add(var); + if (!declarations.containsKey(name)) + declarations.put(name, var); + while (iterator.hasNext()) { + name = iterator.next().getText(); + if (arity == 1) + var = Variable.unary(name); + else + var = Variable.nary(name, arity); + decls = decls.and(var.loneOf(expression)); + if (isDisj) + disjVars.add(var); + if (!declarations.containsKey(name)) + declarations.put(name, var); + } + } + if (!disjVars.isEmpty()) + setOfDisjVars.add(disjVars); + return decls; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitSomeOf(SomeOfContext ctx) { + kodkod.ast.Expression expression = (kodkod.ast.Expression) this.visit(ctx.expression()); + int arity = expression.arity(); + List disjVars = new ArrayList<>(); + boolean isDisj = ctx.disj != null ? true : false; + Iterator iterator = ctx.variableId().iterator(); + kodkod.ast.Decls decls = null; + if (iterator.hasNext()) { + String name = iterator.next().getText(); + Variable var = null; + if (arity == 1) + var = Variable.unary(name); + else + var = Variable.nary(name, arity); + decls = var.oneOf(expression); + if (isDisj) + disjVars.add(var); + if (!declarations.containsKey(name)) + declarations.put(name, var); + while (iterator.hasNext()) { + name = iterator.next().getText(); + if (arity == 1) + var = Variable.unary(name); + else + var = Variable.nary(name, arity); + decls = decls.and(var.someOf(expression)); + if (isDisj) + disjVars.add(var); + if (!declarations.containsKey(name)) + declarations.put(name, var); + } + } + if (!disjVars.isEmpty()) + setOfDisjVars.add(disjVars); + return decls; + } + + /** + * {@inheritDoc} + * + *

+ * The default implementation returns the result of calling {@link #visitChildren} on {@code ctx}. + *

+ */ + @Override + public kodkod.ast.Node visitSetOf(SetOfContext ctx) { + kodkod.ast.Expression expression = (kodkod.ast.Expression) this.visit(ctx.expression()); + int arity = expression.arity(); + List disjVars = new ArrayList<>(); + boolean isDisj = ctx.disj != null ? true : false; + Iterator iterator = ctx.variableId().iterator(); + kodkod.ast.Decls decls = null; + if (iterator.hasNext()) { + String name = iterator.next().getText(); + Variable var = null; + if (arity == 1) + var = Variable.unary(name); + else + var = Variable.nary(name, arity); + decls = var.oneOf(expression); + if (isDisj) + disjVars.add(var); + if (!declarations.containsKey(name)) + declarations.put(name, var); + while (iterator.hasNext()) { + name = iterator.next().getText(); + if (arity == 1) + var = Variable.unary(name); + else + var = Variable.nary(name, arity); + decls = decls.and(var.setOf(expression)); + if (isDisj) + disjVars.add(var); + if (!declarations.containsKey(name)) + declarations.put(name, var); + } + } + if (!disjVars.isEmpty()) + setOfDisjVars.add(disjVars); + return decls; + } +} + + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcore.g4 b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcore.g4 new file mode 100644 index 00000000..7352704f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcore.g4 @@ -0,0 +1,1155 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +grammar AlloyInEcore; + +@parser::header { + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EcoreFactory; +import org.eclipse.emf.ecore.EcorePackage; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.ETypedElement; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EClassifier; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EOperation; +import org.eclipse.emf.ecore.EParameter; +import org.eclipse.emf.ecore.EEnum; +import org.eclipse.emf.ecore.EEnumLiteral; +import org.eclipse.emf.ecore.EDataType; +import org.eclipse.emf.ecore.ETypedElement; +import org.eclipse.emf.ecore.EAnnotation; +import org.eclipse.emf.ecore.EGenericType; +import org.eclipse.emf.ecore.ETypeParameter; + +import eu.modelwriter.core.alloyinecore.structure.base.INamespace; +import eu.modelwriter.core.alloyinecore.structure.base.Repository; +import eu.modelwriter.core.alloyinecore.structure.base.Element; + +import eu.modelwriter.core.alloyinecore.structure.model.ModelElement; +import eu.modelwriter.core.alloyinecore.structure.model.Annotation; +import eu.modelwriter.core.alloyinecore.structure.model.AnnotationDetail; +import eu.modelwriter.core.alloyinecore.structure.model.AnnotationReference; +import eu.modelwriter.core.alloyinecore.structure.model.NamedElement; +import eu.modelwriter.core.alloyinecore.structure.model.Model; +import eu.modelwriter.core.alloyinecore.structure.model.Import; +import eu.modelwriter.core.alloyinecore.structure.model.EcoreImport; +import eu.modelwriter.core.alloyinecore.structure.model.Package; +import eu.modelwriter.core.alloyinecore.structure.model.RootPackage; +import eu.modelwriter.core.alloyinecore.structure.model.Classifier; +import eu.modelwriter.core.alloyinecore.structure.model.Class; +import eu.modelwriter.core.alloyinecore.structure.model.Interface; +import eu.modelwriter.core.alloyinecore.structure.model.DataType; +import eu.modelwriter.core.alloyinecore.structure.model.Enum; +import eu.modelwriter.core.alloyinecore.structure.model.EnumLiteral; +import eu.modelwriter.core.alloyinecore.structure.model.StructuralFeature; +import eu.modelwriter.core.alloyinecore.structure.model.TypedElement; +import eu.modelwriter.core.alloyinecore.structure.model.Multiplicity; +import eu.modelwriter.core.alloyinecore.structure.model.Reference; +import eu.modelwriter.core.alloyinecore.structure.model.Attribute; +import eu.modelwriter.core.alloyinecore.structure.model.Operation; +import eu.modelwriter.core.alloyinecore.structure.model.Parameter; +import eu.modelwriter.core.alloyinecore.structure.model.GenericException; +import eu.modelwriter.core.alloyinecore.structure.model.TypeParameter; +import eu.modelwriter.core.alloyinecore.structure.model.GenericType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericTypeArgument; +import eu.modelwriter.core.alloyinecore.structure.model.GenericElementType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericSuperType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericWildcard; +import eu.modelwriter.core.alloyinecore.structure.model.PrimitiveType; +import eu.modelwriter.core.alloyinecore.structure.model.Invariant; +import eu.modelwriter.core.alloyinecore.structure.model.Derivation; +import eu.modelwriter.core.alloyinecore.structure.model.Body; +import eu.modelwriter.core.alloyinecore.structure.model.PostCondition; +import eu.modelwriter.core.alloyinecore.structure.model.PreCondition; +import eu.modelwriter.core.alloyinecore.structure.model.Initial; + +import eu.modelwriter.core.alloyinecore.structure.instance.ModelImport; +import eu.modelwriter.core.alloyinecore.structure.instance.Instance; +import eu.modelwriter.core.alloyinecore.structure.instance.Object; +import eu.modelwriter.core.alloyinecore.structure.instance.Slot; +import eu.modelwriter.core.alloyinecore.structure.instance.ObjectValue; +import eu.modelwriter.core.alloyinecore.structure.instance.EnumValue; +import eu.modelwriter.core.alloyinecore.structure.instance.IntegerValue; +import eu.modelwriter.core.alloyinecore.structure.instance.RealValue; +import eu.modelwriter.core.alloyinecore.structure.instance.BooleanValue; +import eu.modelwriter.core.alloyinecore.structure.instance.StringValue; +import eu.modelwriter.core.alloyinecore.structure.instance.NullValue; +import eu.modelwriter.core.alloyinecore.structure.instance.CharValue; + +import eu.modelwriter.core.alloyinecore.structure.constraints.Formula; +import eu.modelwriter.core.alloyinecore.structure.constraints.Expression; +import eu.modelwriter.core.alloyinecore.structure.constraints.IntExpression; +import eu.modelwriter.core.alloyinecore.structure.constraints.QuantifierDeclaration; +import eu.modelwriter.core.alloyinecore.structure.constraints.LetDeclaration; +import eu.modelwriter.core.alloyinecore.structure.constraints.ComprehensionDeclaration; +import eu.modelwriter.core.alloyinecore.structure.constraints.Variable; + +import eu.modelwriter.core.alloyinecore.internal.AnnotationSources; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl; +import org.eclipse.emf.ecore.util.EcoreUtil; + +import java.util.stream.Collectors; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +import java.io.IOException; +} + +@parser::members { + +public Model model; +public Instance instance; +private boolean resolveImports = true; + +Repository repository = new Repository(); + + +URI saveURI; + +public AlloyInEcoreParser(TokenStream input, URI saveURI){ + this(input); + this.saveURI = saveURI; + repository = new Repository(saveURI); +} + +public AlloyInEcoreParser(TokenStream input, URI saveURI, boolean resolveImports){ + this(input, saveURI); + this.resolveImports = resolveImports; +} + + +public void saveResource(String filename, String path){ + model.printTree(); + repository.printNamespaces(); + if (model.getOwnedPackage() != null) { + ResourceSet metaResourceSet = new ResourceSetImpl(); + metaResourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("ecore", new XMLResourceFactoryImpl()); + Resource metaResource = metaResourceSet.createResource(URI.createURI(path + filename + ".ecore")); + metaResource.getContents().add(model.getOwnedPackage().getEObject()); + try { + metaResource.save(null); + } catch (java.io.IOException e) { + e.printStackTrace(); + } + } +} + +private String getLocation() { return "["+ getCurrentToken().getLine()+ ","+ getCurrentToken().getCharPositionInLine()+ "]";} + +private String getContextText(ParserRuleContext ctx){ + return getTokenStream().getTokenSource().getInputStream().toString().substring(ctx.start.getStartIndex(),ctx.stop.getStopIndex()); +} + + +private EcoreFactory eFactory = EcoreFactory.eINSTANCE; + +private void signalParsingCompletion() { + //restoreReferences(); + //checkConstraints(); +} + +private void createEAnnotation(EModelElement owner, final String source) { + if (owner.getEAnnotation(source) != null) + return; + final EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation(); + eAnnotation.setSource(source); + owner.getEAnnotations().add(eAnnotation); +} + +//private java.util.Stack owners = new java.util.Stack<>(); + +} + +options: 'options' '{' option (',' option)* '}'; + +option: key= 'symmetry_breaking' ':' value= INT #symmetryBreaking + | key= 'bit_width' ':' value= INT #bitWidth + | key= 'skolem_depth' ':' value= INT #skolemDepth + | key= 'sharing' ':' value= INT #sharing +; + + +/* +Identifying class instance (objects) +===================================== +Since the value of the attribute selected as the identifying attribute is presented in the class instance’s introduction, +its normal representation within the body of the instance’s definition is superfluous, and is thus omitted. + +By default, identifying strings (be they arbitrary or the value of an attribute) are required to be unique over the +set of instance of the class, and over all instance of its subtypes. + +Attributes whose lower multiplicity bound is 0 may be explicitly unset by assigning them to the ‘null’ keyword. + +The association name is optionally displayed before the contained class instance to allow disambiguation for MOF models +that have more than one possible containment association between the container and the contained instance. + +Three reserved words: “true” and “false” for representing boolean values, and “null” for unsetting attribute values. + +‘+’ and ‘-’ can be used to indicate the positive/negative sign of the value. + +*/ +instance[Element owner] locals[Instance current] +@init{$current= new Instance($ctx); instance= $current; if (owner!=null) owner.addOwnedElement($current);} +@after{instance.printTree();}: + ('instance' name= identifier ';')? + packageImport[$current]* modelImport[$current] (rootObject= eObject[$current] | ';') + ; + +modelImport[Element owner] locals[ModelImport current, EObject object] +@init{$current= new ModelImport($ctx); if (owner!=null) owner.addOwnedElement($current);} +@after{ +if ($ownedPathName != null) { + String path = $ownedPathName.getText().replace("'", ""); + if (path.equals(EcorePackage.eNS_URI)) { + notifyErrorListeners($ownedPathName, "You cannot create an instance of ECore Model! Instead, create a model in the model editor!", null); + } else { + Resource resource = repository.loadResource(path); + if (resource == null) { + notifyErrorListeners($ownedPathName, "Import could not be resolved!", null); + } + else { + $object = repository.loadResource(path).getContents().get(0); + if ($object instanceof ENamedElement) { + $current.setEObject($object); + repository.name2Import.put($current.getKey(), $current); + $current.loadNamespace(repository); + } else { + notifyErrorListeners($ownedPathName, "This is an instance, cannot be used as a model!", null); + } + } + } +} +}: + ('model') (name= unrestrictedName ':')? ownedPathName= SINGLE_QUOTED_STRING ';' + ; + +//pathName indicates the class to which this object conforms +eObject[Element owner] locals[Object current] +@init{$current= new Object($ctx); if (owner!=null) owner.addOwnedElement($current);}: + name= pathName[$current] //must conform to a type in imported model + {} + id= literalValue[$owner]? //must conform to the id attribute definition of the type in imported model + {} + ('{' slots+= slot[$current] (',' slots+= slot[$current])* '}' | ';') ; + +slot[Element owner] locals[Slot current] +@init{$current= new Slot($ctx); if (owner!=null) owner.addOwnedElement($current);}: + name= unrestrictedName + {} + (':' ( + {true}? '{' eObject[$current]* '}' //semantic predicate koymayi unutma! + | eObjectValue[$current] + | '[' eObjectValue[$current] (',' eObjectValue[$current] )* ']' + | dataValue[$current] + ) + )?; + +dataValue[Element owner] +@init{}: + literalValue[$owner] | multiValueData[$owner]; + +multiValueData[Element owner] +@init{}: + '[' dataValue[$owner] (',' dataValue[$owner])* ']' ; + +eObjectValue[Element owner] locals[ObjectValue current] +@init{$current= new ObjectValue($ctx); if (owner!=null) owner.addOwnedElement($current);}: + pathName[$current]; + +literalValue[Element owner] locals[Element current] +@init{if($ctx.parent instanceof EObjectContext) {} else { $current = $owner;} }: + enumValue [$current] + | integerValue [$current] + | realValue [$current] + | stringValue [$current] + | charValue [$current] + | booleanValue [$current] + | nullValue [$current] + ; + +enumValue[Element owner] locals[EnumValue current] +@init{$current= new EnumValue($ctx); if (owner!=null) $owner.addOwnedElement($current);} + : identifier; + +booleanValue[Element owner] locals[BooleanValue current] +@init{$current= new BooleanValue($ctx); if (owner!=null) $owner.addOwnedElement($current);} + : 'true' | 'false'; + +integerValue[Element owner] locals[IntegerValue current] +@init{$current= new IntegerValue($ctx); if (owner!=null) $owner.addOwnedElement($current);} + : ('+' | '-')? INT; + + +realValue[Element owner] locals[RealValue current] +@init{$current= new RealValue($ctx); if (owner!=null) $owner.addOwnedElement($current);} + :('+' | '-')? INT? '.' INT; + +stringValue[Element owner] locals[StringValue current] +@init{$current= new StringValue($ctx); if (owner!=null) $owner.addOwnedElement($current);} + : DOUBLE_QUOTED_STRING; + +charValue[Element owner] locals[CharValue current] +@init{$current= new CharValue($ctx); if (owner!=null) $owner.addOwnedElement($current);} + : SINGLE_CHARACTER; + +/* NullValue is intended to be used to explicitly model the lack of a value */ +nullValue[Element owner] locals[NullValue current] +@init{$current= new NullValue($ctx); if (owner!=null) $owner.addOwnedElement($current);} + : 'null'; + +/*http://help.eclipse.org/neon/topic/org.eclipse.ocl.doc/help/OCLinEcore.html*/ +/*optional model declaration*/ +model locals[EAnnotation element] +@init {model = new Model($ctx); $element = eFactory.createEAnnotation(); $element.setSource(AnnotationSources.MODULE);} +@after{signalParsingCompletion();}: + options? {} + ('model' name= identifier ';')? {$element.getDetails().put("name", $name.text);} + (ownedPackageImport+= packageImport[model] )* + (ownedPackage= ePackage[model] {$ePackage.element.getEAnnotations().add($element);} ) + {for(PackageImportContext ctx: $ctx.ownedPackageImport) {$ePackage.element.getEAnnotations().add(ctx.element);}} + ; + +/*Zero or more external metamodels may be imported.*/ +packageImport[Element owner] returns [EAnnotation element] locals [EObject object] +@init{$element = eFactory.createEAnnotation(); $element.setSource(AnnotationSources.IMPORT);} +@after{ +if ($ownedPathName != null) { + String path = $ownedPathName.getText().replace("'", ""); + Import imported = null; + if (path.equals(EcorePackage.eNS_URI)) { + $object = EcorePackage.eINSTANCE; + imported = new EcoreImport($object, $ctx); + $owner.addOwnedElement(imported); + repository.name2Import.put(imported.getKey(), imported); + imported.loadNamespace(repository); + } else { + Resource resource = repository.loadResource(path); + if (resource == null) { + notifyErrorListeners($ownedPathName, "Import could not be resolved!", null); + + } else { + $object = repository.loadResource(path).getContents().get(0); + imported = new Import($object, $ctx); + $owner.addOwnedElement(imported); + repository.name2Import.put(imported.getKey(), imported); + imported.loadNamespace(repository); + } + } +} +}: + ('import') (name= identifier ':')? ownedPathName= SINGLE_QUOTED_STRING ';' + {$element.getDetails().put($name.text, $ownedPathName != null ? $ownedPathName.getText().replace("'", "") : null);} + ; + +/* + Constraints: + 1. WellFormedNsURI + 2. WellFormedNsPrefix + 3. UniqueSubpackageNames + 4. UniqueClassifierNames + 5. UniqueNsURIs +*/ +ePackage[Element owner] returns [EPackage element] locals [Package current] +@init {$element = eFactory.createEPackage(); if($ctx.parent instanceof ModelContext) {$current = new RootPackage($element, $ctx);} else {$current = new Package($element, $ctx);}} +@after{owner.addOwnedElement($current);}: + (visibility= visibilityKind)? {if($ctx.visibility != null) $element.getEAnnotations().add($visibility.element);} + 'package' name= unrestrictedName + {$element.setName($name.text);} + {if($ctx.parent instanceof ModelContext) {repository.name2Import.put(((RootPackage)$current).getKey(), (RootPackage)$current);}} + (':' nsPrefix= identifier) ('=' nsURI= SINGLE_QUOTED_STRING) {$element.setNsPrefix($nsPrefix.text); if($nsURI != null) $element.setNsURI($nsURI.getText().replace("'", ""));} + (('{' ( ownedAnnotations+=eAnnotation[$current] {$element.getEAnnotations().add($eAnnotation.element);} + | eSubPackages+= ePackage[$current] {$element.getESubpackages().add($ePackage.element);} + | eClassifiers+= eClassifier[$current] {if ($eClassifier.element != null) $element.getEClassifiers().add($eClassifier.element);} + | eConstraints+= invariant[$current] {$element.getEAnnotations().add($invariant.element);} + )* + '}') | ';') + ; + +/* + Constraints: + 1. WellFormedInstanceTypeName + 2. UniqueTypeParameterNames +*/ +eClassifier[Element owner] returns [EClassifier element]: + eClass[$owner] {$element= $eClass.element;} + | eDataType[$owner] {$element= $eDataType.element;} + | eEnum[$owner] {$element= $eEnum.element;} + ; + +/* + Once interface is true, abstract is also implicitly true. Interface with abstract modifier is redundant. + Constraints: + 1. InterfaceIsAbstract + 2. AtMostOneID + 3. UniqueFeatureNames + 4. UniqueOperationSignatures + 5. NoCircularSuperTypes + 6. WellFormedMapEntryClass + 7. ConsistentSuperTypes + 8. DisjointFeatureAndOperationSignatures +*/ +eClass[Element owner] returns [EClass element] locals [Class current] +@init {$element = eFactory.createEClass(); $current = new Class($element, $ctx); if (owner!=null) owner.addOwnedElement($current); } +@after{}: + (visibility= visibilityKind)? {if($ctx.visibility != null) $element.getEAnnotations().add($visibility.element);} + (isAbstract= 'abstract'? isClass='class' | isInterface= 'interface') {$element.setAbstract($isAbstract!=null); if ($isInterface!=null) {$element.setInterface(true);$element.setAbstract(true);}} + name= unrestrictedName? + {if ($ctx.name == null) {notifyErrorListeners("missing Class name");} else {$element.setName($name.text);}} + {if ($isInterface!=null) {owner.deleteOwnedElement($current); $current = new Interface($element, $ctx); if (owner!=null) owner.addOwnedElement($current);}} + (ownedSignature= templateSignature[$current])? {if($ctx.templateSignature != null) $element.getETypeParameters().addAll($templateSignature.typeParameters);} + ('extends' eSuperTypes+= eGenericSuperType[$current] (',' eSuperTypes+= eGenericSuperType[$current])*)? {} + (':' instanceClassName= SINGLE_QUOTED_STRING)? {if($instanceClassName != null) $element.setInstanceClassName($instanceClassName.getText().replace("'", ""));} + (('{' ( ownedAnnotations+= eAnnotation[$current] {if ($eAnnotation.element != null) $element.getEAnnotations().add($eAnnotation.element);} + | eOperations+= eOperation[$current] {if ($eOperation.element != null) $element.getEOperations().add($eOperation.element);} + | eStructuralFeatures+= eStructuralFeature[$current] {if ($eStructuralFeature.element != null) $element.getEStructuralFeatures().add($eStructuralFeature.element);} + | eConstraints+= invariant[$current] {if ($invariant.element != null) $element.getEAnnotations().add($invariant.element);} + )* + '}') | ';') + ; + +/* + A StructuralFeature may be an Attribute or a Reference + Constraints: + 1. ValidDefaultValueLiteral +*/ +eStructuralFeature[Element owner] returns [EStructuralFeature element]: + eAttribute[$owner] {$element= $eAttribute.element;} + | eReference[$owner] {$element= $eReference.element;} + ; + +/* + OCL and UML support four permutations of ordered/not-ordered, unique/not-unique to give useful Collection behaviors. + A Parameter may have a variety of qualifiers: + ordered specifies that the returned elements are ordered (default !ordered) + unique specifies that there are no duplicate returned elements (default unique) + + The defaults for multiplicity lower and upper bound and for ordered and unique follow the UML specification and so + corresponds to a single element Set that is [1] {unique,!ordered}. Note that UML defaults differ from the Ecore + defaults which correspond to an optional element OrderedSet, that is [?] {ordered,unique}. + + An Attribute may a simple initializer and a variety of qualifiers: + derived specifies a derived attribute (default !derived) + id specifies that the attribute provides the identifier if its class (default !id) + ordered specifies that the attribute elements are ordered (default !ordered) + readonly specifies that the attribute elements are readonly (not changeable) (default !readonly) + transient specifies that the attribute elements are computed on the fly (default !transient) + unique specifies that there are no duplicate attribute elements (default unique) + unsettable specifies that attribute element may have no value (default !unsettable) + volatile specifies that the attribute elements are not persisted (default !volatile) +*/ + +/* + The defaults for multiplicity lower and upper bound and for ordered and unique correspond to a single element Set + that is [1] {unique,!ordered} + + __Object Declarations__ + mandatoryName : aDataType --[1] indicates that a DataType value is required; a null value is prohibited. (default) + mandatoryName : aDataType[1] --[1] indicates that a DataType value is required; a null value is prohibited. + __Collection Declarations__ + optionalName : aDataType[?] --[?] indicates that a DataType value is optional; a null value is permitted. {nullable} + optionalName : aDataType[*] --[*] represents an array of dataytype such as String[] or Boolean[]. {!nullable} + optionalName : aDataType[+] --[+] represents an array of dataytype such as String[] or Boolean[]. {!nullable} +*/ + +/* + Constraints: + 1. ConsistentTransient +*/ +eAttribute[Element owner] returns [EAttribute element] locals [Attribute current] +@init {$element = eFactory.createEAttribute(); $current = new Attribute($element, $ctx); if (owner!=null) owner.addOwnedElement($current);} +@after{ +if ($ctx.eAttributeType != null) { + EObject genericElementType = $ctx.eAttributeType.element; + if (genericElementType instanceof EClassifier) { $element.setEType((EClassifier) genericElementType);} + else if (genericElementType instanceof EGenericType) { $element.setEGenericType((EGenericType) genericElementType);} +} +}: + (visibility= visibilityKind)? {if ($ctx.visibility != null) $element.getEAnnotations().add($visibility.element);} + (qualifier+='static')? + (qualifier+='model' | qualifier+='ghost')? + (qualifier+='transient')? + (qualifier+='volatile')? + (qualifier+='readonly')? + 'attribute' name= unrestrictedName {$element.setName($name.text);} + ':' eAttributeType= eGenericElementType[$current] (ownedMultiplicity= eMultiplicity[$current, (ETypedElement)$element])? {if($ctx.ownedMultiplicity == null) {$element.setLowerBound(1);} } + ('=' defaultValue= SINGLE_QUOTED_STRING )? {if($defaultValue != null) $element.setDefaultValueLiteral($defaultValue.getText().replace("'", ""));} + ('{'((qualifier+='derived' | qualifier+='id' | + qualifier+='ordered' | qualifier+='!ordered' | qualifier+='unique' | qualifier+='!unique' | + qualifier+='unsettable' | qualifier+='!unsettable') ','? )+ + '}')? + (('{'( (ownedAnnotations+= eAnnotation[$current] {$element.getEAnnotations().add($eAnnotation.element);} )* + (ownedDerivation= derivation[$current] {$element.getEAnnotations().add($derivation.element);} | ownedInitial= initial[$current] {$element.getEAnnotations().add($initial.element);})? + (ownedAnnotations+= eAnnotation[$current] {$element.getEAnnotations().add($eAnnotation.element);} )* ) + '}') | ';') + {for(String s: $qualifier.stream().map(Token::getText).distinct().collect(Collectors.toList())){ + switch (s) { + case "static": createEAnnotation($element, AnnotationSources.STATIC); break; + case "model": createEAnnotation($element, AnnotationSources.MODEL); break; + case "ghost": createEAnnotation($element, AnnotationSources.GHOST); break; + case "transient": $element.setTransient(true); break; + case "volatile": $element.setVolatile(true); break; + case "readonly": $element.setChangeable(false); break; + case "derived": $element.setDerived(true); break; + case "ordered": int u = $element.getUpperBound(); if (u > 1 || u == -1) $element.setOrdered(true); break; + case "!unique": u = $element.getUpperBound(); if (u > 1 || u == -1) $element.setUnique(false); break; + case "unsettable": $element.setUnsettable(true); break; + case "id": $element.setID(true); break;}} + }; + +/* + The defaults for multiplicity lower and upper bound and for ordered and unique correspond to a single element Set + that is [1] {unique,!ordered}. + + We can declare that a collection is null-free; i.e. that it contains no null element, which is also the default way. + ForAll collections are null-free unless explicitly declared to be nullable. + !Nullable specifies a collection of null-free collection declaration. (default {!nullable}) + A reference (field) whose type in an array of reference types such as Object[], both + the field (i.e. [1..*]) that refers to the array and the elements of the array are non-null {!nullable} by default + + __Object Declarations__ + mandatoryRefName : eClassifier --[1..1] indicates that a classifier reference is required; a null value is prohibited. (default) + mandatoryRefName : eClassifier[1] --[1..1] indicates that a classifier reference is required; a null value is prohibited. + optionalRefName : eClassifier[?] --[0..1] indicates that a String reference is optional; a null value is permitted. + __Collection Declarations__ + collectionRefName : eClassifier[*] --[0..*] Reference may be null, but the elements of the array is {!nullable} which is by default. + collectionRefName : eClassifier[*] {nullable} --[0..*] Reference may be null, and the elements of the array is {nullable}. + collectionRefName : eClassifier[+] {nullable} --[1..*] Reference is required, and the elements of the array is {nullable}. +*/ + +/* + Constraints: + 1. ConsistentOpposite + 2. SingleContainer + 3. ConsistentKeys + 4. ConsistentUnique + 5. ConsistentContainer +*/ +eReference[Element owner] returns [EReference element] locals [Reference current] +@init {$element = eFactory.createEReference(); $current = new Reference($element, $ctx); if (owner!=null) owner.addOwnedElement($current);} : + (visibility= visibilityKind)? {if ($ctx.visibility != null) $element.getEAnnotations().add($visibility.element);} + (qualifier+='static')? + (qualifier+='model' | qualifier+='ghost')? + (qualifier+='transient')? + (qualifier+='volatile')? + (qualifier+='readonly')? + 'property' name= unrestrictedName {$element.setName($name.text);} + ('#' eOpposite= unrestrictedName)? {} + (':' eReferenceType= eGenericElementType[$current] (ownedMultiplicity= eMultiplicity[$current, (ETypedElement) $element])? ) {if ($ctx.ownedMultiplicity == null) {$element.setLowerBound(1);} } + ('=' defaultValue= SINGLE_QUOTED_STRING)? {if($defaultValue != null) $element.setDefaultValueLiteral($defaultValue.getText().replace("'", ""));} + ('{'((qualifier+='composes' | qualifier+='derived' | + qualifier+='ordered' | qualifier+='!ordered' | qualifier+='unique' | qualifier+='!unique' | + qualifier+='resolve' | qualifier+='!resolve' | qualifier+='unsettable' | qualifier+='!unsettable' ) ','? )+ + '}')? + (('{' ('key' referredKeys+= unrestrictedName (',' referredKeys+= unrestrictedName)* ';')? //this only lets the attributes of the eReferenceType of this eReference // If both initial and derived constraints are present, the initial constraint is ignored. + ( (ownedAnnotations+= eAnnotation [$current] {$element.getEAnnotations().add($eAnnotation.element);} )* + (ownedDerivation= derivation[$current] {$element.getEAnnotations().add($derivation.element);} | ownedInitial= initial[$current] {$element.getEAnnotations().add($initial.element);})? + (ownedAnnotations+= eAnnotation [$current] {$element.getEAnnotations().add($eAnnotation.element);} )* ) + '}') | ';') + {for(String s: $qualifier.stream().map(Token::getText).distinct().collect(Collectors.toList())){ + switch (s) { + case "static": createEAnnotation($element, AnnotationSources.STATIC); break; + case "model": createEAnnotation($element, AnnotationSources.MODEL); break; + case "ghost": createEAnnotation($element, AnnotationSources.GHOST); break; + case "transient": $element.setTransient(true); break; + case "volatile": $element.setVolatile(true); break; + case "readonly": $element.setChangeable(false); break; + case "unsettable":$element.setUnsettable(true); break; + case "derived": $element.setDerived(true); break; + case "ordered": int u = $element.getUpperBound(); if (u > 1 || u == -1) $element.setOrdered(true); break; + case "!unique": u = $element.getUpperBound(); if (u > 1 || u == -1) $element.setUnique(false); break; + case "composes": $element.setContainment(true); break; + case "!resolve": $element.setResolveProxies(false); break; + default: break;}} + }; + +/* + Constraints: + 1. UniqueParameterNames + 2. UniqueTypeParameterNames + 3. NoRepeatingVoid +*/ +eOperation[Element owner] returns [EOperation element] locals [Operation current] +@init {$element = eFactory.createEOperation(); $current = new Operation($element, $ctx); if (owner!=null) owner.addOwnedElement($current);} : + (visibility= visibilityKind)? {if ($ctx.visibility != null) $element.getEAnnotations().add($visibility.element);} + (qualifier+='static')? + 'operation' (ownedSignature= templateSignature[$current])? {if($ctx.templateSignature != null) $element.getETypeParameters().addAll($templateSignature.typeParameters);} + name= unrestrictedName {$element.setName($name.text);} + ('(' (eParameters+= eParameter[$current] (',' eParameters+= eParameter[$current])*)? ')') {for (EParameterContext ctx: $eParameters){$element.getEParameters().add(ctx.element);}} + (':' eReturnType= eGenericElementType[$current] (ownedMultiplicity= eMultiplicity[$current, (ETypedElement) $element])? )? {if ($ctx.ownedMultiplicity == null) {$element.setLowerBound(1);} } + { if ($ctx.eReturnType != null) $element.setEGenericType($eGenericElementType.element);} + ('throws' ownedException+= eGenericException[$current] (',' ownedException+= eGenericException[$current])*)? + { for(EGenericExceptionContext e: $ownedException) $element.getEGenericExceptions().add(e.element);} + ('{'((qualifier+='ordered' | qualifier+='!ordered' | qualifier+='unique' | qualifier+='!unique' ) ','? )+ '}')? + (('{'( ownedAnnotations+= eAnnotation[$current] {$element.getEAnnotations().add($eAnnotation.element);} + | ownedPreconditions+= precondition[$current] {$element.getEAnnotations().add($precondition.element);} + | ownedBodyExpression += body[$current] {$element.getEAnnotations().add($body.element);} + | ownedPostconditions+= postcondition[$current] {$element.getEAnnotations().add($postcondition.element);} )* + '}') | ';') + {for(String s: $qualifier.stream().map(Token::getText).distinct().collect(Collectors.toList())){ + switch (s) { + case "static": createEAnnotation($element, AnnotationSources.STATIC); break; + case "ordered": int u = $element.getUpperBound(); if (u > 1 || u == -1) $element.setOrdered(true); break; + case "!unique": u = $element.getUpperBound(); if (u > 1 || u == -1) $element.setUnique(false); break;}} + } + ; + +eGenericException [Element owner] returns [EGenericType element] locals [GenericException current] +@init {$current = new GenericException($ctx); if (owner!=null) $owner.addOwnedElement($current);} : + eGenericType[$current] {$element = $eGenericType.element; $current.setEObject($element);} +; + +eGenericSuperType [Element owner] returns [EGenericType element] locals [GenericSuperType current] +@init {$current = new GenericSuperType($ctx); if (owner!=null) $owner.addOwnedElement($current);} : + eGenericType[$current] {$element = $eGenericType.element; $current.setEObject($element);} +; + +/* + The defaults for multiplicity lower and upper bound and for ordered and unique correspond to a single element Set + that is [1] {unique,!ordered} +*/ +eParameter[Element owner] returns [EParameter element] locals [Parameter current] +@init {$element = eFactory.createEParameter(); $current = new Parameter($element, $ctx); if (owner!=null) owner.addOwnedElement($current);} : + name= unrestrictedName {$element.setName($name.text);} + ':' eParameterType= eGenericElementType[$current] (ownedMultiplicity= eMultiplicity[$current, (ETypedElement) $element])? {if ($ctx.ownedMultiplicity == null) {$element.setLowerBound(1);} } + ('{'(( qualifier+='ordered' | qualifier+='!ordered' | qualifier+='unique' | qualifier+='!unique') ','?)+ '}')? + ('{' ownedAnnotations+= eAnnotation[$current]* {$element.getEAnnotations().add($eAnnotation.element);} '}')? + {for(String s: $qualifier.stream().map(Token::getText).distinct().collect(Collectors.toList())){ + switch (s) { + case "ordered": int u = $element.getUpperBound(); if (u > 1 || u == -1) $element.setOrdered(true);break; + case "!unique": u = $element.getUpperBound(); if (u > 1 || u == -1) $element.setUnique(false);break;}} + }; + +/* + ==MultiplicityElement== + [?] is the default for the OCL declarations even though [1] is the default for UML declarations. We should also choose + [1] for default multiplicity for ETypedElement's declarations. + + If a MultiplicityElement specifies a multivalued multiplicity, then an instantiation of this element has a set of values. The + multiplicity is a constraint on the number of values that may validly occur in that set. + + If the MultiplicityElement is specified as ordered (i.e., isOrdered is true), then the set of values in an instantiation of this + element is ordered. This ordering implies that there is a mapping from positive integers to the elements of the set of + values. If a MultiplicityElement is not multivalued, then the value for isOrdered has no semantic effect. + + If the MultiplicityElement is specified as unique (i.e., isUnique is true), then the set of values in an instantiation of this + element must be unique. If a MultiplicityElement is not multivalued, then the value for isUnique has no semantic effect. + + * lower: Specifies the lower bound of the multiplicity interval. Default is one. + + * upper: Specifies the upper bound of the multiplicity interval. Default is one. + + * isOrdered: For a multivalued multiplicity, this attribute specifies whether the values in an instantiation of this element are + sequentially ordered. Default is false. + * isUnique: For a multivalued multiplicity, this attributes specifies whether the values in an instantiation of this element + are unique. Default is true. + + * The lower bound must be a non-negative integer literal. + `lowerBound()->notEmpty() implies lowerBound() >= 0` + + * The upper bound must be greater than or equal to the lower bound. + `(upperBound()->notEmpty() and lowerBound()->notEmpty()) implies upperBound() >= lowerBound()` + + * The query isCollection() checks whether this multiplicity has an upper bound greater than one. + MultiplicityElement::isCollection() : Boolean; + +*/ +eMultiplicity[Element owner, ETypedElement element] locals[int l=1, int u=1] +@after{$element.setLowerBound($l); $element.setUpperBound($u); if (owner!=null) $owner.addOwnedElement(new Multiplicity($ctx));}: + '[' (lowerBound= lower ('..' upperBound= upper)? | stringBound= ('*'|'+'|'?') ) (nullable='|?' | '|1')? ']' + { + if ($ctx.stringBound != null) { + switch ($ctx.stringBound.getText()) { + case "*": $l = 0; $u = -1; break; + case "+": $l = 1; $u = -1; break; + case "?": $l = 0; $u = 1; break; + default: break; + } + } else { + try { $l = Integer.valueOf($lowerBound.text); } catch (NumberFormatException ex) {System.out.println(Arrays.toString(ex.getStackTrace()));} + if ($ctx.upperBound != null) { + if ($ctx.upperBound.getText().equals("*")) $u = -1; + else try {$u = Integer.valueOf($upperBound.text);} catch (NumberFormatException ex){System.out.println(Arrays.toString(ex.getStackTrace()));} + } else { $u = $l;} + } + if (($u > 1 || $u == -1) && $ctx.nullable != null) createEAnnotation($element, AnnotationSources.NULLABLE); + }; + +/* primitive types cannot be qualified by a nullable keyword, only reference types can be nullable. */ +eDataType[Element owner] returns [EDataType element] locals [DataType current] +@init {$element = eFactory.createEDataType(); $current = new DataType($element, $ctx); if (owner!=null) owner.addOwnedElement($current);} : + (visibility= visibilityKind)? {if ($ctx.visibility != null) $element.getEAnnotations().add($visibility.element);} + (qualifier+= 'primitive')? + 'datatype' name= unrestrictedName {$element.setName($name.text);} + (ownedSignature= templateSignature[$current])? {if($ctx.templateSignature != null) $element.getETypeParameters().addAll($templateSignature.typeParameters);} + (':' instanceClassName= SINGLE_QUOTED_STRING)? {if($instanceClassName != null) $element.setInstanceClassName($instanceClassName.getText().replace("'", ""));} + ('{' (qualifier+= 'serializable' | qualifier+= '!serializable')? '}')? + (('{'( ownedAnnotations+= eAnnotation[$current] {$element.getEAnnotations().add($eAnnotation.element);} + | ownedConstraints+= invariant[$current] {$element.getEAnnotations().add($invariant.element);} )* + '}') | ';') + {for(String s: $qualifier.stream().map(Token::getText).distinct().collect(Collectors.toList())){ + switch (s) { + case "primitive": createEAnnotation($element, AnnotationSources.DATATYPE_PRIMITIVE);break; + case "!serializable": $element.setSerializable(false); break; }} + } + ; + +/* + Constraints: + 1. UniqueEnumeratorNames + 2. UniqueEnumeratorLiterals +*/ +eEnum[Element owner] returns [EEnum element] locals [Enum current] +@init {$element = eFactory.createEEnum(); $current = new Enum($element, $ctx); if (owner!=null) owner.addOwnedElement($current);} : + (visibility= visibilityKind)? {if ($ctx.visibility != null) $element.getEAnnotations().add($visibility.element);} + 'enum' name= unrestrictedName {$element.setName($name.text);} + (ownedSignature= templateSignature[$current])? {if($ctx.templateSignature != null) $element.getETypeParameters().addAll($templateSignature.typeParameters);} + (':' instanceClassName= SINGLE_QUOTED_STRING)? {if($instanceClassName != null) $element.setInstanceClassName($instanceClassName.getText().replace("'", ""));} + ('{' (qualifier+='serializable' | qualifier+='!serializable')? '}')? + (('{'( ownedAnnotations+=eAnnotation[$current] {$element.getEAnnotations().add($eAnnotation.element);} + | ownedLiteral+= eEnumLiteral[$current] {$element.getELiterals().add($eEnumLiteral.element);} + | ownedConstraint+= invariant[$current] {$element.getEAnnotations().add($invariant.element);} )* + '}') | ';') + {for(String s: $qualifier.stream().map(Token::getText).distinct().collect(Collectors.toList())){ + switch (s) { + case "!serializable": $element.setSerializable(false); break;}} + }; + +eEnumLiteral[Element owner] returns [EEnumLiteral element] locals [EnumLiteral current] +@init {$element = eFactory.createEEnumLiteral(); $current = new EnumLiteral($element, $ctx); if (owner!=null) owner.addOwnedElement($current);} : + (('literal' name= unrestrictedName) | name= unrestrictedName) {$element.setName($name.text);} + ('=' value= INT)? { } + (( '{' + ownedAnnotations+= eAnnotation[$current]* {$element.getEAnnotations().add($eAnnotation.element);} + '}') |';') + ; + +eAnnotation[Element owner] returns [EAnnotation element] locals [Annotation current] +@init {$element = eFactory.createEAnnotation(); $current = new Annotation($element, $ctx); if (owner!=null) owner.addOwnedElement($current);} : + 'annotation' (source= SINGLE_QUOTED_STRING)? {$element.setSource($source != null ? $source.getText().replace("'", "") : null);} + ('(' ownedDetails+=eDetail[$current] (',' ownedDetails+=eDetail[$current])* ')')? + {for (EDetailContext ctx: $ownedDetails) $element.getDetails().put(ctx.k, ctx.v);} + (('{' ( ownedAnnotations+= eAnnotation[$current] {if($eAnnotation.element != null) $element.getEAnnotations().add($eAnnotation.element);} + | ownedContents+= eModelElement[$current] {if($eModelElement.element != null) $element.getContents().add($eModelElement.element);} + | ownedReferences+= eModelElementRef[$current] {if($eModelElementRef.element != null) $element.getReferences().add($eModelElementRef.element);} + )+ + '}') |';') + ; + +eDetail[Element owner] returns [String k, String v] locals [AnnotationDetail current] +@init{$current = new AnnotationDetail($ctx); if (owner!=null) owner.addOwnedElement($current);} : + key= SINGLE_QUOTED_STRING? '=' value= (SINGLE_QUOTED_STRING|ML_SINGLE_QUOTED_STRING)? + {$k = $key != null ? $key.getText().replace("'", "") : null; $v = $value != null ? $value.getText().replace("'", "") : null; } + ; + +eModelElement[Element owner] returns [EModelElement element]: + eAnnotation [$owner]{$element= $eAnnotation.element;} + | eNamedElement [$owner] {$element= $eNamedElement.element;} + ; + +/* + Constraints: + 1. WellFormedName +*/ +eNamedElement[Element owner] returns [ENamedElement element] : + eTypedElement[$owner] {$element= $eTypedElement.element;} + | eClassifier[$owner] {$element= $eClassifier.element;} + | ePackage[$owner] {$element= $ePackage.element;} + | eEnumLiteral[$owner] {$element= $eEnumLiteral.element;} + ; + +/* + Constraints: + 1. ValidLowerBound + 2. ValidUpperBound + 3. ConsistentBounds + 4. ValidType +*/ +eTypedElement[Element owner] returns [ETypedElement element]: + eOperation[$owner] {$element= $eOperation.element;} + | eParameter[$owner] {$element= $eParameter.element;} + | eStructuralFeature[$owner] {$element= $eStructuralFeature.element;} + ; + +eModelElementRef[Element owner] returns [EObject element] locals [AnnotationReference current] +@init{$current = new AnnotationReference($ctx); if (owner!=null) owner.addOwnedElement($current);} : + 'reference' ownedPathName= pathName[$current] {if ($ownedPathName.element != null) $current.setEObject($element = $ownedPathName.element);} ';' + ; + +templateSignature[Element owner] returns [List typeParameters] +@init {$typeParameters = new ArrayList<>();} +@after{for(ETypeParameterContext ctx: $ownedTypeParameters) $typeParameters.add(ctx.element);}: + '<' ownedTypeParameters+= eTypeParameter[$owner] (',' ownedTypeParameters+= eTypeParameter[$owner])* '>' + ; + +eTypeParameter[Element owner] returns [ETypeParameter element] locals[TypeParameter current] +@init {$element = eFactory.createETypeParameter(); $current = new TypeParameter($element, $ctx); if (owner!=null) owner.addOwnedElement($current);} : + name= unrestrictedName {$element.setName($name.text);} + ('extends' ownedEBounds+= eGenericType[$current] ('&' ownedEBounds+= eGenericType[$current])*)? + {for(EGenericTypeContext ctx: $ownedEBounds) $element.getEBounds().add(ctx.element);} + ; + +eGenericTypeArgument[Element owner] returns [EGenericType element] locals[GenericTypeArgument current] +@init {$current = new GenericTypeArgument($ctx); if (owner!=null) $owner.addOwnedElement($current);} : + eGenericType[$current] {$element= $eGenericType.element; $current.setEObject($element);} + | eGenericWildcard[$current] {$element= $eGenericWildcard.element; $current.setEObject($element);} + ; + +/* + Constraints: + 1. ConsistentType + 2. ConsistentBounds + 3. ConsistentArguments +*/ +eGenericType[Element owner] returns [EGenericType element] locals[Element current] +@init { +$element = eFactory.createEGenericType(); +if ($ctx.parent instanceof ETypeParameterContext) {$current = new GenericType($element, $ctx); owner.addOwnedElement($current);} +else {$current = $owner;} +}: + ownedPathName= pathName[$current] ('<' ownedETypeArguments+= eGenericTypeArgument[$current] (',' ownedETypeArguments+= eGenericTypeArgument[$current])* '>')? + ; + +eGenericElementType[Element owner] returns [EGenericType element] locals[GenericElementType current] +@init {$current = new GenericElementType($ctx); if (owner!=null) $owner.addOwnedElement($current);} : + ePrimitiveType[$current] {$element= $ePrimitiveType.element; $current.setEObject($element);} + | eGenericType[$current] {$element= $eGenericType.element; $current.setEObject($element);} + ; + +eGenericWildcard[Element owner] returns [EGenericType element] locals[GenericWildcard current]: + '?' {$element = eFactory.createEGenericType();} + (bound=('extends' | 'super') {$current = new GenericWildcard($element, $ctx); if (owner!=null) owner.addOwnedElement($current);} + ownedExtend= eGenericType[$current] {if ($bound.equals("extends")) $element.setEUpperBound($eGenericType.element); else $element.setELowerBound($eGenericType.element);})? + ; + +pathName[Element owner] returns [EObject element] +@init{}: + firstSegment= unrestrictedName ('.' index= INT)? (midSegments+= segment* lastSegment= segment)? + ; + +segment: + '::' '@'? name= unrestrictedName ('.' index= INT)? + ; + +/* primitive types cannot be qualified by a nullable keyword, only reference types can be nullable.*/ +ePrimitiveType[Element owner] returns [EGenericType element] locals[PrimitiveType current] +@after{$current = new PrimitiveType($element, $ctx); if (owner!=null) owner.addOwnedElement($current);}: + 'Boolean' {$element = eFactory.createEGenericType(); $element.setEClassifier(EcorePackage.eINSTANCE.getEBoolean());} + | 'Integer' {$element = eFactory.createEGenericType(); $element.setEClassifier(EcorePackage.eINSTANCE.getEInt());} + | 'String' {$element = eFactory.createEGenericType(); $element.setEClassifier(EcorePackage.eINSTANCE.getEString());} + | 'Real' {$element = eFactory.createEGenericType(); $element.setEClassifier(EcorePackage.eINSTANCE.getEBigDecimal());} + | 'UnlimitedNatural' {$element = eFactory.createEGenericType(); $element.setEClassifier(EcorePackage.eINSTANCE.getEBigInteger());} + ; + +body[Element owner] returns [EAnnotation element] locals[Body current] +@init {$element = eFactory.createEAnnotation(); $element.setSource(AnnotationSources.BODY); $current = new Body($ctx); if (owner!=null) $owner.addOwnedElement($current);}: + 'body' name= identifier? {if($ctx.name!=null) $element.getDetails().put("name", $name.text); } + ((':' ownedExpression= expression? ';') | ';') {if($ctx.ownedExpression!=null) {$element.getDetails().put("expression", getContextText($ctx.expression())); $current.addOwnedElement($ownedExpression.element);}} + ; + +/* Class-level invariants are conditions that must be true on entry and exit of every method in a class. */ +invariant[Element owner] returns [EAnnotation element] locals[Invariant current] +@init {$element = eFactory.createEAnnotation(); $element.setSource(AnnotationSources.INVARIANT); $current = new Invariant($ctx); $owner.addOwnedElement($current);}: + (isCallable= 'callable')? {$element.getDetails().put("callable", $isCallable != null ? "true" : "false");} + 'invariant' (name= identifier ('(' message= DOUBLE_QUOTED_STRING ')')? )? {if($ctx.name!=null) $element.getDetails().put("name", $name.text); if($message!=null) $element.getDetails().put("message", $message.text.replace("\"", ""));} + ((':' ownedSpecification= formula? ';') | ';') {if($ctx.ownedSpecification!=null) {$element.getDetails().put("formula", getContextText($ctx.formula())); $current.addOwnedElement($ownedSpecification.element);}} + ; + +/* A precondition is a condition that must be satisfied before calling a method */ +precondition[Element owner] returns [EAnnotation element] locals[PreCondition current] +@init {$element = eFactory.createEAnnotation(); $element.setSource(AnnotationSources.PRECONDITION); $current = new PreCondition($ctx); $owner.addOwnedElement($current);}: + ('precondition' | 'requires') (name= identifier ('(' message= DOUBLE_QUOTED_STRING ')')? )? {if($ctx.name!=null) $element.getDetails().put("name", $name.text); if($message!=null) $element.getDetails().put("message", $message.text.replace("\"", ""));} + ((':' ownedSpecification= formula? ';') | ';') {if($ctx.ownedSpecification!=null) $element.getDetails().put("formula", getContextText($ctx.formula())); $current.addOwnedElement($ownedSpecification.element);} + ; + +/* + The postcondition of a method specifies the responsibilities of the method; that is, when the + method returns, the postcondition should be true +*/ +postcondition[Element owner] returns [EAnnotation element] locals[PostCondition current] +@init {$element = eFactory.createEAnnotation(); $element.setSource(AnnotationSources.POSTCONDITION); $current = new PostCondition($ctx); $owner.addOwnedElement($current);}: + ('postcondition' | 'ensures') (name= identifier ('(' message= DOUBLE_QUOTED_STRING ')')? )? {if($ctx.name!=null) $element.getDetails().put("name", $name.text); if($message!=null) $element.getDetails().put("message", $message.text.replace("\"", ""));} + ((':' ownedSpecification= formula? ';') | ';') {if($ctx.ownedSpecification!=null) $element.getDetails().put("formula", getContextText($ctx.formula())); $current.addOwnedElement($ownedSpecification.element);} + ; + +initial[Element owner] returns [EAnnotation element] locals[Initial current] +@init {$element = eFactory.createEAnnotation(); $element.setSource(AnnotationSources.INITIAL); $current = new Initial($ctx); $owner.addOwnedElement($current);}: + 'initial' name= identifier? {if($ctx.name!=null) $element.getDetails().put("name", $name.text);} + ((':' ownedExpression= expression? ';') | ';') {if($ctx.ownedExpression!=null) {$element.getDetails().put("expression", getContextText($ctx.expression())); $current.addOwnedElement($ownedExpression.element);} } + ; + +derivation[Element owner] returns [EAnnotation element] locals[Derivation current] +@init {$element = eFactory.createEAnnotation(); $element.setSource(AnnotationSources.DERIVATION); $current = new Derivation($ctx); $owner.addOwnedElement($current);}: + 'derivation' name= identifier? {if($ctx.name!=null) $element.getDetails().put("name", $name.text);} + ((':' ownedExpression= expression? ';') | ';') {if($ctx.ownedExpression!=null) {$element.getDetails().put("expression", getContextText($ctx.expression())); $current.addOwnedElement($ownedExpression.element);} } + ; + +/* +Package-private is default as in Java +“+” public +“-“ private +“#” protected +“~” package +*/ +visibilityKind returns [EAnnotation element] +@init {$element = eFactory.createEAnnotation(); $element.setSource(AnnotationSources.VISIBILITY);}: + (qualifier= 'public' | qualifier= 'protected'| qualifier= 'private') {$element.getDetails().put("visibility", $qualifier.text);} + ; + +/* +ForAll binary operators associate to the left, with the exception of implication, which associates to the right. +So, for example, p => q => r is parsed as p => (q => r), and a.b.c is parsed as (a.b).c. +*/ + +//Decls, Expression, Formula, IntExpression: kodkod.ast.Node +formula returns [Formula element] locals[int var=0] +@init {} +@after{}: + + 'no' expression {$element = Formula.create($ctx);} #no //Formula f = expr.no() --Returns the formula 'no expr'. + | 'lone' expression {$element = Formula.create($ctx);} #lone //Formula f = expr.lone() --Returns the formula 'lone expr'. + | 'one' expression {$element = Formula.create($ctx);} #one //Formula f = expr.one() --Returns the formula 'one expr'. + | 'some' expression {$element = Formula.create($ctx);} #some //Formula f = expr.some() --Returns the formula 'some expr'. + + //Set Operators: These operators can be applied to any pair of relations so long as they have the same arity. + | left=expression not=('!' | 'not')? 'in' right=expression {$element = Formula.create($ctx);} #in //Formula f = left.in(right) --Returns the formula 'left in right' (subset). + | left=expression not=('!' | 'not')? '=' right=expression {$element = Formula.create($ctx);} #equal //Formula f = left.eq(right) --Returns the formula 'left = right' (equal). + + //Integer Comparison Operators + | ileft=intExpression not=('!' | 'not')? '=' iright=intExpression {$element = Formula.create($ctx);} #eq //Formula f= left.eq(right) --Returns a formula stating that the given int expression and left have the same value. + | ileft=intExpression not=('!' | 'not')? '<' iright=intExpression {$element = Formula.create($ctx);} #lt //Formula f= left.lt(right) --Returns a formula stating that the value of this int expression is less than the value of the given int expression. + | ileft=intExpression not=('!' | 'not')? '<=' iright=intExpression {$element = Formula.create($ctx);} #lte //Formula f= left.lte(right)--Returns a formula stating that the value of this int expression is less than or equal to the value of the given int expression. + | ileft=intExpression not=('!' | 'not')? '>' iright=intExpression {$element = Formula.create($ctx);} #gt //Formula f= left.qt(right) --Returns a formula stating that the value of this int expression is greater than the value of the given int expression. + | ileft=intExpression not=('!' | 'not')? '>=' iright=intExpression {$element = Formula.create($ctx);} #gte //Formula f= left.qte(right)--Returns a formula stating that the value of this int expression is greater than or equal to the value of the given int expression + + | ('sum' quantifierDeclarations '|' intExpression) {$element = Formula.create($ctx);} #sumDeclaration //IntExpression iexpr = sum(Decls decls); + + | 'acyclic' '[' relationId ']' {$element = Formula.create($ctx);} #acyclic // + | 'function' '[' rel=relationId ':' domain=expression '->' ('one'? | partial='lone') range=expression ']' {$element = Formula.create($ctx);} #function //Relation rel; Formula f = rel.function(domain, range); Formula f = rel.partialFunction(domain, range); --Returns a formula stating that this relation is a total function or partial function with the specified domain and range. + | 'ord' '[' rel=relationId ',' ordered=relationId ',' first=relationId ',' last=relationId ']' {$element = Formula.create($ctx);} #totalOrder //Relation rel; Formula f = rel.totalOrder(Relation ordered, Relation first, Relation last) --Returns a formula stating that this relation imposes a total ordering over the atoms in the set ordered, and that thet first and last elements in the ordering are given by the relations first and last. + + //Logical Operators + //NotFormula + | op=('!' | 'not') formula {$element = Formula.create($ctx);} #not //Formula f = formula.not() --Returns the negation of this formula. + + //BinaryFormula (AND, IFF, IMPLIES, OR) + | fleft=formula op=('&&' | 'and' ) fright=formula {$element = Formula.create($ctx);} #and //Formula f = left.and(right) --Returns the conjunction of left and the specified formula. + | fleft=formula op=('||' | 'or' ) fright=formula {$element = Formula.create($ctx);} #or //Formula f = left.or(right) --Returns the disjunction of left and the specified formula. x => y is true if (and only if) either y is true or x is false + | fleft=formula op=('=>' | 'if' | 'implies') fright=formula {$element = Formula.create($ctx);} #implies //Formula f = left.implies(right) --Returns the implication of the specified formula by left. + | fleft=formula op=('<=>' | 'iff') fright=formula {$element = Formula.create($ctx);} #iff //Formula f = left.iff(right) --Returns a formula that equates left and the specified formula. + + | ('all' quantifierDeclarations ('|' (formula | '{' formula* '}' ) | '{' formula* '}')) {$element = Formula.create($ctx);} #forAll //Formula f = formula.forAll(decls) --Returns a formula that represents a universal quantification of this formula over the given declarations + | ('some' quantifierDeclarations ('|' (formula | '{' formula* '}' ) | '{' formula* '}')) {$element = Formula.create($ctx);} #forSome //Formula f = formula.forSome(decls) --Returns a formula that represents an existential quantification of this formula over the given declarations. + | ('no' quantifierDeclarations ('|' (formula | '{' formula* '}' ) | '{' formula* '}')) {$element = Formula.create($ctx);} #forNo //no x: e | F is true when F is true for no bindings of the variable x. + | ('one' quantifierDeclarations ('|' (formula | '{' formula* '}' ) | '{' formula* '}')) {$element = Formula.create($ctx);} #forOne //one x: e | F is true when F is true for exactly one binding of the variable x. (unique existential quantification) + | ('lone' quantifierDeclarations ('|' (formula | '{' formula* '}' ) | '{' formula* '}')) {$element = Formula.create($ctx);} #forLone //lone x: e | F is true when F is true for at most one binding of the variable x. + + | ('let' letDeclarations ('|' (formula | '{' formula* '}' ) | '{' formula* '}')) {$element = Formula.create($ctx);} #let + + //Constant Formulas + | 'true' {$element = Formula.create($ctx);} #true //Formula f = Formula.FALSE --Constant formula false + | 'false' {$element = Formula.create($ctx);} #false //Formula f = Formula.TRUE --Constant formula true + + | '(' formula ')' {$element = $formula.element;} #f_paranthesis + ; + + +/* +For the set theoretic operations (union, difference, and intersection) and for relational override, +the arguments are required to have the same arity. +*/ +expression returns [Expression element] +@init {} +@after{}: + // Relational Operators: These expressions are required to be unary + '~' expression {$element = Expression.create($ctx);} #transpose //Expression: expr.transpose() --Returns the transpose of expr. + | '^' expression {$element = Expression.create($ctx);} #closure //Expression: expr.closure() --Returns the transitive closure of expr. + | '*' expression {$element = Expression.create($ctx);} #reflexive //Expression: expr.reflexiveClosure()--Returns the reflexive transitive closure of expr. + + // Set theoretic operations: These operators can be applied to any pair of relations so long as they have the same arity. + | left=expression '+' right=expression {$element = Expression.create($ctx);} #union //Expression: left.union(right) --Returns the union of left and the specified expression. + | left=expression '&' right=expression {$element = Expression.create($ctx);} #intersection //Expression: left.intersection(right) --Returns the intersection of left and the specified expression. + | left=expression '-' right=expression {$element = Expression.create($ctx);} #difference //Expression: left.difference(right) --Returns the difference of left and the specified expression. + + //Relational Operators: These expressions are required to be binary + | left=expression '.' right=expression {$element = Expression.create($ctx);} #join //Expression expr = left.join(right) --Returns the join of left and the specified expression. + | right=expression '[' left=expression ']' {$element = Expression.create($ctx);} #boxJoin //Expression expr = left.join(right) --e1[e2] = e2.e1 -- + | left=expression leftMult= mult? '->' rightMult=mult? right=expression {$element = Expression.create($ctx);} #product //Expression expr = left.product(right) --Returns the product of left and the specified expression + | left=expression '++' right=expression {$element = Expression.create($ctx);} #override //Expression expr = left.override(right) --Returns the relational override of left with the specified expression. + + //A comprehension expression, e.g. { a: A, b: B | a.r = b } + //Comprehensions make relations from properties + //{x1: e1, x2: e2, … | F} The relation obtained by taking all tuples x1 -> x2 -> … + // in which x1 is drawn from the set e1, x2 is drawn from the set e2, and so on, + // and for which the constraint F holds. The expressions e1, e2, and so on, must be unary, + // and may not be prefixed by (or contain) multiplicity keywords + //all d: decls.decls[int] | decl.variable.arity = 1 and decl.multiplicity = ONE + | '{' comprehensionDeclarations '|' formula '}' {$element = Expression.create($ctx);} #comprehension //Expression f = formula.comprehension(Decls decls) //Returns the comprehension expression constructed from this formula and the given declarations. + + | op=('=>' | 'if') condition=formula 'then' thenExpr=expression 'else' elseExpr=expression {$element = Expression.create($ctx);} #ifExpression + + //Constants + | 'iden' {$element = Expression.create($ctx);} #iden //Expression expr = Expression.IDEN --The identity relation: maps all atoms in a universe of discourse to themselves. + | 'none' {$element = Expression.create($ctx);} #none //Expression expr = Expression.NONE --The empty relation: contains no atoms. + | 'univ' {$element = Expression.create($ctx);} #univ //Expression expr = Expression.UNIV --The universal relation: contains all atoms in a universe of discourse. + | 'ints' {$element = Expression.create($ctx);} #ints //Expression expr = Expression.INTS --The integer relation: contains all atoms bound to integers + + | '(' expression ')' {$element = $expression.element;} #e_paranthesis + + | pathName[$element] {$element = Expression.create($ctx);} #typeRef //ConstantExpression, Relation, Variable + ; + +intExpression returns [IntExpression element]: + op=('=>' | 'if') condition=formula 'then' thenExpr=intExpression 'else' elseExpr=intExpression {$element = IntExpression.create($ctx);} #ifIntExpression + | 'sum' expression {$element = IntExpression.create($ctx);} #sum //IntExpression iexpr = exp.sum(); --Returns the sum of the integer atoms in this expression. + | '#' expression {$element = IntExpression.create($ctx);} #count //IntExpression iexpr = exp.count(); --Returns the cardinality(the number of elements in the set) of this expression + | ileft=intExpression ('+' | 'plus') iright=intExpression {$element = IntExpression.create($ctx);} #plus //IntExpression iexpr = this.plus(intExpr); --Returns an IntExpression that represents the sum of this and the given int node + | ileft=intExpression ('-' | 'minus') iright=intExpression {$element = IntExpression.create($ctx);} #minus //IntExpression iexpr = this.minus(intExpr); --Returns an IntExpression that represents the difference between this and the given int node. + | ileft=intExpression ('*' | 'mul') iright=intExpression {$element = IntExpression.create($ctx);} #multiply //IntExpression iexpr = this.minus(intExpr); --Returns an IntExpression that represents the product of this and the given int node. + | ileft=intExpression ('/' | 'div') iright=intExpression {$element = IntExpression.create($ctx);} #divide //IntExpression iexpr = this.divide(intExpr); --Returns an IntExpression that represents the quotient of the division between this and the given int node. + | ileft=intExpression ('%' | 'modulo') iright=intExpression {$element = IntExpression.create($ctx);} #modulo //IntExpression iexpr = this.modulo(intExpr); --Returns an IntExpression that represents the remainder of the division between this and the given int node. + | sign='-'? INT {$element = IntExpression.create($ctx);} #intConstant + | '(' intExpression ')' {$element = $intExpression.element;} #i_paranthesis + ; + +//A variable declaration, such as 'x : lone X'. Declarations are used with quantified formulas and comprehension expressions. +quantifierDeclarations returns [List elements] +@init {$elements = new ArrayList<>();} +@after{for(QuantifierDeclarationContext ctx: $ctx.quantifierDeclaration()) $elements.add(ctx.element);}: + quantifierDeclaration (',' quantifierDeclaration)*; + +quantifierDeclaration returns [QuantifierDeclaration element]: + disj='disj'? vars+=variable (',' vars+=variable)* ':' 'one'? expression {$element = QuantifierDeclaration.create($ctx);} #oneOf //Decl d = var.oneOf(expression) + | disj='disj'? vars+=variable (',' vars+=variable)* ':' 'lone' expression {$element = QuantifierDeclaration.create($ctx);} #loneOf //Decl d = var.loneOf(expression) + | disj='disj'? vars+=variable (',' vars+=variable)* ':' 'some' expression {$element = QuantifierDeclaration.create($ctx);} #someOf //Decl d = var.someOf(expression) + | disj='disj'? vars+=variable (',' vars+=variable)* ':' 'set' expression {$element = QuantifierDeclaration.create($ctx);} #setOf //Decl d = var.setOf(expression) + ; + +letDeclarations returns [List elements] +@init {$elements = new ArrayList<>();} +@after {for(LetDeclarationContext ctx: $ctx.letDeclaration()) $elements.add(ctx.element);}: + letDeclaration (',' letDeclaration)*; + +letDeclaration returns [LetDeclaration element]: + vars+= variable (',' vars+= variable)* '=' expression + {$element = new LetDeclaration($ctx); for(VariableContext ctx: $ctx.variable()) $element.addOwnedElements(ctx.element); $element.addOwnedElements($expression.element);}; + +comprehensionDeclarations returns [List elements] +@init {$elements = new ArrayList<>();} +@after {for(ComprehensionDeclarationContext ctx: $ctx.comprehensionDeclaration()) $elements.add(ctx.element);}: + comprehensionDeclaration (',' comprehensionDeclaration)*; + +comprehensionDeclaration returns [ComprehensionDeclaration element]: + disj='disj'? (vars+=variable (',' vars+=variable)* ':' 'one'? expression) + {$element = new ComprehensionDeclaration($ctx); for(VariableContext ctx: $ctx.variable()) $element.addOwnedElements(ctx.element); $element.addOwnedElements($expression.element);}; + +relationId: unrestrictedName; +variable returns [Variable element]: unrestrictedName {$element = new Variable($ctx);}; + +/* Default multiplicity constraint is set*/ +mult: 'set' | 'one' | 'lone' | 'some'; + +unrestrictedName: + identifier + | 'abstract' + | 'attribute' + | 'body' + | 'callable' + | 'class' + | 'composes' + | 'datatype' + | 'definition' + | 'derivation' + | 'derived' + | 'enum' + | 'ensure' + | 'extends' + | 'id' + | 'import' + | 'initial' + | 'interface' + | 'key' + | 'model' + | 'operation' + | 'ordered' + | 'package' + | 'postcondition' + | 'precondition' + | 'primitive' + | 'property' + | 'readonly' + | 'reference' + | 'require' + | 'resolve' + | 'static' + | 'throws' + | 'transient' + | 'unique' + | 'unsettable' + | 'volatile' + | 'invariant' + | 'literal' + | 'serializable' + | 'annotation' + | 'model' + +; + +identifier: IDENTIFIER; +upper: INT | '*'; +lower: INT; + +INT : DIGIT+ ; +IDENTIFIER : (UNDERSCORE | LETTER) (LETTER | APOSTROPHE | DIGIT | UNDERSCORE | DOLLAR)* ; +SINGLE_CHARACTER: '\'' ~['\\] '\''; +DOUBLE_QUOTED_STRING: '"' ( ESCAPED_CHARACTER | ~('\\' | '"' ) )* '"' ; +SINGLE_QUOTED_STRING: '\'' ( ESCAPED_CHARACTER | ~('\'' | '\\') )* '\'' ; + +fragment LETTER: [a-zA-Z]; +fragment DIGIT: [0-9]; +fragment ESCAPED_CHARACTER: '\\' ('b' | 't' | 'n' | 'f' | 'r' | 'u' | '"' | '\'' | '\\'); +fragment UNDERSCORE: '_'; +fragment APOSTROPHE: '\''; +fragment DOLLAR: '$'; +fragment EXCLAMINATION_MARK: '!'; +fragment MINUS: '-'; +ML_SINGLE_QUOTED_STRING : '\'' .*? '\'' -> skip; +MULTILINE_COMMENT : '/*' .*? '*/' -> skip; +SINGLELINE_COMMENT : ('--' | '//') .*? '\r'? '\n' -> skip; +WS: [ \t\r\n]+ -> skip ; // toss out whitespace diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcore.tokens b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcore.tokens new file mode 100644 index 00000000..61cb97cf --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcore.tokens @@ -0,0 +1,277 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +T__7=8 +T__8=9 +T__9=10 +T__10=11 +T__11=12 +T__12=13 +T__13=14 +T__14=15 +T__15=16 +T__16=17 +T__17=18 +T__18=19 +T__19=20 +T__20=21 +T__21=22 +T__22=23 +T__23=24 +T__24=25 +T__25=26 +T__26=27 +T__27=28 +T__28=29 +T__29=30 +T__30=31 +T__31=32 +T__32=33 +T__33=34 +T__34=35 +T__35=36 +T__36=37 +T__37=38 +T__38=39 +T__39=40 +T__40=41 +T__41=42 +T__42=43 +T__43=44 +T__44=45 +T__45=46 +T__46=47 +T__47=48 +T__48=49 +T__49=50 +T__50=51 +T__51=52 +T__52=53 +T__53=54 +T__54=55 +T__55=56 +T__56=57 +T__57=58 +T__58=59 +T__59=60 +T__60=61 +T__61=62 +T__62=63 +T__63=64 +T__64=65 +T__65=66 +T__66=67 +T__67=68 +T__68=69 +T__69=70 +T__70=71 +T__71=72 +T__72=73 +T__73=74 +T__74=75 +T__75=76 +T__76=77 +T__77=78 +T__78=79 +T__79=80 +T__80=81 +T__81=82 +T__82=83 +T__83=84 +T__84=85 +T__85=86 +T__86=87 +T__87=88 +T__88=89 +T__89=90 +T__90=91 +T__91=92 +T__92=93 +T__93=94 +T__94=95 +T__95=96 +T__96=97 +T__97=98 +T__98=99 +T__99=100 +T__100=101 +T__101=102 +T__102=103 +T__103=104 +T__104=105 +T__105=106 +T__106=107 +T__107=108 +T__108=109 +T__109=110 +T__110=111 +T__111=112 +T__112=113 +T__113=114 +T__114=115 +T__115=116 +T__116=117 +T__117=118 +T__118=119 +T__119=120 +T__120=121 +T__121=122 +T__122=123 +T__123=124 +T__124=125 +T__125=126 +T__126=127 +T__127=128 +T__128=129 +T__129=130 +T__130=131 +T__131=132 +T__132=133 +T__133=134 +INT=135 +IDENTIFIER=136 +SINGLE_CHARACTER=137 +DOUBLE_QUOTED_STRING=138 +SINGLE_QUOTED_STRING=139 +ML_SINGLE_QUOTED_STRING=140 +MULTILINE_COMMENT=141 +SINGLELINE_COMMENT=142 +WS=143 +'options'=1 +'{'=2 +','=3 +'}'=4 +'symmetry_breaking'=5 +':'=6 +'bit_width'=7 +'skolem_depth'=8 +'sharing'=9 +'instance'=10 +';'=11 +'model'=12 +'['=13 +']'=14 +'true'=15 +'false'=16 +'+'=17 +'-'=18 +'.'=19 +'null'=20 +'import'=21 +'package'=22 +'='=23 +'abstract'=24 +'class'=25 +'interface'=26 +'extends'=27 +'static'=28 +'ghost'=29 +'transient'=30 +'volatile'=31 +'readonly'=32 +'attribute'=33 +'derived'=34 +'id'=35 +'ordered'=36 +'!ordered'=37 +'unique'=38 +'!unique'=39 +'unsettable'=40 +'!unsettable'=41 +'property'=42 +'#'=43 +'composes'=44 +'resolve'=45 +'!resolve'=46 +'key'=47 +'operation'=48 +'('=49 +')'=50 +'throws'=51 +'..'=52 +'*'=53 +'?'=54 +'|?'=55 +'|1'=56 +'primitive'=57 +'datatype'=58 +'serializable'=59 +'!serializable'=60 +'enum'=61 +'literal'=62 +'annotation'=63 +'reference'=64 +'<'=65 +'>'=66 +'&'=67 +'super'=68 +'::'=69 +'@'=70 +'Boolean'=71 +'Integer'=72 +'String'=73 +'Real'=74 +'UnlimitedNatural'=75 +'body'=76 +'callable'=77 +'invariant'=78 +'precondition'=79 +'requires'=80 +'postcondition'=81 +'ensures'=82 +'initial'=83 +'derivation'=84 +'public'=85 +'protected'=86 +'private'=87 +'no'=88 +'lone'=89 +'one'=90 +'some'=91 +'!'=92 +'not'=93 +'in'=94 +'<='=95 +'>='=96 +'sum'=97 +'|'=98 +'acyclic'=99 +'function'=100 +'->'=101 +'ord'=102 +'&&'=103 +'and'=104 +'||'=105 +'or'=106 +'=>'=107 +'if'=108 +'implies'=109 +'<=>'=110 +'iff'=111 +'all'=112 +'let'=113 +'~'=114 +'^'=115 +'++'=116 +'then'=117 +'else'=118 +'iden'=119 +'none'=120 +'univ'=121 +'ints'=122 +'plus'=123 +'minus'=124 +'mul'=125 +'/'=126 +'div'=127 +'%'=128 +'modulo'=129 +'disj'=130 +'set'=131 +'definition'=132 +'ensure'=133 +'require'=134 diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreBaseListener.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreBaseListener.java new file mode 100644 index 00000000..67f0d4ef --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreBaseListener.java @@ -0,0 +1,1718 @@ +// Generated from /home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcore.g4 by ANTLR 4.6 +package eu.modelwriter.core.alloyinecore.recognizer; + + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EcoreFactory; +import org.eclipse.emf.ecore.EcorePackage; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.ETypedElement; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EClassifier; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EOperation; +import org.eclipse.emf.ecore.EParameter; +import org.eclipse.emf.ecore.EEnum; +import org.eclipse.emf.ecore.EEnumLiteral; +import org.eclipse.emf.ecore.EDataType; +import org.eclipse.emf.ecore.ETypedElement; +import org.eclipse.emf.ecore.EAnnotation; +import org.eclipse.emf.ecore.EGenericType; +import org.eclipse.emf.ecore.ETypeParameter; + +import eu.modelwriter.core.alloyinecore.structure.base.INamespace; +import eu.modelwriter.core.alloyinecore.structure.base.Repository; +import eu.modelwriter.core.alloyinecore.structure.base.Element; + +import eu.modelwriter.core.alloyinecore.structure.model.ModelElement; +import eu.modelwriter.core.alloyinecore.structure.model.Annotation; +import eu.modelwriter.core.alloyinecore.structure.model.AnnotationDetail; +import eu.modelwriter.core.alloyinecore.structure.model.AnnotationReference; +import eu.modelwriter.core.alloyinecore.structure.model.NamedElement; +import eu.modelwriter.core.alloyinecore.structure.model.Model; +import eu.modelwriter.core.alloyinecore.structure.model.Import; +import eu.modelwriter.core.alloyinecore.structure.model.EcoreImport; +import eu.modelwriter.core.alloyinecore.structure.model.Package; +import eu.modelwriter.core.alloyinecore.structure.model.RootPackage; +import eu.modelwriter.core.alloyinecore.structure.model.Classifier; +import eu.modelwriter.core.alloyinecore.structure.model.Class; +import eu.modelwriter.core.alloyinecore.structure.model.Interface; +import eu.modelwriter.core.alloyinecore.structure.model.DataType; +import eu.modelwriter.core.alloyinecore.structure.model.Enum; +import eu.modelwriter.core.alloyinecore.structure.model.EnumLiteral; +import eu.modelwriter.core.alloyinecore.structure.model.StructuralFeature; +import eu.modelwriter.core.alloyinecore.structure.model.TypedElement; +import eu.modelwriter.core.alloyinecore.structure.model.Multiplicity; +import eu.modelwriter.core.alloyinecore.structure.model.Reference; +import eu.modelwriter.core.alloyinecore.structure.model.Attribute; +import eu.modelwriter.core.alloyinecore.structure.model.Operation; +import eu.modelwriter.core.alloyinecore.structure.model.Parameter; +import eu.modelwriter.core.alloyinecore.structure.model.GenericException; +import eu.modelwriter.core.alloyinecore.structure.model.TypeParameter; +import eu.modelwriter.core.alloyinecore.structure.model.GenericType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericTypeArgument; +import eu.modelwriter.core.alloyinecore.structure.model.GenericElementType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericSuperType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericWildcard; +import eu.modelwriter.core.alloyinecore.structure.model.PrimitiveType; +import eu.modelwriter.core.alloyinecore.structure.model.Invariant; +import eu.modelwriter.core.alloyinecore.structure.model.Derivation; +import eu.modelwriter.core.alloyinecore.structure.model.Body; +import eu.modelwriter.core.alloyinecore.structure.model.PostCondition; +import eu.modelwriter.core.alloyinecore.structure.model.PreCondition; +import eu.modelwriter.core.alloyinecore.structure.model.Initial; + +import eu.modelwriter.core.alloyinecore.structure.instance.ModelImport; +import eu.modelwriter.core.alloyinecore.structure.instance.Instance; +import eu.modelwriter.core.alloyinecore.structure.instance.Object; +import eu.modelwriter.core.alloyinecore.structure.instance.Slot; +import eu.modelwriter.core.alloyinecore.structure.instance.ObjectValue; +import eu.modelwriter.core.alloyinecore.structure.instance.EnumValue; +import eu.modelwriter.core.alloyinecore.structure.instance.IntegerValue; +import eu.modelwriter.core.alloyinecore.structure.instance.RealValue; +import eu.modelwriter.core.alloyinecore.structure.instance.BooleanValue; +import eu.modelwriter.core.alloyinecore.structure.instance.StringValue; +import eu.modelwriter.core.alloyinecore.structure.instance.NullValue; +import eu.modelwriter.core.alloyinecore.structure.instance.CharValue; + +import eu.modelwriter.core.alloyinecore.structure.constraints.Formula; +import eu.modelwriter.core.alloyinecore.structure.constraints.Expression; +import eu.modelwriter.core.alloyinecore.structure.constraints.IntExpression; +import eu.modelwriter.core.alloyinecore.structure.constraints.QuantifierDeclaration; +import eu.modelwriter.core.alloyinecore.structure.constraints.LetDeclaration; +import eu.modelwriter.core.alloyinecore.structure.constraints.ComprehensionDeclaration; +import eu.modelwriter.core.alloyinecore.structure.constraints.Variable; + +import eu.modelwriter.core.alloyinecore.internal.AnnotationSources; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl; +import org.eclipse.emf.ecore.util.EcoreUtil; + +import java.util.stream.Collectors; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +import java.io.IOException; + + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.TerminalNode; + +/** + * This class provides an empty implementation of {@link AlloyInEcoreListener}, + * which can be extended to create a listener which only needs to handle a subset + * of the available methods. + */ +public class AlloyInEcoreBaseListener implements AlloyInEcoreListener { + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterOptions(AlloyInEcoreParser.OptionsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitOptions(AlloyInEcoreParser.OptionsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterSymmetryBreaking(AlloyInEcoreParser.SymmetryBreakingContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitSymmetryBreaking(AlloyInEcoreParser.SymmetryBreakingContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterBitWidth(AlloyInEcoreParser.BitWidthContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitBitWidth(AlloyInEcoreParser.BitWidthContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterSkolemDepth(AlloyInEcoreParser.SkolemDepthContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitSkolemDepth(AlloyInEcoreParser.SkolemDepthContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterSharing(AlloyInEcoreParser.SharingContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitSharing(AlloyInEcoreParser.SharingContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterInstance(AlloyInEcoreParser.InstanceContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitInstance(AlloyInEcoreParser.InstanceContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterModelImport(AlloyInEcoreParser.ModelImportContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitModelImport(AlloyInEcoreParser.ModelImportContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEObject(AlloyInEcoreParser.EObjectContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEObject(AlloyInEcoreParser.EObjectContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterSlot(AlloyInEcoreParser.SlotContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitSlot(AlloyInEcoreParser.SlotContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterDataValue(AlloyInEcoreParser.DataValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitDataValue(AlloyInEcoreParser.DataValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterMultiValueData(AlloyInEcoreParser.MultiValueDataContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitMultiValueData(AlloyInEcoreParser.MultiValueDataContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEObjectValue(AlloyInEcoreParser.EObjectValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEObjectValue(AlloyInEcoreParser.EObjectValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterLiteralValue(AlloyInEcoreParser.LiteralValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitLiteralValue(AlloyInEcoreParser.LiteralValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEnumValue(AlloyInEcoreParser.EnumValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEnumValue(AlloyInEcoreParser.EnumValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterBooleanValue(AlloyInEcoreParser.BooleanValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitBooleanValue(AlloyInEcoreParser.BooleanValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIntegerValue(AlloyInEcoreParser.IntegerValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIntegerValue(AlloyInEcoreParser.IntegerValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterRealValue(AlloyInEcoreParser.RealValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitRealValue(AlloyInEcoreParser.RealValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterStringValue(AlloyInEcoreParser.StringValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitStringValue(AlloyInEcoreParser.StringValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterCharValue(AlloyInEcoreParser.CharValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitCharValue(AlloyInEcoreParser.CharValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterNullValue(AlloyInEcoreParser.NullValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitNullValue(AlloyInEcoreParser.NullValueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterModel(AlloyInEcoreParser.ModelContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitModel(AlloyInEcoreParser.ModelContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterPackageImport(AlloyInEcoreParser.PackageImportContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitPackageImport(AlloyInEcoreParser.PackageImportContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEPackage(AlloyInEcoreParser.EPackageContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEPackage(AlloyInEcoreParser.EPackageContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEClassifier(AlloyInEcoreParser.EClassifierContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEClassifier(AlloyInEcoreParser.EClassifierContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEClass(AlloyInEcoreParser.EClassContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEClass(AlloyInEcoreParser.EClassContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEStructuralFeature(AlloyInEcoreParser.EStructuralFeatureContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEStructuralFeature(AlloyInEcoreParser.EStructuralFeatureContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEAttribute(AlloyInEcoreParser.EAttributeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEAttribute(AlloyInEcoreParser.EAttributeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEReference(AlloyInEcoreParser.EReferenceContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEReference(AlloyInEcoreParser.EReferenceContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEOperation(AlloyInEcoreParser.EOperationContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEOperation(AlloyInEcoreParser.EOperationContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEGenericException(AlloyInEcoreParser.EGenericExceptionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEGenericException(AlloyInEcoreParser.EGenericExceptionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEGenericSuperType(AlloyInEcoreParser.EGenericSuperTypeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEGenericSuperType(AlloyInEcoreParser.EGenericSuperTypeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEParameter(AlloyInEcoreParser.EParameterContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEParameter(AlloyInEcoreParser.EParameterContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEMultiplicity(AlloyInEcoreParser.EMultiplicityContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEMultiplicity(AlloyInEcoreParser.EMultiplicityContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEDataType(AlloyInEcoreParser.EDataTypeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEDataType(AlloyInEcoreParser.EDataTypeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEEnum(AlloyInEcoreParser.EEnumContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEEnum(AlloyInEcoreParser.EEnumContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEEnumLiteral(AlloyInEcoreParser.EEnumLiteralContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEEnumLiteral(AlloyInEcoreParser.EEnumLiteralContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEAnnotation(AlloyInEcoreParser.EAnnotationContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEAnnotation(AlloyInEcoreParser.EAnnotationContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEDetail(AlloyInEcoreParser.EDetailContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEDetail(AlloyInEcoreParser.EDetailContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEModelElement(AlloyInEcoreParser.EModelElementContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEModelElement(AlloyInEcoreParser.EModelElementContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterENamedElement(AlloyInEcoreParser.ENamedElementContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitENamedElement(AlloyInEcoreParser.ENamedElementContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterETypedElement(AlloyInEcoreParser.ETypedElementContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitETypedElement(AlloyInEcoreParser.ETypedElementContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEModelElementRef(AlloyInEcoreParser.EModelElementRefContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEModelElementRef(AlloyInEcoreParser.EModelElementRefContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterTemplateSignature(AlloyInEcoreParser.TemplateSignatureContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitTemplateSignature(AlloyInEcoreParser.TemplateSignatureContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterETypeParameter(AlloyInEcoreParser.ETypeParameterContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitETypeParameter(AlloyInEcoreParser.ETypeParameterContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEGenericTypeArgument(AlloyInEcoreParser.EGenericTypeArgumentContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEGenericTypeArgument(AlloyInEcoreParser.EGenericTypeArgumentContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEGenericType(AlloyInEcoreParser.EGenericTypeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEGenericType(AlloyInEcoreParser.EGenericTypeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEGenericElementType(AlloyInEcoreParser.EGenericElementTypeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEGenericElementType(AlloyInEcoreParser.EGenericElementTypeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEGenericWildcard(AlloyInEcoreParser.EGenericWildcardContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEGenericWildcard(AlloyInEcoreParser.EGenericWildcardContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterPathName(AlloyInEcoreParser.PathNameContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitPathName(AlloyInEcoreParser.PathNameContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterSegment(AlloyInEcoreParser.SegmentContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitSegment(AlloyInEcoreParser.SegmentContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEPrimitiveType(AlloyInEcoreParser.EPrimitiveTypeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEPrimitiveType(AlloyInEcoreParser.EPrimitiveTypeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterBody(AlloyInEcoreParser.BodyContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitBody(AlloyInEcoreParser.BodyContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterInvariant(AlloyInEcoreParser.InvariantContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitInvariant(AlloyInEcoreParser.InvariantContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterPrecondition(AlloyInEcoreParser.PreconditionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitPrecondition(AlloyInEcoreParser.PreconditionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterPostcondition(AlloyInEcoreParser.PostconditionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitPostcondition(AlloyInEcoreParser.PostconditionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterInitial(AlloyInEcoreParser.InitialContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitInitial(AlloyInEcoreParser.InitialContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterDerivation(AlloyInEcoreParser.DerivationContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitDerivation(AlloyInEcoreParser.DerivationContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterVisibilityKind(AlloyInEcoreParser.VisibilityKindContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitVisibilityKind(AlloyInEcoreParser.VisibilityKindContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterNo(AlloyInEcoreParser.NoContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitNo(AlloyInEcoreParser.NoContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterSome(AlloyInEcoreParser.SomeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitSome(AlloyInEcoreParser.SomeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterForOne(AlloyInEcoreParser.ForOneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitForOne(AlloyInEcoreParser.ForOneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterSumDeclaration(AlloyInEcoreParser.SumDeclarationContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitSumDeclaration(AlloyInEcoreParser.SumDeclarationContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterForAll(AlloyInEcoreParser.ForAllContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitForAll(AlloyInEcoreParser.ForAllContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterLone(AlloyInEcoreParser.LoneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitLone(AlloyInEcoreParser.LoneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterLt(AlloyInEcoreParser.LtContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitLt(AlloyInEcoreParser.LtContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterForSome(AlloyInEcoreParser.ForSomeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitForSome(AlloyInEcoreParser.ForSomeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterNot(AlloyInEcoreParser.NotContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitNot(AlloyInEcoreParser.NotContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterF_paranthesis(AlloyInEcoreParser.F_paranthesisContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitF_paranthesis(AlloyInEcoreParser.F_paranthesisContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterAnd(AlloyInEcoreParser.AndContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitAnd(AlloyInEcoreParser.AndContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterFunction(AlloyInEcoreParser.FunctionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitFunction(AlloyInEcoreParser.FunctionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterGte(AlloyInEcoreParser.GteContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitGte(AlloyInEcoreParser.GteContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterAcyclic(AlloyInEcoreParser.AcyclicContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitAcyclic(AlloyInEcoreParser.AcyclicContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterLet(AlloyInEcoreParser.LetContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitLet(AlloyInEcoreParser.LetContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterLte(AlloyInEcoreParser.LteContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitLte(AlloyInEcoreParser.LteContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterOr(AlloyInEcoreParser.OrContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitOr(AlloyInEcoreParser.OrContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIn(AlloyInEcoreParser.InContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIn(AlloyInEcoreParser.InContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterOne(AlloyInEcoreParser.OneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitOne(AlloyInEcoreParser.OneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterFalse(AlloyInEcoreParser.FalseContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitFalse(AlloyInEcoreParser.FalseContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIff(AlloyInEcoreParser.IffContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIff(AlloyInEcoreParser.IffContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEq(AlloyInEcoreParser.EqContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEq(AlloyInEcoreParser.EqContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterGt(AlloyInEcoreParser.GtContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitGt(AlloyInEcoreParser.GtContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEqual(AlloyInEcoreParser.EqualContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEqual(AlloyInEcoreParser.EqualContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterForLone(AlloyInEcoreParser.ForLoneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitForLone(AlloyInEcoreParser.ForLoneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterTotalOrder(AlloyInEcoreParser.TotalOrderContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitTotalOrder(AlloyInEcoreParser.TotalOrderContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterTrue(AlloyInEcoreParser.TrueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitTrue(AlloyInEcoreParser.TrueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterForNo(AlloyInEcoreParser.ForNoContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitForNo(AlloyInEcoreParser.ForNoContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterImplies(AlloyInEcoreParser.ImpliesContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitImplies(AlloyInEcoreParser.ImpliesContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterProduct(AlloyInEcoreParser.ProductContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitProduct(AlloyInEcoreParser.ProductContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterNone(AlloyInEcoreParser.NoneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitNone(AlloyInEcoreParser.NoneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterUnion(AlloyInEcoreParser.UnionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitUnion(AlloyInEcoreParser.UnionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterComprehension(AlloyInEcoreParser.ComprehensionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitComprehension(AlloyInEcoreParser.ComprehensionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterUniv(AlloyInEcoreParser.UnivContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitUniv(AlloyInEcoreParser.UnivContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterReflexive(AlloyInEcoreParser.ReflexiveContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitReflexive(AlloyInEcoreParser.ReflexiveContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterE_paranthesis(AlloyInEcoreParser.E_paranthesisContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitE_paranthesis(AlloyInEcoreParser.E_paranthesisContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIden(AlloyInEcoreParser.IdenContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIden(AlloyInEcoreParser.IdenContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterInts(AlloyInEcoreParser.IntsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitInts(AlloyInEcoreParser.IntsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIntersection(AlloyInEcoreParser.IntersectionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIntersection(AlloyInEcoreParser.IntersectionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterDifference(AlloyInEcoreParser.DifferenceContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitDifference(AlloyInEcoreParser.DifferenceContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterTranspose(AlloyInEcoreParser.TransposeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitTranspose(AlloyInEcoreParser.TransposeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterJoin(AlloyInEcoreParser.JoinContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitJoin(AlloyInEcoreParser.JoinContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterOverride(AlloyInEcoreParser.OverrideContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitOverride(AlloyInEcoreParser.OverrideContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIfExpression(AlloyInEcoreParser.IfExpressionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIfExpression(AlloyInEcoreParser.IfExpressionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterClosure(AlloyInEcoreParser.ClosureContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitClosure(AlloyInEcoreParser.ClosureContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterTypeRef(AlloyInEcoreParser.TypeRefContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitTypeRef(AlloyInEcoreParser.TypeRefContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterBoxJoin(AlloyInEcoreParser.BoxJoinContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitBoxJoin(AlloyInEcoreParser.BoxJoinContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterMinus(AlloyInEcoreParser.MinusContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitMinus(AlloyInEcoreParser.MinusContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIntConstant(AlloyInEcoreParser.IntConstantContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIntConstant(AlloyInEcoreParser.IntConstantContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterI_paranthesis(AlloyInEcoreParser.I_paranthesisContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitI_paranthesis(AlloyInEcoreParser.I_paranthesisContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIfIntExpression(AlloyInEcoreParser.IfIntExpressionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIfIntExpression(AlloyInEcoreParser.IfIntExpressionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterCount(AlloyInEcoreParser.CountContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitCount(AlloyInEcoreParser.CountContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterSum(AlloyInEcoreParser.SumContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitSum(AlloyInEcoreParser.SumContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterDivide(AlloyInEcoreParser.DivideContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitDivide(AlloyInEcoreParser.DivideContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterMultiply(AlloyInEcoreParser.MultiplyContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitMultiply(AlloyInEcoreParser.MultiplyContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterModulo(AlloyInEcoreParser.ModuloContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitModulo(AlloyInEcoreParser.ModuloContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterPlus(AlloyInEcoreParser.PlusContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitPlus(AlloyInEcoreParser.PlusContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterQuantifierDeclarations(AlloyInEcoreParser.QuantifierDeclarationsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitQuantifierDeclarations(AlloyInEcoreParser.QuantifierDeclarationsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterOneOf(AlloyInEcoreParser.OneOfContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitOneOf(AlloyInEcoreParser.OneOfContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterLoneOf(AlloyInEcoreParser.LoneOfContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitLoneOf(AlloyInEcoreParser.LoneOfContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterSomeOf(AlloyInEcoreParser.SomeOfContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitSomeOf(AlloyInEcoreParser.SomeOfContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterSetOf(AlloyInEcoreParser.SetOfContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitSetOf(AlloyInEcoreParser.SetOfContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterLetDeclarations(AlloyInEcoreParser.LetDeclarationsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitLetDeclarations(AlloyInEcoreParser.LetDeclarationsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterLetDeclaration(AlloyInEcoreParser.LetDeclarationContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitLetDeclaration(AlloyInEcoreParser.LetDeclarationContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterComprehensionDeclarations(AlloyInEcoreParser.ComprehensionDeclarationsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitComprehensionDeclarations(AlloyInEcoreParser.ComprehensionDeclarationsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterComprehensionDeclaration(AlloyInEcoreParser.ComprehensionDeclarationContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitComprehensionDeclaration(AlloyInEcoreParser.ComprehensionDeclarationContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterRelationId(AlloyInEcoreParser.RelationIdContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitRelationId(AlloyInEcoreParser.RelationIdContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterVariable(AlloyInEcoreParser.VariableContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitVariable(AlloyInEcoreParser.VariableContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterMult(AlloyInEcoreParser.MultContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitMult(AlloyInEcoreParser.MultContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterUnrestrictedName(AlloyInEcoreParser.UnrestrictedNameContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitUnrestrictedName(AlloyInEcoreParser.UnrestrictedNameContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIdentifier(AlloyInEcoreParser.IdentifierContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIdentifier(AlloyInEcoreParser.IdentifierContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterUpper(AlloyInEcoreParser.UpperContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitUpper(AlloyInEcoreParser.UpperContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterLower(AlloyInEcoreParser.LowerContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitLower(AlloyInEcoreParser.LowerContext ctx) { } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEveryRule(ParserRuleContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEveryRule(ParserRuleContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void visitTerminal(TerminalNode node) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void visitErrorNode(ErrorNode node) { } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreBaseVisitor.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreBaseVisitor.java new file mode 100644 index 00000000..4f363308 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreBaseVisitor.java @@ -0,0 +1,1038 @@ +// Generated from /home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcore.g4 by ANTLR 4.6 +package eu.modelwriter.core.alloyinecore.recognizer; + + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EcoreFactory; +import org.eclipse.emf.ecore.EcorePackage; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.ETypedElement; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EClassifier; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EOperation; +import org.eclipse.emf.ecore.EParameter; +import org.eclipse.emf.ecore.EEnum; +import org.eclipse.emf.ecore.EEnumLiteral; +import org.eclipse.emf.ecore.EDataType; +import org.eclipse.emf.ecore.ETypedElement; +import org.eclipse.emf.ecore.EAnnotation; +import org.eclipse.emf.ecore.EGenericType; +import org.eclipse.emf.ecore.ETypeParameter; + +import eu.modelwriter.core.alloyinecore.structure.base.INamespace; +import eu.modelwriter.core.alloyinecore.structure.base.Repository; +import eu.modelwriter.core.alloyinecore.structure.base.Element; + +import eu.modelwriter.core.alloyinecore.structure.model.ModelElement; +import eu.modelwriter.core.alloyinecore.structure.model.Annotation; +import eu.modelwriter.core.alloyinecore.structure.model.AnnotationDetail; +import eu.modelwriter.core.alloyinecore.structure.model.AnnotationReference; +import eu.modelwriter.core.alloyinecore.structure.model.NamedElement; +import eu.modelwriter.core.alloyinecore.structure.model.Model; +import eu.modelwriter.core.alloyinecore.structure.model.Import; +import eu.modelwriter.core.alloyinecore.structure.model.EcoreImport; +import eu.modelwriter.core.alloyinecore.structure.model.Package; +import eu.modelwriter.core.alloyinecore.structure.model.RootPackage; +import eu.modelwriter.core.alloyinecore.structure.model.Classifier; +import eu.modelwriter.core.alloyinecore.structure.model.Class; +import eu.modelwriter.core.alloyinecore.structure.model.Interface; +import eu.modelwriter.core.alloyinecore.structure.model.DataType; +import eu.modelwriter.core.alloyinecore.structure.model.Enum; +import eu.modelwriter.core.alloyinecore.structure.model.EnumLiteral; +import eu.modelwriter.core.alloyinecore.structure.model.StructuralFeature; +import eu.modelwriter.core.alloyinecore.structure.model.TypedElement; +import eu.modelwriter.core.alloyinecore.structure.model.Multiplicity; +import eu.modelwriter.core.alloyinecore.structure.model.Reference; +import eu.modelwriter.core.alloyinecore.structure.model.Attribute; +import eu.modelwriter.core.alloyinecore.structure.model.Operation; +import eu.modelwriter.core.alloyinecore.structure.model.Parameter; +import eu.modelwriter.core.alloyinecore.structure.model.GenericException; +import eu.modelwriter.core.alloyinecore.structure.model.TypeParameter; +import eu.modelwriter.core.alloyinecore.structure.model.GenericType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericTypeArgument; +import eu.modelwriter.core.alloyinecore.structure.model.GenericElementType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericSuperType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericWildcard; +import eu.modelwriter.core.alloyinecore.structure.model.PrimitiveType; +import eu.modelwriter.core.alloyinecore.structure.model.Invariant; +import eu.modelwriter.core.alloyinecore.structure.model.Derivation; +import eu.modelwriter.core.alloyinecore.structure.model.Body; +import eu.modelwriter.core.alloyinecore.structure.model.PostCondition; +import eu.modelwriter.core.alloyinecore.structure.model.PreCondition; +import eu.modelwriter.core.alloyinecore.structure.model.Initial; + +import eu.modelwriter.core.alloyinecore.structure.instance.ModelImport; +import eu.modelwriter.core.alloyinecore.structure.instance.Instance; +import eu.modelwriter.core.alloyinecore.structure.instance.Object; +import eu.modelwriter.core.alloyinecore.structure.instance.Slot; +import eu.modelwriter.core.alloyinecore.structure.instance.ObjectValue; +import eu.modelwriter.core.alloyinecore.structure.instance.EnumValue; +import eu.modelwriter.core.alloyinecore.structure.instance.IntegerValue; +import eu.modelwriter.core.alloyinecore.structure.instance.RealValue; +import eu.modelwriter.core.alloyinecore.structure.instance.BooleanValue; +import eu.modelwriter.core.alloyinecore.structure.instance.StringValue; +import eu.modelwriter.core.alloyinecore.structure.instance.NullValue; +import eu.modelwriter.core.alloyinecore.structure.instance.CharValue; + +import eu.modelwriter.core.alloyinecore.structure.constraints.Formula; +import eu.modelwriter.core.alloyinecore.structure.constraints.Expression; +import eu.modelwriter.core.alloyinecore.structure.constraints.IntExpression; +import eu.modelwriter.core.alloyinecore.structure.constraints.QuantifierDeclaration; +import eu.modelwriter.core.alloyinecore.structure.constraints.LetDeclaration; +import eu.modelwriter.core.alloyinecore.structure.constraints.ComprehensionDeclaration; +import eu.modelwriter.core.alloyinecore.structure.constraints.Variable; + +import eu.modelwriter.core.alloyinecore.internal.AnnotationSources; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl; +import org.eclipse.emf.ecore.util.EcoreUtil; + +import java.util.stream.Collectors; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +import java.io.IOException; + +import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; + +/** + * This class provides an empty implementation of {@link AlloyInEcoreVisitor}, + * which can be extended to create a visitor which only needs to handle a subset + * of the available methods. + * + * @param The return type of the visit operation. Use {@link Void} for + * operations with no return type. + */ +public class AlloyInEcoreBaseVisitor extends AbstractParseTreeVisitor implements AlloyInEcoreVisitor { + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitOptions(AlloyInEcoreParser.OptionsContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitSymmetryBreaking(AlloyInEcoreParser.SymmetryBreakingContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitBitWidth(AlloyInEcoreParser.BitWidthContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitSkolemDepth(AlloyInEcoreParser.SkolemDepthContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitSharing(AlloyInEcoreParser.SharingContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitInstance(AlloyInEcoreParser.InstanceContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitModelImport(AlloyInEcoreParser.ModelImportContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEObject(AlloyInEcoreParser.EObjectContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitSlot(AlloyInEcoreParser.SlotContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitDataValue(AlloyInEcoreParser.DataValueContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitMultiValueData(AlloyInEcoreParser.MultiValueDataContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEObjectValue(AlloyInEcoreParser.EObjectValueContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitLiteralValue(AlloyInEcoreParser.LiteralValueContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEnumValue(AlloyInEcoreParser.EnumValueContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitBooleanValue(AlloyInEcoreParser.BooleanValueContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIntegerValue(AlloyInEcoreParser.IntegerValueContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitRealValue(AlloyInEcoreParser.RealValueContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitStringValue(AlloyInEcoreParser.StringValueContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitCharValue(AlloyInEcoreParser.CharValueContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitNullValue(AlloyInEcoreParser.NullValueContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitModel(AlloyInEcoreParser.ModelContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitPackageImport(AlloyInEcoreParser.PackageImportContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEPackage(AlloyInEcoreParser.EPackageContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEClassifier(AlloyInEcoreParser.EClassifierContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEClass(AlloyInEcoreParser.EClassContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEStructuralFeature(AlloyInEcoreParser.EStructuralFeatureContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEAttribute(AlloyInEcoreParser.EAttributeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEReference(AlloyInEcoreParser.EReferenceContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEOperation(AlloyInEcoreParser.EOperationContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEGenericException(AlloyInEcoreParser.EGenericExceptionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEGenericSuperType(AlloyInEcoreParser.EGenericSuperTypeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEParameter(AlloyInEcoreParser.EParameterContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEMultiplicity(AlloyInEcoreParser.EMultiplicityContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEDataType(AlloyInEcoreParser.EDataTypeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEEnum(AlloyInEcoreParser.EEnumContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEEnumLiteral(AlloyInEcoreParser.EEnumLiteralContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEAnnotation(AlloyInEcoreParser.EAnnotationContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEDetail(AlloyInEcoreParser.EDetailContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEModelElement(AlloyInEcoreParser.EModelElementContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitENamedElement(AlloyInEcoreParser.ENamedElementContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitETypedElement(AlloyInEcoreParser.ETypedElementContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEModelElementRef(AlloyInEcoreParser.EModelElementRefContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitTemplateSignature(AlloyInEcoreParser.TemplateSignatureContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitETypeParameter(AlloyInEcoreParser.ETypeParameterContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEGenericTypeArgument(AlloyInEcoreParser.EGenericTypeArgumentContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEGenericType(AlloyInEcoreParser.EGenericTypeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEGenericElementType(AlloyInEcoreParser.EGenericElementTypeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEGenericWildcard(AlloyInEcoreParser.EGenericWildcardContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitPathName(AlloyInEcoreParser.PathNameContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitSegment(AlloyInEcoreParser.SegmentContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEPrimitiveType(AlloyInEcoreParser.EPrimitiveTypeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitBody(AlloyInEcoreParser.BodyContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitInvariant(AlloyInEcoreParser.InvariantContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitPrecondition(AlloyInEcoreParser.PreconditionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitPostcondition(AlloyInEcoreParser.PostconditionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitInitial(AlloyInEcoreParser.InitialContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitDerivation(AlloyInEcoreParser.DerivationContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitVisibilityKind(AlloyInEcoreParser.VisibilityKindContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitNo(AlloyInEcoreParser.NoContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitSome(AlloyInEcoreParser.SomeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitForOne(AlloyInEcoreParser.ForOneContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitSumDeclaration(AlloyInEcoreParser.SumDeclarationContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitForAll(AlloyInEcoreParser.ForAllContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitLone(AlloyInEcoreParser.LoneContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitLt(AlloyInEcoreParser.LtContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitForSome(AlloyInEcoreParser.ForSomeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitNot(AlloyInEcoreParser.NotContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitF_paranthesis(AlloyInEcoreParser.F_paranthesisContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitAnd(AlloyInEcoreParser.AndContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitFunction(AlloyInEcoreParser.FunctionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitGte(AlloyInEcoreParser.GteContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitAcyclic(AlloyInEcoreParser.AcyclicContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitLet(AlloyInEcoreParser.LetContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitLte(AlloyInEcoreParser.LteContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitOr(AlloyInEcoreParser.OrContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIn(AlloyInEcoreParser.InContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitOne(AlloyInEcoreParser.OneContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitFalse(AlloyInEcoreParser.FalseContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIff(AlloyInEcoreParser.IffContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEq(AlloyInEcoreParser.EqContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitGt(AlloyInEcoreParser.GtContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEqual(AlloyInEcoreParser.EqualContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitForLone(AlloyInEcoreParser.ForLoneContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitTotalOrder(AlloyInEcoreParser.TotalOrderContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitTrue(AlloyInEcoreParser.TrueContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitForNo(AlloyInEcoreParser.ForNoContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitImplies(AlloyInEcoreParser.ImpliesContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitProduct(AlloyInEcoreParser.ProductContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitNone(AlloyInEcoreParser.NoneContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitUnion(AlloyInEcoreParser.UnionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitComprehension(AlloyInEcoreParser.ComprehensionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitUniv(AlloyInEcoreParser.UnivContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitReflexive(AlloyInEcoreParser.ReflexiveContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitE_paranthesis(AlloyInEcoreParser.E_paranthesisContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIden(AlloyInEcoreParser.IdenContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitInts(AlloyInEcoreParser.IntsContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIntersection(AlloyInEcoreParser.IntersectionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitDifference(AlloyInEcoreParser.DifferenceContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitTranspose(AlloyInEcoreParser.TransposeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitJoin(AlloyInEcoreParser.JoinContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitOverride(AlloyInEcoreParser.OverrideContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIfExpression(AlloyInEcoreParser.IfExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitClosure(AlloyInEcoreParser.ClosureContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitTypeRef(AlloyInEcoreParser.TypeRefContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitBoxJoin(AlloyInEcoreParser.BoxJoinContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitMinus(AlloyInEcoreParser.MinusContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIntConstant(AlloyInEcoreParser.IntConstantContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitI_paranthesis(AlloyInEcoreParser.I_paranthesisContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIfIntExpression(AlloyInEcoreParser.IfIntExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitCount(AlloyInEcoreParser.CountContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitSum(AlloyInEcoreParser.SumContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitDivide(AlloyInEcoreParser.DivideContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitMultiply(AlloyInEcoreParser.MultiplyContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitModulo(AlloyInEcoreParser.ModuloContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitPlus(AlloyInEcoreParser.PlusContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitQuantifierDeclarations(AlloyInEcoreParser.QuantifierDeclarationsContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitOneOf(AlloyInEcoreParser.OneOfContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitLoneOf(AlloyInEcoreParser.LoneOfContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitSomeOf(AlloyInEcoreParser.SomeOfContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitSetOf(AlloyInEcoreParser.SetOfContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitLetDeclarations(AlloyInEcoreParser.LetDeclarationsContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitLetDeclaration(AlloyInEcoreParser.LetDeclarationContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitComprehensionDeclarations(AlloyInEcoreParser.ComprehensionDeclarationsContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitComprehensionDeclaration(AlloyInEcoreParser.ComprehensionDeclarationContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitRelationId(AlloyInEcoreParser.RelationIdContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitVariable(AlloyInEcoreParser.VariableContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitMult(AlloyInEcoreParser.MultContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitUnrestrictedName(AlloyInEcoreParser.UnrestrictedNameContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIdentifier(AlloyInEcoreParser.IdentifierContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitUpper(AlloyInEcoreParser.UpperContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitLower(AlloyInEcoreParser.LowerContext ctx) { return visitChildren(ctx); } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreLexer.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreLexer.java new file mode 100644 index 00000000..7898f04f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreLexer.java @@ -0,0 +1,587 @@ +// Generated from /home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcore.g4 by ANTLR 4.6 +package eu.modelwriter.core.alloyinecore.recognizer; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.TokenStream; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.misc.*; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class AlloyInEcoreLexer extends Lexer { + static { RuntimeMetaData.checkVersion("4.6", RuntimeMetaData.VERSION); } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, + T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, + T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, + T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, T__29=30, T__30=31, + T__31=32, T__32=33, T__33=34, T__34=35, T__35=36, T__36=37, T__37=38, + T__38=39, T__39=40, T__40=41, T__41=42, T__42=43, T__43=44, T__44=45, + T__45=46, T__46=47, T__47=48, T__48=49, T__49=50, T__50=51, T__51=52, + T__52=53, T__53=54, T__54=55, T__55=56, T__56=57, T__57=58, T__58=59, + T__59=60, T__60=61, T__61=62, T__62=63, T__63=64, T__64=65, T__65=66, + T__66=67, T__67=68, T__68=69, T__69=70, T__70=71, T__71=72, T__72=73, + T__73=74, T__74=75, T__75=76, T__76=77, T__77=78, T__78=79, T__79=80, + T__80=81, T__81=82, T__82=83, T__83=84, T__84=85, T__85=86, T__86=87, + T__87=88, T__88=89, T__89=90, T__90=91, T__91=92, T__92=93, T__93=94, + T__94=95, T__95=96, T__96=97, T__97=98, T__98=99, T__99=100, T__100=101, + T__101=102, T__102=103, T__103=104, T__104=105, T__105=106, T__106=107, + T__107=108, T__108=109, T__109=110, T__110=111, T__111=112, T__112=113, + T__113=114, T__114=115, T__115=116, T__116=117, T__117=118, T__118=119, + T__119=120, T__120=121, T__121=122, T__122=123, T__123=124, T__124=125, + T__125=126, T__126=127, T__127=128, T__128=129, T__129=130, T__130=131, + T__131=132, T__132=133, T__133=134, INT=135, IDENTIFIER=136, SINGLE_CHARACTER=137, + DOUBLE_QUOTED_STRING=138, SINGLE_QUOTED_STRING=139, ML_SINGLE_QUOTED_STRING=140, + MULTILINE_COMMENT=141, SINGLELINE_COMMENT=142, WS=143; + public static String[] modeNames = { + "DEFAULT_MODE" + }; + + public static final String[] ruleNames = { + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", + "T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16", + "T__17", "T__18", "T__19", "T__20", "T__21", "T__22", "T__23", "T__24", + "T__25", "T__26", "T__27", "T__28", "T__29", "T__30", "T__31", "T__32", + "T__33", "T__34", "T__35", "T__36", "T__37", "T__38", "T__39", "T__40", + "T__41", "T__42", "T__43", "T__44", "T__45", "T__46", "T__47", "T__48", + "T__49", "T__50", "T__51", "T__52", "T__53", "T__54", "T__55", "T__56", + "T__57", "T__58", "T__59", "T__60", "T__61", "T__62", "T__63", "T__64", + "T__65", "T__66", "T__67", "T__68", "T__69", "T__70", "T__71", "T__72", + "T__73", "T__74", "T__75", "T__76", "T__77", "T__78", "T__79", "T__80", + "T__81", "T__82", "T__83", "T__84", "T__85", "T__86", "T__87", "T__88", + "T__89", "T__90", "T__91", "T__92", "T__93", "T__94", "T__95", "T__96", + "T__97", "T__98", "T__99", "T__100", "T__101", "T__102", "T__103", "T__104", + "T__105", "T__106", "T__107", "T__108", "T__109", "T__110", "T__111", + "T__112", "T__113", "T__114", "T__115", "T__116", "T__117", "T__118", + "T__119", "T__120", "T__121", "T__122", "T__123", "T__124", "T__125", + "T__126", "T__127", "T__128", "T__129", "T__130", "T__131", "T__132", + "T__133", "INT", "IDENTIFIER", "SINGLE_CHARACTER", "DOUBLE_QUOTED_STRING", + "SINGLE_QUOTED_STRING", "LETTER", "DIGIT", "ESCAPED_CHARACTER", "UNDERSCORE", + "APOSTROPHE", "DOLLAR", "EXCLAMINATION_MARK", "MINUS", "ML_SINGLE_QUOTED_STRING", + "MULTILINE_COMMENT", "SINGLELINE_COMMENT", "WS" + }; + + private static final String[] _LITERAL_NAMES = { + null, "'options'", "'{'", "','", "'}'", "'symmetry_breaking'", "':'", + "'bit_width'", "'skolem_depth'", "'sharing'", "'instance'", "';'", "'model'", + "'['", "']'", "'true'", "'false'", "'+'", "'-'", "'.'", "'null'", "'import'", + "'package'", "'='", "'abstract'", "'class'", "'interface'", "'extends'", + "'static'", "'ghost'", "'transient'", "'volatile'", "'readonly'", "'attribute'", + "'derived'", "'id'", "'ordered'", "'!ordered'", "'unique'", "'!unique'", + "'unsettable'", "'!unsettable'", "'property'", "'#'", "'composes'", "'resolve'", + "'!resolve'", "'key'", "'operation'", "'('", "')'", "'throws'", "'..'", + "'*'", "'?'", "'|?'", "'|1'", "'primitive'", "'datatype'", "'serializable'", + "'!serializable'", "'enum'", "'literal'", "'annotation'", "'reference'", + "'<'", "'>'", "'&'", "'super'", "'::'", "'@'", "'Boolean'", "'Integer'", + "'String'", "'Real'", "'UnlimitedNatural'", "'body'", "'callable'", "'invariant'", + "'precondition'", "'requires'", "'postcondition'", "'ensures'", "'initial'", + "'derivation'", "'public'", "'protected'", "'private'", "'no'", "'lone'", + "'one'", "'some'", "'!'", "'not'", "'in'", "'<='", "'>='", "'sum'", "'|'", + "'acyclic'", "'function'", "'->'", "'ord'", "'&&'", "'and'", "'||'", "'or'", + "'=>'", "'if'", "'implies'", "'<=>'", "'iff'", "'all'", "'let'", "'~'", + "'^'", "'++'", "'then'", "'else'", "'iden'", "'none'", "'univ'", "'ints'", + "'plus'", "'minus'", "'mul'", "'/'", "'div'", "'%'", "'modulo'", "'disj'", + "'set'", "'definition'", "'ensure'", "'require'" + }; + private static final String[] _SYMBOLIC_NAMES = { + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, "INT", "IDENTIFIER", "SINGLE_CHARACTER", "DOUBLE_QUOTED_STRING", + "SINGLE_QUOTED_STRING", "ML_SINGLE_QUOTED_STRING", "MULTILINE_COMMENT", + "SINGLELINE_COMMENT", "WS" + }; + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + + public AlloyInEcoreLexer(CharStream input) { + super(input); + _interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); + } + + @Override + public String getGrammarFileName() { return "AlloyInEcore.g4"; } + + @Override + public String[] getRuleNames() { return ruleNames; } + + @Override + public String getSerializedATN() { return _serializedATN; } + + @Override + public String[] getModeNames() { return modeNames; } + + @Override + public ATN getATN() { return _ATN; } + + public static final String _serializedATN = + "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2\u0091\u04cb\b\1\4"+ + "\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n"+ + "\4\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22"+ + "\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31"+ + "\t\31\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t"+ + " \4!\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t"+ + "+\4,\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64"+ + "\t\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:\4;\t;\4<\t<\4=\t"+ + "=\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4E\tE\4F\tF\4G\tG\4H\tH\4"+ + "I\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\4T\t"+ + "T\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4^\t^\4_\t_"+ + "\4`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\4h\th\4i\ti\4j\tj\4k"+ + "\tk\4l\tl\4m\tm\4n\tn\4o\to\4p\tp\4q\tq\4r\tr\4s\ts\4t\tt\4u\tu\4v\tv"+ + "\4w\tw\4x\tx\4y\ty\4z\tz\4{\t{\4|\t|\4}\t}\4~\t~\4\177\t\177\4\u0080\t"+ + "\u0080\4\u0081\t\u0081\4\u0082\t\u0082\4\u0083\t\u0083\4\u0084\t\u0084"+ + "\4\u0085\t\u0085\4\u0086\t\u0086\4\u0087\t\u0087\4\u0088\t\u0088\4\u0089"+ + "\t\u0089\4\u008a\t\u008a\4\u008b\t\u008b\4\u008c\t\u008c\4\u008d\t\u008d"+ + "\4\u008e\t\u008e\4\u008f\t\u008f\4\u0090\t\u0090\4\u0091\t\u0091\4\u0092"+ + "\t\u0092\4\u0093\t\u0093\4\u0094\t\u0094\4\u0095\t\u0095\4\u0096\t\u0096"+ + "\4\u0097\t\u0097\4\u0098\t\u0098\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\3\3"+ + "\3\3\4\3\4\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6"+ + "\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3"+ + "\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n"+ + "\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\r"+ + "\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\21"+ + "\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\23\3\23\3\24\3\24\3\25\3\25\3\25"+ + "\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27\3\27"+ + "\3\27\3\27\3\27\3\30\3\30\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31"+ + "\3\32\3\32\3\32\3\32\3\32\3\32\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33"+ + "\3\33\3\33\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\35\3\35\3\35\3\35"+ + "\3\35\3\35\3\35\3\36\3\36\3\36\3\36\3\36\3\36\3\37\3\37\3\37\3\37\3\37"+ + "\3\37\3\37\3\37\3\37\3\37\3 \3 \3 \3 \3 \3 \3 \3 \3 \3!\3!\3!\3!\3!\3"+ + "!\3!\3!\3!\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3#\3#\3#\3#\3#\3#\3"+ + "#\3#\3$\3$\3$\3%\3%\3%\3%\3%\3%\3%\3%\3&\3&\3&\3&\3&\3&\3&\3&\3&\3\'\3"+ + "\'\3\'\3\'\3\'\3\'\3\'\3(\3(\3(\3(\3(\3(\3(\3(\3)\3)\3)\3)\3)\3)\3)\3"+ + ")\3)\3)\3)\3*\3*\3*\3*\3*\3*\3*\3*\3*\3*\3*\3*\3+\3+\3+\3+\3+\3+\3+\3"+ + "+\3+\3,\3,\3-\3-\3-\3-\3-\3-\3-\3-\3-\3.\3.\3.\3.\3.\3.\3.\3.\3/\3/\3"+ + "/\3/\3/\3/\3/\3/\3/\3\60\3\60\3\60\3\60\3\61\3\61\3\61\3\61\3\61\3\61"+ + "\3\61\3\61\3\61\3\61\3\62\3\62\3\63\3\63\3\64\3\64\3\64\3\64\3\64\3\64"+ + "\3\64\3\65\3\65\3\65\3\66\3\66\3\67\3\67\38\38\38\39\39\39\3:\3:\3:\3"+ + ":\3:\3:\3:\3:\3:\3:\3;\3;\3;\3;\3;\3;\3;\3;\3;\3<\3<\3<\3<\3<\3<\3<\3"+ + "<\3<\3<\3<\3<\3<\3=\3=\3=\3=\3=\3=\3=\3=\3=\3=\3=\3=\3=\3=\3>\3>\3>\3"+ + ">\3>\3?\3?\3?\3?\3?\3?\3?\3?\3@\3@\3@\3@\3@\3@\3@\3@\3@\3@\3@\3A\3A\3"+ + "A\3A\3A\3A\3A\3A\3A\3A\3B\3B\3C\3C\3D\3D\3E\3E\3E\3E\3E\3E\3F\3F\3F\3"+ + "G\3G\3H\3H\3H\3H\3H\3H\3H\3H\3I\3I\3I\3I\3I\3I\3I\3I\3J\3J\3J\3J\3J\3"+ + "J\3J\3K\3K\3K\3K\3K\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3"+ + "L\3M\3M\3M\3M\3M\3N\3N\3N\3N\3N\3N\3N\3N\3N\3O\3O\3O\3O\3O\3O\3O\3O\3"+ + "O\3O\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3"+ + "Q\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3S\3S\3S\3S\3S\3S\3S\3S\3"+ + "T\3T\3T\3T\3T\3T\3T\3T\3U\3U\3U\3U\3U\3U\3U\3U\3U\3U\3U\3V\3V\3V\3V\3"+ + "V\3V\3V\3W\3W\3W\3W\3W\3W\3W\3W\3W\3W\3X\3X\3X\3X\3X\3X\3X\3X\3Y\3Y\3"+ + "Y\3Z\3Z\3Z\3Z\3Z\3[\3[\3[\3[\3\\\3\\\3\\\3\\\3\\\3]\3]\3^\3^\3^\3^\3_"+ + "\3_\3_\3`\3`\3`\3a\3a\3a\3b\3b\3b\3b\3c\3c\3d\3d\3d\3d\3d\3d\3d\3d\3e"+ + "\3e\3e\3e\3e\3e\3e\3e\3e\3f\3f\3f\3g\3g\3g\3g\3h\3h\3h\3i\3i\3i\3i\3j"+ + "\3j\3j\3k\3k\3k\3l\3l\3l\3m\3m\3m\3n\3n\3n\3n\3n\3n\3n\3n\3o\3o\3o\3o"+ + "\3p\3p\3p\3p\3q\3q\3q\3q\3r\3r\3r\3r\3s\3s\3t\3t\3u\3u\3u\3v\3v\3v\3v"+ + "\3v\3w\3w\3w\3w\3w\3x\3x\3x\3x\3x\3y\3y\3y\3y\3y\3z\3z\3z\3z\3z\3{\3{"+ + "\3{\3{\3{\3|\3|\3|\3|\3|\3}\3}\3}\3}\3}\3}\3~\3~\3~\3~\3\177\3\177\3\u0080"+ + "\3\u0080\3\u0080\3\u0080\3\u0081\3\u0081\3\u0082\3\u0082\3\u0082\3\u0082"+ + "\3\u0082\3\u0082\3\u0082\3\u0083\3\u0083\3\u0083\3\u0083\3\u0083\3\u0084"+ + "\3\u0084\3\u0084\3\u0084\3\u0085\3\u0085\3\u0085\3\u0085\3\u0085\3\u0085"+ + "\3\u0085\3\u0085\3\u0085\3\u0085\3\u0085\3\u0086\3\u0086\3\u0086\3\u0086"+ + "\3\u0086\3\u0086\3\u0086\3\u0087\3\u0087\3\u0087\3\u0087\3\u0087\3\u0087"+ + "\3\u0087\3\u0087\3\u0088\6\u0088\u045e\n\u0088\r\u0088\16\u0088\u045f"+ + "\3\u0089\3\u0089\5\u0089\u0464\n\u0089\3\u0089\3\u0089\3\u0089\3\u0089"+ + "\3\u0089\7\u0089\u046b\n\u0089\f\u0089\16\u0089\u046e\13\u0089\3\u008a"+ + "\3\u008a\3\u008a\3\u008a\3\u008b\3\u008b\3\u008b\7\u008b\u0477\n\u008b"+ + "\f\u008b\16\u008b\u047a\13\u008b\3\u008b\3\u008b\3\u008c\3\u008c\3\u008c"+ + "\7\u008c\u0481\n\u008c\f\u008c\16\u008c\u0484\13\u008c\3\u008c\3\u008c"+ + "\3\u008d\3\u008d\3\u008e\3\u008e\3\u008f\3\u008f\3\u008f\3\u0090\3\u0090"+ + "\3\u0091\3\u0091\3\u0092\3\u0092\3\u0093\3\u0093\3\u0094\3\u0094\3\u0095"+ + "\3\u0095\7\u0095\u049b\n\u0095\f\u0095\16\u0095\u049e\13\u0095\3\u0095"+ + "\3\u0095\3\u0095\3\u0095\3\u0096\3\u0096\3\u0096\3\u0096\7\u0096\u04a8"+ + "\n\u0096\f\u0096\16\u0096\u04ab\13\u0096\3\u0096\3\u0096\3\u0096\3\u0096"+ + "\3\u0096\3\u0097\3\u0097\3\u0097\3\u0097\5\u0097\u04b6\n\u0097\3\u0097"+ + "\7\u0097\u04b9\n\u0097\f\u0097\16\u0097\u04bc\13\u0097\3\u0097\5\u0097"+ + "\u04bf\n\u0097\3\u0097\3\u0097\3\u0097\3\u0097\3\u0098\6\u0098\u04c6\n"+ + "\u0098\r\u0098\16\u0098\u04c7\3\u0098\3\u0098\5\u049c\u04a9\u04ba\2\u0099"+ + "\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20"+ + "\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37"+ + "= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o"+ + "9q:s;u{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH"+ + "\u008fI\u0091J\u0093K\u0095L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1"+ + "R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5"+ + "\\\u00b7]\u00b9^\u00bb_\u00bd`\u00bfa\u00c1b\u00c3c\u00c5d\u00c7e\u00c9"+ + "f\u00cbg\u00cdh\u00cfi\u00d1j\u00d3k\u00d5l\u00d7m\u00d9n\u00dbo\u00dd"+ + "p\u00dfq\u00e1r\u00e3s\u00e5t\u00e7u\u00e9v\u00ebw\u00edx\u00efy\u00f1"+ + "z\u00f3{\u00f5|\u00f7}\u00f9~\u00fb\177\u00fd\u0080\u00ff\u0081\u0101"+ + "\u0082\u0103\u0083\u0105\u0084\u0107\u0085\u0109\u0086\u010b\u0087\u010d"+ + "\u0088\u010f\u0089\u0111\u008a\u0113\u008b\u0115\u008c\u0117\u008d\u0119"+ + "\2\u011b\2\u011d\2\u011f\2\u0121\2\u0123\2\u0125\2\u0127\2\u0129\u008e"+ + "\u012b\u008f\u012d\u0090\u012f\u0091\3\2\b\4\2))^^\4\2$$^^\4\2C\\c|\3"+ + "\2\62;\n\2$$))^^ddhhppttvw\5\2\13\f\17\17\"\"\u04d3\2\3\3\2\2\2\2\5\3"+ + "\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2"+ + "\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3"+ + "\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'"+ + "\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63"+ + "\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2"+ + "?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3"+ + "\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2"+ + "\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2"+ + "e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3"+ + "\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2"+ + "\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087"+ + "\3\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2"+ + "\2\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\2\u0099"+ + "\3\2\2\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2\2\2\u00a1\3\2\2"+ + "\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab"+ + "\3\2\2\2\2\u00ad\3\2\2\2\2\u00af\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2"+ + "\2\2\u00b5\3\2\2\2\2\u00b7\3\2\2\2\2\u00b9\3\2\2\2\2\u00bb\3\2\2\2\2\u00bd"+ + "\3\2\2\2\2\u00bf\3\2\2\2\2\u00c1\3\2\2\2\2\u00c3\3\2\2\2\2\u00c5\3\2\2"+ + "\2\2\u00c7\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb\3\2\2\2\2\u00cd\3\2\2\2\2\u00cf"+ + "\3\2\2\2\2\u00d1\3\2\2\2\2\u00d3\3\2\2\2\2\u00d5\3\2\2\2\2\u00d7\3\2\2"+ + "\2\2\u00d9\3\2\2\2\2\u00db\3\2\2\2\2\u00dd\3\2\2\2\2\u00df\3\2\2\2\2\u00e1"+ + "\3\2\2\2\2\u00e3\3\2\2\2\2\u00e5\3\2\2\2\2\u00e7\3\2\2\2\2\u00e9\3\2\2"+ + "\2\2\u00eb\3\2\2\2\2\u00ed\3\2\2\2\2\u00ef\3\2\2\2\2\u00f1\3\2\2\2\2\u00f3"+ + "\3\2\2\2\2\u00f5\3\2\2\2\2\u00f7\3\2\2\2\2\u00f9\3\2\2\2\2\u00fb\3\2\2"+ + "\2\2\u00fd\3\2\2\2\2\u00ff\3\2\2\2\2\u0101\3\2\2\2\2\u0103\3\2\2\2\2\u0105"+ + "\3\2\2\2\2\u0107\3\2\2\2\2\u0109\3\2\2\2\2\u010b\3\2\2\2\2\u010d\3\2\2"+ + "\2\2\u010f\3\2\2\2\2\u0111\3\2\2\2\2\u0113\3\2\2\2\2\u0115\3\2\2\2\2\u0117"+ + "\3\2\2\2\2\u0129\3\2\2\2\2\u012b\3\2\2\2\2\u012d\3\2\2\2\2\u012f\3\2\2"+ + "\2\3\u0131\3\2\2\2\5\u0139\3\2\2\2\7\u013b\3\2\2\2\t\u013d\3\2\2\2\13"+ + "\u013f\3\2\2\2\r\u0151\3\2\2\2\17\u0153\3\2\2\2\21\u015d\3\2\2\2\23\u016a"+ + "\3\2\2\2\25\u0172\3\2\2\2\27\u017b\3\2\2\2\31\u017d\3\2\2\2\33\u0183\3"+ + "\2\2\2\35\u0185\3\2\2\2\37\u0187\3\2\2\2!\u018c\3\2\2\2#\u0192\3\2\2\2"+ + "%\u0194\3\2\2\2\'\u0196\3\2\2\2)\u0198\3\2\2\2+\u019d\3\2\2\2-\u01a4\3"+ + "\2\2\2/\u01ac\3\2\2\2\61\u01ae\3\2\2\2\63\u01b7\3\2\2\2\65\u01bd\3\2\2"+ + "\2\67\u01c7\3\2\2\29\u01cf\3\2\2\2;\u01d6\3\2\2\2=\u01dc\3\2\2\2?\u01e6"+ + "\3\2\2\2A\u01ef\3\2\2\2C\u01f8\3\2\2\2E\u0202\3\2\2\2G\u020a\3\2\2\2I"+ + "\u020d\3\2\2\2K\u0215\3\2\2\2M\u021e\3\2\2\2O\u0225\3\2\2\2Q\u022d\3\2"+ + "\2\2S\u0238\3\2\2\2U\u0244\3\2\2\2W\u024d\3\2\2\2Y\u024f\3\2\2\2[\u0258"+ + "\3\2\2\2]\u0260\3\2\2\2_\u0269\3\2\2\2a\u026d\3\2\2\2c\u0277\3\2\2\2e"+ + "\u0279\3\2\2\2g\u027b\3\2\2\2i\u0282\3\2\2\2k\u0285\3\2\2\2m\u0287\3\2"+ + "\2\2o\u0289\3\2\2\2q\u028c\3\2\2\2s\u028f\3\2\2\2u\u0299\3\2\2\2w\u02a2"+ + "\3\2\2\2y\u02af\3\2\2\2{\u02bd\3\2\2\2}\u02c2\3\2\2\2\177\u02ca\3\2\2"+ + "\2\u0081\u02d5\3\2\2\2\u0083\u02df\3\2\2\2\u0085\u02e1\3\2\2\2\u0087\u02e3"+ + "\3\2\2\2\u0089\u02e5\3\2\2\2\u008b\u02eb\3\2\2\2\u008d\u02ee\3\2\2\2\u008f"+ + "\u02f0\3\2\2\2\u0091\u02f8\3\2\2\2\u0093\u0300\3\2\2\2\u0095\u0307\3\2"+ + "\2\2\u0097\u030c\3\2\2\2\u0099\u031d\3\2\2\2\u009b\u0322\3\2\2\2\u009d"+ + "\u032b\3\2\2\2\u009f\u0335\3\2\2\2\u00a1\u0342\3\2\2\2\u00a3\u034b\3\2"+ + "\2\2\u00a5\u0359\3\2\2\2\u00a7\u0361\3\2\2\2\u00a9\u0369\3\2\2\2\u00ab"+ + "\u0374\3\2\2\2\u00ad\u037b\3\2\2\2\u00af\u0385\3\2\2\2\u00b1\u038d\3\2"+ + "\2\2\u00b3\u0390\3\2\2\2\u00b5\u0395\3\2\2\2\u00b7\u0399\3\2\2\2\u00b9"+ + "\u039e\3\2\2\2\u00bb\u03a0\3\2\2\2\u00bd\u03a4\3\2\2\2\u00bf\u03a7\3\2"+ + "\2\2\u00c1\u03aa\3\2\2\2\u00c3\u03ad\3\2\2\2\u00c5\u03b1\3\2\2\2\u00c7"+ + "\u03b3\3\2\2\2\u00c9\u03bb\3\2\2\2\u00cb\u03c4\3\2\2\2\u00cd\u03c7\3\2"+ + "\2\2\u00cf\u03cb\3\2\2\2\u00d1\u03ce\3\2\2\2\u00d3\u03d2\3\2\2\2\u00d5"+ + "\u03d5\3\2\2\2\u00d7\u03d8\3\2\2\2\u00d9\u03db\3\2\2\2\u00db\u03de\3\2"+ + "\2\2\u00dd\u03e6\3\2\2\2\u00df\u03ea\3\2\2\2\u00e1\u03ee\3\2\2\2\u00e3"+ + "\u03f2\3\2\2\2\u00e5\u03f6\3\2\2\2\u00e7\u03f8\3\2\2\2\u00e9\u03fa\3\2"+ + "\2\2\u00eb\u03fd\3\2\2\2\u00ed\u0402\3\2\2\2\u00ef\u0407\3\2\2\2\u00f1"+ + "\u040c\3\2\2\2\u00f3\u0411\3\2\2\2\u00f5\u0416\3\2\2\2\u00f7\u041b\3\2"+ + "\2\2\u00f9\u0420\3\2\2\2\u00fb\u0426\3\2\2\2\u00fd\u042a\3\2\2\2\u00ff"+ + "\u042c\3\2\2\2\u0101\u0430\3\2\2\2\u0103\u0432\3\2\2\2\u0105\u0439\3\2"+ + "\2\2\u0107\u043e\3\2\2\2\u0109\u0442\3\2\2\2\u010b\u044d\3\2\2\2\u010d"+ + "\u0454\3\2\2\2\u010f\u045d\3\2\2\2\u0111\u0463\3\2\2\2\u0113\u046f\3\2"+ + "\2\2\u0115\u0473\3\2\2\2\u0117\u047d\3\2\2\2\u0119\u0487\3\2\2\2\u011b"+ + "\u0489\3\2\2\2\u011d\u048b\3\2\2\2\u011f\u048e\3\2\2\2\u0121\u0490\3\2"+ + "\2\2\u0123\u0492\3\2\2\2\u0125\u0494\3\2\2\2\u0127\u0496\3\2\2\2\u0129"+ + "\u0498\3\2\2\2\u012b\u04a3\3\2\2\2\u012d\u04b5\3\2\2\2\u012f\u04c5\3\2"+ + "\2\2\u0131\u0132\7q\2\2\u0132\u0133\7r\2\2\u0133\u0134\7v\2\2\u0134\u0135"+ + "\7k\2\2\u0135\u0136\7q\2\2\u0136\u0137\7p\2\2\u0137\u0138\7u\2\2\u0138"+ + "\4\3\2\2\2\u0139\u013a\7}\2\2\u013a\6\3\2\2\2\u013b\u013c\7.\2\2\u013c"+ + "\b\3\2\2\2\u013d\u013e\7\177\2\2\u013e\n\3\2\2\2\u013f\u0140\7u\2\2\u0140"+ + "\u0141\7{\2\2\u0141\u0142\7o\2\2\u0142\u0143\7o\2\2\u0143\u0144\7g\2\2"+ + "\u0144\u0145\7v\2\2\u0145\u0146\7t\2\2\u0146\u0147\7{\2\2\u0147\u0148"+ + "\7a\2\2\u0148\u0149\7d\2\2\u0149\u014a\7t\2\2\u014a\u014b\7g\2\2\u014b"+ + "\u014c\7c\2\2\u014c\u014d\7m\2\2\u014d\u014e\7k\2\2\u014e\u014f\7p\2\2"+ + "\u014f\u0150\7i\2\2\u0150\f\3\2\2\2\u0151\u0152\7<\2\2\u0152\16\3\2\2"+ + "\2\u0153\u0154\7d\2\2\u0154\u0155\7k\2\2\u0155\u0156\7v\2\2\u0156\u0157"+ + "\7a\2\2\u0157\u0158\7y\2\2\u0158\u0159\7k\2\2\u0159\u015a\7f\2\2\u015a"+ + "\u015b\7v\2\2\u015b\u015c\7j\2\2\u015c\20\3\2\2\2\u015d\u015e\7u\2\2\u015e"+ + "\u015f\7m\2\2\u015f\u0160\7q\2\2\u0160\u0161\7n\2\2\u0161\u0162\7g\2\2"+ + "\u0162\u0163\7o\2\2\u0163\u0164\7a\2\2\u0164\u0165\7f\2\2\u0165\u0166"+ + "\7g\2\2\u0166\u0167\7r\2\2\u0167\u0168\7v\2\2\u0168\u0169\7j\2\2\u0169"+ + "\22\3\2\2\2\u016a\u016b\7u\2\2\u016b\u016c\7j\2\2\u016c\u016d\7c\2\2\u016d"+ + "\u016e\7t\2\2\u016e\u016f\7k\2\2\u016f\u0170\7p\2\2\u0170\u0171\7i\2\2"+ + "\u0171\24\3\2\2\2\u0172\u0173\7k\2\2\u0173\u0174\7p\2\2\u0174\u0175\7"+ + "u\2\2\u0175\u0176\7v\2\2\u0176\u0177\7c\2\2\u0177\u0178\7p\2\2\u0178\u0179"+ + "\7e\2\2\u0179\u017a\7g\2\2\u017a\26\3\2\2\2\u017b\u017c\7=\2\2\u017c\30"+ + "\3\2\2\2\u017d\u017e\7o\2\2\u017e\u017f\7q\2\2\u017f\u0180\7f\2\2\u0180"+ + "\u0181\7g\2\2\u0181\u0182\7n\2\2\u0182\32\3\2\2\2\u0183\u0184\7]\2\2\u0184"+ + "\34\3\2\2\2\u0185\u0186\7_\2\2\u0186\36\3\2\2\2\u0187\u0188\7v\2\2\u0188"+ + "\u0189\7t\2\2\u0189\u018a\7w\2\2\u018a\u018b\7g\2\2\u018b \3\2\2\2\u018c"+ + "\u018d\7h\2\2\u018d\u018e\7c\2\2\u018e\u018f\7n\2\2\u018f\u0190\7u\2\2"+ + "\u0190\u0191\7g\2\2\u0191\"\3\2\2\2\u0192\u0193\7-\2\2\u0193$\3\2\2\2"+ + "\u0194\u0195\7/\2\2\u0195&\3\2\2\2\u0196\u0197\7\60\2\2\u0197(\3\2\2\2"+ + "\u0198\u0199\7p\2\2\u0199\u019a\7w\2\2\u019a\u019b\7n\2\2\u019b\u019c"+ + "\7n\2\2\u019c*\3\2\2\2\u019d\u019e\7k\2\2\u019e\u019f\7o\2\2\u019f\u01a0"+ + "\7r\2\2\u01a0\u01a1\7q\2\2\u01a1\u01a2\7t\2\2\u01a2\u01a3\7v\2\2\u01a3"+ + ",\3\2\2\2\u01a4\u01a5\7r\2\2\u01a5\u01a6\7c\2\2\u01a6\u01a7\7e\2\2\u01a7"+ + "\u01a8\7m\2\2\u01a8\u01a9\7c\2\2\u01a9\u01aa\7i\2\2\u01aa\u01ab\7g\2\2"+ + "\u01ab.\3\2\2\2\u01ac\u01ad\7?\2\2\u01ad\60\3\2\2\2\u01ae\u01af\7c\2\2"+ + "\u01af\u01b0\7d\2\2\u01b0\u01b1\7u\2\2\u01b1\u01b2\7v\2\2\u01b2\u01b3"+ + "\7t\2\2\u01b3\u01b4\7c\2\2\u01b4\u01b5\7e\2\2\u01b5\u01b6\7v\2\2\u01b6"+ + "\62\3\2\2\2\u01b7\u01b8\7e\2\2\u01b8\u01b9\7n\2\2\u01b9\u01ba\7c\2\2\u01ba"+ + "\u01bb\7u\2\2\u01bb\u01bc\7u\2\2\u01bc\64\3\2\2\2\u01bd\u01be\7k\2\2\u01be"+ + "\u01bf\7p\2\2\u01bf\u01c0\7v\2\2\u01c0\u01c1\7g\2\2\u01c1\u01c2\7t\2\2"+ + "\u01c2\u01c3\7h\2\2\u01c3\u01c4\7c\2\2\u01c4\u01c5\7e\2\2\u01c5\u01c6"+ + "\7g\2\2\u01c6\66\3\2\2\2\u01c7\u01c8\7g\2\2\u01c8\u01c9\7z\2\2\u01c9\u01ca"+ + "\7v\2\2\u01ca\u01cb\7g\2\2\u01cb\u01cc\7p\2\2\u01cc\u01cd\7f\2\2\u01cd"+ + "\u01ce\7u\2\2\u01ce8\3\2\2\2\u01cf\u01d0\7u\2\2\u01d0\u01d1\7v\2\2\u01d1"+ + "\u01d2\7c\2\2\u01d2\u01d3\7v\2\2\u01d3\u01d4\7k\2\2\u01d4\u01d5\7e\2\2"+ + "\u01d5:\3\2\2\2\u01d6\u01d7\7i\2\2\u01d7\u01d8\7j\2\2\u01d8\u01d9\7q\2"+ + "\2\u01d9\u01da\7u\2\2\u01da\u01db\7v\2\2\u01db<\3\2\2\2\u01dc\u01dd\7"+ + "v\2\2\u01dd\u01de\7t\2\2\u01de\u01df\7c\2\2\u01df\u01e0\7p\2\2\u01e0\u01e1"+ + "\7u\2\2\u01e1\u01e2\7k\2\2\u01e2\u01e3\7g\2\2\u01e3\u01e4\7p\2\2\u01e4"+ + "\u01e5\7v\2\2\u01e5>\3\2\2\2\u01e6\u01e7\7x\2\2\u01e7\u01e8\7q\2\2\u01e8"+ + "\u01e9\7n\2\2\u01e9\u01ea\7c\2\2\u01ea\u01eb\7v\2\2\u01eb\u01ec\7k\2\2"+ + "\u01ec\u01ed\7n\2\2\u01ed\u01ee\7g\2\2\u01ee@\3\2\2\2\u01ef\u01f0\7t\2"+ + "\2\u01f0\u01f1\7g\2\2\u01f1\u01f2\7c\2\2\u01f2\u01f3\7f\2\2\u01f3\u01f4"+ + "\7q\2\2\u01f4\u01f5\7p\2\2\u01f5\u01f6\7n\2\2\u01f6\u01f7\7{\2\2\u01f7"+ + "B\3\2\2\2\u01f8\u01f9\7c\2\2\u01f9\u01fa\7v\2\2\u01fa\u01fb\7v\2\2\u01fb"+ + "\u01fc\7t\2\2\u01fc\u01fd\7k\2\2\u01fd\u01fe\7d\2\2\u01fe\u01ff\7w\2\2"+ + "\u01ff\u0200\7v\2\2\u0200\u0201\7g\2\2\u0201D\3\2\2\2\u0202\u0203\7f\2"+ + "\2\u0203\u0204\7g\2\2\u0204\u0205\7t\2\2\u0205\u0206\7k\2\2\u0206\u0207"+ + "\7x\2\2\u0207\u0208\7g\2\2\u0208\u0209\7f\2\2\u0209F\3\2\2\2\u020a\u020b"+ + "\7k\2\2\u020b\u020c\7f\2\2\u020cH\3\2\2\2\u020d\u020e\7q\2\2\u020e\u020f"+ + "\7t\2\2\u020f\u0210\7f\2\2\u0210\u0211\7g\2\2\u0211\u0212\7t\2\2\u0212"+ + "\u0213\7g\2\2\u0213\u0214\7f\2\2\u0214J\3\2\2\2\u0215\u0216\7#\2\2\u0216"+ + "\u0217\7q\2\2\u0217\u0218\7t\2\2\u0218\u0219\7f\2\2\u0219\u021a\7g\2\2"+ + "\u021a\u021b\7t\2\2\u021b\u021c\7g\2\2\u021c\u021d\7f\2\2\u021dL\3\2\2"+ + "\2\u021e\u021f\7w\2\2\u021f\u0220\7p\2\2\u0220\u0221\7k\2\2\u0221\u0222"+ + "\7s\2\2\u0222\u0223\7w\2\2\u0223\u0224\7g\2\2\u0224N\3\2\2\2\u0225\u0226"+ + "\7#\2\2\u0226\u0227\7w\2\2\u0227\u0228\7p\2\2\u0228\u0229\7k\2\2\u0229"+ + "\u022a\7s\2\2\u022a\u022b\7w\2\2\u022b\u022c\7g\2\2\u022cP\3\2\2\2\u022d"+ + "\u022e\7w\2\2\u022e\u022f\7p\2\2\u022f\u0230\7u\2\2\u0230\u0231\7g\2\2"+ + "\u0231\u0232\7v\2\2\u0232\u0233\7v\2\2\u0233\u0234\7c\2\2\u0234\u0235"+ + "\7d\2\2\u0235\u0236\7n\2\2\u0236\u0237\7g\2\2\u0237R\3\2\2\2\u0238\u0239"+ + "\7#\2\2\u0239\u023a\7w\2\2\u023a\u023b\7p\2\2\u023b\u023c\7u\2\2\u023c"+ + "\u023d\7g\2\2\u023d\u023e\7v\2\2\u023e\u023f\7v\2\2\u023f\u0240\7c\2\2"+ + "\u0240\u0241\7d\2\2\u0241\u0242\7n\2\2\u0242\u0243\7g\2\2\u0243T\3\2\2"+ + "\2\u0244\u0245\7r\2\2\u0245\u0246\7t\2\2\u0246\u0247\7q\2\2\u0247\u0248"+ + "\7r\2\2\u0248\u0249\7g\2\2\u0249\u024a\7t\2\2\u024a\u024b\7v\2\2\u024b"+ + "\u024c\7{\2\2\u024cV\3\2\2\2\u024d\u024e\7%\2\2\u024eX\3\2\2\2\u024f\u0250"+ + "\7e\2\2\u0250\u0251\7q\2\2\u0251\u0252\7o\2\2\u0252\u0253\7r\2\2\u0253"+ + "\u0254\7q\2\2\u0254\u0255\7u\2\2\u0255\u0256\7g\2\2\u0256\u0257\7u\2\2"+ + "\u0257Z\3\2\2\2\u0258\u0259\7t\2\2\u0259\u025a\7g\2\2\u025a\u025b\7u\2"+ + "\2\u025b\u025c\7q\2\2\u025c\u025d\7n\2\2\u025d\u025e\7x\2\2\u025e\u025f"+ + "\7g\2\2\u025f\\\3\2\2\2\u0260\u0261\7#\2\2\u0261\u0262\7t\2\2\u0262\u0263"+ + "\7g\2\2\u0263\u0264\7u\2\2\u0264\u0265\7q\2\2\u0265\u0266\7n\2\2\u0266"+ + "\u0267\7x\2\2\u0267\u0268\7g\2\2\u0268^\3\2\2\2\u0269\u026a\7m\2\2\u026a"+ + "\u026b\7g\2\2\u026b\u026c\7{\2\2\u026c`\3\2\2\2\u026d\u026e\7q\2\2\u026e"+ + "\u026f\7r\2\2\u026f\u0270\7g\2\2\u0270\u0271\7t\2\2\u0271\u0272\7c\2\2"+ + "\u0272\u0273\7v\2\2\u0273\u0274\7k\2\2\u0274\u0275\7q\2\2\u0275\u0276"+ + "\7p\2\2\u0276b\3\2\2\2\u0277\u0278\7*\2\2\u0278d\3\2\2\2\u0279\u027a\7"+ + "+\2\2\u027af\3\2\2\2\u027b\u027c\7v\2\2\u027c\u027d\7j\2\2\u027d\u027e"+ + "\7t\2\2\u027e\u027f\7q\2\2\u027f\u0280\7y\2\2\u0280\u0281\7u\2\2\u0281"+ + "h\3\2\2\2\u0282\u0283\7\60\2\2\u0283\u0284\7\60\2\2\u0284j\3\2\2\2\u0285"+ + "\u0286\7,\2\2\u0286l\3\2\2\2\u0287\u0288\7A\2\2\u0288n\3\2\2\2\u0289\u028a"+ + "\7~\2\2\u028a\u028b\7A\2\2\u028bp\3\2\2\2\u028c\u028d\7~\2\2\u028d\u028e"+ + "\7\63\2\2\u028er\3\2\2\2\u028f\u0290\7r\2\2\u0290\u0291\7t\2\2\u0291\u0292"+ + "\7k\2\2\u0292\u0293\7o\2\2\u0293\u0294\7k\2\2\u0294\u0295\7v\2\2\u0295"+ + "\u0296\7k\2\2\u0296\u0297\7x\2\2\u0297\u0298\7g\2\2\u0298t\3\2\2\2\u0299"+ + "\u029a\7f\2\2\u029a\u029b\7c\2\2\u029b\u029c\7v\2\2\u029c\u029d\7c\2\2"+ + "\u029d\u029e\7v\2\2\u029e\u029f\7{\2\2\u029f\u02a0\7r\2\2\u02a0\u02a1"+ + "\7g\2\2\u02a1v\3\2\2\2\u02a2\u02a3\7u\2\2\u02a3\u02a4\7g\2\2\u02a4\u02a5"+ + "\7t\2\2\u02a5\u02a6\7k\2\2\u02a6\u02a7\7c\2\2\u02a7\u02a8\7n\2\2\u02a8"+ + "\u02a9\7k\2\2\u02a9\u02aa\7|\2\2\u02aa\u02ab\7c\2\2\u02ab\u02ac\7d\2\2"+ + "\u02ac\u02ad\7n\2\2\u02ad\u02ae\7g\2\2\u02aex\3\2\2\2\u02af\u02b0\7#\2"+ + "\2\u02b0\u02b1\7u\2\2\u02b1\u02b2\7g\2\2\u02b2\u02b3\7t\2\2\u02b3\u02b4"+ + "\7k\2\2\u02b4\u02b5\7c\2\2\u02b5\u02b6\7n\2\2\u02b6\u02b7\7k\2\2\u02b7"+ + "\u02b8\7|\2\2\u02b8\u02b9\7c\2\2\u02b9\u02ba\7d\2\2\u02ba\u02bb\7n\2\2"+ + "\u02bb\u02bc\7g\2\2\u02bcz\3\2\2\2\u02bd\u02be\7g\2\2\u02be\u02bf\7p\2"+ + "\2\u02bf\u02c0\7w\2\2\u02c0\u02c1\7o\2\2\u02c1|\3\2\2\2\u02c2\u02c3\7"+ + "n\2\2\u02c3\u02c4\7k\2\2\u02c4\u02c5\7v\2\2\u02c5\u02c6\7g\2\2\u02c6\u02c7"+ + "\7t\2\2\u02c7\u02c8\7c\2\2\u02c8\u02c9\7n\2\2\u02c9~\3\2\2\2\u02ca\u02cb"+ + "\7c\2\2\u02cb\u02cc\7p\2\2\u02cc\u02cd\7p\2\2\u02cd\u02ce\7q\2\2\u02ce"+ + "\u02cf\7v\2\2\u02cf\u02d0\7c\2\2\u02d0\u02d1\7v\2\2\u02d1\u02d2\7k\2\2"+ + "\u02d2\u02d3\7q\2\2\u02d3\u02d4\7p\2\2\u02d4\u0080\3\2\2\2\u02d5\u02d6"+ + "\7t\2\2\u02d6\u02d7\7g\2\2\u02d7\u02d8\7h\2\2\u02d8\u02d9\7g\2\2\u02d9"+ + "\u02da\7t\2\2\u02da\u02db\7g\2\2\u02db\u02dc\7p\2\2\u02dc\u02dd\7e\2\2"+ + "\u02dd\u02de\7g\2\2\u02de\u0082\3\2\2\2\u02df\u02e0\7>\2\2\u02e0\u0084"+ + "\3\2\2\2\u02e1\u02e2\7@\2\2\u02e2\u0086\3\2\2\2\u02e3\u02e4\7(\2\2\u02e4"+ + "\u0088\3\2\2\2\u02e5\u02e6\7u\2\2\u02e6\u02e7\7w\2\2\u02e7\u02e8\7r\2"+ + "\2\u02e8\u02e9\7g\2\2\u02e9\u02ea\7t\2\2\u02ea\u008a\3\2\2\2\u02eb\u02ec"+ + "\7<\2\2\u02ec\u02ed\7<\2\2\u02ed\u008c\3\2\2\2\u02ee\u02ef\7B\2\2\u02ef"+ + "\u008e\3\2\2\2\u02f0\u02f1\7D\2\2\u02f1\u02f2\7q\2\2\u02f2\u02f3\7q\2"+ + "\2\u02f3\u02f4\7n\2\2\u02f4\u02f5\7g\2\2\u02f5\u02f6\7c\2\2\u02f6\u02f7"+ + "\7p\2\2\u02f7\u0090\3\2\2\2\u02f8\u02f9\7K\2\2\u02f9\u02fa\7p\2\2\u02fa"+ + "\u02fb\7v\2\2\u02fb\u02fc\7g\2\2\u02fc\u02fd\7i\2\2\u02fd\u02fe\7g\2\2"+ + "\u02fe\u02ff\7t\2\2\u02ff\u0092\3\2\2\2\u0300\u0301\7U\2\2\u0301\u0302"+ + "\7v\2\2\u0302\u0303\7t\2\2\u0303\u0304\7k\2\2\u0304\u0305\7p\2\2\u0305"+ + "\u0306\7i\2\2\u0306\u0094\3\2\2\2\u0307\u0308\7T\2\2\u0308\u0309\7g\2"+ + "\2\u0309\u030a\7c\2\2\u030a\u030b\7n\2\2\u030b\u0096\3\2\2\2\u030c\u030d"+ + "\7W\2\2\u030d\u030e\7p\2\2\u030e\u030f\7n\2\2\u030f\u0310\7k\2\2\u0310"+ + "\u0311\7o\2\2\u0311\u0312\7k\2\2\u0312\u0313\7v\2\2\u0313\u0314\7g\2\2"+ + "\u0314\u0315\7f\2\2\u0315\u0316\7P\2\2\u0316\u0317\7c\2\2\u0317\u0318"+ + "\7v\2\2\u0318\u0319\7w\2\2\u0319\u031a\7t\2\2\u031a\u031b\7c\2\2\u031b"+ + "\u031c\7n\2\2\u031c\u0098\3\2\2\2\u031d\u031e\7d\2\2\u031e\u031f\7q\2"+ + "\2\u031f\u0320\7f\2\2\u0320\u0321\7{\2\2\u0321\u009a\3\2\2\2\u0322\u0323"+ + "\7e\2\2\u0323\u0324\7c\2\2\u0324\u0325\7n\2\2\u0325\u0326\7n\2\2\u0326"+ + "\u0327\7c\2\2\u0327\u0328\7d\2\2\u0328\u0329\7n\2\2\u0329\u032a\7g\2\2"+ + "\u032a\u009c\3\2\2\2\u032b\u032c\7k\2\2\u032c\u032d\7p\2\2\u032d\u032e"+ + "\7x\2\2\u032e\u032f\7c\2\2\u032f\u0330\7t\2\2\u0330\u0331\7k\2\2\u0331"+ + "\u0332\7c\2\2\u0332\u0333\7p\2\2\u0333\u0334\7v\2\2\u0334\u009e\3\2\2"+ + "\2\u0335\u0336\7r\2\2\u0336\u0337\7t\2\2\u0337\u0338\7g\2\2\u0338\u0339"+ + "\7e\2\2\u0339\u033a\7q\2\2\u033a\u033b\7p\2\2\u033b\u033c\7f\2\2\u033c"+ + "\u033d\7k\2\2\u033d\u033e\7v\2\2\u033e\u033f\7k\2\2\u033f\u0340\7q\2\2"+ + "\u0340\u0341\7p\2\2\u0341\u00a0\3\2\2\2\u0342\u0343\7t\2\2\u0343\u0344"+ + "\7g\2\2\u0344\u0345\7s\2\2\u0345\u0346\7w\2\2\u0346\u0347\7k\2\2\u0347"+ + "\u0348\7t\2\2\u0348\u0349\7g\2\2\u0349\u034a\7u\2\2\u034a\u00a2\3\2\2"+ + "\2\u034b\u034c\7r\2\2\u034c\u034d\7q\2\2\u034d\u034e\7u\2\2\u034e\u034f"+ + "\7v\2\2\u034f\u0350\7e\2\2\u0350\u0351\7q\2\2\u0351\u0352\7p\2\2\u0352"+ + "\u0353\7f\2\2\u0353\u0354\7k\2\2\u0354\u0355\7v\2\2\u0355\u0356\7k\2\2"+ + "\u0356\u0357\7q\2\2\u0357\u0358\7p\2\2\u0358\u00a4\3\2\2\2\u0359\u035a"+ + "\7g\2\2\u035a\u035b\7p\2\2\u035b\u035c\7u\2\2\u035c\u035d\7w\2\2\u035d"+ + "\u035e\7t\2\2\u035e\u035f\7g\2\2\u035f\u0360\7u\2\2\u0360\u00a6\3\2\2"+ + "\2\u0361\u0362\7k\2\2\u0362\u0363\7p\2\2\u0363\u0364\7k\2\2\u0364\u0365"+ + "\7v\2\2\u0365\u0366\7k\2\2\u0366\u0367\7c\2\2\u0367\u0368\7n\2\2\u0368"+ + "\u00a8\3\2\2\2\u0369\u036a\7f\2\2\u036a\u036b\7g\2\2\u036b\u036c\7t\2"+ + "\2\u036c\u036d\7k\2\2\u036d\u036e\7x\2\2\u036e\u036f\7c\2\2\u036f\u0370"+ + "\7v\2\2\u0370\u0371\7k\2\2\u0371\u0372\7q\2\2\u0372\u0373\7p\2\2\u0373"+ + "\u00aa\3\2\2\2\u0374\u0375\7r\2\2\u0375\u0376\7w\2\2\u0376\u0377\7d\2"+ + "\2\u0377\u0378\7n\2\2\u0378\u0379\7k\2\2\u0379\u037a\7e\2\2\u037a\u00ac"+ + "\3\2\2\2\u037b\u037c\7r\2\2\u037c\u037d\7t\2\2\u037d\u037e\7q\2\2\u037e"+ + "\u037f\7v\2\2\u037f\u0380\7g\2\2\u0380\u0381\7e\2\2\u0381\u0382\7v\2\2"+ + "\u0382\u0383\7g\2\2\u0383\u0384\7f\2\2\u0384\u00ae\3\2\2\2\u0385\u0386"+ + "\7r\2\2\u0386\u0387\7t\2\2\u0387\u0388\7k\2\2\u0388\u0389\7x\2\2\u0389"+ + "\u038a\7c\2\2\u038a\u038b\7v\2\2\u038b\u038c\7g\2\2\u038c\u00b0\3\2\2"+ + "\2\u038d\u038e\7p\2\2\u038e\u038f\7q\2\2\u038f\u00b2\3\2\2\2\u0390\u0391"+ + "\7n\2\2\u0391\u0392\7q\2\2\u0392\u0393\7p\2\2\u0393\u0394\7g\2\2\u0394"+ + "\u00b4\3\2\2\2\u0395\u0396\7q\2\2\u0396\u0397\7p\2\2\u0397\u0398\7g\2"+ + "\2\u0398\u00b6\3\2\2\2\u0399\u039a\7u\2\2\u039a\u039b\7q\2\2\u039b\u039c"+ + "\7o\2\2\u039c\u039d\7g\2\2\u039d\u00b8\3\2\2\2\u039e\u039f\7#\2\2\u039f"+ + "\u00ba\3\2\2\2\u03a0\u03a1\7p\2\2\u03a1\u03a2\7q\2\2\u03a2\u03a3\7v\2"+ + "\2\u03a3\u00bc\3\2\2\2\u03a4\u03a5\7k\2\2\u03a5\u03a6\7p\2\2\u03a6\u00be"+ + "\3\2\2\2\u03a7\u03a8\7>\2\2\u03a8\u03a9\7?\2\2\u03a9\u00c0\3\2\2\2\u03aa"+ + "\u03ab\7@\2\2\u03ab\u03ac\7?\2\2\u03ac\u00c2\3\2\2\2\u03ad\u03ae\7u\2"+ + "\2\u03ae\u03af\7w\2\2\u03af\u03b0\7o\2\2\u03b0\u00c4\3\2\2\2\u03b1\u03b2"+ + "\7~\2\2\u03b2\u00c6\3\2\2\2\u03b3\u03b4\7c\2\2\u03b4\u03b5\7e\2\2\u03b5"+ + "\u03b6\7{\2\2\u03b6\u03b7\7e\2\2\u03b7\u03b8\7n\2\2\u03b8\u03b9\7k\2\2"+ + "\u03b9\u03ba\7e\2\2\u03ba\u00c8\3\2\2\2\u03bb\u03bc\7h\2\2\u03bc\u03bd"+ + "\7w\2\2\u03bd\u03be\7p\2\2\u03be\u03bf\7e\2\2\u03bf\u03c0\7v\2\2\u03c0"+ + "\u03c1\7k\2\2\u03c1\u03c2\7q\2\2\u03c2\u03c3\7p\2\2\u03c3\u00ca\3\2\2"+ + "\2\u03c4\u03c5\7/\2\2\u03c5\u03c6\7@\2\2\u03c6\u00cc\3\2\2\2\u03c7\u03c8"+ + "\7q\2\2\u03c8\u03c9\7t\2\2\u03c9\u03ca\7f\2\2\u03ca\u00ce\3\2\2\2\u03cb"+ + "\u03cc\7(\2\2\u03cc\u03cd\7(\2\2\u03cd\u00d0\3\2\2\2\u03ce\u03cf\7c\2"+ + "\2\u03cf\u03d0\7p\2\2\u03d0\u03d1\7f\2\2\u03d1\u00d2\3\2\2\2\u03d2\u03d3"+ + "\7~\2\2\u03d3\u03d4\7~\2\2\u03d4\u00d4\3\2\2\2\u03d5\u03d6\7q\2\2\u03d6"+ + "\u03d7\7t\2\2\u03d7\u00d6\3\2\2\2\u03d8\u03d9\7?\2\2\u03d9\u03da\7@\2"+ + "\2\u03da\u00d8\3\2\2\2\u03db\u03dc\7k\2\2\u03dc\u03dd\7h\2\2\u03dd\u00da"+ + "\3\2\2\2\u03de\u03df\7k\2\2\u03df\u03e0\7o\2\2\u03e0\u03e1\7r\2\2\u03e1"+ + "\u03e2\7n\2\2\u03e2\u03e3\7k\2\2\u03e3\u03e4\7g\2\2\u03e4\u03e5\7u\2\2"+ + "\u03e5\u00dc\3\2\2\2\u03e6\u03e7\7>\2\2\u03e7\u03e8\7?\2\2\u03e8\u03e9"+ + "\7@\2\2\u03e9\u00de\3\2\2\2\u03ea\u03eb\7k\2\2\u03eb\u03ec\7h\2\2\u03ec"+ + "\u03ed\7h\2\2\u03ed\u00e0\3\2\2\2\u03ee\u03ef\7c\2\2\u03ef\u03f0\7n\2"+ + "\2\u03f0\u03f1\7n\2\2\u03f1\u00e2\3\2\2\2\u03f2\u03f3\7n\2\2\u03f3\u03f4"+ + "\7g\2\2\u03f4\u03f5\7v\2\2\u03f5\u00e4\3\2\2\2\u03f6\u03f7\7\u0080\2\2"+ + "\u03f7\u00e6\3\2\2\2\u03f8\u03f9\7`\2\2\u03f9\u00e8\3\2\2\2\u03fa\u03fb"+ + "\7-\2\2\u03fb\u03fc\7-\2\2\u03fc\u00ea\3\2\2\2\u03fd\u03fe\7v\2\2\u03fe"+ + "\u03ff\7j\2\2\u03ff\u0400\7g\2\2\u0400\u0401\7p\2\2\u0401\u00ec\3\2\2"+ + "\2\u0402\u0403\7g\2\2\u0403\u0404\7n\2\2\u0404\u0405\7u\2\2\u0405\u0406"+ + "\7g\2\2\u0406\u00ee\3\2\2\2\u0407\u0408\7k\2\2\u0408\u0409\7f\2\2\u0409"+ + "\u040a\7g\2\2\u040a\u040b\7p\2\2\u040b\u00f0\3\2\2\2\u040c\u040d\7p\2"+ + "\2\u040d\u040e\7q\2\2\u040e\u040f\7p\2\2\u040f\u0410\7g\2\2\u0410\u00f2"+ + "\3\2\2\2\u0411\u0412\7w\2\2\u0412\u0413\7p\2\2\u0413\u0414\7k\2\2\u0414"+ + "\u0415\7x\2\2\u0415\u00f4\3\2\2\2\u0416\u0417\7k\2\2\u0417\u0418\7p\2"+ + "\2\u0418\u0419\7v\2\2\u0419\u041a\7u\2\2\u041a\u00f6\3\2\2\2\u041b\u041c"+ + "\7r\2\2\u041c\u041d\7n\2\2\u041d\u041e\7w\2\2\u041e\u041f\7u\2\2\u041f"+ + "\u00f8\3\2\2\2\u0420\u0421\7o\2\2\u0421\u0422\7k\2\2\u0422\u0423\7p\2"+ + "\2\u0423\u0424\7w\2\2\u0424\u0425\7u\2\2\u0425\u00fa\3\2\2\2\u0426\u0427"+ + "\7o\2\2\u0427\u0428\7w\2\2\u0428\u0429\7n\2\2\u0429\u00fc\3\2\2\2\u042a"+ + "\u042b\7\61\2\2\u042b\u00fe\3\2\2\2\u042c\u042d\7f\2\2\u042d\u042e\7k"+ + "\2\2\u042e\u042f\7x\2\2\u042f\u0100\3\2\2\2\u0430\u0431\7\'\2\2\u0431"+ + "\u0102\3\2\2\2\u0432\u0433\7o\2\2\u0433\u0434\7q\2\2\u0434\u0435\7f\2"+ + "\2\u0435\u0436\7w\2\2\u0436\u0437\7n\2\2\u0437\u0438\7q\2\2\u0438\u0104"+ + "\3\2\2\2\u0439\u043a\7f\2\2\u043a\u043b\7k\2\2\u043b\u043c\7u\2\2\u043c"+ + "\u043d\7l\2\2\u043d\u0106\3\2\2\2\u043e\u043f\7u\2\2\u043f\u0440\7g\2"+ + "\2\u0440\u0441\7v\2\2\u0441\u0108\3\2\2\2\u0442\u0443\7f\2\2\u0443\u0444"+ + "\7g\2\2\u0444\u0445\7h\2\2\u0445\u0446\7k\2\2\u0446\u0447\7p\2\2\u0447"+ + "\u0448\7k\2\2\u0448\u0449\7v\2\2\u0449\u044a\7k\2\2\u044a\u044b\7q\2\2"+ + "\u044b\u044c\7p\2\2\u044c\u010a\3\2\2\2\u044d\u044e\7g\2\2\u044e\u044f"+ + "\7p\2\2\u044f\u0450\7u\2\2\u0450\u0451\7w\2\2\u0451\u0452\7t\2\2\u0452"+ + "\u0453\7g\2\2\u0453\u010c\3\2\2\2\u0454\u0455\7t\2\2\u0455\u0456\7g\2"+ + "\2\u0456\u0457\7s\2\2\u0457\u0458\7w\2\2\u0458\u0459\7k\2\2\u0459\u045a"+ + "\7t\2\2\u045a\u045b\7g\2\2\u045b\u010e\3\2\2\2\u045c\u045e\5\u011b\u008e"+ + "\2\u045d\u045c\3\2\2\2\u045e\u045f\3\2\2\2\u045f\u045d\3\2\2\2\u045f\u0460"+ + "\3\2\2\2\u0460\u0110\3\2\2\2\u0461\u0464\5\u011f\u0090\2\u0462\u0464\5"+ + "\u0119\u008d\2\u0463\u0461\3\2\2\2\u0463\u0462\3\2\2\2\u0464\u046c\3\2"+ + "\2\2\u0465\u046b\5\u0119\u008d\2\u0466\u046b\5\u0121\u0091\2\u0467\u046b"+ + "\5\u011b\u008e\2\u0468\u046b\5\u011f\u0090\2\u0469\u046b\5\u0123\u0092"+ + "\2\u046a\u0465\3\2\2\2\u046a\u0466\3\2\2\2\u046a\u0467\3\2\2\2\u046a\u0468"+ + "\3\2\2\2\u046a\u0469\3\2\2\2\u046b\u046e\3\2\2\2\u046c\u046a\3\2\2\2\u046c"+ + "\u046d\3\2\2\2\u046d\u0112\3\2\2\2\u046e\u046c\3\2\2\2\u046f\u0470\7)"+ + "\2\2\u0470\u0471\n\2\2\2\u0471\u0472\7)\2\2\u0472\u0114\3\2\2\2\u0473"+ + "\u0478\7$\2\2\u0474\u0477\5\u011d\u008f\2\u0475\u0477\n\3\2\2\u0476\u0474"+ + "\3\2\2\2\u0476\u0475\3\2\2\2\u0477\u047a\3\2\2\2\u0478\u0476\3\2\2\2\u0478"+ + "\u0479\3\2\2\2\u0479\u047b\3\2\2\2\u047a\u0478\3\2\2\2\u047b\u047c\7$"+ + "\2\2\u047c\u0116\3\2\2\2\u047d\u0482\7)\2\2\u047e\u0481\5\u011d\u008f"+ + "\2\u047f\u0481\n\2\2\2\u0480\u047e\3\2\2\2\u0480\u047f\3\2\2\2\u0481\u0484"+ + "\3\2\2\2\u0482\u0480\3\2\2\2\u0482\u0483\3\2\2\2\u0483\u0485\3\2\2\2\u0484"+ + "\u0482\3\2\2\2\u0485\u0486\7)\2\2\u0486\u0118\3\2\2\2\u0487\u0488\t\4"+ + "\2\2\u0488\u011a\3\2\2\2\u0489\u048a\t\5\2\2\u048a\u011c\3\2\2\2\u048b"+ + "\u048c\7^\2\2\u048c\u048d\t\6\2\2\u048d\u011e\3\2\2\2\u048e\u048f\7a\2"+ + "\2\u048f\u0120\3\2\2\2\u0490\u0491\7)\2\2\u0491\u0122\3\2\2\2\u0492\u0493"+ + "\7&\2\2\u0493\u0124\3\2\2\2\u0494\u0495\7#\2\2\u0495\u0126\3\2\2\2\u0496"+ + "\u0497\7/\2\2\u0497\u0128\3\2\2\2\u0498\u049c\7)\2\2\u0499\u049b\13\2"+ + "\2\2\u049a\u0499\3\2\2\2\u049b\u049e\3\2\2\2\u049c\u049d\3\2\2\2\u049c"+ + "\u049a\3\2\2\2\u049d\u049f\3\2\2\2\u049e\u049c\3\2\2\2\u049f\u04a0\7)"+ + "\2\2\u04a0\u04a1\3\2\2\2\u04a1\u04a2\b\u0095\2\2\u04a2\u012a\3\2\2\2\u04a3"+ + "\u04a4\7\61\2\2\u04a4\u04a5\7,\2\2\u04a5\u04a9\3\2\2\2\u04a6\u04a8\13"+ + "\2\2\2\u04a7\u04a6\3\2\2\2\u04a8\u04ab\3\2\2\2\u04a9\u04aa\3\2\2\2\u04a9"+ + "\u04a7\3\2\2\2\u04aa\u04ac\3\2\2\2\u04ab\u04a9\3\2\2\2\u04ac\u04ad\7,"+ + "\2\2\u04ad\u04ae\7\61\2\2\u04ae\u04af\3\2\2\2\u04af\u04b0\b\u0096\2\2"+ + "\u04b0\u012c\3\2\2\2\u04b1\u04b2\7/\2\2\u04b2\u04b6\7/\2\2\u04b3\u04b4"+ + "\7\61\2\2\u04b4\u04b6\7\61\2\2\u04b5\u04b1\3\2\2\2\u04b5\u04b3\3\2\2\2"+ + "\u04b6\u04ba\3\2\2\2\u04b7\u04b9\13\2\2\2\u04b8\u04b7\3\2\2\2\u04b9\u04bc"+ + "\3\2\2\2\u04ba\u04bb\3\2\2\2\u04ba\u04b8\3\2\2\2\u04bb\u04be\3\2\2\2\u04bc"+ + "\u04ba\3\2\2\2\u04bd\u04bf\7\17\2\2\u04be\u04bd\3\2\2\2\u04be\u04bf\3"+ + "\2\2\2\u04bf\u04c0\3\2\2\2\u04c0\u04c1\7\f\2\2\u04c1\u04c2\3\2\2\2\u04c2"+ + "\u04c3\b\u0097\2\2\u04c3\u012e\3\2\2\2\u04c4\u04c6\t\7\2\2\u04c5\u04c4"+ + "\3\2\2\2\u04c6\u04c7\3\2\2\2\u04c7\u04c5\3\2\2\2\u04c7\u04c8\3\2\2\2\u04c8"+ + "\u04c9\3\2\2\2\u04c9\u04ca\b\u0098\2\2\u04ca\u0130\3\2\2\2\21\2\u045f"+ + "\u0463\u046a\u046c\u0476\u0478\u0480\u0482\u049c\u04a9\u04b5\u04ba\u04be"+ + "\u04c7\3\b\2\2"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreLexer.tokens b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreLexer.tokens new file mode 100644 index 00000000..61cb97cf --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreLexer.tokens @@ -0,0 +1,277 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +T__7=8 +T__8=9 +T__9=10 +T__10=11 +T__11=12 +T__12=13 +T__13=14 +T__14=15 +T__15=16 +T__16=17 +T__17=18 +T__18=19 +T__19=20 +T__20=21 +T__21=22 +T__22=23 +T__23=24 +T__24=25 +T__25=26 +T__26=27 +T__27=28 +T__28=29 +T__29=30 +T__30=31 +T__31=32 +T__32=33 +T__33=34 +T__34=35 +T__35=36 +T__36=37 +T__37=38 +T__38=39 +T__39=40 +T__40=41 +T__41=42 +T__42=43 +T__43=44 +T__44=45 +T__45=46 +T__46=47 +T__47=48 +T__48=49 +T__49=50 +T__50=51 +T__51=52 +T__52=53 +T__53=54 +T__54=55 +T__55=56 +T__56=57 +T__57=58 +T__58=59 +T__59=60 +T__60=61 +T__61=62 +T__62=63 +T__63=64 +T__64=65 +T__65=66 +T__66=67 +T__67=68 +T__68=69 +T__69=70 +T__70=71 +T__71=72 +T__72=73 +T__73=74 +T__74=75 +T__75=76 +T__76=77 +T__77=78 +T__78=79 +T__79=80 +T__80=81 +T__81=82 +T__82=83 +T__83=84 +T__84=85 +T__85=86 +T__86=87 +T__87=88 +T__88=89 +T__89=90 +T__90=91 +T__91=92 +T__92=93 +T__93=94 +T__94=95 +T__95=96 +T__96=97 +T__97=98 +T__98=99 +T__99=100 +T__100=101 +T__101=102 +T__102=103 +T__103=104 +T__104=105 +T__105=106 +T__106=107 +T__107=108 +T__108=109 +T__109=110 +T__110=111 +T__111=112 +T__112=113 +T__113=114 +T__114=115 +T__115=116 +T__116=117 +T__117=118 +T__118=119 +T__119=120 +T__120=121 +T__121=122 +T__122=123 +T__123=124 +T__124=125 +T__125=126 +T__126=127 +T__127=128 +T__128=129 +T__129=130 +T__130=131 +T__131=132 +T__132=133 +T__133=134 +INT=135 +IDENTIFIER=136 +SINGLE_CHARACTER=137 +DOUBLE_QUOTED_STRING=138 +SINGLE_QUOTED_STRING=139 +ML_SINGLE_QUOTED_STRING=140 +MULTILINE_COMMENT=141 +SINGLELINE_COMMENT=142 +WS=143 +'options'=1 +'{'=2 +','=3 +'}'=4 +'symmetry_breaking'=5 +':'=6 +'bit_width'=7 +'skolem_depth'=8 +'sharing'=9 +'instance'=10 +';'=11 +'model'=12 +'['=13 +']'=14 +'true'=15 +'false'=16 +'+'=17 +'-'=18 +'.'=19 +'null'=20 +'import'=21 +'package'=22 +'='=23 +'abstract'=24 +'class'=25 +'interface'=26 +'extends'=27 +'static'=28 +'ghost'=29 +'transient'=30 +'volatile'=31 +'readonly'=32 +'attribute'=33 +'derived'=34 +'id'=35 +'ordered'=36 +'!ordered'=37 +'unique'=38 +'!unique'=39 +'unsettable'=40 +'!unsettable'=41 +'property'=42 +'#'=43 +'composes'=44 +'resolve'=45 +'!resolve'=46 +'key'=47 +'operation'=48 +'('=49 +')'=50 +'throws'=51 +'..'=52 +'*'=53 +'?'=54 +'|?'=55 +'|1'=56 +'primitive'=57 +'datatype'=58 +'serializable'=59 +'!serializable'=60 +'enum'=61 +'literal'=62 +'annotation'=63 +'reference'=64 +'<'=65 +'>'=66 +'&'=67 +'super'=68 +'::'=69 +'@'=70 +'Boolean'=71 +'Integer'=72 +'String'=73 +'Real'=74 +'UnlimitedNatural'=75 +'body'=76 +'callable'=77 +'invariant'=78 +'precondition'=79 +'requires'=80 +'postcondition'=81 +'ensures'=82 +'initial'=83 +'derivation'=84 +'public'=85 +'protected'=86 +'private'=87 +'no'=88 +'lone'=89 +'one'=90 +'some'=91 +'!'=92 +'not'=93 +'in'=94 +'<='=95 +'>='=96 +'sum'=97 +'|'=98 +'acyclic'=99 +'function'=100 +'->'=101 +'ord'=102 +'&&'=103 +'and'=104 +'||'=105 +'or'=106 +'=>'=107 +'if'=108 +'implies'=109 +'<=>'=110 +'iff'=111 +'all'=112 +'let'=113 +'~'=114 +'^'=115 +'++'=116 +'then'=117 +'else'=118 +'iden'=119 +'none'=120 +'univ'=121 +'ints'=122 +'plus'=123 +'minus'=124 +'mul'=125 +'/'=126 +'div'=127 +'%'=128 +'modulo'=129 +'disj'=130 +'set'=131 +'definition'=132 +'ensure'=133 +'require'=134 diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreListener.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreListener.java new file mode 100644 index 00000000..d7c5018e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreListener.java @@ -0,0 +1,1557 @@ +// Generated from /home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcore.g4 by ANTLR 4.6 +package eu.modelwriter.core.alloyinecore.recognizer; + + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EcoreFactory; +import org.eclipse.emf.ecore.EcorePackage; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.ETypedElement; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EClassifier; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EOperation; +import org.eclipse.emf.ecore.EParameter; +import org.eclipse.emf.ecore.EEnum; +import org.eclipse.emf.ecore.EEnumLiteral; +import org.eclipse.emf.ecore.EDataType; +import org.eclipse.emf.ecore.ETypedElement; +import org.eclipse.emf.ecore.EAnnotation; +import org.eclipse.emf.ecore.EGenericType; +import org.eclipse.emf.ecore.ETypeParameter; + +import eu.modelwriter.core.alloyinecore.structure.base.INamespace; +import eu.modelwriter.core.alloyinecore.structure.base.Repository; +import eu.modelwriter.core.alloyinecore.structure.base.Element; + +import eu.modelwriter.core.alloyinecore.structure.model.ModelElement; +import eu.modelwriter.core.alloyinecore.structure.model.Annotation; +import eu.modelwriter.core.alloyinecore.structure.model.AnnotationDetail; +import eu.modelwriter.core.alloyinecore.structure.model.AnnotationReference; +import eu.modelwriter.core.alloyinecore.structure.model.NamedElement; +import eu.modelwriter.core.alloyinecore.structure.model.Model; +import eu.modelwriter.core.alloyinecore.structure.model.Import; +import eu.modelwriter.core.alloyinecore.structure.model.EcoreImport; +import eu.modelwriter.core.alloyinecore.structure.model.Package; +import eu.modelwriter.core.alloyinecore.structure.model.RootPackage; +import eu.modelwriter.core.alloyinecore.structure.model.Classifier; +import eu.modelwriter.core.alloyinecore.structure.model.Class; +import eu.modelwriter.core.alloyinecore.structure.model.Interface; +import eu.modelwriter.core.alloyinecore.structure.model.DataType; +import eu.modelwriter.core.alloyinecore.structure.model.Enum; +import eu.modelwriter.core.alloyinecore.structure.model.EnumLiteral; +import eu.modelwriter.core.alloyinecore.structure.model.StructuralFeature; +import eu.modelwriter.core.alloyinecore.structure.model.TypedElement; +import eu.modelwriter.core.alloyinecore.structure.model.Multiplicity; +import eu.modelwriter.core.alloyinecore.structure.model.Reference; +import eu.modelwriter.core.alloyinecore.structure.model.Attribute; +import eu.modelwriter.core.alloyinecore.structure.model.Operation; +import eu.modelwriter.core.alloyinecore.structure.model.Parameter; +import eu.modelwriter.core.alloyinecore.structure.model.GenericException; +import eu.modelwriter.core.alloyinecore.structure.model.TypeParameter; +import eu.modelwriter.core.alloyinecore.structure.model.GenericType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericTypeArgument; +import eu.modelwriter.core.alloyinecore.structure.model.GenericElementType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericSuperType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericWildcard; +import eu.modelwriter.core.alloyinecore.structure.model.PrimitiveType; +import eu.modelwriter.core.alloyinecore.structure.model.Invariant; +import eu.modelwriter.core.alloyinecore.structure.model.Derivation; +import eu.modelwriter.core.alloyinecore.structure.model.Body; +import eu.modelwriter.core.alloyinecore.structure.model.PostCondition; +import eu.modelwriter.core.alloyinecore.structure.model.PreCondition; +import eu.modelwriter.core.alloyinecore.structure.model.Initial; + +import eu.modelwriter.core.alloyinecore.structure.instance.ModelImport; +import eu.modelwriter.core.alloyinecore.structure.instance.Instance; +import eu.modelwriter.core.alloyinecore.structure.instance.Object; +import eu.modelwriter.core.alloyinecore.structure.instance.Slot; +import eu.modelwriter.core.alloyinecore.structure.instance.ObjectValue; +import eu.modelwriter.core.alloyinecore.structure.instance.EnumValue; +import eu.modelwriter.core.alloyinecore.structure.instance.IntegerValue; +import eu.modelwriter.core.alloyinecore.structure.instance.RealValue; +import eu.modelwriter.core.alloyinecore.structure.instance.BooleanValue; +import eu.modelwriter.core.alloyinecore.structure.instance.StringValue; +import eu.modelwriter.core.alloyinecore.structure.instance.NullValue; +import eu.modelwriter.core.alloyinecore.structure.instance.CharValue; + +import eu.modelwriter.core.alloyinecore.structure.constraints.Formula; +import eu.modelwriter.core.alloyinecore.structure.constraints.Expression; +import eu.modelwriter.core.alloyinecore.structure.constraints.IntExpression; +import eu.modelwriter.core.alloyinecore.structure.constraints.QuantifierDeclaration; +import eu.modelwriter.core.alloyinecore.structure.constraints.LetDeclaration; +import eu.modelwriter.core.alloyinecore.structure.constraints.ComprehensionDeclaration; +import eu.modelwriter.core.alloyinecore.structure.constraints.Variable; + +import eu.modelwriter.core.alloyinecore.internal.AnnotationSources; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl; +import org.eclipse.emf.ecore.util.EcoreUtil; + +import java.util.stream.Collectors; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +import java.io.IOException; + +import org.antlr.v4.runtime.tree.ParseTreeListener; + +/** + * This interface defines a complete listener for a parse tree produced by + * {@link AlloyInEcoreParser}. + */ +public interface AlloyInEcoreListener extends ParseTreeListener { + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#options}. + * @param ctx the parse tree + */ + void enterOptions(AlloyInEcoreParser.OptionsContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#options}. + * @param ctx the parse tree + */ + void exitOptions(AlloyInEcoreParser.OptionsContext ctx); + /** + * Enter a parse tree produced by the {@code symmetryBreaking} + * labeled alternative in {@link AlloyInEcoreParser#option}. + * @param ctx the parse tree + */ + void enterSymmetryBreaking(AlloyInEcoreParser.SymmetryBreakingContext ctx); + /** + * Exit a parse tree produced by the {@code symmetryBreaking} + * labeled alternative in {@link AlloyInEcoreParser#option}. + * @param ctx the parse tree + */ + void exitSymmetryBreaking(AlloyInEcoreParser.SymmetryBreakingContext ctx); + /** + * Enter a parse tree produced by the {@code bitWidth} + * labeled alternative in {@link AlloyInEcoreParser#option}. + * @param ctx the parse tree + */ + void enterBitWidth(AlloyInEcoreParser.BitWidthContext ctx); + /** + * Exit a parse tree produced by the {@code bitWidth} + * labeled alternative in {@link AlloyInEcoreParser#option}. + * @param ctx the parse tree + */ + void exitBitWidth(AlloyInEcoreParser.BitWidthContext ctx); + /** + * Enter a parse tree produced by the {@code skolemDepth} + * labeled alternative in {@link AlloyInEcoreParser#option}. + * @param ctx the parse tree + */ + void enterSkolemDepth(AlloyInEcoreParser.SkolemDepthContext ctx); + /** + * Exit a parse tree produced by the {@code skolemDepth} + * labeled alternative in {@link AlloyInEcoreParser#option}. + * @param ctx the parse tree + */ + void exitSkolemDepth(AlloyInEcoreParser.SkolemDepthContext ctx); + /** + * Enter a parse tree produced by the {@code sharing} + * labeled alternative in {@link AlloyInEcoreParser#option}. + * @param ctx the parse tree + */ + void enterSharing(AlloyInEcoreParser.SharingContext ctx); + /** + * Exit a parse tree produced by the {@code sharing} + * labeled alternative in {@link AlloyInEcoreParser#option}. + * @param ctx the parse tree + */ + void exitSharing(AlloyInEcoreParser.SharingContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#instance}. + * @param ctx the parse tree + */ + void enterInstance(AlloyInEcoreParser.InstanceContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#instance}. + * @param ctx the parse tree + */ + void exitInstance(AlloyInEcoreParser.InstanceContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#modelImport}. + * @param ctx the parse tree + */ + void enterModelImport(AlloyInEcoreParser.ModelImportContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#modelImport}. + * @param ctx the parse tree + */ + void exitModelImport(AlloyInEcoreParser.ModelImportContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eObject}. + * @param ctx the parse tree + */ + void enterEObject(AlloyInEcoreParser.EObjectContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eObject}. + * @param ctx the parse tree + */ + void exitEObject(AlloyInEcoreParser.EObjectContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#slot}. + * @param ctx the parse tree + */ + void enterSlot(AlloyInEcoreParser.SlotContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#slot}. + * @param ctx the parse tree + */ + void exitSlot(AlloyInEcoreParser.SlotContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#dataValue}. + * @param ctx the parse tree + */ + void enterDataValue(AlloyInEcoreParser.DataValueContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#dataValue}. + * @param ctx the parse tree + */ + void exitDataValue(AlloyInEcoreParser.DataValueContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#multiValueData}. + * @param ctx the parse tree + */ + void enterMultiValueData(AlloyInEcoreParser.MultiValueDataContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#multiValueData}. + * @param ctx the parse tree + */ + void exitMultiValueData(AlloyInEcoreParser.MultiValueDataContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eObjectValue}. + * @param ctx the parse tree + */ + void enterEObjectValue(AlloyInEcoreParser.EObjectValueContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eObjectValue}. + * @param ctx the parse tree + */ + void exitEObjectValue(AlloyInEcoreParser.EObjectValueContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#literalValue}. + * @param ctx the parse tree + */ + void enterLiteralValue(AlloyInEcoreParser.LiteralValueContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#literalValue}. + * @param ctx the parse tree + */ + void exitLiteralValue(AlloyInEcoreParser.LiteralValueContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#enumValue}. + * @param ctx the parse tree + */ + void enterEnumValue(AlloyInEcoreParser.EnumValueContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#enumValue}. + * @param ctx the parse tree + */ + void exitEnumValue(AlloyInEcoreParser.EnumValueContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#booleanValue}. + * @param ctx the parse tree + */ + void enterBooleanValue(AlloyInEcoreParser.BooleanValueContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#booleanValue}. + * @param ctx the parse tree + */ + void exitBooleanValue(AlloyInEcoreParser.BooleanValueContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#integerValue}. + * @param ctx the parse tree + */ + void enterIntegerValue(AlloyInEcoreParser.IntegerValueContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#integerValue}. + * @param ctx the parse tree + */ + void exitIntegerValue(AlloyInEcoreParser.IntegerValueContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#realValue}. + * @param ctx the parse tree + */ + void enterRealValue(AlloyInEcoreParser.RealValueContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#realValue}. + * @param ctx the parse tree + */ + void exitRealValue(AlloyInEcoreParser.RealValueContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#stringValue}. + * @param ctx the parse tree + */ + void enterStringValue(AlloyInEcoreParser.StringValueContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#stringValue}. + * @param ctx the parse tree + */ + void exitStringValue(AlloyInEcoreParser.StringValueContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#charValue}. + * @param ctx the parse tree + */ + void enterCharValue(AlloyInEcoreParser.CharValueContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#charValue}. + * @param ctx the parse tree + */ + void exitCharValue(AlloyInEcoreParser.CharValueContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#nullValue}. + * @param ctx the parse tree + */ + void enterNullValue(AlloyInEcoreParser.NullValueContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#nullValue}. + * @param ctx the parse tree + */ + void exitNullValue(AlloyInEcoreParser.NullValueContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#model}. + * @param ctx the parse tree + */ + void enterModel(AlloyInEcoreParser.ModelContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#model}. + * @param ctx the parse tree + */ + void exitModel(AlloyInEcoreParser.ModelContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#packageImport}. + * @param ctx the parse tree + */ + void enterPackageImport(AlloyInEcoreParser.PackageImportContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#packageImport}. + * @param ctx the parse tree + */ + void exitPackageImport(AlloyInEcoreParser.PackageImportContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#ePackage}. + * @param ctx the parse tree + */ + void enterEPackage(AlloyInEcoreParser.EPackageContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#ePackage}. + * @param ctx the parse tree + */ + void exitEPackage(AlloyInEcoreParser.EPackageContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eClassifier}. + * @param ctx the parse tree + */ + void enterEClassifier(AlloyInEcoreParser.EClassifierContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eClassifier}. + * @param ctx the parse tree + */ + void exitEClassifier(AlloyInEcoreParser.EClassifierContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eClass}. + * @param ctx the parse tree + */ + void enterEClass(AlloyInEcoreParser.EClassContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eClass}. + * @param ctx the parse tree + */ + void exitEClass(AlloyInEcoreParser.EClassContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eStructuralFeature}. + * @param ctx the parse tree + */ + void enterEStructuralFeature(AlloyInEcoreParser.EStructuralFeatureContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eStructuralFeature}. + * @param ctx the parse tree + */ + void exitEStructuralFeature(AlloyInEcoreParser.EStructuralFeatureContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eAttribute}. + * @param ctx the parse tree + */ + void enterEAttribute(AlloyInEcoreParser.EAttributeContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eAttribute}. + * @param ctx the parse tree + */ + void exitEAttribute(AlloyInEcoreParser.EAttributeContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eReference}. + * @param ctx the parse tree + */ + void enterEReference(AlloyInEcoreParser.EReferenceContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eReference}. + * @param ctx the parse tree + */ + void exitEReference(AlloyInEcoreParser.EReferenceContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eOperation}. + * @param ctx the parse tree + */ + void enterEOperation(AlloyInEcoreParser.EOperationContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eOperation}. + * @param ctx the parse tree + */ + void exitEOperation(AlloyInEcoreParser.EOperationContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eGenericException}. + * @param ctx the parse tree + */ + void enterEGenericException(AlloyInEcoreParser.EGenericExceptionContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eGenericException}. + * @param ctx the parse tree + */ + void exitEGenericException(AlloyInEcoreParser.EGenericExceptionContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eGenericSuperType}. + * @param ctx the parse tree + */ + void enterEGenericSuperType(AlloyInEcoreParser.EGenericSuperTypeContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eGenericSuperType}. + * @param ctx the parse tree + */ + void exitEGenericSuperType(AlloyInEcoreParser.EGenericSuperTypeContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eParameter}. + * @param ctx the parse tree + */ + void enterEParameter(AlloyInEcoreParser.EParameterContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eParameter}. + * @param ctx the parse tree + */ + void exitEParameter(AlloyInEcoreParser.EParameterContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eMultiplicity}. + * @param ctx the parse tree + */ + void enterEMultiplicity(AlloyInEcoreParser.EMultiplicityContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eMultiplicity}. + * @param ctx the parse tree + */ + void exitEMultiplicity(AlloyInEcoreParser.EMultiplicityContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eDataType}. + * @param ctx the parse tree + */ + void enterEDataType(AlloyInEcoreParser.EDataTypeContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eDataType}. + * @param ctx the parse tree + */ + void exitEDataType(AlloyInEcoreParser.EDataTypeContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eEnum}. + * @param ctx the parse tree + */ + void enterEEnum(AlloyInEcoreParser.EEnumContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eEnum}. + * @param ctx the parse tree + */ + void exitEEnum(AlloyInEcoreParser.EEnumContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eEnumLiteral}. + * @param ctx the parse tree + */ + void enterEEnumLiteral(AlloyInEcoreParser.EEnumLiteralContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eEnumLiteral}. + * @param ctx the parse tree + */ + void exitEEnumLiteral(AlloyInEcoreParser.EEnumLiteralContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eAnnotation}. + * @param ctx the parse tree + */ + void enterEAnnotation(AlloyInEcoreParser.EAnnotationContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eAnnotation}. + * @param ctx the parse tree + */ + void exitEAnnotation(AlloyInEcoreParser.EAnnotationContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eDetail}. + * @param ctx the parse tree + */ + void enterEDetail(AlloyInEcoreParser.EDetailContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eDetail}. + * @param ctx the parse tree + */ + void exitEDetail(AlloyInEcoreParser.EDetailContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eModelElement}. + * @param ctx the parse tree + */ + void enterEModelElement(AlloyInEcoreParser.EModelElementContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eModelElement}. + * @param ctx the parse tree + */ + void exitEModelElement(AlloyInEcoreParser.EModelElementContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eNamedElement}. + * @param ctx the parse tree + */ + void enterENamedElement(AlloyInEcoreParser.ENamedElementContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eNamedElement}. + * @param ctx the parse tree + */ + void exitENamedElement(AlloyInEcoreParser.ENamedElementContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eTypedElement}. + * @param ctx the parse tree + */ + void enterETypedElement(AlloyInEcoreParser.ETypedElementContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eTypedElement}. + * @param ctx the parse tree + */ + void exitETypedElement(AlloyInEcoreParser.ETypedElementContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eModelElementRef}. + * @param ctx the parse tree + */ + void enterEModelElementRef(AlloyInEcoreParser.EModelElementRefContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eModelElementRef}. + * @param ctx the parse tree + */ + void exitEModelElementRef(AlloyInEcoreParser.EModelElementRefContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#templateSignature}. + * @param ctx the parse tree + */ + void enterTemplateSignature(AlloyInEcoreParser.TemplateSignatureContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#templateSignature}. + * @param ctx the parse tree + */ + void exitTemplateSignature(AlloyInEcoreParser.TemplateSignatureContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eTypeParameter}. + * @param ctx the parse tree + */ + void enterETypeParameter(AlloyInEcoreParser.ETypeParameterContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eTypeParameter}. + * @param ctx the parse tree + */ + void exitETypeParameter(AlloyInEcoreParser.ETypeParameterContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eGenericTypeArgument}. + * @param ctx the parse tree + */ + void enterEGenericTypeArgument(AlloyInEcoreParser.EGenericTypeArgumentContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eGenericTypeArgument}. + * @param ctx the parse tree + */ + void exitEGenericTypeArgument(AlloyInEcoreParser.EGenericTypeArgumentContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eGenericType}. + * @param ctx the parse tree + */ + void enterEGenericType(AlloyInEcoreParser.EGenericTypeContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eGenericType}. + * @param ctx the parse tree + */ + void exitEGenericType(AlloyInEcoreParser.EGenericTypeContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eGenericElementType}. + * @param ctx the parse tree + */ + void enterEGenericElementType(AlloyInEcoreParser.EGenericElementTypeContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eGenericElementType}. + * @param ctx the parse tree + */ + void exitEGenericElementType(AlloyInEcoreParser.EGenericElementTypeContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#eGenericWildcard}. + * @param ctx the parse tree + */ + void enterEGenericWildcard(AlloyInEcoreParser.EGenericWildcardContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#eGenericWildcard}. + * @param ctx the parse tree + */ + void exitEGenericWildcard(AlloyInEcoreParser.EGenericWildcardContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#pathName}. + * @param ctx the parse tree + */ + void enterPathName(AlloyInEcoreParser.PathNameContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#pathName}. + * @param ctx the parse tree + */ + void exitPathName(AlloyInEcoreParser.PathNameContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#segment}. + * @param ctx the parse tree + */ + void enterSegment(AlloyInEcoreParser.SegmentContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#segment}. + * @param ctx the parse tree + */ + void exitSegment(AlloyInEcoreParser.SegmentContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#ePrimitiveType}. + * @param ctx the parse tree + */ + void enterEPrimitiveType(AlloyInEcoreParser.EPrimitiveTypeContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#ePrimitiveType}. + * @param ctx the parse tree + */ + void exitEPrimitiveType(AlloyInEcoreParser.EPrimitiveTypeContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#body}. + * @param ctx the parse tree + */ + void enterBody(AlloyInEcoreParser.BodyContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#body}. + * @param ctx the parse tree + */ + void exitBody(AlloyInEcoreParser.BodyContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#invariant}. + * @param ctx the parse tree + */ + void enterInvariant(AlloyInEcoreParser.InvariantContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#invariant}. + * @param ctx the parse tree + */ + void exitInvariant(AlloyInEcoreParser.InvariantContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#precondition}. + * @param ctx the parse tree + */ + void enterPrecondition(AlloyInEcoreParser.PreconditionContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#precondition}. + * @param ctx the parse tree + */ + void exitPrecondition(AlloyInEcoreParser.PreconditionContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#postcondition}. + * @param ctx the parse tree + */ + void enterPostcondition(AlloyInEcoreParser.PostconditionContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#postcondition}. + * @param ctx the parse tree + */ + void exitPostcondition(AlloyInEcoreParser.PostconditionContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#initial}. + * @param ctx the parse tree + */ + void enterInitial(AlloyInEcoreParser.InitialContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#initial}. + * @param ctx the parse tree + */ + void exitInitial(AlloyInEcoreParser.InitialContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#derivation}. + * @param ctx the parse tree + */ + void enterDerivation(AlloyInEcoreParser.DerivationContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#derivation}. + * @param ctx the parse tree + */ + void exitDerivation(AlloyInEcoreParser.DerivationContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#visibilityKind}. + * @param ctx the parse tree + */ + void enterVisibilityKind(AlloyInEcoreParser.VisibilityKindContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#visibilityKind}. + * @param ctx the parse tree + */ + void exitVisibilityKind(AlloyInEcoreParser.VisibilityKindContext ctx); + /** + * Enter a parse tree produced by the {@code no} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterNo(AlloyInEcoreParser.NoContext ctx); + /** + * Exit a parse tree produced by the {@code no} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitNo(AlloyInEcoreParser.NoContext ctx); + /** + * Enter a parse tree produced by the {@code some} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterSome(AlloyInEcoreParser.SomeContext ctx); + /** + * Exit a parse tree produced by the {@code some} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitSome(AlloyInEcoreParser.SomeContext ctx); + /** + * Enter a parse tree produced by the {@code forOne} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterForOne(AlloyInEcoreParser.ForOneContext ctx); + /** + * Exit a parse tree produced by the {@code forOne} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitForOne(AlloyInEcoreParser.ForOneContext ctx); + /** + * Enter a parse tree produced by the {@code sumDeclaration} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterSumDeclaration(AlloyInEcoreParser.SumDeclarationContext ctx); + /** + * Exit a parse tree produced by the {@code sumDeclaration} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitSumDeclaration(AlloyInEcoreParser.SumDeclarationContext ctx); + /** + * Enter a parse tree produced by the {@code forAll} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterForAll(AlloyInEcoreParser.ForAllContext ctx); + /** + * Exit a parse tree produced by the {@code forAll} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitForAll(AlloyInEcoreParser.ForAllContext ctx); + /** + * Enter a parse tree produced by the {@code lone} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterLone(AlloyInEcoreParser.LoneContext ctx); + /** + * Exit a parse tree produced by the {@code lone} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitLone(AlloyInEcoreParser.LoneContext ctx); + /** + * Enter a parse tree produced by the {@code lt} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterLt(AlloyInEcoreParser.LtContext ctx); + /** + * Exit a parse tree produced by the {@code lt} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitLt(AlloyInEcoreParser.LtContext ctx); + /** + * Enter a parse tree produced by the {@code forSome} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterForSome(AlloyInEcoreParser.ForSomeContext ctx); + /** + * Exit a parse tree produced by the {@code forSome} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitForSome(AlloyInEcoreParser.ForSomeContext ctx); + /** + * Enter a parse tree produced by the {@code not} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterNot(AlloyInEcoreParser.NotContext ctx); + /** + * Exit a parse tree produced by the {@code not} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitNot(AlloyInEcoreParser.NotContext ctx); + /** + * Enter a parse tree produced by the {@code f_paranthesis} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterF_paranthesis(AlloyInEcoreParser.F_paranthesisContext ctx); + /** + * Exit a parse tree produced by the {@code f_paranthesis} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitF_paranthesis(AlloyInEcoreParser.F_paranthesisContext ctx); + /** + * Enter a parse tree produced by the {@code and} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterAnd(AlloyInEcoreParser.AndContext ctx); + /** + * Exit a parse tree produced by the {@code and} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitAnd(AlloyInEcoreParser.AndContext ctx); + /** + * Enter a parse tree produced by the {@code function} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterFunction(AlloyInEcoreParser.FunctionContext ctx); + /** + * Exit a parse tree produced by the {@code function} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitFunction(AlloyInEcoreParser.FunctionContext ctx); + /** + * Enter a parse tree produced by the {@code gte} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterGte(AlloyInEcoreParser.GteContext ctx); + /** + * Exit a parse tree produced by the {@code gte} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitGte(AlloyInEcoreParser.GteContext ctx); + /** + * Enter a parse tree produced by the {@code acyclic} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterAcyclic(AlloyInEcoreParser.AcyclicContext ctx); + /** + * Exit a parse tree produced by the {@code acyclic} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitAcyclic(AlloyInEcoreParser.AcyclicContext ctx); + /** + * Enter a parse tree produced by the {@code let} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterLet(AlloyInEcoreParser.LetContext ctx); + /** + * Exit a parse tree produced by the {@code let} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitLet(AlloyInEcoreParser.LetContext ctx); + /** + * Enter a parse tree produced by the {@code lte} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterLte(AlloyInEcoreParser.LteContext ctx); + /** + * Exit a parse tree produced by the {@code lte} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitLte(AlloyInEcoreParser.LteContext ctx); + /** + * Enter a parse tree produced by the {@code or} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterOr(AlloyInEcoreParser.OrContext ctx); + /** + * Exit a parse tree produced by the {@code or} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitOr(AlloyInEcoreParser.OrContext ctx); + /** + * Enter a parse tree produced by the {@code in} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterIn(AlloyInEcoreParser.InContext ctx); + /** + * Exit a parse tree produced by the {@code in} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitIn(AlloyInEcoreParser.InContext ctx); + /** + * Enter a parse tree produced by the {@code one} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterOne(AlloyInEcoreParser.OneContext ctx); + /** + * Exit a parse tree produced by the {@code one} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitOne(AlloyInEcoreParser.OneContext ctx); + /** + * Enter a parse tree produced by the {@code false} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterFalse(AlloyInEcoreParser.FalseContext ctx); + /** + * Exit a parse tree produced by the {@code false} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitFalse(AlloyInEcoreParser.FalseContext ctx); + /** + * Enter a parse tree produced by the {@code iff} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterIff(AlloyInEcoreParser.IffContext ctx); + /** + * Exit a parse tree produced by the {@code iff} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitIff(AlloyInEcoreParser.IffContext ctx); + /** + * Enter a parse tree produced by the {@code eq} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterEq(AlloyInEcoreParser.EqContext ctx); + /** + * Exit a parse tree produced by the {@code eq} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitEq(AlloyInEcoreParser.EqContext ctx); + /** + * Enter a parse tree produced by the {@code gt} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterGt(AlloyInEcoreParser.GtContext ctx); + /** + * Exit a parse tree produced by the {@code gt} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitGt(AlloyInEcoreParser.GtContext ctx); + /** + * Enter a parse tree produced by the {@code equal} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterEqual(AlloyInEcoreParser.EqualContext ctx); + /** + * Exit a parse tree produced by the {@code equal} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitEqual(AlloyInEcoreParser.EqualContext ctx); + /** + * Enter a parse tree produced by the {@code forLone} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterForLone(AlloyInEcoreParser.ForLoneContext ctx); + /** + * Exit a parse tree produced by the {@code forLone} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitForLone(AlloyInEcoreParser.ForLoneContext ctx); + /** + * Enter a parse tree produced by the {@code totalOrder} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterTotalOrder(AlloyInEcoreParser.TotalOrderContext ctx); + /** + * Exit a parse tree produced by the {@code totalOrder} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitTotalOrder(AlloyInEcoreParser.TotalOrderContext ctx); + /** + * Enter a parse tree produced by the {@code true} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterTrue(AlloyInEcoreParser.TrueContext ctx); + /** + * Exit a parse tree produced by the {@code true} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitTrue(AlloyInEcoreParser.TrueContext ctx); + /** + * Enter a parse tree produced by the {@code forNo} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterForNo(AlloyInEcoreParser.ForNoContext ctx); + /** + * Exit a parse tree produced by the {@code forNo} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitForNo(AlloyInEcoreParser.ForNoContext ctx); + /** + * Enter a parse tree produced by the {@code implies} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void enterImplies(AlloyInEcoreParser.ImpliesContext ctx); + /** + * Exit a parse tree produced by the {@code implies} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + */ + void exitImplies(AlloyInEcoreParser.ImpliesContext ctx); + /** + * Enter a parse tree produced by the {@code product} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void enterProduct(AlloyInEcoreParser.ProductContext ctx); + /** + * Exit a parse tree produced by the {@code product} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void exitProduct(AlloyInEcoreParser.ProductContext ctx); + /** + * Enter a parse tree produced by the {@code none} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void enterNone(AlloyInEcoreParser.NoneContext ctx); + /** + * Exit a parse tree produced by the {@code none} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void exitNone(AlloyInEcoreParser.NoneContext ctx); + /** + * Enter a parse tree produced by the {@code union} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void enterUnion(AlloyInEcoreParser.UnionContext ctx); + /** + * Exit a parse tree produced by the {@code union} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void exitUnion(AlloyInEcoreParser.UnionContext ctx); + /** + * Enter a parse tree produced by the {@code comprehension} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void enterComprehension(AlloyInEcoreParser.ComprehensionContext ctx); + /** + * Exit a parse tree produced by the {@code comprehension} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void exitComprehension(AlloyInEcoreParser.ComprehensionContext ctx); + /** + * Enter a parse tree produced by the {@code univ} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void enterUniv(AlloyInEcoreParser.UnivContext ctx); + /** + * Exit a parse tree produced by the {@code univ} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void exitUniv(AlloyInEcoreParser.UnivContext ctx); + /** + * Enter a parse tree produced by the {@code reflexive} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void enterReflexive(AlloyInEcoreParser.ReflexiveContext ctx); + /** + * Exit a parse tree produced by the {@code reflexive} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void exitReflexive(AlloyInEcoreParser.ReflexiveContext ctx); + /** + * Enter a parse tree produced by the {@code e_paranthesis} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void enterE_paranthesis(AlloyInEcoreParser.E_paranthesisContext ctx); + /** + * Exit a parse tree produced by the {@code e_paranthesis} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void exitE_paranthesis(AlloyInEcoreParser.E_paranthesisContext ctx); + /** + * Enter a parse tree produced by the {@code iden} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void enterIden(AlloyInEcoreParser.IdenContext ctx); + /** + * Exit a parse tree produced by the {@code iden} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void exitIden(AlloyInEcoreParser.IdenContext ctx); + /** + * Enter a parse tree produced by the {@code ints} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void enterInts(AlloyInEcoreParser.IntsContext ctx); + /** + * Exit a parse tree produced by the {@code ints} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void exitInts(AlloyInEcoreParser.IntsContext ctx); + /** + * Enter a parse tree produced by the {@code intersection} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void enterIntersection(AlloyInEcoreParser.IntersectionContext ctx); + /** + * Exit a parse tree produced by the {@code intersection} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void exitIntersection(AlloyInEcoreParser.IntersectionContext ctx); + /** + * Enter a parse tree produced by the {@code difference} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void enterDifference(AlloyInEcoreParser.DifferenceContext ctx); + /** + * Exit a parse tree produced by the {@code difference} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void exitDifference(AlloyInEcoreParser.DifferenceContext ctx); + /** + * Enter a parse tree produced by the {@code transpose} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void enterTranspose(AlloyInEcoreParser.TransposeContext ctx); + /** + * Exit a parse tree produced by the {@code transpose} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void exitTranspose(AlloyInEcoreParser.TransposeContext ctx); + /** + * Enter a parse tree produced by the {@code join} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void enterJoin(AlloyInEcoreParser.JoinContext ctx); + /** + * Exit a parse tree produced by the {@code join} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void exitJoin(AlloyInEcoreParser.JoinContext ctx); + /** + * Enter a parse tree produced by the {@code override} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void enterOverride(AlloyInEcoreParser.OverrideContext ctx); + /** + * Exit a parse tree produced by the {@code override} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void exitOverride(AlloyInEcoreParser.OverrideContext ctx); + /** + * Enter a parse tree produced by the {@code ifExpression} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void enterIfExpression(AlloyInEcoreParser.IfExpressionContext ctx); + /** + * Exit a parse tree produced by the {@code ifExpression} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void exitIfExpression(AlloyInEcoreParser.IfExpressionContext ctx); + /** + * Enter a parse tree produced by the {@code closure} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void enterClosure(AlloyInEcoreParser.ClosureContext ctx); + /** + * Exit a parse tree produced by the {@code closure} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void exitClosure(AlloyInEcoreParser.ClosureContext ctx); + /** + * Enter a parse tree produced by the {@code typeRef} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void enterTypeRef(AlloyInEcoreParser.TypeRefContext ctx); + /** + * Exit a parse tree produced by the {@code typeRef} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void exitTypeRef(AlloyInEcoreParser.TypeRefContext ctx); + /** + * Enter a parse tree produced by the {@code boxJoin} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void enterBoxJoin(AlloyInEcoreParser.BoxJoinContext ctx); + /** + * Exit a parse tree produced by the {@code boxJoin} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + */ + void exitBoxJoin(AlloyInEcoreParser.BoxJoinContext ctx); + /** + * Enter a parse tree produced by the {@code minus} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void enterMinus(AlloyInEcoreParser.MinusContext ctx); + /** + * Exit a parse tree produced by the {@code minus} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void exitMinus(AlloyInEcoreParser.MinusContext ctx); + /** + * Enter a parse tree produced by the {@code intConstant} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void enterIntConstant(AlloyInEcoreParser.IntConstantContext ctx); + /** + * Exit a parse tree produced by the {@code intConstant} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void exitIntConstant(AlloyInEcoreParser.IntConstantContext ctx); + /** + * Enter a parse tree produced by the {@code i_paranthesis} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void enterI_paranthesis(AlloyInEcoreParser.I_paranthesisContext ctx); + /** + * Exit a parse tree produced by the {@code i_paranthesis} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void exitI_paranthesis(AlloyInEcoreParser.I_paranthesisContext ctx); + /** + * Enter a parse tree produced by the {@code ifIntExpression} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void enterIfIntExpression(AlloyInEcoreParser.IfIntExpressionContext ctx); + /** + * Exit a parse tree produced by the {@code ifIntExpression} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void exitIfIntExpression(AlloyInEcoreParser.IfIntExpressionContext ctx); + /** + * Enter a parse tree produced by the {@code count} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void enterCount(AlloyInEcoreParser.CountContext ctx); + /** + * Exit a parse tree produced by the {@code count} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void exitCount(AlloyInEcoreParser.CountContext ctx); + /** + * Enter a parse tree produced by the {@code sum} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void enterSum(AlloyInEcoreParser.SumContext ctx); + /** + * Exit a parse tree produced by the {@code sum} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void exitSum(AlloyInEcoreParser.SumContext ctx); + /** + * Enter a parse tree produced by the {@code divide} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void enterDivide(AlloyInEcoreParser.DivideContext ctx); + /** + * Exit a parse tree produced by the {@code divide} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void exitDivide(AlloyInEcoreParser.DivideContext ctx); + /** + * Enter a parse tree produced by the {@code multiply} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void enterMultiply(AlloyInEcoreParser.MultiplyContext ctx); + /** + * Exit a parse tree produced by the {@code multiply} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void exitMultiply(AlloyInEcoreParser.MultiplyContext ctx); + /** + * Enter a parse tree produced by the {@code modulo} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void enterModulo(AlloyInEcoreParser.ModuloContext ctx); + /** + * Exit a parse tree produced by the {@code modulo} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void exitModulo(AlloyInEcoreParser.ModuloContext ctx); + /** + * Enter a parse tree produced by the {@code plus} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void enterPlus(AlloyInEcoreParser.PlusContext ctx); + /** + * Exit a parse tree produced by the {@code plus} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + */ + void exitPlus(AlloyInEcoreParser.PlusContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#quantifierDeclarations}. + * @param ctx the parse tree + */ + void enterQuantifierDeclarations(AlloyInEcoreParser.QuantifierDeclarationsContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#quantifierDeclarations}. + * @param ctx the parse tree + */ + void exitQuantifierDeclarations(AlloyInEcoreParser.QuantifierDeclarationsContext ctx); + /** + * Enter a parse tree produced by the {@code oneOf} + * labeled alternative in {@link AlloyInEcoreParser#quantifierDeclaration}. + * @param ctx the parse tree + */ + void enterOneOf(AlloyInEcoreParser.OneOfContext ctx); + /** + * Exit a parse tree produced by the {@code oneOf} + * labeled alternative in {@link AlloyInEcoreParser#quantifierDeclaration}. + * @param ctx the parse tree + */ + void exitOneOf(AlloyInEcoreParser.OneOfContext ctx); + /** + * Enter a parse tree produced by the {@code loneOf} + * labeled alternative in {@link AlloyInEcoreParser#quantifierDeclaration}. + * @param ctx the parse tree + */ + void enterLoneOf(AlloyInEcoreParser.LoneOfContext ctx); + /** + * Exit a parse tree produced by the {@code loneOf} + * labeled alternative in {@link AlloyInEcoreParser#quantifierDeclaration}. + * @param ctx the parse tree + */ + void exitLoneOf(AlloyInEcoreParser.LoneOfContext ctx); + /** + * Enter a parse tree produced by the {@code someOf} + * labeled alternative in {@link AlloyInEcoreParser#quantifierDeclaration}. + * @param ctx the parse tree + */ + void enterSomeOf(AlloyInEcoreParser.SomeOfContext ctx); + /** + * Exit a parse tree produced by the {@code someOf} + * labeled alternative in {@link AlloyInEcoreParser#quantifierDeclaration}. + * @param ctx the parse tree + */ + void exitSomeOf(AlloyInEcoreParser.SomeOfContext ctx); + /** + * Enter a parse tree produced by the {@code setOf} + * labeled alternative in {@link AlloyInEcoreParser#quantifierDeclaration}. + * @param ctx the parse tree + */ + void enterSetOf(AlloyInEcoreParser.SetOfContext ctx); + /** + * Exit a parse tree produced by the {@code setOf} + * labeled alternative in {@link AlloyInEcoreParser#quantifierDeclaration}. + * @param ctx the parse tree + */ + void exitSetOf(AlloyInEcoreParser.SetOfContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#letDeclarations}. + * @param ctx the parse tree + */ + void enterLetDeclarations(AlloyInEcoreParser.LetDeclarationsContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#letDeclarations}. + * @param ctx the parse tree + */ + void exitLetDeclarations(AlloyInEcoreParser.LetDeclarationsContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#letDeclaration}. + * @param ctx the parse tree + */ + void enterLetDeclaration(AlloyInEcoreParser.LetDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#letDeclaration}. + * @param ctx the parse tree + */ + void exitLetDeclaration(AlloyInEcoreParser.LetDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#comprehensionDeclarations}. + * @param ctx the parse tree + */ + void enterComprehensionDeclarations(AlloyInEcoreParser.ComprehensionDeclarationsContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#comprehensionDeclarations}. + * @param ctx the parse tree + */ + void exitComprehensionDeclarations(AlloyInEcoreParser.ComprehensionDeclarationsContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#comprehensionDeclaration}. + * @param ctx the parse tree + */ + void enterComprehensionDeclaration(AlloyInEcoreParser.ComprehensionDeclarationContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#comprehensionDeclaration}. + * @param ctx the parse tree + */ + void exitComprehensionDeclaration(AlloyInEcoreParser.ComprehensionDeclarationContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#relationId}. + * @param ctx the parse tree + */ + void enterRelationId(AlloyInEcoreParser.RelationIdContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#relationId}. + * @param ctx the parse tree + */ + void exitRelationId(AlloyInEcoreParser.RelationIdContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#variable}. + * @param ctx the parse tree + */ + void enterVariable(AlloyInEcoreParser.VariableContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#variable}. + * @param ctx the parse tree + */ + void exitVariable(AlloyInEcoreParser.VariableContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#mult}. + * @param ctx the parse tree + */ + void enterMult(AlloyInEcoreParser.MultContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#mult}. + * @param ctx the parse tree + */ + void exitMult(AlloyInEcoreParser.MultContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#unrestrictedName}. + * @param ctx the parse tree + */ + void enterUnrestrictedName(AlloyInEcoreParser.UnrestrictedNameContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#unrestrictedName}. + * @param ctx the parse tree + */ + void exitUnrestrictedName(AlloyInEcoreParser.UnrestrictedNameContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#identifier}. + * @param ctx the parse tree + */ + void enterIdentifier(AlloyInEcoreParser.IdentifierContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#identifier}. + * @param ctx the parse tree + */ + void exitIdentifier(AlloyInEcoreParser.IdentifierContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#upper}. + * @param ctx the parse tree + */ + void enterUpper(AlloyInEcoreParser.UpperContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#upper}. + * @param ctx the parse tree + */ + void exitUpper(AlloyInEcoreParser.UpperContext ctx); + /** + * Enter a parse tree produced by {@link AlloyInEcoreParser#lower}. + * @param ctx the parse tree + */ + void enterLower(AlloyInEcoreParser.LowerContext ctx); + /** + * Exit a parse tree produced by {@link AlloyInEcoreParser#lower}. + * @param ctx the parse tree + */ + void exitLower(AlloyInEcoreParser.LowerContext ctx); +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreParser.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreParser.java new file mode 100644 index 00000000..068ee813 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreParser.java @@ -0,0 +1,12289 @@ +// Generated from /home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcore.g4 by ANTLR 4.6 +package eu.modelwriter.core.alloyinecore.recognizer; + + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EcoreFactory; +import org.eclipse.emf.ecore.EcorePackage; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.ETypedElement; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EClassifier; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EOperation; +import org.eclipse.emf.ecore.EParameter; +import org.eclipse.emf.ecore.EEnum; +import org.eclipse.emf.ecore.EEnumLiteral; +import org.eclipse.emf.ecore.EDataType; +import org.eclipse.emf.ecore.ETypedElement; +import org.eclipse.emf.ecore.EAnnotation; +import org.eclipse.emf.ecore.EGenericType; +import org.eclipse.emf.ecore.ETypeParameter; + +import eu.modelwriter.core.alloyinecore.structure.base.INamespace; +import eu.modelwriter.core.alloyinecore.structure.base.Repository; +import eu.modelwriter.core.alloyinecore.structure.base.Element; + +import eu.modelwriter.core.alloyinecore.structure.model.ModelElement; +import eu.modelwriter.core.alloyinecore.structure.model.Annotation; +import eu.modelwriter.core.alloyinecore.structure.model.AnnotationDetail; +import eu.modelwriter.core.alloyinecore.structure.model.AnnotationReference; +import eu.modelwriter.core.alloyinecore.structure.model.NamedElement; +import eu.modelwriter.core.alloyinecore.structure.model.Model; +import eu.modelwriter.core.alloyinecore.structure.model.Import; +import eu.modelwriter.core.alloyinecore.structure.model.EcoreImport; +import eu.modelwriter.core.alloyinecore.structure.model.Package; +import eu.modelwriter.core.alloyinecore.structure.model.RootPackage; +import eu.modelwriter.core.alloyinecore.structure.model.Classifier; +import eu.modelwriter.core.alloyinecore.structure.model.Class; +import eu.modelwriter.core.alloyinecore.structure.model.Interface; +import eu.modelwriter.core.alloyinecore.structure.model.DataType; +import eu.modelwriter.core.alloyinecore.structure.model.Enum; +import eu.modelwriter.core.alloyinecore.structure.model.EnumLiteral; +import eu.modelwriter.core.alloyinecore.structure.model.StructuralFeature; +import eu.modelwriter.core.alloyinecore.structure.model.TypedElement; +import eu.modelwriter.core.alloyinecore.structure.model.Multiplicity; +import eu.modelwriter.core.alloyinecore.structure.model.Reference; +import eu.modelwriter.core.alloyinecore.structure.model.Attribute; +import eu.modelwriter.core.alloyinecore.structure.model.Operation; +import eu.modelwriter.core.alloyinecore.structure.model.Parameter; +import eu.modelwriter.core.alloyinecore.structure.model.GenericException; +import eu.modelwriter.core.alloyinecore.structure.model.TypeParameter; +import eu.modelwriter.core.alloyinecore.structure.model.GenericType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericTypeArgument; +import eu.modelwriter.core.alloyinecore.structure.model.GenericElementType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericSuperType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericWildcard; +import eu.modelwriter.core.alloyinecore.structure.model.PrimitiveType; +import eu.modelwriter.core.alloyinecore.structure.model.Invariant; +import eu.modelwriter.core.alloyinecore.structure.model.Derivation; +import eu.modelwriter.core.alloyinecore.structure.model.Body; +import eu.modelwriter.core.alloyinecore.structure.model.PostCondition; +import eu.modelwriter.core.alloyinecore.structure.model.PreCondition; +import eu.modelwriter.core.alloyinecore.structure.model.Initial; + +import eu.modelwriter.core.alloyinecore.structure.instance.ModelImport; +import eu.modelwriter.core.alloyinecore.structure.instance.Instance; +import eu.modelwriter.core.alloyinecore.structure.instance.Object; +import eu.modelwriter.core.alloyinecore.structure.instance.Slot; +import eu.modelwriter.core.alloyinecore.structure.instance.ObjectValue; +import eu.modelwriter.core.alloyinecore.structure.instance.EnumValue; +import eu.modelwriter.core.alloyinecore.structure.instance.IntegerValue; +import eu.modelwriter.core.alloyinecore.structure.instance.RealValue; +import eu.modelwriter.core.alloyinecore.structure.instance.BooleanValue; +import eu.modelwriter.core.alloyinecore.structure.instance.StringValue; +import eu.modelwriter.core.alloyinecore.structure.instance.NullValue; +import eu.modelwriter.core.alloyinecore.structure.instance.CharValue; + +import eu.modelwriter.core.alloyinecore.structure.constraints.Formula; +import eu.modelwriter.core.alloyinecore.structure.constraints.Expression; +import eu.modelwriter.core.alloyinecore.structure.constraints.IntExpression; +import eu.modelwriter.core.alloyinecore.structure.constraints.QuantifierDeclaration; +import eu.modelwriter.core.alloyinecore.structure.constraints.LetDeclaration; +import eu.modelwriter.core.alloyinecore.structure.constraints.ComprehensionDeclaration; +import eu.modelwriter.core.alloyinecore.structure.constraints.Variable; + +import eu.modelwriter.core.alloyinecore.internal.AnnotationSources; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl; +import org.eclipse.emf.ecore.util.EcoreUtil; + +import java.util.stream.Collectors; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +import java.io.IOException; + +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.misc.*; +import org.antlr.v4.runtime.tree.*; +import java.util.List; +import java.util.Iterator; +import java.util.ArrayList; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class AlloyInEcoreParser extends Parser { + static { RuntimeMetaData.checkVersion("4.6", RuntimeMetaData.VERSION); } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, + T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, + T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, + T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, T__29=30, T__30=31, + T__31=32, T__32=33, T__33=34, T__34=35, T__35=36, T__36=37, T__37=38, + T__38=39, T__39=40, T__40=41, T__41=42, T__42=43, T__43=44, T__44=45, + T__45=46, T__46=47, T__47=48, T__48=49, T__49=50, T__50=51, T__51=52, + T__52=53, T__53=54, T__54=55, T__55=56, T__56=57, T__57=58, T__58=59, + T__59=60, T__60=61, T__61=62, T__62=63, T__63=64, T__64=65, T__65=66, + T__66=67, T__67=68, T__68=69, T__69=70, T__70=71, T__71=72, T__72=73, + T__73=74, T__74=75, T__75=76, T__76=77, T__77=78, T__78=79, T__79=80, + T__80=81, T__81=82, T__82=83, T__83=84, T__84=85, T__85=86, T__86=87, + T__87=88, T__88=89, T__89=90, T__90=91, T__91=92, T__92=93, T__93=94, + T__94=95, T__95=96, T__96=97, T__97=98, T__98=99, T__99=100, T__100=101, + T__101=102, T__102=103, T__103=104, T__104=105, T__105=106, T__106=107, + T__107=108, T__108=109, T__109=110, T__110=111, T__111=112, T__112=113, + T__113=114, T__114=115, T__115=116, T__116=117, T__117=118, T__118=119, + T__119=120, T__120=121, T__121=122, T__122=123, T__123=124, T__124=125, + T__125=126, T__126=127, T__127=128, T__128=129, T__129=130, T__130=131, + T__131=132, T__132=133, T__133=134, INT=135, IDENTIFIER=136, SINGLE_CHARACTER=137, + DOUBLE_QUOTED_STRING=138, SINGLE_QUOTED_STRING=139, ML_SINGLE_QUOTED_STRING=140, + MULTILINE_COMMENT=141, SINGLELINE_COMMENT=142, WS=143; + public static final int + RULE_options = 0, RULE_option = 1, RULE_instance = 2, RULE_modelImport = 3, + RULE_eObject = 4, RULE_slot = 5, RULE_dataValue = 6, RULE_multiValueData = 7, + RULE_eObjectValue = 8, RULE_literalValue = 9, RULE_enumValue = 10, RULE_booleanValue = 11, + RULE_integerValue = 12, RULE_realValue = 13, RULE_stringValue = 14, RULE_charValue = 15, + RULE_nullValue = 16, RULE_model = 17, RULE_packageImport = 18, RULE_ePackage = 19, + RULE_eClassifier = 20, RULE_eClass = 21, RULE_eStructuralFeature = 22, + RULE_eAttribute = 23, RULE_eReference = 24, RULE_eOperation = 25, RULE_eGenericException = 26, + RULE_eGenericSuperType = 27, RULE_eParameter = 28, RULE_eMultiplicity = 29, + RULE_eDataType = 30, RULE_eEnum = 31, RULE_eEnumLiteral = 32, RULE_eAnnotation = 33, + RULE_eDetail = 34, RULE_eModelElement = 35, RULE_eNamedElement = 36, RULE_eTypedElement = 37, + RULE_eModelElementRef = 38, RULE_templateSignature = 39, RULE_eTypeParameter = 40, + RULE_eGenericTypeArgument = 41, RULE_eGenericType = 42, RULE_eGenericElementType = 43, + RULE_eGenericWildcard = 44, RULE_pathName = 45, RULE_segment = 46, RULE_ePrimitiveType = 47, + RULE_body = 48, RULE_invariant = 49, RULE_precondition = 50, RULE_postcondition = 51, + RULE_initial = 52, RULE_derivation = 53, RULE_visibilityKind = 54, RULE_formula = 55, + RULE_expression = 56, RULE_intExpression = 57, RULE_quantifierDeclarations = 58, + RULE_quantifierDeclaration = 59, RULE_letDeclarations = 60, RULE_letDeclaration = 61, + RULE_comprehensionDeclarations = 62, RULE_comprehensionDeclaration = 63, + RULE_relationId = 64, RULE_variable = 65, RULE_mult = 66, RULE_unrestrictedName = 67, + RULE_identifier = 68, RULE_upper = 69, RULE_lower = 70; + public static final String[] ruleNames = { + "options", "option", "instance", "modelImport", "eObject", "slot", "dataValue", + "multiValueData", "eObjectValue", "literalValue", "enumValue", "booleanValue", + "integerValue", "realValue", "stringValue", "charValue", "nullValue", + "model", "packageImport", "ePackage", "eClassifier", "eClass", "eStructuralFeature", + "eAttribute", "eReference", "eOperation", "eGenericException", "eGenericSuperType", + "eParameter", "eMultiplicity", "eDataType", "eEnum", "eEnumLiteral", "eAnnotation", + "eDetail", "eModelElement", "eNamedElement", "eTypedElement", "eModelElementRef", + "templateSignature", "eTypeParameter", "eGenericTypeArgument", "eGenericType", + "eGenericElementType", "eGenericWildcard", "pathName", "segment", "ePrimitiveType", + "body", "invariant", "precondition", "postcondition", "initial", "derivation", + "visibilityKind", "formula", "expression", "intExpression", "quantifierDeclarations", + "quantifierDeclaration", "letDeclarations", "letDeclaration", "comprehensionDeclarations", + "comprehensionDeclaration", "relationId", "variable", "mult", "unrestrictedName", + "identifier", "upper", "lower" + }; + + private static final String[] _LITERAL_NAMES = { + null, "'options'", "'{'", "','", "'}'", "'symmetry_breaking'", "':'", + "'bit_width'", "'skolem_depth'", "'sharing'", "'instance'", "';'", "'model'", + "'['", "']'", "'true'", "'false'", "'+'", "'-'", "'.'", "'null'", "'import'", + "'package'", "'='", "'abstract'", "'class'", "'interface'", "'extends'", + "'static'", "'ghost'", "'transient'", "'volatile'", "'readonly'", "'attribute'", + "'derived'", "'id'", "'ordered'", "'!ordered'", "'unique'", "'!unique'", + "'unsettable'", "'!unsettable'", "'property'", "'#'", "'composes'", "'resolve'", + "'!resolve'", "'key'", "'operation'", "'('", "')'", "'throws'", "'..'", + "'*'", "'?'", "'|?'", "'|1'", "'primitive'", "'datatype'", "'serializable'", + "'!serializable'", "'enum'", "'literal'", "'annotation'", "'reference'", + "'<'", "'>'", "'&'", "'super'", "'::'", "'@'", "'Boolean'", "'Integer'", + "'String'", "'Real'", "'UnlimitedNatural'", "'body'", "'callable'", "'invariant'", + "'precondition'", "'requires'", "'postcondition'", "'ensures'", "'initial'", + "'derivation'", "'public'", "'protected'", "'private'", "'no'", "'lone'", + "'one'", "'some'", "'!'", "'not'", "'in'", "'<='", "'>='", "'sum'", "'|'", + "'acyclic'", "'function'", "'->'", "'ord'", "'&&'", "'and'", "'||'", "'or'", + "'=>'", "'if'", "'implies'", "'<=>'", "'iff'", "'all'", "'let'", "'~'", + "'^'", "'++'", "'then'", "'else'", "'iden'", "'none'", "'univ'", "'ints'", + "'plus'", "'minus'", "'mul'", "'/'", "'div'", "'%'", "'modulo'", "'disj'", + "'set'", "'definition'", "'ensure'", "'require'" + }; + private static final String[] _SYMBOLIC_NAMES = { + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, "INT", "IDENTIFIER", "SINGLE_CHARACTER", "DOUBLE_QUOTED_STRING", + "SINGLE_QUOTED_STRING", "ML_SINGLE_QUOTED_STRING", "MULTILINE_COMMENT", + "SINGLELINE_COMMENT", "WS" + }; + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + @Override + public String getGrammarFileName() { return "AlloyInEcore.g4"; } + + @Override + public String[] getRuleNames() { return ruleNames; } + + @Override + public String getSerializedATN() { return _serializedATN; } + + @Override + public ATN getATN() { return _ATN; } + + + + public Model model; + public Instance instance; + private boolean resolveImports = true; + + Repository repository = new Repository(); + + + URI saveURI; + + public AlloyInEcoreParser(TokenStream input, URI saveURI){ + this(input); + this.saveURI = saveURI; + repository = new Repository(saveURI); + } + + public AlloyInEcoreParser(TokenStream input, URI saveURI, boolean resolveImports){ + this(input, saveURI); + this.resolveImports = resolveImports; + } + + + public void saveResource(String filename, String path){ + model.printTree(); + repository.printNamespaces(); + if (model.getOwnedPackage() != null) { + ResourceSet metaResourceSet = new ResourceSetImpl(); + metaResourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("ecore", new XMLResourceFactoryImpl()); + Resource metaResource = metaResourceSet.createResource(URI.createURI(path + filename + ".ecore")); + metaResource.getContents().add(model.getOwnedPackage().getEObject()); + try { + metaResource.save(null); + } catch (java.io.IOException e) { + e.printStackTrace(); + } + } + } + + private String getLocation() { return "["+ getCurrentToken().getLine()+ ","+ getCurrentToken().getCharPositionInLine()+ "]";} + + private String getContextText(ParserRuleContext ctx){ + return getTokenStream().getTokenSource().getInputStream().toString().substring(ctx.start.getStartIndex(),ctx.stop.getStopIndex()); + } + + + private EcoreFactory eFactory = EcoreFactory.eINSTANCE; + + private void signalParsingCompletion() { + //restoreReferences(); + //checkConstraints(); + } + + private void createEAnnotation(EModelElement owner, final String source) { + if (owner.getEAnnotation(source) != null) + return; + final EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation(); + eAnnotation.setSource(source); + owner.getEAnnotations().add(eAnnotation); + } + + //private java.util.Stack owners = new java.util.Stack<>(); + + + public AlloyInEcoreParser(TokenStream input) { + super(input); + _interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); + } + public static class OptionsContext extends ParserRuleContext { + public List option() { + return getRuleContexts(OptionContext.class); + } + public OptionContext option(int i) { + return getRuleContext(OptionContext.class,i); + } + public OptionsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_options; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterOptions(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitOptions(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitOptions(this); + else return visitor.visitChildren(this); + } + } + + public final OptionsContext options() throws RecognitionException { + OptionsContext _localctx = new OptionsContext(_ctx, getState()); + enterRule(_localctx, 0, RULE_options); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(142); + match(T__0); + setState(143); + match(T__1); + setState(144); + option(); + setState(149); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(145); + match(T__2); + setState(146); + option(); + } + } + setState(151); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(152); + match(T__3); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class OptionContext extends ParserRuleContext { + public OptionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_option; } + + public OptionContext() { } + public void copyFrom(OptionContext ctx) { + super.copyFrom(ctx); + } + } + public static class SymmetryBreakingContext extends OptionContext { + public Token key; + public Token value; + public TerminalNode INT() { return getToken(AlloyInEcoreParser.INT, 0); } + public SymmetryBreakingContext(OptionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterSymmetryBreaking(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitSymmetryBreaking(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitSymmetryBreaking(this); + else return visitor.visitChildren(this); + } + } + public static class BitWidthContext extends OptionContext { + public Token key; + public Token value; + public TerminalNode INT() { return getToken(AlloyInEcoreParser.INT, 0); } + public BitWidthContext(OptionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterBitWidth(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitBitWidth(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitBitWidth(this); + else return visitor.visitChildren(this); + } + } + public static class SkolemDepthContext extends OptionContext { + public Token key; + public Token value; + public TerminalNode INT() { return getToken(AlloyInEcoreParser.INT, 0); } + public SkolemDepthContext(OptionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterSkolemDepth(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitSkolemDepth(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitSkolemDepth(this); + else return visitor.visitChildren(this); + } + } + public static class SharingContext extends OptionContext { + public Token key; + public Token value; + public TerminalNode INT() { return getToken(AlloyInEcoreParser.INT, 0); } + public SharingContext(OptionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterSharing(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitSharing(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitSharing(this); + else return visitor.visitChildren(this); + } + } + + public final OptionContext option() throws RecognitionException { + OptionContext _localctx = new OptionContext(_ctx, getState()); + enterRule(_localctx, 2, RULE_option); + try { + setState(166); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__4: + _localctx = new SymmetryBreakingContext(_localctx); + enterOuterAlt(_localctx, 1); + { + setState(154); + ((SymmetryBreakingContext)_localctx).key = match(T__4); + setState(155); + match(T__5); + setState(156); + ((SymmetryBreakingContext)_localctx).value = match(INT); + } + break; + case T__6: + _localctx = new BitWidthContext(_localctx); + enterOuterAlt(_localctx, 2); + { + setState(157); + ((BitWidthContext)_localctx).key = match(T__6); + setState(158); + match(T__5); + setState(159); + ((BitWidthContext)_localctx).value = match(INT); + } + break; + case T__7: + _localctx = new SkolemDepthContext(_localctx); + enterOuterAlt(_localctx, 3); + { + setState(160); + ((SkolemDepthContext)_localctx).key = match(T__7); + setState(161); + match(T__5); + setState(162); + ((SkolemDepthContext)_localctx).value = match(INT); + } + break; + case T__8: + _localctx = new SharingContext(_localctx); + enterOuterAlt(_localctx, 4); + { + setState(163); + ((SharingContext)_localctx).key = match(T__8); + setState(164); + match(T__5); + setState(165); + ((SharingContext)_localctx).value = match(INT); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class InstanceContext extends ParserRuleContext { + public Element owner; + public Instance current; + public IdentifierContext name; + public EObjectContext rootObject; + public ModelImportContext modelImport() { + return getRuleContext(ModelImportContext.class,0); + } + public List packageImport() { + return getRuleContexts(PackageImportContext.class); + } + public PackageImportContext packageImport(int i) { + return getRuleContext(PackageImportContext.class,i); + } + public EObjectContext eObject() { + return getRuleContext(EObjectContext.class,0); + } + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class,0); + } + public InstanceContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public InstanceContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_instance; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterInstance(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitInstance(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitInstance(this); + else return visitor.visitChildren(this); + } + } + + public final InstanceContext instance(Element owner) throws RecognitionException { + InstanceContext _localctx = new InstanceContext(_ctx, getState(), owner); + enterRule(_localctx, 4, RULE_instance); + ((InstanceContext)_localctx).current = new Instance(_localctx); instance= _localctx.current; if (owner!=null) owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(172); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__9) { + { + setState(168); + match(T__9); + setState(169); + ((InstanceContext)_localctx).name = identifier(); + setState(170); + match(T__10); + } + } + + setState(177); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__20) { + { + { + setState(174); + packageImport(_localctx.current); + } + } + setState(179); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(180); + modelImport(_localctx.current); + setState(183); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__11: + case T__20: + case T__21: + case T__23: + case T__24: + case T__25: + case T__26: + case T__27: + case T__29: + case T__30: + case T__31: + case T__32: + case T__33: + case T__34: + case T__35: + case T__37: + case T__39: + case T__41: + case T__43: + case T__44: + case T__46: + case T__47: + case T__50: + case T__56: + case T__57: + case T__58: + case T__60: + case T__61: + case T__62: + case T__63: + case T__75: + case T__76: + case T__77: + case T__78: + case T__80: + case T__82: + case T__83: + case T__131: + case T__132: + case T__133: + case IDENTIFIER: + { + setState(181); + ((InstanceContext)_localctx).rootObject = eObject(_localctx.current); + } + break; + case T__10: + { + setState(182); + match(T__10); + } + break; + default: + throw new NoViableAltException(this); + } + } + _ctx.stop = _input.LT(-1); + instance.printTree(); + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ModelImportContext extends ParserRuleContext { + public Element owner; + public ModelImport current; + public EObject object; + public UnrestrictedNameContext name; + public Token ownedPathName; + public TerminalNode SINGLE_QUOTED_STRING() { return getToken(AlloyInEcoreParser.SINGLE_QUOTED_STRING, 0); } + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public ModelImportContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public ModelImportContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_modelImport; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterModelImport(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitModelImport(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitModelImport(this); + else return visitor.visitChildren(this); + } + } + + public final ModelImportContext modelImport(Element owner) throws RecognitionException { + ModelImportContext _localctx = new ModelImportContext(_ctx, getState(), owner); + enterRule(_localctx, 6, RULE_modelImport); + ((ModelImportContext)_localctx).current = new ModelImport(_localctx); if (owner!=null) owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + { + setState(185); + match(T__11); + } + setState(189); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 12)) & ~0x3f) == 0 && ((1L << (_la - 12)) & ((1L << (T__11 - 12)) | (1L << (T__20 - 12)) | (1L << (T__21 - 12)) | (1L << (T__23 - 12)) | (1L << (T__24 - 12)) | (1L << (T__25 - 12)) | (1L << (T__26 - 12)) | (1L << (T__27 - 12)) | (1L << (T__29 - 12)) | (1L << (T__30 - 12)) | (1L << (T__31 - 12)) | (1L << (T__32 - 12)) | (1L << (T__33 - 12)) | (1L << (T__34 - 12)) | (1L << (T__35 - 12)) | (1L << (T__37 - 12)) | (1L << (T__39 - 12)) | (1L << (T__41 - 12)) | (1L << (T__43 - 12)) | (1L << (T__44 - 12)) | (1L << (T__46 - 12)) | (1L << (T__47 - 12)) | (1L << (T__50 - 12)) | (1L << (T__56 - 12)) | (1L << (T__57 - 12)) | (1L << (T__58 - 12)) | (1L << (T__60 - 12)) | (1L << (T__61 - 12)) | (1L << (T__62 - 12)) | (1L << (T__63 - 12)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + setState(186); + ((ModelImportContext)_localctx).name = unrestrictedName(); + setState(187); + match(T__5); + } + } + + setState(191); + ((ModelImportContext)_localctx).ownedPathName = match(SINGLE_QUOTED_STRING); + setState(192); + match(T__10); + } + _ctx.stop = _input.LT(-1); + + if (((ModelImportContext)_localctx).ownedPathName != null) { + String path = ((ModelImportContext)_localctx).ownedPathName.getText().replace("'", ""); + if (path.equals(EcorePackage.eNS_URI)) { + notifyErrorListeners(((ModelImportContext)_localctx).ownedPathName, "You cannot create an instance of ECore Model! Instead, create a model in model editor!", null); + } else { + Resource resource = repository.loadResource(path); + if (resource == null) { + notifyErrorListeners(((ModelImportContext)_localctx).ownedPathName, "Import could not be resolved!", null); + } + else { + ((ModelImportContext)_localctx).object = repository.loadResource(path).getContents().get(0); + if (_localctx.object instanceof ENamedElement) { + _localctx.current.setEObject(_localctx.object); + repository.name2Import.put(_localctx.current.getKey(), _localctx.current); + _localctx.current.loadNamespace(repository); + } else { + notifyErrorListeners(((ModelImportContext)_localctx).ownedPathName, "This is an instance, cannot be used as a model!", null); + } + } + } + } + + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EObjectContext extends ParserRuleContext { + public Element owner; + public Object current; + public PathNameContext name; + public LiteralValueContext id; + public SlotContext slot; + public List slots = new ArrayList(); + public PathNameContext pathName() { + return getRuleContext(PathNameContext.class,0); + } + public List slot() { + return getRuleContexts(SlotContext.class); + } + public SlotContext slot(int i) { + return getRuleContext(SlotContext.class,i); + } + public LiteralValueContext literalValue() { + return getRuleContext(LiteralValueContext.class,0); + } + public EObjectContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EObjectContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eObject; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEObject(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEObject(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEObject(this); + else return visitor.visitChildren(this); + } + } + + public final EObjectContext eObject(Element owner) throws RecognitionException { + EObjectContext _localctx = new EObjectContext(_ctx, getState(), owner); + enterRule(_localctx, 8, RULE_eObject); + ((EObjectContext)_localctx).current = new Object(_localctx); if (owner!=null) owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(194); + ((EObjectContext)_localctx).name = pathName(_localctx.current); + + setState(197); + _errHandler.sync(this); + _la = _input.LA(1); + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19))) != 0) || ((((_la - 135)) & ~0x3f) == 0 && ((1L << (_la - 135)) & ((1L << (INT - 135)) | (1L << (IDENTIFIER - 135)) | (1L << (SINGLE_CHARACTER - 135)) | (1L << (DOUBLE_QUOTED_STRING - 135)))) != 0)) { + { + setState(196); + ((EObjectContext)_localctx).id = literalValue(_localctx.owner); + } + } + + + setState(212); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__1: + { + setState(200); + match(T__1); + setState(201); + ((EObjectContext)_localctx).slot = slot(_localctx.current); + ((EObjectContext)_localctx).slots.add(((EObjectContext)_localctx).slot); + setState(206); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(202); + match(T__2); + setState(203); + ((EObjectContext)_localctx).slot = slot(_localctx.current); + ((EObjectContext)_localctx).slots.add(((EObjectContext)_localctx).slot); + } + } + setState(208); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(209); + match(T__3); + } + break; + case T__10: + { + setState(211); + match(T__10); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class SlotContext extends ParserRuleContext { + public Element owner; + public Slot current; + public UnrestrictedNameContext name; + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public List eObjectValue() { + return getRuleContexts(EObjectValueContext.class); + } + public EObjectValueContext eObjectValue(int i) { + return getRuleContext(EObjectValueContext.class,i); + } + public DataValueContext dataValue() { + return getRuleContext(DataValueContext.class,0); + } + public List eObject() { + return getRuleContexts(EObjectContext.class); + } + public EObjectContext eObject(int i) { + return getRuleContext(EObjectContext.class,i); + } + public SlotContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public SlotContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_slot; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterSlot(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitSlot(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitSlot(this); + else return visitor.visitChildren(this); + } + } + + public final SlotContext slot(Element owner) throws RecognitionException { + SlotContext _localctx = new SlotContext(_ctx, getState(), owner); + enterRule(_localctx, 10, RULE_slot); + ((SlotContext)_localctx).current = new Slot(_localctx); if (owner!=null) owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(214); + ((SlotContext)_localctx).name = unrestrictedName(); + + setState(241); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__5) { + { + setState(216); + match(T__5); + setState(239); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,11,_ctx) ) { + case 1: + { + setState(217); + if (!(true)) throw new FailedPredicateException(this, "true"); + setState(218); + match(T__1); + setState(222); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 12)) & ~0x3f) == 0 && ((1L << (_la - 12)) & ((1L << (T__11 - 12)) | (1L << (T__20 - 12)) | (1L << (T__21 - 12)) | (1L << (T__23 - 12)) | (1L << (T__24 - 12)) | (1L << (T__25 - 12)) | (1L << (T__26 - 12)) | (1L << (T__27 - 12)) | (1L << (T__29 - 12)) | (1L << (T__30 - 12)) | (1L << (T__31 - 12)) | (1L << (T__32 - 12)) | (1L << (T__33 - 12)) | (1L << (T__34 - 12)) | (1L << (T__35 - 12)) | (1L << (T__37 - 12)) | (1L << (T__39 - 12)) | (1L << (T__41 - 12)) | (1L << (T__43 - 12)) | (1L << (T__44 - 12)) | (1L << (T__46 - 12)) | (1L << (T__47 - 12)) | (1L << (T__50 - 12)) | (1L << (T__56 - 12)) | (1L << (T__57 - 12)) | (1L << (T__58 - 12)) | (1L << (T__60 - 12)) | (1L << (T__61 - 12)) | (1L << (T__62 - 12)) | (1L << (T__63 - 12)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + { + setState(219); + eObject(_localctx.current); + } + } + setState(224); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(225); + match(T__3); + } + break; + case 2: + { + setState(226); + eObjectValue(_localctx.current); + } + break; + case 3: + { + setState(227); + match(T__12); + setState(228); + eObjectValue(_localctx.current); + setState(233); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(229); + match(T__2); + setState(230); + eObjectValue(_localctx.current); + } + } + setState(235); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(236); + match(T__13); + } + break; + case 4: + { + setState(238); + dataValue(_localctx.current); + } + break; + } + } + } + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class DataValueContext extends ParserRuleContext { + public Element owner; + public LiteralValueContext literalValue() { + return getRuleContext(LiteralValueContext.class,0); + } + public MultiValueDataContext multiValueData() { + return getRuleContext(MultiValueDataContext.class,0); + } + public DataValueContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public DataValueContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_dataValue; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterDataValue(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitDataValue(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitDataValue(this); + else return visitor.visitChildren(this); + } + } + + public final DataValueContext dataValue(Element owner) throws RecognitionException { + DataValueContext _localctx = new DataValueContext(_ctx, getState(), owner); + enterRule(_localctx, 12, RULE_dataValue); + try { + setState(245); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__14: + case T__15: + case T__16: + case T__17: + case T__18: + case T__19: + case INT: + case IDENTIFIER: + case SINGLE_CHARACTER: + case DOUBLE_QUOTED_STRING: + enterOuterAlt(_localctx, 1); + { + setState(243); + literalValue(_localctx.owner); + } + break; + case T__12: + enterOuterAlt(_localctx, 2); + { + setState(244); + multiValueData(_localctx.owner); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class MultiValueDataContext extends ParserRuleContext { + public Element owner; + public List dataValue() { + return getRuleContexts(DataValueContext.class); + } + public DataValueContext dataValue(int i) { + return getRuleContext(DataValueContext.class,i); + } + public MultiValueDataContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public MultiValueDataContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_multiValueData; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterMultiValueData(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitMultiValueData(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitMultiValueData(this); + else return visitor.visitChildren(this); + } + } + + public final MultiValueDataContext multiValueData(Element owner) throws RecognitionException { + MultiValueDataContext _localctx = new MultiValueDataContext(_ctx, getState(), owner); + enterRule(_localctx, 14, RULE_multiValueData); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(247); + match(T__12); + setState(248); + dataValue(_localctx.owner); + setState(253); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(249); + match(T__2); + setState(250); + dataValue(_localctx.owner); + } + } + setState(255); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(256); + match(T__13); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EObjectValueContext extends ParserRuleContext { + public Element owner; + public ObjectValue current; + public PathNameContext pathName() { + return getRuleContext(PathNameContext.class,0); + } + public EObjectValueContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EObjectValueContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eObjectValue; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEObjectValue(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEObjectValue(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEObjectValue(this); + else return visitor.visitChildren(this); + } + } + + public final EObjectValueContext eObjectValue(Element owner) throws RecognitionException { + EObjectValueContext _localctx = new EObjectValueContext(_ctx, getState(), owner); + enterRule(_localctx, 16, RULE_eObjectValue); + ((EObjectValueContext)_localctx).current = new ObjectValue(_localctx); if (owner!=null) owner.addOwnedElement(_localctx.current); + try { + enterOuterAlt(_localctx, 1); + { + setState(258); + pathName(_localctx.current); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class LiteralValueContext extends ParserRuleContext { + public Element owner; + public Element current; + public EnumValueContext enumValue() { + return getRuleContext(EnumValueContext.class,0); + } + public IntegerValueContext integerValue() { + return getRuleContext(IntegerValueContext.class,0); + } + public RealValueContext realValue() { + return getRuleContext(RealValueContext.class,0); + } + public StringValueContext stringValue() { + return getRuleContext(StringValueContext.class,0); + } + public CharValueContext charValue() { + return getRuleContext(CharValueContext.class,0); + } + public BooleanValueContext booleanValue() { + return getRuleContext(BooleanValueContext.class,0); + } + public NullValueContext nullValue() { + return getRuleContext(NullValueContext.class,0); + } + public LiteralValueContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public LiteralValueContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_literalValue; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterLiteralValue(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitLiteralValue(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitLiteralValue(this); + else return visitor.visitChildren(this); + } + } + + public final LiteralValueContext literalValue(Element owner) throws RecognitionException { + LiteralValueContext _localctx = new LiteralValueContext(_ctx, getState(), owner); + enterRule(_localctx, 18, RULE_literalValue); + if(_localctx.parent instanceof EObjectContext) {} else { ((LiteralValueContext)_localctx).current = _localctx.owner;} + try { + setState(267); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,15,_ctx) ) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(260); + enumValue(_localctx.current); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(261); + integerValue(_localctx.current); + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(262); + realValue(_localctx.current); + } + break; + case 4: + enterOuterAlt(_localctx, 4); + { + setState(263); + stringValue(_localctx.current); + } + break; + case 5: + enterOuterAlt(_localctx, 5); + { + setState(264); + charValue(_localctx.current); + } + break; + case 6: + enterOuterAlt(_localctx, 6); + { + setState(265); + booleanValue(_localctx.current); + } + break; + case 7: + enterOuterAlt(_localctx, 7); + { + setState(266); + nullValue(_localctx.current); + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EnumValueContext extends ParserRuleContext { + public Element owner; + public EnumValue current; + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class,0); + } + public EnumValueContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EnumValueContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_enumValue; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEnumValue(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEnumValue(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEnumValue(this); + else return visitor.visitChildren(this); + } + } + + public final EnumValueContext enumValue(Element owner) throws RecognitionException { + EnumValueContext _localctx = new EnumValueContext(_ctx, getState(), owner); + enterRule(_localctx, 20, RULE_enumValue); + ((EnumValueContext)_localctx).current = new EnumValue(_localctx); if (owner!=null) _localctx.owner.addOwnedElement(_localctx.current); + try { + enterOuterAlt(_localctx, 1); + { + setState(269); + identifier(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class BooleanValueContext extends ParserRuleContext { + public Element owner; + public BooleanValue current; + public BooleanValueContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public BooleanValueContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_booleanValue; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterBooleanValue(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitBooleanValue(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitBooleanValue(this); + else return visitor.visitChildren(this); + } + } + + public final BooleanValueContext booleanValue(Element owner) throws RecognitionException { + BooleanValueContext _localctx = new BooleanValueContext(_ctx, getState(), owner); + enterRule(_localctx, 22, RULE_booleanValue); + ((BooleanValueContext)_localctx).current = new BooleanValue(_localctx); if (owner!=null) _localctx.owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(271); + _la = _input.LA(1); + if ( !(_la==T__14 || _la==T__15) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class IntegerValueContext extends ParserRuleContext { + public Element owner; + public IntegerValue current; + public TerminalNode INT() { return getToken(AlloyInEcoreParser.INT, 0); } + public IntegerValueContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public IntegerValueContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_integerValue; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterIntegerValue(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitIntegerValue(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitIntegerValue(this); + else return visitor.visitChildren(this); + } + } + + public final IntegerValueContext integerValue(Element owner) throws RecognitionException { + IntegerValueContext _localctx = new IntegerValueContext(_ctx, getState(), owner); + enterRule(_localctx, 24, RULE_integerValue); + ((IntegerValueContext)_localctx).current = new IntegerValue(_localctx); if (owner!=null) _localctx.owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(274); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__16 || _la==T__17) { + { + setState(273); + _la = _input.LA(1); + if ( !(_la==T__16 || _la==T__17) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + + setState(276); + match(INT); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class RealValueContext extends ParserRuleContext { + public Element owner; + public RealValue current; + public List INT() { return getTokens(AlloyInEcoreParser.INT); } + public TerminalNode INT(int i) { + return getToken(AlloyInEcoreParser.INT, i); + } + public RealValueContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public RealValueContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_realValue; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterRealValue(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitRealValue(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitRealValue(this); + else return visitor.visitChildren(this); + } + } + + public final RealValueContext realValue(Element owner) throws RecognitionException { + RealValueContext _localctx = new RealValueContext(_ctx, getState(), owner); + enterRule(_localctx, 26, RULE_realValue); + ((RealValueContext)_localctx).current = new RealValue(_localctx); if (owner!=null) _localctx.owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(279); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__16 || _la==T__17) { + { + setState(278); + _la = _input.LA(1); + if ( !(_la==T__16 || _la==T__17) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + + setState(282); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==INT) { + { + setState(281); + match(INT); + } + } + + setState(284); + match(T__18); + setState(285); + match(INT); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class StringValueContext extends ParserRuleContext { + public Element owner; + public StringValue current; + public TerminalNode DOUBLE_QUOTED_STRING() { return getToken(AlloyInEcoreParser.DOUBLE_QUOTED_STRING, 0); } + public StringValueContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public StringValueContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_stringValue; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterStringValue(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitStringValue(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitStringValue(this); + else return visitor.visitChildren(this); + } + } + + public final StringValueContext stringValue(Element owner) throws RecognitionException { + StringValueContext _localctx = new StringValueContext(_ctx, getState(), owner); + enterRule(_localctx, 28, RULE_stringValue); + ((StringValueContext)_localctx).current = new StringValue(_localctx); if (owner!=null) _localctx.owner.addOwnedElement(_localctx.current); + try { + enterOuterAlt(_localctx, 1); + { + setState(287); + match(DOUBLE_QUOTED_STRING); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class CharValueContext extends ParserRuleContext { + public Element owner; + public CharValue current; + public TerminalNode SINGLE_CHARACTER() { return getToken(AlloyInEcoreParser.SINGLE_CHARACTER, 0); } + public CharValueContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public CharValueContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_charValue; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterCharValue(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitCharValue(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitCharValue(this); + else return visitor.visitChildren(this); + } + } + + public final CharValueContext charValue(Element owner) throws RecognitionException { + CharValueContext _localctx = new CharValueContext(_ctx, getState(), owner); + enterRule(_localctx, 30, RULE_charValue); + ((CharValueContext)_localctx).current = new CharValue(_localctx); if (owner!=null) _localctx.owner.addOwnedElement(_localctx.current); + try { + enterOuterAlt(_localctx, 1); + { + setState(289); + match(SINGLE_CHARACTER); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class NullValueContext extends ParserRuleContext { + public Element owner; + public NullValue current; + public NullValueContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public NullValueContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_nullValue; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterNullValue(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitNullValue(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitNullValue(this); + else return visitor.visitChildren(this); + } + } + + public final NullValueContext nullValue(Element owner) throws RecognitionException { + NullValueContext _localctx = new NullValueContext(_ctx, getState(), owner); + enterRule(_localctx, 32, RULE_nullValue); + ((NullValueContext)_localctx).current = new NullValue(_localctx); if (owner!=null) _localctx.owner.addOwnedElement(_localctx.current); + try { + enterOuterAlt(_localctx, 1); + { + setState(291); + match(T__19); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ModelContext extends ParserRuleContext { + public EAnnotation element; + public IdentifierContext name; + public PackageImportContext packageImport; + public List ownedPackageImport = new ArrayList(); + public EPackageContext ownedPackage; + public EPackageContext ePackage; + public OptionsContext options() { + return getRuleContext(OptionsContext.class,0); + } + public EPackageContext ePackage() { + return getRuleContext(EPackageContext.class,0); + } + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class,0); + } + public List packageImport() { + return getRuleContexts(PackageImportContext.class); + } + public PackageImportContext packageImport(int i) { + return getRuleContext(PackageImportContext.class,i); + } + public ModelContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_model; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterModel(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitModel(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitModel(this); + else return visitor.visitChildren(this); + } + } + + public final ModelContext model() throws RecognitionException { + ModelContext _localctx = new ModelContext(_ctx, getState()); + enterRule(_localctx, 34, RULE_model); + model = new Model(_localctx); ((ModelContext)_localctx).element = eFactory.createEAnnotation(); _localctx.element.setSource(AnnotationSources.MODULE); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(294); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__0) { + { + setState(293); + options(); + } + } + + + setState(301); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__11) { + { + setState(297); + match(T__11); + setState(298); + ((ModelContext)_localctx).name = identifier(); + setState(299); + match(T__10); + } + } + + _localctx.element.getDetails().put("name", (((ModelContext)_localctx).name!=null?_input.getText(((ModelContext)_localctx).name.start,((ModelContext)_localctx).name.stop):null)); + setState(307); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__20) { + { + { + setState(304); + ((ModelContext)_localctx).packageImport = packageImport(model); + ((ModelContext)_localctx).ownedPackageImport.add(((ModelContext)_localctx).packageImport); + } + } + setState(309); + _errHandler.sync(this); + _la = _input.LA(1); + } + { + setState(310); + ((ModelContext)_localctx).ownedPackage = ((ModelContext)_localctx).ePackage = ePackage(model); + ((ModelContext)_localctx).ePackage.element.getEAnnotations().add(_localctx.element); + } + for(PackageImportContext ctx: _localctx.ownedPackageImport) {((ModelContext)_localctx).ePackage.element.getEAnnotations().add(ctx.element);} + } + _ctx.stop = _input.LT(-1); + signalParsingCompletion(); + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class PackageImportContext extends ParserRuleContext { + public Element owner; + public EAnnotation element; + public EObject object; + public IdentifierContext name; + public Token ownedPathName; + public TerminalNode SINGLE_QUOTED_STRING() { return getToken(AlloyInEcoreParser.SINGLE_QUOTED_STRING, 0); } + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class,0); + } + public PackageImportContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public PackageImportContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_packageImport; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterPackageImport(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitPackageImport(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitPackageImport(this); + else return visitor.visitChildren(this); + } + } + + public final PackageImportContext packageImport(Element owner) throws RecognitionException { + PackageImportContext _localctx = new PackageImportContext(_ctx, getState(), owner); + enterRule(_localctx, 36, RULE_packageImport); + ((PackageImportContext)_localctx).element = eFactory.createEAnnotation(); _localctx.element.setSource(AnnotationSources.IMPORT); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + { + setState(315); + match(T__20); + } + setState(319); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==IDENTIFIER) { + { + setState(316); + ((PackageImportContext)_localctx).name = identifier(); + setState(317); + match(T__5); + } + } + + setState(321); + ((PackageImportContext)_localctx).ownedPathName = match(SINGLE_QUOTED_STRING); + setState(322); + match(T__10); + _localctx.element.getDetails().put((((PackageImportContext)_localctx).name!=null?_input.getText(((PackageImportContext)_localctx).name.start,((PackageImportContext)_localctx).name.stop):null), ((PackageImportContext)_localctx).ownedPathName != null ? ((PackageImportContext)_localctx).ownedPathName.getText().replace("'", "") : null); + } + _ctx.stop = _input.LT(-1); + + if (((PackageImportContext)_localctx).ownedPathName != null) { + String path = ((PackageImportContext)_localctx).ownedPathName.getText().replace("'", ""); + Import imported = null; + if (path.equals(EcorePackage.eNS_URI)) { + ((PackageImportContext)_localctx).object = EcorePackage.eINSTANCE; + imported = new EcoreImport(_localctx.object, _localctx); + _localctx.owner.addOwnedElement(imported); + repository.name2Import.put(imported.getKey(), imported); + imported.loadNamespace(repository); + } else { + Resource resource = repository.loadResource(path); + if (resource == null) { + notifyErrorListeners(((PackageImportContext)_localctx).ownedPathName, "Import could not be resolved!", null); + + } else { + ((PackageImportContext)_localctx).object = repository.loadResource(path).getContents().get(0); + imported = new Import(_localctx.object, _localctx); + _localctx.owner.addOwnedElement(imported); + repository.name2Import.put(imported.getKey(), imported); + imported.loadNamespace(repository); + } + } + } + + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EPackageContext extends ParserRuleContext { + public Element owner; + public EPackage element; + public Package current; + public VisibilityKindContext visibility; + public UnrestrictedNameContext name; + public IdentifierContext nsPrefix; + public Token nsURI; + public EAnnotationContext eAnnotation; + public List ownedAnnotations = new ArrayList(); + public EPackageContext ePackage; + public List eSubPackages = new ArrayList(); + public EClassifierContext eClassifier; + public List eClassifiers = new ArrayList(); + public InvariantContext invariant; + public List eConstraints = new ArrayList(); + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class,0); + } + public TerminalNode SINGLE_QUOTED_STRING() { return getToken(AlloyInEcoreParser.SINGLE_QUOTED_STRING, 0); } + public VisibilityKindContext visibilityKind() { + return getRuleContext(VisibilityKindContext.class,0); + } + public List eAnnotation() { + return getRuleContexts(EAnnotationContext.class); + } + public EAnnotationContext eAnnotation(int i) { + return getRuleContext(EAnnotationContext.class,i); + } + public List ePackage() { + return getRuleContexts(EPackageContext.class); + } + public EPackageContext ePackage(int i) { + return getRuleContext(EPackageContext.class,i); + } + public List eClassifier() { + return getRuleContexts(EClassifierContext.class); + } + public EClassifierContext eClassifier(int i) { + return getRuleContext(EClassifierContext.class,i); + } + public List invariant() { + return getRuleContexts(InvariantContext.class); + } + public InvariantContext invariant(int i) { + return getRuleContext(InvariantContext.class,i); + } + public EPackageContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EPackageContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_ePackage; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEPackage(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEPackage(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEPackage(this); + else return visitor.visitChildren(this); + } + } + + public final EPackageContext ePackage(Element owner) throws RecognitionException { + EPackageContext _localctx = new EPackageContext(_ctx, getState(), owner); + enterRule(_localctx, 38, RULE_ePackage); + ((EPackageContext)_localctx).element = eFactory.createEPackage(); if(_localctx.parent instanceof ModelContext) {((EPackageContext)_localctx).current = new RootPackage(_localctx.element, _localctx);} else {((EPackageContext)_localctx).current = new Package(_localctx.element, _localctx);} + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(326); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 85)) & ~0x3f) == 0 && ((1L << (_la - 85)) & ((1L << (T__84 - 85)) | (1L << (T__85 - 85)) | (1L << (T__86 - 85)))) != 0)) { + { + setState(325); + ((EPackageContext)_localctx).visibility = visibilityKind(); + } + } + + if(_localctx.visibility != null) _localctx.element.getEAnnotations().add(((EPackageContext)_localctx).visibility.element); + setState(329); + match(T__21); + setState(330); + ((EPackageContext)_localctx).name = unrestrictedName(); + _localctx.element.setName((((EPackageContext)_localctx).name!=null?_input.getText(((EPackageContext)_localctx).name.start,((EPackageContext)_localctx).name.stop):null)); + if(_localctx.parent instanceof ModelContext) {repository.name2Import.put(((RootPackage)_localctx.current).getKey(), (RootPackage)_localctx.current);} + { + setState(333); + match(T__5); + setState(334); + ((EPackageContext)_localctx).nsPrefix = identifier(); + } + { + setState(336); + match(T__22); + setState(337); + ((EPackageContext)_localctx).nsURI = match(SINGLE_QUOTED_STRING); + } + _localctx.element.setNsPrefix((((EPackageContext)_localctx).nsPrefix!=null?_input.getText(((EPackageContext)_localctx).nsPrefix.start,((EPackageContext)_localctx).nsPrefix.stop):null)); if(((EPackageContext)_localctx).nsURI != null) _localctx.element.setNsURI(((EPackageContext)_localctx).nsURI.getText().replace("'", "")); + setState(360); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__1: + { + { + setState(340); + match(T__1); + setState(355); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__21) | (1L << T__23) | (1L << T__24) | (1L << T__25) | (1L << T__56) | (1L << T__57) | (1L << T__60) | (1L << T__62))) != 0) || ((((_la - 77)) & ~0x3f) == 0 && ((1L << (_la - 77)) & ((1L << (T__76 - 77)) | (1L << (T__77 - 77)) | (1L << (T__84 - 77)) | (1L << (T__85 - 77)) | (1L << (T__86 - 77)))) != 0)) { + { + setState(353); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,24,_ctx) ) { + case 1: + { + setState(341); + ((EPackageContext)_localctx).eAnnotation = ((EPackageContext)_localctx).eAnnotation = eAnnotation(_localctx.current); + ((EPackageContext)_localctx).ownedAnnotations.add(((EPackageContext)_localctx).eAnnotation); + _localctx.element.getEAnnotations().add(((EPackageContext)_localctx).eAnnotation.element); + } + break; + case 2: + { + setState(344); + ((EPackageContext)_localctx).ePackage = ((EPackageContext)_localctx).ePackage = ePackage(_localctx.current); + ((EPackageContext)_localctx).eSubPackages.add(((EPackageContext)_localctx).ePackage); + _localctx.element.getESubpackages().add(((EPackageContext)_localctx).ePackage.element); + } + break; + case 3: + { + setState(347); + ((EPackageContext)_localctx).eClassifier = ((EPackageContext)_localctx).eClassifier = eClassifier(_localctx.current); + ((EPackageContext)_localctx).eClassifiers.add(((EPackageContext)_localctx).eClassifier); + if (((EPackageContext)_localctx).eClassifier.element != null) _localctx.element.getEClassifiers().add(((EPackageContext)_localctx).eClassifier.element); + } + break; + case 4: + { + setState(350); + ((EPackageContext)_localctx).invariant = ((EPackageContext)_localctx).invariant = invariant(_localctx.current); + ((EPackageContext)_localctx).eConstraints.add(((EPackageContext)_localctx).invariant); + _localctx.element.getEAnnotations().add(((EPackageContext)_localctx).invariant.element); + } + break; + } + } + setState(357); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(358); + match(T__3); + } + } + break; + case T__10: + { + setState(359); + match(T__10); + } + break; + default: + throw new NoViableAltException(this); + } + } + _ctx.stop = _input.LT(-1); + owner.addOwnedElement(_localctx.current); + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EClassifierContext extends ParserRuleContext { + public Element owner; + public EClassifier element; + public EClassContext eClass; + public EDataTypeContext eDataType; + public EEnumContext eEnum; + public EClassContext eClass() { + return getRuleContext(EClassContext.class,0); + } + public EDataTypeContext eDataType() { + return getRuleContext(EDataTypeContext.class,0); + } + public EEnumContext eEnum() { + return getRuleContext(EEnumContext.class,0); + } + public EClassifierContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EClassifierContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eClassifier; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEClassifier(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEClassifier(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEClassifier(this); + else return visitor.visitChildren(this); + } + } + + public final EClassifierContext eClassifier(Element owner) throws RecognitionException { + EClassifierContext _localctx = new EClassifierContext(_ctx, getState(), owner); + enterRule(_localctx, 40, RULE_eClassifier); + try { + setState(371); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,27,_ctx) ) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(362); + ((EClassifierContext)_localctx).eClass = eClass(_localctx.owner); + ((EClassifierContext)_localctx).element = ((EClassifierContext)_localctx).eClass.element; + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(365); + ((EClassifierContext)_localctx).eDataType = eDataType(_localctx.owner); + ((EClassifierContext)_localctx).element = ((EClassifierContext)_localctx).eDataType.element; + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(368); + ((EClassifierContext)_localctx).eEnum = eEnum(_localctx.owner); + ((EClassifierContext)_localctx).element = ((EClassifierContext)_localctx).eEnum.element; + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EClassContext extends ParserRuleContext { + public Element owner; + public EClass element; + public Class current; + public VisibilityKindContext visibility; + public Token isAbstract; + public Token isClass; + public Token isInterface; + public UnrestrictedNameContext name; + public TemplateSignatureContext ownedSignature; + public TemplateSignatureContext templateSignature; + public EGenericSuperTypeContext eGenericSuperType; + public List eSuperTypes = new ArrayList(); + public Token instanceClassName; + public EAnnotationContext eAnnotation; + public List ownedAnnotations = new ArrayList(); + public EOperationContext eOperation; + public List eOperations = new ArrayList(); + public EStructuralFeatureContext eStructuralFeature; + public List eStructuralFeatures = new ArrayList(); + public InvariantContext invariant; + public List eConstraints = new ArrayList(); + public VisibilityKindContext visibilityKind() { + return getRuleContext(VisibilityKindContext.class,0); + } + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public TemplateSignatureContext templateSignature() { + return getRuleContext(TemplateSignatureContext.class,0); + } + public List eGenericSuperType() { + return getRuleContexts(EGenericSuperTypeContext.class); + } + public EGenericSuperTypeContext eGenericSuperType(int i) { + return getRuleContext(EGenericSuperTypeContext.class,i); + } + public TerminalNode SINGLE_QUOTED_STRING() { return getToken(AlloyInEcoreParser.SINGLE_QUOTED_STRING, 0); } + public List eAnnotation() { + return getRuleContexts(EAnnotationContext.class); + } + public EAnnotationContext eAnnotation(int i) { + return getRuleContext(EAnnotationContext.class,i); + } + public List eOperation() { + return getRuleContexts(EOperationContext.class); + } + public EOperationContext eOperation(int i) { + return getRuleContext(EOperationContext.class,i); + } + public List eStructuralFeature() { + return getRuleContexts(EStructuralFeatureContext.class); + } + public EStructuralFeatureContext eStructuralFeature(int i) { + return getRuleContext(EStructuralFeatureContext.class,i); + } + public List invariant() { + return getRuleContexts(InvariantContext.class); + } + public InvariantContext invariant(int i) { + return getRuleContext(InvariantContext.class,i); + } + public EClassContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EClassContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eClass; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEClass(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEClass(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEClass(this); + else return visitor.visitChildren(this); + } + } + + public final EClassContext eClass(Element owner) throws RecognitionException { + EClassContext _localctx = new EClassContext(_ctx, getState(), owner); + enterRule(_localctx, 42, RULE_eClass); + ((EClassContext)_localctx).element = eFactory.createEClass(); ((EClassContext)_localctx).current = new Class(_localctx.element, _localctx); if (owner!=null) owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(374); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 85)) & ~0x3f) == 0 && ((1L << (_la - 85)) & ((1L << (T__84 - 85)) | (1L << (T__85 - 85)) | (1L << (T__86 - 85)))) != 0)) { + { + setState(373); + ((EClassContext)_localctx).visibility = visibilityKind(); + } + } + + if(_localctx.visibility != null) _localctx.element.getEAnnotations().add(((EClassContext)_localctx).visibility.element); + setState(382); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__23: + case T__24: + { + setState(378); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__23) { + { + setState(377); + ((EClassContext)_localctx).isAbstract = match(T__23); + } + } + + setState(380); + ((EClassContext)_localctx).isClass = match(T__24); + } + break; + case T__25: + { + setState(381); + ((EClassContext)_localctx).isInterface = match(T__25); + } + break; + default: + throw new NoViableAltException(this); + } + _localctx.element.setAbstract(((EClassContext)_localctx).isAbstract!=null); if (((EClassContext)_localctx).isInterface!=null) {_localctx.element.setInterface(true);_localctx.element.setAbstract(true);} + setState(386); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,31,_ctx) ) { + case 1: + { + setState(385); + ((EClassContext)_localctx).name = unrestrictedName(); + } + break; + } + if (_localctx.name == null) {notifyErrorListeners("missing Class name");} else {_localctx.element.setName((((EClassContext)_localctx).name!=null?_input.getText(((EClassContext)_localctx).name.start,((EClassContext)_localctx).name.stop):null));} + if (((EClassContext)_localctx).isInterface!=null) {owner.deleteOwnedElement(_localctx.current); ((EClassContext)_localctx).current = new Interface(_localctx.element, _localctx); if (owner!=null) owner.addOwnedElement(_localctx.current);} + setState(391); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__64) { + { + setState(390); + ((EClassContext)_localctx).ownedSignature = ((EClassContext)_localctx).templateSignature = templateSignature(_localctx.current); + } + } + + if(_localctx.templateSignature != null) _localctx.element.getETypeParameters().addAll(((EClassContext)_localctx).templateSignature.typeParameters); + setState(403); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__26) { + { + setState(394); + match(T__26); + setState(395); + ((EClassContext)_localctx).eGenericSuperType = eGenericSuperType(_localctx.current); + ((EClassContext)_localctx).eSuperTypes.add(((EClassContext)_localctx).eGenericSuperType); + setState(400); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(396); + match(T__2); + setState(397); + ((EClassContext)_localctx).eGenericSuperType = eGenericSuperType(_localctx.current); + ((EClassContext)_localctx).eSuperTypes.add(((EClassContext)_localctx).eGenericSuperType); + } + } + setState(402); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + + + setState(408); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__5) { + { + setState(406); + match(T__5); + setState(407); + ((EClassContext)_localctx).instanceClassName = match(SINGLE_QUOTED_STRING); + } + } + + if(((EClassContext)_localctx).instanceClassName != null) _localctx.element.setInstanceClassName(((EClassContext)_localctx).instanceClassName.getText().replace("'", "")); + setState(431); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__1: + { + { + setState(411); + match(T__1); + setState(426); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__11) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__30) | (1L << T__31) | (1L << T__32) | (1L << T__41) | (1L << T__47) | (1L << T__62))) != 0) || ((((_la - 77)) & ~0x3f) == 0 && ((1L << (_la - 77)) & ((1L << (T__76 - 77)) | (1L << (T__77 - 77)) | (1L << (T__84 - 77)) | (1L << (T__85 - 77)) | (1L << (T__86 - 77)))) != 0)) { + { + setState(424); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,36,_ctx) ) { + case 1: + { + setState(412); + ((EClassContext)_localctx).eAnnotation = ((EClassContext)_localctx).eAnnotation = eAnnotation(_localctx.current); + ((EClassContext)_localctx).ownedAnnotations.add(((EClassContext)_localctx).eAnnotation); + if (((EClassContext)_localctx).eAnnotation.element != null) _localctx.element.getEAnnotations().add(((EClassContext)_localctx).eAnnotation.element); + } + break; + case 2: + { + setState(415); + ((EClassContext)_localctx).eOperation = ((EClassContext)_localctx).eOperation = eOperation(_localctx.current); + ((EClassContext)_localctx).eOperations.add(((EClassContext)_localctx).eOperation); + if (((EClassContext)_localctx).eOperation.element != null) _localctx.element.getEOperations().add(((EClassContext)_localctx).eOperation.element); + } + break; + case 3: + { + setState(418); + ((EClassContext)_localctx).eStructuralFeature = ((EClassContext)_localctx).eStructuralFeature = eStructuralFeature(_localctx.current); + ((EClassContext)_localctx).eStructuralFeatures.add(((EClassContext)_localctx).eStructuralFeature); + if (((EClassContext)_localctx).eStructuralFeature.element != null) _localctx.element.getEStructuralFeatures().add(((EClassContext)_localctx).eStructuralFeature.element); + } + break; + case 4: + { + setState(421); + ((EClassContext)_localctx).invariant = ((EClassContext)_localctx).invariant = invariant(_localctx.current); + ((EClassContext)_localctx).eConstraints.add(((EClassContext)_localctx).invariant); + if (((EClassContext)_localctx).invariant.element != null) _localctx.element.getEAnnotations().add(((EClassContext)_localctx).invariant.element); + } + break; + } + } + setState(428); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(429); + match(T__3); + } + } + break; + case T__10: + { + setState(430); + match(T__10); + } + break; + default: + throw new NoViableAltException(this); + } + } + _ctx.stop = _input.LT(-1); + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EStructuralFeatureContext extends ParserRuleContext { + public Element owner; + public EStructuralFeature element; + public EAttributeContext eAttribute; + public EReferenceContext eReference; + public EAttributeContext eAttribute() { + return getRuleContext(EAttributeContext.class,0); + } + public EReferenceContext eReference() { + return getRuleContext(EReferenceContext.class,0); + } + public EStructuralFeatureContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EStructuralFeatureContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eStructuralFeature; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEStructuralFeature(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEStructuralFeature(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEStructuralFeature(this); + else return visitor.visitChildren(this); + } + } + + public final EStructuralFeatureContext eStructuralFeature(Element owner) throws RecognitionException { + EStructuralFeatureContext _localctx = new EStructuralFeatureContext(_ctx, getState(), owner); + enterRule(_localctx, 44, RULE_eStructuralFeature); + try { + setState(439); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,39,_ctx) ) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(433); + ((EStructuralFeatureContext)_localctx).eAttribute = eAttribute(_localctx.owner); + ((EStructuralFeatureContext)_localctx).element = ((EStructuralFeatureContext)_localctx).eAttribute.element; + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(436); + ((EStructuralFeatureContext)_localctx).eReference = eReference(_localctx.owner); + ((EStructuralFeatureContext)_localctx).element = ((EStructuralFeatureContext)_localctx).eReference.element; + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EAttributeContext extends ParserRuleContext { + public Element owner; + public EAttribute element; + public Attribute current; + public VisibilityKindContext visibility; + public Token s28; + public List qualifier = new ArrayList(); + public Token s12; + public Token s29; + public Token s30; + public Token s31; + public Token s32; + public UnrestrictedNameContext name; + public EGenericElementTypeContext eAttributeType; + public EMultiplicityContext ownedMultiplicity; + public Token defaultValue; + public Token s34; + public Token s35; + public Token s36; + public Token s37; + public Token s38; + public Token s39; + public Token s40; + public Token s41; + public EAnnotationContext eAnnotation; + public List ownedAnnotations = new ArrayList(); + public DerivationContext ownedDerivation; + public DerivationContext derivation; + public InitialContext ownedInitial; + public InitialContext initial; + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public EGenericElementTypeContext eGenericElementType() { + return getRuleContext(EGenericElementTypeContext.class,0); + } + public VisibilityKindContext visibilityKind() { + return getRuleContext(VisibilityKindContext.class,0); + } + public EMultiplicityContext eMultiplicity() { + return getRuleContext(EMultiplicityContext.class,0); + } + public TerminalNode SINGLE_QUOTED_STRING() { return getToken(AlloyInEcoreParser.SINGLE_QUOTED_STRING, 0); } + public List eAnnotation() { + return getRuleContexts(EAnnotationContext.class); + } + public EAnnotationContext eAnnotation(int i) { + return getRuleContext(EAnnotationContext.class,i); + } + public DerivationContext derivation() { + return getRuleContext(DerivationContext.class,0); + } + public InitialContext initial() { + return getRuleContext(InitialContext.class,0); + } + public EAttributeContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EAttributeContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eAttribute; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEAttribute(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEAttribute(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEAttribute(this); + else return visitor.visitChildren(this); + } + } + + public final EAttributeContext eAttribute(Element owner) throws RecognitionException { + EAttributeContext _localctx = new EAttributeContext(_ctx, getState(), owner); + enterRule(_localctx, 46, RULE_eAttribute); + ((EAttributeContext)_localctx).element = eFactory.createEAttribute(); ((EAttributeContext)_localctx).current = new Attribute(_localctx.element, _localctx); if (owner!=null) owner.addOwnedElement(_localctx.current); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(442); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 85)) & ~0x3f) == 0 && ((1L << (_la - 85)) & ((1L << (T__84 - 85)) | (1L << (T__85 - 85)) | (1L << (T__86 - 85)))) != 0)) { + { + setState(441); + ((EAttributeContext)_localctx).visibility = visibilityKind(); + } + } + + if (_localctx.visibility != null) _localctx.element.getEAnnotations().add(((EAttributeContext)_localctx).visibility.element); + setState(446); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__27) { + { + setState(445); + ((EAttributeContext)_localctx).s28 = match(T__27); + ((EAttributeContext)_localctx).qualifier.add(((EAttributeContext)_localctx).s28); + } + } + + setState(450); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__11: + { + setState(448); + ((EAttributeContext)_localctx).s12 = match(T__11); + ((EAttributeContext)_localctx).qualifier.add(((EAttributeContext)_localctx).s12); + } + break; + case T__28: + { + setState(449); + ((EAttributeContext)_localctx).s29 = match(T__28); + ((EAttributeContext)_localctx).qualifier.add(((EAttributeContext)_localctx).s29); + } + break; + case T__29: + case T__30: + case T__31: + case T__32: + break; + default: + throw new NoViableAltException(this); + } + setState(453); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__29) { + { + setState(452); + ((EAttributeContext)_localctx).s30 = match(T__29); + ((EAttributeContext)_localctx).qualifier.add(((EAttributeContext)_localctx).s30); + } + } + + setState(456); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__30) { + { + setState(455); + ((EAttributeContext)_localctx).s31 = match(T__30); + ((EAttributeContext)_localctx).qualifier.add(((EAttributeContext)_localctx).s31); + } + } + + setState(459); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__31) { + { + setState(458); + ((EAttributeContext)_localctx).s32 = match(T__31); + ((EAttributeContext)_localctx).qualifier.add(((EAttributeContext)_localctx).s32); + } + } + + setState(461); + match(T__32); + setState(462); + ((EAttributeContext)_localctx).name = unrestrictedName(); + _localctx.element.setName((((EAttributeContext)_localctx).name!=null?_input.getText(((EAttributeContext)_localctx).name.start,((EAttributeContext)_localctx).name.stop):null)); + setState(464); + match(T__5); + setState(465); + ((EAttributeContext)_localctx).eAttributeType = eGenericElementType(_localctx.current); + setState(467); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__12) { + { + setState(466); + ((EAttributeContext)_localctx).ownedMultiplicity = eMultiplicity(_localctx.current, (ETypedElement)_localctx.element); + } + } + + if(_localctx.ownedMultiplicity == null) {_localctx.element.setLowerBound(1);} + setState(472); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__22) { + { + setState(470); + match(T__22); + setState(471); + ((EAttributeContext)_localctx).defaultValue = match(SINGLE_QUOTED_STRING); + } + } + + if(((EAttributeContext)_localctx).defaultValue != null) _localctx.element.setDefaultValueLiteral(((EAttributeContext)_localctx).defaultValue.getText().replace("'", "")); + setState(494); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,51,_ctx) ) { + case 1: + { + setState(475); + match(T__1); + setState(489); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(484); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__33: + { + setState(476); + ((EAttributeContext)_localctx).s34 = match(T__33); + ((EAttributeContext)_localctx).qualifier.add(((EAttributeContext)_localctx).s34); + } + break; + case T__34: + { + setState(477); + ((EAttributeContext)_localctx).s35 = match(T__34); + ((EAttributeContext)_localctx).qualifier.add(((EAttributeContext)_localctx).s35); + } + break; + case T__35: + { + setState(478); + ((EAttributeContext)_localctx).s36 = match(T__35); + ((EAttributeContext)_localctx).qualifier.add(((EAttributeContext)_localctx).s36); + } + break; + case T__36: + { + setState(479); + ((EAttributeContext)_localctx).s37 = match(T__36); + ((EAttributeContext)_localctx).qualifier.add(((EAttributeContext)_localctx).s37); + } + break; + case T__37: + { + setState(480); + ((EAttributeContext)_localctx).s38 = match(T__37); + ((EAttributeContext)_localctx).qualifier.add(((EAttributeContext)_localctx).s38); + } + break; + case T__38: + { + setState(481); + ((EAttributeContext)_localctx).s39 = match(T__38); + ((EAttributeContext)_localctx).qualifier.add(((EAttributeContext)_localctx).s39); + } + break; + case T__39: + { + setState(482); + ((EAttributeContext)_localctx).s40 = match(T__39); + ((EAttributeContext)_localctx).qualifier.add(((EAttributeContext)_localctx).s40); + } + break; + case T__40: + { + setState(483); + ((EAttributeContext)_localctx).s41 = match(T__40); + ((EAttributeContext)_localctx).qualifier.add(((EAttributeContext)_localctx).s41); + } + break; + default: + throw new NoViableAltException(this); + } + setState(487); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__2) { + { + setState(486); + match(T__2); + } + } + + } + } + setState(491); + _errHandler.sync(this); + _la = _input.LA(1); + } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40))) != 0) ); + setState(493); + match(T__3); + } + break; + } + setState(523); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__1: + { + { + setState(496); + match(T__1); + { + setState(502); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,52,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(497); + ((EAttributeContext)_localctx).eAnnotation = ((EAttributeContext)_localctx).eAnnotation = eAnnotation(_localctx.current); + ((EAttributeContext)_localctx).ownedAnnotations.add(((EAttributeContext)_localctx).eAnnotation); + _localctx.element.getEAnnotations().add(((EAttributeContext)_localctx).eAnnotation.element); + } + } + } + setState(504); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,52,_ctx); + } + setState(511); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__83: + { + setState(505); + ((EAttributeContext)_localctx).ownedDerivation = ((EAttributeContext)_localctx).derivation = derivation(_localctx.current); + _localctx.element.getEAnnotations().add(((EAttributeContext)_localctx).derivation.element); + } + break; + case T__82: + { + setState(508); + ((EAttributeContext)_localctx).ownedInitial = ((EAttributeContext)_localctx).initial = initial(_localctx.current); + _localctx.element.getEAnnotations().add(((EAttributeContext)_localctx).initial.element); + } + break; + case T__3: + case T__62: + break; + default: + throw new NoViableAltException(this); + } + setState(518); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__62) { + { + { + setState(513); + ((EAttributeContext)_localctx).eAnnotation = ((EAttributeContext)_localctx).eAnnotation = eAnnotation(_localctx.current); + ((EAttributeContext)_localctx).ownedAnnotations.add(((EAttributeContext)_localctx).eAnnotation); + _localctx.element.getEAnnotations().add(((EAttributeContext)_localctx).eAnnotation.element); + } + } + setState(520); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + setState(521); + match(T__3); + } + } + break; + case T__10: + { + setState(522); + match(T__10); + } + break; + default: + throw new NoViableAltException(this); + } + for(String s: ((EAttributeContext)_localctx).qualifier.stream().map(Token::getText).distinct().collect(Collectors.toList())){ + switch (s) { + case "static": createEAnnotation(_localctx.element, AnnotationSources.STATIC); break; + case "model": createEAnnotation(_localctx.element, AnnotationSources.MODEL); break; + case "ghost": createEAnnotation(_localctx.element, AnnotationSources.GHOST); break; + case "transient": _localctx.element.setTransient(true); break; + case "volatile": _localctx.element.setVolatile(true); break; + case "readonly": _localctx.element.setChangeable(false); break; + case "derived": _localctx.element.setDerived(true); break; + case "ordered": int u = _localctx.element.getUpperBound(); if (u > 1 || u == -1) _localctx.element.setOrdered(true); break; + case "!unique": u = _localctx.element.getUpperBound(); if (u > 1 || u == -1) _localctx.element.setUnique(false); break; + case "unsettable": _localctx.element.setUnsettable(true); break; + case "id": _localctx.element.setID(true); break;}} + + } + _ctx.stop = _input.LT(-1); + + if (_localctx.eAttributeType != null) { + EObject genericElementType = _localctx.eAttributeType.element; + if (genericElementType instanceof EClassifier) { _localctx.element.setEType((EClassifier) genericElementType);} + else if (genericElementType instanceof EGenericType) { _localctx.element.setEGenericType((EGenericType) genericElementType);} + } + + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EReferenceContext extends ParserRuleContext { + public Element owner; + public EReference element; + public Reference current; + public VisibilityKindContext visibility; + public Token s28; + public List qualifier = new ArrayList(); + public Token s12; + public Token s29; + public Token s30; + public Token s31; + public Token s32; + public UnrestrictedNameContext name; + public UnrestrictedNameContext eOpposite; + public EGenericElementTypeContext eReferenceType; + public EMultiplicityContext ownedMultiplicity; + public Token defaultValue; + public Token s44; + public Token s34; + public Token s36; + public Token s37; + public Token s38; + public Token s39; + public Token s45; + public Token s46; + public Token s40; + public Token s41; + public UnrestrictedNameContext unrestrictedName; + public List referredKeys = new ArrayList(); + public EAnnotationContext eAnnotation; + public List ownedAnnotations = new ArrayList(); + public DerivationContext ownedDerivation; + public DerivationContext derivation; + public InitialContext ownedInitial; + public InitialContext initial; + public List unrestrictedName() { + return getRuleContexts(UnrestrictedNameContext.class); + } + public UnrestrictedNameContext unrestrictedName(int i) { + return getRuleContext(UnrestrictedNameContext.class,i); + } + public EGenericElementTypeContext eGenericElementType() { + return getRuleContext(EGenericElementTypeContext.class,0); + } + public VisibilityKindContext visibilityKind() { + return getRuleContext(VisibilityKindContext.class,0); + } + public TerminalNode SINGLE_QUOTED_STRING() { return getToken(AlloyInEcoreParser.SINGLE_QUOTED_STRING, 0); } + public EMultiplicityContext eMultiplicity() { + return getRuleContext(EMultiplicityContext.class,0); + } + public List eAnnotation() { + return getRuleContexts(EAnnotationContext.class); + } + public EAnnotationContext eAnnotation(int i) { + return getRuleContext(EAnnotationContext.class,i); + } + public DerivationContext derivation() { + return getRuleContext(DerivationContext.class,0); + } + public InitialContext initial() { + return getRuleContext(InitialContext.class,0); + } + public EReferenceContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EReferenceContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eReference; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEReference(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEReference(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEReference(this); + else return visitor.visitChildren(this); + } + } + + public final EReferenceContext eReference(Element owner) throws RecognitionException { + EReferenceContext _localctx = new EReferenceContext(_ctx, getState(), owner); + enterRule(_localctx, 48, RULE_eReference); + ((EReferenceContext)_localctx).element = eFactory.createEReference(); ((EReferenceContext)_localctx).current = new Reference(_localctx.element, _localctx); if (owner!=null) owner.addOwnedElement(_localctx.current); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(528); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 85)) & ~0x3f) == 0 && ((1L << (_la - 85)) & ((1L << (T__84 - 85)) | (1L << (T__85 - 85)) | (1L << (T__86 - 85)))) != 0)) { + { + setState(527); + ((EReferenceContext)_localctx).visibility = visibilityKind(); + } + } + + if (_localctx.visibility != null) _localctx.element.getEAnnotations().add(((EReferenceContext)_localctx).visibility.element); + setState(532); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__27) { + { + setState(531); + ((EReferenceContext)_localctx).s28 = match(T__27); + ((EReferenceContext)_localctx).qualifier.add(((EReferenceContext)_localctx).s28); + } + } + + setState(536); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__11: + { + setState(534); + ((EReferenceContext)_localctx).s12 = match(T__11); + ((EReferenceContext)_localctx).qualifier.add(((EReferenceContext)_localctx).s12); + } + break; + case T__28: + { + setState(535); + ((EReferenceContext)_localctx).s29 = match(T__28); + ((EReferenceContext)_localctx).qualifier.add(((EReferenceContext)_localctx).s29); + } + break; + case T__29: + case T__30: + case T__31: + case T__41: + break; + default: + throw new NoViableAltException(this); + } + setState(539); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__29) { + { + setState(538); + ((EReferenceContext)_localctx).s30 = match(T__29); + ((EReferenceContext)_localctx).qualifier.add(((EReferenceContext)_localctx).s30); + } + } + + setState(542); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__30) { + { + setState(541); + ((EReferenceContext)_localctx).s31 = match(T__30); + ((EReferenceContext)_localctx).qualifier.add(((EReferenceContext)_localctx).s31); + } + } + + setState(545); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__31) { + { + setState(544); + ((EReferenceContext)_localctx).s32 = match(T__31); + ((EReferenceContext)_localctx).qualifier.add(((EReferenceContext)_localctx).s32); + } + } + + setState(547); + match(T__41); + setState(548); + ((EReferenceContext)_localctx).name = unrestrictedName(); + _localctx.element.setName((((EReferenceContext)_localctx).name!=null?_input.getText(((EReferenceContext)_localctx).name.start,((EReferenceContext)_localctx).name.stop):null)); + setState(552); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__42) { + { + setState(550); + match(T__42); + setState(551); + ((EReferenceContext)_localctx).eOpposite = unrestrictedName(); + } + } + + + { + setState(555); + match(T__5); + setState(556); + ((EReferenceContext)_localctx).eReferenceType = eGenericElementType(_localctx.current); + setState(558); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__12) { + { + setState(557); + ((EReferenceContext)_localctx).ownedMultiplicity = eMultiplicity(_localctx.current, (ETypedElement) _localctx.element); + } + } + + } + if (_localctx.ownedMultiplicity == null) {_localctx.element.setLowerBound(1);} + setState(563); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__22) { + { + setState(561); + match(T__22); + setState(562); + ((EReferenceContext)_localctx).defaultValue = match(SINGLE_QUOTED_STRING); + } + } + + if(((EReferenceContext)_localctx).defaultValue != null) _localctx.element.setDefaultValueLiteral(((EReferenceContext)_localctx).defaultValue.getText().replace("'", "")); + setState(587); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,68,_ctx) ) { + case 1: + { + setState(566); + match(T__1); + setState(582); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(577); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__43: + { + setState(567); + ((EReferenceContext)_localctx).s44 = match(T__43); + ((EReferenceContext)_localctx).qualifier.add(((EReferenceContext)_localctx).s44); + } + break; + case T__33: + { + setState(568); + ((EReferenceContext)_localctx).s34 = match(T__33); + ((EReferenceContext)_localctx).qualifier.add(((EReferenceContext)_localctx).s34); + } + break; + case T__35: + { + setState(569); + ((EReferenceContext)_localctx).s36 = match(T__35); + ((EReferenceContext)_localctx).qualifier.add(((EReferenceContext)_localctx).s36); + } + break; + case T__36: + { + setState(570); + ((EReferenceContext)_localctx).s37 = match(T__36); + ((EReferenceContext)_localctx).qualifier.add(((EReferenceContext)_localctx).s37); + } + break; + case T__37: + { + setState(571); + ((EReferenceContext)_localctx).s38 = match(T__37); + ((EReferenceContext)_localctx).qualifier.add(((EReferenceContext)_localctx).s38); + } + break; + case T__38: + { + setState(572); + ((EReferenceContext)_localctx).s39 = match(T__38); + ((EReferenceContext)_localctx).qualifier.add(((EReferenceContext)_localctx).s39); + } + break; + case T__44: + { + setState(573); + ((EReferenceContext)_localctx).s45 = match(T__44); + ((EReferenceContext)_localctx).qualifier.add(((EReferenceContext)_localctx).s45); + } + break; + case T__45: + { + setState(574); + ((EReferenceContext)_localctx).s46 = match(T__45); + ((EReferenceContext)_localctx).qualifier.add(((EReferenceContext)_localctx).s46); + } + break; + case T__39: + { + setState(575); + ((EReferenceContext)_localctx).s40 = match(T__39); + ((EReferenceContext)_localctx).qualifier.add(((EReferenceContext)_localctx).s40); + } + break; + case T__40: + { + setState(576); + ((EReferenceContext)_localctx).s41 = match(T__40); + ((EReferenceContext)_localctx).qualifier.add(((EReferenceContext)_localctx).s41); + } + break; + default: + throw new NoViableAltException(this); + } + setState(580); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__2) { + { + setState(579); + match(T__2); + } + } + + } + } + setState(584); + _errHandler.sync(this); + _la = _input.LA(1); + } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__33) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__43) | (1L << T__44) | (1L << T__45))) != 0) ); + setState(586); + match(T__3); + } + break; + } + setState(629); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__1: + { + { + setState(589); + match(T__1); + setState(601); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__46) { + { + setState(590); + match(T__46); + setState(591); + ((EReferenceContext)_localctx).unrestrictedName = unrestrictedName(); + ((EReferenceContext)_localctx).referredKeys.add(((EReferenceContext)_localctx).unrestrictedName); + setState(596); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(592); + match(T__2); + setState(593); + ((EReferenceContext)_localctx).unrestrictedName = unrestrictedName(); + ((EReferenceContext)_localctx).referredKeys.add(((EReferenceContext)_localctx).unrestrictedName); + } + } + setState(598); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(599); + match(T__10); + } + } + + { + setState(608); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,71,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(603); + ((EReferenceContext)_localctx).eAnnotation = ((EReferenceContext)_localctx).eAnnotation = eAnnotation(_localctx.current); + ((EReferenceContext)_localctx).ownedAnnotations.add(((EReferenceContext)_localctx).eAnnotation); + _localctx.element.getEAnnotations().add(((EReferenceContext)_localctx).eAnnotation.element); + } + } + } + setState(610); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,71,_ctx); + } + setState(617); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__83: + { + setState(611); + ((EReferenceContext)_localctx).ownedDerivation = ((EReferenceContext)_localctx).derivation = derivation(_localctx.current); + _localctx.element.getEAnnotations().add(((EReferenceContext)_localctx).derivation.element); + } + break; + case T__82: + { + setState(614); + ((EReferenceContext)_localctx).ownedInitial = ((EReferenceContext)_localctx).initial = initial(_localctx.current); + _localctx.element.getEAnnotations().add(((EReferenceContext)_localctx).initial.element); + } + break; + case T__3: + case T__62: + break; + default: + throw new NoViableAltException(this); + } + setState(624); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__62) { + { + { + setState(619); + ((EReferenceContext)_localctx).eAnnotation = ((EReferenceContext)_localctx).eAnnotation = eAnnotation(_localctx.current); + ((EReferenceContext)_localctx).ownedAnnotations.add(((EReferenceContext)_localctx).eAnnotation); + _localctx.element.getEAnnotations().add(((EReferenceContext)_localctx).eAnnotation.element); + } + } + setState(626); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + setState(627); + match(T__3); + } + } + break; + case T__10: + { + setState(628); + match(T__10); + } + break; + default: + throw new NoViableAltException(this); + } + for(String s: ((EReferenceContext)_localctx).qualifier.stream().map(Token::getText).distinct().collect(Collectors.toList())){ + switch (s) { + case "static": createEAnnotation(_localctx.element, AnnotationSources.STATIC); break; + case "model": createEAnnotation(_localctx.element, AnnotationSources.MODEL); break; + case "ghost": createEAnnotation(_localctx.element, AnnotationSources.GHOST); break; + case "transient": _localctx.element.setTransient(true); break; + case "volatile": _localctx.element.setVolatile(true); break; + case "readonly": _localctx.element.setChangeable(false); break; + case "unsettable":_localctx.element.setUnsettable(true); break; + case "derived": _localctx.element.setDerived(true); break; + case "ordered": int u = _localctx.element.getUpperBound(); if (u > 1 || u == -1) _localctx.element.setOrdered(true); break; + case "!unique": u = _localctx.element.getUpperBound(); if (u > 1 || u == -1) _localctx.element.setUnique(false); break; + case "composes": _localctx.element.setContainment(true); break; + case "!resolve": _localctx.element.setResolveProxies(false); break; + default: break;}} + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EOperationContext extends ParserRuleContext { + public Element owner; + public EOperation element; + public Operation current; + public VisibilityKindContext visibility; + public Token s28; + public List qualifier = new ArrayList(); + public TemplateSignatureContext ownedSignature; + public TemplateSignatureContext templateSignature; + public UnrestrictedNameContext name; + public EParameterContext eParameter; + public List eParameters = new ArrayList(); + public EGenericElementTypeContext eReturnType; + public EGenericElementTypeContext eGenericElementType; + public EMultiplicityContext ownedMultiplicity; + public EGenericExceptionContext eGenericException; + public List ownedException = new ArrayList(); + public Token s36; + public Token s37; + public Token s38; + public Token s39; + public EAnnotationContext eAnnotation; + public List ownedAnnotations = new ArrayList(); + public PreconditionContext precondition; + public List ownedPreconditions = new ArrayList(); + public BodyContext body; + public List ownedBodyExpression = new ArrayList(); + public PostconditionContext postcondition; + public List ownedPostconditions = new ArrayList(); + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public VisibilityKindContext visibilityKind() { + return getRuleContext(VisibilityKindContext.class,0); + } + public TemplateSignatureContext templateSignature() { + return getRuleContext(TemplateSignatureContext.class,0); + } + public EGenericElementTypeContext eGenericElementType() { + return getRuleContext(EGenericElementTypeContext.class,0); + } + public List eGenericException() { + return getRuleContexts(EGenericExceptionContext.class); + } + public EGenericExceptionContext eGenericException(int i) { + return getRuleContext(EGenericExceptionContext.class,i); + } + public List eParameter() { + return getRuleContexts(EParameterContext.class); + } + public EParameterContext eParameter(int i) { + return getRuleContext(EParameterContext.class,i); + } + public EMultiplicityContext eMultiplicity() { + return getRuleContext(EMultiplicityContext.class,0); + } + public List eAnnotation() { + return getRuleContexts(EAnnotationContext.class); + } + public EAnnotationContext eAnnotation(int i) { + return getRuleContext(EAnnotationContext.class,i); + } + public List precondition() { + return getRuleContexts(PreconditionContext.class); + } + public PreconditionContext precondition(int i) { + return getRuleContext(PreconditionContext.class,i); + } + public List body() { + return getRuleContexts(BodyContext.class); + } + public BodyContext body(int i) { + return getRuleContext(BodyContext.class,i); + } + public List postcondition() { + return getRuleContexts(PostconditionContext.class); + } + public PostconditionContext postcondition(int i) { + return getRuleContext(PostconditionContext.class,i); + } + public EOperationContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EOperationContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eOperation; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEOperation(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEOperation(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEOperation(this); + else return visitor.visitChildren(this); + } + } + + public final EOperationContext eOperation(Element owner) throws RecognitionException { + EOperationContext _localctx = new EOperationContext(_ctx, getState(), owner); + enterRule(_localctx, 50, RULE_eOperation); + ((EOperationContext)_localctx).element = eFactory.createEOperation(); ((EOperationContext)_localctx).current = new Operation(_localctx.element, _localctx); if (owner!=null) owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(634); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 85)) & ~0x3f) == 0 && ((1L << (_la - 85)) & ((1L << (T__84 - 85)) | (1L << (T__85 - 85)) | (1L << (T__86 - 85)))) != 0)) { + { + setState(633); + ((EOperationContext)_localctx).visibility = visibilityKind(); + } + } + + if (_localctx.visibility != null) _localctx.element.getEAnnotations().add(((EOperationContext)_localctx).visibility.element); + setState(638); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__27) { + { + setState(637); + ((EOperationContext)_localctx).s28 = match(T__27); + ((EOperationContext)_localctx).qualifier.add(((EOperationContext)_localctx).s28); + } + } + + setState(640); + match(T__47); + setState(642); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__64) { + { + setState(641); + ((EOperationContext)_localctx).ownedSignature = ((EOperationContext)_localctx).templateSignature = templateSignature(_localctx.current); + } + } + + if(_localctx.templateSignature != null) _localctx.element.getETypeParameters().addAll(((EOperationContext)_localctx).templateSignature.typeParameters); + setState(645); + ((EOperationContext)_localctx).name = unrestrictedName(); + _localctx.element.setName((((EOperationContext)_localctx).name!=null?_input.getText(((EOperationContext)_localctx).name.start,((EOperationContext)_localctx).name.stop):null)); + { + setState(647); + match(T__48); + setState(656); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 12)) & ~0x3f) == 0 && ((1L << (_la - 12)) & ((1L << (T__11 - 12)) | (1L << (T__20 - 12)) | (1L << (T__21 - 12)) | (1L << (T__23 - 12)) | (1L << (T__24 - 12)) | (1L << (T__25 - 12)) | (1L << (T__26 - 12)) | (1L << (T__27 - 12)) | (1L << (T__29 - 12)) | (1L << (T__30 - 12)) | (1L << (T__31 - 12)) | (1L << (T__32 - 12)) | (1L << (T__33 - 12)) | (1L << (T__34 - 12)) | (1L << (T__35 - 12)) | (1L << (T__37 - 12)) | (1L << (T__39 - 12)) | (1L << (T__41 - 12)) | (1L << (T__43 - 12)) | (1L << (T__44 - 12)) | (1L << (T__46 - 12)) | (1L << (T__47 - 12)) | (1L << (T__50 - 12)) | (1L << (T__56 - 12)) | (1L << (T__57 - 12)) | (1L << (T__58 - 12)) | (1L << (T__60 - 12)) | (1L << (T__61 - 12)) | (1L << (T__62 - 12)) | (1L << (T__63 - 12)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + setState(648); + ((EOperationContext)_localctx).eParameter = eParameter(_localctx.current); + ((EOperationContext)_localctx).eParameters.add(((EOperationContext)_localctx).eParameter); + setState(653); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(649); + match(T__2); + setState(650); + ((EOperationContext)_localctx).eParameter = eParameter(_localctx.current); + ((EOperationContext)_localctx).eParameters.add(((EOperationContext)_localctx).eParameter); + } + } + setState(655); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + + setState(658); + match(T__49); + } + for (EParameterContext ctx: ((EOperationContext)_localctx).eParameters){_localctx.element.getEParameters().add(ctx.element);} + setState(666); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__5) { + { + setState(661); + match(T__5); + setState(662); + ((EOperationContext)_localctx).eReturnType = ((EOperationContext)_localctx).eGenericElementType = eGenericElementType(_localctx.current); + setState(664); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__12) { + { + setState(663); + ((EOperationContext)_localctx).ownedMultiplicity = eMultiplicity(_localctx.current, (ETypedElement) _localctx.element); + } + } + + } + } + + if (_localctx.ownedMultiplicity == null) {_localctx.element.setLowerBound(1);} + if (_localctx.eReturnType != null) _localctx.element.setEGenericType(((EOperationContext)_localctx).eGenericElementType.element); + setState(679); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__50) { + { + setState(670); + match(T__50); + setState(671); + ((EOperationContext)_localctx).eGenericException = eGenericException(_localctx.current); + ((EOperationContext)_localctx).ownedException.add(((EOperationContext)_localctx).eGenericException); + setState(676); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(672); + match(T__2); + setState(673); + ((EOperationContext)_localctx).eGenericException = eGenericException(_localctx.current); + ((EOperationContext)_localctx).ownedException.add(((EOperationContext)_localctx).eGenericException); + } + } + setState(678); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + + for(EGenericExceptionContext e: ((EOperationContext)_localctx).ownedException) _localctx.element.getEGenericExceptions().add(e.element); + setState(697); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,87,_ctx) ) { + case 1: + { + setState(682); + match(T__1); + setState(692); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(687); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__35: + { + setState(683); + ((EOperationContext)_localctx).s36 = match(T__35); + ((EOperationContext)_localctx).qualifier.add(((EOperationContext)_localctx).s36); + } + break; + case T__36: + { + setState(684); + ((EOperationContext)_localctx).s37 = match(T__36); + ((EOperationContext)_localctx).qualifier.add(((EOperationContext)_localctx).s37); + } + break; + case T__37: + { + setState(685); + ((EOperationContext)_localctx).s38 = match(T__37); + ((EOperationContext)_localctx).qualifier.add(((EOperationContext)_localctx).s38); + } + break; + case T__38: + { + setState(686); + ((EOperationContext)_localctx).s39 = match(T__38); + ((EOperationContext)_localctx).qualifier.add(((EOperationContext)_localctx).s39); + } + break; + default: + throw new NoViableAltException(this); + } + setState(690); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__2) { + { + setState(689); + match(T__2); + } + } + + } + } + setState(694); + _errHandler.sync(this); + _la = _input.LA(1); + } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38))) != 0) ); + setState(696); + match(T__3); + } + break; + } + setState(719); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__1: + { + { + setState(699); + match(T__1); + setState(714); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 63)) & ~0x3f) == 0 && ((1L << (_la - 63)) & ((1L << (T__62 - 63)) | (1L << (T__75 - 63)) | (1L << (T__78 - 63)) | (1L << (T__79 - 63)) | (1L << (T__80 - 63)) | (1L << (T__81 - 63)))) != 0)) { + { + setState(712); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__62: + { + setState(700); + ((EOperationContext)_localctx).eAnnotation = ((EOperationContext)_localctx).eAnnotation = eAnnotation(_localctx.current); + ((EOperationContext)_localctx).ownedAnnotations.add(((EOperationContext)_localctx).eAnnotation); + _localctx.element.getEAnnotations().add(((EOperationContext)_localctx).eAnnotation.element); + } + break; + case T__78: + case T__79: + { + setState(703); + ((EOperationContext)_localctx).precondition = ((EOperationContext)_localctx).precondition = precondition(_localctx.current); + ((EOperationContext)_localctx).ownedPreconditions.add(((EOperationContext)_localctx).precondition); + _localctx.element.getEAnnotations().add(((EOperationContext)_localctx).precondition.element); + } + break; + case T__75: + { + setState(706); + ((EOperationContext)_localctx).body = ((EOperationContext)_localctx).body = body(_localctx.current); + ((EOperationContext)_localctx).ownedBodyExpression.add(((EOperationContext)_localctx).body); + _localctx.element.getEAnnotations().add(((EOperationContext)_localctx).body.element); + } + break; + case T__80: + case T__81: + { + setState(709); + ((EOperationContext)_localctx).postcondition = ((EOperationContext)_localctx).postcondition = postcondition(_localctx.current); + ((EOperationContext)_localctx).ownedPostconditions.add(((EOperationContext)_localctx).postcondition); + _localctx.element.getEAnnotations().add(((EOperationContext)_localctx).postcondition.element); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(716); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(717); + match(T__3); + } + } + break; + case T__10: + { + setState(718); + match(T__10); + } + break; + default: + throw new NoViableAltException(this); + } + for(String s: ((EOperationContext)_localctx).qualifier.stream().map(Token::getText).distinct().collect(Collectors.toList())){ + switch (s) { + case "static": createEAnnotation(_localctx.element, AnnotationSources.STATIC); break; + case "ordered": int u = _localctx.element.getUpperBound(); if (u > 1 || u == -1) _localctx.element.setOrdered(true); break; + case "!unique": u = _localctx.element.getUpperBound(); if (u > 1 || u == -1) _localctx.element.setUnique(false); break;}} + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EGenericExceptionContext extends ParserRuleContext { + public Element owner; + public EGenericType element; + public GenericException current; + public EGenericTypeContext eGenericType; + public EGenericTypeContext eGenericType() { + return getRuleContext(EGenericTypeContext.class,0); + } + public EGenericExceptionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EGenericExceptionContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eGenericException; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEGenericException(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEGenericException(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEGenericException(this); + else return visitor.visitChildren(this); + } + } + + public final EGenericExceptionContext eGenericException(Element owner) throws RecognitionException { + EGenericExceptionContext _localctx = new EGenericExceptionContext(_ctx, getState(), owner); + enterRule(_localctx, 52, RULE_eGenericException); + ((EGenericExceptionContext)_localctx).current = new GenericException(_localctx); if (owner!=null) _localctx.owner.addOwnedElement(_localctx.current); + try { + enterOuterAlt(_localctx, 1); + { + setState(723); + ((EGenericExceptionContext)_localctx).eGenericType = eGenericType(_localctx.current); + ((EGenericExceptionContext)_localctx).element = ((EGenericExceptionContext)_localctx).eGenericType.element; _localctx.current.setEObject(_localctx.element); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EGenericSuperTypeContext extends ParserRuleContext { + public Element owner; + public EGenericType element; + public GenericSuperType current; + public EGenericTypeContext eGenericType; + public EGenericTypeContext eGenericType() { + return getRuleContext(EGenericTypeContext.class,0); + } + public EGenericSuperTypeContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EGenericSuperTypeContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eGenericSuperType; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEGenericSuperType(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEGenericSuperType(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEGenericSuperType(this); + else return visitor.visitChildren(this); + } + } + + public final EGenericSuperTypeContext eGenericSuperType(Element owner) throws RecognitionException { + EGenericSuperTypeContext _localctx = new EGenericSuperTypeContext(_ctx, getState(), owner); + enterRule(_localctx, 54, RULE_eGenericSuperType); + ((EGenericSuperTypeContext)_localctx).current = new GenericSuperType(_localctx); if (owner!=null) _localctx.owner.addOwnedElement(_localctx.current); + try { + enterOuterAlt(_localctx, 1); + { + setState(726); + ((EGenericSuperTypeContext)_localctx).eGenericType = eGenericType(_localctx.current); + ((EGenericSuperTypeContext)_localctx).element = ((EGenericSuperTypeContext)_localctx).eGenericType.element; _localctx.current.setEObject(_localctx.element); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EParameterContext extends ParserRuleContext { + public Element owner; + public EParameter element; + public Parameter current; + public UnrestrictedNameContext name; + public EGenericElementTypeContext eParameterType; + public EMultiplicityContext ownedMultiplicity; + public Token s36; + public List qualifier = new ArrayList(); + public Token s37; + public Token s38; + public Token s39; + public EAnnotationContext eAnnotation; + public List ownedAnnotations = new ArrayList(); + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public EGenericElementTypeContext eGenericElementType() { + return getRuleContext(EGenericElementTypeContext.class,0); + } + public EMultiplicityContext eMultiplicity() { + return getRuleContext(EMultiplicityContext.class,0); + } + public List eAnnotation() { + return getRuleContexts(EAnnotationContext.class); + } + public EAnnotationContext eAnnotation(int i) { + return getRuleContext(EAnnotationContext.class,i); + } + public EParameterContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EParameterContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eParameter; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEParameter(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEParameter(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEParameter(this); + else return visitor.visitChildren(this); + } + } + + public final EParameterContext eParameter(Element owner) throws RecognitionException { + EParameterContext _localctx = new EParameterContext(_ctx, getState(), owner); + enterRule(_localctx, 56, RULE_eParameter); + ((EParameterContext)_localctx).element = eFactory.createEParameter(); ((EParameterContext)_localctx).current = new Parameter(_localctx.element, _localctx); if (owner!=null) owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(729); + ((EParameterContext)_localctx).name = unrestrictedName(); + _localctx.element.setName((((EParameterContext)_localctx).name!=null?_input.getText(((EParameterContext)_localctx).name.start,((EParameterContext)_localctx).name.stop):null)); + setState(731); + match(T__5); + setState(732); + ((EParameterContext)_localctx).eParameterType = eGenericElementType(_localctx.current); + setState(734); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__12) { + { + setState(733); + ((EParameterContext)_localctx).ownedMultiplicity = eMultiplicity(_localctx.current, (ETypedElement) _localctx.element); + } + } + + if (_localctx.ownedMultiplicity == null) {_localctx.element.setLowerBound(1);} + setState(752); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,95,_ctx) ) { + case 1: + { + setState(737); + match(T__1); + setState(747); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(742); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__35: + { + setState(738); + ((EParameterContext)_localctx).s36 = match(T__35); + ((EParameterContext)_localctx).qualifier.add(((EParameterContext)_localctx).s36); + } + break; + case T__36: + { + setState(739); + ((EParameterContext)_localctx).s37 = match(T__36); + ((EParameterContext)_localctx).qualifier.add(((EParameterContext)_localctx).s37); + } + break; + case T__37: + { + setState(740); + ((EParameterContext)_localctx).s38 = match(T__37); + ((EParameterContext)_localctx).qualifier.add(((EParameterContext)_localctx).s38); + } + break; + case T__38: + { + setState(741); + ((EParameterContext)_localctx).s39 = match(T__38); + ((EParameterContext)_localctx).qualifier.add(((EParameterContext)_localctx).s39); + } + break; + default: + throw new NoViableAltException(this); + } + setState(745); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__2) { + { + setState(744); + match(T__2); + } + } + + } + } + setState(749); + _errHandler.sync(this); + _la = _input.LA(1); + } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38))) != 0) ); + setState(751); + match(T__3); + } + break; + } + setState(763); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__1) { + { + setState(754); + match(T__1); + setState(758); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__62) { + { + { + setState(755); + ((EParameterContext)_localctx).eAnnotation = ((EParameterContext)_localctx).eAnnotation = eAnnotation(_localctx.current); + ((EParameterContext)_localctx).ownedAnnotations.add(((EParameterContext)_localctx).eAnnotation); + } + } + setState(760); + _errHandler.sync(this); + _la = _input.LA(1); + } + _localctx.element.getEAnnotations().add(((EParameterContext)_localctx).eAnnotation.element); + setState(762); + match(T__3); + } + } + + for(String s: ((EParameterContext)_localctx).qualifier.stream().map(Token::getText).distinct().collect(Collectors.toList())){ + switch (s) { + case "ordered": int u = _localctx.element.getUpperBound(); if (u > 1 || u == -1) _localctx.element.setOrdered(true);break; + case "!unique": u = _localctx.element.getUpperBound(); if (u > 1 || u == -1) _localctx.element.setUnique(false);break;}} + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EMultiplicityContext extends ParserRuleContext { + public Element owner; + public ETypedElement element; + public int l = 1; + public int u = 1; + public LowerContext lowerBound; + public UpperContext upperBound; + public Token stringBound; + public Token nullable; + public LowerContext lower() { + return getRuleContext(LowerContext.class,0); + } + public UpperContext upper() { + return getRuleContext(UpperContext.class,0); + } + public EMultiplicityContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EMultiplicityContext(ParserRuleContext parent, int invokingState, Element owner, ETypedElement element) { + super(parent, invokingState); + this.owner = owner; + this.element = element; + } + @Override public int getRuleIndex() { return RULE_eMultiplicity; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEMultiplicity(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEMultiplicity(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEMultiplicity(this); + else return visitor.visitChildren(this); + } + } + + public final EMultiplicityContext eMultiplicity(Element owner,ETypedElement element) throws RecognitionException { + EMultiplicityContext _localctx = new EMultiplicityContext(_ctx, getState(), owner, element); + enterRule(_localctx, 58, RULE_eMultiplicity); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(767); + match(T__12); + setState(774); + _errHandler.sync(this); + switch (_input.LA(1)) { + case INT: + { + setState(768); + ((EMultiplicityContext)_localctx).lowerBound = lower(); + setState(771); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__51) { + { + setState(769); + match(T__51); + setState(770); + ((EMultiplicityContext)_localctx).upperBound = upper(); + } + } + + } + break; + case T__16: + case T__52: + case T__53: + { + setState(773); + ((EMultiplicityContext)_localctx).stringBound = _input.LT(1); + _la = _input.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__16) | (1L << T__52) | (1L << T__53))) != 0)) ) { + ((EMultiplicityContext)_localctx).stringBound = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + break; + default: + throw new NoViableAltException(this); + } + setState(778); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__54: + { + setState(776); + ((EMultiplicityContext)_localctx).nullable = match(T__54); + } + break; + case T__55: + { + setState(777); + match(T__55); + } + break; + case T__13: + break; + default: + throw new NoViableAltException(this); + } + setState(780); + match(T__13); + + if (_localctx.stringBound != null) { + switch (_localctx.stringBound.getText()) { + case "*": ((EMultiplicityContext)_localctx).l = 0; ((EMultiplicityContext)_localctx).u = -1; break; + case "+": ((EMultiplicityContext)_localctx).l = 1; ((EMultiplicityContext)_localctx).u = -1; break; + case "?": ((EMultiplicityContext)_localctx).l = 0; ((EMultiplicityContext)_localctx).u = 1; break; + default: break; + } + } else { + try { ((EMultiplicityContext)_localctx).l = Integer.valueOf((((EMultiplicityContext)_localctx).lowerBound!=null?_input.getText(((EMultiplicityContext)_localctx).lowerBound.start,((EMultiplicityContext)_localctx).lowerBound.stop):null)); } catch (NumberFormatException ex) {System.out.println(Arrays.toString(ex.getStackTrace()));} + if (_localctx.upperBound != null) { + if (_localctx.upperBound.getText().equals("*")) ((EMultiplicityContext)_localctx).u = -1; + else try {((EMultiplicityContext)_localctx).u = Integer.valueOf((((EMultiplicityContext)_localctx).upperBound!=null?_input.getText(((EMultiplicityContext)_localctx).upperBound.start,((EMultiplicityContext)_localctx).upperBound.stop):null));} catch (NumberFormatException ex){System.out.println(Arrays.toString(ex.getStackTrace()));} + } else { ((EMultiplicityContext)_localctx).u = _localctx.l;} + } + if ((_localctx.u > 1 || _localctx.u == -1) && _localctx.nullable != null) createEAnnotation(_localctx.element, AnnotationSources.NULLABLE); + + } + _ctx.stop = _input.LT(-1); + _localctx.element.setLowerBound(_localctx.l); _localctx.element.setUpperBound(_localctx.u); if (owner!=null) _localctx.owner.addOwnedElement(new Multiplicity(_localctx)); + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EDataTypeContext extends ParserRuleContext { + public Element owner; + public EDataType element; + public DataType current; + public VisibilityKindContext visibility; + public Token s57; + public List qualifier = new ArrayList(); + public UnrestrictedNameContext name; + public TemplateSignatureContext ownedSignature; + public TemplateSignatureContext templateSignature; + public Token instanceClassName; + public Token s59; + public Token s60; + public EAnnotationContext eAnnotation; + public List ownedAnnotations = new ArrayList(); + public InvariantContext invariant; + public List ownedConstraints = new ArrayList(); + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public VisibilityKindContext visibilityKind() { + return getRuleContext(VisibilityKindContext.class,0); + } + public TemplateSignatureContext templateSignature() { + return getRuleContext(TemplateSignatureContext.class,0); + } + public TerminalNode SINGLE_QUOTED_STRING() { return getToken(AlloyInEcoreParser.SINGLE_QUOTED_STRING, 0); } + public List eAnnotation() { + return getRuleContexts(EAnnotationContext.class); + } + public EAnnotationContext eAnnotation(int i) { + return getRuleContext(EAnnotationContext.class,i); + } + public List invariant() { + return getRuleContexts(InvariantContext.class); + } + public InvariantContext invariant(int i) { + return getRuleContext(InvariantContext.class,i); + } + public EDataTypeContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EDataTypeContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eDataType; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEDataType(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEDataType(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEDataType(this); + else return visitor.visitChildren(this); + } + } + + public final EDataTypeContext eDataType(Element owner) throws RecognitionException { + EDataTypeContext _localctx = new EDataTypeContext(_ctx, getState(), owner); + enterRule(_localctx, 60, RULE_eDataType); + ((EDataTypeContext)_localctx).element = eFactory.createEDataType(); ((EDataTypeContext)_localctx).current = new DataType(_localctx.element, _localctx); if (owner!=null) owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(784); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 85)) & ~0x3f) == 0 && ((1L << (_la - 85)) & ((1L << (T__84 - 85)) | (1L << (T__85 - 85)) | (1L << (T__86 - 85)))) != 0)) { + { + setState(783); + ((EDataTypeContext)_localctx).visibility = visibilityKind(); + } + } + + if (_localctx.visibility != null) _localctx.element.getEAnnotations().add(((EDataTypeContext)_localctx).visibility.element); + setState(788); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__56) { + { + setState(787); + ((EDataTypeContext)_localctx).s57 = match(T__56); + ((EDataTypeContext)_localctx).qualifier.add(((EDataTypeContext)_localctx).s57); + } + } + + setState(790); + match(T__57); + setState(791); + ((EDataTypeContext)_localctx).name = unrestrictedName(); + _localctx.element.setName((((EDataTypeContext)_localctx).name!=null?_input.getText(((EDataTypeContext)_localctx).name.start,((EDataTypeContext)_localctx).name.stop):null)); + setState(794); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__64) { + { + setState(793); + ((EDataTypeContext)_localctx).ownedSignature = ((EDataTypeContext)_localctx).templateSignature = templateSignature(_localctx.current); + } + } + + if(_localctx.templateSignature != null) _localctx.element.getETypeParameters().addAll(((EDataTypeContext)_localctx).templateSignature.typeParameters); + setState(799); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__5) { + { + setState(797); + match(T__5); + setState(798); + ((EDataTypeContext)_localctx).instanceClassName = match(SINGLE_QUOTED_STRING); + } + } + + if(((EDataTypeContext)_localctx).instanceClassName != null) _localctx.element.setInstanceClassName(((EDataTypeContext)_localctx).instanceClassName.getText().replace("'", "")); + setState(808); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,106,_ctx) ) { + case 1: + { + setState(802); + match(T__1); + setState(805); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__58: + { + setState(803); + ((EDataTypeContext)_localctx).s59 = match(T__58); + ((EDataTypeContext)_localctx).qualifier.add(((EDataTypeContext)_localctx).s59); + } + break; + case T__59: + { + setState(804); + ((EDataTypeContext)_localctx).s60 = match(T__59); + ((EDataTypeContext)_localctx).qualifier.add(((EDataTypeContext)_localctx).s60); + } + break; + case T__3: + break; + default: + throw new NoViableAltException(this); + } + setState(807); + match(T__3); + } + break; + } + setState(824); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__1: + { + { + setState(810); + match(T__1); + setState(819); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 63)) & ~0x3f) == 0 && ((1L << (_la - 63)) & ((1L << (T__62 - 63)) | (1L << (T__76 - 63)) | (1L << (T__77 - 63)))) != 0)) { + { + setState(817); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__62: + { + setState(811); + ((EDataTypeContext)_localctx).eAnnotation = ((EDataTypeContext)_localctx).eAnnotation = eAnnotation(_localctx.current); + ((EDataTypeContext)_localctx).ownedAnnotations.add(((EDataTypeContext)_localctx).eAnnotation); + _localctx.element.getEAnnotations().add(((EDataTypeContext)_localctx).eAnnotation.element); + } + break; + case T__76: + case T__77: + { + setState(814); + ((EDataTypeContext)_localctx).invariant = ((EDataTypeContext)_localctx).invariant = invariant(_localctx.current); + ((EDataTypeContext)_localctx).ownedConstraints.add(((EDataTypeContext)_localctx).invariant); + _localctx.element.getEAnnotations().add(((EDataTypeContext)_localctx).invariant.element); + } + break; + default: + throw new NoViableAltException(this); + } + } + setState(821); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(822); + match(T__3); + } + } + break; + case T__10: + { + setState(823); + match(T__10); + } + break; + default: + throw new NoViableAltException(this); + } + for(String s: ((EDataTypeContext)_localctx).qualifier.stream().map(Token::getText).distinct().collect(Collectors.toList())){ + switch (s) { + case "primitive": createEAnnotation(_localctx.element, AnnotationSources.DATATYPE_PRIMITIVE);break; + case "!serializable": _localctx.element.setSerializable(false); break; }} + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EEnumContext extends ParserRuleContext { + public Element owner; + public EEnum element; + public Enum current; + public VisibilityKindContext visibility; + public UnrestrictedNameContext name; + public TemplateSignatureContext ownedSignature; + public TemplateSignatureContext templateSignature; + public Token instanceClassName; + public Token s59; + public List qualifier = new ArrayList(); + public Token s60; + public EAnnotationContext eAnnotation; + public List ownedAnnotations = new ArrayList(); + public EEnumLiteralContext eEnumLiteral; + public List ownedLiteral = new ArrayList(); + public InvariantContext invariant; + public List ownedConstraint = new ArrayList(); + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public VisibilityKindContext visibilityKind() { + return getRuleContext(VisibilityKindContext.class,0); + } + public TemplateSignatureContext templateSignature() { + return getRuleContext(TemplateSignatureContext.class,0); + } + public TerminalNode SINGLE_QUOTED_STRING() { return getToken(AlloyInEcoreParser.SINGLE_QUOTED_STRING, 0); } + public List eAnnotation() { + return getRuleContexts(EAnnotationContext.class); + } + public EAnnotationContext eAnnotation(int i) { + return getRuleContext(EAnnotationContext.class,i); + } + public List eEnumLiteral() { + return getRuleContexts(EEnumLiteralContext.class); + } + public EEnumLiteralContext eEnumLiteral(int i) { + return getRuleContext(EEnumLiteralContext.class,i); + } + public List invariant() { + return getRuleContexts(InvariantContext.class); + } + public InvariantContext invariant(int i) { + return getRuleContext(InvariantContext.class,i); + } + public EEnumContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EEnumContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eEnum; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEEnum(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEEnum(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEEnum(this); + else return visitor.visitChildren(this); + } + } + + public final EEnumContext eEnum(Element owner) throws RecognitionException { + EEnumContext _localctx = new EEnumContext(_ctx, getState(), owner); + enterRule(_localctx, 62, RULE_eEnum); + ((EEnumContext)_localctx).element = eFactory.createEEnum(); ((EEnumContext)_localctx).current = new Enum(_localctx.element, _localctx); if (owner!=null) owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(829); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 85)) & ~0x3f) == 0 && ((1L << (_la - 85)) & ((1L << (T__84 - 85)) | (1L << (T__85 - 85)) | (1L << (T__86 - 85)))) != 0)) { + { + setState(828); + ((EEnumContext)_localctx).visibility = visibilityKind(); + } + } + + if (_localctx.visibility != null) _localctx.element.getEAnnotations().add(((EEnumContext)_localctx).visibility.element); + setState(832); + match(T__60); + setState(833); + ((EEnumContext)_localctx).name = unrestrictedName(); + _localctx.element.setName((((EEnumContext)_localctx).name!=null?_input.getText(((EEnumContext)_localctx).name.start,((EEnumContext)_localctx).name.stop):null)); + setState(836); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__64) { + { + setState(835); + ((EEnumContext)_localctx).ownedSignature = ((EEnumContext)_localctx).templateSignature = templateSignature(_localctx.current); + } + } + + if(_localctx.templateSignature != null) _localctx.element.getETypeParameters().addAll(((EEnumContext)_localctx).templateSignature.typeParameters); + setState(841); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__5) { + { + setState(839); + match(T__5); + setState(840); + ((EEnumContext)_localctx).instanceClassName = match(SINGLE_QUOTED_STRING); + } + } + + if(((EEnumContext)_localctx).instanceClassName != null) _localctx.element.setInstanceClassName(((EEnumContext)_localctx).instanceClassName.getText().replace("'", "")); + setState(850); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,114,_ctx) ) { + case 1: + { + setState(844); + match(T__1); + setState(847); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__58: + { + setState(845); + ((EEnumContext)_localctx).s59 = match(T__58); + ((EEnumContext)_localctx).qualifier.add(((EEnumContext)_localctx).s59); + } + break; + case T__59: + { + setState(846); + ((EEnumContext)_localctx).s60 = match(T__59); + ((EEnumContext)_localctx).qualifier.add(((EEnumContext)_localctx).s60); + } + break; + case T__3: + break; + default: + throw new NoViableAltException(this); + } + setState(849); + match(T__3); + } + break; + } + setState(869); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__1: + { + { + setState(852); + match(T__1); + setState(864); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 12)) & ~0x3f) == 0 && ((1L << (_la - 12)) & ((1L << (T__11 - 12)) | (1L << (T__20 - 12)) | (1L << (T__21 - 12)) | (1L << (T__23 - 12)) | (1L << (T__24 - 12)) | (1L << (T__25 - 12)) | (1L << (T__26 - 12)) | (1L << (T__27 - 12)) | (1L << (T__29 - 12)) | (1L << (T__30 - 12)) | (1L << (T__31 - 12)) | (1L << (T__32 - 12)) | (1L << (T__33 - 12)) | (1L << (T__34 - 12)) | (1L << (T__35 - 12)) | (1L << (T__37 - 12)) | (1L << (T__39 - 12)) | (1L << (T__41 - 12)) | (1L << (T__43 - 12)) | (1L << (T__44 - 12)) | (1L << (T__46 - 12)) | (1L << (T__47 - 12)) | (1L << (T__50 - 12)) | (1L << (T__56 - 12)) | (1L << (T__57 - 12)) | (1L << (T__58 - 12)) | (1L << (T__60 - 12)) | (1L << (T__61 - 12)) | (1L << (T__62 - 12)) | (1L << (T__63 - 12)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + setState(862); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,115,_ctx) ) { + case 1: + { + setState(853); + ((EEnumContext)_localctx).eAnnotation = ((EEnumContext)_localctx).eAnnotation = eAnnotation(_localctx.current); + ((EEnumContext)_localctx).ownedAnnotations.add(((EEnumContext)_localctx).eAnnotation); + _localctx.element.getEAnnotations().add(((EEnumContext)_localctx).eAnnotation.element); + } + break; + case 2: + { + setState(856); + ((EEnumContext)_localctx).eEnumLiteral = ((EEnumContext)_localctx).eEnumLiteral = eEnumLiteral(_localctx.current); + ((EEnumContext)_localctx).ownedLiteral.add(((EEnumContext)_localctx).eEnumLiteral); + _localctx.element.getELiterals().add(((EEnumContext)_localctx).eEnumLiteral.element); + } + break; + case 3: + { + setState(859); + ((EEnumContext)_localctx).invariant = ((EEnumContext)_localctx).invariant = invariant(_localctx.current); + ((EEnumContext)_localctx).ownedConstraint.add(((EEnumContext)_localctx).invariant); + _localctx.element.getEAnnotations().add(((EEnumContext)_localctx).invariant.element); + } + break; + } + } + setState(866); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(867); + match(T__3); + } + } + break; + case T__10: + { + setState(868); + match(T__10); + } + break; + default: + throw new NoViableAltException(this); + } + for(String s: ((EEnumContext)_localctx).qualifier.stream().map(Token::getText).distinct().collect(Collectors.toList())){ + switch (s) { + case "!serializable": _localctx.element.setSerializable(false); break;}} + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EEnumLiteralContext extends ParserRuleContext { + public Element owner; + public EEnumLiteral element; + public EnumLiteral current; + public UnrestrictedNameContext name; + public Token value; + public EAnnotationContext eAnnotation; + public List ownedAnnotations = new ArrayList(); + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public TerminalNode INT() { return getToken(AlloyInEcoreParser.INT, 0); } + public List eAnnotation() { + return getRuleContexts(EAnnotationContext.class); + } + public EAnnotationContext eAnnotation(int i) { + return getRuleContext(EAnnotationContext.class,i); + } + public EEnumLiteralContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EEnumLiteralContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eEnumLiteral; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEEnumLiteral(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEEnumLiteral(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEEnumLiteral(this); + else return visitor.visitChildren(this); + } + } + + public final EEnumLiteralContext eEnumLiteral(Element owner) throws RecognitionException { + EEnumLiteralContext _localctx = new EEnumLiteralContext(_ctx, getState(), owner); + enterRule(_localctx, 64, RULE_eEnumLiteral); + ((EEnumLiteralContext)_localctx).element = eFactory.createEEnumLiteral(); ((EEnumLiteralContext)_localctx).current = new EnumLiteral(_localctx.element, _localctx); if (owner!=null) owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(876); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,118,_ctx) ) { + case 1: + { + { + setState(873); + match(T__61); + setState(874); + ((EEnumLiteralContext)_localctx).name = unrestrictedName(); + } + } + break; + case 2: + { + setState(875); + ((EEnumLiteralContext)_localctx).name = unrestrictedName(); + } + break; + } + _localctx.element.setName((((EEnumLiteralContext)_localctx).name!=null?_input.getText(((EEnumLiteralContext)_localctx).name.start,((EEnumLiteralContext)_localctx).name.stop):null)); + setState(881); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__22) { + { + setState(879); + match(T__22); + setState(880); + ((EEnumLiteralContext)_localctx).value = match(INT); + } + } + + + setState(894); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__1: + { + { + setState(884); + match(T__1); + setState(888); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__62) { + { + { + setState(885); + ((EEnumLiteralContext)_localctx).eAnnotation = ((EEnumLiteralContext)_localctx).eAnnotation = eAnnotation(_localctx.current); + ((EEnumLiteralContext)_localctx).ownedAnnotations.add(((EEnumLiteralContext)_localctx).eAnnotation); + } + } + setState(890); + _errHandler.sync(this); + _la = _input.LA(1); + } + _localctx.element.getEAnnotations().add(((EEnumLiteralContext)_localctx).eAnnotation.element); + setState(892); + match(T__3); + } + } + break; + case T__10: + { + setState(893); + match(T__10); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EAnnotationContext extends ParserRuleContext { + public Element owner; + public EAnnotation element; + public Annotation current; + public Token source; + public EDetailContext eDetail; + public List ownedDetails = new ArrayList(); + public EAnnotationContext eAnnotation; + public List ownedAnnotations = new ArrayList(); + public EModelElementContext eModelElement; + public List ownedContents = new ArrayList(); + public EModelElementRefContext eModelElementRef; + public List ownedReferences = new ArrayList(); + public TerminalNode SINGLE_QUOTED_STRING() { return getToken(AlloyInEcoreParser.SINGLE_QUOTED_STRING, 0); } + public List eDetail() { + return getRuleContexts(EDetailContext.class); + } + public EDetailContext eDetail(int i) { + return getRuleContext(EDetailContext.class,i); + } + public List eAnnotation() { + return getRuleContexts(EAnnotationContext.class); + } + public EAnnotationContext eAnnotation(int i) { + return getRuleContext(EAnnotationContext.class,i); + } + public List eModelElement() { + return getRuleContexts(EModelElementContext.class); + } + public EModelElementContext eModelElement(int i) { + return getRuleContext(EModelElementContext.class,i); + } + public List eModelElementRef() { + return getRuleContexts(EModelElementRefContext.class); + } + public EModelElementRefContext eModelElementRef(int i) { + return getRuleContext(EModelElementRefContext.class,i); + } + public EAnnotationContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EAnnotationContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eAnnotation; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEAnnotation(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEAnnotation(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEAnnotation(this); + else return visitor.visitChildren(this); + } + } + + public final EAnnotationContext eAnnotation(Element owner) throws RecognitionException { + EAnnotationContext _localctx = new EAnnotationContext(_ctx, getState(), owner); + enterRule(_localctx, 66, RULE_eAnnotation); + ((EAnnotationContext)_localctx).element = eFactory.createEAnnotation(); ((EAnnotationContext)_localctx).current = new Annotation(_localctx.element, _localctx); if (owner!=null) owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(896); + match(T__62); + setState(898); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==SINGLE_QUOTED_STRING) { + { + setState(897); + ((EAnnotationContext)_localctx).source = match(SINGLE_QUOTED_STRING); + } + } + + _localctx.element.setSource(((EAnnotationContext)_localctx).source != null ? ((EAnnotationContext)_localctx).source.getText().replace("'", "") : null); + setState(912); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__48) { + { + setState(901); + match(T__48); + setState(902); + ((EAnnotationContext)_localctx).eDetail = eDetail(_localctx.current); + ((EAnnotationContext)_localctx).ownedDetails.add(((EAnnotationContext)_localctx).eDetail); + setState(907); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(903); + match(T__2); + setState(904); + ((EAnnotationContext)_localctx).eDetail = eDetail(_localctx.current); + ((EAnnotationContext)_localctx).ownedDetails.add(((EAnnotationContext)_localctx).eDetail); + } + } + setState(909); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(910); + match(T__49); + } + } + + for (EDetailContext ctx: ((EAnnotationContext)_localctx).ownedDetails) _localctx.element.getDetails().put(ctx.k, ctx.v); + setState(932); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__1: + { + { + setState(915); + match(T__1); + setState(925); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + setState(925); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,125,_ctx) ) { + case 1: + { + setState(916); + ((EAnnotationContext)_localctx).eAnnotation = ((EAnnotationContext)_localctx).eAnnotation = eAnnotation(_localctx.current); + ((EAnnotationContext)_localctx).ownedAnnotations.add(((EAnnotationContext)_localctx).eAnnotation); + if(((EAnnotationContext)_localctx).eAnnotation.element != null) _localctx.element.getEAnnotations().add(((EAnnotationContext)_localctx).eAnnotation.element); + } + break; + case 2: + { + setState(919); + ((EAnnotationContext)_localctx).eModelElement = ((EAnnotationContext)_localctx).eModelElement = eModelElement(_localctx.current); + ((EAnnotationContext)_localctx).ownedContents.add(((EAnnotationContext)_localctx).eModelElement); + if(((EAnnotationContext)_localctx).eModelElement.element != null) _localctx.element.getContents().add(((EAnnotationContext)_localctx).eModelElement.element); + } + break; + case 3: + { + setState(922); + ((EAnnotationContext)_localctx).eModelElementRef = ((EAnnotationContext)_localctx).eModelElementRef = eModelElementRef(_localctx.current); + ((EAnnotationContext)_localctx).ownedReferences.add(((EAnnotationContext)_localctx).eModelElementRef); + if(((EAnnotationContext)_localctx).eModelElementRef.element != null) _localctx.element.getReferences().add(((EAnnotationContext)_localctx).eModelElementRef.element); + } + break; + } + } + setState(927); + _errHandler.sync(this); + _la = _input.LA(1); + } while ( ((((_la - 12)) & ~0x3f) == 0 && ((1L << (_la - 12)) & ((1L << (T__11 - 12)) | (1L << (T__20 - 12)) | (1L << (T__21 - 12)) | (1L << (T__23 - 12)) | (1L << (T__24 - 12)) | (1L << (T__25 - 12)) | (1L << (T__26 - 12)) | (1L << (T__27 - 12)) | (1L << (T__28 - 12)) | (1L << (T__29 - 12)) | (1L << (T__30 - 12)) | (1L << (T__31 - 12)) | (1L << (T__32 - 12)) | (1L << (T__33 - 12)) | (1L << (T__34 - 12)) | (1L << (T__35 - 12)) | (1L << (T__37 - 12)) | (1L << (T__39 - 12)) | (1L << (T__41 - 12)) | (1L << (T__43 - 12)) | (1L << (T__44 - 12)) | (1L << (T__46 - 12)) | (1L << (T__47 - 12)) | (1L << (T__50 - 12)) | (1L << (T__56 - 12)) | (1L << (T__57 - 12)) | (1L << (T__58 - 12)) | (1L << (T__60 - 12)) | (1L << (T__61 - 12)) | (1L << (T__62 - 12)) | (1L << (T__63 - 12)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__84 - 76)) | (1L << (T__85 - 76)) | (1L << (T__86 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (IDENTIFIER - 76)))) != 0) ); + setState(929); + match(T__3); + } + } + break; + case T__10: + { + setState(931); + match(T__10); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EDetailContext extends ParserRuleContext { + public Element owner; + public String k; + public String v; + public AnnotationDetail current; + public Token key; + public Token value; + public List SINGLE_QUOTED_STRING() { return getTokens(AlloyInEcoreParser.SINGLE_QUOTED_STRING); } + public TerminalNode SINGLE_QUOTED_STRING(int i) { + return getToken(AlloyInEcoreParser.SINGLE_QUOTED_STRING, i); + } + public TerminalNode ML_SINGLE_QUOTED_STRING() { return getToken(AlloyInEcoreParser.ML_SINGLE_QUOTED_STRING, 0); } + public EDetailContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EDetailContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eDetail; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEDetail(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEDetail(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEDetail(this); + else return visitor.visitChildren(this); + } + } + + public final EDetailContext eDetail(Element owner) throws RecognitionException { + EDetailContext _localctx = new EDetailContext(_ctx, getState(), owner); + enterRule(_localctx, 68, RULE_eDetail); + ((EDetailContext)_localctx).current = new AnnotationDetail(_localctx); if (owner!=null) owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(935); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==SINGLE_QUOTED_STRING) { + { + setState(934); + ((EDetailContext)_localctx).key = match(SINGLE_QUOTED_STRING); + } + } + + setState(937); + match(T__22); + setState(939); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==SINGLE_QUOTED_STRING || _la==ML_SINGLE_QUOTED_STRING) { + { + setState(938); + ((EDetailContext)_localctx).value = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==SINGLE_QUOTED_STRING || _la==ML_SINGLE_QUOTED_STRING) ) { + ((EDetailContext)_localctx).value = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + + ((EDetailContext)_localctx).k = ((EDetailContext)_localctx).key != null ? ((EDetailContext)_localctx).key.getText().replace("'", "") : null; ((EDetailContext)_localctx).v = ((EDetailContext)_localctx).value != null ? ((EDetailContext)_localctx).value.getText().replace("'", "") : null; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EModelElementContext extends ParserRuleContext { + public Element owner; + public EModelElement element; + public EAnnotationContext eAnnotation; + public ENamedElementContext eNamedElement; + public EAnnotationContext eAnnotation() { + return getRuleContext(EAnnotationContext.class,0); + } + public ENamedElementContext eNamedElement() { + return getRuleContext(ENamedElementContext.class,0); + } + public EModelElementContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EModelElementContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eModelElement; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEModelElement(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEModelElement(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEModelElement(this); + else return visitor.visitChildren(this); + } + } + + public final EModelElementContext eModelElement(Element owner) throws RecognitionException { + EModelElementContext _localctx = new EModelElementContext(_ctx, getState(), owner); + enterRule(_localctx, 70, RULE_eModelElement); + try { + setState(949); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,130,_ctx) ) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(943); + ((EModelElementContext)_localctx).eAnnotation = eAnnotation(_localctx.owner); + ((EModelElementContext)_localctx).element = ((EModelElementContext)_localctx).eAnnotation.element; + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(946); + ((EModelElementContext)_localctx).eNamedElement = eNamedElement(_localctx.owner); + ((EModelElementContext)_localctx).element = ((EModelElementContext)_localctx).eNamedElement.element; + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ENamedElementContext extends ParserRuleContext { + public Element owner; + public ENamedElement element; + public ETypedElementContext eTypedElement; + public EClassifierContext eClassifier; + public EPackageContext ePackage; + public EEnumLiteralContext eEnumLiteral; + public ETypedElementContext eTypedElement() { + return getRuleContext(ETypedElementContext.class,0); + } + public EClassifierContext eClassifier() { + return getRuleContext(EClassifierContext.class,0); + } + public EPackageContext ePackage() { + return getRuleContext(EPackageContext.class,0); + } + public EEnumLiteralContext eEnumLiteral() { + return getRuleContext(EEnumLiteralContext.class,0); + } + public ENamedElementContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public ENamedElementContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eNamedElement; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterENamedElement(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitENamedElement(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitENamedElement(this); + else return visitor.visitChildren(this); + } + } + + public final ENamedElementContext eNamedElement(Element owner) throws RecognitionException { + ENamedElementContext _localctx = new ENamedElementContext(_ctx, getState(), owner); + enterRule(_localctx, 72, RULE_eNamedElement); + try { + setState(963); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,131,_ctx) ) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(951); + ((ENamedElementContext)_localctx).eTypedElement = eTypedElement(_localctx.owner); + ((ENamedElementContext)_localctx).element = ((ENamedElementContext)_localctx).eTypedElement.element; + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(954); + ((ENamedElementContext)_localctx).eClassifier = eClassifier(_localctx.owner); + ((ENamedElementContext)_localctx).element = ((ENamedElementContext)_localctx).eClassifier.element; + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(957); + ((ENamedElementContext)_localctx).ePackage = ePackage(_localctx.owner); + ((ENamedElementContext)_localctx).element = ((ENamedElementContext)_localctx).ePackage.element; + } + break; + case 4: + enterOuterAlt(_localctx, 4); + { + setState(960); + ((ENamedElementContext)_localctx).eEnumLiteral = eEnumLiteral(_localctx.owner); + ((ENamedElementContext)_localctx).element = ((ENamedElementContext)_localctx).eEnumLiteral.element; + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ETypedElementContext extends ParserRuleContext { + public Element owner; + public ETypedElement element; + public EOperationContext eOperation; + public EParameterContext eParameter; + public EStructuralFeatureContext eStructuralFeature; + public EOperationContext eOperation() { + return getRuleContext(EOperationContext.class,0); + } + public EParameterContext eParameter() { + return getRuleContext(EParameterContext.class,0); + } + public EStructuralFeatureContext eStructuralFeature() { + return getRuleContext(EStructuralFeatureContext.class,0); + } + public ETypedElementContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public ETypedElementContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eTypedElement; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterETypedElement(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitETypedElement(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitETypedElement(this); + else return visitor.visitChildren(this); + } + } + + public final ETypedElementContext eTypedElement(Element owner) throws RecognitionException { + ETypedElementContext _localctx = new ETypedElementContext(_ctx, getState(), owner); + enterRule(_localctx, 74, RULE_eTypedElement); + try { + setState(974); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,132,_ctx) ) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(965); + ((ETypedElementContext)_localctx).eOperation = eOperation(_localctx.owner); + ((ETypedElementContext)_localctx).element = ((ETypedElementContext)_localctx).eOperation.element; + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(968); + ((ETypedElementContext)_localctx).eParameter = eParameter(_localctx.owner); + ((ETypedElementContext)_localctx).element = ((ETypedElementContext)_localctx).eParameter.element; + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(971); + ((ETypedElementContext)_localctx).eStructuralFeature = eStructuralFeature(_localctx.owner); + ((ETypedElementContext)_localctx).element = ((ETypedElementContext)_localctx).eStructuralFeature.element; + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EModelElementRefContext extends ParserRuleContext { + public Element owner; + public EObject element; + public AnnotationReference current; + public PathNameContext ownedPathName; + public PathNameContext pathName() { + return getRuleContext(PathNameContext.class,0); + } + public EModelElementRefContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EModelElementRefContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eModelElementRef; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEModelElementRef(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEModelElementRef(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEModelElementRef(this); + else return visitor.visitChildren(this); + } + } + + public final EModelElementRefContext eModelElementRef(Element owner) throws RecognitionException { + EModelElementRefContext _localctx = new EModelElementRefContext(_ctx, getState(), owner); + enterRule(_localctx, 76, RULE_eModelElementRef); + ((EModelElementRefContext)_localctx).current = new AnnotationReference(_localctx); if (owner!=null) owner.addOwnedElement(_localctx.current); + try { + enterOuterAlt(_localctx, 1); + { + setState(976); + match(T__63); + setState(977); + ((EModelElementRefContext)_localctx).ownedPathName = pathName(_localctx.current); + if (((EModelElementRefContext)_localctx).ownedPathName.element != null) _localctx.current.setEObject(((EModelElementRefContext)_localctx).element = ((EModelElementRefContext)_localctx).ownedPathName.element); + setState(979); + match(T__10); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class TemplateSignatureContext extends ParserRuleContext { + public Element owner; + public List typeParameters; + public ETypeParameterContext eTypeParameter; + public List ownedTypeParameters = new ArrayList(); + public List eTypeParameter() { + return getRuleContexts(ETypeParameterContext.class); + } + public ETypeParameterContext eTypeParameter(int i) { + return getRuleContext(ETypeParameterContext.class,i); + } + public TemplateSignatureContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public TemplateSignatureContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_templateSignature; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterTemplateSignature(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitTemplateSignature(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitTemplateSignature(this); + else return visitor.visitChildren(this); + } + } + + public final TemplateSignatureContext templateSignature(Element owner) throws RecognitionException { + TemplateSignatureContext _localctx = new TemplateSignatureContext(_ctx, getState(), owner); + enterRule(_localctx, 78, RULE_templateSignature); + ((TemplateSignatureContext)_localctx).typeParameters = new ArrayList<>(); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(981); + match(T__64); + setState(982); + ((TemplateSignatureContext)_localctx).eTypeParameter = eTypeParameter(_localctx.owner); + ((TemplateSignatureContext)_localctx).ownedTypeParameters.add(((TemplateSignatureContext)_localctx).eTypeParameter); + setState(987); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(983); + match(T__2); + setState(984); + ((TemplateSignatureContext)_localctx).eTypeParameter = eTypeParameter(_localctx.owner); + ((TemplateSignatureContext)_localctx).ownedTypeParameters.add(((TemplateSignatureContext)_localctx).eTypeParameter); + } + } + setState(989); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(990); + match(T__65); + } + _ctx.stop = _input.LT(-1); + for(ETypeParameterContext ctx: ((TemplateSignatureContext)_localctx).ownedTypeParameters) _localctx.typeParameters.add(ctx.element); + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ETypeParameterContext extends ParserRuleContext { + public Element owner; + public ETypeParameter element; + public TypeParameter current; + public UnrestrictedNameContext name; + public EGenericTypeContext eGenericType; + public List ownedEBounds = new ArrayList(); + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public List eGenericType() { + return getRuleContexts(EGenericTypeContext.class); + } + public EGenericTypeContext eGenericType(int i) { + return getRuleContext(EGenericTypeContext.class,i); + } + public ETypeParameterContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public ETypeParameterContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eTypeParameter; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterETypeParameter(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitETypeParameter(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitETypeParameter(this); + else return visitor.visitChildren(this); + } + } + + public final ETypeParameterContext eTypeParameter(Element owner) throws RecognitionException { + ETypeParameterContext _localctx = new ETypeParameterContext(_ctx, getState(), owner); + enterRule(_localctx, 80, RULE_eTypeParameter); + ((ETypeParameterContext)_localctx).element = eFactory.createETypeParameter(); ((ETypeParameterContext)_localctx).current = new TypeParameter(_localctx.element, _localctx); if (owner!=null) owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(992); + ((ETypeParameterContext)_localctx).name = unrestrictedName(); + _localctx.element.setName((((ETypeParameterContext)_localctx).name!=null?_input.getText(((ETypeParameterContext)_localctx).name.start,((ETypeParameterContext)_localctx).name.stop):null)); + setState(1003); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__26) { + { + setState(994); + match(T__26); + setState(995); + ((ETypeParameterContext)_localctx).eGenericType = eGenericType(_localctx.current); + ((ETypeParameterContext)_localctx).ownedEBounds.add(((ETypeParameterContext)_localctx).eGenericType); + setState(1000); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__66) { + { + { + setState(996); + match(T__66); + setState(997); + ((ETypeParameterContext)_localctx).eGenericType = eGenericType(_localctx.current); + ((ETypeParameterContext)_localctx).ownedEBounds.add(((ETypeParameterContext)_localctx).eGenericType); + } + } + setState(1002); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + + for(EGenericTypeContext ctx: ((ETypeParameterContext)_localctx).ownedEBounds) _localctx.element.getEBounds().add(ctx.element); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EGenericTypeArgumentContext extends ParserRuleContext { + public Element owner; + public EGenericType element; + public GenericTypeArgument current; + public EGenericTypeContext eGenericType; + public EGenericWildcardContext eGenericWildcard; + public EGenericTypeContext eGenericType() { + return getRuleContext(EGenericTypeContext.class,0); + } + public EGenericWildcardContext eGenericWildcard() { + return getRuleContext(EGenericWildcardContext.class,0); + } + public EGenericTypeArgumentContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EGenericTypeArgumentContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eGenericTypeArgument; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEGenericTypeArgument(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEGenericTypeArgument(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEGenericTypeArgument(this); + else return visitor.visitChildren(this); + } + } + + public final EGenericTypeArgumentContext eGenericTypeArgument(Element owner) throws RecognitionException { + EGenericTypeArgumentContext _localctx = new EGenericTypeArgumentContext(_ctx, getState(), owner); + enterRule(_localctx, 82, RULE_eGenericTypeArgument); + ((EGenericTypeArgumentContext)_localctx).current = new GenericTypeArgument(_localctx); if (owner!=null) _localctx.owner.addOwnedElement(_localctx.current); + try { + setState(1013); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__11: + case T__20: + case T__21: + case T__23: + case T__24: + case T__25: + case T__26: + case T__27: + case T__29: + case T__30: + case T__31: + case T__32: + case T__33: + case T__34: + case T__35: + case T__37: + case T__39: + case T__41: + case T__43: + case T__44: + case T__46: + case T__47: + case T__50: + case T__56: + case T__57: + case T__58: + case T__60: + case T__61: + case T__62: + case T__63: + case T__75: + case T__76: + case T__77: + case T__78: + case T__80: + case T__82: + case T__83: + case T__131: + case T__132: + case T__133: + case IDENTIFIER: + enterOuterAlt(_localctx, 1); + { + setState(1007); + ((EGenericTypeArgumentContext)_localctx).eGenericType = eGenericType(_localctx.current); + ((EGenericTypeArgumentContext)_localctx).element = ((EGenericTypeArgumentContext)_localctx).eGenericType.element; _localctx.current.setEObject(_localctx.element); + } + break; + case T__53: + enterOuterAlt(_localctx, 2); + { + setState(1010); + ((EGenericTypeArgumentContext)_localctx).eGenericWildcard = eGenericWildcard(_localctx.current); + ((EGenericTypeArgumentContext)_localctx).element = ((EGenericTypeArgumentContext)_localctx).eGenericWildcard.element; _localctx.current.setEObject(_localctx.element); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EGenericTypeContext extends ParserRuleContext { + public Element owner; + public EGenericType element; + public Element current; + public PathNameContext ownedPathName; + public EGenericTypeArgumentContext eGenericTypeArgument; + public List ownedETypeArguments = new ArrayList(); + public PathNameContext pathName() { + return getRuleContext(PathNameContext.class,0); + } + public List eGenericTypeArgument() { + return getRuleContexts(EGenericTypeArgumentContext.class); + } + public EGenericTypeArgumentContext eGenericTypeArgument(int i) { + return getRuleContext(EGenericTypeArgumentContext.class,i); + } + public EGenericTypeContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EGenericTypeContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eGenericType; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEGenericType(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEGenericType(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEGenericType(this); + else return visitor.visitChildren(this); + } + } + + public final EGenericTypeContext eGenericType(Element owner) throws RecognitionException { + EGenericTypeContext _localctx = new EGenericTypeContext(_ctx, getState(), owner); + enterRule(_localctx, 84, RULE_eGenericType); + + ((EGenericTypeContext)_localctx).element = eFactory.createEGenericType(); + if (_localctx.parent instanceof ETypeParameterContext) {((EGenericTypeContext)_localctx).current = new GenericType(_localctx.element, _localctx); owner.addOwnedElement(_localctx.current);} + else {((EGenericTypeContext)_localctx).current = _localctx.owner;} + + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1015); + ((EGenericTypeContext)_localctx).ownedPathName = pathName(_localctx.current); + setState(1027); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__64) { + { + setState(1016); + match(T__64); + setState(1017); + ((EGenericTypeContext)_localctx).eGenericTypeArgument = eGenericTypeArgument(_localctx.current); + ((EGenericTypeContext)_localctx).ownedETypeArguments.add(((EGenericTypeContext)_localctx).eGenericTypeArgument); + setState(1022); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(1018); + match(T__2); + setState(1019); + ((EGenericTypeContext)_localctx).eGenericTypeArgument = eGenericTypeArgument(_localctx.current); + ((EGenericTypeContext)_localctx).ownedETypeArguments.add(((EGenericTypeContext)_localctx).eGenericTypeArgument); + } + } + setState(1024); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1025); + match(T__65); + } + } + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EGenericElementTypeContext extends ParserRuleContext { + public Element owner; + public EGenericType element; + public GenericElementType current; + public EPrimitiveTypeContext ePrimitiveType; + public EGenericTypeContext eGenericType; + public EPrimitiveTypeContext ePrimitiveType() { + return getRuleContext(EPrimitiveTypeContext.class,0); + } + public EGenericTypeContext eGenericType() { + return getRuleContext(EGenericTypeContext.class,0); + } + public EGenericElementTypeContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EGenericElementTypeContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eGenericElementType; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEGenericElementType(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEGenericElementType(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEGenericElementType(this); + else return visitor.visitChildren(this); + } + } + + public final EGenericElementTypeContext eGenericElementType(Element owner) throws RecognitionException { + EGenericElementTypeContext _localctx = new EGenericElementTypeContext(_ctx, getState(), owner); + enterRule(_localctx, 86, RULE_eGenericElementType); + ((EGenericElementTypeContext)_localctx).current = new GenericElementType(_localctx); if (owner!=null) _localctx.owner.addOwnedElement(_localctx.current); + try { + setState(1035); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__70: + case T__71: + case T__72: + case T__73: + case T__74: + enterOuterAlt(_localctx, 1); + { + setState(1029); + ((EGenericElementTypeContext)_localctx).ePrimitiveType = ePrimitiveType(_localctx.current); + ((EGenericElementTypeContext)_localctx).element = ((EGenericElementTypeContext)_localctx).ePrimitiveType.element; _localctx.current.setEObject(_localctx.element); + } + break; + case T__11: + case T__20: + case T__21: + case T__23: + case T__24: + case T__25: + case T__26: + case T__27: + case T__29: + case T__30: + case T__31: + case T__32: + case T__33: + case T__34: + case T__35: + case T__37: + case T__39: + case T__41: + case T__43: + case T__44: + case T__46: + case T__47: + case T__50: + case T__56: + case T__57: + case T__58: + case T__60: + case T__61: + case T__62: + case T__63: + case T__75: + case T__76: + case T__77: + case T__78: + case T__80: + case T__82: + case T__83: + case T__131: + case T__132: + case T__133: + case IDENTIFIER: + enterOuterAlt(_localctx, 2); + { + setState(1032); + ((EGenericElementTypeContext)_localctx).eGenericType = eGenericType(_localctx.current); + ((EGenericElementTypeContext)_localctx).element = ((EGenericElementTypeContext)_localctx).eGenericType.element; _localctx.current.setEObject(_localctx.element); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EGenericWildcardContext extends ParserRuleContext { + public Element owner; + public EGenericType element; + public GenericWildcard current; + public Token bound; + public EGenericTypeContext ownedExtend; + public EGenericTypeContext eGenericType; + public EGenericTypeContext eGenericType() { + return getRuleContext(EGenericTypeContext.class,0); + } + public EGenericWildcardContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EGenericWildcardContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_eGenericWildcard; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEGenericWildcard(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEGenericWildcard(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEGenericWildcard(this); + else return visitor.visitChildren(this); + } + } + + public final EGenericWildcardContext eGenericWildcard(Element owner) throws RecognitionException { + EGenericWildcardContext _localctx = new EGenericWildcardContext(_ctx, getState(), owner); + enterRule(_localctx, 88, RULE_eGenericWildcard); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1037); + match(T__53); + ((EGenericWildcardContext)_localctx).element = eFactory.createEGenericType(); + setState(1044); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__26 || _la==T__67) { + { + setState(1039); + ((EGenericWildcardContext)_localctx).bound = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__26 || _la==T__67) ) { + ((EGenericWildcardContext)_localctx).bound = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + ((EGenericWildcardContext)_localctx).current = new GenericWildcard(_localctx.element, _localctx); if (owner!=null) owner.addOwnedElement(_localctx.current); + setState(1041); + ((EGenericWildcardContext)_localctx).ownedExtend = ((EGenericWildcardContext)_localctx).eGenericType = eGenericType(_localctx.current); + if (((EGenericWildcardContext)_localctx).bound.equals("extends")) _localctx.element.setEUpperBound(((EGenericWildcardContext)_localctx).eGenericType.element); else _localctx.element.setELowerBound(((EGenericWildcardContext)_localctx).eGenericType.element); + } + } + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class PathNameContext extends ParserRuleContext { + public Element owner; + public EObject element; + public UnrestrictedNameContext firstSegment; + public Token index; + public SegmentContext segment; + public List midSegments = new ArrayList(); + public SegmentContext lastSegment; + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public TerminalNode INT() { return getToken(AlloyInEcoreParser.INT, 0); } + public List segment() { + return getRuleContexts(SegmentContext.class); + } + public SegmentContext segment(int i) { + return getRuleContext(SegmentContext.class,i); + } + public PathNameContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public PathNameContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_pathName; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterPathName(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitPathName(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitPathName(this); + else return visitor.visitChildren(this); + } + } + + public final PathNameContext pathName(Element owner) throws RecognitionException { + PathNameContext _localctx = new PathNameContext(_ctx, getState(), owner); + enterRule(_localctx, 90, RULE_pathName); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(1046); + ((PathNameContext)_localctx).firstSegment = unrestrictedName(); + setState(1049); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,141,_ctx) ) { + case 1: + { + setState(1047); + match(T__18); + setState(1048); + ((PathNameContext)_localctx).index = match(INT); + } + break; + } + setState(1058); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,143,_ctx) ) { + case 1: + { + setState(1054); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,142,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(1051); + ((PathNameContext)_localctx).segment = segment(); + ((PathNameContext)_localctx).midSegments.add(((PathNameContext)_localctx).segment); + } + } + } + setState(1056); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,142,_ctx); + } + setState(1057); + ((PathNameContext)_localctx).lastSegment = segment(); + } + break; + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class SegmentContext extends ParserRuleContext { + public UnrestrictedNameContext name; + public Token index; + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public TerminalNode INT() { return getToken(AlloyInEcoreParser.INT, 0); } + public SegmentContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_segment; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterSegment(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitSegment(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitSegment(this); + else return visitor.visitChildren(this); + } + } + + public final SegmentContext segment() throws RecognitionException { + SegmentContext _localctx = new SegmentContext(_ctx, getState()); + enterRule(_localctx, 92, RULE_segment); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1060); + match(T__68); + setState(1062); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__69) { + { + setState(1061); + match(T__69); + } + } + + setState(1064); + ((SegmentContext)_localctx).name = unrestrictedName(); + setState(1067); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,145,_ctx) ) { + case 1: + { + setState(1065); + match(T__18); + setState(1066); + ((SegmentContext)_localctx).index = match(INT); + } + break; + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class EPrimitiveTypeContext extends ParserRuleContext { + public Element owner; + public EGenericType element; + public PrimitiveType current; + public EPrimitiveTypeContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public EPrimitiveTypeContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_ePrimitiveType; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEPrimitiveType(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEPrimitiveType(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEPrimitiveType(this); + else return visitor.visitChildren(this); + } + } + + public final EPrimitiveTypeContext ePrimitiveType(Element owner) throws RecognitionException { + EPrimitiveTypeContext _localctx = new EPrimitiveTypeContext(_ctx, getState(), owner); + enterRule(_localctx, 94, RULE_ePrimitiveType); + try { + setState(1079); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__70: + enterOuterAlt(_localctx, 1); + { + setState(1069); + match(T__70); + ((EPrimitiveTypeContext)_localctx).element = eFactory.createEGenericType(); _localctx.element.setEClassifier(EcorePackage.eINSTANCE.getEBoolean()); + } + break; + case T__71: + enterOuterAlt(_localctx, 2); + { + setState(1071); + match(T__71); + ((EPrimitiveTypeContext)_localctx).element = eFactory.createEGenericType(); _localctx.element.setEClassifier(EcorePackage.eINSTANCE.getEInt()); + } + break; + case T__72: + enterOuterAlt(_localctx, 3); + { + setState(1073); + match(T__72); + ((EPrimitiveTypeContext)_localctx).element = eFactory.createEGenericType(); _localctx.element.setEClassifier(EcorePackage.eINSTANCE.getEString()); + } + break; + case T__73: + enterOuterAlt(_localctx, 4); + { + setState(1075); + match(T__73); + ((EPrimitiveTypeContext)_localctx).element = eFactory.createEGenericType(); _localctx.element.setEClassifier(EcorePackage.eINSTANCE.getEBigDecimal()); + } + break; + case T__74: + enterOuterAlt(_localctx, 5); + { + setState(1077); + match(T__74); + ((EPrimitiveTypeContext)_localctx).element = eFactory.createEGenericType(); _localctx.element.setEClassifier(EcorePackage.eINSTANCE.getEBigInteger()); + } + break; + default: + throw new NoViableAltException(this); + } + _ctx.stop = _input.LT(-1); + ((EPrimitiveTypeContext)_localctx).current = new PrimitiveType(_localctx.element, _localctx); if (owner!=null) owner.addOwnedElement(_localctx.current); + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class BodyContext extends ParserRuleContext { + public Element owner; + public EAnnotation element; + public Body current; + public IdentifierContext name; + public ExpressionContext ownedExpression; + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class,0); + } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public BodyContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public BodyContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_body; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterBody(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitBody(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitBody(this); + else return visitor.visitChildren(this); + } + } + + public final BodyContext body(Element owner) throws RecognitionException { + BodyContext _localctx = new BodyContext(_ctx, getState(), owner); + enterRule(_localctx, 96, RULE_body); + ((BodyContext)_localctx).element = eFactory.createEAnnotation(); _localctx.element.setSource(AnnotationSources.BODY); ((BodyContext)_localctx).current = new Body(_localctx); if (owner!=null) _localctx.owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1081); + match(T__75); + setState(1083); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==IDENTIFIER) { + { + setState(1082); + ((BodyContext)_localctx).name = identifier(); + } + } + + if(_localctx.name!=null) _localctx.element.getDetails().put("name", (((BodyContext)_localctx).name!=null?_input.getText(((BodyContext)_localctx).name.start,((BodyContext)_localctx).name.stop):null)); + setState(1092); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__5: + { + { + setState(1086); + match(T__5); + setState(1088); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 2)) & ~0x3f) == 0 && ((1L << (_la - 2)) & ((1L << (T__1 - 2)) | (1L << (T__11 - 2)) | (1L << (T__20 - 2)) | (1L << (T__21 - 2)) | (1L << (T__23 - 2)) | (1L << (T__24 - 2)) | (1L << (T__25 - 2)) | (1L << (T__26 - 2)) | (1L << (T__27 - 2)) | (1L << (T__29 - 2)) | (1L << (T__30 - 2)) | (1L << (T__31 - 2)) | (1L << (T__32 - 2)) | (1L << (T__33 - 2)) | (1L << (T__34 - 2)) | (1L << (T__35 - 2)) | (1L << (T__37 - 2)) | (1L << (T__39 - 2)) | (1L << (T__41 - 2)) | (1L << (T__43 - 2)) | (1L << (T__44 - 2)) | (1L << (T__46 - 2)) | (1L << (T__47 - 2)) | (1L << (T__48 - 2)) | (1L << (T__50 - 2)) | (1L << (T__52 - 2)) | (1L << (T__56 - 2)) | (1L << (T__57 - 2)) | (1L << (T__58 - 2)) | (1L << (T__60 - 2)) | (1L << (T__61 - 2)) | (1L << (T__62 - 2)) | (1L << (T__63 - 2)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__106 - 76)) | (1L << (T__107 - 76)) | (1L << (T__113 - 76)) | (1L << (T__114 - 76)) | (1L << (T__118 - 76)) | (1L << (T__119 - 76)) | (1L << (T__120 - 76)) | (1L << (T__121 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + setState(1087); + ((BodyContext)_localctx).ownedExpression = expression(0); + } + } + + setState(1090); + match(T__10); + } + } + break; + case T__10: + { + setState(1091); + match(T__10); + } + break; + default: + throw new NoViableAltException(this); + } + if(_localctx.ownedExpression!=null) {_localctx.element.getDetails().put("expression", getContextText(_localctx.expression())); _localctx.current.addOwnedElement(((BodyContext)_localctx).ownedExpression.element);} + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class InvariantContext extends ParserRuleContext { + public Element owner; + public EAnnotation element; + public Invariant current; + public Token isCallable; + public IdentifierContext name; + public Token message; + public FormulaContext ownedSpecification; + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class,0); + } + public TerminalNode DOUBLE_QUOTED_STRING() { return getToken(AlloyInEcoreParser.DOUBLE_QUOTED_STRING, 0); } + public FormulaContext formula() { + return getRuleContext(FormulaContext.class,0); + } + public InvariantContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public InvariantContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_invariant; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterInvariant(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitInvariant(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitInvariant(this); + else return visitor.visitChildren(this); + } + } + + public final InvariantContext invariant(Element owner) throws RecognitionException { + InvariantContext _localctx = new InvariantContext(_ctx, getState(), owner); + enterRule(_localctx, 98, RULE_invariant); + ((InvariantContext)_localctx).element = eFactory.createEAnnotation(); _localctx.element.setSource(AnnotationSources.INVARIANT); ((InvariantContext)_localctx).current = new Invariant(_localctx); _localctx.owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1097); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__76) { + { + setState(1096); + ((InvariantContext)_localctx).isCallable = match(T__76); + } + } + + _localctx.element.getDetails().put("callable", ((InvariantContext)_localctx).isCallable != null ? "true" : "false"); + setState(1100); + match(T__77); + setState(1107); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==IDENTIFIER) { + { + setState(1101); + ((InvariantContext)_localctx).name = identifier(); + setState(1105); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__48) { + { + setState(1102); + match(T__48); + setState(1103); + ((InvariantContext)_localctx).message = match(DOUBLE_QUOTED_STRING); + setState(1104); + match(T__49); + } + } + + } + } + + if(_localctx.name!=null) _localctx.element.getDetails().put("name", (((InvariantContext)_localctx).name!=null?_input.getText(((InvariantContext)_localctx).name.start,((InvariantContext)_localctx).name.stop):null)); if(((InvariantContext)_localctx).message!=null) _localctx.element.getDetails().put("message", (((InvariantContext)_localctx).message!=null?((InvariantContext)_localctx).message.getText():null).replace("\"", "")); + setState(1116); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__5: + { + { + setState(1110); + match(T__5); + setState(1112); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 2)) & ~0x3f) == 0 && ((1L << (_la - 2)) & ((1L << (T__1 - 2)) | (1L << (T__11 - 2)) | (1L << (T__14 - 2)) | (1L << (T__15 - 2)) | (1L << (T__17 - 2)) | (1L << (T__20 - 2)) | (1L << (T__21 - 2)) | (1L << (T__23 - 2)) | (1L << (T__24 - 2)) | (1L << (T__25 - 2)) | (1L << (T__26 - 2)) | (1L << (T__27 - 2)) | (1L << (T__29 - 2)) | (1L << (T__30 - 2)) | (1L << (T__31 - 2)) | (1L << (T__32 - 2)) | (1L << (T__33 - 2)) | (1L << (T__34 - 2)) | (1L << (T__35 - 2)) | (1L << (T__37 - 2)) | (1L << (T__39 - 2)) | (1L << (T__41 - 2)) | (1L << (T__42 - 2)) | (1L << (T__43 - 2)) | (1L << (T__44 - 2)) | (1L << (T__46 - 2)) | (1L << (T__47 - 2)) | (1L << (T__48 - 2)) | (1L << (T__50 - 2)) | (1L << (T__52 - 2)) | (1L << (T__56 - 2)) | (1L << (T__57 - 2)) | (1L << (T__58 - 2)) | (1L << (T__60 - 2)) | (1L << (T__61 - 2)) | (1L << (T__62 - 2)) | (1L << (T__63 - 2)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__87 - 76)) | (1L << (T__88 - 76)) | (1L << (T__89 - 76)) | (1L << (T__90 - 76)) | (1L << (T__91 - 76)) | (1L << (T__92 - 76)) | (1L << (T__96 - 76)) | (1L << (T__98 - 76)) | (1L << (T__99 - 76)) | (1L << (T__101 - 76)) | (1L << (T__106 - 76)) | (1L << (T__107 - 76)) | (1L << (T__111 - 76)) | (1L << (T__112 - 76)) | (1L << (T__113 - 76)) | (1L << (T__114 - 76)) | (1L << (T__118 - 76)) | (1L << (T__119 - 76)) | (1L << (T__120 - 76)) | (1L << (T__121 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (INT - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + setState(1111); + ((InvariantContext)_localctx).ownedSpecification = formula(0); + } + } + + setState(1114); + match(T__10); + } + } + break; + case T__10: + { + setState(1115); + match(T__10); + } + break; + default: + throw new NoViableAltException(this); + } + if(_localctx.ownedSpecification!=null) {_localctx.element.getDetails().put("formula", getContextText(_localctx.formula())); _localctx.current.addOwnedElement(((InvariantContext)_localctx).ownedSpecification.element);} + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class PreconditionContext extends ParserRuleContext { + public Element owner; + public EAnnotation element; + public PreCondition current; + public IdentifierContext name; + public Token message; + public FormulaContext ownedSpecification; + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class,0); + } + public TerminalNode DOUBLE_QUOTED_STRING() { return getToken(AlloyInEcoreParser.DOUBLE_QUOTED_STRING, 0); } + public FormulaContext formula() { + return getRuleContext(FormulaContext.class,0); + } + public PreconditionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public PreconditionContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_precondition; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterPrecondition(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitPrecondition(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitPrecondition(this); + else return visitor.visitChildren(this); + } + } + + public final PreconditionContext precondition(Element owner) throws RecognitionException { + PreconditionContext _localctx = new PreconditionContext(_ctx, getState(), owner); + enterRule(_localctx, 100, RULE_precondition); + ((PreconditionContext)_localctx).element = eFactory.createEAnnotation(); _localctx.element.setSource(AnnotationSources.PRECONDITION); ((PreconditionContext)_localctx).current = new PreCondition(_localctx); _localctx.owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1120); + _la = _input.LA(1); + if ( !(_la==T__78 || _la==T__79) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1127); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==IDENTIFIER) { + { + setState(1121); + ((PreconditionContext)_localctx).name = identifier(); + setState(1125); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__48) { + { + setState(1122); + match(T__48); + setState(1123); + ((PreconditionContext)_localctx).message = match(DOUBLE_QUOTED_STRING); + setState(1124); + match(T__49); + } + } + + } + } + + if(_localctx.name!=null) _localctx.element.getDetails().put("name", (((PreconditionContext)_localctx).name!=null?_input.getText(((PreconditionContext)_localctx).name.start,((PreconditionContext)_localctx).name.stop):null)); if(((PreconditionContext)_localctx).message!=null) _localctx.element.getDetails().put("message", (((PreconditionContext)_localctx).message!=null?((PreconditionContext)_localctx).message.getText():null).replace("\"", "")); + setState(1136); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__5: + { + { + setState(1130); + match(T__5); + setState(1132); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 2)) & ~0x3f) == 0 && ((1L << (_la - 2)) & ((1L << (T__1 - 2)) | (1L << (T__11 - 2)) | (1L << (T__14 - 2)) | (1L << (T__15 - 2)) | (1L << (T__17 - 2)) | (1L << (T__20 - 2)) | (1L << (T__21 - 2)) | (1L << (T__23 - 2)) | (1L << (T__24 - 2)) | (1L << (T__25 - 2)) | (1L << (T__26 - 2)) | (1L << (T__27 - 2)) | (1L << (T__29 - 2)) | (1L << (T__30 - 2)) | (1L << (T__31 - 2)) | (1L << (T__32 - 2)) | (1L << (T__33 - 2)) | (1L << (T__34 - 2)) | (1L << (T__35 - 2)) | (1L << (T__37 - 2)) | (1L << (T__39 - 2)) | (1L << (T__41 - 2)) | (1L << (T__42 - 2)) | (1L << (T__43 - 2)) | (1L << (T__44 - 2)) | (1L << (T__46 - 2)) | (1L << (T__47 - 2)) | (1L << (T__48 - 2)) | (1L << (T__50 - 2)) | (1L << (T__52 - 2)) | (1L << (T__56 - 2)) | (1L << (T__57 - 2)) | (1L << (T__58 - 2)) | (1L << (T__60 - 2)) | (1L << (T__61 - 2)) | (1L << (T__62 - 2)) | (1L << (T__63 - 2)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__87 - 76)) | (1L << (T__88 - 76)) | (1L << (T__89 - 76)) | (1L << (T__90 - 76)) | (1L << (T__91 - 76)) | (1L << (T__92 - 76)) | (1L << (T__96 - 76)) | (1L << (T__98 - 76)) | (1L << (T__99 - 76)) | (1L << (T__101 - 76)) | (1L << (T__106 - 76)) | (1L << (T__107 - 76)) | (1L << (T__111 - 76)) | (1L << (T__112 - 76)) | (1L << (T__113 - 76)) | (1L << (T__114 - 76)) | (1L << (T__118 - 76)) | (1L << (T__119 - 76)) | (1L << (T__120 - 76)) | (1L << (T__121 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (INT - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + setState(1131); + ((PreconditionContext)_localctx).ownedSpecification = formula(0); + } + } + + setState(1134); + match(T__10); + } + } + break; + case T__10: + { + setState(1135); + match(T__10); + } + break; + default: + throw new NoViableAltException(this); + } + if(_localctx.ownedSpecification!=null) _localctx.element.getDetails().put("formula", getContextText(_localctx.formula())); _localctx.current.addOwnedElement(((PreconditionContext)_localctx).ownedSpecification.element); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class PostconditionContext extends ParserRuleContext { + public Element owner; + public EAnnotation element; + public PostCondition current; + public IdentifierContext name; + public Token message; + public FormulaContext ownedSpecification; + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class,0); + } + public TerminalNode DOUBLE_QUOTED_STRING() { return getToken(AlloyInEcoreParser.DOUBLE_QUOTED_STRING, 0); } + public FormulaContext formula() { + return getRuleContext(FormulaContext.class,0); + } + public PostconditionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public PostconditionContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_postcondition; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterPostcondition(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitPostcondition(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitPostcondition(this); + else return visitor.visitChildren(this); + } + } + + public final PostconditionContext postcondition(Element owner) throws RecognitionException { + PostconditionContext _localctx = new PostconditionContext(_ctx, getState(), owner); + enterRule(_localctx, 102, RULE_postcondition); + ((PostconditionContext)_localctx).element = eFactory.createEAnnotation(); _localctx.element.setSource(AnnotationSources.POSTCONDITION); ((PostconditionContext)_localctx).current = new PostCondition(_localctx); _localctx.owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1140); + _la = _input.LA(1); + if ( !(_la==T__80 || _la==T__81) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1147); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==IDENTIFIER) { + { + setState(1141); + ((PostconditionContext)_localctx).name = identifier(); + setState(1145); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__48) { + { + setState(1142); + match(T__48); + setState(1143); + ((PostconditionContext)_localctx).message = match(DOUBLE_QUOTED_STRING); + setState(1144); + match(T__49); + } + } + + } + } + + if(_localctx.name!=null) _localctx.element.getDetails().put("name", (((PostconditionContext)_localctx).name!=null?_input.getText(((PostconditionContext)_localctx).name.start,((PostconditionContext)_localctx).name.stop):null)); if(((PostconditionContext)_localctx).message!=null) _localctx.element.getDetails().put("message", (((PostconditionContext)_localctx).message!=null?((PostconditionContext)_localctx).message.getText():null).replace("\"", "")); + setState(1156); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__5: + { + { + setState(1150); + match(T__5); + setState(1152); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 2)) & ~0x3f) == 0 && ((1L << (_la - 2)) & ((1L << (T__1 - 2)) | (1L << (T__11 - 2)) | (1L << (T__14 - 2)) | (1L << (T__15 - 2)) | (1L << (T__17 - 2)) | (1L << (T__20 - 2)) | (1L << (T__21 - 2)) | (1L << (T__23 - 2)) | (1L << (T__24 - 2)) | (1L << (T__25 - 2)) | (1L << (T__26 - 2)) | (1L << (T__27 - 2)) | (1L << (T__29 - 2)) | (1L << (T__30 - 2)) | (1L << (T__31 - 2)) | (1L << (T__32 - 2)) | (1L << (T__33 - 2)) | (1L << (T__34 - 2)) | (1L << (T__35 - 2)) | (1L << (T__37 - 2)) | (1L << (T__39 - 2)) | (1L << (T__41 - 2)) | (1L << (T__42 - 2)) | (1L << (T__43 - 2)) | (1L << (T__44 - 2)) | (1L << (T__46 - 2)) | (1L << (T__47 - 2)) | (1L << (T__48 - 2)) | (1L << (T__50 - 2)) | (1L << (T__52 - 2)) | (1L << (T__56 - 2)) | (1L << (T__57 - 2)) | (1L << (T__58 - 2)) | (1L << (T__60 - 2)) | (1L << (T__61 - 2)) | (1L << (T__62 - 2)) | (1L << (T__63 - 2)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__87 - 76)) | (1L << (T__88 - 76)) | (1L << (T__89 - 76)) | (1L << (T__90 - 76)) | (1L << (T__91 - 76)) | (1L << (T__92 - 76)) | (1L << (T__96 - 76)) | (1L << (T__98 - 76)) | (1L << (T__99 - 76)) | (1L << (T__101 - 76)) | (1L << (T__106 - 76)) | (1L << (T__107 - 76)) | (1L << (T__111 - 76)) | (1L << (T__112 - 76)) | (1L << (T__113 - 76)) | (1L << (T__114 - 76)) | (1L << (T__118 - 76)) | (1L << (T__119 - 76)) | (1L << (T__120 - 76)) | (1L << (T__121 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (INT - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + setState(1151); + ((PostconditionContext)_localctx).ownedSpecification = formula(0); + } + } + + setState(1154); + match(T__10); + } + } + break; + case T__10: + { + setState(1155); + match(T__10); + } + break; + default: + throw new NoViableAltException(this); + } + if(_localctx.ownedSpecification!=null) _localctx.element.getDetails().put("formula", getContextText(_localctx.formula())); _localctx.current.addOwnedElement(((PostconditionContext)_localctx).ownedSpecification.element); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class InitialContext extends ParserRuleContext { + public Element owner; + public EAnnotation element; + public Initial current; + public IdentifierContext name; + public ExpressionContext ownedExpression; + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class,0); + } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public InitialContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public InitialContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_initial; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterInitial(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitInitial(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitInitial(this); + else return visitor.visitChildren(this); + } + } + + public final InitialContext initial(Element owner) throws RecognitionException { + InitialContext _localctx = new InitialContext(_ctx, getState(), owner); + enterRule(_localctx, 104, RULE_initial); + ((InitialContext)_localctx).element = eFactory.createEAnnotation(); _localctx.element.setSource(AnnotationSources.INITIAL); ((InitialContext)_localctx).current = new Initial(_localctx); _localctx.owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1160); + match(T__82); + setState(1162); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==IDENTIFIER) { + { + setState(1161); + ((InitialContext)_localctx).name = identifier(); + } + } + + if(_localctx.name!=null) _localctx.element.getDetails().put("name", (((InitialContext)_localctx).name!=null?_input.getText(((InitialContext)_localctx).name.start,((InitialContext)_localctx).name.stop):null)); + setState(1171); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__5: + { + { + setState(1165); + match(T__5); + setState(1167); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 2)) & ~0x3f) == 0 && ((1L << (_la - 2)) & ((1L << (T__1 - 2)) | (1L << (T__11 - 2)) | (1L << (T__20 - 2)) | (1L << (T__21 - 2)) | (1L << (T__23 - 2)) | (1L << (T__24 - 2)) | (1L << (T__25 - 2)) | (1L << (T__26 - 2)) | (1L << (T__27 - 2)) | (1L << (T__29 - 2)) | (1L << (T__30 - 2)) | (1L << (T__31 - 2)) | (1L << (T__32 - 2)) | (1L << (T__33 - 2)) | (1L << (T__34 - 2)) | (1L << (T__35 - 2)) | (1L << (T__37 - 2)) | (1L << (T__39 - 2)) | (1L << (T__41 - 2)) | (1L << (T__43 - 2)) | (1L << (T__44 - 2)) | (1L << (T__46 - 2)) | (1L << (T__47 - 2)) | (1L << (T__48 - 2)) | (1L << (T__50 - 2)) | (1L << (T__52 - 2)) | (1L << (T__56 - 2)) | (1L << (T__57 - 2)) | (1L << (T__58 - 2)) | (1L << (T__60 - 2)) | (1L << (T__61 - 2)) | (1L << (T__62 - 2)) | (1L << (T__63 - 2)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__106 - 76)) | (1L << (T__107 - 76)) | (1L << (T__113 - 76)) | (1L << (T__114 - 76)) | (1L << (T__118 - 76)) | (1L << (T__119 - 76)) | (1L << (T__120 - 76)) | (1L << (T__121 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + setState(1166); + ((InitialContext)_localctx).ownedExpression = expression(0); + } + } + + setState(1169); + match(T__10); + } + } + break; + case T__10: + { + setState(1170); + match(T__10); + } + break; + default: + throw new NoViableAltException(this); + } + if(_localctx.ownedExpression!=null) {_localctx.element.getDetails().put("expression", getContextText(_localctx.expression())); _localctx.current.addOwnedElement(((InitialContext)_localctx).ownedExpression.element);} + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class DerivationContext extends ParserRuleContext { + public Element owner; + public EAnnotation element; + public Derivation current; + public IdentifierContext name; + public ExpressionContext ownedExpression; + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class,0); + } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public DerivationContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public DerivationContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_derivation; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterDerivation(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitDerivation(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitDerivation(this); + else return visitor.visitChildren(this); + } + } + + public final DerivationContext derivation(Element owner) throws RecognitionException { + DerivationContext _localctx = new DerivationContext(_ctx, getState(), owner); + enterRule(_localctx, 106, RULE_derivation); + ((DerivationContext)_localctx).element = eFactory.createEAnnotation(); _localctx.element.setSource(AnnotationSources.DERIVATION); ((DerivationContext)_localctx).current = new Derivation(_localctx); _localctx.owner.addOwnedElement(_localctx.current); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1175); + match(T__83); + setState(1177); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==IDENTIFIER) { + { + setState(1176); + ((DerivationContext)_localctx).name = identifier(); + } + } + + if(_localctx.name!=null) _localctx.element.getDetails().put("name", (((DerivationContext)_localctx).name!=null?_input.getText(((DerivationContext)_localctx).name.start,((DerivationContext)_localctx).name.stop):null)); + setState(1186); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__5: + { + { + setState(1180); + match(T__5); + setState(1182); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 2)) & ~0x3f) == 0 && ((1L << (_la - 2)) & ((1L << (T__1 - 2)) | (1L << (T__11 - 2)) | (1L << (T__20 - 2)) | (1L << (T__21 - 2)) | (1L << (T__23 - 2)) | (1L << (T__24 - 2)) | (1L << (T__25 - 2)) | (1L << (T__26 - 2)) | (1L << (T__27 - 2)) | (1L << (T__29 - 2)) | (1L << (T__30 - 2)) | (1L << (T__31 - 2)) | (1L << (T__32 - 2)) | (1L << (T__33 - 2)) | (1L << (T__34 - 2)) | (1L << (T__35 - 2)) | (1L << (T__37 - 2)) | (1L << (T__39 - 2)) | (1L << (T__41 - 2)) | (1L << (T__43 - 2)) | (1L << (T__44 - 2)) | (1L << (T__46 - 2)) | (1L << (T__47 - 2)) | (1L << (T__48 - 2)) | (1L << (T__50 - 2)) | (1L << (T__52 - 2)) | (1L << (T__56 - 2)) | (1L << (T__57 - 2)) | (1L << (T__58 - 2)) | (1L << (T__60 - 2)) | (1L << (T__61 - 2)) | (1L << (T__62 - 2)) | (1L << (T__63 - 2)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__106 - 76)) | (1L << (T__107 - 76)) | (1L << (T__113 - 76)) | (1L << (T__114 - 76)) | (1L << (T__118 - 76)) | (1L << (T__119 - 76)) | (1L << (T__120 - 76)) | (1L << (T__121 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + setState(1181); + ((DerivationContext)_localctx).ownedExpression = expression(0); + } + } + + setState(1184); + match(T__10); + } + } + break; + case T__10: + { + setState(1185); + match(T__10); + } + break; + default: + throw new NoViableAltException(this); + } + if(_localctx.ownedExpression!=null) {_localctx.element.getDetails().put("expression", getContextText(_localctx.expression())); _localctx.current.addOwnedElement(((DerivationContext)_localctx).ownedExpression.element);} + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class VisibilityKindContext extends ParserRuleContext { + public EAnnotation element; + public Token qualifier; + public VisibilityKindContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_visibilityKind; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterVisibilityKind(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitVisibilityKind(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitVisibilityKind(this); + else return visitor.visitChildren(this); + } + } + + public final VisibilityKindContext visibilityKind() throws RecognitionException { + VisibilityKindContext _localctx = new VisibilityKindContext(_ctx, getState()); + enterRule(_localctx, 108, RULE_visibilityKind); + ((VisibilityKindContext)_localctx).element = eFactory.createEAnnotation(); _localctx.element.setSource(AnnotationSources.VISIBILITY); + try { + enterOuterAlt(_localctx, 1); + { + setState(1193); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__84: + { + setState(1190); + ((VisibilityKindContext)_localctx).qualifier = match(T__84); + } + break; + case T__85: + { + setState(1191); + ((VisibilityKindContext)_localctx).qualifier = match(T__85); + } + break; + case T__86: + { + setState(1192); + ((VisibilityKindContext)_localctx).qualifier = match(T__86); + } + break; + default: + throw new NoViableAltException(this); + } + _localctx.element.getDetails().put("visibility", (((VisibilityKindContext)_localctx).qualifier!=null?((VisibilityKindContext)_localctx).qualifier.getText():null)); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class FormulaContext extends ParserRuleContext { + public Formula element; + public int var = 0; + public FormulaContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_formula; } + + public FormulaContext() { } + public void copyFrom(FormulaContext ctx) { + super.copyFrom(ctx); + this.element = ctx.element; + this.var = ctx.var; + } + } + public static class NoContext extends FormulaContext { + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public NoContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterNo(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitNo(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitNo(this); + else return visitor.visitChildren(this); + } + } + public static class SomeContext extends FormulaContext { + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public SomeContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterSome(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitSome(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitSome(this); + else return visitor.visitChildren(this); + } + } + public static class ForOneContext extends FormulaContext { + public FormulaContext formula; + public QuantifierDeclarationsContext quantifierDeclarations() { + return getRuleContext(QuantifierDeclarationsContext.class,0); + } + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public ForOneContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterForOne(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitForOne(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitForOne(this); + else return visitor.visitChildren(this); + } + } + public static class SumDeclarationContext extends FormulaContext { + public QuantifierDeclarationsContext quantifierDeclarations() { + return getRuleContext(QuantifierDeclarationsContext.class,0); + } + public IntExpressionContext intExpression() { + return getRuleContext(IntExpressionContext.class,0); + } + public SumDeclarationContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterSumDeclaration(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitSumDeclaration(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitSumDeclaration(this); + else return visitor.visitChildren(this); + } + } + public static class ForAllContext extends FormulaContext { + public FormulaContext formula; + public QuantifierDeclarationsContext quantifierDeclarations() { + return getRuleContext(QuantifierDeclarationsContext.class,0); + } + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public ForAllContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterForAll(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitForAll(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitForAll(this); + else return visitor.visitChildren(this); + } + } + public static class LoneContext extends FormulaContext { + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public LoneContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterLone(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitLone(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitLone(this); + else return visitor.visitChildren(this); + } + } + public static class LtContext extends FormulaContext { + public IntExpressionContext ileft; + public Token not; + public IntExpressionContext iright; + public List intExpression() { + return getRuleContexts(IntExpressionContext.class); + } + public IntExpressionContext intExpression(int i) { + return getRuleContext(IntExpressionContext.class,i); + } + public LtContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterLt(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitLt(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitLt(this); + else return visitor.visitChildren(this); + } + } + public static class ForSomeContext extends FormulaContext { + public FormulaContext formula; + public QuantifierDeclarationsContext quantifierDeclarations() { + return getRuleContext(QuantifierDeclarationsContext.class,0); + } + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public ForSomeContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterForSome(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitForSome(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitForSome(this); + else return visitor.visitChildren(this); + } + } + public static class NotContext extends FormulaContext { + public Token op; + public FormulaContext formula; + public FormulaContext formula() { + return getRuleContext(FormulaContext.class,0); + } + public NotContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterNot(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitNot(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitNot(this); + else return visitor.visitChildren(this); + } + } + public static class F_paranthesisContext extends FormulaContext { + public FormulaContext formula; + public FormulaContext formula() { + return getRuleContext(FormulaContext.class,0); + } + public F_paranthesisContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterF_paranthesis(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitF_paranthesis(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitF_paranthesis(this); + else return visitor.visitChildren(this); + } + } + public static class AndContext extends FormulaContext { + public FormulaContext fleft; + public Token op; + public FormulaContext fright; + public FormulaContext formula; + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public AndContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterAnd(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitAnd(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitAnd(this); + else return visitor.visitChildren(this); + } + } + public static class FunctionContext extends FormulaContext { + public RelationIdContext rel; + public ExpressionContext domain; + public Token partial; + public ExpressionContext range; + public RelationIdContext relationId() { + return getRuleContext(RelationIdContext.class,0); + } + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public FunctionContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterFunction(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitFunction(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitFunction(this); + else return visitor.visitChildren(this); + } + } + public static class GteContext extends FormulaContext { + public IntExpressionContext ileft; + public Token not; + public IntExpressionContext iright; + public List intExpression() { + return getRuleContexts(IntExpressionContext.class); + } + public IntExpressionContext intExpression(int i) { + return getRuleContext(IntExpressionContext.class,i); + } + public GteContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterGte(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitGte(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitGte(this); + else return visitor.visitChildren(this); + } + } + public static class AcyclicContext extends FormulaContext { + public RelationIdContext relationId() { + return getRuleContext(RelationIdContext.class,0); + } + public AcyclicContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterAcyclic(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitAcyclic(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitAcyclic(this); + else return visitor.visitChildren(this); + } + } + public static class LetContext extends FormulaContext { + public FormulaContext formula; + public LetDeclarationsContext letDeclarations() { + return getRuleContext(LetDeclarationsContext.class,0); + } + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public LetContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterLet(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitLet(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitLet(this); + else return visitor.visitChildren(this); + } + } + public static class LteContext extends FormulaContext { + public IntExpressionContext ileft; + public Token not; + public IntExpressionContext iright; + public List intExpression() { + return getRuleContexts(IntExpressionContext.class); + } + public IntExpressionContext intExpression(int i) { + return getRuleContext(IntExpressionContext.class,i); + } + public LteContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterLte(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitLte(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitLte(this); + else return visitor.visitChildren(this); + } + } + public static class OrContext extends FormulaContext { + public FormulaContext fleft; + public Token op; + public FormulaContext fright; + public FormulaContext formula; + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public OrContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterOr(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitOr(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitOr(this); + else return visitor.visitChildren(this); + } + } + public static class InContext extends FormulaContext { + public ExpressionContext left; + public Token not; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public InContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterIn(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitIn(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitIn(this); + else return visitor.visitChildren(this); + } + } + public static class OneContext extends FormulaContext { + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public OneContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterOne(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitOne(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitOne(this); + else return visitor.visitChildren(this); + } + } + public static class FalseContext extends FormulaContext { + public FalseContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterFalse(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitFalse(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitFalse(this); + else return visitor.visitChildren(this); + } + } + public static class IffContext extends FormulaContext { + public FormulaContext fleft; + public Token op; + public FormulaContext fright; + public FormulaContext formula; + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public IffContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterIff(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitIff(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitIff(this); + else return visitor.visitChildren(this); + } + } + public static class EqContext extends FormulaContext { + public IntExpressionContext ileft; + public Token not; + public IntExpressionContext iright; + public List intExpression() { + return getRuleContexts(IntExpressionContext.class); + } + public IntExpressionContext intExpression(int i) { + return getRuleContext(IntExpressionContext.class,i); + } + public EqContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEq(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEq(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEq(this); + else return visitor.visitChildren(this); + } + } + public static class GtContext extends FormulaContext { + public IntExpressionContext ileft; + public Token not; + public IntExpressionContext iright; + public List intExpression() { + return getRuleContexts(IntExpressionContext.class); + } + public IntExpressionContext intExpression(int i) { + return getRuleContext(IntExpressionContext.class,i); + } + public GtContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterGt(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitGt(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitGt(this); + else return visitor.visitChildren(this); + } + } + public static class EqualContext extends FormulaContext { + public ExpressionContext left; + public Token not; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public EqualContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterEqual(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitEqual(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitEqual(this); + else return visitor.visitChildren(this); + } + } + public static class ForLoneContext extends FormulaContext { + public FormulaContext formula; + public QuantifierDeclarationsContext quantifierDeclarations() { + return getRuleContext(QuantifierDeclarationsContext.class,0); + } + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public ForLoneContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterForLone(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitForLone(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitForLone(this); + else return visitor.visitChildren(this); + } + } + public static class TotalOrderContext extends FormulaContext { + public RelationIdContext rel; + public RelationIdContext ordered; + public RelationIdContext first; + public RelationIdContext last; + public List relationId() { + return getRuleContexts(RelationIdContext.class); + } + public RelationIdContext relationId(int i) { + return getRuleContext(RelationIdContext.class,i); + } + public TotalOrderContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterTotalOrder(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitTotalOrder(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitTotalOrder(this); + else return visitor.visitChildren(this); + } + } + public static class TrueContext extends FormulaContext { + public TrueContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterTrue(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitTrue(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitTrue(this); + else return visitor.visitChildren(this); + } + } + public static class ForNoContext extends FormulaContext { + public FormulaContext formula; + public QuantifierDeclarationsContext quantifierDeclarations() { + return getRuleContext(QuantifierDeclarationsContext.class,0); + } + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public ForNoContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterForNo(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitForNo(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitForNo(this); + else return visitor.visitChildren(this); + } + } + public static class ImpliesContext extends FormulaContext { + public FormulaContext fleft; + public Token op; + public FormulaContext fright; + public FormulaContext formula; + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public ImpliesContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterImplies(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitImplies(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitImplies(this); + else return visitor.visitChildren(this); + } + } + + public final FormulaContext formula() throws RecognitionException { + return formula(0); + } + + private FormulaContext formula(int _p) throws RecognitionException { + ParserRuleContext _parentctx = _ctx; + int _parentState = getState(); + FormulaContext _localctx = new FormulaContext(_ctx, _parentState); + FormulaContext _prevctx = _localctx; + int _startState = 110; + enterRecursionRule(_localctx, 110, RULE_formula, _p); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(1480); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,203,_ctx) ) { + case 1: + { + _localctx = new NoContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + + setState(1198); + match(T__87); + setState(1199); + expression(0); + ((NoContext)_localctx).element = Formula.create(_localctx); + } + break; + case 2: + { + _localctx = new LoneContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1202); + match(T__88); + setState(1203); + expression(0); + ((LoneContext)_localctx).element = Formula.create(_localctx); + } + break; + case 3: + { + _localctx = new OneContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1206); + match(T__89); + setState(1207); + expression(0); + ((OneContext)_localctx).element = Formula.create(_localctx); + } + break; + case 4: + { + _localctx = new SomeContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1210); + match(T__90); + setState(1211); + expression(0); + ((SomeContext)_localctx).element = Formula.create(_localctx); + } + break; + case 5: + { + _localctx = new InContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1214); + ((InContext)_localctx).left = expression(0); + setState(1216); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__91 || _la==T__92) { + { + setState(1215); + ((InContext)_localctx).not = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__91 || _la==T__92) ) { + ((InContext)_localctx).not = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + + setState(1218); + match(T__93); + setState(1219); + ((InContext)_localctx).right = expression(0); + ((InContext)_localctx).element = Formula.create(_localctx); + } + break; + case 6: + { + _localctx = new EqualContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1222); + ((EqualContext)_localctx).left = expression(0); + setState(1224); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__91 || _la==T__92) { + { + setState(1223); + ((EqualContext)_localctx).not = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__91 || _la==T__92) ) { + ((EqualContext)_localctx).not = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + + setState(1226); + match(T__22); + setState(1227); + ((EqualContext)_localctx).right = expression(0); + ((EqualContext)_localctx).element = Formula.create(_localctx); + } + break; + case 7: + { + _localctx = new EqContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1230); + ((EqContext)_localctx).ileft = intExpression(0); + setState(1232); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__91 || _la==T__92) { + { + setState(1231); + ((EqContext)_localctx).not = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__91 || _la==T__92) ) { + ((EqContext)_localctx).not = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + + setState(1234); + match(T__22); + setState(1235); + ((EqContext)_localctx).iright = intExpression(0); + ((EqContext)_localctx).element = Formula.create(_localctx); + } + break; + case 8: + { + _localctx = new LtContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1238); + ((LtContext)_localctx).ileft = intExpression(0); + setState(1240); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__91 || _la==T__92) { + { + setState(1239); + ((LtContext)_localctx).not = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__91 || _la==T__92) ) { + ((LtContext)_localctx).not = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + + setState(1242); + match(T__64); + setState(1243); + ((LtContext)_localctx).iright = intExpression(0); + ((LtContext)_localctx).element = Formula.create(_localctx); + } + break; + case 9: + { + _localctx = new LteContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1246); + ((LteContext)_localctx).ileft = intExpression(0); + setState(1248); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__91 || _la==T__92) { + { + setState(1247); + ((LteContext)_localctx).not = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__91 || _la==T__92) ) { + ((LteContext)_localctx).not = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + + setState(1250); + match(T__94); + setState(1251); + ((LteContext)_localctx).iright = intExpression(0); + ((LteContext)_localctx).element = Formula.create(_localctx); + } + break; + case 10: + { + _localctx = new GtContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1254); + ((GtContext)_localctx).ileft = intExpression(0); + setState(1256); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__91 || _la==T__92) { + { + setState(1255); + ((GtContext)_localctx).not = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__91 || _la==T__92) ) { + ((GtContext)_localctx).not = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + + setState(1258); + match(T__65); + setState(1259); + ((GtContext)_localctx).iright = intExpression(0); + ((GtContext)_localctx).element = Formula.create(_localctx); + } + break; + case 11: + { + _localctx = new GteContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1262); + ((GteContext)_localctx).ileft = intExpression(0); + setState(1264); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__91 || _la==T__92) { + { + setState(1263); + ((GteContext)_localctx).not = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__91 || _la==T__92) ) { + ((GteContext)_localctx).not = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + + setState(1266); + match(T__95); + setState(1267); + ((GteContext)_localctx).iright = intExpression(0); + ((GteContext)_localctx).element = Formula.create(_localctx); + } + break; + case 12: + { + _localctx = new SumDeclarationContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + { + setState(1270); + match(T__96); + setState(1271); + quantifierDeclarations(); + setState(1272); + match(T__97); + setState(1273); + intExpression(0); + } + ((SumDeclarationContext)_localctx).element = Formula.create(_localctx); + } + break; + case 13: + { + _localctx = new AcyclicContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1277); + match(T__98); + setState(1278); + match(T__12); + setState(1279); + relationId(); + setState(1280); + match(T__13); + ((AcyclicContext)_localctx).element = Formula.create(_localctx); + } + break; + case 14: + { + _localctx = new FunctionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1283); + match(T__99); + setState(1284); + match(T__12); + setState(1285); + ((FunctionContext)_localctx).rel = relationId(); + setState(1286); + match(T__5); + setState(1287); + ((FunctionContext)_localctx).domain = expression(0); + setState(1288); + match(T__100); + setState(1293); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__1: + case T__11: + case T__20: + case T__21: + case T__23: + case T__24: + case T__25: + case T__26: + case T__27: + case T__29: + case T__30: + case T__31: + case T__32: + case T__33: + case T__34: + case T__35: + case T__37: + case T__39: + case T__41: + case T__43: + case T__44: + case T__46: + case T__47: + case T__48: + case T__50: + case T__52: + case T__56: + case T__57: + case T__58: + case T__60: + case T__61: + case T__62: + case T__63: + case T__75: + case T__76: + case T__77: + case T__78: + case T__80: + case T__82: + case T__83: + case T__89: + case T__106: + case T__107: + case T__113: + case T__114: + case T__118: + case T__119: + case T__120: + case T__121: + case T__131: + case T__132: + case T__133: + case IDENTIFIER: + { + setState(1290); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__89) { + { + setState(1289); + match(T__89); + } + } + + } + break; + case T__88: + { + setState(1292); + ((FunctionContext)_localctx).partial = match(T__88); + } + break; + default: + throw new NoViableAltException(this); + } + setState(1295); + ((FunctionContext)_localctx).range = expression(0); + setState(1296); + match(T__13); + ((FunctionContext)_localctx).element = Formula.create(_localctx); + } + break; + case 15: + { + _localctx = new TotalOrderContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1299); + match(T__101); + setState(1300); + match(T__12); + setState(1301); + ((TotalOrderContext)_localctx).rel = relationId(); + setState(1302); + match(T__2); + setState(1303); + ((TotalOrderContext)_localctx).ordered = relationId(); + setState(1304); + match(T__2); + setState(1305); + ((TotalOrderContext)_localctx).first = relationId(); + setState(1306); + match(T__2); + setState(1307); + ((TotalOrderContext)_localctx).last = relationId(); + setState(1308); + match(T__13); + ((TotalOrderContext)_localctx).element = Formula.create(_localctx); + } + break; + case 16: + { + _localctx = new NotContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1311); + ((NotContext)_localctx).op = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__91 || _la==T__92) ) { + ((NotContext)_localctx).op = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1312); + ((NotContext)_localctx).formula = formula(14); + ((NotContext)_localctx).element = Formula.create(_localctx); + } + break; + case 17: + { + _localctx = new ForAllContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + { + setState(1315); + match(T__111); + setState(1316); + quantifierDeclarations(); + setState(1337); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__97: + { + setState(1317); + match(T__97); + setState(1327); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,180,_ctx) ) { + case 1: + { + setState(1318); + ((ForAllContext)_localctx).formula = formula(0); + } + break; + case 2: + { + setState(1319); + match(T__1); + setState(1323); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 2)) & ~0x3f) == 0 && ((1L << (_la - 2)) & ((1L << (T__1 - 2)) | (1L << (T__11 - 2)) | (1L << (T__14 - 2)) | (1L << (T__15 - 2)) | (1L << (T__17 - 2)) | (1L << (T__20 - 2)) | (1L << (T__21 - 2)) | (1L << (T__23 - 2)) | (1L << (T__24 - 2)) | (1L << (T__25 - 2)) | (1L << (T__26 - 2)) | (1L << (T__27 - 2)) | (1L << (T__29 - 2)) | (1L << (T__30 - 2)) | (1L << (T__31 - 2)) | (1L << (T__32 - 2)) | (1L << (T__33 - 2)) | (1L << (T__34 - 2)) | (1L << (T__35 - 2)) | (1L << (T__37 - 2)) | (1L << (T__39 - 2)) | (1L << (T__41 - 2)) | (1L << (T__42 - 2)) | (1L << (T__43 - 2)) | (1L << (T__44 - 2)) | (1L << (T__46 - 2)) | (1L << (T__47 - 2)) | (1L << (T__48 - 2)) | (1L << (T__50 - 2)) | (1L << (T__52 - 2)) | (1L << (T__56 - 2)) | (1L << (T__57 - 2)) | (1L << (T__58 - 2)) | (1L << (T__60 - 2)) | (1L << (T__61 - 2)) | (1L << (T__62 - 2)) | (1L << (T__63 - 2)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__87 - 76)) | (1L << (T__88 - 76)) | (1L << (T__89 - 76)) | (1L << (T__90 - 76)) | (1L << (T__91 - 76)) | (1L << (T__92 - 76)) | (1L << (T__96 - 76)) | (1L << (T__98 - 76)) | (1L << (T__99 - 76)) | (1L << (T__101 - 76)) | (1L << (T__106 - 76)) | (1L << (T__107 - 76)) | (1L << (T__111 - 76)) | (1L << (T__112 - 76)) | (1L << (T__113 - 76)) | (1L << (T__114 - 76)) | (1L << (T__118 - 76)) | (1L << (T__119 - 76)) | (1L << (T__120 - 76)) | (1L << (T__121 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (INT - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + { + setState(1320); + ((ForAllContext)_localctx).formula = formula(0); + } + } + setState(1325); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1326); + match(T__3); + } + break; + } + } + break; + case T__1: + { + setState(1329); + match(T__1); + setState(1333); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 2)) & ~0x3f) == 0 && ((1L << (_la - 2)) & ((1L << (T__1 - 2)) | (1L << (T__11 - 2)) | (1L << (T__14 - 2)) | (1L << (T__15 - 2)) | (1L << (T__17 - 2)) | (1L << (T__20 - 2)) | (1L << (T__21 - 2)) | (1L << (T__23 - 2)) | (1L << (T__24 - 2)) | (1L << (T__25 - 2)) | (1L << (T__26 - 2)) | (1L << (T__27 - 2)) | (1L << (T__29 - 2)) | (1L << (T__30 - 2)) | (1L << (T__31 - 2)) | (1L << (T__32 - 2)) | (1L << (T__33 - 2)) | (1L << (T__34 - 2)) | (1L << (T__35 - 2)) | (1L << (T__37 - 2)) | (1L << (T__39 - 2)) | (1L << (T__41 - 2)) | (1L << (T__42 - 2)) | (1L << (T__43 - 2)) | (1L << (T__44 - 2)) | (1L << (T__46 - 2)) | (1L << (T__47 - 2)) | (1L << (T__48 - 2)) | (1L << (T__50 - 2)) | (1L << (T__52 - 2)) | (1L << (T__56 - 2)) | (1L << (T__57 - 2)) | (1L << (T__58 - 2)) | (1L << (T__60 - 2)) | (1L << (T__61 - 2)) | (1L << (T__62 - 2)) | (1L << (T__63 - 2)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__87 - 76)) | (1L << (T__88 - 76)) | (1L << (T__89 - 76)) | (1L << (T__90 - 76)) | (1L << (T__91 - 76)) | (1L << (T__92 - 76)) | (1L << (T__96 - 76)) | (1L << (T__98 - 76)) | (1L << (T__99 - 76)) | (1L << (T__101 - 76)) | (1L << (T__106 - 76)) | (1L << (T__107 - 76)) | (1L << (T__111 - 76)) | (1L << (T__112 - 76)) | (1L << (T__113 - 76)) | (1L << (T__114 - 76)) | (1L << (T__118 - 76)) | (1L << (T__119 - 76)) | (1L << (T__120 - 76)) | (1L << (T__121 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (INT - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + { + setState(1330); + ((ForAllContext)_localctx).formula = formula(0); + } + } + setState(1335); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1336); + match(T__3); + } + break; + default: + throw new NoViableAltException(this); + } + } + ((ForAllContext)_localctx).element = Formula.create(_localctx); + } + break; + case 18: + { + _localctx = new ForSomeContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + { + setState(1341); + match(T__90); + setState(1342); + quantifierDeclarations(); + setState(1363); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__97: + { + setState(1343); + match(T__97); + setState(1353); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,184,_ctx) ) { + case 1: + { + setState(1344); + ((ForSomeContext)_localctx).formula = formula(0); + } + break; + case 2: + { + setState(1345); + match(T__1); + setState(1349); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 2)) & ~0x3f) == 0 && ((1L << (_la - 2)) & ((1L << (T__1 - 2)) | (1L << (T__11 - 2)) | (1L << (T__14 - 2)) | (1L << (T__15 - 2)) | (1L << (T__17 - 2)) | (1L << (T__20 - 2)) | (1L << (T__21 - 2)) | (1L << (T__23 - 2)) | (1L << (T__24 - 2)) | (1L << (T__25 - 2)) | (1L << (T__26 - 2)) | (1L << (T__27 - 2)) | (1L << (T__29 - 2)) | (1L << (T__30 - 2)) | (1L << (T__31 - 2)) | (1L << (T__32 - 2)) | (1L << (T__33 - 2)) | (1L << (T__34 - 2)) | (1L << (T__35 - 2)) | (1L << (T__37 - 2)) | (1L << (T__39 - 2)) | (1L << (T__41 - 2)) | (1L << (T__42 - 2)) | (1L << (T__43 - 2)) | (1L << (T__44 - 2)) | (1L << (T__46 - 2)) | (1L << (T__47 - 2)) | (1L << (T__48 - 2)) | (1L << (T__50 - 2)) | (1L << (T__52 - 2)) | (1L << (T__56 - 2)) | (1L << (T__57 - 2)) | (1L << (T__58 - 2)) | (1L << (T__60 - 2)) | (1L << (T__61 - 2)) | (1L << (T__62 - 2)) | (1L << (T__63 - 2)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__87 - 76)) | (1L << (T__88 - 76)) | (1L << (T__89 - 76)) | (1L << (T__90 - 76)) | (1L << (T__91 - 76)) | (1L << (T__92 - 76)) | (1L << (T__96 - 76)) | (1L << (T__98 - 76)) | (1L << (T__99 - 76)) | (1L << (T__101 - 76)) | (1L << (T__106 - 76)) | (1L << (T__107 - 76)) | (1L << (T__111 - 76)) | (1L << (T__112 - 76)) | (1L << (T__113 - 76)) | (1L << (T__114 - 76)) | (1L << (T__118 - 76)) | (1L << (T__119 - 76)) | (1L << (T__120 - 76)) | (1L << (T__121 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (INT - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + { + setState(1346); + ((ForSomeContext)_localctx).formula = formula(0); + } + } + setState(1351); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1352); + match(T__3); + } + break; + } + } + break; + case T__1: + { + setState(1355); + match(T__1); + setState(1359); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 2)) & ~0x3f) == 0 && ((1L << (_la - 2)) & ((1L << (T__1 - 2)) | (1L << (T__11 - 2)) | (1L << (T__14 - 2)) | (1L << (T__15 - 2)) | (1L << (T__17 - 2)) | (1L << (T__20 - 2)) | (1L << (T__21 - 2)) | (1L << (T__23 - 2)) | (1L << (T__24 - 2)) | (1L << (T__25 - 2)) | (1L << (T__26 - 2)) | (1L << (T__27 - 2)) | (1L << (T__29 - 2)) | (1L << (T__30 - 2)) | (1L << (T__31 - 2)) | (1L << (T__32 - 2)) | (1L << (T__33 - 2)) | (1L << (T__34 - 2)) | (1L << (T__35 - 2)) | (1L << (T__37 - 2)) | (1L << (T__39 - 2)) | (1L << (T__41 - 2)) | (1L << (T__42 - 2)) | (1L << (T__43 - 2)) | (1L << (T__44 - 2)) | (1L << (T__46 - 2)) | (1L << (T__47 - 2)) | (1L << (T__48 - 2)) | (1L << (T__50 - 2)) | (1L << (T__52 - 2)) | (1L << (T__56 - 2)) | (1L << (T__57 - 2)) | (1L << (T__58 - 2)) | (1L << (T__60 - 2)) | (1L << (T__61 - 2)) | (1L << (T__62 - 2)) | (1L << (T__63 - 2)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__87 - 76)) | (1L << (T__88 - 76)) | (1L << (T__89 - 76)) | (1L << (T__90 - 76)) | (1L << (T__91 - 76)) | (1L << (T__92 - 76)) | (1L << (T__96 - 76)) | (1L << (T__98 - 76)) | (1L << (T__99 - 76)) | (1L << (T__101 - 76)) | (1L << (T__106 - 76)) | (1L << (T__107 - 76)) | (1L << (T__111 - 76)) | (1L << (T__112 - 76)) | (1L << (T__113 - 76)) | (1L << (T__114 - 76)) | (1L << (T__118 - 76)) | (1L << (T__119 - 76)) | (1L << (T__120 - 76)) | (1L << (T__121 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (INT - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + { + setState(1356); + ((ForSomeContext)_localctx).formula = formula(0); + } + } + setState(1361); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1362); + match(T__3); + } + break; + default: + throw new NoViableAltException(this); + } + } + ((ForSomeContext)_localctx).element = Formula.create(_localctx); + } + break; + case 19: + { + _localctx = new ForNoContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + { + setState(1367); + match(T__87); + setState(1368); + quantifierDeclarations(); + setState(1389); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__97: + { + setState(1369); + match(T__97); + setState(1379); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,188,_ctx) ) { + case 1: + { + setState(1370); + ((ForNoContext)_localctx).formula = formula(0); + } + break; + case 2: + { + setState(1371); + match(T__1); + setState(1375); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 2)) & ~0x3f) == 0 && ((1L << (_la - 2)) & ((1L << (T__1 - 2)) | (1L << (T__11 - 2)) | (1L << (T__14 - 2)) | (1L << (T__15 - 2)) | (1L << (T__17 - 2)) | (1L << (T__20 - 2)) | (1L << (T__21 - 2)) | (1L << (T__23 - 2)) | (1L << (T__24 - 2)) | (1L << (T__25 - 2)) | (1L << (T__26 - 2)) | (1L << (T__27 - 2)) | (1L << (T__29 - 2)) | (1L << (T__30 - 2)) | (1L << (T__31 - 2)) | (1L << (T__32 - 2)) | (1L << (T__33 - 2)) | (1L << (T__34 - 2)) | (1L << (T__35 - 2)) | (1L << (T__37 - 2)) | (1L << (T__39 - 2)) | (1L << (T__41 - 2)) | (1L << (T__42 - 2)) | (1L << (T__43 - 2)) | (1L << (T__44 - 2)) | (1L << (T__46 - 2)) | (1L << (T__47 - 2)) | (1L << (T__48 - 2)) | (1L << (T__50 - 2)) | (1L << (T__52 - 2)) | (1L << (T__56 - 2)) | (1L << (T__57 - 2)) | (1L << (T__58 - 2)) | (1L << (T__60 - 2)) | (1L << (T__61 - 2)) | (1L << (T__62 - 2)) | (1L << (T__63 - 2)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__87 - 76)) | (1L << (T__88 - 76)) | (1L << (T__89 - 76)) | (1L << (T__90 - 76)) | (1L << (T__91 - 76)) | (1L << (T__92 - 76)) | (1L << (T__96 - 76)) | (1L << (T__98 - 76)) | (1L << (T__99 - 76)) | (1L << (T__101 - 76)) | (1L << (T__106 - 76)) | (1L << (T__107 - 76)) | (1L << (T__111 - 76)) | (1L << (T__112 - 76)) | (1L << (T__113 - 76)) | (1L << (T__114 - 76)) | (1L << (T__118 - 76)) | (1L << (T__119 - 76)) | (1L << (T__120 - 76)) | (1L << (T__121 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (INT - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + { + setState(1372); + ((ForNoContext)_localctx).formula = formula(0); + } + } + setState(1377); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1378); + match(T__3); + } + break; + } + } + break; + case T__1: + { + setState(1381); + match(T__1); + setState(1385); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 2)) & ~0x3f) == 0 && ((1L << (_la - 2)) & ((1L << (T__1 - 2)) | (1L << (T__11 - 2)) | (1L << (T__14 - 2)) | (1L << (T__15 - 2)) | (1L << (T__17 - 2)) | (1L << (T__20 - 2)) | (1L << (T__21 - 2)) | (1L << (T__23 - 2)) | (1L << (T__24 - 2)) | (1L << (T__25 - 2)) | (1L << (T__26 - 2)) | (1L << (T__27 - 2)) | (1L << (T__29 - 2)) | (1L << (T__30 - 2)) | (1L << (T__31 - 2)) | (1L << (T__32 - 2)) | (1L << (T__33 - 2)) | (1L << (T__34 - 2)) | (1L << (T__35 - 2)) | (1L << (T__37 - 2)) | (1L << (T__39 - 2)) | (1L << (T__41 - 2)) | (1L << (T__42 - 2)) | (1L << (T__43 - 2)) | (1L << (T__44 - 2)) | (1L << (T__46 - 2)) | (1L << (T__47 - 2)) | (1L << (T__48 - 2)) | (1L << (T__50 - 2)) | (1L << (T__52 - 2)) | (1L << (T__56 - 2)) | (1L << (T__57 - 2)) | (1L << (T__58 - 2)) | (1L << (T__60 - 2)) | (1L << (T__61 - 2)) | (1L << (T__62 - 2)) | (1L << (T__63 - 2)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__87 - 76)) | (1L << (T__88 - 76)) | (1L << (T__89 - 76)) | (1L << (T__90 - 76)) | (1L << (T__91 - 76)) | (1L << (T__92 - 76)) | (1L << (T__96 - 76)) | (1L << (T__98 - 76)) | (1L << (T__99 - 76)) | (1L << (T__101 - 76)) | (1L << (T__106 - 76)) | (1L << (T__107 - 76)) | (1L << (T__111 - 76)) | (1L << (T__112 - 76)) | (1L << (T__113 - 76)) | (1L << (T__114 - 76)) | (1L << (T__118 - 76)) | (1L << (T__119 - 76)) | (1L << (T__120 - 76)) | (1L << (T__121 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (INT - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + { + setState(1382); + ((ForNoContext)_localctx).formula = formula(0); + } + } + setState(1387); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1388); + match(T__3); + } + break; + default: + throw new NoViableAltException(this); + } + } + ((ForNoContext)_localctx).element = Formula.create(_localctx); + } + break; + case 20: + { + _localctx = new ForOneContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + { + setState(1393); + match(T__89); + setState(1394); + quantifierDeclarations(); + setState(1415); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__97: + { + setState(1395); + match(T__97); + setState(1405); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,192,_ctx) ) { + case 1: + { + setState(1396); + ((ForOneContext)_localctx).formula = formula(0); + } + break; + case 2: + { + setState(1397); + match(T__1); + setState(1401); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 2)) & ~0x3f) == 0 && ((1L << (_la - 2)) & ((1L << (T__1 - 2)) | (1L << (T__11 - 2)) | (1L << (T__14 - 2)) | (1L << (T__15 - 2)) | (1L << (T__17 - 2)) | (1L << (T__20 - 2)) | (1L << (T__21 - 2)) | (1L << (T__23 - 2)) | (1L << (T__24 - 2)) | (1L << (T__25 - 2)) | (1L << (T__26 - 2)) | (1L << (T__27 - 2)) | (1L << (T__29 - 2)) | (1L << (T__30 - 2)) | (1L << (T__31 - 2)) | (1L << (T__32 - 2)) | (1L << (T__33 - 2)) | (1L << (T__34 - 2)) | (1L << (T__35 - 2)) | (1L << (T__37 - 2)) | (1L << (T__39 - 2)) | (1L << (T__41 - 2)) | (1L << (T__42 - 2)) | (1L << (T__43 - 2)) | (1L << (T__44 - 2)) | (1L << (T__46 - 2)) | (1L << (T__47 - 2)) | (1L << (T__48 - 2)) | (1L << (T__50 - 2)) | (1L << (T__52 - 2)) | (1L << (T__56 - 2)) | (1L << (T__57 - 2)) | (1L << (T__58 - 2)) | (1L << (T__60 - 2)) | (1L << (T__61 - 2)) | (1L << (T__62 - 2)) | (1L << (T__63 - 2)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__87 - 76)) | (1L << (T__88 - 76)) | (1L << (T__89 - 76)) | (1L << (T__90 - 76)) | (1L << (T__91 - 76)) | (1L << (T__92 - 76)) | (1L << (T__96 - 76)) | (1L << (T__98 - 76)) | (1L << (T__99 - 76)) | (1L << (T__101 - 76)) | (1L << (T__106 - 76)) | (1L << (T__107 - 76)) | (1L << (T__111 - 76)) | (1L << (T__112 - 76)) | (1L << (T__113 - 76)) | (1L << (T__114 - 76)) | (1L << (T__118 - 76)) | (1L << (T__119 - 76)) | (1L << (T__120 - 76)) | (1L << (T__121 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (INT - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + { + setState(1398); + ((ForOneContext)_localctx).formula = formula(0); + } + } + setState(1403); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1404); + match(T__3); + } + break; + } + } + break; + case T__1: + { + setState(1407); + match(T__1); + setState(1411); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 2)) & ~0x3f) == 0 && ((1L << (_la - 2)) & ((1L << (T__1 - 2)) | (1L << (T__11 - 2)) | (1L << (T__14 - 2)) | (1L << (T__15 - 2)) | (1L << (T__17 - 2)) | (1L << (T__20 - 2)) | (1L << (T__21 - 2)) | (1L << (T__23 - 2)) | (1L << (T__24 - 2)) | (1L << (T__25 - 2)) | (1L << (T__26 - 2)) | (1L << (T__27 - 2)) | (1L << (T__29 - 2)) | (1L << (T__30 - 2)) | (1L << (T__31 - 2)) | (1L << (T__32 - 2)) | (1L << (T__33 - 2)) | (1L << (T__34 - 2)) | (1L << (T__35 - 2)) | (1L << (T__37 - 2)) | (1L << (T__39 - 2)) | (1L << (T__41 - 2)) | (1L << (T__42 - 2)) | (1L << (T__43 - 2)) | (1L << (T__44 - 2)) | (1L << (T__46 - 2)) | (1L << (T__47 - 2)) | (1L << (T__48 - 2)) | (1L << (T__50 - 2)) | (1L << (T__52 - 2)) | (1L << (T__56 - 2)) | (1L << (T__57 - 2)) | (1L << (T__58 - 2)) | (1L << (T__60 - 2)) | (1L << (T__61 - 2)) | (1L << (T__62 - 2)) | (1L << (T__63 - 2)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__87 - 76)) | (1L << (T__88 - 76)) | (1L << (T__89 - 76)) | (1L << (T__90 - 76)) | (1L << (T__91 - 76)) | (1L << (T__92 - 76)) | (1L << (T__96 - 76)) | (1L << (T__98 - 76)) | (1L << (T__99 - 76)) | (1L << (T__101 - 76)) | (1L << (T__106 - 76)) | (1L << (T__107 - 76)) | (1L << (T__111 - 76)) | (1L << (T__112 - 76)) | (1L << (T__113 - 76)) | (1L << (T__114 - 76)) | (1L << (T__118 - 76)) | (1L << (T__119 - 76)) | (1L << (T__120 - 76)) | (1L << (T__121 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (INT - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + { + setState(1408); + ((ForOneContext)_localctx).formula = formula(0); + } + } + setState(1413); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1414); + match(T__3); + } + break; + default: + throw new NoViableAltException(this); + } + } + ((ForOneContext)_localctx).element = Formula.create(_localctx); + } + break; + case 21: + { + _localctx = new ForLoneContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + { + setState(1419); + match(T__88); + setState(1420); + quantifierDeclarations(); + setState(1441); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__97: + { + setState(1421); + match(T__97); + setState(1431); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,196,_ctx) ) { + case 1: + { + setState(1422); + ((ForLoneContext)_localctx).formula = formula(0); + } + break; + case 2: + { + setState(1423); + match(T__1); + setState(1427); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 2)) & ~0x3f) == 0 && ((1L << (_la - 2)) & ((1L << (T__1 - 2)) | (1L << (T__11 - 2)) | (1L << (T__14 - 2)) | (1L << (T__15 - 2)) | (1L << (T__17 - 2)) | (1L << (T__20 - 2)) | (1L << (T__21 - 2)) | (1L << (T__23 - 2)) | (1L << (T__24 - 2)) | (1L << (T__25 - 2)) | (1L << (T__26 - 2)) | (1L << (T__27 - 2)) | (1L << (T__29 - 2)) | (1L << (T__30 - 2)) | (1L << (T__31 - 2)) | (1L << (T__32 - 2)) | (1L << (T__33 - 2)) | (1L << (T__34 - 2)) | (1L << (T__35 - 2)) | (1L << (T__37 - 2)) | (1L << (T__39 - 2)) | (1L << (T__41 - 2)) | (1L << (T__42 - 2)) | (1L << (T__43 - 2)) | (1L << (T__44 - 2)) | (1L << (T__46 - 2)) | (1L << (T__47 - 2)) | (1L << (T__48 - 2)) | (1L << (T__50 - 2)) | (1L << (T__52 - 2)) | (1L << (T__56 - 2)) | (1L << (T__57 - 2)) | (1L << (T__58 - 2)) | (1L << (T__60 - 2)) | (1L << (T__61 - 2)) | (1L << (T__62 - 2)) | (1L << (T__63 - 2)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__87 - 76)) | (1L << (T__88 - 76)) | (1L << (T__89 - 76)) | (1L << (T__90 - 76)) | (1L << (T__91 - 76)) | (1L << (T__92 - 76)) | (1L << (T__96 - 76)) | (1L << (T__98 - 76)) | (1L << (T__99 - 76)) | (1L << (T__101 - 76)) | (1L << (T__106 - 76)) | (1L << (T__107 - 76)) | (1L << (T__111 - 76)) | (1L << (T__112 - 76)) | (1L << (T__113 - 76)) | (1L << (T__114 - 76)) | (1L << (T__118 - 76)) | (1L << (T__119 - 76)) | (1L << (T__120 - 76)) | (1L << (T__121 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (INT - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + { + setState(1424); + ((ForLoneContext)_localctx).formula = formula(0); + } + } + setState(1429); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1430); + match(T__3); + } + break; + } + } + break; + case T__1: + { + setState(1433); + match(T__1); + setState(1437); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 2)) & ~0x3f) == 0 && ((1L << (_la - 2)) & ((1L << (T__1 - 2)) | (1L << (T__11 - 2)) | (1L << (T__14 - 2)) | (1L << (T__15 - 2)) | (1L << (T__17 - 2)) | (1L << (T__20 - 2)) | (1L << (T__21 - 2)) | (1L << (T__23 - 2)) | (1L << (T__24 - 2)) | (1L << (T__25 - 2)) | (1L << (T__26 - 2)) | (1L << (T__27 - 2)) | (1L << (T__29 - 2)) | (1L << (T__30 - 2)) | (1L << (T__31 - 2)) | (1L << (T__32 - 2)) | (1L << (T__33 - 2)) | (1L << (T__34 - 2)) | (1L << (T__35 - 2)) | (1L << (T__37 - 2)) | (1L << (T__39 - 2)) | (1L << (T__41 - 2)) | (1L << (T__42 - 2)) | (1L << (T__43 - 2)) | (1L << (T__44 - 2)) | (1L << (T__46 - 2)) | (1L << (T__47 - 2)) | (1L << (T__48 - 2)) | (1L << (T__50 - 2)) | (1L << (T__52 - 2)) | (1L << (T__56 - 2)) | (1L << (T__57 - 2)) | (1L << (T__58 - 2)) | (1L << (T__60 - 2)) | (1L << (T__61 - 2)) | (1L << (T__62 - 2)) | (1L << (T__63 - 2)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__87 - 76)) | (1L << (T__88 - 76)) | (1L << (T__89 - 76)) | (1L << (T__90 - 76)) | (1L << (T__91 - 76)) | (1L << (T__92 - 76)) | (1L << (T__96 - 76)) | (1L << (T__98 - 76)) | (1L << (T__99 - 76)) | (1L << (T__101 - 76)) | (1L << (T__106 - 76)) | (1L << (T__107 - 76)) | (1L << (T__111 - 76)) | (1L << (T__112 - 76)) | (1L << (T__113 - 76)) | (1L << (T__114 - 76)) | (1L << (T__118 - 76)) | (1L << (T__119 - 76)) | (1L << (T__120 - 76)) | (1L << (T__121 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (INT - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + { + setState(1434); + ((ForLoneContext)_localctx).formula = formula(0); + } + } + setState(1439); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1440); + match(T__3); + } + break; + default: + throw new NoViableAltException(this); + } + } + ((ForLoneContext)_localctx).element = Formula.create(_localctx); + } + break; + case 22: + { + _localctx = new LetContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + { + setState(1445); + match(T__112); + setState(1446); + letDeclarations(); + setState(1467); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__97: + { + setState(1447); + match(T__97); + setState(1457); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,200,_ctx) ) { + case 1: + { + setState(1448); + ((LetContext)_localctx).formula = formula(0); + } + break; + case 2: + { + setState(1449); + match(T__1); + setState(1453); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 2)) & ~0x3f) == 0 && ((1L << (_la - 2)) & ((1L << (T__1 - 2)) | (1L << (T__11 - 2)) | (1L << (T__14 - 2)) | (1L << (T__15 - 2)) | (1L << (T__17 - 2)) | (1L << (T__20 - 2)) | (1L << (T__21 - 2)) | (1L << (T__23 - 2)) | (1L << (T__24 - 2)) | (1L << (T__25 - 2)) | (1L << (T__26 - 2)) | (1L << (T__27 - 2)) | (1L << (T__29 - 2)) | (1L << (T__30 - 2)) | (1L << (T__31 - 2)) | (1L << (T__32 - 2)) | (1L << (T__33 - 2)) | (1L << (T__34 - 2)) | (1L << (T__35 - 2)) | (1L << (T__37 - 2)) | (1L << (T__39 - 2)) | (1L << (T__41 - 2)) | (1L << (T__42 - 2)) | (1L << (T__43 - 2)) | (1L << (T__44 - 2)) | (1L << (T__46 - 2)) | (1L << (T__47 - 2)) | (1L << (T__48 - 2)) | (1L << (T__50 - 2)) | (1L << (T__52 - 2)) | (1L << (T__56 - 2)) | (1L << (T__57 - 2)) | (1L << (T__58 - 2)) | (1L << (T__60 - 2)) | (1L << (T__61 - 2)) | (1L << (T__62 - 2)) | (1L << (T__63 - 2)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__87 - 76)) | (1L << (T__88 - 76)) | (1L << (T__89 - 76)) | (1L << (T__90 - 76)) | (1L << (T__91 - 76)) | (1L << (T__92 - 76)) | (1L << (T__96 - 76)) | (1L << (T__98 - 76)) | (1L << (T__99 - 76)) | (1L << (T__101 - 76)) | (1L << (T__106 - 76)) | (1L << (T__107 - 76)) | (1L << (T__111 - 76)) | (1L << (T__112 - 76)) | (1L << (T__113 - 76)) | (1L << (T__114 - 76)) | (1L << (T__118 - 76)) | (1L << (T__119 - 76)) | (1L << (T__120 - 76)) | (1L << (T__121 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (INT - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + { + setState(1450); + ((LetContext)_localctx).formula = formula(0); + } + } + setState(1455); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1456); + match(T__3); + } + break; + } + } + break; + case T__1: + { + setState(1459); + match(T__1); + setState(1463); + _errHandler.sync(this); + _la = _input.LA(1); + while (((((_la - 2)) & ~0x3f) == 0 && ((1L << (_la - 2)) & ((1L << (T__1 - 2)) | (1L << (T__11 - 2)) | (1L << (T__14 - 2)) | (1L << (T__15 - 2)) | (1L << (T__17 - 2)) | (1L << (T__20 - 2)) | (1L << (T__21 - 2)) | (1L << (T__23 - 2)) | (1L << (T__24 - 2)) | (1L << (T__25 - 2)) | (1L << (T__26 - 2)) | (1L << (T__27 - 2)) | (1L << (T__29 - 2)) | (1L << (T__30 - 2)) | (1L << (T__31 - 2)) | (1L << (T__32 - 2)) | (1L << (T__33 - 2)) | (1L << (T__34 - 2)) | (1L << (T__35 - 2)) | (1L << (T__37 - 2)) | (1L << (T__39 - 2)) | (1L << (T__41 - 2)) | (1L << (T__42 - 2)) | (1L << (T__43 - 2)) | (1L << (T__44 - 2)) | (1L << (T__46 - 2)) | (1L << (T__47 - 2)) | (1L << (T__48 - 2)) | (1L << (T__50 - 2)) | (1L << (T__52 - 2)) | (1L << (T__56 - 2)) | (1L << (T__57 - 2)) | (1L << (T__58 - 2)) | (1L << (T__60 - 2)) | (1L << (T__61 - 2)) | (1L << (T__62 - 2)) | (1L << (T__63 - 2)))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (T__75 - 76)) | (1L << (T__76 - 76)) | (1L << (T__77 - 76)) | (1L << (T__78 - 76)) | (1L << (T__80 - 76)) | (1L << (T__82 - 76)) | (1L << (T__83 - 76)) | (1L << (T__87 - 76)) | (1L << (T__88 - 76)) | (1L << (T__89 - 76)) | (1L << (T__90 - 76)) | (1L << (T__91 - 76)) | (1L << (T__92 - 76)) | (1L << (T__96 - 76)) | (1L << (T__98 - 76)) | (1L << (T__99 - 76)) | (1L << (T__101 - 76)) | (1L << (T__106 - 76)) | (1L << (T__107 - 76)) | (1L << (T__111 - 76)) | (1L << (T__112 - 76)) | (1L << (T__113 - 76)) | (1L << (T__114 - 76)) | (1L << (T__118 - 76)) | (1L << (T__119 - 76)) | (1L << (T__120 - 76)) | (1L << (T__121 - 76)) | (1L << (T__131 - 76)) | (1L << (T__132 - 76)) | (1L << (T__133 - 76)) | (1L << (INT - 76)) | (1L << (IDENTIFIER - 76)))) != 0)) { + { + { + setState(1460); + ((LetContext)_localctx).formula = formula(0); + } + } + setState(1465); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1466); + match(T__3); + } + break; + default: + throw new NoViableAltException(this); + } + } + ((LetContext)_localctx).element = Formula.create(_localctx); + } + break; + case 23: + { + _localctx = new TrueContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1471); + match(T__14); + ((TrueContext)_localctx).element = Formula.create(_localctx); + } + break; + case 24: + { + _localctx = new FalseContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1473); + match(T__15); + ((FalseContext)_localctx).element = Formula.create(_localctx); + } + break; + case 25: + { + _localctx = new F_paranthesisContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1475); + match(T__48); + setState(1476); + ((F_paranthesisContext)_localctx).formula = formula(0); + setState(1477); + match(T__49); + ((F_paranthesisContext)_localctx).element = ((F_paranthesisContext)_localctx).formula.element; + } + break; + } + _ctx.stop = _input.LT(-1); + setState(1504); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,205,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + if ( _parseListeners!=null ) triggerExitRuleEvent(); + _prevctx = _localctx; + { + setState(1502); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,204,_ctx) ) { + case 1: + { + _localctx = new AndContext(new FormulaContext(_parentctx, _parentState)); + ((AndContext)_localctx).fleft = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_formula); + setState(1482); + if (!(precpred(_ctx, 13))) throw new FailedPredicateException(this, "precpred(_ctx, 13)"); + setState(1483); + ((AndContext)_localctx).op = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__102 || _la==T__103) ) { + ((AndContext)_localctx).op = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1484); + ((AndContext)_localctx).fright = ((AndContext)_localctx).formula = formula(14); + ((AndContext)_localctx).element = Formula.create(_localctx); + } + break; + case 2: + { + _localctx = new OrContext(new FormulaContext(_parentctx, _parentState)); + ((OrContext)_localctx).fleft = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_formula); + setState(1487); + if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)"); + setState(1488); + ((OrContext)_localctx).op = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__104 || _la==T__105) ) { + ((OrContext)_localctx).op = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1489); + ((OrContext)_localctx).fright = ((OrContext)_localctx).formula = formula(13); + ((OrContext)_localctx).element = Formula.create(_localctx); + } + break; + case 3: + { + _localctx = new ImpliesContext(new FormulaContext(_parentctx, _parentState)); + ((ImpliesContext)_localctx).fleft = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_formula); + setState(1492); + if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)"); + setState(1493); + ((ImpliesContext)_localctx).op = _input.LT(1); + _la = _input.LA(1); + if ( !(((((_la - 107)) & ~0x3f) == 0 && ((1L << (_la - 107)) & ((1L << (T__106 - 107)) | (1L << (T__107 - 107)) | (1L << (T__108 - 107)))) != 0)) ) { + ((ImpliesContext)_localctx).op = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1494); + ((ImpliesContext)_localctx).fright = ((ImpliesContext)_localctx).formula = formula(11); + ((ImpliesContext)_localctx).element = Formula.create(_localctx); + } + break; + case 4: + { + _localctx = new IffContext(new FormulaContext(_parentctx, _parentState)); + ((IffContext)_localctx).fleft = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_formula); + setState(1497); + if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); + setState(1498); + ((IffContext)_localctx).op = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__109 || _la==T__110) ) { + ((IffContext)_localctx).op = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1499); + ((IffContext)_localctx).fright = ((IffContext)_localctx).formula = formula(10); + ((IffContext)_localctx).element = Formula.create(_localctx); + } + break; + } + } + } + setState(1506); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,205,_ctx); + } + } + _ctx.stop = _input.LT(-1); + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + unrollRecursionContexts(_parentctx); + } + return _localctx; + } + + public static class ExpressionContext extends ParserRuleContext { + public Expression element; + public ExpressionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_expression; } + + public ExpressionContext() { } + public void copyFrom(ExpressionContext ctx) { + super.copyFrom(ctx); + this.element = ctx.element; + } + } + public static class ProductContext extends ExpressionContext { + public ExpressionContext left; + public MultContext leftMult; + public MultContext rightMult; + public ExpressionContext right; + public ExpressionContext expression; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public List mult() { + return getRuleContexts(MultContext.class); + } + public MultContext mult(int i) { + return getRuleContext(MultContext.class,i); + } + public ProductContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterProduct(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitProduct(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitProduct(this); + else return visitor.visitChildren(this); + } + } + public static class NoneContext extends ExpressionContext { + public NoneContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterNone(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitNone(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitNone(this); + else return visitor.visitChildren(this); + } + } + public static class UnionContext extends ExpressionContext { + public ExpressionContext left; + public ExpressionContext right; + public ExpressionContext expression; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public UnionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterUnion(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitUnion(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitUnion(this); + else return visitor.visitChildren(this); + } + } + public static class ComprehensionContext extends ExpressionContext { + public ComprehensionDeclarationsContext comprehensionDeclarations() { + return getRuleContext(ComprehensionDeclarationsContext.class,0); + } + public FormulaContext formula() { + return getRuleContext(FormulaContext.class,0); + } + public ComprehensionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterComprehension(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitComprehension(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitComprehension(this); + else return visitor.visitChildren(this); + } + } + public static class UnivContext extends ExpressionContext { + public UnivContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterUniv(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitUniv(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitUniv(this); + else return visitor.visitChildren(this); + } + } + public static class ReflexiveContext extends ExpressionContext { + public ExpressionContext expression; + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public ReflexiveContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterReflexive(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitReflexive(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitReflexive(this); + else return visitor.visitChildren(this); + } + } + public static class E_paranthesisContext extends ExpressionContext { + public ExpressionContext expression; + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public E_paranthesisContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterE_paranthesis(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitE_paranthesis(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitE_paranthesis(this); + else return visitor.visitChildren(this); + } + } + public static class IdenContext extends ExpressionContext { + public IdenContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterIden(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitIden(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitIden(this); + else return visitor.visitChildren(this); + } + } + public static class IntsContext extends ExpressionContext { + public IntsContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterInts(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitInts(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitInts(this); + else return visitor.visitChildren(this); + } + } + public static class IntersectionContext extends ExpressionContext { + public ExpressionContext left; + public ExpressionContext right; + public ExpressionContext expression; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public IntersectionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterIntersection(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitIntersection(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitIntersection(this); + else return visitor.visitChildren(this); + } + } + public static class DifferenceContext extends ExpressionContext { + public ExpressionContext left; + public ExpressionContext right; + public ExpressionContext expression; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public DifferenceContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterDifference(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitDifference(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitDifference(this); + else return visitor.visitChildren(this); + } + } + public static class TransposeContext extends ExpressionContext { + public ExpressionContext expression; + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public TransposeContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterTranspose(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitTranspose(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitTranspose(this); + else return visitor.visitChildren(this); + } + } + public static class JoinContext extends ExpressionContext { + public ExpressionContext left; + public ExpressionContext right; + public ExpressionContext expression; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public JoinContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterJoin(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitJoin(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitJoin(this); + else return visitor.visitChildren(this); + } + } + public static class OverrideContext extends ExpressionContext { + public ExpressionContext left; + public ExpressionContext right; + public ExpressionContext expression; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public OverrideContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterOverride(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitOverride(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitOverride(this); + else return visitor.visitChildren(this); + } + } + public static class IfExpressionContext extends ExpressionContext { + public Token op; + public FormulaContext condition; + public ExpressionContext thenExpr; + public ExpressionContext expression; + public ExpressionContext elseExpr; + public FormulaContext formula() { + return getRuleContext(FormulaContext.class,0); + } + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public IfExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterIfExpression(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitIfExpression(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitIfExpression(this); + else return visitor.visitChildren(this); + } + } + public static class ClosureContext extends ExpressionContext { + public ExpressionContext expression; + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public ClosureContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterClosure(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitClosure(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitClosure(this); + else return visitor.visitChildren(this); + } + } + public static class TypeRefContext extends ExpressionContext { + public PathNameContext pathName() { + return getRuleContext(PathNameContext.class,0); + } + public TypeRefContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterTypeRef(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitTypeRef(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitTypeRef(this); + else return visitor.visitChildren(this); + } + } + public static class BoxJoinContext extends ExpressionContext { + public ExpressionContext right; + public ExpressionContext left; + public ExpressionContext expression; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public BoxJoinContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterBoxJoin(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitBoxJoin(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitBoxJoin(this); + else return visitor.visitChildren(this); + } + } + + public final ExpressionContext expression() throws RecognitionException { + return expression(0); + } + + private ExpressionContext expression(int _p) throws RecognitionException { + ParserRuleContext _parentctx = _ctx; + int _parentState = getState(); + ExpressionContext _localctx = new ExpressionContext(_ctx, _parentState); + ExpressionContext _prevctx = _localctx; + int _startState = 112; + enterRecursionRule(_localctx, 112, RULE_expression, _p); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(1551); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__113: + { + _localctx = new TransposeContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + + setState(1508); + match(T__113); + setState(1509); + ((TransposeContext)_localctx).expression = expression(18); + ((TransposeContext)_localctx).element = Expression.create(_localctx); + } + break; + case T__114: + { + _localctx = new ClosureContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1512); + match(T__114); + setState(1513); + ((ClosureContext)_localctx).expression = expression(17); + ((ClosureContext)_localctx).element = Expression.create(_localctx); + } + break; + case T__52: + { + _localctx = new ReflexiveContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1516); + match(T__52); + setState(1517); + ((ReflexiveContext)_localctx).expression = expression(16); + ((ReflexiveContext)_localctx).element = Expression.create(_localctx); + } + break; + case T__1: + { + _localctx = new ComprehensionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1520); + match(T__1); + setState(1521); + comprehensionDeclarations(); + setState(1522); + match(T__97); + setState(1523); + formula(0); + setState(1524); + match(T__3); + ((ComprehensionContext)_localctx).element = Expression.create(_localctx); + } + break; + case T__106: + case T__107: + { + _localctx = new IfExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1527); + ((IfExpressionContext)_localctx).op = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__106 || _la==T__107) ) { + ((IfExpressionContext)_localctx).op = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1528); + ((IfExpressionContext)_localctx).condition = formula(0); + setState(1529); + match(T__116); + setState(1530); + ((IfExpressionContext)_localctx).thenExpr = ((IfExpressionContext)_localctx).expression = expression(0); + setState(1531); + match(T__117); + setState(1532); + ((IfExpressionContext)_localctx).elseExpr = ((IfExpressionContext)_localctx).expression = expression(7); + ((IfExpressionContext)_localctx).element = Expression.create(_localctx); + } + break; + case T__118: + { + _localctx = new IdenContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1535); + match(T__118); + ((IdenContext)_localctx).element = Expression.create(_localctx); + } + break; + case T__119: + { + _localctx = new NoneContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1537); + match(T__119); + ((NoneContext)_localctx).element = Expression.create(_localctx); + } + break; + case T__120: + { + _localctx = new UnivContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1539); + match(T__120); + ((UnivContext)_localctx).element = Expression.create(_localctx); + } + break; + case T__121: + { + _localctx = new IntsContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1541); + match(T__121); + ((IntsContext)_localctx).element = Expression.create(_localctx); + } + break; + case T__48: + { + _localctx = new E_paranthesisContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1543); + match(T__48); + setState(1544); + ((E_paranthesisContext)_localctx).expression = expression(0); + setState(1545); + match(T__49); + ((E_paranthesisContext)_localctx).element = ((E_paranthesisContext)_localctx).expression.element; + } + break; + case T__11: + case T__20: + case T__21: + case T__23: + case T__24: + case T__25: + case T__26: + case T__27: + case T__29: + case T__30: + case T__31: + case T__32: + case T__33: + case T__34: + case T__35: + case T__37: + case T__39: + case T__41: + case T__43: + case T__44: + case T__46: + case T__47: + case T__50: + case T__56: + case T__57: + case T__58: + case T__60: + case T__61: + case T__62: + case T__63: + case T__75: + case T__76: + case T__77: + case T__78: + case T__80: + case T__82: + case T__83: + case T__131: + case T__132: + case T__133: + case IDENTIFIER: + { + _localctx = new TypeRefContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1548); + pathName(_localctx.element); + ((TypeRefContext)_localctx).element = Expression.create(_localctx); + } + break; + default: + throw new NoViableAltException(this); + } + _ctx.stop = _input.LT(-1); + setState(1597); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,210,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + if ( _parseListeners!=null ) triggerExitRuleEvent(); + _prevctx = _localctx; + { + setState(1595); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,209,_ctx) ) { + case 1: + { + _localctx = new UnionContext(new ExpressionContext(_parentctx, _parentState)); + ((UnionContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1553); + if (!(precpred(_ctx, 15))) throw new FailedPredicateException(this, "precpred(_ctx, 15)"); + setState(1554); + match(T__16); + setState(1555); + ((UnionContext)_localctx).right = ((UnionContext)_localctx).expression = expression(16); + ((UnionContext)_localctx).element = Expression.create(_localctx); + } + break; + case 2: + { + _localctx = new IntersectionContext(new ExpressionContext(_parentctx, _parentState)); + ((IntersectionContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1558); + if (!(precpred(_ctx, 14))) throw new FailedPredicateException(this, "precpred(_ctx, 14)"); + setState(1559); + match(T__66); + setState(1560); + ((IntersectionContext)_localctx).right = ((IntersectionContext)_localctx).expression = expression(15); + ((IntersectionContext)_localctx).element = Expression.create(_localctx); + } + break; + case 3: + { + _localctx = new DifferenceContext(new ExpressionContext(_parentctx, _parentState)); + ((DifferenceContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1563); + if (!(precpred(_ctx, 13))) throw new FailedPredicateException(this, "precpred(_ctx, 13)"); + setState(1564); + match(T__17); + setState(1565); + ((DifferenceContext)_localctx).right = ((DifferenceContext)_localctx).expression = expression(14); + ((DifferenceContext)_localctx).element = Expression.create(_localctx); + } + break; + case 4: + { + _localctx = new JoinContext(new ExpressionContext(_parentctx, _parentState)); + ((JoinContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1568); + if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)"); + setState(1569); + match(T__18); + setState(1570); + ((JoinContext)_localctx).right = ((JoinContext)_localctx).expression = expression(13); + ((JoinContext)_localctx).element = Expression.create(_localctx); + } + break; + case 5: + { + _localctx = new ProductContext(new ExpressionContext(_parentctx, _parentState)); + ((ProductContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1573); + if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); + setState(1575); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 89)) & ~0x3f) == 0 && ((1L << (_la - 89)) & ((1L << (T__88 - 89)) | (1L << (T__89 - 89)) | (1L << (T__90 - 89)) | (1L << (T__130 - 89)))) != 0)) { + { + setState(1574); + ((ProductContext)_localctx).leftMult = mult(); + } + } + + setState(1577); + match(T__100); + setState(1579); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 89)) & ~0x3f) == 0 && ((1L << (_la - 89)) & ((1L << (T__88 - 89)) | (1L << (T__89 - 89)) | (1L << (T__90 - 89)) | (1L << (T__130 - 89)))) != 0)) { + { + setState(1578); + ((ProductContext)_localctx).rightMult = mult(); + } + } + + setState(1581); + ((ProductContext)_localctx).right = ((ProductContext)_localctx).expression = expression(10); + ((ProductContext)_localctx).element = Expression.create(_localctx); + } + break; + case 6: + { + _localctx = new OverrideContext(new ExpressionContext(_parentctx, _parentState)); + ((OverrideContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1584); + if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); + setState(1585); + match(T__115); + setState(1586); + ((OverrideContext)_localctx).right = ((OverrideContext)_localctx).expression = expression(10); + ((OverrideContext)_localctx).element = Expression.create(_localctx); + } + break; + case 7: + { + _localctx = new BoxJoinContext(new ExpressionContext(_parentctx, _parentState)); + ((BoxJoinContext)_localctx).right = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(1589); + if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)"); + setState(1590); + match(T__12); + setState(1591); + ((BoxJoinContext)_localctx).left = ((BoxJoinContext)_localctx).expression = expression(0); + setState(1592); + match(T__13); + ((BoxJoinContext)_localctx).element = Expression.create(_localctx); + } + break; + } + } + } + setState(1599); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,210,_ctx); + } + } + _ctx.stop = _input.LT(-1); + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + unrollRecursionContexts(_parentctx); + } + return _localctx; + } + + public static class IntExpressionContext extends ParserRuleContext { + public IntExpression element; + public IntExpressionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_intExpression; } + + public IntExpressionContext() { } + public void copyFrom(IntExpressionContext ctx) { + super.copyFrom(ctx); + this.element = ctx.element; + } + } + public static class MinusContext extends IntExpressionContext { + public IntExpressionContext ileft; + public IntExpressionContext iright; + public IntExpressionContext intExpression; + public List intExpression() { + return getRuleContexts(IntExpressionContext.class); + } + public IntExpressionContext intExpression(int i) { + return getRuleContext(IntExpressionContext.class,i); + } + public MinusContext(IntExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterMinus(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitMinus(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitMinus(this); + else return visitor.visitChildren(this); + } + } + public static class IntConstantContext extends IntExpressionContext { + public Token sign; + public TerminalNode INT() { return getToken(AlloyInEcoreParser.INT, 0); } + public IntConstantContext(IntExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterIntConstant(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitIntConstant(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitIntConstant(this); + else return visitor.visitChildren(this); + } + } + public static class I_paranthesisContext extends IntExpressionContext { + public IntExpressionContext intExpression; + public IntExpressionContext intExpression() { + return getRuleContext(IntExpressionContext.class,0); + } + public I_paranthesisContext(IntExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterI_paranthesis(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitI_paranthesis(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitI_paranthesis(this); + else return visitor.visitChildren(this); + } + } + public static class IfIntExpressionContext extends IntExpressionContext { + public Token op; + public FormulaContext condition; + public IntExpressionContext thenExpr; + public IntExpressionContext intExpression; + public IntExpressionContext elseExpr; + public FormulaContext formula() { + return getRuleContext(FormulaContext.class,0); + } + public List intExpression() { + return getRuleContexts(IntExpressionContext.class); + } + public IntExpressionContext intExpression(int i) { + return getRuleContext(IntExpressionContext.class,i); + } + public IfIntExpressionContext(IntExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterIfIntExpression(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitIfIntExpression(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitIfIntExpression(this); + else return visitor.visitChildren(this); + } + } + public static class CountContext extends IntExpressionContext { + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public CountContext(IntExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterCount(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitCount(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitCount(this); + else return visitor.visitChildren(this); + } + } + public static class SumContext extends IntExpressionContext { + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public SumContext(IntExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterSum(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitSum(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitSum(this); + else return visitor.visitChildren(this); + } + } + public static class DivideContext extends IntExpressionContext { + public IntExpressionContext ileft; + public IntExpressionContext iright; + public IntExpressionContext intExpression; + public List intExpression() { + return getRuleContexts(IntExpressionContext.class); + } + public IntExpressionContext intExpression(int i) { + return getRuleContext(IntExpressionContext.class,i); + } + public DivideContext(IntExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterDivide(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitDivide(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitDivide(this); + else return visitor.visitChildren(this); + } + } + public static class MultiplyContext extends IntExpressionContext { + public IntExpressionContext ileft; + public IntExpressionContext iright; + public IntExpressionContext intExpression; + public List intExpression() { + return getRuleContexts(IntExpressionContext.class); + } + public IntExpressionContext intExpression(int i) { + return getRuleContext(IntExpressionContext.class,i); + } + public MultiplyContext(IntExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterMultiply(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitMultiply(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitMultiply(this); + else return visitor.visitChildren(this); + } + } + public static class ModuloContext extends IntExpressionContext { + public IntExpressionContext ileft; + public IntExpressionContext iright; + public IntExpressionContext intExpression; + public List intExpression() { + return getRuleContexts(IntExpressionContext.class); + } + public IntExpressionContext intExpression(int i) { + return getRuleContext(IntExpressionContext.class,i); + } + public ModuloContext(IntExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterModulo(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitModulo(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitModulo(this); + else return visitor.visitChildren(this); + } + } + public static class PlusContext extends IntExpressionContext { + public IntExpressionContext ileft; + public IntExpressionContext iright; + public IntExpressionContext intExpression; + public List intExpression() { + return getRuleContexts(IntExpressionContext.class); + } + public IntExpressionContext intExpression(int i) { + return getRuleContext(IntExpressionContext.class,i); + } + public PlusContext(IntExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterPlus(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitPlus(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitPlus(this); + else return visitor.visitChildren(this); + } + } + + public final IntExpressionContext intExpression() throws RecognitionException { + return intExpression(0); + } + + private IntExpressionContext intExpression(int _p) throws RecognitionException { + ParserRuleContext _parentctx = _ctx; + int _parentState = getState(); + IntExpressionContext _localctx = new IntExpressionContext(_ctx, _parentState); + IntExpressionContext _prevctx = _localctx; + int _startState = 114; + enterRecursionRule(_localctx, 114, RULE_intExpression, _p); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(1627); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__106: + case T__107: + { + _localctx = new IfIntExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + + setState(1601); + ((IfIntExpressionContext)_localctx).op = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__106 || _la==T__107) ) { + ((IfIntExpressionContext)_localctx).op = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1602); + ((IfIntExpressionContext)_localctx).condition = formula(0); + setState(1603); + match(T__116); + setState(1604); + ((IfIntExpressionContext)_localctx).thenExpr = ((IfIntExpressionContext)_localctx).intExpression = intExpression(0); + setState(1605); + match(T__117); + setState(1606); + ((IfIntExpressionContext)_localctx).elseExpr = ((IfIntExpressionContext)_localctx).intExpression = intExpression(10); + ((IfIntExpressionContext)_localctx).element = IntExpression.create(_localctx); + } + break; + case T__96: + { + _localctx = new SumContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1609); + match(T__96); + setState(1610); + expression(0); + ((SumContext)_localctx).element = IntExpression.create(_localctx); + } + break; + case T__42: + { + _localctx = new CountContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1613); + match(T__42); + setState(1614); + expression(0); + ((CountContext)_localctx).element = IntExpression.create(_localctx); + } + break; + case T__17: + case INT: + { + _localctx = new IntConstantContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1618); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__17) { + { + setState(1617); + ((IntConstantContext)_localctx).sign = match(T__17); + } + } + + setState(1620); + match(INT); + ((IntConstantContext)_localctx).element = IntExpression.create(_localctx); + } + break; + case T__48: + { + _localctx = new I_paranthesisContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(1622); + match(T__48); + setState(1623); + ((I_paranthesisContext)_localctx).intExpression = intExpression(0); + setState(1624); + match(T__49); + ((I_paranthesisContext)_localctx).element = ((I_paranthesisContext)_localctx).intExpression.element; + } + break; + default: + throw new NoViableAltException(this); + } + _ctx.stop = _input.LT(-1); + setState(1656); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,214,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + if ( _parseListeners!=null ) triggerExitRuleEvent(); + _prevctx = _localctx; + { + setState(1654); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,213,_ctx) ) { + case 1: + { + _localctx = new PlusContext(new IntExpressionContext(_parentctx, _parentState)); + ((PlusContext)_localctx).ileft = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_intExpression); + setState(1629); + if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); + setState(1630); + _la = _input.LA(1); + if ( !(_la==T__16 || _la==T__122) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1631); + ((PlusContext)_localctx).iright = ((PlusContext)_localctx).intExpression = intExpression(8); + ((PlusContext)_localctx).element = IntExpression.create(_localctx); + } + break; + case 2: + { + _localctx = new MinusContext(new IntExpressionContext(_parentctx, _parentState)); + ((MinusContext)_localctx).ileft = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_intExpression); + setState(1634); + if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)"); + setState(1635); + _la = _input.LA(1); + if ( !(_la==T__17 || _la==T__123) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1636); + ((MinusContext)_localctx).iright = ((MinusContext)_localctx).intExpression = intExpression(7); + ((MinusContext)_localctx).element = IntExpression.create(_localctx); + } + break; + case 3: + { + _localctx = new MultiplyContext(new IntExpressionContext(_parentctx, _parentState)); + ((MultiplyContext)_localctx).ileft = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_intExpression); + setState(1639); + if (!(precpred(_ctx, 5))) throw new FailedPredicateException(this, "precpred(_ctx, 5)"); + setState(1640); + _la = _input.LA(1); + if ( !(_la==T__52 || _la==T__124) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1641); + ((MultiplyContext)_localctx).iright = ((MultiplyContext)_localctx).intExpression = intExpression(6); + ((MultiplyContext)_localctx).element = IntExpression.create(_localctx); + } + break; + case 4: + { + _localctx = new DivideContext(new IntExpressionContext(_parentctx, _parentState)); + ((DivideContext)_localctx).ileft = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_intExpression); + setState(1644); + if (!(precpred(_ctx, 4))) throw new FailedPredicateException(this, "precpred(_ctx, 4)"); + setState(1645); + _la = _input.LA(1); + if ( !(_la==T__125 || _la==T__126) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1646); + ((DivideContext)_localctx).iright = ((DivideContext)_localctx).intExpression = intExpression(5); + ((DivideContext)_localctx).element = IntExpression.create(_localctx); + } + break; + case 5: + { + _localctx = new ModuloContext(new IntExpressionContext(_parentctx, _parentState)); + ((ModuloContext)_localctx).ileft = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_intExpression); + setState(1649); + if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)"); + setState(1650); + _la = _input.LA(1); + if ( !(_la==T__127 || _la==T__128) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(1651); + ((ModuloContext)_localctx).iright = ((ModuloContext)_localctx).intExpression = intExpression(4); + ((ModuloContext)_localctx).element = IntExpression.create(_localctx); + } + break; + } + } + } + setState(1658); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,214,_ctx); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + unrollRecursionContexts(_parentctx); + } + return _localctx; + } + + public static class QuantifierDeclarationsContext extends ParserRuleContext { + public List elements; + public List quantifierDeclaration() { + return getRuleContexts(QuantifierDeclarationContext.class); + } + public QuantifierDeclarationContext quantifierDeclaration(int i) { + return getRuleContext(QuantifierDeclarationContext.class,i); + } + public QuantifierDeclarationsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_quantifierDeclarations; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterQuantifierDeclarations(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitQuantifierDeclarations(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitQuantifierDeclarations(this); + else return visitor.visitChildren(this); + } + } + + public final QuantifierDeclarationsContext quantifierDeclarations() throws RecognitionException { + QuantifierDeclarationsContext _localctx = new QuantifierDeclarationsContext(_ctx, getState()); + enterRule(_localctx, 116, RULE_quantifierDeclarations); + ((QuantifierDeclarationsContext)_localctx).elements = new ArrayList<>(); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1659); + quantifierDeclaration(); + setState(1664); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(1660); + match(T__2); + setState(1661); + quantifierDeclaration(); + } + } + setState(1666); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + _ctx.stop = _input.LT(-1); + for(QuantifierDeclarationContext ctx: _localctx.quantifierDeclaration()) _localctx.elements.add(ctx.element); + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class QuantifierDeclarationContext extends ParserRuleContext { + public QuantifierDeclaration element; + public QuantifierDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_quantifierDeclaration; } + + public QuantifierDeclarationContext() { } + public void copyFrom(QuantifierDeclarationContext ctx) { + super.copyFrom(ctx); + this.element = ctx.element; + } + } + public static class OneOfContext extends QuantifierDeclarationContext { + public Token disj; + public VariableContext variable; + public List vars = new ArrayList(); + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public List variable() { + return getRuleContexts(VariableContext.class); + } + public VariableContext variable(int i) { + return getRuleContext(VariableContext.class,i); + } + public OneOfContext(QuantifierDeclarationContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterOneOf(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitOneOf(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitOneOf(this); + else return visitor.visitChildren(this); + } + } + public static class SomeOfContext extends QuantifierDeclarationContext { + public Token disj; + public VariableContext variable; + public List vars = new ArrayList(); + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public List variable() { + return getRuleContexts(VariableContext.class); + } + public VariableContext variable(int i) { + return getRuleContext(VariableContext.class,i); + } + public SomeOfContext(QuantifierDeclarationContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterSomeOf(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitSomeOf(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitSomeOf(this); + else return visitor.visitChildren(this); + } + } + public static class LoneOfContext extends QuantifierDeclarationContext { + public Token disj; + public VariableContext variable; + public List vars = new ArrayList(); + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public List variable() { + return getRuleContexts(VariableContext.class); + } + public VariableContext variable(int i) { + return getRuleContext(VariableContext.class,i); + } + public LoneOfContext(QuantifierDeclarationContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterLoneOf(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitLoneOf(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitLoneOf(this); + else return visitor.visitChildren(this); + } + } + public static class SetOfContext extends QuantifierDeclarationContext { + public Token disj; + public VariableContext variable; + public List vars = new ArrayList(); + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public List variable() { + return getRuleContexts(VariableContext.class); + } + public VariableContext variable(int i) { + return getRuleContext(VariableContext.class,i); + } + public SetOfContext(QuantifierDeclarationContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterSetOf(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitSetOf(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitSetOf(this); + else return visitor.visitChildren(this); + } + } + + public final QuantifierDeclarationContext quantifierDeclaration() throws RecognitionException { + QuantifierDeclarationContext _localctx = new QuantifierDeclarationContext(_ctx, getState()); + enterRule(_localctx, 118, RULE_quantifierDeclaration); + int _la; + try { + setState(1733); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,225,_ctx) ) { + case 1: + _localctx = new OneOfContext(_localctx); + enterOuterAlt(_localctx, 1); + { + setState(1668); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__129) { + { + setState(1667); + ((OneOfContext)_localctx).disj = match(T__129); + } + } + + setState(1670); + ((OneOfContext)_localctx).variable = variable(); + ((OneOfContext)_localctx).vars.add(((OneOfContext)_localctx).variable); + setState(1675); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(1671); + match(T__2); + setState(1672); + ((OneOfContext)_localctx).variable = variable(); + ((OneOfContext)_localctx).vars.add(((OneOfContext)_localctx).variable); + } + } + setState(1677); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1678); + match(T__5); + setState(1680); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__89) { + { + setState(1679); + match(T__89); + } + } + + setState(1682); + expression(0); + ((OneOfContext)_localctx).element = QuantifierDeclaration.create(_localctx); + } + break; + case 2: + _localctx = new LoneOfContext(_localctx); + enterOuterAlt(_localctx, 2); + { + setState(1686); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__129) { + { + setState(1685); + ((LoneOfContext)_localctx).disj = match(T__129); + } + } + + setState(1688); + ((LoneOfContext)_localctx).variable = variable(); + ((LoneOfContext)_localctx).vars.add(((LoneOfContext)_localctx).variable); + setState(1693); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(1689); + match(T__2); + setState(1690); + ((LoneOfContext)_localctx).variable = variable(); + ((LoneOfContext)_localctx).vars.add(((LoneOfContext)_localctx).variable); + } + } + setState(1695); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1696); + match(T__5); + setState(1697); + match(T__88); + setState(1698); + expression(0); + ((LoneOfContext)_localctx).element = QuantifierDeclaration.create(_localctx); + } + break; + case 3: + _localctx = new SomeOfContext(_localctx); + enterOuterAlt(_localctx, 3); + { + setState(1702); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__129) { + { + setState(1701); + ((SomeOfContext)_localctx).disj = match(T__129); + } + } + + setState(1704); + ((SomeOfContext)_localctx).variable = variable(); + ((SomeOfContext)_localctx).vars.add(((SomeOfContext)_localctx).variable); + setState(1709); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(1705); + match(T__2); + setState(1706); + ((SomeOfContext)_localctx).variable = variable(); + ((SomeOfContext)_localctx).vars.add(((SomeOfContext)_localctx).variable); + } + } + setState(1711); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1712); + match(T__5); + setState(1713); + match(T__90); + setState(1714); + expression(0); + ((SomeOfContext)_localctx).element = QuantifierDeclaration.create(_localctx); + } + break; + case 4: + _localctx = new SetOfContext(_localctx); + enterOuterAlt(_localctx, 4); + { + setState(1718); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__129) { + { + setState(1717); + ((SetOfContext)_localctx).disj = match(T__129); + } + } + + setState(1720); + ((SetOfContext)_localctx).variable = variable(); + ((SetOfContext)_localctx).vars.add(((SetOfContext)_localctx).variable); + setState(1725); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(1721); + match(T__2); + setState(1722); + ((SetOfContext)_localctx).variable = variable(); + ((SetOfContext)_localctx).vars.add(((SetOfContext)_localctx).variable); + } + } + setState(1727); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1728); + match(T__5); + setState(1729); + match(T__130); + setState(1730); + expression(0); + ((SetOfContext)_localctx).element = QuantifierDeclaration.create(_localctx); + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class LetDeclarationsContext extends ParserRuleContext { + public List elements; + public List letDeclaration() { + return getRuleContexts(LetDeclarationContext.class); + } + public LetDeclarationContext letDeclaration(int i) { + return getRuleContext(LetDeclarationContext.class,i); + } + public LetDeclarationsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_letDeclarations; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterLetDeclarations(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitLetDeclarations(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitLetDeclarations(this); + else return visitor.visitChildren(this); + } + } + + public final LetDeclarationsContext letDeclarations() throws RecognitionException { + LetDeclarationsContext _localctx = new LetDeclarationsContext(_ctx, getState()); + enterRule(_localctx, 120, RULE_letDeclarations); + ((LetDeclarationsContext)_localctx).elements = new ArrayList<>(); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1735); + letDeclaration(); + setState(1740); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(1736); + match(T__2); + setState(1737); + letDeclaration(); + } + } + setState(1742); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + _ctx.stop = _input.LT(-1); + for(LetDeclarationContext ctx: _localctx.letDeclaration()) _localctx.elements.add(ctx.element); + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class LetDeclarationContext extends ParserRuleContext { + public LetDeclaration element; + public VariableContext variable; + public List vars = new ArrayList(); + public ExpressionContext expression; + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public List variable() { + return getRuleContexts(VariableContext.class); + } + public VariableContext variable(int i) { + return getRuleContext(VariableContext.class,i); + } + public LetDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_letDeclaration; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterLetDeclaration(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitLetDeclaration(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitLetDeclaration(this); + else return visitor.visitChildren(this); + } + } + + public final LetDeclarationContext letDeclaration() throws RecognitionException { + LetDeclarationContext _localctx = new LetDeclarationContext(_ctx, getState()); + enterRule(_localctx, 122, RULE_letDeclaration); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1743); + ((LetDeclarationContext)_localctx).variable = variable(); + ((LetDeclarationContext)_localctx).vars.add(((LetDeclarationContext)_localctx).variable); + setState(1748); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(1744); + match(T__2); + setState(1745); + ((LetDeclarationContext)_localctx).variable = variable(); + ((LetDeclarationContext)_localctx).vars.add(((LetDeclarationContext)_localctx).variable); + } + } + setState(1750); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1751); + match(T__22); + setState(1752); + ((LetDeclarationContext)_localctx).expression = expression(0); + ((LetDeclarationContext)_localctx).element = new LetDeclaration(_localctx); for(VariableContext ctx: _localctx.variable()) _localctx.element.addOwnedElements(ctx.element); _localctx.element.addOwnedElements(((LetDeclarationContext)_localctx).expression.element); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ComprehensionDeclarationsContext extends ParserRuleContext { + public List elements; + public List comprehensionDeclaration() { + return getRuleContexts(ComprehensionDeclarationContext.class); + } + public ComprehensionDeclarationContext comprehensionDeclaration(int i) { + return getRuleContext(ComprehensionDeclarationContext.class,i); + } + public ComprehensionDeclarationsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_comprehensionDeclarations; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterComprehensionDeclarations(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitComprehensionDeclarations(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitComprehensionDeclarations(this); + else return visitor.visitChildren(this); + } + } + + public final ComprehensionDeclarationsContext comprehensionDeclarations() throws RecognitionException { + ComprehensionDeclarationsContext _localctx = new ComprehensionDeclarationsContext(_ctx, getState()); + enterRule(_localctx, 124, RULE_comprehensionDeclarations); + ((ComprehensionDeclarationsContext)_localctx).elements = new ArrayList<>(); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1755); + comprehensionDeclaration(); + setState(1760); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(1756); + match(T__2); + setState(1757); + comprehensionDeclaration(); + } + } + setState(1762); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + _ctx.stop = _input.LT(-1); + for(ComprehensionDeclarationContext ctx: _localctx.comprehensionDeclaration()) _localctx.elements.add(ctx.element); + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ComprehensionDeclarationContext extends ParserRuleContext { + public ComprehensionDeclaration element; + public Token disj; + public VariableContext variable; + public List vars = new ArrayList(); + public ExpressionContext expression; + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public List variable() { + return getRuleContexts(VariableContext.class); + } + public VariableContext variable(int i) { + return getRuleContext(VariableContext.class,i); + } + public ComprehensionDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_comprehensionDeclaration; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterComprehensionDeclaration(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitComprehensionDeclaration(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitComprehensionDeclaration(this); + else return visitor.visitChildren(this); + } + } + + public final ComprehensionDeclarationContext comprehensionDeclaration() throws RecognitionException { + ComprehensionDeclarationContext _localctx = new ComprehensionDeclarationContext(_ctx, getState()); + enterRule(_localctx, 126, RULE_comprehensionDeclaration); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1764); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__129) { + { + setState(1763); + ((ComprehensionDeclarationContext)_localctx).disj = match(T__129); + } + } + + { + setState(1766); + ((ComprehensionDeclarationContext)_localctx).variable = variable(); + ((ComprehensionDeclarationContext)_localctx).vars.add(((ComprehensionDeclarationContext)_localctx).variable); + setState(1771); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(1767); + match(T__2); + setState(1768); + ((ComprehensionDeclarationContext)_localctx).variable = variable(); + ((ComprehensionDeclarationContext)_localctx).vars.add(((ComprehensionDeclarationContext)_localctx).variable); + } + } + setState(1773); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(1774); + match(T__5); + setState(1776); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__89) { + { + setState(1775); + match(T__89); + } + } + + setState(1778); + ((ComprehensionDeclarationContext)_localctx).expression = expression(0); + } + ((ComprehensionDeclarationContext)_localctx).element = new ComprehensionDeclaration(_localctx); for(VariableContext ctx: _localctx.variable()) _localctx.element.addOwnedElements(ctx.element); _localctx.element.addOwnedElements(((ComprehensionDeclarationContext)_localctx).expression.element); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class RelationIdContext extends ParserRuleContext { + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public RelationIdContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_relationId; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterRelationId(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitRelationId(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitRelationId(this); + else return visitor.visitChildren(this); + } + } + + public final RelationIdContext relationId() throws RecognitionException { + RelationIdContext _localctx = new RelationIdContext(_ctx, getState()); + enterRule(_localctx, 128, RULE_relationId); + try { + enterOuterAlt(_localctx, 1); + { + setState(1782); + unrestrictedName(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class VariableContext extends ParserRuleContext { + public Variable element; + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public VariableContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_variable; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterVariable(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitVariable(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitVariable(this); + else return visitor.visitChildren(this); + } + } + + public final VariableContext variable() throws RecognitionException { + VariableContext _localctx = new VariableContext(_ctx, getState()); + enterRule(_localctx, 130, RULE_variable); + try { + enterOuterAlt(_localctx, 1); + { + setState(1784); + unrestrictedName(); + ((VariableContext)_localctx).element = new Variable(_localctx); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class MultContext extends ParserRuleContext { + public MultContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_mult; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterMult(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitMult(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitMult(this); + else return visitor.visitChildren(this); + } + } + + public final MultContext mult() throws RecognitionException { + MultContext _localctx = new MultContext(_ctx, getState()); + enterRule(_localctx, 132, RULE_mult); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1787); + _la = _input.LA(1); + if ( !(((((_la - 89)) & ~0x3f) == 0 && ((1L << (_la - 89)) & ((1L << (T__88 - 89)) | (1L << (T__89 - 89)) | (1L << (T__90 - 89)) | (1L << (T__130 - 89)))) != 0)) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class UnrestrictedNameContext extends ParserRuleContext { + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class,0); + } + public UnrestrictedNameContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_unrestrictedName; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterUnrestrictedName(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitUnrestrictedName(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitUnrestrictedName(this); + else return visitor.visitChildren(this); + } + } + + public final UnrestrictedNameContext unrestrictedName() throws RecognitionException { + UnrestrictedNameContext _localctx = new UnrestrictedNameContext(_ctx, getState()); + enterRule(_localctx, 134, RULE_unrestrictedName); + try { + setState(1831); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,232,_ctx) ) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(1789); + identifier(); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(1790); + match(T__23); + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(1791); + match(T__32); + } + break; + case 4: + enterOuterAlt(_localctx, 4); + { + setState(1792); + match(T__75); + } + break; + case 5: + enterOuterAlt(_localctx, 5); + { + setState(1793); + match(T__76); + } + break; + case 6: + enterOuterAlt(_localctx, 6); + { + setState(1794); + match(T__24); + } + break; + case 7: + enterOuterAlt(_localctx, 7); + { + setState(1795); + match(T__43); + } + break; + case 8: + enterOuterAlt(_localctx, 8); + { + setState(1796); + match(T__57); + } + break; + case 9: + enterOuterAlt(_localctx, 9); + { + setState(1797); + match(T__131); + } + break; + case 10: + enterOuterAlt(_localctx, 10); + { + setState(1798); + match(T__83); + } + break; + case 11: + enterOuterAlt(_localctx, 11); + { + setState(1799); + match(T__33); + } + break; + case 12: + enterOuterAlt(_localctx, 12); + { + setState(1800); + match(T__60); + } + break; + case 13: + enterOuterAlt(_localctx, 13); + { + setState(1801); + match(T__132); + } + break; + case 14: + enterOuterAlt(_localctx, 14); + { + setState(1802); + match(T__26); + } + break; + case 15: + enterOuterAlt(_localctx, 15); + { + setState(1803); + match(T__34); + } + break; + case 16: + enterOuterAlt(_localctx, 16); + { + setState(1804); + match(T__20); + } + break; + case 17: + enterOuterAlt(_localctx, 17); + { + setState(1805); + match(T__82); + } + break; + case 18: + enterOuterAlt(_localctx, 18); + { + setState(1806); + match(T__25); + } + break; + case 19: + enterOuterAlt(_localctx, 19); + { + setState(1807); + match(T__46); + } + break; + case 20: + enterOuterAlt(_localctx, 20); + { + setState(1808); + match(T__11); + } + break; + case 21: + enterOuterAlt(_localctx, 21); + { + setState(1809); + match(T__47); + } + break; + case 22: + enterOuterAlt(_localctx, 22); + { + setState(1810); + match(T__35); + } + break; + case 23: + enterOuterAlt(_localctx, 23); + { + setState(1811); + match(T__21); + } + break; + case 24: + enterOuterAlt(_localctx, 24); + { + setState(1812); + match(T__80); + } + break; + case 25: + enterOuterAlt(_localctx, 25); + { + setState(1813); + match(T__78); + } + break; + case 26: + enterOuterAlt(_localctx, 26); + { + setState(1814); + match(T__56); + } + break; + case 27: + enterOuterAlt(_localctx, 27); + { + setState(1815); + match(T__41); + } + break; + case 28: + enterOuterAlt(_localctx, 28); + { + setState(1816); + match(T__31); + } + break; + case 29: + enterOuterAlt(_localctx, 29); + { + setState(1817); + match(T__63); + } + break; + case 30: + enterOuterAlt(_localctx, 30); + { + setState(1818); + match(T__133); + } + break; + case 31: + enterOuterAlt(_localctx, 31); + { + setState(1819); + match(T__44); + } + break; + case 32: + enterOuterAlt(_localctx, 32); + { + setState(1820); + match(T__27); + } + break; + case 33: + enterOuterAlt(_localctx, 33); + { + setState(1821); + match(T__50); + } + break; + case 34: + enterOuterAlt(_localctx, 34); + { + setState(1822); + match(T__29); + } + break; + case 35: + enterOuterAlt(_localctx, 35); + { + setState(1823); + match(T__37); + } + break; + case 36: + enterOuterAlt(_localctx, 36); + { + setState(1824); + match(T__39); + } + break; + case 37: + enterOuterAlt(_localctx, 37); + { + setState(1825); + match(T__30); + } + break; + case 38: + enterOuterAlt(_localctx, 38); + { + setState(1826); + match(T__77); + } + break; + case 39: + enterOuterAlt(_localctx, 39); + { + setState(1827); + match(T__61); + } + break; + case 40: + enterOuterAlt(_localctx, 40); + { + setState(1828); + match(T__58); + } + break; + case 41: + enterOuterAlt(_localctx, 41); + { + setState(1829); + match(T__62); + } + break; + case 42: + enterOuterAlt(_localctx, 42); + { + setState(1830); + match(T__11); + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class IdentifierContext extends ParserRuleContext { + public TerminalNode IDENTIFIER() { return getToken(AlloyInEcoreParser.IDENTIFIER, 0); } + public IdentifierContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_identifier; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterIdentifier(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitIdentifier(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitIdentifier(this); + else return visitor.visitChildren(this); + } + } + + public final IdentifierContext identifier() throws RecognitionException { + IdentifierContext _localctx = new IdentifierContext(_ctx, getState()); + enterRule(_localctx, 136, RULE_identifier); + try { + enterOuterAlt(_localctx, 1); + { + setState(1833); + match(IDENTIFIER); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class UpperContext extends ParserRuleContext { + public TerminalNode INT() { return getToken(AlloyInEcoreParser.INT, 0); } + public UpperContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_upper; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterUpper(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitUpper(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitUpper(this); + else return visitor.visitChildren(this); + } + } + + public final UpperContext upper() throws RecognitionException { + UpperContext _localctx = new UpperContext(_ctx, getState()); + enterRule(_localctx, 138, RULE_upper); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(1835); + _la = _input.LA(1); + if ( !(_la==T__52 || _la==INT) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class LowerContext extends ParserRuleContext { + public TerminalNode INT() { return getToken(AlloyInEcoreParser.INT, 0); } + public LowerContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_lower; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).enterLower(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof AlloyInEcoreListener ) ((AlloyInEcoreListener)listener).exitLower(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof AlloyInEcoreVisitor ) return ((AlloyInEcoreVisitor)visitor).visitLower(this); + else return visitor.visitChildren(this); + } + } + + public final LowerContext lower() throws RecognitionException { + LowerContext _localctx = new LowerContext(_ctx, getState()); + enterRule(_localctx, 140, RULE_lower); + try { + enterOuterAlt(_localctx, 1); + { + setState(1837); + match(INT); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) { + switch (ruleIndex) { + case 5: + return slot_sempred((SlotContext)_localctx, predIndex); + case 55: + return formula_sempred((FormulaContext)_localctx, predIndex); + case 56: + return expression_sempred((ExpressionContext)_localctx, predIndex); + case 57: + return intExpression_sempred((IntExpressionContext)_localctx, predIndex); + } + return true; + } + private boolean slot_sempred(SlotContext _localctx, int predIndex) { + switch (predIndex) { + case 0: + return true; + } + return true; + } + private boolean formula_sempred(FormulaContext _localctx, int predIndex) { + switch (predIndex) { + case 1: + return precpred(_ctx, 13); + case 2: + return precpred(_ctx, 12); + case 3: + return precpred(_ctx, 11); + case 4: + return precpred(_ctx, 10); + } + return true; + } + private boolean expression_sempred(ExpressionContext _localctx, int predIndex) { + switch (predIndex) { + case 5: + return precpred(_ctx, 15); + case 6: + return precpred(_ctx, 14); + case 7: + return precpred(_ctx, 13); + case 8: + return precpred(_ctx, 12); + case 9: + return precpred(_ctx, 10); + case 10: + return precpred(_ctx, 9); + case 11: + return precpred(_ctx, 11); + } + return true; + } + private boolean intExpression_sempred(IntExpressionContext _localctx, int predIndex) { + switch (predIndex) { + case 12: + return precpred(_ctx, 7); + case 13: + return precpred(_ctx, 6); + case 14: + return precpred(_ctx, 5); + case 15: + return precpred(_ctx, 4); + case 16: + return precpred(_ctx, 3); + } + return true; + } + + public static final String _serializedATN = + "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3\u0091\u0732\4\2\t"+ + "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ + "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ + "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ + "\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+ + "\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t+\4"+ + ",\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64\t"+ + "\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:\4;\t;\4<\t<\4=\t="+ + "\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4E\tE\4F\tF\4G\tG\4H\tH\3\2"+ + "\3\2\3\2\3\2\3\2\7\2\u0096\n\2\f\2\16\2\u0099\13\2\3\2\3\2\3\3\3\3\3\3"+ + "\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\5\3\u00a9\n\3\3\4\3\4\3\4\3\4\5\4"+ + "\u00af\n\4\3\4\7\4\u00b2\n\4\f\4\16\4\u00b5\13\4\3\4\3\4\3\4\5\4\u00ba"+ + "\n\4\3\5\3\5\3\5\3\5\5\5\u00c0\n\5\3\5\3\5\3\5\3\6\3\6\3\6\5\6\u00c8\n"+ + "\6\3\6\3\6\3\6\3\6\3\6\7\6\u00cf\n\6\f\6\16\6\u00d2\13\6\3\6\3\6\3\6\5"+ + "\6\u00d7\n\6\3\7\3\7\3\7\3\7\3\7\3\7\7\7\u00df\n\7\f\7\16\7\u00e2\13\7"+ + "\3\7\3\7\3\7\3\7\3\7\3\7\7\7\u00ea\n\7\f\7\16\7\u00ed\13\7\3\7\3\7\3\7"+ + "\5\7\u00f2\n\7\5\7\u00f4\n\7\3\b\3\b\5\b\u00f8\n\b\3\t\3\t\3\t\3\t\7\t"+ + "\u00fe\n\t\f\t\16\t\u0101\13\t\3\t\3\t\3\n\3\n\3\13\3\13\3\13\3\13\3\13"+ + "\3\13\3\13\5\13\u010e\n\13\3\f\3\f\3\r\3\r\3\16\5\16\u0115\n\16\3\16\3"+ + "\16\3\17\5\17\u011a\n\17\3\17\5\17\u011d\n\17\3\17\3\17\3\17\3\20\3\20"+ + "\3\21\3\21\3\22\3\22\3\23\5\23\u0129\n\23\3\23\3\23\3\23\3\23\3\23\5\23"+ + "\u0130\n\23\3\23\3\23\7\23\u0134\n\23\f\23\16\23\u0137\13\23\3\23\3\23"+ + "\3\23\3\23\3\23\3\24\3\24\3\24\3\24\5\24\u0142\n\24\3\24\3\24\3\24\3\24"+ + "\3\25\5\25\u0149\n\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25"+ + "\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25"+ + "\3\25\7\25\u0164\n\25\f\25\16\25\u0167\13\25\3\25\3\25\5\25\u016b\n\25"+ + "\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\5\26\u0176\n\26\3\27\5\27"+ + "\u0179\n\27\3\27\3\27\5\27\u017d\n\27\3\27\3\27\5\27\u0181\n\27\3\27\3"+ + "\27\5\27\u0185\n\27\3\27\3\27\3\27\5\27\u018a\n\27\3\27\3\27\3\27\3\27"+ + "\3\27\7\27\u0191\n\27\f\27\16\27\u0194\13\27\5\27\u0196\n\27\3\27\3\27"+ + "\3\27\5\27\u019b\n\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27"+ + "\3\27\3\27\3\27\3\27\7\27\u01ab\n\27\f\27\16\27\u01ae\13\27\3\27\3\27"+ + "\5\27\u01b2\n\27\3\30\3\30\3\30\3\30\3\30\3\30\5\30\u01ba\n\30\3\31\5"+ + "\31\u01bd\n\31\3\31\3\31\5\31\u01c1\n\31\3\31\3\31\5\31\u01c5\n\31\3\31"+ + "\5\31\u01c8\n\31\3\31\5\31\u01cb\n\31\3\31\5\31\u01ce\n\31\3\31\3\31\3"+ + "\31\3\31\3\31\3\31\5\31\u01d6\n\31\3\31\3\31\3\31\5\31\u01db\n\31\3\31"+ + "\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31\5\31\u01e7\n\31\3\31\5\31"+ + "\u01ea\n\31\6\31\u01ec\n\31\r\31\16\31\u01ed\3\31\5\31\u01f1\n\31\3\31"+ + "\3\31\3\31\3\31\7\31\u01f7\n\31\f\31\16\31\u01fa\13\31\3\31\3\31\3\31"+ + "\3\31\3\31\3\31\5\31\u0202\n\31\3\31\3\31\3\31\7\31\u0207\n\31\f\31\16"+ + "\31\u020a\13\31\3\31\3\31\5\31\u020e\n\31\3\31\3\31\3\32\5\32\u0213\n"+ + "\32\3\32\3\32\5\32\u0217\n\32\3\32\3\32\5\32\u021b\n\32\3\32\5\32\u021e"+ + "\n\32\3\32\5\32\u0221\n\32\3\32\5\32\u0224\n\32\3\32\3\32\3\32\3\32\3"+ + "\32\5\32\u022b\n\32\3\32\3\32\3\32\3\32\5\32\u0231\n\32\3\32\3\32\3\32"+ + "\5\32\u0236\n\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32"+ + "\3\32\5\32\u0244\n\32\3\32\5\32\u0247\n\32\6\32\u0249\n\32\r\32\16\32"+ + "\u024a\3\32\5\32\u024e\n\32\3\32\3\32\3\32\3\32\3\32\7\32\u0255\n\32\f"+ + "\32\16\32\u0258\13\32\3\32\3\32\5\32\u025c\n\32\3\32\3\32\3\32\7\32\u0261"+ + "\n\32\f\32\16\32\u0264\13\32\3\32\3\32\3\32\3\32\3\32\3\32\5\32\u026c"+ + "\n\32\3\32\3\32\3\32\7\32\u0271\n\32\f\32\16\32\u0274\13\32\3\32\3\32"+ + "\5\32\u0278\n\32\3\32\3\32\3\33\5\33\u027d\n\33\3\33\3\33\5\33\u0281\n"+ + "\33\3\33\3\33\5\33\u0285\n\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\7\33"+ + "\u028e\n\33\f\33\16\33\u0291\13\33\5\33\u0293\n\33\3\33\3\33\3\33\3\33"+ + "\3\33\3\33\5\33\u029b\n\33\5\33\u029d\n\33\3\33\3\33\3\33\3\33\3\33\3"+ + "\33\7\33\u02a5\n\33\f\33\16\33\u02a8\13\33\5\33\u02aa\n\33\3\33\3\33\3"+ + "\33\3\33\3\33\3\33\5\33\u02b2\n\33\3\33\5\33\u02b5\n\33\6\33\u02b7\n\33"+ + "\r\33\16\33\u02b8\3\33\5\33\u02bc\n\33\3\33\3\33\3\33\3\33\3\33\3\33\3"+ + "\33\3\33\3\33\3\33\3\33\3\33\3\33\7\33\u02cb\n\33\f\33\16\33\u02ce\13"+ + "\33\3\33\3\33\5\33\u02d2\n\33\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\35"+ + "\3\36\3\36\3\36\3\36\3\36\5\36\u02e1\n\36\3\36\3\36\3\36\3\36\3\36\3\36"+ + "\5\36\u02e9\n\36\3\36\5\36\u02ec\n\36\6\36\u02ee\n\36\r\36\16\36\u02ef"+ + "\3\36\5\36\u02f3\n\36\3\36\3\36\7\36\u02f7\n\36\f\36\16\36\u02fa\13\36"+ + "\3\36\3\36\5\36\u02fe\n\36\3\36\3\36\3\37\3\37\3\37\3\37\5\37\u0306\n"+ + "\37\3\37\5\37\u0309\n\37\3\37\3\37\5\37\u030d\n\37\3\37\3\37\3\37\3 \5"+ + " \u0313\n \3 \3 \5 \u0317\n \3 \3 \3 \3 \5 \u031d\n \3 \3 \3 \5 \u0322"+ + "\n \3 \3 \3 \3 \5 \u0328\n \3 \5 \u032b\n \3 \3 \3 \3 \3 \3 \3 \7 \u0334"+ + "\n \f \16 \u0337\13 \3 \3 \5 \u033b\n \3 \3 \3!\5!\u0340\n!\3!\3!\3!\3"+ + "!\3!\5!\u0347\n!\3!\3!\3!\5!\u034c\n!\3!\3!\3!\3!\5!\u0352\n!\3!\5!\u0355"+ + "\n!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\7!\u0361\n!\f!\16!\u0364\13!\3!\3!\5"+ + "!\u0368\n!\3!\3!\3\"\3\"\3\"\5\"\u036f\n\"\3\"\3\"\3\"\5\"\u0374\n\"\3"+ + "\"\3\"\3\"\7\"\u0379\n\"\f\"\16\"\u037c\13\"\3\"\3\"\3\"\5\"\u0381\n\""+ + "\3#\3#\5#\u0385\n#\3#\3#\3#\3#\3#\7#\u038c\n#\f#\16#\u038f\13#\3#\3#\5"+ + "#\u0393\n#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\6#\u03a0\n#\r#\16#\u03a1\3"+ + "#\3#\3#\5#\u03a7\n#\3$\5$\u03aa\n$\3$\3$\5$\u03ae\n$\3$\3$\3%\3%\3%\3"+ + "%\3%\3%\5%\u03b8\n%\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\5&\u03c6\n&\3"+ + "\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'\5\'\u03d1\n\'\3(\3(\3(\3(\3(\3)\3)"+ + "\3)\3)\7)\u03dc\n)\f)\16)\u03df\13)\3)\3)\3*\3*\3*\3*\3*\3*\7*\u03e9\n"+ + "*\f*\16*\u03ec\13*\5*\u03ee\n*\3*\3*\3+\3+\3+\3+\3+\3+\5+\u03f8\n+\3,"+ + "\3,\3,\3,\3,\7,\u03ff\n,\f,\16,\u0402\13,\3,\3,\5,\u0406\n,\3-\3-\3-\3"+ + "-\3-\3-\5-\u040e\n-\3.\3.\3.\3.\3.\3.\3.\5.\u0417\n.\3/\3/\3/\5/\u041c"+ + "\n/\3/\7/\u041f\n/\f/\16/\u0422\13/\3/\5/\u0425\n/\3\60\3\60\5\60\u0429"+ + "\n\60\3\60\3\60\3\60\5\60\u042e\n\60\3\61\3\61\3\61\3\61\3\61\3\61\3\61"+ + "\3\61\3\61\3\61\5\61\u043a\n\61\3\62\3\62\5\62\u043e\n\62\3\62\3\62\3"+ + "\62\5\62\u0443\n\62\3\62\3\62\5\62\u0447\n\62\3\62\3\62\3\63\5\63\u044c"+ + "\n\63\3\63\3\63\3\63\3\63\3\63\3\63\5\63\u0454\n\63\5\63\u0456\n\63\3"+ + "\63\3\63\3\63\5\63\u045b\n\63\3\63\3\63\5\63\u045f\n\63\3\63\3\63\3\64"+ + "\3\64\3\64\3\64\3\64\5\64\u0468\n\64\5\64\u046a\n\64\3\64\3\64\3\64\5"+ + "\64\u046f\n\64\3\64\3\64\5\64\u0473\n\64\3\64\3\64\3\65\3\65\3\65\3\65"+ + "\3\65\5\65\u047c\n\65\5\65\u047e\n\65\3\65\3\65\3\65\5\65\u0483\n\65\3"+ + "\65\3\65\5\65\u0487\n\65\3\65\3\65\3\66\3\66\5\66\u048d\n\66\3\66\3\66"+ + "\3\66\5\66\u0492\n\66\3\66\3\66\5\66\u0496\n\66\3\66\3\66\3\67\3\67\5"+ + "\67\u049c\n\67\3\67\3\67\3\67\5\67\u04a1\n\67\3\67\3\67\5\67\u04a5\n\67"+ + "\3\67\3\67\38\38\38\58\u04ac\n8\38\38\39\39\39\39\39\39\39\39\39\39\3"+ + "9\39\39\39\39\39\39\39\39\59\u04c3\n9\39\39\39\39\39\39\59\u04cb\n9\3"+ + "9\39\39\39\39\39\59\u04d3\n9\39\39\39\39\39\39\59\u04db\n9\39\39\39\3"+ + "9\39\39\59\u04e3\n9\39\39\39\39\39\39\59\u04eb\n9\39\39\39\39\39\39\5"+ + "9\u04f3\n9\39\39\39\39\39\39\39\39\39\39\39\39\39\39\39\39\39\39\39\3"+ + "9\39\39\39\39\59\u050d\n9\39\59\u0510\n9\39\39\39\39\39\39\39\39\39\3"+ + "9\39\39\39\39\39\39\39\39\39\39\39\39\39\39\39\39\79\u052c\n9\f9\169\u052f"+ + "\139\39\59\u0532\n9\39\39\79\u0536\n9\f9\169\u0539\139\39\59\u053c\n9"+ + "\39\39\39\39\39\39\39\39\79\u0546\n9\f9\169\u0549\139\39\59\u054c\n9\3"+ + "9\39\79\u0550\n9\f9\169\u0553\139\39\59\u0556\n9\39\39\39\39\39\39\39"+ + "\39\79\u0560\n9\f9\169\u0563\139\39\59\u0566\n9\39\39\79\u056a\n9\f9\16"+ + "9\u056d\139\39\59\u0570\n9\39\39\39\39\39\39\39\39\79\u057a\n9\f9\169"+ + "\u057d\139\39\59\u0580\n9\39\39\79\u0584\n9\f9\169\u0587\139\39\59\u058a"+ + "\n9\39\39\39\39\39\39\39\39\79\u0594\n9\f9\169\u0597\139\39\59\u059a\n"+ + "9\39\39\79\u059e\n9\f9\169\u05a1\139\39\59\u05a4\n9\39\39\39\39\39\39"+ + "\39\39\79\u05ae\n9\f9\169\u05b1\139\39\59\u05b4\n9\39\39\79\u05b8\n9\f"+ + "9\169\u05bb\139\39\59\u05be\n9\39\39\39\39\39\39\39\39\39\39\39\59\u05cb"+ + "\n9\39\39\39\39\39\39\39\39\39\39\39\39\39\39\39\39\39\39\39\39\79\u05e1"+ + "\n9\f9\169\u05e4\139\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3"+ + ":\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3"+ + ":\3:\3:\3:\3:\5:\u0612\n:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3"+ + ":\3:\3:\3:\3:\3:\3:\3:\5:\u062a\n:\3:\3:\5:\u062e\n:\3:\3:\3:\3:\3:\3"+ + ":\3:\3:\3:\3:\3:\3:\3:\3:\7:\u063e\n:\f:\16:\u0641\13:\3;\3;\3;\3;\3;"+ + "\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\5;\u0655\n;\3;\3;\3;\3;\3;\3;"+ + "\3;\5;\u065e\n;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;"+ + "\3;\3;\3;\3;\3;\3;\3;\7;\u0679\n;\f;\16;\u067c\13;\3<\3<\3<\7<\u0681\n"+ + "<\f<\16<\u0684\13<\3=\5=\u0687\n=\3=\3=\3=\7=\u068c\n=\f=\16=\u068f\13"+ + "=\3=\3=\5=\u0693\n=\3=\3=\3=\3=\5=\u0699\n=\3=\3=\3=\7=\u069e\n=\f=\16"+ + "=\u06a1\13=\3=\3=\3=\3=\3=\3=\5=\u06a9\n=\3=\3=\3=\7=\u06ae\n=\f=\16="+ + "\u06b1\13=\3=\3=\3=\3=\3=\3=\5=\u06b9\n=\3=\3=\3=\7=\u06be\n=\f=\16=\u06c1"+ + "\13=\3=\3=\3=\3=\3=\5=\u06c8\n=\3>\3>\3>\7>\u06cd\n>\f>\16>\u06d0\13>"+ + "\3?\3?\3?\7?\u06d5\n?\f?\16?\u06d8\13?\3?\3?\3?\3?\3@\3@\3@\7@\u06e1\n"+ + "@\f@\16@\u06e4\13@\3A\5A\u06e7\nA\3A\3A\3A\7A\u06ec\nA\fA\16A\u06ef\13"+ + "A\3A\3A\5A\u06f3\nA\3A\3A\3A\3A\3B\3B\3C\3C\3C\3D\3D\3E\3E\3E\3E\3E\3"+ + "E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3"+ + "E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\5E\u072a\nE\3F\3F\3G\3G\3H\3"+ + "H\3H\2\5prtI\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60\62\64"+ + "\668:<>@BDFHJLNPRTVXZ\\^`bdfhjlnprtvxz|~\u0080\u0082\u0084\u0086\u0088"+ + "\u008a\u008c\u008e\2\26\3\2\21\22\3\2\23\24\4\2\23\23\678\3\2\u008d\u008e"+ + "\4\2\35\35FF\3\2QR\3\2ST\3\2^_\3\2ij\3\2kl\3\2mo\3\2pq\3\2mn\4\2\23\23"+ + "}}\4\2\24\24~~\4\2\67\67\177\177\3\2\u0080\u0081\3\2\u0082\u0083\4\2["+ + "]\u0085\u0085\4\2\67\67\u0089\u0089\u085c\2\u0090\3\2\2\2\4\u00a8\3\2"+ + "\2\2\6\u00ae\3\2\2\2\b\u00bb\3\2\2\2\n\u00c4\3\2\2\2\f\u00d8\3\2\2\2\16"+ + "\u00f7\3\2\2\2\20\u00f9\3\2\2\2\22\u0104\3\2\2\2\24\u010d\3\2\2\2\26\u010f"+ + "\3\2\2\2\30\u0111\3\2\2\2\32\u0114\3\2\2\2\34\u0119\3\2\2\2\36\u0121\3"+ + "\2\2\2 \u0123\3\2\2\2\"\u0125\3\2\2\2$\u0128\3\2\2\2&\u013d\3\2\2\2(\u0148"+ + "\3\2\2\2*\u0175\3\2\2\2,\u0178\3\2\2\2.\u01b9\3\2\2\2\60\u01bc\3\2\2\2"+ + "\62\u0212\3\2\2\2\64\u027c\3\2\2\2\66\u02d5\3\2\2\28\u02d8\3\2\2\2:\u02db"+ + "\3\2\2\2<\u0301\3\2\2\2>\u0312\3\2\2\2@\u033f\3\2\2\2B\u036e\3\2\2\2D"+ + "\u0382\3\2\2\2F\u03a9\3\2\2\2H\u03b7\3\2\2\2J\u03c5\3\2\2\2L\u03d0\3\2"+ + "\2\2N\u03d2\3\2\2\2P\u03d7\3\2\2\2R\u03e2\3\2\2\2T\u03f7\3\2\2\2V\u03f9"+ + "\3\2\2\2X\u040d\3\2\2\2Z\u040f\3\2\2\2\\\u0418\3\2\2\2^\u0426\3\2\2\2"+ + "`\u0439\3\2\2\2b\u043b\3\2\2\2d\u044b\3\2\2\2f\u0462\3\2\2\2h\u0476\3"+ + "\2\2\2j\u048a\3\2\2\2l\u0499\3\2\2\2n\u04ab\3\2\2\2p\u05ca\3\2\2\2r\u0611"+ + "\3\2\2\2t\u065d\3\2\2\2v\u067d\3\2\2\2x\u06c7\3\2\2\2z\u06c9\3\2\2\2|"+ + "\u06d1\3\2\2\2~\u06dd\3\2\2\2\u0080\u06e6\3\2\2\2\u0082\u06f8\3\2\2\2"+ + "\u0084\u06fa\3\2\2\2\u0086\u06fd\3\2\2\2\u0088\u0729\3\2\2\2\u008a\u072b"+ + "\3\2\2\2\u008c\u072d\3\2\2\2\u008e\u072f\3\2\2\2\u0090\u0091\7\3\2\2\u0091"+ + "\u0092\7\4\2\2\u0092\u0097\5\4\3\2\u0093\u0094\7\5\2\2\u0094\u0096\5\4"+ + "\3\2\u0095\u0093\3\2\2\2\u0096\u0099\3\2\2\2\u0097\u0095\3\2\2\2\u0097"+ + "\u0098\3\2\2\2\u0098\u009a\3\2\2\2\u0099\u0097\3\2\2\2\u009a\u009b\7\6"+ + "\2\2\u009b\3\3\2\2\2\u009c\u009d\7\7\2\2\u009d\u009e\7\b\2\2\u009e\u00a9"+ + "\7\u0089\2\2\u009f\u00a0\7\t\2\2\u00a0\u00a1\7\b\2\2\u00a1\u00a9\7\u0089"+ + "\2\2\u00a2\u00a3\7\n\2\2\u00a3\u00a4\7\b\2\2\u00a4\u00a9\7\u0089\2\2\u00a5"+ + "\u00a6\7\13\2\2\u00a6\u00a7\7\b\2\2\u00a7\u00a9\7\u0089\2\2\u00a8\u009c"+ + "\3\2\2\2\u00a8\u009f\3\2\2\2\u00a8\u00a2\3\2\2\2\u00a8\u00a5\3\2\2\2\u00a9"+ + "\5\3\2\2\2\u00aa\u00ab\7\f\2\2\u00ab\u00ac\5\u008aF\2\u00ac\u00ad\7\r"+ + "\2\2\u00ad\u00af\3\2\2\2\u00ae\u00aa\3\2\2\2\u00ae\u00af\3\2\2\2\u00af"+ + "\u00b3\3\2\2\2\u00b0\u00b2\5&\24\2\u00b1\u00b0\3\2\2\2\u00b2\u00b5\3\2"+ + "\2\2\u00b3\u00b1\3\2\2\2\u00b3\u00b4\3\2\2\2\u00b4\u00b6\3\2\2\2\u00b5"+ + "\u00b3\3\2\2\2\u00b6\u00b9\5\b\5\2\u00b7\u00ba\5\n\6\2\u00b8\u00ba\7\r"+ + "\2\2\u00b9\u00b7\3\2\2\2\u00b9\u00b8\3\2\2\2\u00ba\7\3\2\2\2\u00bb\u00bf"+ + "\7\16\2\2\u00bc\u00bd\5\u0088E\2\u00bd\u00be\7\b\2\2\u00be\u00c0\3\2\2"+ + "\2\u00bf\u00bc\3\2\2\2\u00bf\u00c0\3\2\2\2\u00c0\u00c1\3\2\2\2\u00c1\u00c2"+ + "\7\u008d\2\2\u00c2\u00c3\7\r\2\2\u00c3\t\3\2\2\2\u00c4\u00c5\5\\/\2\u00c5"+ + "\u00c7\b\6\1\2\u00c6\u00c8\5\24\13\2\u00c7\u00c6\3\2\2\2\u00c7\u00c8\3"+ + "\2\2\2\u00c8\u00c9\3\2\2\2\u00c9\u00d6\b\6\1\2\u00ca\u00cb\7\4\2\2\u00cb"+ + "\u00d0\5\f\7\2\u00cc\u00cd\7\5\2\2\u00cd\u00cf\5\f\7\2\u00ce\u00cc\3\2"+ + "\2\2\u00cf\u00d2\3\2\2\2\u00d0\u00ce\3\2\2\2\u00d0\u00d1\3\2\2\2\u00d1"+ + "\u00d3\3\2\2\2\u00d2\u00d0\3\2\2\2\u00d3\u00d4\7\6\2\2\u00d4\u00d7\3\2"+ + "\2\2\u00d5\u00d7\7\r\2\2\u00d6\u00ca\3\2\2\2\u00d6\u00d5\3\2\2\2\u00d7"+ + "\13\3\2\2\2\u00d8\u00d9\5\u0088E\2\u00d9\u00f3\b\7\1\2\u00da\u00f1\7\b"+ + "\2\2\u00db\u00dc\6\7\2\2\u00dc\u00e0\7\4\2\2\u00dd\u00df\5\n\6\2\u00de"+ + "\u00dd\3\2\2\2\u00df\u00e2\3\2\2\2\u00e0\u00de\3\2\2\2\u00e0\u00e1\3\2"+ + "\2\2\u00e1\u00e3\3\2\2\2\u00e2\u00e0\3\2\2\2\u00e3\u00f2\7\6\2\2\u00e4"+ + "\u00f2\5\22\n\2\u00e5\u00e6\7\17\2\2\u00e6\u00eb\5\22\n\2\u00e7\u00e8"+ + "\7\5\2\2\u00e8\u00ea\5\22\n\2\u00e9\u00e7\3\2\2\2\u00ea\u00ed\3\2\2\2"+ + "\u00eb\u00e9\3\2\2\2\u00eb\u00ec\3\2\2\2\u00ec\u00ee\3\2\2\2\u00ed\u00eb"+ + "\3\2\2\2\u00ee\u00ef\7\20\2\2\u00ef\u00f2\3\2\2\2\u00f0\u00f2\5\16\b\2"+ + "\u00f1\u00db\3\2\2\2\u00f1\u00e4\3\2\2\2\u00f1\u00e5\3\2\2\2\u00f1\u00f0"+ + "\3\2\2\2\u00f2\u00f4\3\2\2\2\u00f3\u00da\3\2\2\2\u00f3\u00f4\3\2\2\2\u00f4"+ + "\r\3\2\2\2\u00f5\u00f8\5\24\13\2\u00f6\u00f8\5\20\t\2\u00f7\u00f5\3\2"+ + "\2\2\u00f7\u00f6\3\2\2\2\u00f8\17\3\2\2\2\u00f9\u00fa\7\17\2\2\u00fa\u00ff"+ + "\5\16\b\2\u00fb\u00fc\7\5\2\2\u00fc\u00fe\5\16\b\2\u00fd\u00fb\3\2\2\2"+ + "\u00fe\u0101\3\2\2\2\u00ff\u00fd\3\2\2\2\u00ff\u0100\3\2\2\2\u0100\u0102"+ + "\3\2\2\2\u0101\u00ff\3\2\2\2\u0102\u0103\7\20\2\2\u0103\21\3\2\2\2\u0104"+ + "\u0105\5\\/\2\u0105\23\3\2\2\2\u0106\u010e\5\26\f\2\u0107\u010e\5\32\16"+ + "\2\u0108\u010e\5\34\17\2\u0109\u010e\5\36\20\2\u010a\u010e\5 \21\2\u010b"+ + "\u010e\5\30\r\2\u010c\u010e\5\"\22\2\u010d\u0106\3\2\2\2\u010d\u0107\3"+ + "\2\2\2\u010d\u0108\3\2\2\2\u010d\u0109\3\2\2\2\u010d\u010a\3\2\2\2\u010d"+ + "\u010b\3\2\2\2\u010d\u010c\3\2\2\2\u010e\25\3\2\2\2\u010f\u0110\5\u008a"+ + "F\2\u0110\27\3\2\2\2\u0111\u0112\t\2\2\2\u0112\31\3\2\2\2\u0113\u0115"+ + "\t\3\2\2\u0114\u0113\3\2\2\2\u0114\u0115\3\2\2\2\u0115\u0116\3\2\2\2\u0116"+ + "\u0117\7\u0089\2\2\u0117\33\3\2\2\2\u0118\u011a\t\3\2\2\u0119\u0118\3"+ + "\2\2\2\u0119\u011a\3\2\2\2\u011a\u011c\3\2\2\2\u011b\u011d\7\u0089\2\2"+ + "\u011c\u011b\3\2\2\2\u011c\u011d\3\2\2\2\u011d\u011e\3\2\2\2\u011e\u011f"+ + "\7\25\2\2\u011f\u0120\7\u0089\2\2\u0120\35\3\2\2\2\u0121\u0122\7\u008c"+ + "\2\2\u0122\37\3\2\2\2\u0123\u0124\7\u008b\2\2\u0124!\3\2\2\2\u0125\u0126"+ + "\7\26\2\2\u0126#\3\2\2\2\u0127\u0129\5\2\2\2\u0128\u0127\3\2\2\2\u0128"+ + "\u0129\3\2\2\2\u0129\u012a\3\2\2\2\u012a\u012f\b\23\1\2\u012b\u012c\7"+ + "\16\2\2\u012c\u012d\5\u008aF\2\u012d\u012e\7\r\2\2\u012e\u0130\3\2\2\2"+ + "\u012f\u012b\3\2\2\2\u012f\u0130\3\2\2\2\u0130\u0131\3\2\2\2\u0131\u0135"+ + "\b\23\1\2\u0132\u0134\5&\24\2\u0133\u0132\3\2\2\2\u0134\u0137\3\2\2\2"+ + "\u0135\u0133\3\2\2\2\u0135\u0136\3\2\2\2\u0136\u0138\3\2\2\2\u0137\u0135"+ + "\3\2\2\2\u0138\u0139\5(\25\2\u0139\u013a\b\23\1\2\u013a\u013b\3\2\2\2"+ + "\u013b\u013c\b\23\1\2\u013c%\3\2\2\2\u013d\u0141\7\27\2\2\u013e\u013f"+ + "\5\u008aF\2\u013f\u0140\7\b\2\2\u0140\u0142\3\2\2\2\u0141\u013e\3\2\2"+ + "\2\u0141\u0142\3\2\2\2\u0142\u0143\3\2\2\2\u0143\u0144\7\u008d\2\2\u0144"+ + "\u0145\7\r\2\2\u0145\u0146\b\24\1\2\u0146\'\3\2\2\2\u0147\u0149\5n8\2"+ + "\u0148\u0147\3\2\2\2\u0148\u0149\3\2\2\2\u0149\u014a\3\2\2\2\u014a\u014b"+ + "\b\25\1\2\u014b\u014c\7\30\2\2\u014c\u014d\5\u0088E\2\u014d\u014e\b\25"+ + "\1\2\u014e\u014f\b\25\1\2\u014f\u0150\7\b\2\2\u0150\u0151\5\u008aF\2\u0151"+ + "\u0152\3\2\2\2\u0152\u0153\7\31\2\2\u0153\u0154\7\u008d\2\2\u0154\u0155"+ + "\3\2\2\2\u0155\u016a\b\25\1\2\u0156\u0165\7\4\2\2\u0157\u0158\5D#\2\u0158"+ + "\u0159\b\25\1\2\u0159\u0164\3\2\2\2\u015a\u015b\5(\25\2\u015b\u015c\b"+ + "\25\1\2\u015c\u0164\3\2\2\2\u015d\u015e\5*\26\2\u015e\u015f\b\25\1\2\u015f"+ + "\u0164\3\2\2\2\u0160\u0161\5d\63\2\u0161\u0162\b\25\1\2\u0162\u0164\3"+ + "\2\2\2\u0163\u0157\3\2\2\2\u0163\u015a\3\2\2\2\u0163\u015d\3\2\2\2\u0163"+ + "\u0160\3\2\2\2\u0164\u0167\3\2\2\2\u0165\u0163\3\2\2\2\u0165\u0166\3\2"+ + "\2\2\u0166\u0168\3\2\2\2\u0167\u0165\3\2\2\2\u0168\u016b\7\6\2\2\u0169"+ + "\u016b\7\r\2\2\u016a\u0156\3\2\2\2\u016a\u0169\3\2\2\2\u016b)\3\2\2\2"+ + "\u016c\u016d\5,\27\2\u016d\u016e\b\26\1\2\u016e\u0176\3\2\2\2\u016f\u0170"+ + "\5> \2\u0170\u0171\b\26\1\2\u0171\u0176\3\2\2\2\u0172\u0173\5@!\2\u0173"+ + "\u0174\b\26\1\2\u0174\u0176\3\2\2\2\u0175\u016c\3\2\2\2\u0175\u016f\3"+ + "\2\2\2\u0175\u0172\3\2\2\2\u0176+\3\2\2\2\u0177\u0179\5n8\2\u0178\u0177"+ + "\3\2\2\2\u0178\u0179\3\2\2\2\u0179\u017a\3\2\2\2\u017a\u0180\b\27\1\2"+ + "\u017b\u017d\7\32\2\2\u017c\u017b\3\2\2\2\u017c\u017d\3\2\2\2\u017d\u017e"+ + "\3\2\2\2\u017e\u0181\7\33\2\2\u017f\u0181\7\34\2\2\u0180\u017c\3\2\2\2"+ + "\u0180\u017f\3\2\2\2\u0181\u0182\3\2\2\2\u0182\u0184\b\27\1\2\u0183\u0185"+ + "\5\u0088E\2\u0184\u0183\3\2\2\2\u0184\u0185\3\2\2\2\u0185\u0186\3\2\2"+ + "\2\u0186\u0187\b\27\1\2\u0187\u0189\b\27\1\2\u0188\u018a\5P)\2\u0189\u0188"+ + "\3\2\2\2\u0189\u018a\3\2\2\2\u018a\u018b\3\2\2\2\u018b\u0195\b\27\1\2"+ + "\u018c\u018d\7\35\2\2\u018d\u0192\58\35\2\u018e\u018f\7\5\2\2\u018f\u0191"+ + "\58\35\2\u0190\u018e\3\2\2\2\u0191\u0194\3\2\2\2\u0192\u0190\3\2\2\2\u0192"+ + "\u0193\3\2\2\2\u0193\u0196\3\2\2\2\u0194\u0192\3\2\2\2\u0195\u018c\3\2"+ + "\2\2\u0195\u0196\3\2\2\2\u0196\u0197\3\2\2\2\u0197\u019a\b\27\1\2\u0198"+ + "\u0199\7\b\2\2\u0199\u019b\7\u008d\2\2\u019a\u0198\3\2\2\2\u019a\u019b"+ + "\3\2\2\2\u019b\u019c\3\2\2\2\u019c\u01b1\b\27\1\2\u019d\u01ac\7\4\2\2"+ + "\u019e\u019f\5D#\2\u019f\u01a0\b\27\1\2\u01a0\u01ab\3\2\2\2\u01a1\u01a2"+ + "\5\64\33\2\u01a2\u01a3\b\27\1\2\u01a3\u01ab\3\2\2\2\u01a4\u01a5\5.\30"+ + "\2\u01a5\u01a6\b\27\1\2\u01a6\u01ab\3\2\2\2\u01a7\u01a8\5d\63\2\u01a8"+ + "\u01a9\b\27\1\2\u01a9\u01ab\3\2\2\2\u01aa\u019e\3\2\2\2\u01aa\u01a1\3"+ + "\2\2\2\u01aa\u01a4\3\2\2\2\u01aa\u01a7\3\2\2\2\u01ab\u01ae\3\2\2\2\u01ac"+ + "\u01aa\3\2\2\2\u01ac\u01ad\3\2\2\2\u01ad\u01af\3\2\2\2\u01ae\u01ac\3\2"+ + "\2\2\u01af\u01b2\7\6\2\2\u01b0\u01b2\7\r\2\2\u01b1\u019d\3\2\2\2\u01b1"+ + "\u01b0\3\2\2\2\u01b2-\3\2\2\2\u01b3\u01b4\5\60\31\2\u01b4\u01b5\b\30\1"+ + "\2\u01b5\u01ba\3\2\2\2\u01b6\u01b7\5\62\32\2\u01b7\u01b8\b\30\1\2\u01b8"+ + "\u01ba\3\2\2\2\u01b9\u01b3\3\2\2\2\u01b9\u01b6\3\2\2\2\u01ba/\3\2\2\2"+ + "\u01bb\u01bd\5n8\2\u01bc\u01bb\3\2\2\2\u01bc\u01bd\3\2\2\2\u01bd\u01be"+ + "\3\2\2\2\u01be\u01c0\b\31\1\2\u01bf\u01c1\7\36\2\2\u01c0\u01bf\3\2\2\2"+ + "\u01c0\u01c1\3\2\2\2\u01c1\u01c4\3\2\2\2\u01c2\u01c5\7\16\2\2\u01c3\u01c5"+ + "\7\37\2\2\u01c4\u01c2\3\2\2\2\u01c4\u01c3\3\2\2\2\u01c4\u01c5\3\2\2\2"+ + "\u01c5\u01c7\3\2\2\2\u01c6\u01c8\7 \2\2\u01c7\u01c6\3\2\2\2\u01c7\u01c8"+ + "\3\2\2\2\u01c8\u01ca\3\2\2\2\u01c9\u01cb\7!\2\2\u01ca\u01c9\3\2\2\2\u01ca"+ + "\u01cb\3\2\2\2\u01cb\u01cd\3\2\2\2\u01cc\u01ce\7\"\2\2\u01cd\u01cc\3\2"+ + "\2\2\u01cd\u01ce\3\2\2\2\u01ce\u01cf\3\2\2\2\u01cf\u01d0\7#\2\2\u01d0"+ + "\u01d1\5\u0088E\2\u01d1\u01d2\b\31\1\2\u01d2\u01d3\7\b\2\2\u01d3\u01d5"+ + "\5X-\2\u01d4\u01d6\5<\37\2\u01d5\u01d4\3\2\2\2\u01d5\u01d6\3\2\2\2\u01d6"+ + "\u01d7\3\2\2\2\u01d7\u01da\b\31\1\2\u01d8\u01d9\7\31\2\2\u01d9\u01db\7"+ + "\u008d\2\2\u01da\u01d8\3\2\2\2\u01da\u01db\3\2\2\2\u01db\u01dc\3\2\2\2"+ + "\u01dc\u01f0\b\31\1\2\u01dd\u01eb\7\4\2\2\u01de\u01e7\7$\2\2\u01df\u01e7"+ + "\7%\2\2\u01e0\u01e7\7&\2\2\u01e1\u01e7\7\'\2\2\u01e2\u01e7\7(\2\2\u01e3"+ + "\u01e7\7)\2\2\u01e4\u01e7\7*\2\2\u01e5\u01e7\7+\2\2\u01e6\u01de\3\2\2"+ + "\2\u01e6\u01df\3\2\2\2\u01e6\u01e0\3\2\2\2\u01e6\u01e1\3\2\2\2\u01e6\u01e2"+ + "\3\2\2\2\u01e6\u01e3\3\2\2\2\u01e6\u01e4\3\2\2\2\u01e6\u01e5\3\2\2\2\u01e7"+ + "\u01e9\3\2\2\2\u01e8\u01ea\7\5\2\2\u01e9\u01e8\3\2\2\2\u01e9\u01ea\3\2"+ + "\2\2\u01ea\u01ec\3\2\2\2\u01eb\u01e6\3\2\2\2\u01ec\u01ed\3\2\2\2\u01ed"+ + "\u01eb\3\2\2\2\u01ed\u01ee\3\2\2\2\u01ee\u01ef\3\2\2\2\u01ef\u01f1\7\6"+ + "\2\2\u01f0\u01dd\3\2\2\2\u01f0\u01f1\3\2\2\2\u01f1\u020d\3\2\2\2\u01f2"+ + "\u01f8\7\4\2\2\u01f3\u01f4\5D#\2\u01f4\u01f5\b\31\1\2\u01f5\u01f7\3\2"+ + "\2\2\u01f6\u01f3\3\2\2\2\u01f7\u01fa\3\2\2\2\u01f8\u01f6\3\2\2\2\u01f8"+ + "\u01f9\3\2\2\2\u01f9\u0201\3\2\2\2\u01fa\u01f8\3\2\2\2\u01fb\u01fc\5l"+ + "\67\2\u01fc\u01fd\b\31\1\2\u01fd\u0202\3\2\2\2\u01fe\u01ff\5j\66\2\u01ff"+ + "\u0200\b\31\1\2\u0200\u0202\3\2\2\2\u0201\u01fb\3\2\2\2\u0201\u01fe\3"+ + "\2\2\2\u0201\u0202\3\2\2\2\u0202\u0208\3\2\2\2\u0203\u0204\5D#\2\u0204"+ + "\u0205\b\31\1\2\u0205\u0207\3\2\2\2\u0206\u0203\3\2\2\2\u0207\u020a\3"+ + "\2\2\2\u0208\u0206\3\2\2\2\u0208\u0209\3\2\2\2\u0209\u020b\3\2\2\2\u020a"+ + "\u0208\3\2\2\2\u020b\u020e\7\6\2\2\u020c\u020e\7\r\2\2\u020d\u01f2\3\2"+ + "\2\2\u020d\u020c\3\2\2\2\u020e\u020f\3\2\2\2\u020f\u0210\b\31\1\2\u0210"+ + "\61\3\2\2\2\u0211\u0213\5n8\2\u0212\u0211\3\2\2\2\u0212\u0213\3\2\2\2"+ + "\u0213\u0214\3\2\2\2\u0214\u0216\b\32\1\2\u0215\u0217\7\36\2\2\u0216\u0215"+ + "\3\2\2\2\u0216\u0217\3\2\2\2\u0217\u021a\3\2\2\2\u0218\u021b\7\16\2\2"+ + "\u0219\u021b\7\37\2\2\u021a\u0218\3\2\2\2\u021a\u0219\3\2\2\2\u021a\u021b"+ + "\3\2\2\2\u021b\u021d\3\2\2\2\u021c\u021e\7 \2\2\u021d\u021c\3\2\2\2\u021d"+ + "\u021e\3\2\2\2\u021e\u0220\3\2\2\2\u021f\u0221\7!\2\2\u0220\u021f\3\2"+ + "\2\2\u0220\u0221\3\2\2\2\u0221\u0223\3\2\2\2\u0222\u0224\7\"\2\2\u0223"+ + "\u0222\3\2\2\2\u0223\u0224\3\2\2\2\u0224\u0225\3\2\2\2\u0225\u0226\7,"+ + "\2\2\u0226\u0227\5\u0088E\2\u0227\u022a\b\32\1\2\u0228\u0229\7-\2\2\u0229"+ + "\u022b\5\u0088E\2\u022a\u0228\3\2\2\2\u022a\u022b\3\2\2\2\u022b\u022c"+ + "\3\2\2\2\u022c\u022d\b\32\1\2\u022d\u022e\7\b\2\2\u022e\u0230\5X-\2\u022f"+ + "\u0231\5<\37\2\u0230\u022f\3\2\2\2\u0230\u0231\3\2\2\2\u0231\u0232\3\2"+ + "\2\2\u0232\u0235\b\32\1\2\u0233\u0234\7\31\2\2\u0234\u0236\7\u008d\2\2"+ + "\u0235\u0233\3\2\2\2\u0235\u0236\3\2\2\2\u0236\u0237\3\2\2\2\u0237\u024d"+ + "\b\32\1\2\u0238\u0248\7\4\2\2\u0239\u0244\7.\2\2\u023a\u0244\7$\2\2\u023b"+ + "\u0244\7&\2\2\u023c\u0244\7\'\2\2\u023d\u0244\7(\2\2\u023e\u0244\7)\2"+ + "\2\u023f\u0244\7/\2\2\u0240\u0244\7\60\2\2\u0241\u0244\7*\2\2\u0242\u0244"+ + "\7+\2\2\u0243\u0239\3\2\2\2\u0243\u023a\3\2\2\2\u0243\u023b\3\2\2\2\u0243"+ + "\u023c\3\2\2\2\u0243\u023d\3\2\2\2\u0243\u023e\3\2\2\2\u0243\u023f\3\2"+ + "\2\2\u0243\u0240\3\2\2\2\u0243\u0241\3\2\2\2\u0243\u0242\3\2\2\2\u0244"+ + "\u0246\3\2\2\2\u0245\u0247\7\5\2\2\u0246\u0245\3\2\2\2\u0246\u0247\3\2"+ + "\2\2\u0247\u0249\3\2\2\2\u0248\u0243\3\2\2\2\u0249\u024a\3\2\2\2\u024a"+ + "\u0248\3\2\2\2\u024a\u024b\3\2\2\2\u024b\u024c\3\2\2\2\u024c\u024e\7\6"+ + "\2\2\u024d\u0238\3\2\2\2\u024d\u024e\3\2\2\2\u024e\u0277\3\2\2\2\u024f"+ + "\u025b\7\4\2\2\u0250\u0251\7\61\2\2\u0251\u0256\5\u0088E\2\u0252\u0253"+ + "\7\5\2\2\u0253\u0255\5\u0088E\2\u0254\u0252\3\2\2\2\u0255\u0258\3\2\2"+ + "\2\u0256\u0254\3\2\2\2\u0256\u0257\3\2\2\2\u0257\u0259\3\2\2\2\u0258\u0256"+ + "\3\2\2\2\u0259\u025a\7\r\2\2\u025a\u025c\3\2\2\2\u025b\u0250\3\2\2\2\u025b"+ + "\u025c\3\2\2\2\u025c\u0262\3\2\2\2\u025d\u025e\5D#\2\u025e\u025f\b\32"+ + "\1\2\u025f\u0261\3\2\2\2\u0260\u025d\3\2\2\2\u0261\u0264\3\2\2\2\u0262"+ + "\u0260\3\2\2\2\u0262\u0263\3\2\2\2\u0263\u026b\3\2\2\2\u0264\u0262\3\2"+ + "\2\2\u0265\u0266\5l\67\2\u0266\u0267\b\32\1\2\u0267\u026c\3\2\2\2\u0268"+ + "\u0269\5j\66\2\u0269\u026a\b\32\1\2\u026a\u026c\3\2\2\2\u026b\u0265\3"+ + "\2\2\2\u026b\u0268\3\2\2\2\u026b\u026c\3\2\2\2\u026c\u0272\3\2\2\2\u026d"+ + "\u026e\5D#\2\u026e\u026f\b\32\1\2\u026f\u0271\3\2\2\2\u0270\u026d\3\2"+ + "\2\2\u0271\u0274\3\2\2\2\u0272\u0270\3\2\2\2\u0272\u0273\3\2\2\2\u0273"+ + "\u0275\3\2\2\2\u0274\u0272\3\2\2\2\u0275\u0278\7\6\2\2\u0276\u0278\7\r"+ + "\2\2\u0277\u024f\3\2\2\2\u0277\u0276\3\2\2\2\u0278\u0279\3\2\2\2\u0279"+ + "\u027a\b\32\1\2\u027a\63\3\2\2\2\u027b\u027d\5n8\2\u027c\u027b\3\2\2\2"+ + "\u027c\u027d\3\2\2\2\u027d\u027e\3\2\2\2\u027e\u0280\b\33\1\2\u027f\u0281"+ + "\7\36\2\2\u0280\u027f\3\2\2\2\u0280\u0281\3\2\2\2\u0281\u0282\3\2\2\2"+ + "\u0282\u0284\7\62\2\2\u0283\u0285\5P)\2\u0284\u0283\3\2\2\2\u0284\u0285"+ + "\3\2\2\2\u0285\u0286\3\2\2\2\u0286\u0287\b\33\1\2\u0287\u0288\5\u0088"+ + "E\2\u0288\u0289\b\33\1\2\u0289\u0292\7\63\2\2\u028a\u028f\5:\36\2\u028b"+ + "\u028c\7\5\2\2\u028c\u028e\5:\36\2\u028d\u028b\3\2\2\2\u028e\u0291\3\2"+ + "\2\2\u028f\u028d\3\2\2\2\u028f\u0290\3\2\2\2\u0290\u0293\3\2\2\2\u0291"+ + "\u028f\3\2\2\2\u0292\u028a\3\2\2\2\u0292\u0293\3\2\2\2\u0293\u0294\3\2"+ + "\2\2\u0294\u0295\7\64\2\2\u0295\u0296\3\2\2\2\u0296\u029c\b\33\1\2\u0297"+ + "\u0298\7\b\2\2\u0298\u029a\5X-\2\u0299\u029b\5<\37\2\u029a\u0299\3\2\2"+ + "\2\u029a\u029b\3\2\2\2\u029b\u029d\3\2\2\2\u029c\u0297\3\2\2\2\u029c\u029d"+ + "\3\2\2\2\u029d\u029e\3\2\2\2\u029e\u029f\b\33\1\2\u029f\u02a9\b\33\1\2"+ + "\u02a0\u02a1\7\65\2\2\u02a1\u02a6\5\66\34\2\u02a2\u02a3\7\5\2\2\u02a3"+ + "\u02a5\5\66\34\2\u02a4\u02a2\3\2\2\2\u02a5\u02a8\3\2\2\2\u02a6\u02a4\3"+ + "\2\2\2\u02a6\u02a7\3\2\2\2\u02a7\u02aa\3\2\2\2\u02a8\u02a6\3\2\2\2\u02a9"+ + "\u02a0\3\2\2\2\u02a9\u02aa\3\2\2\2\u02aa\u02ab\3\2\2\2\u02ab\u02bb\b\33"+ + "\1\2\u02ac\u02b6\7\4\2\2\u02ad\u02b2\7&\2\2\u02ae\u02b2\7\'\2\2\u02af"+ + "\u02b2\7(\2\2\u02b0\u02b2\7)\2\2\u02b1\u02ad\3\2\2\2\u02b1\u02ae\3\2\2"+ + "\2\u02b1\u02af\3\2\2\2\u02b1\u02b0\3\2\2\2\u02b2\u02b4\3\2\2\2\u02b3\u02b5"+ + "\7\5\2\2\u02b4\u02b3\3\2\2\2\u02b4\u02b5\3\2\2\2\u02b5\u02b7\3\2\2\2\u02b6"+ + "\u02b1\3\2\2\2\u02b7\u02b8\3\2\2\2\u02b8\u02b6\3\2\2\2\u02b8\u02b9\3\2"+ + "\2\2\u02b9\u02ba\3\2\2\2\u02ba\u02bc\7\6\2\2\u02bb\u02ac\3\2\2\2\u02bb"+ + "\u02bc\3\2\2\2\u02bc\u02d1\3\2\2\2\u02bd\u02cc\7\4\2\2\u02be\u02bf\5D"+ + "#\2\u02bf\u02c0\b\33\1\2\u02c0\u02cb\3\2\2\2\u02c1\u02c2\5f\64\2\u02c2"+ + "\u02c3\b\33\1\2\u02c3\u02cb\3\2\2\2\u02c4\u02c5\5b\62\2\u02c5\u02c6\b"+ + "\33\1\2\u02c6\u02cb\3\2\2\2\u02c7\u02c8\5h\65\2\u02c8\u02c9\b\33\1\2\u02c9"+ + "\u02cb\3\2\2\2\u02ca\u02be\3\2\2\2\u02ca\u02c1\3\2\2\2\u02ca\u02c4\3\2"+ + "\2\2\u02ca\u02c7\3\2\2\2\u02cb\u02ce\3\2\2\2\u02cc\u02ca\3\2\2\2\u02cc"+ + "\u02cd\3\2\2\2\u02cd\u02cf\3\2\2\2\u02ce\u02cc\3\2\2\2\u02cf\u02d2\7\6"+ + "\2\2\u02d0\u02d2\7\r\2\2\u02d1\u02bd\3\2\2\2\u02d1\u02d0\3\2\2\2\u02d2"+ + "\u02d3\3\2\2\2\u02d3\u02d4\b\33\1\2\u02d4\65\3\2\2\2\u02d5\u02d6\5V,\2"+ + "\u02d6\u02d7\b\34\1\2\u02d7\67\3\2\2\2\u02d8\u02d9\5V,\2\u02d9\u02da\b"+ + "\35\1\2\u02da9\3\2\2\2\u02db\u02dc\5\u0088E\2\u02dc\u02dd\b\36\1\2\u02dd"+ + "\u02de\7\b\2\2\u02de\u02e0\5X-\2\u02df\u02e1\5<\37\2\u02e0\u02df\3\2\2"+ + "\2\u02e0\u02e1\3\2\2\2\u02e1\u02e2\3\2\2\2\u02e2\u02f2\b\36\1\2\u02e3"+ + "\u02ed\7\4\2\2\u02e4\u02e9\7&\2\2\u02e5\u02e9\7\'\2\2\u02e6\u02e9\7(\2"+ + "\2\u02e7\u02e9\7)\2\2\u02e8\u02e4\3\2\2\2\u02e8\u02e5\3\2\2\2\u02e8\u02e6"+ + "\3\2\2\2\u02e8\u02e7\3\2\2\2\u02e9\u02eb\3\2\2\2\u02ea\u02ec\7\5\2\2\u02eb"+ + "\u02ea\3\2\2\2\u02eb\u02ec\3\2\2\2\u02ec\u02ee\3\2\2\2\u02ed\u02e8\3\2"+ + "\2\2\u02ee\u02ef\3\2\2\2\u02ef\u02ed\3\2\2\2\u02ef\u02f0\3\2\2\2\u02f0"+ + "\u02f1\3\2\2\2\u02f1\u02f3\7\6\2\2\u02f2\u02e3\3\2\2\2\u02f2\u02f3\3\2"+ + "\2\2\u02f3\u02fd\3\2\2\2\u02f4\u02f8\7\4\2\2\u02f5\u02f7\5D#\2\u02f6\u02f5"+ + "\3\2\2\2\u02f7\u02fa\3\2\2\2\u02f8\u02f6\3\2\2\2\u02f8\u02f9\3\2\2\2\u02f9"+ + "\u02fb\3\2\2\2\u02fa\u02f8\3\2\2\2\u02fb\u02fc\b\36\1\2\u02fc\u02fe\7"+ + "\6\2\2\u02fd\u02f4\3\2\2\2\u02fd\u02fe\3\2\2\2\u02fe\u02ff\3\2\2\2\u02ff"+ + "\u0300\b\36\1\2\u0300;\3\2\2\2\u0301\u0308\7\17\2\2\u0302\u0305\5\u008e"+ + "H\2\u0303\u0304\7\66\2\2\u0304\u0306\5\u008cG\2\u0305\u0303\3\2\2\2\u0305"+ + "\u0306\3\2\2\2\u0306\u0309\3\2\2\2\u0307\u0309\t\4\2\2\u0308\u0302\3\2"+ + "\2\2\u0308\u0307\3\2\2\2\u0309\u030c\3\2\2\2\u030a\u030d\79\2\2\u030b"+ + "\u030d\7:\2\2\u030c\u030a\3\2\2\2\u030c\u030b\3\2\2\2\u030c\u030d\3\2"+ + "\2\2\u030d\u030e\3\2\2\2\u030e\u030f\7\20\2\2\u030f\u0310\b\37\1\2\u0310"+ + "=\3\2\2\2\u0311\u0313\5n8\2\u0312\u0311\3\2\2\2\u0312\u0313\3\2\2\2\u0313"+ + "\u0314\3\2\2\2\u0314\u0316\b \1\2\u0315\u0317\7;\2\2\u0316\u0315\3\2\2"+ + "\2\u0316\u0317\3\2\2\2\u0317\u0318\3\2\2\2\u0318\u0319\7<\2\2\u0319\u031a"+ + "\5\u0088E\2\u031a\u031c\b \1\2\u031b\u031d\5P)\2\u031c\u031b\3\2\2\2\u031c"+ + "\u031d\3\2\2\2\u031d\u031e\3\2\2\2\u031e\u0321\b \1\2\u031f\u0320\7\b"+ + "\2\2\u0320\u0322\7\u008d\2\2\u0321\u031f\3\2\2\2\u0321\u0322\3\2\2\2\u0322"+ + "\u0323\3\2\2\2\u0323\u032a\b \1\2\u0324\u0327\7\4\2\2\u0325\u0328\7=\2"+ + "\2\u0326\u0328\7>\2\2\u0327\u0325\3\2\2\2\u0327\u0326\3\2\2\2\u0327\u0328"+ + "\3\2\2\2\u0328\u0329\3\2\2\2\u0329\u032b\7\6\2\2\u032a\u0324\3\2\2\2\u032a"+ + "\u032b\3\2\2\2\u032b\u033a\3\2\2\2\u032c\u0335\7\4\2\2\u032d\u032e\5D"+ + "#\2\u032e\u032f\b \1\2\u032f\u0334\3\2\2\2\u0330\u0331\5d\63\2\u0331\u0332"+ + "\b \1\2\u0332\u0334\3\2\2\2\u0333\u032d\3\2\2\2\u0333\u0330\3\2\2\2\u0334"+ + "\u0337\3\2\2\2\u0335\u0333\3\2\2\2\u0335\u0336\3\2\2\2\u0336\u0338\3\2"+ + "\2\2\u0337\u0335\3\2\2\2\u0338\u033b\7\6\2\2\u0339\u033b\7\r\2\2\u033a"+ + "\u032c\3\2\2\2\u033a\u0339\3\2\2\2\u033b\u033c\3\2\2\2\u033c\u033d\b "+ + "\1\2\u033d?\3\2\2\2\u033e\u0340\5n8\2\u033f\u033e\3\2\2\2\u033f\u0340"+ + "\3\2\2\2\u0340\u0341\3\2\2\2\u0341\u0342\b!\1\2\u0342\u0343\7?\2\2\u0343"+ + "\u0344\5\u0088E\2\u0344\u0346\b!\1\2\u0345\u0347\5P)\2\u0346\u0345\3\2"+ + "\2\2\u0346\u0347\3\2\2\2\u0347\u0348\3\2\2\2\u0348\u034b\b!\1\2\u0349"+ + "\u034a\7\b\2\2\u034a\u034c\7\u008d\2\2\u034b\u0349\3\2\2\2\u034b\u034c"+ + "\3\2\2\2\u034c\u034d\3\2\2\2\u034d\u0354\b!\1\2\u034e\u0351\7\4\2\2\u034f"+ + "\u0352\7=\2\2\u0350\u0352\7>\2\2\u0351\u034f\3\2\2\2\u0351\u0350\3\2\2"+ + "\2\u0351\u0352\3\2\2\2\u0352\u0353\3\2\2\2\u0353\u0355\7\6\2\2\u0354\u034e"+ + "\3\2\2\2\u0354\u0355\3\2\2\2\u0355\u0367\3\2\2\2\u0356\u0362\7\4\2\2\u0357"+ + "\u0358\5D#\2\u0358\u0359\b!\1\2\u0359\u0361\3\2\2\2\u035a\u035b\5B\"\2"+ + "\u035b\u035c\b!\1\2\u035c\u0361\3\2\2\2\u035d\u035e\5d\63\2\u035e\u035f"+ + "\b!\1\2\u035f\u0361\3\2\2\2\u0360\u0357\3\2\2\2\u0360\u035a\3\2\2\2\u0360"+ + "\u035d\3\2\2\2\u0361\u0364\3\2\2\2\u0362\u0360\3\2\2\2\u0362\u0363\3\2"+ + "\2\2\u0363\u0365\3\2\2\2\u0364\u0362\3\2\2\2\u0365\u0368\7\6\2\2\u0366"+ + "\u0368\7\r\2\2\u0367\u0356\3\2\2\2\u0367\u0366\3\2\2\2\u0368\u0369\3\2"+ + "\2\2\u0369\u036a\b!\1\2\u036aA\3\2\2\2\u036b\u036c\7@\2\2\u036c\u036f"+ + "\5\u0088E\2\u036d\u036f\5\u0088E\2\u036e\u036b\3\2\2\2\u036e\u036d\3\2"+ + "\2\2\u036f\u0370\3\2\2\2\u0370\u0373\b\"\1\2\u0371\u0372\7\31\2\2\u0372"+ + "\u0374\7\u0089\2\2\u0373\u0371\3\2\2\2\u0373\u0374\3\2\2\2\u0374\u0375"+ + "\3\2\2\2\u0375\u0380\b\"\1\2\u0376\u037a\7\4\2\2\u0377\u0379\5D#\2\u0378"+ + "\u0377\3\2\2\2\u0379\u037c\3\2\2\2\u037a\u0378\3\2\2\2\u037a\u037b\3\2"+ + "\2\2\u037b\u037d\3\2\2\2\u037c\u037a\3\2\2\2\u037d\u037e\b\"\1\2\u037e"+ + "\u0381\7\6\2\2\u037f\u0381\7\r\2\2\u0380\u0376\3\2\2\2\u0380\u037f\3\2"+ + "\2\2\u0381C\3\2\2\2\u0382\u0384\7A\2\2\u0383\u0385\7\u008d\2\2\u0384\u0383"+ + "\3\2\2\2\u0384\u0385\3\2\2\2\u0385\u0386\3\2\2\2\u0386\u0392\b#\1\2\u0387"+ + "\u0388\7\63\2\2\u0388\u038d\5F$\2\u0389\u038a\7\5\2\2\u038a\u038c\5F$"+ + "\2\u038b\u0389\3\2\2\2\u038c\u038f\3\2\2\2\u038d\u038b\3\2\2\2\u038d\u038e"+ + "\3\2\2\2\u038e\u0390\3\2\2\2\u038f\u038d\3\2\2\2\u0390\u0391\7\64\2\2"+ + "\u0391\u0393\3\2\2\2\u0392\u0387\3\2\2\2\u0392\u0393\3\2\2\2\u0393\u0394"+ + "\3\2\2\2\u0394\u03a6\b#\1\2\u0395\u039f\7\4\2\2\u0396\u0397\5D#\2\u0397"+ + "\u0398\b#\1\2\u0398\u03a0\3\2\2\2\u0399\u039a\5H%\2\u039a\u039b\b#\1\2"+ + "\u039b\u03a0\3\2\2\2\u039c\u039d\5N(\2\u039d\u039e\b#\1\2\u039e\u03a0"+ + "\3\2\2\2\u039f\u0396\3\2\2\2\u039f\u0399\3\2\2\2\u039f\u039c\3\2\2\2\u03a0"+ + "\u03a1\3\2\2\2\u03a1\u039f\3\2\2\2\u03a1\u03a2\3\2\2\2\u03a2\u03a3\3\2"+ + "\2\2\u03a3\u03a4\7\6\2\2\u03a4\u03a7\3\2\2\2\u03a5\u03a7\7\r\2\2\u03a6"+ + "\u0395\3\2\2\2\u03a6\u03a5\3\2\2\2\u03a7E\3\2\2\2\u03a8\u03aa\7\u008d"+ + "\2\2\u03a9\u03a8\3\2\2\2\u03a9\u03aa\3\2\2\2\u03aa\u03ab\3\2\2\2\u03ab"+ + "\u03ad\7\31\2\2\u03ac\u03ae\t\5\2\2\u03ad\u03ac\3\2\2\2\u03ad\u03ae\3"+ + "\2\2\2\u03ae\u03af\3\2\2\2\u03af\u03b0\b$\1\2\u03b0G\3\2\2\2\u03b1\u03b2"+ + "\5D#\2\u03b2\u03b3\b%\1\2\u03b3\u03b8\3\2\2\2\u03b4\u03b5\5J&\2\u03b5"+ + "\u03b6\b%\1\2\u03b6\u03b8\3\2\2\2\u03b7\u03b1\3\2\2\2\u03b7\u03b4\3\2"+ + "\2\2\u03b8I\3\2\2\2\u03b9\u03ba\5L\'\2\u03ba\u03bb\b&\1\2\u03bb\u03c6"+ + "\3\2\2\2\u03bc\u03bd\5*\26\2\u03bd\u03be\b&\1\2\u03be\u03c6\3\2\2\2\u03bf"+ + "\u03c0\5(\25\2\u03c0\u03c1\b&\1\2\u03c1\u03c6\3\2\2\2\u03c2\u03c3\5B\""+ + "\2\u03c3\u03c4\b&\1\2\u03c4\u03c6\3\2\2\2\u03c5\u03b9\3\2\2\2\u03c5\u03bc"+ + "\3\2\2\2\u03c5\u03bf\3\2\2\2\u03c5\u03c2\3\2\2\2\u03c6K\3\2\2\2\u03c7"+ + "\u03c8\5\64\33\2\u03c8\u03c9\b\'\1\2\u03c9\u03d1\3\2\2\2\u03ca\u03cb\5"+ + ":\36\2\u03cb\u03cc\b\'\1\2\u03cc\u03d1\3\2\2\2\u03cd\u03ce\5.\30\2\u03ce"+ + "\u03cf\b\'\1\2\u03cf\u03d1\3\2\2\2\u03d0\u03c7\3\2\2\2\u03d0\u03ca\3\2"+ + "\2\2\u03d0\u03cd\3\2\2\2\u03d1M\3\2\2\2\u03d2\u03d3\7B\2\2\u03d3\u03d4"+ + "\5\\/\2\u03d4\u03d5\b(\1\2\u03d5\u03d6\7\r\2\2\u03d6O\3\2\2\2\u03d7\u03d8"+ + "\7C\2\2\u03d8\u03dd\5R*\2\u03d9\u03da\7\5\2\2\u03da\u03dc\5R*\2\u03db"+ + "\u03d9\3\2\2\2\u03dc\u03df\3\2\2\2\u03dd\u03db\3\2\2\2\u03dd\u03de\3\2"+ + "\2\2\u03de\u03e0\3\2\2\2\u03df\u03dd\3\2\2\2\u03e0\u03e1\7D\2\2\u03e1"+ + "Q\3\2\2\2\u03e2\u03e3\5\u0088E\2\u03e3\u03ed\b*\1\2\u03e4\u03e5\7\35\2"+ + "\2\u03e5\u03ea\5V,\2\u03e6\u03e7\7E\2\2\u03e7\u03e9\5V,\2\u03e8\u03e6"+ + "\3\2\2\2\u03e9\u03ec\3\2\2\2\u03ea\u03e8\3\2\2\2\u03ea\u03eb\3\2\2\2\u03eb"+ + "\u03ee\3\2\2\2\u03ec\u03ea\3\2\2\2\u03ed\u03e4\3\2\2\2\u03ed\u03ee\3\2"+ + "\2\2\u03ee\u03ef\3\2\2\2\u03ef\u03f0\b*\1\2\u03f0S\3\2\2\2\u03f1\u03f2"+ + "\5V,\2\u03f2\u03f3\b+\1\2\u03f3\u03f8\3\2\2\2\u03f4\u03f5\5Z.\2\u03f5"+ + "\u03f6\b+\1\2\u03f6\u03f8\3\2\2\2\u03f7\u03f1\3\2\2\2\u03f7\u03f4\3\2"+ + "\2\2\u03f8U\3\2\2\2\u03f9\u0405\5\\/\2\u03fa\u03fb\7C\2\2\u03fb\u0400"+ + "\5T+\2\u03fc\u03fd\7\5\2\2\u03fd\u03ff\5T+\2\u03fe\u03fc\3\2\2\2\u03ff"+ + "\u0402\3\2\2\2\u0400\u03fe\3\2\2\2\u0400\u0401\3\2\2\2\u0401\u0403\3\2"+ + "\2\2\u0402\u0400\3\2\2\2\u0403\u0404\7D\2\2\u0404\u0406\3\2\2\2\u0405"+ + "\u03fa\3\2\2\2\u0405\u0406\3\2\2\2\u0406W\3\2\2\2\u0407\u0408\5`\61\2"+ + "\u0408\u0409\b-\1\2\u0409\u040e\3\2\2\2\u040a\u040b\5V,\2\u040b\u040c"+ + "\b-\1\2\u040c\u040e\3\2\2\2\u040d\u0407\3\2\2\2\u040d\u040a\3\2\2\2\u040e"+ + "Y\3\2\2\2\u040f\u0410\78\2\2\u0410\u0416\b.\1\2\u0411\u0412\t\6\2\2\u0412"+ + "\u0413\b.\1\2\u0413\u0414\5V,\2\u0414\u0415\b.\1\2\u0415\u0417\3\2\2\2"+ + "\u0416\u0411\3\2\2\2\u0416\u0417\3\2\2\2\u0417[\3\2\2\2\u0418\u041b\5"+ + "\u0088E\2\u0419\u041a\7\25\2\2\u041a\u041c\7\u0089\2\2\u041b\u0419\3\2"+ + "\2\2\u041b\u041c\3\2\2\2\u041c\u0424\3\2\2\2\u041d\u041f\5^\60\2\u041e"+ + "\u041d\3\2\2\2\u041f\u0422\3\2\2\2\u0420\u041e\3\2\2\2\u0420\u0421\3\2"+ + "\2\2\u0421\u0423\3\2\2\2\u0422\u0420\3\2\2\2\u0423\u0425\5^\60\2\u0424"+ + "\u0420\3\2\2\2\u0424\u0425\3\2\2\2\u0425]\3\2\2\2\u0426\u0428\7G\2\2\u0427"+ + "\u0429\7H\2\2\u0428\u0427\3\2\2\2\u0428\u0429\3\2\2\2\u0429\u042a\3\2"+ + "\2\2\u042a\u042d\5\u0088E\2\u042b\u042c\7\25\2\2\u042c\u042e\7\u0089\2"+ + "\2\u042d\u042b\3\2\2\2\u042d\u042e\3\2\2\2\u042e_\3\2\2\2\u042f\u0430"+ + "\7I\2\2\u0430\u043a\b\61\1\2\u0431\u0432\7J\2\2\u0432\u043a\b\61\1\2\u0433"+ + "\u0434\7K\2\2\u0434\u043a\b\61\1\2\u0435\u0436\7L\2\2\u0436\u043a\b\61"+ + "\1\2\u0437\u0438\7M\2\2\u0438\u043a\b\61\1\2\u0439\u042f\3\2\2\2\u0439"+ + "\u0431\3\2\2\2\u0439\u0433\3\2\2\2\u0439\u0435\3\2\2\2\u0439\u0437\3\2"+ + "\2\2\u043aa\3\2\2\2\u043b\u043d\7N\2\2\u043c\u043e\5\u008aF\2\u043d\u043c"+ + "\3\2\2\2\u043d\u043e\3\2\2\2\u043e\u043f\3\2\2\2\u043f\u0446\b\62\1\2"+ + "\u0440\u0442\7\b\2\2\u0441\u0443\5r:\2\u0442\u0441\3\2\2\2\u0442\u0443"+ + "\3\2\2\2\u0443\u0444\3\2\2\2\u0444\u0447\7\r\2\2\u0445\u0447\7\r\2\2\u0446"+ + "\u0440\3\2\2\2\u0446\u0445\3\2\2\2\u0447\u0448\3\2\2\2\u0448\u0449\b\62"+ + "\1\2\u0449c\3\2\2\2\u044a\u044c\7O\2\2\u044b\u044a\3\2\2\2\u044b\u044c"+ + "\3\2\2\2\u044c\u044d\3\2\2\2\u044d\u044e\b\63\1\2\u044e\u0455\7P\2\2\u044f"+ + "\u0453\5\u008aF\2\u0450\u0451\7\63\2\2\u0451\u0452\7\u008c\2\2\u0452\u0454"+ + "\7\64\2\2\u0453\u0450\3\2\2\2\u0453\u0454\3\2\2\2\u0454\u0456\3\2\2\2"+ + "\u0455\u044f\3\2\2\2\u0455\u0456\3\2\2\2\u0456\u0457\3\2\2\2\u0457\u045e"+ + "\b\63\1\2\u0458\u045a\7\b\2\2\u0459\u045b\5p9\2\u045a\u0459\3\2\2\2\u045a"+ + "\u045b\3\2\2\2\u045b\u045c\3\2\2\2\u045c\u045f\7\r\2\2\u045d\u045f\7\r"+ + "\2\2\u045e\u0458\3\2\2\2\u045e\u045d\3\2\2\2\u045f\u0460\3\2\2\2\u0460"+ + "\u0461\b\63\1\2\u0461e\3\2\2\2\u0462\u0469\t\7\2\2\u0463\u0467\5\u008a"+ + "F\2\u0464\u0465\7\63\2\2\u0465\u0466\7\u008c\2\2\u0466\u0468\7\64\2\2"+ + "\u0467\u0464\3\2\2\2\u0467\u0468\3\2\2\2\u0468\u046a\3\2\2\2\u0469\u0463"+ + "\3\2\2\2\u0469\u046a\3\2\2\2\u046a\u046b\3\2\2\2\u046b\u0472\b\64\1\2"+ + "\u046c\u046e\7\b\2\2\u046d\u046f\5p9\2\u046e\u046d\3\2\2\2\u046e\u046f"+ + "\3\2\2\2\u046f\u0470\3\2\2\2\u0470\u0473\7\r\2\2\u0471\u0473\7\r\2\2\u0472"+ + "\u046c\3\2\2\2\u0472\u0471\3\2\2\2\u0473\u0474\3\2\2\2\u0474\u0475\b\64"+ + "\1\2\u0475g\3\2\2\2\u0476\u047d\t\b\2\2\u0477\u047b\5\u008aF\2\u0478\u0479"+ + "\7\63\2\2\u0479\u047a\7\u008c\2\2\u047a\u047c\7\64\2\2\u047b\u0478\3\2"+ + "\2\2\u047b\u047c\3\2\2\2\u047c\u047e\3\2\2\2\u047d\u0477\3\2\2\2\u047d"+ + "\u047e\3\2\2\2\u047e\u047f\3\2\2\2\u047f\u0486\b\65\1\2\u0480\u0482\7"+ + "\b\2\2\u0481\u0483\5p9\2\u0482\u0481\3\2\2\2\u0482\u0483\3\2\2\2\u0483"+ + "\u0484\3\2\2\2\u0484\u0487\7\r\2\2\u0485\u0487\7\r\2\2\u0486\u0480\3\2"+ + "\2\2\u0486\u0485\3\2\2\2\u0487\u0488\3\2\2\2\u0488\u0489\b\65\1\2\u0489"+ + "i\3\2\2\2\u048a\u048c\7U\2\2\u048b\u048d\5\u008aF\2\u048c\u048b\3\2\2"+ + "\2\u048c\u048d\3\2\2\2\u048d\u048e\3\2\2\2\u048e\u0495\b\66\1\2\u048f"+ + "\u0491\7\b\2\2\u0490\u0492\5r:\2\u0491\u0490\3\2\2\2\u0491\u0492\3\2\2"+ + "\2\u0492\u0493\3\2\2\2\u0493\u0496\7\r\2\2\u0494\u0496\7\r\2\2\u0495\u048f"+ + "\3\2\2\2\u0495\u0494\3\2\2\2\u0496\u0497\3\2\2\2\u0497\u0498\b\66\1\2"+ + "\u0498k\3\2\2\2\u0499\u049b\7V\2\2\u049a\u049c\5\u008aF\2\u049b\u049a"+ + "\3\2\2\2\u049b\u049c\3\2\2\2\u049c\u049d\3\2\2\2\u049d\u04a4\b\67\1\2"+ + "\u049e\u04a0\7\b\2\2\u049f\u04a1\5r:\2\u04a0\u049f\3\2\2\2\u04a0\u04a1"+ + "\3\2\2\2\u04a1\u04a2\3\2\2\2\u04a2\u04a5\7\r\2\2\u04a3\u04a5\7\r\2\2\u04a4"+ + "\u049e\3\2\2\2\u04a4\u04a3\3\2\2\2\u04a5\u04a6\3\2\2\2\u04a6\u04a7\b\67"+ + "\1\2\u04a7m\3\2\2\2\u04a8\u04ac\7W\2\2\u04a9\u04ac\7X\2\2\u04aa\u04ac"+ + "\7Y\2\2\u04ab\u04a8\3\2\2\2\u04ab\u04a9\3\2\2\2\u04ab\u04aa\3\2\2\2\u04ac"+ + "\u04ad\3\2\2\2\u04ad\u04ae\b8\1\2\u04aeo\3\2\2\2\u04af\u04b0\b9\1\2\u04b0"+ + "\u04b1\7Z\2\2\u04b1\u04b2\5r:\2\u04b2\u04b3\b9\1\2\u04b3\u05cb\3\2\2\2"+ + "\u04b4\u04b5\7[\2\2\u04b5\u04b6\5r:\2\u04b6\u04b7\b9\1\2\u04b7\u05cb\3"+ + "\2\2\2\u04b8\u04b9\7\\\2\2\u04b9\u04ba\5r:\2\u04ba\u04bb\b9\1\2\u04bb"+ + "\u05cb\3\2\2\2\u04bc\u04bd\7]\2\2\u04bd\u04be\5r:\2\u04be\u04bf\b9\1\2"+ + "\u04bf\u05cb\3\2\2\2\u04c0\u04c2\5r:\2\u04c1\u04c3\t\t\2\2\u04c2\u04c1"+ + "\3\2\2\2\u04c2\u04c3\3\2\2\2\u04c3\u04c4\3\2\2\2\u04c4\u04c5\7`\2\2\u04c5"+ + "\u04c6\5r:\2\u04c6\u04c7\b9\1\2\u04c7\u05cb\3\2\2\2\u04c8\u04ca\5r:\2"+ + "\u04c9\u04cb\t\t\2\2\u04ca\u04c9\3\2\2\2\u04ca\u04cb\3\2\2\2\u04cb\u04cc"+ + "\3\2\2\2\u04cc\u04cd\7\31\2\2\u04cd\u04ce\5r:\2\u04ce\u04cf\b9\1\2\u04cf"+ + "\u05cb\3\2\2\2\u04d0\u04d2\5t;\2\u04d1\u04d3\t\t\2\2\u04d2\u04d1\3\2\2"+ + "\2\u04d2\u04d3\3\2\2\2\u04d3\u04d4\3\2\2\2\u04d4\u04d5\7\31\2\2\u04d5"+ + "\u04d6\5t;\2\u04d6\u04d7\b9\1\2\u04d7\u05cb\3\2\2\2\u04d8\u04da\5t;\2"+ + "\u04d9\u04db\t\t\2\2\u04da\u04d9\3\2\2\2\u04da\u04db\3\2\2\2\u04db\u04dc"+ + "\3\2\2\2\u04dc\u04dd\7C\2\2\u04dd\u04de\5t;\2\u04de\u04df\b9\1\2\u04df"+ + "\u05cb\3\2\2\2\u04e0\u04e2\5t;\2\u04e1\u04e3\t\t\2\2\u04e2\u04e1\3\2\2"+ + "\2\u04e2\u04e3\3\2\2\2\u04e3\u04e4\3\2\2\2\u04e4\u04e5\7a\2\2\u04e5\u04e6"+ + "\5t;\2\u04e6\u04e7\b9\1\2\u04e7\u05cb\3\2\2\2\u04e8\u04ea\5t;\2\u04e9"+ + "\u04eb\t\t\2\2\u04ea\u04e9\3\2\2\2\u04ea\u04eb\3\2\2\2\u04eb\u04ec\3\2"+ + "\2\2\u04ec\u04ed\7D\2\2\u04ed\u04ee\5t;\2\u04ee\u04ef\b9\1\2\u04ef\u05cb"+ + "\3\2\2\2\u04f0\u04f2\5t;\2\u04f1\u04f3\t\t\2\2\u04f2\u04f1\3\2\2\2\u04f2"+ + "\u04f3\3\2\2\2\u04f3\u04f4\3\2\2\2\u04f4\u04f5\7b\2\2\u04f5\u04f6\5t;"+ + "\2\u04f6\u04f7\b9\1\2\u04f7\u05cb\3\2\2\2\u04f8\u04f9\7c\2\2\u04f9\u04fa"+ + "\5v<\2\u04fa\u04fb\7d\2\2\u04fb\u04fc\5t;\2\u04fc\u04fd\3\2\2\2\u04fd"+ + "\u04fe\b9\1\2\u04fe\u05cb\3\2\2\2\u04ff\u0500\7e\2\2\u0500\u0501\7\17"+ + "\2\2\u0501\u0502\5\u0082B\2\u0502\u0503\7\20\2\2\u0503\u0504\b9\1\2\u0504"+ + "\u05cb\3\2\2\2\u0505\u0506\7f\2\2\u0506\u0507\7\17\2\2\u0507\u0508\5\u0082"+ + "B\2\u0508\u0509\7\b\2\2\u0509\u050a\5r:\2\u050a\u050f\7g\2\2\u050b\u050d"+ + "\7\\\2\2\u050c\u050b\3\2\2\2\u050c\u050d\3\2\2\2\u050d\u0510\3\2\2\2\u050e"+ + "\u0510\7[\2\2\u050f\u050c\3\2\2\2\u050f\u050e\3\2\2\2\u0510\u0511\3\2"+ + "\2\2\u0511\u0512\5r:\2\u0512\u0513\7\20\2\2\u0513\u0514\b9\1\2\u0514\u05cb"+ + "\3\2\2\2\u0515\u0516\7h\2\2\u0516\u0517\7\17\2\2\u0517\u0518\5\u0082B"+ + "\2\u0518\u0519\7\5\2\2\u0519\u051a\5\u0082B\2\u051a\u051b\7\5\2\2\u051b"+ + "\u051c\5\u0082B\2\u051c\u051d\7\5\2\2\u051d\u051e\5\u0082B\2\u051e\u051f"+ + "\7\20\2\2\u051f\u0520\b9\1\2\u0520\u05cb\3\2\2\2\u0521\u0522\t\t\2\2\u0522"+ + "\u0523\5p9\20\u0523\u0524\b9\1\2\u0524\u05cb\3\2\2\2\u0525\u0526\7r\2"+ + "\2\u0526\u053b\5v<\2\u0527\u0531\7d\2\2\u0528\u0532\5p9\2\u0529\u052d"+ + "\7\4\2\2\u052a\u052c\5p9\2\u052b\u052a\3\2\2\2\u052c\u052f\3\2\2\2\u052d"+ + "\u052b\3\2\2\2\u052d\u052e\3\2\2\2\u052e\u0530\3\2\2\2\u052f\u052d\3\2"+ + "\2\2\u0530\u0532\7\6\2\2\u0531\u0528\3\2\2\2\u0531\u0529\3\2\2\2\u0532"+ + "\u053c\3\2\2\2\u0533\u0537\7\4\2\2\u0534\u0536\5p9\2\u0535\u0534\3\2\2"+ + "\2\u0536\u0539\3\2\2\2\u0537\u0535\3\2\2\2\u0537\u0538\3\2\2\2\u0538\u053a"+ + "\3\2\2\2\u0539\u0537\3\2\2\2\u053a\u053c\7\6\2\2\u053b\u0527\3\2\2\2\u053b"+ + "\u0533\3\2\2\2\u053c\u053d\3\2\2\2\u053d\u053e\b9\1\2\u053e\u05cb\3\2"+ + "\2\2\u053f\u0540\7]\2\2\u0540\u0555\5v<\2\u0541\u054b\7d\2\2\u0542\u054c"+ + "\5p9\2\u0543\u0547\7\4\2\2\u0544\u0546\5p9\2\u0545\u0544\3\2\2\2\u0546"+ + "\u0549\3\2\2\2\u0547\u0545\3\2\2\2\u0547\u0548\3\2\2\2\u0548\u054a\3\2"+ + "\2\2\u0549\u0547\3\2\2\2\u054a\u054c\7\6\2\2\u054b\u0542\3\2\2\2\u054b"+ + "\u0543\3\2\2\2\u054c\u0556\3\2\2\2\u054d\u0551\7\4\2\2\u054e\u0550\5p"+ + "9\2\u054f\u054e\3\2\2\2\u0550\u0553\3\2\2\2\u0551\u054f\3\2\2\2\u0551"+ + "\u0552\3\2\2\2\u0552\u0554\3\2\2\2\u0553\u0551\3\2\2\2\u0554\u0556\7\6"+ + "\2\2\u0555\u0541\3\2\2\2\u0555\u054d\3\2\2\2\u0556\u0557\3\2\2\2\u0557"+ + "\u0558\b9\1\2\u0558\u05cb\3\2\2\2\u0559\u055a\7Z\2\2\u055a\u056f\5v<\2"+ + "\u055b\u0565\7d\2\2\u055c\u0566\5p9\2\u055d\u0561\7\4\2\2\u055e\u0560"+ + "\5p9\2\u055f\u055e\3\2\2\2\u0560\u0563\3\2\2\2\u0561\u055f\3\2\2\2\u0561"+ + "\u0562\3\2\2\2\u0562\u0564\3\2\2\2\u0563\u0561\3\2\2\2\u0564\u0566\7\6"+ + "\2\2\u0565\u055c\3\2\2\2\u0565\u055d\3\2\2\2\u0566\u0570\3\2\2\2\u0567"+ + "\u056b\7\4\2\2\u0568\u056a\5p9\2\u0569\u0568\3\2\2\2\u056a\u056d\3\2\2"+ + "\2\u056b\u0569\3\2\2\2\u056b\u056c\3\2\2\2\u056c\u056e\3\2\2\2\u056d\u056b"+ + "\3\2\2\2\u056e\u0570\7\6\2\2\u056f\u055b\3\2\2\2\u056f\u0567\3\2\2\2\u0570"+ + "\u0571\3\2\2\2\u0571\u0572\b9\1\2\u0572\u05cb\3\2\2\2\u0573\u0574\7\\"+ + "\2\2\u0574\u0589\5v<\2\u0575\u057f\7d\2\2\u0576\u0580\5p9\2\u0577\u057b"+ + "\7\4\2\2\u0578\u057a\5p9\2\u0579\u0578\3\2\2\2\u057a\u057d\3\2\2\2\u057b"+ + "\u0579\3\2\2\2\u057b\u057c\3\2\2\2\u057c\u057e\3\2\2\2\u057d\u057b\3\2"+ + "\2\2\u057e\u0580\7\6\2\2\u057f\u0576\3\2\2\2\u057f\u0577\3\2\2\2\u0580"+ + "\u058a\3\2\2\2\u0581\u0585\7\4\2\2\u0582\u0584\5p9\2\u0583\u0582\3\2\2"+ + "\2\u0584\u0587\3\2\2\2\u0585\u0583\3\2\2\2\u0585\u0586\3\2\2\2\u0586\u0588"+ + "\3\2\2\2\u0587\u0585\3\2\2\2\u0588\u058a\7\6\2\2\u0589\u0575\3\2\2\2\u0589"+ + "\u0581\3\2\2\2\u058a\u058b\3\2\2\2\u058b\u058c\b9\1\2\u058c\u05cb\3\2"+ + "\2\2\u058d\u058e\7[\2\2\u058e\u05a3\5v<\2\u058f\u0599\7d\2\2\u0590\u059a"+ + "\5p9\2\u0591\u0595\7\4\2\2\u0592\u0594\5p9\2\u0593\u0592\3\2\2\2\u0594"+ + "\u0597\3\2\2\2\u0595\u0593\3\2\2\2\u0595\u0596\3\2\2\2\u0596\u0598\3\2"+ + "\2\2\u0597\u0595\3\2\2\2\u0598\u059a\7\6\2\2\u0599\u0590\3\2\2\2\u0599"+ + "\u0591\3\2\2\2\u059a\u05a4\3\2\2\2\u059b\u059f\7\4\2\2\u059c\u059e\5p"+ + "9\2\u059d\u059c\3\2\2\2\u059e\u05a1\3\2\2\2\u059f\u059d\3\2\2\2\u059f"+ + "\u05a0\3\2\2\2\u05a0\u05a2\3\2\2\2\u05a1\u059f\3\2\2\2\u05a2\u05a4\7\6"+ + "\2\2\u05a3\u058f\3\2\2\2\u05a3\u059b\3\2\2\2\u05a4\u05a5\3\2\2\2\u05a5"+ + "\u05a6\b9\1\2\u05a6\u05cb\3\2\2\2\u05a7\u05a8\7s\2\2\u05a8\u05bd\5z>\2"+ + "\u05a9\u05b3\7d\2\2\u05aa\u05b4\5p9\2\u05ab\u05af\7\4\2\2\u05ac\u05ae"+ + "\5p9\2\u05ad\u05ac\3\2\2\2\u05ae\u05b1\3\2\2\2\u05af\u05ad\3\2\2\2\u05af"+ + "\u05b0\3\2\2\2\u05b0\u05b2\3\2\2\2\u05b1\u05af\3\2\2\2\u05b2\u05b4\7\6"+ + "\2\2\u05b3\u05aa\3\2\2\2\u05b3\u05ab\3\2\2\2\u05b4\u05be\3\2\2\2\u05b5"+ + "\u05b9\7\4\2\2\u05b6\u05b8\5p9\2\u05b7\u05b6\3\2\2\2\u05b8\u05bb\3\2\2"+ + "\2\u05b9\u05b7\3\2\2\2\u05b9\u05ba\3\2\2\2\u05ba\u05bc\3\2\2\2\u05bb\u05b9"+ + "\3\2\2\2\u05bc\u05be\7\6\2\2\u05bd\u05a9\3\2\2\2\u05bd\u05b5\3\2\2\2\u05be"+ + "\u05bf\3\2\2\2\u05bf\u05c0\b9\1\2\u05c0\u05cb\3\2\2\2\u05c1\u05c2\7\21"+ + "\2\2\u05c2\u05cb\b9\1\2\u05c3\u05c4\7\22\2\2\u05c4\u05cb\b9\1\2\u05c5"+ + "\u05c6\7\63\2\2\u05c6\u05c7\5p9\2\u05c7\u05c8\7\64\2\2\u05c8\u05c9\b9"+ + "\1\2\u05c9\u05cb\3\2\2\2\u05ca\u04af\3\2\2\2\u05ca\u04b4\3\2\2\2\u05ca"+ + "\u04b8\3\2\2\2\u05ca\u04bc\3\2\2\2\u05ca\u04c0\3\2\2\2\u05ca\u04c8\3\2"+ + "\2\2\u05ca\u04d0\3\2\2\2\u05ca\u04d8\3\2\2\2\u05ca\u04e0\3\2\2\2\u05ca"+ + "\u04e8\3\2\2\2\u05ca\u04f0\3\2\2\2\u05ca\u04f8\3\2\2\2\u05ca\u04ff\3\2"+ + "\2\2\u05ca\u0505\3\2\2\2\u05ca\u0515\3\2\2\2\u05ca\u0521\3\2\2\2\u05ca"+ + "\u0525\3\2\2\2\u05ca\u053f\3\2\2\2\u05ca\u0559\3\2\2\2\u05ca\u0573\3\2"+ + "\2\2\u05ca\u058d\3\2\2\2\u05ca\u05a7\3\2\2\2\u05ca\u05c1\3\2\2\2\u05ca"+ + "\u05c3\3\2\2\2\u05ca\u05c5\3\2\2\2\u05cb\u05e2\3\2\2\2\u05cc\u05cd\f\17"+ + "\2\2\u05cd\u05ce\t\n\2\2\u05ce\u05cf\5p9\20\u05cf\u05d0\b9\1\2\u05d0\u05e1"+ + "\3\2\2\2\u05d1\u05d2\f\16\2\2\u05d2\u05d3\t\13\2\2\u05d3\u05d4\5p9\17"+ + "\u05d4\u05d5\b9\1\2\u05d5\u05e1\3\2\2\2\u05d6\u05d7\f\r\2\2\u05d7\u05d8"+ + "\t\f\2\2\u05d8\u05d9\5p9\r\u05d9\u05da\b9\1\2\u05da\u05e1\3\2\2\2\u05db"+ + "\u05dc\f\f\2\2\u05dc\u05dd\t\r\2\2\u05dd\u05de\5p9\f\u05de\u05df\b9\1"+ + "\2\u05df\u05e1\3\2\2\2\u05e0\u05cc\3\2\2\2\u05e0\u05d1\3\2\2\2\u05e0\u05d6"+ + "\3\2\2\2\u05e0\u05db\3\2\2\2\u05e1\u05e4\3\2\2\2\u05e2\u05e0\3\2\2\2\u05e2"+ + "\u05e3\3\2\2\2\u05e3q\3\2\2\2\u05e4\u05e2\3\2\2\2\u05e5\u05e6\b:\1\2\u05e6"+ + "\u05e7\7t\2\2\u05e7\u05e8\5r:\24\u05e8\u05e9\b:\1\2\u05e9\u0612\3\2\2"+ + "\2\u05ea\u05eb\7u\2\2\u05eb\u05ec\5r:\23\u05ec\u05ed\b:\1\2\u05ed\u0612"+ + "\3\2\2\2\u05ee\u05ef\7\67\2\2\u05ef\u05f0\5r:\22\u05f0\u05f1\b:\1\2\u05f1"+ + "\u0612\3\2\2\2\u05f2\u05f3\7\4\2\2\u05f3\u05f4\5~@\2\u05f4\u05f5\7d\2"+ + "\2\u05f5\u05f6\5p9\2\u05f6\u05f7\7\6\2\2\u05f7\u05f8\b:\1\2\u05f8\u0612"+ + "\3\2\2\2\u05f9\u05fa\t\16\2\2\u05fa\u05fb\5p9\2\u05fb\u05fc\7w\2\2\u05fc"+ + "\u05fd\5r:\2\u05fd\u05fe\7x\2\2\u05fe\u05ff\5r:\t\u05ff\u0600\b:\1\2\u0600"+ + "\u0612\3\2\2\2\u0601\u0602\7y\2\2\u0602\u0612\b:\1\2\u0603\u0604\7z\2"+ + "\2\u0604\u0612\b:\1\2\u0605\u0606\7{\2\2\u0606\u0612\b:\1\2\u0607\u0608"+ + "\7|\2\2\u0608\u0612\b:\1\2\u0609\u060a\7\63\2\2\u060a\u060b\5r:\2\u060b"+ + "\u060c\7\64\2\2\u060c\u060d\b:\1\2\u060d\u0612\3\2\2\2\u060e\u060f\5\\"+ + "/\2\u060f\u0610\b:\1\2\u0610\u0612\3\2\2\2\u0611\u05e5\3\2\2\2\u0611\u05ea"+ + "\3\2\2\2\u0611\u05ee\3\2\2\2\u0611\u05f2\3\2\2\2\u0611\u05f9\3\2\2\2\u0611"+ + "\u0601\3\2\2\2\u0611\u0603\3\2\2\2\u0611\u0605\3\2\2\2\u0611\u0607\3\2"+ + "\2\2\u0611\u0609\3\2\2\2\u0611\u060e\3\2\2\2\u0612\u063f\3\2\2\2\u0613"+ + "\u0614\f\21\2\2\u0614\u0615\7\23\2\2\u0615\u0616\5r:\22\u0616\u0617\b"+ + ":\1\2\u0617\u063e\3\2\2\2\u0618\u0619\f\20\2\2\u0619\u061a\7E\2\2\u061a"+ + "\u061b\5r:\21\u061b\u061c\b:\1\2\u061c\u063e\3\2\2\2\u061d\u061e\f\17"+ + "\2\2\u061e\u061f\7\24\2\2\u061f\u0620\5r:\20\u0620\u0621\b:\1\2\u0621"+ + "\u063e\3\2\2\2\u0622\u0623\f\16\2\2\u0623\u0624\7\25\2\2\u0624\u0625\5"+ + "r:\17\u0625\u0626\b:\1\2\u0626\u063e\3\2\2\2\u0627\u0629\f\f\2\2\u0628"+ + "\u062a\5\u0086D\2\u0629\u0628\3\2\2\2\u0629\u062a\3\2\2\2\u062a\u062b"+ + "\3\2\2\2\u062b\u062d\7g\2\2\u062c\u062e\5\u0086D\2\u062d\u062c\3\2\2\2"+ + "\u062d\u062e\3\2\2\2\u062e\u062f\3\2\2\2\u062f\u0630\5r:\f\u0630\u0631"+ + "\b:\1\2\u0631\u063e\3\2\2\2\u0632\u0633\f\13\2\2\u0633\u0634\7v\2\2\u0634"+ + "\u0635\5r:\f\u0635\u0636\b:\1\2\u0636\u063e\3\2\2\2\u0637\u0638\f\r\2"+ + "\2\u0638\u0639\7\17\2\2\u0639\u063a\5r:\2\u063a\u063b\7\20\2\2\u063b\u063c"+ + "\b:\1\2\u063c\u063e\3\2\2\2\u063d\u0613\3\2\2\2\u063d\u0618\3\2\2\2\u063d"+ + "\u061d\3\2\2\2\u063d\u0622\3\2\2\2\u063d\u0627\3\2\2\2\u063d\u0632\3\2"+ + "\2\2\u063d\u0637\3\2\2\2\u063e\u0641\3\2\2\2\u063f\u063d\3\2\2\2\u063f"+ + "\u0640\3\2\2\2\u0640s\3\2\2\2\u0641\u063f\3\2\2\2\u0642\u0643\b;\1\2\u0643"+ + "\u0644\t\16\2\2\u0644\u0645\5p9\2\u0645\u0646\7w\2\2\u0646\u0647\5t;\2"+ + "\u0647\u0648\7x\2\2\u0648\u0649\5t;\f\u0649\u064a\b;\1\2\u064a\u065e\3"+ + "\2\2\2\u064b\u064c\7c\2\2\u064c\u064d\5r:\2\u064d\u064e\b;\1\2\u064e\u065e"+ + "\3\2\2\2\u064f\u0650\7-\2\2\u0650\u0651\5r:\2\u0651\u0652\b;\1\2\u0652"+ + "\u065e\3\2\2\2\u0653\u0655\7\24\2\2\u0654\u0653\3\2\2\2\u0654\u0655\3"+ + "\2\2\2\u0655\u0656\3\2\2\2\u0656\u0657\7\u0089\2\2\u0657\u065e\b;\1\2"+ + "\u0658\u0659\7\63\2\2\u0659\u065a\5t;\2\u065a\u065b\7\64\2\2\u065b\u065c"+ + "\b;\1\2\u065c\u065e\3\2\2\2\u065d\u0642\3\2\2\2\u065d\u064b\3\2\2\2\u065d"+ + "\u064f\3\2\2\2\u065d\u0654\3\2\2\2\u065d\u0658\3\2\2\2\u065e\u067a\3\2"+ + "\2\2\u065f\u0660\f\t\2\2\u0660\u0661\t\17\2\2\u0661\u0662\5t;\n\u0662"+ + "\u0663\b;\1\2\u0663\u0679\3\2\2\2\u0664\u0665\f\b\2\2\u0665\u0666\t\20"+ + "\2\2\u0666\u0667\5t;\t\u0667\u0668\b;\1\2\u0668\u0679\3\2\2\2\u0669\u066a"+ + "\f\7\2\2\u066a\u066b\t\21\2\2\u066b\u066c\5t;\b\u066c\u066d\b;\1\2\u066d"+ + "\u0679\3\2\2\2\u066e\u066f\f\6\2\2\u066f\u0670\t\22\2\2\u0670\u0671\5"+ + "t;\7\u0671\u0672\b;\1\2\u0672\u0679\3\2\2\2\u0673\u0674\f\5\2\2\u0674"+ + "\u0675\t\23\2\2\u0675\u0676\5t;\6\u0676\u0677\b;\1\2\u0677\u0679\3\2\2"+ + "\2\u0678\u065f\3\2\2\2\u0678\u0664\3\2\2\2\u0678\u0669\3\2\2\2\u0678\u066e"+ + "\3\2\2\2\u0678\u0673\3\2\2\2\u0679\u067c\3\2\2\2\u067a\u0678\3\2\2\2\u067a"+ + "\u067b\3\2\2\2\u067bu\3\2\2\2\u067c\u067a\3\2\2\2\u067d\u0682\5x=\2\u067e"+ + "\u067f\7\5\2\2\u067f\u0681\5x=\2\u0680\u067e\3\2\2\2\u0681\u0684\3\2\2"+ + "\2\u0682\u0680\3\2\2\2\u0682\u0683\3\2\2\2\u0683w\3\2\2\2\u0684\u0682"+ + "\3\2\2\2\u0685\u0687\7\u0084\2\2\u0686\u0685\3\2\2\2\u0686\u0687\3\2\2"+ + "\2\u0687\u0688\3\2\2\2\u0688\u068d\5\u0084C\2\u0689\u068a\7\5\2\2\u068a"+ + "\u068c\5\u0084C\2\u068b\u0689\3\2\2\2\u068c\u068f\3\2\2\2\u068d\u068b"+ + "\3\2\2\2\u068d\u068e\3\2\2\2\u068e\u0690\3\2\2\2\u068f\u068d\3\2\2\2\u0690"+ + "\u0692\7\b\2\2\u0691\u0693\7\\\2\2\u0692\u0691\3\2\2\2\u0692\u0693\3\2"+ + "\2\2\u0693\u0694\3\2\2\2\u0694\u0695\5r:\2\u0695\u0696\b=\1\2\u0696\u06c8"+ + "\3\2\2\2\u0697\u0699\7\u0084\2\2\u0698\u0697\3\2\2\2\u0698\u0699\3\2\2"+ + "\2\u0699\u069a\3\2\2\2\u069a\u069f\5\u0084C\2\u069b\u069c\7\5\2\2\u069c"+ + "\u069e\5\u0084C\2\u069d\u069b\3\2\2\2\u069e\u06a1\3\2\2\2\u069f\u069d"+ + "\3\2\2\2\u069f\u06a0\3\2\2\2\u06a0\u06a2\3\2\2\2\u06a1\u069f\3\2\2\2\u06a2"+ + "\u06a3\7\b\2\2\u06a3\u06a4\7[\2\2\u06a4\u06a5\5r:\2\u06a5\u06a6\b=\1\2"+ + "\u06a6\u06c8\3\2\2\2\u06a7\u06a9\7\u0084\2\2\u06a8\u06a7\3\2\2\2\u06a8"+ + "\u06a9\3\2\2\2\u06a9\u06aa\3\2\2\2\u06aa\u06af\5\u0084C\2\u06ab\u06ac"+ + "\7\5\2\2\u06ac\u06ae\5\u0084C\2\u06ad\u06ab\3\2\2\2\u06ae\u06b1\3\2\2"+ + "\2\u06af\u06ad\3\2\2\2\u06af\u06b0\3\2\2\2\u06b0\u06b2\3\2\2\2\u06b1\u06af"+ + "\3\2\2\2\u06b2\u06b3\7\b\2\2\u06b3\u06b4\7]\2\2\u06b4\u06b5\5r:\2\u06b5"+ + "\u06b6\b=\1\2\u06b6\u06c8\3\2\2\2\u06b7\u06b9\7\u0084\2\2\u06b8\u06b7"+ + "\3\2\2\2\u06b8\u06b9\3\2\2\2\u06b9\u06ba\3\2\2\2\u06ba\u06bf\5\u0084C"+ + "\2\u06bb\u06bc\7\5\2\2\u06bc\u06be\5\u0084C\2\u06bd\u06bb\3\2\2\2\u06be"+ + "\u06c1\3\2\2\2\u06bf\u06bd\3\2\2\2\u06bf\u06c0\3\2\2\2\u06c0\u06c2\3\2"+ + "\2\2\u06c1\u06bf\3\2\2\2\u06c2\u06c3\7\b\2\2\u06c3\u06c4\7\u0085\2\2\u06c4"+ + "\u06c5\5r:\2\u06c5\u06c6\b=\1\2\u06c6\u06c8\3\2\2\2\u06c7\u0686\3\2\2"+ + "\2\u06c7\u0698\3\2\2\2\u06c7\u06a8\3\2\2\2\u06c7\u06b8\3\2\2\2\u06c8y"+ + "\3\2\2\2\u06c9\u06ce\5|?\2\u06ca\u06cb\7\5\2\2\u06cb\u06cd\5|?\2\u06cc"+ + "\u06ca\3\2\2\2\u06cd\u06d0\3\2\2\2\u06ce\u06cc\3\2\2\2\u06ce\u06cf\3\2"+ + "\2\2\u06cf{\3\2\2\2\u06d0\u06ce\3\2\2\2\u06d1\u06d6\5\u0084C\2\u06d2\u06d3"+ + "\7\5\2\2\u06d3\u06d5\5\u0084C\2\u06d4\u06d2\3\2\2\2\u06d5\u06d8\3\2\2"+ + "\2\u06d6\u06d4\3\2\2\2\u06d6\u06d7\3\2\2\2\u06d7\u06d9\3\2\2\2\u06d8\u06d6"+ + "\3\2\2\2\u06d9\u06da\7\31\2\2\u06da\u06db\5r:\2\u06db\u06dc\b?\1\2\u06dc"+ + "}\3\2\2\2\u06dd\u06e2\5\u0080A\2\u06de\u06df\7\5\2\2\u06df\u06e1\5\u0080"+ + "A\2\u06e0\u06de\3\2\2\2\u06e1\u06e4\3\2\2\2\u06e2\u06e0\3\2\2\2\u06e2"+ + "\u06e3\3\2\2\2\u06e3\177\3\2\2\2\u06e4\u06e2\3\2\2\2\u06e5\u06e7\7\u0084"+ + "\2\2\u06e6\u06e5\3\2\2\2\u06e6\u06e7\3\2\2\2\u06e7\u06e8\3\2\2\2\u06e8"+ + "\u06ed\5\u0084C\2\u06e9\u06ea\7\5\2\2\u06ea\u06ec\5\u0084C\2\u06eb\u06e9"+ + "\3\2\2\2\u06ec\u06ef\3\2\2\2\u06ed\u06eb\3\2\2\2\u06ed\u06ee\3\2\2\2\u06ee"+ + "\u06f0\3\2\2\2\u06ef\u06ed\3\2\2\2\u06f0\u06f2\7\b\2\2\u06f1\u06f3\7\\"+ + "\2\2\u06f2\u06f1\3\2\2\2\u06f2\u06f3\3\2\2\2\u06f3\u06f4\3\2\2\2\u06f4"+ + "\u06f5\5r:\2\u06f5\u06f6\3\2\2\2\u06f6\u06f7\bA\1\2\u06f7\u0081\3\2\2"+ + "\2\u06f8\u06f9\5\u0088E\2\u06f9\u0083\3\2\2\2\u06fa\u06fb\5\u0088E\2\u06fb"+ + "\u06fc\bC\1\2\u06fc\u0085\3\2\2\2\u06fd\u06fe\t\24\2\2\u06fe\u0087\3\2"+ + "\2\2\u06ff\u072a\5\u008aF\2\u0700\u072a\7\32\2\2\u0701\u072a\7#\2\2\u0702"+ + "\u072a\7N\2\2\u0703\u072a\7O\2\2\u0704\u072a\7\33\2\2\u0705\u072a\7.\2"+ + "\2\u0706\u072a\7<\2\2\u0707\u072a\7\u0086\2\2\u0708\u072a\7V\2\2\u0709"+ + "\u072a\7$\2\2\u070a\u072a\7?\2\2\u070b\u072a\7\u0087\2\2\u070c\u072a\7"+ + "\35\2\2\u070d\u072a\7%\2\2\u070e\u072a\7\27\2\2\u070f\u072a\7U\2\2\u0710"+ + "\u072a\7\34\2\2\u0711\u072a\7\61\2\2\u0712\u072a\7\16\2\2\u0713\u072a"+ + "\7\62\2\2\u0714\u072a\7&\2\2\u0715\u072a\7\30\2\2\u0716\u072a\7S\2\2\u0717"+ + "\u072a\7Q\2\2\u0718\u072a\7;\2\2\u0719\u072a\7,\2\2\u071a\u072a\7\"\2"+ + "\2\u071b\u072a\7B\2\2\u071c\u072a\7\u0088\2\2\u071d\u072a\7/\2\2\u071e"+ + "\u072a\7\36\2\2\u071f\u072a\7\65\2\2\u0720\u072a\7 \2\2\u0721\u072a\7"+ + "(\2\2\u0722\u072a\7*\2\2\u0723\u072a\7!\2\2\u0724\u072a\7P\2\2\u0725\u072a"+ + "\7@\2\2\u0726\u072a\7=\2\2\u0727\u072a\7A\2\2\u0728\u072a\7\16\2\2\u0729"+ + "\u06ff\3\2\2\2\u0729\u0700\3\2\2\2\u0729\u0701\3\2\2\2\u0729\u0702\3\2"+ + "\2\2\u0729\u0703\3\2\2\2\u0729\u0704\3\2\2\2\u0729\u0705\3\2\2\2\u0729"+ + "\u0706\3\2\2\2\u0729\u0707\3\2\2\2\u0729\u0708\3\2\2\2\u0729\u0709\3\2"+ + "\2\2\u0729\u070a\3\2\2\2\u0729\u070b\3\2\2\2\u0729\u070c\3\2\2\2\u0729"+ + "\u070d\3\2\2\2\u0729\u070e\3\2\2\2\u0729\u070f\3\2\2\2\u0729\u0710\3\2"+ + "\2\2\u0729\u0711\3\2\2\2\u0729\u0712\3\2\2\2\u0729\u0713\3\2\2\2\u0729"+ + "\u0714\3\2\2\2\u0729\u0715\3\2\2\2\u0729\u0716\3\2\2\2\u0729\u0717\3\2"+ + "\2\2\u0729\u0718\3\2\2\2\u0729\u0719\3\2\2\2\u0729\u071a\3\2\2\2\u0729"+ + "\u071b\3\2\2\2\u0729\u071c\3\2\2\2\u0729\u071d\3\2\2\2\u0729\u071e\3\2"+ + "\2\2\u0729\u071f\3\2\2\2\u0729\u0720\3\2\2\2\u0729\u0721\3\2\2\2\u0729"+ + "\u0722\3\2\2\2\u0729\u0723\3\2\2\2\u0729\u0724\3\2\2\2\u0729\u0725\3\2"+ + "\2\2\u0729\u0726\3\2\2\2\u0729\u0727\3\2\2\2\u0729\u0728\3\2\2\2\u072a"+ + "\u0089\3\2\2\2\u072b\u072c\7\u008a\2\2\u072c\u008b\3\2\2\2\u072d\u072e"+ + "\t\25\2\2\u072e\u008d\3\2\2\2\u072f\u0730\7\u0089\2\2\u0730\u008f\3\2"+ + "\2\2\u00eb\u0097\u00a8\u00ae\u00b3\u00b9\u00bf\u00c7\u00d0\u00d6\u00e0"+ + "\u00eb\u00f1\u00f3\u00f7\u00ff\u010d\u0114\u0119\u011c\u0128\u012f\u0135"+ + "\u0141\u0148\u0163\u0165\u016a\u0175\u0178\u017c\u0180\u0184\u0189\u0192"+ + "\u0195\u019a\u01aa\u01ac\u01b1\u01b9\u01bc\u01c0\u01c4\u01c7\u01ca\u01cd"+ + "\u01d5\u01da\u01e6\u01e9\u01ed\u01f0\u01f8\u0201\u0208\u020d\u0212\u0216"+ + "\u021a\u021d\u0220\u0223\u022a\u0230\u0235\u0243\u0246\u024a\u024d\u0256"+ + "\u025b\u0262\u026b\u0272\u0277\u027c\u0280\u0284\u028f\u0292\u029a\u029c"+ + "\u02a6\u02a9\u02b1\u02b4\u02b8\u02bb\u02ca\u02cc\u02d1\u02e0\u02e8\u02eb"+ + "\u02ef\u02f2\u02f8\u02fd\u0305\u0308\u030c\u0312\u0316\u031c\u0321\u0327"+ + "\u032a\u0333\u0335\u033a\u033f\u0346\u034b\u0351\u0354\u0360\u0362\u0367"+ + "\u036e\u0373\u037a\u0380\u0384\u038d\u0392\u039f\u03a1\u03a6\u03a9\u03ad"+ + "\u03b7\u03c5\u03d0\u03dd\u03ea\u03ed\u03f7\u0400\u0405\u040d\u0416\u041b"+ + "\u0420\u0424\u0428\u042d\u0439\u043d\u0442\u0446\u044b\u0453\u0455\u045a"+ + "\u045e\u0467\u0469\u046e\u0472\u047b\u047d\u0482\u0486\u048c\u0491\u0495"+ + "\u049b\u04a0\u04a4\u04ab\u04c2\u04ca\u04d2\u04da\u04e2\u04ea\u04f2\u050c"+ + "\u050f\u052d\u0531\u0537\u053b\u0547\u054b\u0551\u0555\u0561\u0565\u056b"+ + "\u056f\u057b\u057f\u0585\u0589\u0595\u0599\u059f\u05a3\u05af\u05b3\u05b9"+ + "\u05bd\u05ca\u05e0\u05e2\u0611\u0629\u062d\u063d\u063f\u0654\u065d\u0678"+ + "\u067a\u0682\u0686\u068d\u0692\u0698\u069f\u06a8\u06af\u06b8\u06bf\u06c7"+ + "\u06ce\u06d6\u06e2\u06e6\u06ed\u06f2\u0729"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreVisitor.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreVisitor.java new file mode 100644 index 00000000..ac33706a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreVisitor.java @@ -0,0 +1,971 @@ +// Generated from /home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcore.g4 by ANTLR 4.6 +package eu.modelwriter.core.alloyinecore.recognizer; + + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EcoreFactory; +import org.eclipse.emf.ecore.EcorePackage; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.ETypedElement; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EClassifier; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EOperation; +import org.eclipse.emf.ecore.EParameter; +import org.eclipse.emf.ecore.EEnum; +import org.eclipse.emf.ecore.EEnumLiteral; +import org.eclipse.emf.ecore.EDataType; +import org.eclipse.emf.ecore.ETypedElement; +import org.eclipse.emf.ecore.EAnnotation; +import org.eclipse.emf.ecore.EGenericType; +import org.eclipse.emf.ecore.ETypeParameter; + +import eu.modelwriter.core.alloyinecore.structure.base.INamespace; +import eu.modelwriter.core.alloyinecore.structure.base.Repository; +import eu.modelwriter.core.alloyinecore.structure.base.Element; + +import eu.modelwriter.core.alloyinecore.structure.model.ModelElement; +import eu.modelwriter.core.alloyinecore.structure.model.Annotation; +import eu.modelwriter.core.alloyinecore.structure.model.AnnotationDetail; +import eu.modelwriter.core.alloyinecore.structure.model.AnnotationReference; +import eu.modelwriter.core.alloyinecore.structure.model.NamedElement; +import eu.modelwriter.core.alloyinecore.structure.model.Model; +import eu.modelwriter.core.alloyinecore.structure.model.Import; +import eu.modelwriter.core.alloyinecore.structure.model.EcoreImport; +import eu.modelwriter.core.alloyinecore.structure.model.Package; +import eu.modelwriter.core.alloyinecore.structure.model.RootPackage; +import eu.modelwriter.core.alloyinecore.structure.model.Classifier; +import eu.modelwriter.core.alloyinecore.structure.model.Class; +import eu.modelwriter.core.alloyinecore.structure.model.Interface; +import eu.modelwriter.core.alloyinecore.structure.model.DataType; +import eu.modelwriter.core.alloyinecore.structure.model.Enum; +import eu.modelwriter.core.alloyinecore.structure.model.EnumLiteral; +import eu.modelwriter.core.alloyinecore.structure.model.StructuralFeature; +import eu.modelwriter.core.alloyinecore.structure.model.TypedElement; +import eu.modelwriter.core.alloyinecore.structure.model.Multiplicity; +import eu.modelwriter.core.alloyinecore.structure.model.Reference; +import eu.modelwriter.core.alloyinecore.structure.model.Attribute; +import eu.modelwriter.core.alloyinecore.structure.model.Operation; +import eu.modelwriter.core.alloyinecore.structure.model.Parameter; +import eu.modelwriter.core.alloyinecore.structure.model.GenericException; +import eu.modelwriter.core.alloyinecore.structure.model.TypeParameter; +import eu.modelwriter.core.alloyinecore.structure.model.GenericType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericTypeArgument; +import eu.modelwriter.core.alloyinecore.structure.model.GenericElementType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericSuperType; +import eu.modelwriter.core.alloyinecore.structure.model.GenericWildcard; +import eu.modelwriter.core.alloyinecore.structure.model.PrimitiveType; +import eu.modelwriter.core.alloyinecore.structure.model.Invariant; +import eu.modelwriter.core.alloyinecore.structure.model.Derivation; +import eu.modelwriter.core.alloyinecore.structure.model.Body; +import eu.modelwriter.core.alloyinecore.structure.model.PostCondition; +import eu.modelwriter.core.alloyinecore.structure.model.PreCondition; +import eu.modelwriter.core.alloyinecore.structure.model.Initial; + +import eu.modelwriter.core.alloyinecore.structure.instance.ModelImport; +import eu.modelwriter.core.alloyinecore.structure.instance.Instance; +import eu.modelwriter.core.alloyinecore.structure.instance.Object; +import eu.modelwriter.core.alloyinecore.structure.instance.Slot; +import eu.modelwriter.core.alloyinecore.structure.instance.ObjectValue; +import eu.modelwriter.core.alloyinecore.structure.instance.EnumValue; +import eu.modelwriter.core.alloyinecore.structure.instance.IntegerValue; +import eu.modelwriter.core.alloyinecore.structure.instance.RealValue; +import eu.modelwriter.core.alloyinecore.structure.instance.BooleanValue; +import eu.modelwriter.core.alloyinecore.structure.instance.StringValue; +import eu.modelwriter.core.alloyinecore.structure.instance.NullValue; +import eu.modelwriter.core.alloyinecore.structure.instance.CharValue; + +import eu.modelwriter.core.alloyinecore.structure.constraints.Formula; +import eu.modelwriter.core.alloyinecore.structure.constraints.Expression; +import eu.modelwriter.core.alloyinecore.structure.constraints.IntExpression; +import eu.modelwriter.core.alloyinecore.structure.constraints.QuantifierDeclaration; +import eu.modelwriter.core.alloyinecore.structure.constraints.LetDeclaration; +import eu.modelwriter.core.alloyinecore.structure.constraints.ComprehensionDeclaration; +import eu.modelwriter.core.alloyinecore.structure.constraints.Variable; + +import eu.modelwriter.core.alloyinecore.internal.AnnotationSources; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl; +import org.eclipse.emf.ecore.util.EcoreUtil; + +import java.util.stream.Collectors; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +import java.io.IOException; + +import org.antlr.v4.runtime.tree.ParseTreeVisitor; + +/** + * This interface defines a complete generic visitor for a parse tree produced + * by {@link AlloyInEcoreParser}. + * + * @param The return type of the visit operation. Use {@link Void} for + * operations with no return type. + */ +public interface AlloyInEcoreVisitor extends ParseTreeVisitor { + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#options}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitOptions(AlloyInEcoreParser.OptionsContext ctx); + /** + * Visit a parse tree produced by the {@code symmetryBreaking} + * labeled alternative in {@link AlloyInEcoreParser#option}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSymmetryBreaking(AlloyInEcoreParser.SymmetryBreakingContext ctx); + /** + * Visit a parse tree produced by the {@code bitWidth} + * labeled alternative in {@link AlloyInEcoreParser#option}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitBitWidth(AlloyInEcoreParser.BitWidthContext ctx); + /** + * Visit a parse tree produced by the {@code skolemDepth} + * labeled alternative in {@link AlloyInEcoreParser#option}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSkolemDepth(AlloyInEcoreParser.SkolemDepthContext ctx); + /** + * Visit a parse tree produced by the {@code sharing} + * labeled alternative in {@link AlloyInEcoreParser#option}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSharing(AlloyInEcoreParser.SharingContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#instance}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitInstance(AlloyInEcoreParser.InstanceContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#modelImport}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitModelImport(AlloyInEcoreParser.ModelImportContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eObject}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEObject(AlloyInEcoreParser.EObjectContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#slot}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSlot(AlloyInEcoreParser.SlotContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#dataValue}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitDataValue(AlloyInEcoreParser.DataValueContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#multiValueData}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitMultiValueData(AlloyInEcoreParser.MultiValueDataContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eObjectValue}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEObjectValue(AlloyInEcoreParser.EObjectValueContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#literalValue}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitLiteralValue(AlloyInEcoreParser.LiteralValueContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#enumValue}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEnumValue(AlloyInEcoreParser.EnumValueContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#booleanValue}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitBooleanValue(AlloyInEcoreParser.BooleanValueContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#integerValue}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIntegerValue(AlloyInEcoreParser.IntegerValueContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#realValue}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitRealValue(AlloyInEcoreParser.RealValueContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#stringValue}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitStringValue(AlloyInEcoreParser.StringValueContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#charValue}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitCharValue(AlloyInEcoreParser.CharValueContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#nullValue}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitNullValue(AlloyInEcoreParser.NullValueContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#model}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitModel(AlloyInEcoreParser.ModelContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#packageImport}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitPackageImport(AlloyInEcoreParser.PackageImportContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#ePackage}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEPackage(AlloyInEcoreParser.EPackageContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eClassifier}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEClassifier(AlloyInEcoreParser.EClassifierContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eClass}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEClass(AlloyInEcoreParser.EClassContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eStructuralFeature}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEStructuralFeature(AlloyInEcoreParser.EStructuralFeatureContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eAttribute}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEAttribute(AlloyInEcoreParser.EAttributeContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eReference}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEReference(AlloyInEcoreParser.EReferenceContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eOperation}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEOperation(AlloyInEcoreParser.EOperationContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eGenericException}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEGenericException(AlloyInEcoreParser.EGenericExceptionContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eGenericSuperType}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEGenericSuperType(AlloyInEcoreParser.EGenericSuperTypeContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eParameter}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEParameter(AlloyInEcoreParser.EParameterContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eMultiplicity}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEMultiplicity(AlloyInEcoreParser.EMultiplicityContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eDataType}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEDataType(AlloyInEcoreParser.EDataTypeContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eEnum}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEEnum(AlloyInEcoreParser.EEnumContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eEnumLiteral}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEEnumLiteral(AlloyInEcoreParser.EEnumLiteralContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eAnnotation}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEAnnotation(AlloyInEcoreParser.EAnnotationContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eDetail}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEDetail(AlloyInEcoreParser.EDetailContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eModelElement}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEModelElement(AlloyInEcoreParser.EModelElementContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eNamedElement}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitENamedElement(AlloyInEcoreParser.ENamedElementContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eTypedElement}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitETypedElement(AlloyInEcoreParser.ETypedElementContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eModelElementRef}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEModelElementRef(AlloyInEcoreParser.EModelElementRefContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#templateSignature}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitTemplateSignature(AlloyInEcoreParser.TemplateSignatureContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eTypeParameter}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitETypeParameter(AlloyInEcoreParser.ETypeParameterContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eGenericTypeArgument}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEGenericTypeArgument(AlloyInEcoreParser.EGenericTypeArgumentContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eGenericType}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEGenericType(AlloyInEcoreParser.EGenericTypeContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eGenericElementType}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEGenericElementType(AlloyInEcoreParser.EGenericElementTypeContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#eGenericWildcard}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEGenericWildcard(AlloyInEcoreParser.EGenericWildcardContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#pathName}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitPathName(AlloyInEcoreParser.PathNameContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#segment}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSegment(AlloyInEcoreParser.SegmentContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#ePrimitiveType}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEPrimitiveType(AlloyInEcoreParser.EPrimitiveTypeContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#body}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitBody(AlloyInEcoreParser.BodyContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#invariant}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitInvariant(AlloyInEcoreParser.InvariantContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#precondition}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitPrecondition(AlloyInEcoreParser.PreconditionContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#postcondition}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitPostcondition(AlloyInEcoreParser.PostconditionContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#initial}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitInitial(AlloyInEcoreParser.InitialContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#derivation}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitDerivation(AlloyInEcoreParser.DerivationContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#visibilityKind}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitVisibilityKind(AlloyInEcoreParser.VisibilityKindContext ctx); + /** + * Visit a parse tree produced by the {@code no} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitNo(AlloyInEcoreParser.NoContext ctx); + /** + * Visit a parse tree produced by the {@code some} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSome(AlloyInEcoreParser.SomeContext ctx); + /** + * Visit a parse tree produced by the {@code forOne} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitForOne(AlloyInEcoreParser.ForOneContext ctx); + /** + * Visit a parse tree produced by the {@code sumDeclaration} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSumDeclaration(AlloyInEcoreParser.SumDeclarationContext ctx); + /** + * Visit a parse tree produced by the {@code forAll} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitForAll(AlloyInEcoreParser.ForAllContext ctx); + /** + * Visit a parse tree produced by the {@code lone} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitLone(AlloyInEcoreParser.LoneContext ctx); + /** + * Visit a parse tree produced by the {@code lt} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitLt(AlloyInEcoreParser.LtContext ctx); + /** + * Visit a parse tree produced by the {@code forSome} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitForSome(AlloyInEcoreParser.ForSomeContext ctx); + /** + * Visit a parse tree produced by the {@code not} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitNot(AlloyInEcoreParser.NotContext ctx); + /** + * Visit a parse tree produced by the {@code f_paranthesis} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitF_paranthesis(AlloyInEcoreParser.F_paranthesisContext ctx); + /** + * Visit a parse tree produced by the {@code and} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitAnd(AlloyInEcoreParser.AndContext ctx); + /** + * Visit a parse tree produced by the {@code function} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitFunction(AlloyInEcoreParser.FunctionContext ctx); + /** + * Visit a parse tree produced by the {@code gte} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitGte(AlloyInEcoreParser.GteContext ctx); + /** + * Visit a parse tree produced by the {@code acyclic} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitAcyclic(AlloyInEcoreParser.AcyclicContext ctx); + /** + * Visit a parse tree produced by the {@code let} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitLet(AlloyInEcoreParser.LetContext ctx); + /** + * Visit a parse tree produced by the {@code lte} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitLte(AlloyInEcoreParser.LteContext ctx); + /** + * Visit a parse tree produced by the {@code or} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitOr(AlloyInEcoreParser.OrContext ctx); + /** + * Visit a parse tree produced by the {@code in} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIn(AlloyInEcoreParser.InContext ctx); + /** + * Visit a parse tree produced by the {@code one} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitOne(AlloyInEcoreParser.OneContext ctx); + /** + * Visit a parse tree produced by the {@code false} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitFalse(AlloyInEcoreParser.FalseContext ctx); + /** + * Visit a parse tree produced by the {@code iff} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIff(AlloyInEcoreParser.IffContext ctx); + /** + * Visit a parse tree produced by the {@code eq} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEq(AlloyInEcoreParser.EqContext ctx); + /** + * Visit a parse tree produced by the {@code gt} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitGt(AlloyInEcoreParser.GtContext ctx); + /** + * Visit a parse tree produced by the {@code equal} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEqual(AlloyInEcoreParser.EqualContext ctx); + /** + * Visit a parse tree produced by the {@code forLone} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitForLone(AlloyInEcoreParser.ForLoneContext ctx); + /** + * Visit a parse tree produced by the {@code totalOrder} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitTotalOrder(AlloyInEcoreParser.TotalOrderContext ctx); + /** + * Visit a parse tree produced by the {@code true} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitTrue(AlloyInEcoreParser.TrueContext ctx); + /** + * Visit a parse tree produced by the {@code forNo} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitForNo(AlloyInEcoreParser.ForNoContext ctx); + /** + * Visit a parse tree produced by the {@code implies} + * labeled alternative in {@link AlloyInEcoreParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitImplies(AlloyInEcoreParser.ImpliesContext ctx); + /** + * Visit a parse tree produced by the {@code product} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitProduct(AlloyInEcoreParser.ProductContext ctx); + /** + * Visit a parse tree produced by the {@code none} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitNone(AlloyInEcoreParser.NoneContext ctx); + /** + * Visit a parse tree produced by the {@code union} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitUnion(AlloyInEcoreParser.UnionContext ctx); + /** + * Visit a parse tree produced by the {@code comprehension} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitComprehension(AlloyInEcoreParser.ComprehensionContext ctx); + /** + * Visit a parse tree produced by the {@code univ} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitUniv(AlloyInEcoreParser.UnivContext ctx); + /** + * Visit a parse tree produced by the {@code reflexive} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitReflexive(AlloyInEcoreParser.ReflexiveContext ctx); + /** + * Visit a parse tree produced by the {@code e_paranthesis} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitE_paranthesis(AlloyInEcoreParser.E_paranthesisContext ctx); + /** + * Visit a parse tree produced by the {@code iden} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIden(AlloyInEcoreParser.IdenContext ctx); + /** + * Visit a parse tree produced by the {@code ints} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitInts(AlloyInEcoreParser.IntsContext ctx); + /** + * Visit a parse tree produced by the {@code intersection} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIntersection(AlloyInEcoreParser.IntersectionContext ctx); + /** + * Visit a parse tree produced by the {@code difference} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitDifference(AlloyInEcoreParser.DifferenceContext ctx); + /** + * Visit a parse tree produced by the {@code transpose} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitTranspose(AlloyInEcoreParser.TransposeContext ctx); + /** + * Visit a parse tree produced by the {@code join} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitJoin(AlloyInEcoreParser.JoinContext ctx); + /** + * Visit a parse tree produced by the {@code override} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitOverride(AlloyInEcoreParser.OverrideContext ctx); + /** + * Visit a parse tree produced by the {@code ifExpression} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIfExpression(AlloyInEcoreParser.IfExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code closure} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitClosure(AlloyInEcoreParser.ClosureContext ctx); + /** + * Visit a parse tree produced by the {@code typeRef} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitTypeRef(AlloyInEcoreParser.TypeRefContext ctx); + /** + * Visit a parse tree produced by the {@code boxJoin} + * labeled alternative in {@link AlloyInEcoreParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitBoxJoin(AlloyInEcoreParser.BoxJoinContext ctx); + /** + * Visit a parse tree produced by the {@code minus} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitMinus(AlloyInEcoreParser.MinusContext ctx); + /** + * Visit a parse tree produced by the {@code intConstant} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIntConstant(AlloyInEcoreParser.IntConstantContext ctx); + /** + * Visit a parse tree produced by the {@code i_paranthesis} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitI_paranthesis(AlloyInEcoreParser.I_paranthesisContext ctx); + /** + * Visit a parse tree produced by the {@code ifIntExpression} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIfIntExpression(AlloyInEcoreParser.IfIntExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code count} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitCount(AlloyInEcoreParser.CountContext ctx); + /** + * Visit a parse tree produced by the {@code sum} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSum(AlloyInEcoreParser.SumContext ctx); + /** + * Visit a parse tree produced by the {@code divide} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitDivide(AlloyInEcoreParser.DivideContext ctx); + /** + * Visit a parse tree produced by the {@code multiply} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitMultiply(AlloyInEcoreParser.MultiplyContext ctx); + /** + * Visit a parse tree produced by the {@code modulo} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitModulo(AlloyInEcoreParser.ModuloContext ctx); + /** + * Visit a parse tree produced by the {@code plus} + * labeled alternative in {@link AlloyInEcoreParser#intExpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitPlus(AlloyInEcoreParser.PlusContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#quantifierDeclarations}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitQuantifierDeclarations(AlloyInEcoreParser.QuantifierDeclarationsContext ctx); + /** + * Visit a parse tree produced by the {@code oneOf} + * labeled alternative in {@link AlloyInEcoreParser#quantifierDeclaration}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitOneOf(AlloyInEcoreParser.OneOfContext ctx); + /** + * Visit a parse tree produced by the {@code loneOf} + * labeled alternative in {@link AlloyInEcoreParser#quantifierDeclaration}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitLoneOf(AlloyInEcoreParser.LoneOfContext ctx); + /** + * Visit a parse tree produced by the {@code someOf} + * labeled alternative in {@link AlloyInEcoreParser#quantifierDeclaration}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSomeOf(AlloyInEcoreParser.SomeOfContext ctx); + /** + * Visit a parse tree produced by the {@code setOf} + * labeled alternative in {@link AlloyInEcoreParser#quantifierDeclaration}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSetOf(AlloyInEcoreParser.SetOfContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#letDeclarations}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitLetDeclarations(AlloyInEcoreParser.LetDeclarationsContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#letDeclaration}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitLetDeclaration(AlloyInEcoreParser.LetDeclarationContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#comprehensionDeclarations}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitComprehensionDeclarations(AlloyInEcoreParser.ComprehensionDeclarationsContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#comprehensionDeclaration}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitComprehensionDeclaration(AlloyInEcoreParser.ComprehensionDeclarationContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#relationId}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitRelationId(AlloyInEcoreParser.RelationIdContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#variable}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitVariable(AlloyInEcoreParser.VariableContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#mult}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitMult(AlloyInEcoreParser.MultContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#unrestrictedName}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitUnrestrictedName(AlloyInEcoreParser.UnrestrictedNameContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#identifier}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIdentifier(AlloyInEcoreParser.IdentifierContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#upper}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitUpper(AlloyInEcoreParser.UpperContext ctx); + /** + * Visit a parse tree produced by {@link AlloyInEcoreParser#lower}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitLower(AlloyInEcoreParser.LowerContext ctx); +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/UnderlineErrorListener.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/UnderlineErrorListener.java new file mode 100644 index 00000000..c38e60b6 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/UnderlineErrorListener.java @@ -0,0 +1,59 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.recognizer; + +import org.antlr.v4.runtime.*; + +public class UnderlineErrorListener extends BaseErrorListener { + public void syntaxError(Recognizer recognizer, + Object offendingSymbol, + int line, int charPositionInLine, + String msg, + RecognitionException e) { + underlineError(recognizer, (Token) offendingSymbol, line, charPositionInLine, msg); + } + + private void underlineError(Recognizer recognizer, + Token offendingToken, int line, + int charPositionInLine, String msg) { + CommonTokenStream tokens = (CommonTokenStream) recognizer.getInputStream(); + String input = tokens.getTokenSource().getInputStream().toString(); + String[] lines = input.split("\n"); + String errorLine = lines[line - 1]; + System.err.println("line " + line + ":" + charPositionInLine + " " + msg); + System.err.println(errorLine); + + + for (int i = 0; i < charPositionInLine; i++) System.err.print(" "); + + int start = offendingToken.getStartIndex(); + int stop = offendingToken.getStopIndex(); + + if (start >= 0 && stop >= 0) { + for (int i = start; i <= stop; i++) System.err.print("^"); + } + System.err.println(); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/WarningRecognitionException.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/WarningRecognitionException.java new file mode 100644 index 00000000..2e21ae18 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/WarningRecognitionException.java @@ -0,0 +1,43 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.recognizer; + +import org.antlr.v4.runtime.IntStream; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.Recognizer; + +/** + * Created by ferhat on 1/11/17. + */ +public class WarningRecognitionException extends RecognitionException { + public WarningRecognitionException(Recognizer recognizer, IntStream input, ParserRuleContext ctx) { + super(recognizer, input, ctx); + } + + public WarningRecognitionException(String message, Recognizer recognizer, IntStream input, ParserRuleContext ctx) { + super(message, recognizer, input, ctx); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/Imports.g4 b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/Imports.g4 new file mode 100644 index 00000000..e409e3c0 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/Imports.g4 @@ -0,0 +1,131 @@ +grammar Imports; +//https://github.com/antlr/antlr4/blob/master/doc/wildcard.md + +@parser::header { +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedPackage; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedClass; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedInterface; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedDataType; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedEnum; +import eu.modelwriter.core.alloyinecore.structure.model.Import; +} + +@parser::members { +private Element owningElement; +} + +importModel[Element owner] +@init{owningElement=owner;}: + .*? iPackage[owningElement]* + ; + +iPackage[Element owner] locals[ImportedPackage current] +@after{if(owner != null) owner.addOwnedElement($current); else owningElement= $current;}: + visibility? 'package' name= unrestrictedName {$current = new ImportedPackage($ctx);} + ':' identifier '=' nsURI= SINGLE_QUOTED_STRING ('{' (iClassifier[$current] | iPackage[$current] | . )*? '}' | ';') + + ; + +iClassifier[Element owner]: + (iClass[$owner] | iDataType[$owner]) (block | ';'); + +iClass[Element owner] locals[ImportedClass current] +@after{owner.addOwnedElement($current);}: + visibility? (isAbstract= 'abstract'? isClass='class' | isInterface= 'interface') name= unrestrictedName templateSignature? ('extends' iGenericType (',' iGenericType)*)? + {if ($isInterface!=null) $current = new ImportedInterface($ctx); else $current = new ImportedClass($ctx);} + ; + +iDataType[Element owner] locals[ImportedDataType current] +@after{owner.addOwnedElement($current);}: + visibility? (isDataType= 'datatype' | isEnum= 'enum') name= unrestrictedName templateSignature? (':' instanceClassName= SINGLE_QUOTED_STRING)? + {if ($isDataType!=null) $current = new ImportedDataType($ctx); else $current = new ImportedEnum($ctx);} + ; + +visibility: 'public' | 'protected'| 'private' ; + +block : '{' (block | .)*? '}' ; + +templateSignature: '<' iTypeParameter (',' iTypeParameter)* '>'; + +iTypeParameter: unrestrictedName ('extends' iGenericType ('&' iGenericType)* )?; + +iGenericType: pathName ('<' iGenericTypeArgument (',' iGenericTypeArgument)* '>')? ; + +iGenericTypeArgument: iGenericType | iGenericWildcard ; + +iGenericWildcard: '?' (bound=('extends' | 'super') iGenericType)? ; + +pathName:firstSegment= unrestrictedName ('.' index= INT)? (midSegments+= segment* lastSegment= segment)? ; + +segment: '::' '@'? name= unrestrictedName ('.' index= INT)? ; + +unrestrictedName: + identifier + | 'abstract' + | 'attribute' + | 'body' + | 'callable' + | 'class' + | 'composes' + | 'datatype' + | 'definition' + | 'derivation' + | 'derived' + | 'enum' + | 'ensure' + | 'extends' + | 'id' + | 'import' + | 'initial' + | 'interface'1 + | 'key' + | 'model' + | 'operation' + | 'ordered' + | 'package' + | 'postcondition' + | 'precondition' + | 'primitive' + | 'property'1 + | 'readonly' + | 'reference' + | 'require' + | 'resolve' + | 'static' + | 'throws' + | 'transient' + | 'unique' + | 'unsettable' + | 'volatile' + | 'invariant' + | 'literal' + | 'serializable' + | 'annotation' + | 'model' + +; + +identifier: IDENTIFIER; +//upper: INT | '*'; +//lower: INT; + +INT : DIGIT+ ; +IDENTIFIER : (UNDERSCORE | LETTER) (LETTER | APOSTROPHE | DIGIT | UNDERSCORE | DOLLAR)* ; +SINGLE_CHARACTER: '\'' ~['\\] '\''; +DOUBLE_QUOTED_STRING: '"' ( ESCAPED_CHARACTER | ~('\\' | '"' ) )* '"' ; +SINGLE_QUOTED_STRING: '\'' ( ESCAPED_CHARACTER | ~('\'' | '\\') )* '\'' ; + +fragment LETTER: [a-zA-Z]; +fragment DIGIT: [0-9]; +fragment ESCAPED_CHARACTER: '\\' ('b' | 't' | 'n' | 'f' | 'r' | 'u' | '"' | '\'' | '\\'); +fragment UNDERSCORE: '_'; +fragment APOSTROPHE: '\''; +fragment DOLLAR: '$'; +fragment EXCLAMINATION_MARK: '!'; +fragment MINUS: '-'; +ML_SINGLE_QUOTED_STRING : '\'' .*? '\'' -> skip; +MULTILINE_COMMENT : '/*' .*? '*/' -> skip; +SINGLELINE_COMMENT : ('--' | '//') .*? '\r'? '\n' -> skip; +WS: [ \t\r\n]+ -> skip ; // toss out whitespace +ANY : . ; \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/Imports.tokens b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/Imports.tokens new file mode 100644 index 00000000..5b786306 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/Imports.tokens @@ -0,0 +1,124 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +T__7=8 +T__8=9 +T__9=10 +T__10=11 +T__11=12 +T__12=13 +T__13=14 +T__14=15 +T__15=16 +T__16=17 +T__17=18 +T__18=19 +T__19=20 +T__20=21 +T__21=22 +T__22=23 +T__23=24 +T__24=25 +T__25=26 +T__26=27 +T__27=28 +T__28=29 +T__29=30 +T__30=31 +T__31=32 +T__32=33 +T__33=34 +T__34=35 +T__35=36 +T__36=37 +T__37=38 +T__38=39 +T__39=40 +T__40=41 +T__41=42 +T__42=43 +T__43=44 +T__44=45 +T__45=46 +T__46=47 +T__47=48 +T__48=49 +T__49=50 +T__50=51 +T__51=52 +T__52=53 +T__53=54 +T__54=55 +T__55=56 +T__56=57 +INT=58 +IDENTIFIER=59 +SINGLE_CHARACTER=60 +DOUBLE_QUOTED_STRING=61 +SINGLE_QUOTED_STRING=62 +ML_SINGLE_QUOTED_STRING=63 +MULTILINE_COMMENT=64 +SINGLELINE_COMMENT=65 +WS=66 +ANY=67 +'package'=1 +':'=2 +'='=3 +'{'=4 +'}'=5 +';'=6 +'abstract'=7 +'class'=8 +'interface'=9 +'extends'=10 +','=11 +'datatype'=12 +'enum'=13 +'public'=14 +'protected'=15 +'private'=16 +'<'=17 +'>'=18 +'&'=19 +'?'=20 +'super'=21 +'.'=22 +'::'=23 +'@'=24 +'attribute'=25 +'body'=26 +'callable'=27 +'composes'=28 +'definition'=29 +'derivation'=30 +'derived'=31 +'ensure'=32 +'id'=33 +'import'=34 +'initial'=35 +'key'=36 +'model'=37 +'operation'=38 +'ordered'=39 +'postcondition'=40 +'precondition'=41 +'primitive'=42 +'property'=43 +'readonly'=44 +'reference'=45 +'require'=46 +'resolve'=47 +'static'=48 +'throws'=49 +'transient'=50 +'unique'=51 +'unsettable'=52 +'volatile'=53 +'invariant'=54 +'literal'=55 +'serializable'=56 +'annotation'=57 diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsBaseListener.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsBaseListener.java new file mode 100644 index 00000000..c18db8ff --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsBaseListener.java @@ -0,0 +1,264 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +// Generated from /home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/Imports.g4 by ANTLR 4.6 +package eu.modelwriter.core.alloyinecore.recognizer.imports; + +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedPackage; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedClass; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedInterface; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedDataType; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedEnum; +import eu.modelwriter.core.alloyinecore.structure.model.Import; + + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.TerminalNode; + +/** + * This class provides an empty implementation of {@link ImportsListener}, + * which can be extended to create a listener which only needs to handle a subset + * of the available methods. + */ +public class ImportsBaseListener implements ImportsListener { + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterImportModel(ImportsParser.ImportModelContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitImportModel(ImportsParser.ImportModelContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIPackage(ImportsParser.IPackageContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIPackage(ImportsParser.IPackageContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIClassifier(ImportsParser.IClassifierContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIClassifier(ImportsParser.IClassifierContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIClass(ImportsParser.IClassContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIClass(ImportsParser.IClassContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIDataType(ImportsParser.IDataTypeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIDataType(ImportsParser.IDataTypeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterVisibility(ImportsParser.VisibilityContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitVisibility(ImportsParser.VisibilityContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterBlock(ImportsParser.BlockContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitBlock(ImportsParser.BlockContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterTemplateSignature(ImportsParser.TemplateSignatureContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitTemplateSignature(ImportsParser.TemplateSignatureContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterITypeParameter(ImportsParser.ITypeParameterContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitITypeParameter(ImportsParser.ITypeParameterContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIGenericType(ImportsParser.IGenericTypeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIGenericType(ImportsParser.IGenericTypeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIGenericTypeArgument(ImportsParser.IGenericTypeArgumentContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIGenericTypeArgument(ImportsParser.IGenericTypeArgumentContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIGenericWildcard(ImportsParser.IGenericWildcardContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIGenericWildcard(ImportsParser.IGenericWildcardContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterPathName(ImportsParser.PathNameContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitPathName(ImportsParser.PathNameContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterSegment(ImportsParser.SegmentContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitSegment(ImportsParser.SegmentContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterUnrestrictedName(ImportsParser.UnrestrictedNameContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitUnrestrictedName(ImportsParser.UnrestrictedNameContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIdentifier(ImportsParser.IdentifierContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIdentifier(ImportsParser.IdentifierContext ctx) { } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEveryRule(ParserRuleContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEveryRule(ParserRuleContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void visitTerminal(TerminalNode node) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void visitErrorNode(ErrorNode node) { } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsBaseVisitor.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsBaseVisitor.java new file mode 100644 index 00000000..c1922c22 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsBaseVisitor.java @@ -0,0 +1,159 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +// Generated from /home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/Imports.g4 by ANTLR 4.6 +package eu.modelwriter.core.alloyinecore.recognizer.imports; + +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedPackage; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedClass; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedInterface; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedDataType; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedEnum; +import eu.modelwriter.core.alloyinecore.structure.model.Import; + +import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; + +/** + * This class provides an empty implementation of {@link ImportsVisitor}, + * which can be extended to create a visitor which only needs to handle a subset + * of the available methods. + * + * @param The return type of the visit operation. Use {@link Void} for + * operations with no return type. + */ +public class ImportsBaseVisitor extends AbstractParseTreeVisitor implements ImportsVisitor { + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitImportModel(ImportsParser.ImportModelContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIPackage(ImportsParser.IPackageContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIClassifier(ImportsParser.IClassifierContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIClass(ImportsParser.IClassContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIDataType(ImportsParser.IDataTypeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitVisibility(ImportsParser.VisibilityContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitBlock(ImportsParser.BlockContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitTemplateSignature(ImportsParser.TemplateSignatureContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitITypeParameter(ImportsParser.ITypeParameterContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIGenericType(ImportsParser.IGenericTypeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIGenericTypeArgument(ImportsParser.IGenericTypeArgumentContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIGenericWildcard(ImportsParser.IGenericWildcardContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitPathName(ImportsParser.PathNameContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitSegment(ImportsParser.SegmentContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitUnrestrictedName(ImportsParser.UnrestrictedNameContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIdentifier(ImportsParser.IdentifierContext ctx) { return visitChildren(ctx); } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsLexer.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsLexer.java new file mode 100644 index 00000000..f80560e3 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsLexer.java @@ -0,0 +1,374 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +// Generated from /home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/Imports.g4 by ANTLR 4.6 +package eu.modelwriter.core.alloyinecore.recognizer.imports; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.TokenStream; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.misc.*; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class ImportsLexer extends Lexer { + static { RuntimeMetaData.checkVersion("4.6", RuntimeMetaData.VERSION); } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, + T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, + T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, + T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, T__29=30, T__30=31, + T__31=32, T__32=33, T__33=34, T__34=35, T__35=36, T__36=37, T__37=38, + T__38=39, T__39=40, T__40=41, T__41=42, T__42=43, T__43=44, T__44=45, + T__45=46, T__46=47, T__47=48, T__48=49, T__49=50, T__50=51, T__51=52, + T__52=53, T__53=54, T__54=55, T__55=56, T__56=57, INT=58, IDENTIFIER=59, + SINGLE_CHARACTER=60, DOUBLE_QUOTED_STRING=61, SINGLE_QUOTED_STRING=62, + ML_SINGLE_QUOTED_STRING=63, MULTILINE_COMMENT=64, SINGLELINE_COMMENT=65, + WS=66, ANY=67; + public static String[] modeNames = { + "DEFAULT_MODE" + }; + + public static final String[] ruleNames = { + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", + "T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16", + "T__17", "T__18", "T__19", "T__20", "T__21", "T__22", "T__23", "T__24", + "T__25", "T__26", "T__27", "T__28", "T__29", "T__30", "T__31", "T__32", + "T__33", "T__34", "T__35", "T__36", "T__37", "T__38", "T__39", "T__40", + "T__41", "T__42", "T__43", "T__44", "T__45", "T__46", "T__47", "T__48", + "T__49", "T__50", "T__51", "T__52", "T__53", "T__54", "T__55", "T__56", + "INT", "IDENTIFIER", "SINGLE_CHARACTER", "DOUBLE_QUOTED_STRING", "SINGLE_QUOTED_STRING", + "LETTER", "DIGIT", "ESCAPED_CHARACTER", "UNDERSCORE", "APOSTROPHE", "DOLLAR", + "EXCLAMINATION_MARK", "MINUS", "ML_SINGLE_QUOTED_STRING", "MULTILINE_COMMENT", + "SINGLELINE_COMMENT", "WS", "ANY" + }; + + private static final String[] _LITERAL_NAMES = { + null, "'package'", "':'", "'='", "'{'", "'}'", "';'", "'abstract'", "'class'", + "'interface'", "'extends'", "','", "'datatype'", "'enum'", "'public'", + "'protected'", "'private'", "'<'", "'>'", "'&'", "'?'", "'super'", "'.'", + "'::'", "'@'", "'attribute'", "'body'", "'callable'", "'composes'", "'definition'", + "'derivation'", "'derived'", "'ensure'", "'id'", "'import'", "'initial'", + "'key'", "'model'", "'operation'", "'ordered'", "'postcondition'", "'precondition'", + "'primitive'", "'property'", "'readonly'", "'reference'", "'require'", + "'resolve'", "'static'", "'throws'", "'transient'", "'unique'", "'unsettable'", + "'volatile'", "'invariant'", "'literal'", "'serializable'", "'annotation'" + }; + private static final String[] _SYMBOLIC_NAMES = { + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, "INT", "IDENTIFIER", + "SINGLE_CHARACTER", "DOUBLE_QUOTED_STRING", "SINGLE_QUOTED_STRING", "ML_SINGLE_QUOTED_STRING", + "MULTILINE_COMMENT", "SINGLELINE_COMMENT", "WS", "ANY" + }; + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + + public ImportsLexer(CharStream input) { + super(input); + _interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); + } + + @Override + public String getGrammarFileName() { return "Imports.g4"; } + + @Override + public String[] getRuleNames() { return ruleNames; } + + @Override + public String getSerializedATN() { return _serializedATN; } + + @Override + public String[] getModeNames() { return modeNames; } + + @Override + public ATN getATN() { return _ATN; } + + public static final String _serializedATN = + "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2E\u029d\b\1\4\2\t"+ + "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ + "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ + "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ + "\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+ + "\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t+\4"+ + ",\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64\t"+ + "\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:\4;\t;\4<\t<\4=\t="+ + "\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4E\tE\4F\tF\4G\tG\4H\tH\4I"+ + "\tI\4J\tJ\4K\tK\4L\tL\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\3\3\3\3\4\3\4"+ + "\3\5\3\5\3\6\3\6\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3"+ + "\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13"+ + "\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r"+ + "\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\20\3\20"+ + "\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21"+ + "\3\21\3\21\3\22\3\22\3\23\3\23\3\24\3\24\3\25\3\25\3\26\3\26\3\26\3\26"+ + "\3\26\3\26\3\27\3\27\3\30\3\30\3\30\3\31\3\31\3\32\3\32\3\32\3\32\3\32"+ + "\3\32\3\32\3\32\3\32\3\32\3\33\3\33\3\33\3\33\3\33\3\34\3\34\3\34\3\34"+ + "\3\34\3\34\3\34\3\34\3\34\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35"+ + "\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\37\3\37\3\37"+ + "\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3 \3 \3 \3 \3 \3 \3 \3 \3!\3"+ + "!\3!\3!\3!\3!\3!\3\"\3\"\3\"\3#\3#\3#\3#\3#\3#\3#\3$\3$\3$\3$\3$\3$\3"+ + "$\3$\3%\3%\3%\3%\3&\3&\3&\3&\3&\3&\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'"+ + "\3\'\3(\3(\3(\3(\3(\3(\3(\3(\3)\3)\3)\3)\3)\3)\3)\3)\3)\3)\3)\3)\3)\3"+ + ")\3*\3*\3*\3*\3*\3*\3*\3*\3*\3*\3*\3*\3*\3+\3+\3+\3+\3+\3+\3+\3+\3+\3"+ + "+\3,\3,\3,\3,\3,\3,\3,\3,\3,\3-\3-\3-\3-\3-\3-\3-\3-\3-\3.\3.\3.\3.\3"+ + ".\3.\3.\3.\3.\3.\3/\3/\3/\3/\3/\3/\3/\3/\3\60\3\60\3\60\3\60\3\60\3\60"+ + "\3\60\3\60\3\61\3\61\3\61\3\61\3\61\3\61\3\61\3\62\3\62\3\62\3\62\3\62"+ + "\3\62\3\62\3\63\3\63\3\63\3\63\3\63\3\63\3\63\3\63\3\63\3\63\3\64\3\64"+ + "\3\64\3\64\3\64\3\64\3\64\3\65\3\65\3\65\3\65\3\65\3\65\3\65\3\65\3\65"+ + "\3\65\3\65\3\66\3\66\3\66\3\66\3\66\3\66\3\66\3\66\3\66\3\67\3\67\3\67"+ + "\3\67\3\67\3\67\3\67\3\67\3\67\3\67\38\38\38\38\38\38\38\38\39\39\39\3"+ + "9\39\39\39\39\39\39\39\39\39\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3:\3;\6;\u022e"+ + "\n;\r;\16;\u022f\3<\3<\5<\u0234\n<\3<\3<\3<\3<\3<\7<\u023b\n<\f<\16<\u023e"+ + "\13<\3=\3=\3=\3=\3>\3>\3>\7>\u0247\n>\f>\16>\u024a\13>\3>\3>\3?\3?\3?"+ + "\7?\u0251\n?\f?\16?\u0254\13?\3?\3?\3@\3@\3A\3A\3B\3B\3B\3C\3C\3D\3D\3"+ + "E\3E\3F\3F\3G\3G\3H\3H\7H\u026b\nH\fH\16H\u026e\13H\3H\3H\3H\3H\3I\3I"+ + "\3I\3I\7I\u0278\nI\fI\16I\u027b\13I\3I\3I\3I\3I\3I\3J\3J\3J\3J\5J\u0286"+ + "\nJ\3J\7J\u0289\nJ\fJ\16J\u028c\13J\3J\5J\u028f\nJ\3J\3J\3J\3J\3K\6K\u0296"+ + "\nK\rK\16K\u0297\3K\3K\3L\3L\5\u026c\u0279\u028a\2M\3\3\5\4\7\5\t\6\13"+ + "\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'"+ + "\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'"+ + "M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o9q:s;u{?}@\177"+ + "\2\u0081\2\u0083\2\u0085\2\u0087\2\u0089\2\u008b\2\u008d\2\u008fA\u0091"+ + "B\u0093C\u0095D\u0097E\3\2\b\4\2))^^\4\2$$^^\4\2C\\c|\3\2\62;\n\2$$))"+ + "^^ddhhppttvw\5\2\13\f\17\17\"\"\u02a5\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2"+ + "\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2"+ + "\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3"+ + "\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3"+ + "\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65"+ + "\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3"+ + "\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2"+ + "\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2"+ + "[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3"+ + "\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2"+ + "\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2\u008f\3\2"+ + "\2\2\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\3"+ + "\u0099\3\2\2\2\5\u00a1\3\2\2\2\7\u00a3\3\2\2\2\t\u00a5\3\2\2\2\13\u00a7"+ + "\3\2\2\2\r\u00a9\3\2\2\2\17\u00ab\3\2\2\2\21\u00b4\3\2\2\2\23\u00ba\3"+ + "\2\2\2\25\u00c4\3\2\2\2\27\u00cc\3\2\2\2\31\u00ce\3\2\2\2\33\u00d7\3\2"+ + "\2\2\35\u00dc\3\2\2\2\37\u00e3\3\2\2\2!\u00ed\3\2\2\2#\u00f5\3\2\2\2%"+ + "\u00f7\3\2\2\2\'\u00f9\3\2\2\2)\u00fb\3\2\2\2+\u00fd\3\2\2\2-\u0103\3"+ + "\2\2\2/\u0105\3\2\2\2\61\u0108\3\2\2\2\63\u010a\3\2\2\2\65\u0114\3\2\2"+ + "\2\67\u0119\3\2\2\29\u0122\3\2\2\2;\u012b\3\2\2\2=\u0136\3\2\2\2?\u0141"+ + "\3\2\2\2A\u0149\3\2\2\2C\u0150\3\2\2\2E\u0153\3\2\2\2G\u015a\3\2\2\2I"+ + "\u0162\3\2\2\2K\u0166\3\2\2\2M\u016c\3\2\2\2O\u0176\3\2\2\2Q\u017e\3\2"+ + "\2\2S\u018c\3\2\2\2U\u0199\3\2\2\2W\u01a3\3\2\2\2Y\u01ac\3\2\2\2[\u01b5"+ + "\3\2\2\2]\u01bf\3\2\2\2_\u01c7\3\2\2\2a\u01cf\3\2\2\2c\u01d6\3\2\2\2e"+ + "\u01dd\3\2\2\2g\u01e7\3\2\2\2i\u01ee\3\2\2\2k\u01f9\3\2\2\2m\u0202\3\2"+ + "\2\2o\u020c\3\2\2\2q\u0214\3\2\2\2s\u0221\3\2\2\2u\u022d\3\2\2\2w\u0233"+ + "\3\2\2\2y\u023f\3\2\2\2{\u0243\3\2\2\2}\u024d\3\2\2\2\177\u0257\3\2\2"+ + "\2\u0081\u0259\3\2\2\2\u0083\u025b\3\2\2\2\u0085\u025e\3\2\2\2\u0087\u0260"+ + "\3\2\2\2\u0089\u0262\3\2\2\2\u008b\u0264\3\2\2\2\u008d\u0266\3\2\2\2\u008f"+ + "\u0268\3\2\2\2\u0091\u0273\3\2\2\2\u0093\u0285\3\2\2\2\u0095\u0295\3\2"+ + "\2\2\u0097\u029b\3\2\2\2\u0099\u009a\7r\2\2\u009a\u009b\7c\2\2\u009b\u009c"+ + "\7e\2\2\u009c\u009d\7m\2\2\u009d\u009e\7c\2\2\u009e\u009f\7i\2\2\u009f"+ + "\u00a0\7g\2\2\u00a0\4\3\2\2\2\u00a1\u00a2\7<\2\2\u00a2\6\3\2\2\2\u00a3"+ + "\u00a4\7?\2\2\u00a4\b\3\2\2\2\u00a5\u00a6\7}\2\2\u00a6\n\3\2\2\2\u00a7"+ + "\u00a8\7\177\2\2\u00a8\f\3\2\2\2\u00a9\u00aa\7=\2\2\u00aa\16\3\2\2\2\u00ab"+ + "\u00ac\7c\2\2\u00ac\u00ad\7d\2\2\u00ad\u00ae\7u\2\2\u00ae\u00af\7v\2\2"+ + "\u00af\u00b0\7t\2\2\u00b0\u00b1\7c\2\2\u00b1\u00b2\7e\2\2\u00b2\u00b3"+ + "\7v\2\2\u00b3\20\3\2\2\2\u00b4\u00b5\7e\2\2\u00b5\u00b6\7n\2\2\u00b6\u00b7"+ + "\7c\2\2\u00b7\u00b8\7u\2\2\u00b8\u00b9\7u\2\2\u00b9\22\3\2\2\2\u00ba\u00bb"+ + "\7k\2\2\u00bb\u00bc\7p\2\2\u00bc\u00bd\7v\2\2\u00bd\u00be\7g\2\2\u00be"+ + "\u00bf\7t\2\2\u00bf\u00c0\7h\2\2\u00c0\u00c1\7c\2\2\u00c1\u00c2\7e\2\2"+ + "\u00c2\u00c3\7g\2\2\u00c3\24\3\2\2\2\u00c4\u00c5\7g\2\2\u00c5\u00c6\7"+ + "z\2\2\u00c6\u00c7\7v\2\2\u00c7\u00c8\7g\2\2\u00c8\u00c9\7p\2\2\u00c9\u00ca"+ + "\7f\2\2\u00ca\u00cb\7u\2\2\u00cb\26\3\2\2\2\u00cc\u00cd\7.\2\2\u00cd\30"+ + "\3\2\2\2\u00ce\u00cf\7f\2\2\u00cf\u00d0\7c\2\2\u00d0\u00d1\7v\2\2\u00d1"+ + "\u00d2\7c\2\2\u00d2\u00d3\7v\2\2\u00d3\u00d4\7{\2\2\u00d4\u00d5\7r\2\2"+ + "\u00d5\u00d6\7g\2\2\u00d6\32\3\2\2\2\u00d7\u00d8\7g\2\2\u00d8\u00d9\7"+ + "p\2\2\u00d9\u00da\7w\2\2\u00da\u00db\7o\2\2\u00db\34\3\2\2\2\u00dc\u00dd"+ + "\7r\2\2\u00dd\u00de\7w\2\2\u00de\u00df\7d\2\2\u00df\u00e0\7n\2\2\u00e0"+ + "\u00e1\7k\2\2\u00e1\u00e2\7e\2\2\u00e2\36\3\2\2\2\u00e3\u00e4\7r\2\2\u00e4"+ + "\u00e5\7t\2\2\u00e5\u00e6\7q\2\2\u00e6\u00e7\7v\2\2\u00e7\u00e8\7g\2\2"+ + "\u00e8\u00e9\7e\2\2\u00e9\u00ea\7v\2\2\u00ea\u00eb\7g\2\2\u00eb\u00ec"+ + "\7f\2\2\u00ec \3\2\2\2\u00ed\u00ee\7r\2\2\u00ee\u00ef\7t\2\2\u00ef\u00f0"+ + "\7k\2\2\u00f0\u00f1\7x\2\2\u00f1\u00f2\7c\2\2\u00f2\u00f3\7v\2\2\u00f3"+ + "\u00f4\7g\2\2\u00f4\"\3\2\2\2\u00f5\u00f6\7>\2\2\u00f6$\3\2\2\2\u00f7"+ + "\u00f8\7@\2\2\u00f8&\3\2\2\2\u00f9\u00fa\7(\2\2\u00fa(\3\2\2\2\u00fb\u00fc"+ + "\7A\2\2\u00fc*\3\2\2\2\u00fd\u00fe\7u\2\2\u00fe\u00ff\7w\2\2\u00ff\u0100"+ + "\7r\2\2\u0100\u0101\7g\2\2\u0101\u0102\7t\2\2\u0102,\3\2\2\2\u0103\u0104"+ + "\7\60\2\2\u0104.\3\2\2\2\u0105\u0106\7<\2\2\u0106\u0107\7<\2\2\u0107\60"+ + "\3\2\2\2\u0108\u0109\7B\2\2\u0109\62\3\2\2\2\u010a\u010b\7c\2\2\u010b"+ + "\u010c\7v\2\2\u010c\u010d\7v\2\2\u010d\u010e\7t\2\2\u010e\u010f\7k\2\2"+ + "\u010f\u0110\7d\2\2\u0110\u0111\7w\2\2\u0111\u0112\7v\2\2\u0112\u0113"+ + "\7g\2\2\u0113\64\3\2\2\2\u0114\u0115\7d\2\2\u0115\u0116\7q\2\2\u0116\u0117"+ + "\7f\2\2\u0117\u0118\7{\2\2\u0118\66\3\2\2\2\u0119\u011a\7e\2\2\u011a\u011b"+ + "\7c\2\2\u011b\u011c\7n\2\2\u011c\u011d\7n\2\2\u011d\u011e\7c\2\2\u011e"+ + "\u011f\7d\2\2\u011f\u0120\7n\2\2\u0120\u0121\7g\2\2\u01218\3\2\2\2\u0122"+ + "\u0123\7e\2\2\u0123\u0124\7q\2\2\u0124\u0125\7o\2\2\u0125\u0126\7r\2\2"+ + "\u0126\u0127\7q\2\2\u0127\u0128\7u\2\2\u0128\u0129\7g\2\2\u0129\u012a"+ + "\7u\2\2\u012a:\3\2\2\2\u012b\u012c\7f\2\2\u012c\u012d\7g\2\2\u012d\u012e"+ + "\7h\2\2\u012e\u012f\7k\2\2\u012f\u0130\7p\2\2\u0130\u0131\7k\2\2\u0131"+ + "\u0132\7v\2\2\u0132\u0133\7k\2\2\u0133\u0134\7q\2\2\u0134\u0135\7p\2\2"+ + "\u0135<\3\2\2\2\u0136\u0137\7f\2\2\u0137\u0138\7g\2\2\u0138\u0139\7t\2"+ + "\2\u0139\u013a\7k\2\2\u013a\u013b\7x\2\2\u013b\u013c\7c\2\2\u013c\u013d"+ + "\7v\2\2\u013d\u013e\7k\2\2\u013e\u013f\7q\2\2\u013f\u0140\7p\2\2\u0140"+ + ">\3\2\2\2\u0141\u0142\7f\2\2\u0142\u0143\7g\2\2\u0143\u0144\7t\2\2\u0144"+ + "\u0145\7k\2\2\u0145\u0146\7x\2\2\u0146\u0147\7g\2\2\u0147\u0148\7f\2\2"+ + "\u0148@\3\2\2\2\u0149\u014a\7g\2\2\u014a\u014b\7p\2\2\u014b\u014c\7u\2"+ + "\2\u014c\u014d\7w\2\2\u014d\u014e\7t\2\2\u014e\u014f\7g\2\2\u014fB\3\2"+ + "\2\2\u0150\u0151\7k\2\2\u0151\u0152\7f\2\2\u0152D\3\2\2\2\u0153\u0154"+ + "\7k\2\2\u0154\u0155\7o\2\2\u0155\u0156\7r\2\2\u0156\u0157\7q\2\2\u0157"+ + "\u0158\7t\2\2\u0158\u0159\7v\2\2\u0159F\3\2\2\2\u015a\u015b\7k\2\2\u015b"+ + "\u015c\7p\2\2\u015c\u015d\7k\2\2\u015d\u015e\7v\2\2\u015e\u015f\7k\2\2"+ + "\u015f\u0160\7c\2\2\u0160\u0161\7n\2\2\u0161H\3\2\2\2\u0162\u0163\7m\2"+ + "\2\u0163\u0164\7g\2\2\u0164\u0165\7{\2\2\u0165J\3\2\2\2\u0166\u0167\7"+ + "o\2\2\u0167\u0168\7q\2\2\u0168\u0169\7f\2\2\u0169\u016a\7g\2\2\u016a\u016b"+ + "\7n\2\2\u016bL\3\2\2\2\u016c\u016d\7q\2\2\u016d\u016e\7r\2\2\u016e\u016f"+ + "\7g\2\2\u016f\u0170\7t\2\2\u0170\u0171\7c\2\2\u0171\u0172\7v\2\2\u0172"+ + "\u0173\7k\2\2\u0173\u0174\7q\2\2\u0174\u0175\7p\2\2\u0175N\3\2\2\2\u0176"+ + "\u0177\7q\2\2\u0177\u0178\7t\2\2\u0178\u0179\7f\2\2\u0179\u017a\7g\2\2"+ + "\u017a\u017b\7t\2\2\u017b\u017c\7g\2\2\u017c\u017d\7f\2\2\u017dP\3\2\2"+ + "\2\u017e\u017f\7r\2\2\u017f\u0180\7q\2\2\u0180\u0181\7u\2\2\u0181\u0182"+ + "\7v\2\2\u0182\u0183\7e\2\2\u0183\u0184\7q\2\2\u0184\u0185\7p\2\2\u0185"+ + "\u0186\7f\2\2\u0186\u0187\7k\2\2\u0187\u0188\7v\2\2\u0188\u0189\7k\2\2"+ + "\u0189\u018a\7q\2\2\u018a\u018b\7p\2\2\u018bR\3\2\2\2\u018c\u018d\7r\2"+ + "\2\u018d\u018e\7t\2\2\u018e\u018f\7g\2\2\u018f\u0190\7e\2\2\u0190\u0191"+ + "\7q\2\2\u0191\u0192\7p\2\2\u0192\u0193\7f\2\2\u0193\u0194\7k\2\2\u0194"+ + "\u0195\7v\2\2\u0195\u0196\7k\2\2\u0196\u0197\7q\2\2\u0197\u0198\7p\2\2"+ + "\u0198T\3\2\2\2\u0199\u019a\7r\2\2\u019a\u019b\7t\2\2\u019b\u019c\7k\2"+ + "\2\u019c\u019d\7o\2\2\u019d\u019e\7k\2\2\u019e\u019f\7v\2\2\u019f\u01a0"+ + "\7k\2\2\u01a0\u01a1\7x\2\2\u01a1\u01a2\7g\2\2\u01a2V\3\2\2\2\u01a3\u01a4"+ + "\7r\2\2\u01a4\u01a5\7t\2\2\u01a5\u01a6\7q\2\2\u01a6\u01a7\7r\2\2\u01a7"+ + "\u01a8\7g\2\2\u01a8\u01a9\7t\2\2\u01a9\u01aa\7v\2\2\u01aa\u01ab\7{\2\2"+ + "\u01abX\3\2\2\2\u01ac\u01ad\7t\2\2\u01ad\u01ae\7g\2\2\u01ae\u01af\7c\2"+ + "\2\u01af\u01b0\7f\2\2\u01b0\u01b1\7q\2\2\u01b1\u01b2\7p\2\2\u01b2\u01b3"+ + "\7n\2\2\u01b3\u01b4\7{\2\2\u01b4Z\3\2\2\2\u01b5\u01b6\7t\2\2\u01b6\u01b7"+ + "\7g\2\2\u01b7\u01b8\7h\2\2\u01b8\u01b9\7g\2\2\u01b9\u01ba\7t\2\2\u01ba"+ + "\u01bb\7g\2\2\u01bb\u01bc\7p\2\2\u01bc\u01bd\7e\2\2\u01bd\u01be\7g\2\2"+ + "\u01be\\\3\2\2\2\u01bf\u01c0\7t\2\2\u01c0\u01c1\7g\2\2\u01c1\u01c2\7s"+ + "\2\2\u01c2\u01c3\7w\2\2\u01c3\u01c4\7k\2\2\u01c4\u01c5\7t\2\2\u01c5\u01c6"+ + "\7g\2\2\u01c6^\3\2\2\2\u01c7\u01c8\7t\2\2\u01c8\u01c9\7g\2\2\u01c9\u01ca"+ + "\7u\2\2\u01ca\u01cb\7q\2\2\u01cb\u01cc\7n\2\2\u01cc\u01cd\7x\2\2\u01cd"+ + "\u01ce\7g\2\2\u01ce`\3\2\2\2\u01cf\u01d0\7u\2\2\u01d0\u01d1\7v\2\2\u01d1"+ + "\u01d2\7c\2\2\u01d2\u01d3\7v\2\2\u01d3\u01d4\7k\2\2\u01d4\u01d5\7e\2\2"+ + "\u01d5b\3\2\2\2\u01d6\u01d7\7v\2\2\u01d7\u01d8\7j\2\2\u01d8\u01d9\7t\2"+ + "\2\u01d9\u01da\7q\2\2\u01da\u01db\7y\2\2\u01db\u01dc\7u\2\2\u01dcd\3\2"+ + "\2\2\u01dd\u01de\7v\2\2\u01de\u01df\7t\2\2\u01df\u01e0\7c\2\2\u01e0\u01e1"+ + "\7p\2\2\u01e1\u01e2\7u\2\2\u01e2\u01e3\7k\2\2\u01e3\u01e4\7g\2\2\u01e4"+ + "\u01e5\7p\2\2\u01e5\u01e6\7v\2\2\u01e6f\3\2\2\2\u01e7\u01e8\7w\2\2\u01e8"+ + "\u01e9\7p\2\2\u01e9\u01ea\7k\2\2\u01ea\u01eb\7s\2\2\u01eb\u01ec\7w\2\2"+ + "\u01ec\u01ed\7g\2\2\u01edh\3\2\2\2\u01ee\u01ef\7w\2\2\u01ef\u01f0\7p\2"+ + "\2\u01f0\u01f1\7u\2\2\u01f1\u01f2\7g\2\2\u01f2\u01f3\7v\2\2\u01f3\u01f4"+ + "\7v\2\2\u01f4\u01f5\7c\2\2\u01f5\u01f6\7d\2\2\u01f6\u01f7\7n\2\2\u01f7"+ + "\u01f8\7g\2\2\u01f8j\3\2\2\2\u01f9\u01fa\7x\2\2\u01fa\u01fb\7q\2\2\u01fb"+ + "\u01fc\7n\2\2\u01fc\u01fd\7c\2\2\u01fd\u01fe\7v\2\2\u01fe\u01ff\7k\2\2"+ + "\u01ff\u0200\7n\2\2\u0200\u0201\7g\2\2\u0201l\3\2\2\2\u0202\u0203\7k\2"+ + "\2\u0203\u0204\7p\2\2\u0204\u0205\7x\2\2\u0205\u0206\7c\2\2\u0206\u0207"+ + "\7t\2\2\u0207\u0208\7k\2\2\u0208\u0209\7c\2\2\u0209\u020a\7p\2\2\u020a"+ + "\u020b\7v\2\2\u020bn\3\2\2\2\u020c\u020d\7n\2\2\u020d\u020e\7k\2\2\u020e"+ + "\u020f\7v\2\2\u020f\u0210\7g\2\2\u0210\u0211\7t\2\2\u0211\u0212\7c\2\2"+ + "\u0212\u0213\7n\2\2\u0213p\3\2\2\2\u0214\u0215\7u\2\2\u0215\u0216\7g\2"+ + "\2\u0216\u0217\7t\2\2\u0217\u0218\7k\2\2\u0218\u0219\7c\2\2\u0219\u021a"+ + "\7n\2\2\u021a\u021b\7k\2\2\u021b\u021c\7|\2\2\u021c\u021d\7c\2\2\u021d"+ + "\u021e\7d\2\2\u021e\u021f\7n\2\2\u021f\u0220\7g\2\2\u0220r\3\2\2\2\u0221"+ + "\u0222\7c\2\2\u0222\u0223\7p\2\2\u0223\u0224\7p\2\2\u0224\u0225\7q\2\2"+ + "\u0225\u0226\7v\2\2\u0226\u0227\7c\2\2\u0227\u0228\7v\2\2\u0228\u0229"+ + "\7k\2\2\u0229\u022a\7q\2\2\u022a\u022b\7p\2\2\u022bt\3\2\2\2\u022c\u022e"+ + "\5\u0081A\2\u022d\u022c\3\2\2\2\u022e\u022f\3\2\2\2\u022f\u022d\3\2\2"+ + "\2\u022f\u0230\3\2\2\2\u0230v\3\2\2\2\u0231\u0234\5\u0085C\2\u0232\u0234"+ + "\5\177@\2\u0233\u0231\3\2\2\2\u0233\u0232\3\2\2\2\u0234\u023c\3\2\2\2"+ + "\u0235\u023b\5\177@\2\u0236\u023b\5\u0087D\2\u0237\u023b\5\u0081A\2\u0238"+ + "\u023b\5\u0085C\2\u0239\u023b\5\u0089E\2\u023a\u0235\3\2\2\2\u023a\u0236"+ + "\3\2\2\2\u023a\u0237\3\2\2\2\u023a\u0238\3\2\2\2\u023a\u0239\3\2\2\2\u023b"+ + "\u023e\3\2\2\2\u023c\u023a\3\2\2\2\u023c\u023d\3\2\2\2\u023dx\3\2\2\2"+ + "\u023e\u023c\3\2\2\2\u023f\u0240\7)\2\2\u0240\u0241\n\2\2\2\u0241\u0242"+ + "\7)\2\2\u0242z\3\2\2\2\u0243\u0248\7$\2\2\u0244\u0247\5\u0083B\2\u0245"+ + "\u0247\n\3\2\2\u0246\u0244\3\2\2\2\u0246\u0245\3\2\2\2\u0247\u024a\3\2"+ + "\2\2\u0248\u0246\3\2\2\2\u0248\u0249\3\2\2\2\u0249\u024b\3\2\2\2\u024a"+ + "\u0248\3\2\2\2\u024b\u024c\7$\2\2\u024c|\3\2\2\2\u024d\u0252\7)\2\2\u024e"+ + "\u0251\5\u0083B\2\u024f\u0251\n\2\2\2\u0250\u024e\3\2\2\2\u0250\u024f"+ + "\3\2\2\2\u0251\u0254\3\2\2\2\u0252\u0250\3\2\2\2\u0252\u0253\3\2\2\2\u0253"+ + "\u0255\3\2\2\2\u0254\u0252\3\2\2\2\u0255\u0256\7)\2\2\u0256~\3\2\2\2\u0257"+ + "\u0258\t\4\2\2\u0258\u0080\3\2\2\2\u0259\u025a\t\5\2\2\u025a\u0082\3\2"+ + "\2\2\u025b\u025c\7^\2\2\u025c\u025d\t\6\2\2\u025d\u0084\3\2\2\2\u025e"+ + "\u025f\7a\2\2\u025f\u0086\3\2\2\2\u0260\u0261\7)\2\2\u0261\u0088\3\2\2"+ + "\2\u0262\u0263\7&\2\2\u0263\u008a\3\2\2\2\u0264\u0265\7#\2\2\u0265\u008c"+ + "\3\2\2\2\u0266\u0267\7/\2\2\u0267\u008e\3\2\2\2\u0268\u026c\7)\2\2\u0269"+ + "\u026b\13\2\2\2\u026a\u0269\3\2\2\2\u026b\u026e\3\2\2\2\u026c\u026d\3"+ + "\2\2\2\u026c\u026a\3\2\2\2\u026d\u026f\3\2\2\2\u026e\u026c\3\2\2\2\u026f"+ + "\u0270\7)\2\2\u0270\u0271\3\2\2\2\u0271\u0272\bH\2\2\u0272\u0090\3\2\2"+ + "\2\u0273\u0274\7\61\2\2\u0274\u0275\7,\2\2\u0275\u0279\3\2\2\2\u0276\u0278"+ + "\13\2\2\2\u0277\u0276\3\2\2\2\u0278\u027b\3\2\2\2\u0279\u027a\3\2\2\2"+ + "\u0279\u0277\3\2\2\2\u027a\u027c\3\2\2\2\u027b\u0279\3\2\2\2\u027c\u027d"+ + "\7,\2\2\u027d\u027e\7\61\2\2\u027e\u027f\3\2\2\2\u027f\u0280\bI\2\2\u0280"+ + "\u0092\3\2\2\2\u0281\u0282\7/\2\2\u0282\u0286\7/\2\2\u0283\u0284\7\61"+ + "\2\2\u0284\u0286\7\61\2\2\u0285\u0281\3\2\2\2\u0285\u0283\3\2\2\2\u0286"+ + "\u028a\3\2\2\2\u0287\u0289\13\2\2\2\u0288\u0287\3\2\2\2\u0289\u028c\3"+ + "\2\2\2\u028a\u028b\3\2\2\2\u028a\u0288\3\2\2\2\u028b\u028e\3\2\2\2\u028c"+ + "\u028a\3\2\2\2\u028d\u028f\7\17\2\2\u028e\u028d\3\2\2\2\u028e\u028f\3"+ + "\2\2\2\u028f\u0290\3\2\2\2\u0290\u0291\7\f\2\2\u0291\u0292\3\2\2\2\u0292"+ + "\u0293\bJ\2\2\u0293\u0094\3\2\2\2\u0294\u0296\t\7\2\2\u0295\u0294\3\2"+ + "\2\2\u0296\u0297\3\2\2\2\u0297\u0295\3\2\2\2\u0297\u0298\3\2\2\2\u0298"+ + "\u0299\3\2\2\2\u0299\u029a\bK\2\2\u029a\u0096\3\2\2\2\u029b\u029c\13\2"+ + "\2\2\u029c\u0098\3\2\2\2\21\2\u022f\u0233\u023a\u023c\u0246\u0248\u0250"+ + "\u0252\u026c\u0279\u0285\u028a\u028e\u0297\3\b\2\2"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsLexer.tokens b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsLexer.tokens new file mode 100644 index 00000000..5b786306 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsLexer.tokens @@ -0,0 +1,124 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +T__7=8 +T__8=9 +T__9=10 +T__10=11 +T__11=12 +T__12=13 +T__13=14 +T__14=15 +T__15=16 +T__16=17 +T__17=18 +T__18=19 +T__19=20 +T__20=21 +T__21=22 +T__22=23 +T__23=24 +T__24=25 +T__25=26 +T__26=27 +T__27=28 +T__28=29 +T__29=30 +T__30=31 +T__31=32 +T__32=33 +T__33=34 +T__34=35 +T__35=36 +T__36=37 +T__37=38 +T__38=39 +T__39=40 +T__40=41 +T__41=42 +T__42=43 +T__43=44 +T__44=45 +T__45=46 +T__46=47 +T__47=48 +T__48=49 +T__49=50 +T__50=51 +T__51=52 +T__52=53 +T__53=54 +T__54=55 +T__55=56 +T__56=57 +INT=58 +IDENTIFIER=59 +SINGLE_CHARACTER=60 +DOUBLE_QUOTED_STRING=61 +SINGLE_QUOTED_STRING=62 +ML_SINGLE_QUOTED_STRING=63 +MULTILINE_COMMENT=64 +SINGLELINE_COMMENT=65 +WS=66 +ANY=67 +'package'=1 +':'=2 +'='=3 +'{'=4 +'}'=5 +';'=6 +'abstract'=7 +'class'=8 +'interface'=9 +'extends'=10 +','=11 +'datatype'=12 +'enum'=13 +'public'=14 +'protected'=15 +'private'=16 +'<'=17 +'>'=18 +'&'=19 +'?'=20 +'super'=21 +'.'=22 +'::'=23 +'@'=24 +'attribute'=25 +'body'=26 +'callable'=27 +'composes'=28 +'definition'=29 +'derivation'=30 +'derived'=31 +'ensure'=32 +'id'=33 +'import'=34 +'initial'=35 +'key'=36 +'model'=37 +'operation'=38 +'ordered'=39 +'postcondition'=40 +'precondition'=41 +'primitive'=42 +'property'=43 +'readonly'=44 +'reference'=45 +'require'=46 +'resolve'=47 +'static'=48 +'throws'=49 +'transient'=50 +'unique'=51 +'unsettable'=52 +'volatile'=53 +'invariant'=54 +'literal'=55 +'serializable'=56 +'annotation'=57 diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsListener.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsListener.java new file mode 100644 index 00000000..e1ae6e95 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsListener.java @@ -0,0 +1,203 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +// Generated from /home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/Imports.g4 by ANTLR 4.6 +package eu.modelwriter.core.alloyinecore.recognizer.imports; + +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedPackage; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedClass; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedInterface; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedDataType; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedEnum; +import eu.modelwriter.core.alloyinecore.structure.model.Import; + +import org.antlr.v4.runtime.tree.ParseTreeListener; + +/** + * This interface defines a complete listener for a parse tree produced by + * {@link ImportsParser}. + */ +public interface ImportsListener extends ParseTreeListener { + /** + * Enter a parse tree produced by {@link ImportsParser#importModel}. + * @param ctx the parse tree + */ + void enterImportModel(ImportsParser.ImportModelContext ctx); + /** + * Exit a parse tree produced by {@link ImportsParser#importModel}. + * @param ctx the parse tree + */ + void exitImportModel(ImportsParser.ImportModelContext ctx); + /** + * Enter a parse tree produced by {@link ImportsParser#iPackage}. + * @param ctx the parse tree + */ + void enterIPackage(ImportsParser.IPackageContext ctx); + /** + * Exit a parse tree produced by {@link ImportsParser#iPackage}. + * @param ctx the parse tree + */ + void exitIPackage(ImportsParser.IPackageContext ctx); + /** + * Enter a parse tree produced by {@link ImportsParser#iClassifier}. + * @param ctx the parse tree + */ + void enterIClassifier(ImportsParser.IClassifierContext ctx); + /** + * Exit a parse tree produced by {@link ImportsParser#iClassifier}. + * @param ctx the parse tree + */ + void exitIClassifier(ImportsParser.IClassifierContext ctx); + /** + * Enter a parse tree produced by {@link ImportsParser#iClass}. + * @param ctx the parse tree + */ + void enterIClass(ImportsParser.IClassContext ctx); + /** + * Exit a parse tree produced by {@link ImportsParser#iClass}. + * @param ctx the parse tree + */ + void exitIClass(ImportsParser.IClassContext ctx); + /** + * Enter a parse tree produced by {@link ImportsParser#iDataType}. + * @param ctx the parse tree + */ + void enterIDataType(ImportsParser.IDataTypeContext ctx); + /** + * Exit a parse tree produced by {@link ImportsParser#iDataType}. + * @param ctx the parse tree + */ + void exitIDataType(ImportsParser.IDataTypeContext ctx); + /** + * Enter a parse tree produced by {@link ImportsParser#visibility}. + * @param ctx the parse tree + */ + void enterVisibility(ImportsParser.VisibilityContext ctx); + /** + * Exit a parse tree produced by {@link ImportsParser#visibility}. + * @param ctx the parse tree + */ + void exitVisibility(ImportsParser.VisibilityContext ctx); + /** + * Enter a parse tree produced by {@link ImportsParser#block}. + * @param ctx the parse tree + */ + void enterBlock(ImportsParser.BlockContext ctx); + /** + * Exit a parse tree produced by {@link ImportsParser#block}. + * @param ctx the parse tree + */ + void exitBlock(ImportsParser.BlockContext ctx); + /** + * Enter a parse tree produced by {@link ImportsParser#templateSignature}. + * @param ctx the parse tree + */ + void enterTemplateSignature(ImportsParser.TemplateSignatureContext ctx); + /** + * Exit a parse tree produced by {@link ImportsParser#templateSignature}. + * @param ctx the parse tree + */ + void exitTemplateSignature(ImportsParser.TemplateSignatureContext ctx); + /** + * Enter a parse tree produced by {@link ImportsParser#iTypeParameter}. + * @param ctx the parse tree + */ + void enterITypeParameter(ImportsParser.ITypeParameterContext ctx); + /** + * Exit a parse tree produced by {@link ImportsParser#iTypeParameter}. + * @param ctx the parse tree + */ + void exitITypeParameter(ImportsParser.ITypeParameterContext ctx); + /** + * Enter a parse tree produced by {@link ImportsParser#iGenericType}. + * @param ctx the parse tree + */ + void enterIGenericType(ImportsParser.IGenericTypeContext ctx); + /** + * Exit a parse tree produced by {@link ImportsParser#iGenericType}. + * @param ctx the parse tree + */ + void exitIGenericType(ImportsParser.IGenericTypeContext ctx); + /** + * Enter a parse tree produced by {@link ImportsParser#iGenericTypeArgument}. + * @param ctx the parse tree + */ + void enterIGenericTypeArgument(ImportsParser.IGenericTypeArgumentContext ctx); + /** + * Exit a parse tree produced by {@link ImportsParser#iGenericTypeArgument}. + * @param ctx the parse tree + */ + void exitIGenericTypeArgument(ImportsParser.IGenericTypeArgumentContext ctx); + /** + * Enter a parse tree produced by {@link ImportsParser#iGenericWildcard}. + * @param ctx the parse tree + */ + void enterIGenericWildcard(ImportsParser.IGenericWildcardContext ctx); + /** + * Exit a parse tree produced by {@link ImportsParser#iGenericWildcard}. + * @param ctx the parse tree + */ + void exitIGenericWildcard(ImportsParser.IGenericWildcardContext ctx); + /** + * Enter a parse tree produced by {@link ImportsParser#pathName}. + * @param ctx the parse tree + */ + void enterPathName(ImportsParser.PathNameContext ctx); + /** + * Exit a parse tree produced by {@link ImportsParser#pathName}. + * @param ctx the parse tree + */ + void exitPathName(ImportsParser.PathNameContext ctx); + /** + * Enter a parse tree produced by {@link ImportsParser#segment}. + * @param ctx the parse tree + */ + void enterSegment(ImportsParser.SegmentContext ctx); + /** + * Exit a parse tree produced by {@link ImportsParser#segment}. + * @param ctx the parse tree + */ + void exitSegment(ImportsParser.SegmentContext ctx); + /** + * Enter a parse tree produced by {@link ImportsParser#unrestrictedName}. + * @param ctx the parse tree + */ + void enterUnrestrictedName(ImportsParser.UnrestrictedNameContext ctx); + /** + * Exit a parse tree produced by {@link ImportsParser#unrestrictedName}. + * @param ctx the parse tree + */ + void exitUnrestrictedName(ImportsParser.UnrestrictedNameContext ctx); + /** + * Enter a parse tree produced by {@link ImportsParser#identifier}. + * @param ctx the parse tree + */ + void enterIdentifier(ImportsParser.IdentifierContext ctx); + /** + * Exit a parse tree produced by {@link ImportsParser#identifier}. + * @param ctx the parse tree + */ + void exitIdentifier(ImportsParser.IdentifierContext ctx); +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsParser.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsParser.java new file mode 100644 index 00000000..29a2a095 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsParser.java @@ -0,0 +1,1894 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +// Generated from /home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/Imports.g4 by ANTLR 4.6 +package eu.modelwriter.core.alloyinecore.recognizer.imports; + +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedPackage; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedClass; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedInterface; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedDataType; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedEnum; +import eu.modelwriter.core.alloyinecore.structure.model.Import; + +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.misc.*; +import org.antlr.v4.runtime.tree.*; +import java.util.List; +import java.util.Iterator; +import java.util.ArrayList; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class ImportsParser extends Parser { + static { RuntimeMetaData.checkVersion("4.6", RuntimeMetaData.VERSION); } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, + T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, + T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, + T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, T__29=30, T__30=31, + T__31=32, T__32=33, T__33=34, T__34=35, T__35=36, T__36=37, T__37=38, + T__38=39, T__39=40, T__40=41, T__41=42, T__42=43, T__43=44, T__44=45, + T__45=46, T__46=47, T__47=48, T__48=49, T__49=50, T__50=51, T__51=52, + T__52=53, T__53=54, T__54=55, T__55=56, T__56=57, INT=58, IDENTIFIER=59, + SINGLE_CHARACTER=60, DOUBLE_QUOTED_STRING=61, SINGLE_QUOTED_STRING=62, + ML_SINGLE_QUOTED_STRING=63, MULTILINE_COMMENT=64, SINGLELINE_COMMENT=65, + WS=66, ANY=67; + public static final int + RULE_importModel = 0, RULE_iPackage = 1, RULE_iClassifier = 2, RULE_iClass = 3, + RULE_iDataType = 4, RULE_visibility = 5, RULE_block = 6, RULE_templateSignature = 7, + RULE_iTypeParameter = 8, RULE_iGenericType = 9, RULE_iGenericTypeArgument = 10, + RULE_iGenericWildcard = 11, RULE_pathName = 12, RULE_segment = 13, RULE_unrestrictedName = 14, + RULE_identifier = 15; + public static final String[] ruleNames = { + "importModel", "iPackage", "iClassifier", "iClass", "iDataType", "visibility", + "block", "templateSignature", "iTypeParameter", "iGenericType", "iGenericTypeArgument", + "iGenericWildcard", "pathName", "segment", "unrestrictedName", "identifier" + }; + + private static final String[] _LITERAL_NAMES = { + null, "'package'", "':'", "'='", "'{'", "'}'", "';'", "'abstract'", "'class'", + "'interface'", "'extends'", "','", "'datatype'", "'enum'", "'public'", + "'protected'", "'private'", "'<'", "'>'", "'&'", "'?'", "'super'", "'.'", + "'::'", "'@'", "'attribute'", "'body'", "'callable'", "'composes'", "'definition'", + "'derivation'", "'derived'", "'ensure'", "'id'", "'import'", "'initial'", + "'key'", "'model'", "'operation'", "'ordered'", "'postcondition'", "'precondition'", + "'primitive'", "'property'", "'readonly'", "'reference'", "'require'", + "'resolve'", "'static'", "'throws'", "'transient'", "'unique'", "'unsettable'", + "'volatile'", "'invariant'", "'literal'", "'serializable'", "'annotation'" + }; + private static final String[] _SYMBOLIC_NAMES = { + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, "INT", "IDENTIFIER", + "SINGLE_CHARACTER", "DOUBLE_QUOTED_STRING", "SINGLE_QUOTED_STRING", "ML_SINGLE_QUOTED_STRING", + "MULTILINE_COMMENT", "SINGLELINE_COMMENT", "WS", "ANY" + }; + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + @Override + public String getGrammarFileName() { return "Imports.g4"; } + + @Override + public String[] getRuleNames() { return ruleNames; } + + @Override + public String getSerializedATN() { return _serializedATN; } + + @Override + public ATN getATN() { return _ATN; } + + + private Element owningElement; + + public ImportsParser(TokenStream input) { + super(input); + _interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); + } + public static class ImportModelContext extends ParserRuleContext { + public Element owner; + public List iPackage() { + return getRuleContexts(IPackageContext.class); + } + public IPackageContext iPackage(int i) { + return getRuleContext(IPackageContext.class,i); + } + public ImportModelContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public ImportModelContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_importModel; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).enterImportModel(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).exitImportModel(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof ImportsVisitor ) return ((ImportsVisitor)visitor).visitImportModel(this); + else return visitor.visitChildren(this); + } + } + + public final ImportModelContext importModel(Element owner) throws RecognitionException { + ImportModelContext _localctx = new ImportModelContext(_ctx, getState(), owner); + enterRule(_localctx, 0, RULE_importModel); + owningElement=owner; + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(35); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,0,_ctx); + while ( _alt!=1 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1+1 ) { + { + { + setState(32); + matchWildcard(); + } + } + } + setState(37); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,0,_ctx); + } + setState(41); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__13) | (1L << T__14) | (1L << T__15))) != 0)) { + { + { + setState(38); + iPackage(owningElement); + } + } + setState(43); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class IPackageContext extends ParserRuleContext { + public Element owner; + public ImportedPackage current; + public UnrestrictedNameContext name; + public Token nsURI; + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class,0); + } + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public TerminalNode SINGLE_QUOTED_STRING() { return getToken(ImportsParser.SINGLE_QUOTED_STRING, 0); } + public VisibilityContext visibility() { + return getRuleContext(VisibilityContext.class,0); + } + public List iClassifier() { + return getRuleContexts(IClassifierContext.class); + } + public IClassifierContext iClassifier(int i) { + return getRuleContext(IClassifierContext.class,i); + } + public List iPackage() { + return getRuleContexts(IPackageContext.class); + } + public IPackageContext iPackage(int i) { + return getRuleContext(IPackageContext.class,i); + } + public IPackageContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public IPackageContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_iPackage; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).enterIPackage(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).exitIPackage(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof ImportsVisitor ) return ((ImportsVisitor)visitor).visitIPackage(this); + else return visitor.visitChildren(this); + } + } + + public final IPackageContext iPackage(Element owner) throws RecognitionException { + IPackageContext _localctx = new IPackageContext(_ctx, getState(), owner); + enterRule(_localctx, 2, RULE_iPackage); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(45); + _errHandler.sync(this); + _la = _input.LA(1); + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__13) | (1L << T__14) | (1L << T__15))) != 0)) { + { + setState(44); + visibility(); + } + } + + setState(47); + match(T__0); + setState(48); + ((IPackageContext)_localctx).name = unrestrictedName(); + ((IPackageContext)_localctx).current = new ImportedPackage(_localctx); + setState(50); + match(T__1); + setState(51); + identifier(); + setState(52); + match(T__2); + setState(53); + ((IPackageContext)_localctx).nsURI = match(SINGLE_QUOTED_STRING); + setState(65); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__3: + { + setState(54); + match(T__3); + setState(60); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,4,_ctx); + while ( _alt!=1 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1+1 ) { + { + setState(58); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,3,_ctx) ) { + case 1: + { + setState(55); + iClassifier(_localctx.current); + } + break; + case 2: + { + setState(56); + iPackage(_localctx.current); + } + break; + case 3: + { + setState(57); + matchWildcard(); + } + break; + } + } + } + setState(62); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,4,_ctx); + } + setState(63); + match(T__4); + } + break; + case T__5: + { + setState(64); + match(T__5); + } + break; + default: + throw new NoViableAltException(this); + } + } + _ctx.stop = _input.LT(-1); + if(owner != null) owner.addOwnedElement(_localctx.current); else owningElement= _localctx.current; + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class IClassifierContext extends ParserRuleContext { + public Element owner; + public IClassContext iClass() { + return getRuleContext(IClassContext.class,0); + } + public IDataTypeContext iDataType() { + return getRuleContext(IDataTypeContext.class,0); + } + public BlockContext block() { + return getRuleContext(BlockContext.class,0); + } + public IClassifierContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public IClassifierContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_iClassifier; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).enterIClassifier(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).exitIClassifier(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof ImportsVisitor ) return ((ImportsVisitor)visitor).visitIClassifier(this); + else return visitor.visitChildren(this); + } + } + + public final IClassifierContext iClassifier(Element owner) throws RecognitionException { + IClassifierContext _localctx = new IClassifierContext(_ctx, getState(), owner); + enterRule(_localctx, 4, RULE_iClassifier); + try { + enterOuterAlt(_localctx, 1); + { + setState(69); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,6,_ctx) ) { + case 1: + { + setState(67); + iClass(_localctx.owner); + } + break; + case 2: + { + setState(68); + iDataType(_localctx.owner); + } + break; + } + setState(73); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__3: + { + setState(71); + block(); + } + break; + case T__5: + { + setState(72); + match(T__5); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class IClassContext extends ParserRuleContext { + public Element owner; + public ImportedClass current; + public Token isAbstract; + public Token isClass; + public Token isInterface; + public UnrestrictedNameContext name; + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public VisibilityContext visibility() { + return getRuleContext(VisibilityContext.class,0); + } + public TemplateSignatureContext templateSignature() { + return getRuleContext(TemplateSignatureContext.class,0); + } + public List iGenericType() { + return getRuleContexts(IGenericTypeContext.class); + } + public IGenericTypeContext iGenericType(int i) { + return getRuleContext(IGenericTypeContext.class,i); + } + public IClassContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public IClassContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_iClass; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).enterIClass(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).exitIClass(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof ImportsVisitor ) return ((ImportsVisitor)visitor).visitIClass(this); + else return visitor.visitChildren(this); + } + } + + public final IClassContext iClass(Element owner) throws RecognitionException { + IClassContext _localctx = new IClassContext(_ctx, getState(), owner); + enterRule(_localctx, 6, RULE_iClass); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(76); + _errHandler.sync(this); + _la = _input.LA(1); + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__13) | (1L << T__14) | (1L << T__15))) != 0)) { + { + setState(75); + visibility(); + } + } + + setState(83); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__6: + case T__7: + { + setState(79); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__6) { + { + setState(78); + ((IClassContext)_localctx).isAbstract = match(T__6); + } + } + + setState(81); + ((IClassContext)_localctx).isClass = match(T__7); + } + break; + case T__8: + { + setState(82); + ((IClassContext)_localctx).isInterface = match(T__8); + } + break; + default: + throw new NoViableAltException(this); + } + setState(85); + ((IClassContext)_localctx).name = unrestrictedName(); + setState(87); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__16) { + { + setState(86); + templateSignature(); + } + } + + setState(98); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__9) { + { + setState(89); + match(T__9); + setState(90); + iGenericType(); + setState(95); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__10) { + { + { + setState(91); + match(T__10); + setState(92); + iGenericType(); + } + } + setState(97); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + + if (((IClassContext)_localctx).isInterface!=null) ((IClassContext)_localctx).current = new ImportedInterface(_localctx); else ((IClassContext)_localctx).current = new ImportedClass(_localctx); + } + _ctx.stop = _input.LT(-1); + owner.addOwnedElement(_localctx.current); + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class IDataTypeContext extends ParserRuleContext { + public Element owner; + public ImportedDataType current; + public Token isDataType; + public Token isEnum; + public UnrestrictedNameContext name; + public Token instanceClassName; + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public VisibilityContext visibility() { + return getRuleContext(VisibilityContext.class,0); + } + public TemplateSignatureContext templateSignature() { + return getRuleContext(TemplateSignatureContext.class,0); + } + public TerminalNode SINGLE_QUOTED_STRING() { return getToken(ImportsParser.SINGLE_QUOTED_STRING, 0); } + public IDataTypeContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } + public IDataTypeContext(ParserRuleContext parent, int invokingState, Element owner) { + super(parent, invokingState); + this.owner = owner; + } + @Override public int getRuleIndex() { return RULE_iDataType; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).enterIDataType(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).exitIDataType(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof ImportsVisitor ) return ((ImportsVisitor)visitor).visitIDataType(this); + else return visitor.visitChildren(this); + } + } + + public final IDataTypeContext iDataType(Element owner) throws RecognitionException { + IDataTypeContext _localctx = new IDataTypeContext(_ctx, getState(), owner); + enterRule(_localctx, 8, RULE_iDataType); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(103); + _errHandler.sync(this); + _la = _input.LA(1); + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__13) | (1L << T__14) | (1L << T__15))) != 0)) { + { + setState(102); + visibility(); + } + } + + setState(107); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__11: + { + setState(105); + ((IDataTypeContext)_localctx).isDataType = match(T__11); + } + break; + case T__12: + { + setState(106); + ((IDataTypeContext)_localctx).isEnum = match(T__12); + } + break; + default: + throw new NoViableAltException(this); + } + setState(109); + ((IDataTypeContext)_localctx).name = unrestrictedName(); + setState(111); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__16) { + { + setState(110); + templateSignature(); + } + } + + setState(115); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__1) { + { + setState(113); + match(T__1); + setState(114); + ((IDataTypeContext)_localctx).instanceClassName = match(SINGLE_QUOTED_STRING); + } + } + + if (((IDataTypeContext)_localctx).isDataType!=null) ((IDataTypeContext)_localctx).current = new ImportedDataType(_localctx); else ((IDataTypeContext)_localctx).current = new ImportedEnum(_localctx); + } + _ctx.stop = _input.LT(-1); + owner.addOwnedElement(_localctx.current); + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class VisibilityContext extends ParserRuleContext { + public VisibilityContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_visibility; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).enterVisibility(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).exitVisibility(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof ImportsVisitor ) return ((ImportsVisitor)visitor).visitVisibility(this); + else return visitor.visitChildren(this); + } + } + + public final VisibilityContext visibility() throws RecognitionException { + VisibilityContext _localctx = new VisibilityContext(_ctx, getState()); + enterRule(_localctx, 10, RULE_visibility); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(119); + _la = _input.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__13) | (1L << T__14) | (1L << T__15))) != 0)) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class BlockContext extends ParserRuleContext { + public List block() { + return getRuleContexts(BlockContext.class); + } + public BlockContext block(int i) { + return getRuleContext(BlockContext.class,i); + } + public BlockContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_block; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).enterBlock(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).exitBlock(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof ImportsVisitor ) return ((ImportsVisitor)visitor).visitBlock(this); + else return visitor.visitChildren(this); + } + } + + public final BlockContext block() throws RecognitionException { + BlockContext _localctx = new BlockContext(_ctx, getState()); + enterRule(_localctx, 12, RULE_block); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(121); + match(T__3); + setState(126); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,19,_ctx); + while ( _alt!=1 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1+1 ) { + { + setState(124); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,18,_ctx) ) { + case 1: + { + setState(122); + block(); + } + break; + case 2: + { + setState(123); + matchWildcard(); + } + break; + } + } + } + setState(128); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,19,_ctx); + } + setState(129); + match(T__4); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class TemplateSignatureContext extends ParserRuleContext { + public List iTypeParameter() { + return getRuleContexts(ITypeParameterContext.class); + } + public ITypeParameterContext iTypeParameter(int i) { + return getRuleContext(ITypeParameterContext.class,i); + } + public TemplateSignatureContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_templateSignature; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).enterTemplateSignature(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).exitTemplateSignature(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof ImportsVisitor ) return ((ImportsVisitor)visitor).visitTemplateSignature(this); + else return visitor.visitChildren(this); + } + } + + public final TemplateSignatureContext templateSignature() throws RecognitionException { + TemplateSignatureContext _localctx = new TemplateSignatureContext(_ctx, getState()); + enterRule(_localctx, 14, RULE_templateSignature); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(131); + match(T__16); + setState(132); + iTypeParameter(); + setState(137); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__10) { + { + { + setState(133); + match(T__10); + setState(134); + iTypeParameter(); + } + } + setState(139); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(140); + match(T__17); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ITypeParameterContext extends ParserRuleContext { + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public List iGenericType() { + return getRuleContexts(IGenericTypeContext.class); + } + public IGenericTypeContext iGenericType(int i) { + return getRuleContext(IGenericTypeContext.class,i); + } + public ITypeParameterContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_iTypeParameter; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).enterITypeParameter(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).exitITypeParameter(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof ImportsVisitor ) return ((ImportsVisitor)visitor).visitITypeParameter(this); + else return visitor.visitChildren(this); + } + } + + public final ITypeParameterContext iTypeParameter() throws RecognitionException { + ITypeParameterContext _localctx = new ITypeParameterContext(_ctx, getState()); + enterRule(_localctx, 16, RULE_iTypeParameter); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(142); + unrestrictedName(); + setState(152); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__9) { + { + setState(143); + match(T__9); + setState(144); + iGenericType(); + setState(149); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__18) { + { + { + setState(145); + match(T__18); + setState(146); + iGenericType(); + } + } + setState(151); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class IGenericTypeContext extends ParserRuleContext { + public PathNameContext pathName() { + return getRuleContext(PathNameContext.class,0); + } + public List iGenericTypeArgument() { + return getRuleContexts(IGenericTypeArgumentContext.class); + } + public IGenericTypeArgumentContext iGenericTypeArgument(int i) { + return getRuleContext(IGenericTypeArgumentContext.class,i); + } + public IGenericTypeContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_iGenericType; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).enterIGenericType(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).exitIGenericType(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof ImportsVisitor ) return ((ImportsVisitor)visitor).visitIGenericType(this); + else return visitor.visitChildren(this); + } + } + + public final IGenericTypeContext iGenericType() throws RecognitionException { + IGenericTypeContext _localctx = new IGenericTypeContext(_ctx, getState()); + enterRule(_localctx, 18, RULE_iGenericType); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(154); + pathName(); + setState(166); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__16) { + { + setState(155); + match(T__16); + setState(156); + iGenericTypeArgument(); + setState(161); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__10) { + { + { + setState(157); + match(T__10); + setState(158); + iGenericTypeArgument(); + } + } + setState(163); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(164); + match(T__17); + } + } + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class IGenericTypeArgumentContext extends ParserRuleContext { + public IGenericTypeContext iGenericType() { + return getRuleContext(IGenericTypeContext.class,0); + } + public IGenericWildcardContext iGenericWildcard() { + return getRuleContext(IGenericWildcardContext.class,0); + } + public IGenericTypeArgumentContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_iGenericTypeArgument; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).enterIGenericTypeArgument(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).exitIGenericTypeArgument(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof ImportsVisitor ) return ((ImportsVisitor)visitor).visitIGenericTypeArgument(this); + else return visitor.visitChildren(this); + } + } + + public final IGenericTypeArgumentContext iGenericTypeArgument() throws RecognitionException { + IGenericTypeArgumentContext _localctx = new IGenericTypeArgumentContext(_ctx, getState()); + enterRule(_localctx, 20, RULE_iGenericTypeArgument); + try { + setState(170); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__0: + case T__6: + case T__7: + case T__8: + case T__9: + case T__11: + case T__12: + case T__24: + case T__25: + case T__26: + case T__27: + case T__28: + case T__29: + case T__30: + case T__31: + case T__32: + case T__33: + case T__34: + case T__35: + case T__36: + case T__37: + case T__38: + case T__39: + case T__40: + case T__41: + case T__42: + case T__43: + case T__44: + case T__45: + case T__46: + case T__47: + case T__48: + case T__49: + case T__50: + case T__51: + case T__52: + case T__53: + case T__54: + case T__55: + case T__56: + case IDENTIFIER: + enterOuterAlt(_localctx, 1); + { + setState(168); + iGenericType(); + } + break; + case T__19: + enterOuterAlt(_localctx, 2); + { + setState(169); + iGenericWildcard(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class IGenericWildcardContext extends ParserRuleContext { + public Token bound; + public IGenericTypeContext iGenericType() { + return getRuleContext(IGenericTypeContext.class,0); + } + public IGenericWildcardContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_iGenericWildcard; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).enterIGenericWildcard(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).exitIGenericWildcard(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof ImportsVisitor ) return ((ImportsVisitor)visitor).visitIGenericWildcard(this); + else return visitor.visitChildren(this); + } + } + + public final IGenericWildcardContext iGenericWildcard() throws RecognitionException { + IGenericWildcardContext _localctx = new IGenericWildcardContext(_ctx, getState()); + enterRule(_localctx, 22, RULE_iGenericWildcard); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(172); + match(T__19); + setState(175); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__9 || _la==T__20) { + { + setState(173); + ((IGenericWildcardContext)_localctx).bound = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__9 || _la==T__20) ) { + ((IGenericWildcardContext)_localctx).bound = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(174); + iGenericType(); + } + } + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class PathNameContext extends ParserRuleContext { + public UnrestrictedNameContext firstSegment; + public Token index; + public SegmentContext segment; + public List midSegments = new ArrayList(); + public SegmentContext lastSegment; + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public TerminalNode INT() { return getToken(ImportsParser.INT, 0); } + public List segment() { + return getRuleContexts(SegmentContext.class); + } + public SegmentContext segment(int i) { + return getRuleContext(SegmentContext.class,i); + } + public PathNameContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_pathName; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).enterPathName(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).exitPathName(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof ImportsVisitor ) return ((ImportsVisitor)visitor).visitPathName(this); + else return visitor.visitChildren(this); + } + } + + public final PathNameContext pathName() throws RecognitionException { + PathNameContext _localctx = new PathNameContext(_ctx, getState()); + enterRule(_localctx, 24, RULE_pathName); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(177); + ((PathNameContext)_localctx).firstSegment = unrestrictedName(); + setState(180); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__21) { + { + setState(178); + match(T__21); + setState(179); + ((PathNameContext)_localctx).index = match(INT); + } + } + + setState(189); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__22) { + { + setState(185); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,28,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(182); + ((PathNameContext)_localctx).segment = segment(); + ((PathNameContext)_localctx).midSegments.add(((PathNameContext)_localctx).segment); + } + } + } + setState(187); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,28,_ctx); + } + setState(188); + ((PathNameContext)_localctx).lastSegment = segment(); + } + } + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class SegmentContext extends ParserRuleContext { + public UnrestrictedNameContext name; + public Token index; + public UnrestrictedNameContext unrestrictedName() { + return getRuleContext(UnrestrictedNameContext.class,0); + } + public TerminalNode INT() { return getToken(ImportsParser.INT, 0); } + public SegmentContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_segment; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).enterSegment(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).exitSegment(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof ImportsVisitor ) return ((ImportsVisitor)visitor).visitSegment(this); + else return visitor.visitChildren(this); + } + } + + public final SegmentContext segment() throws RecognitionException { + SegmentContext _localctx = new SegmentContext(_ctx, getState()); + enterRule(_localctx, 26, RULE_segment); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(191); + match(T__22); + setState(193); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__23) { + { + setState(192); + match(T__23); + } + } + + setState(195); + ((SegmentContext)_localctx).name = unrestrictedName(); + setState(198); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__21) { + { + setState(196); + match(T__21); + setState(197); + ((SegmentContext)_localctx).index = match(INT); + } + } + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class UnrestrictedNameContext extends ParserRuleContext { + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class,0); + } + public UnrestrictedNameContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_unrestrictedName; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).enterUnrestrictedName(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).exitUnrestrictedName(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof ImportsVisitor ) return ((ImportsVisitor)visitor).visitUnrestrictedName(this); + else return visitor.visitChildren(this); + } + } + + public final UnrestrictedNameContext unrestrictedName() throws RecognitionException { + UnrestrictedNameContext _localctx = new UnrestrictedNameContext(_ctx, getState()); + enterRule(_localctx, 28, RULE_unrestrictedName); + try { + setState(242); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,32,_ctx) ) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(200); + identifier(); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(201); + match(T__6); + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(202); + match(T__24); + } + break; + case 4: + enterOuterAlt(_localctx, 4); + { + setState(203); + match(T__25); + } + break; + case 5: + enterOuterAlt(_localctx, 5); + { + setState(204); + match(T__26); + } + break; + case 6: + enterOuterAlt(_localctx, 6); + { + setState(205); + match(T__7); + } + break; + case 7: + enterOuterAlt(_localctx, 7); + { + setState(206); + match(T__27); + } + break; + case 8: + enterOuterAlt(_localctx, 8); + { + setState(207); + match(T__11); + } + break; + case 9: + enterOuterAlt(_localctx, 9); + { + setState(208); + match(T__28); + } + break; + case 10: + enterOuterAlt(_localctx, 10); + { + setState(209); + match(T__29); + } + break; + case 11: + enterOuterAlt(_localctx, 11); + { + setState(210); + match(T__30); + } + break; + case 12: + enterOuterAlt(_localctx, 12); + { + setState(211); + match(T__12); + } + break; + case 13: + enterOuterAlt(_localctx, 13); + { + setState(212); + match(T__31); + } + break; + case 14: + enterOuterAlt(_localctx, 14); + { + setState(213); + match(T__9); + } + break; + case 15: + enterOuterAlt(_localctx, 15); + { + setState(214); + match(T__32); + } + break; + case 16: + enterOuterAlt(_localctx, 16); + { + setState(215); + match(T__33); + } + break; + case 17: + enterOuterAlt(_localctx, 17); + { + setState(216); + match(T__34); + } + break; + case 18: + enterOuterAlt(_localctx, 18); + { + setState(217); + match(T__8); + } + break; + case 19: + enterOuterAlt(_localctx, 19); + { + setState(218); + match(T__35); + } + break; + case 20: + enterOuterAlt(_localctx, 20); + { + setState(219); + match(T__36); + } + break; + case 21: + enterOuterAlt(_localctx, 21); + { + setState(220); + match(T__37); + } + break; + case 22: + enterOuterAlt(_localctx, 22); + { + setState(221); + match(T__38); + } + break; + case 23: + enterOuterAlt(_localctx, 23); + { + setState(222); + match(T__0); + } + break; + case 24: + enterOuterAlt(_localctx, 24); + { + setState(223); + match(T__39); + } + break; + case 25: + enterOuterAlt(_localctx, 25); + { + setState(224); + match(T__40); + } + break; + case 26: + enterOuterAlt(_localctx, 26); + { + setState(225); + match(T__41); + } + break; + case 27: + enterOuterAlt(_localctx, 27); + { + setState(226); + match(T__42); + } + break; + case 28: + enterOuterAlt(_localctx, 28); + { + setState(227); + match(T__43); + } + break; + case 29: + enterOuterAlt(_localctx, 29); + { + setState(228); + match(T__44); + } + break; + case 30: + enterOuterAlt(_localctx, 30); + { + setState(229); + match(T__45); + } + break; + case 31: + enterOuterAlt(_localctx, 31); + { + setState(230); + match(T__46); + } + break; + case 32: + enterOuterAlt(_localctx, 32); + { + setState(231); + match(T__47); + } + break; + case 33: + enterOuterAlt(_localctx, 33); + { + setState(232); + match(T__48); + } + break; + case 34: + enterOuterAlt(_localctx, 34); + { + setState(233); + match(T__49); + } + break; + case 35: + enterOuterAlt(_localctx, 35); + { + setState(234); + match(T__50); + } + break; + case 36: + enterOuterAlt(_localctx, 36); + { + setState(235); + match(T__51); + } + break; + case 37: + enterOuterAlt(_localctx, 37); + { + setState(236); + match(T__52); + } + break; + case 38: + enterOuterAlt(_localctx, 38); + { + setState(237); + match(T__53); + } + break; + case 39: + enterOuterAlt(_localctx, 39); + { + setState(238); + match(T__54); + } + break; + case 40: + enterOuterAlt(_localctx, 40); + { + setState(239); + match(T__55); + } + break; + case 41: + enterOuterAlt(_localctx, 41); + { + setState(240); + match(T__56); + } + break; + case 42: + enterOuterAlt(_localctx, 42); + { + setState(241); + match(T__36); + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class IdentifierContext extends ParserRuleContext { + public TerminalNode IDENTIFIER() { return getToken(ImportsParser.IDENTIFIER, 0); } + public IdentifierContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_identifier; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).enterIdentifier(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof ImportsListener ) ((ImportsListener)listener).exitIdentifier(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof ImportsVisitor ) return ((ImportsVisitor)visitor).visitIdentifier(this); + else return visitor.visitChildren(this); + } + } + + public final IdentifierContext identifier() throws RecognitionException { + IdentifierContext _localctx = new IdentifierContext(_ctx, getState()); + enterRule(_localctx, 30, RULE_identifier); + try { + enterOuterAlt(_localctx, 1); + { + setState(244); + match(IDENTIFIER); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static final String _serializedATN = + "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3E\u00f9\4\2\t\2\4"+ + "\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"+ + "\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\3\2\7\2$\n"+ + "\2\f\2\16\2\'\13\2\3\2\7\2*\n\2\f\2\16\2-\13\2\3\3\5\3\60\n\3\3\3\3\3"+ + "\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\7\3=\n\3\f\3\16\3@\13\3\3\3\3\3\5"+ + "\3D\n\3\3\4\3\4\5\4H\n\4\3\4\3\4\5\4L\n\4\3\5\5\5O\n\5\3\5\5\5R\n\5\3"+ + "\5\3\5\5\5V\n\5\3\5\3\5\5\5Z\n\5\3\5\3\5\3\5\3\5\7\5`\n\5\f\5\16\5c\13"+ + "\5\5\5e\n\5\3\5\3\5\3\6\5\6j\n\6\3\6\3\6\5\6n\n\6\3\6\3\6\5\6r\n\6\3\6"+ + "\3\6\5\6v\n\6\3\6\3\6\3\7\3\7\3\b\3\b\3\b\7\b\177\n\b\f\b\16\b\u0082\13"+ + "\b\3\b\3\b\3\t\3\t\3\t\3\t\7\t\u008a\n\t\f\t\16\t\u008d\13\t\3\t\3\t\3"+ + "\n\3\n\3\n\3\n\3\n\7\n\u0096\n\n\f\n\16\n\u0099\13\n\5\n\u009b\n\n\3\13"+ + "\3\13\3\13\3\13\3\13\7\13\u00a2\n\13\f\13\16\13\u00a5\13\13\3\13\3\13"+ + "\5\13\u00a9\n\13\3\f\3\f\5\f\u00ad\n\f\3\r\3\r\3\r\5\r\u00b2\n\r\3\16"+ + "\3\16\3\16\5\16\u00b7\n\16\3\16\7\16\u00ba\n\16\f\16\16\16\u00bd\13\16"+ + "\3\16\5\16\u00c0\n\16\3\17\3\17\5\17\u00c4\n\17\3\17\3\17\3\17\5\17\u00c9"+ + "\n\17\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20"+ + "\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20"+ + "\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20"+ + "\3\20\5\20\u00f5\n\20\3\21\3\21\3\21\5%>\u0080\2\22\2\4\6\b\n\f\16\20"+ + "\22\24\26\30\32\34\36 \2\4\3\2\20\22\4\2\f\f\27\27\u0132\2%\3\2\2\2\4"+ + "/\3\2\2\2\6G\3\2\2\2\bN\3\2\2\2\ni\3\2\2\2\fy\3\2\2\2\16{\3\2\2\2\20\u0085"+ + "\3\2\2\2\22\u0090\3\2\2\2\24\u009c\3\2\2\2\26\u00ac\3\2\2\2\30\u00ae\3"+ + "\2\2\2\32\u00b3\3\2\2\2\34\u00c1\3\2\2\2\36\u00f4\3\2\2\2 \u00f6\3\2\2"+ + "\2\"$\13\2\2\2#\"\3\2\2\2$\'\3\2\2\2%&\3\2\2\2%#\3\2\2\2&+\3\2\2\2\'%"+ + "\3\2\2\2(*\5\4\3\2)(\3\2\2\2*-\3\2\2\2+)\3\2\2\2+,\3\2\2\2,\3\3\2\2\2"+ + "-+\3\2\2\2.\60\5\f\7\2/.\3\2\2\2/\60\3\2\2\2\60\61\3\2\2\2\61\62\7\3\2"+ + "\2\62\63\5\36\20\2\63\64\b\3\1\2\64\65\7\4\2\2\65\66\5 \21\2\66\67\7\5"+ + "\2\2\67C\7@\2\28>\7\6\2\29=\5\6\4\2:=\5\4\3\2;=\13\2\2\2<9\3\2\2\2<:\3"+ + "\2\2\2<;\3\2\2\2=@\3\2\2\2>?\3\2\2\2><\3\2\2\2?A\3\2\2\2@>\3\2\2\2AD\7"+ + "\7\2\2BD\7\b\2\2C8\3\2\2\2CB\3\2\2\2D\5\3\2\2\2EH\5\b\5\2FH\5\n\6\2GE"+ + "\3\2\2\2GF\3\2\2\2HK\3\2\2\2IL\5\16\b\2JL\7\b\2\2KI\3\2\2\2KJ\3\2\2\2"+ + "L\7\3\2\2\2MO\5\f\7\2NM\3\2\2\2NO\3\2\2\2OU\3\2\2\2PR\7\t\2\2QP\3\2\2"+ + "\2QR\3\2\2\2RS\3\2\2\2SV\7\n\2\2TV\7\13\2\2UQ\3\2\2\2UT\3\2\2\2VW\3\2"+ + "\2\2WY\5\36\20\2XZ\5\20\t\2YX\3\2\2\2YZ\3\2\2\2Zd\3\2\2\2[\\\7\f\2\2\\"+ + "a\5\24\13\2]^\7\r\2\2^`\5\24\13\2_]\3\2\2\2`c\3\2\2\2a_\3\2\2\2ab\3\2"+ + "\2\2be\3\2\2\2ca\3\2\2\2d[\3\2\2\2de\3\2\2\2ef\3\2\2\2fg\b\5\1\2g\t\3"+ + "\2\2\2hj\5\f\7\2ih\3\2\2\2ij\3\2\2\2jm\3\2\2\2kn\7\16\2\2ln\7\17\2\2m"+ + "k\3\2\2\2ml\3\2\2\2no\3\2\2\2oq\5\36\20\2pr\5\20\t\2qp\3\2\2\2qr\3\2\2"+ + "\2ru\3\2\2\2st\7\4\2\2tv\7@\2\2us\3\2\2\2uv\3\2\2\2vw\3\2\2\2wx\b\6\1"+ + "\2x\13\3\2\2\2yz\t\2\2\2z\r\3\2\2\2{\u0080\7\6\2\2|\177\5\16\b\2}\177"+ + "\13\2\2\2~|\3\2\2\2~}\3\2\2\2\177\u0082\3\2\2\2\u0080\u0081\3\2\2\2\u0080"+ + "~\3\2\2\2\u0081\u0083\3\2\2\2\u0082\u0080\3\2\2\2\u0083\u0084\7\7\2\2"+ + "\u0084\17\3\2\2\2\u0085\u0086\7\23\2\2\u0086\u008b\5\22\n\2\u0087\u0088"+ + "\7\r\2\2\u0088\u008a\5\22\n\2\u0089\u0087\3\2\2\2\u008a\u008d\3\2\2\2"+ + "\u008b\u0089\3\2\2\2\u008b\u008c\3\2\2\2\u008c\u008e\3\2\2\2\u008d\u008b"+ + "\3\2\2\2\u008e\u008f\7\24\2\2\u008f\21\3\2\2\2\u0090\u009a\5\36\20\2\u0091"+ + "\u0092\7\f\2\2\u0092\u0097\5\24\13\2\u0093\u0094\7\25\2\2\u0094\u0096"+ + "\5\24\13\2\u0095\u0093\3\2\2\2\u0096\u0099\3\2\2\2\u0097\u0095\3\2\2\2"+ + "\u0097\u0098\3\2\2\2\u0098\u009b\3\2\2\2\u0099\u0097\3\2\2\2\u009a\u0091"+ + "\3\2\2\2\u009a\u009b\3\2\2\2\u009b\23\3\2\2\2\u009c\u00a8\5\32\16\2\u009d"+ + "\u009e\7\23\2\2\u009e\u00a3\5\26\f\2\u009f\u00a0\7\r\2\2\u00a0\u00a2\5"+ + "\26\f\2\u00a1\u009f\3\2\2\2\u00a2\u00a5\3\2\2\2\u00a3\u00a1\3\2\2\2\u00a3"+ + "\u00a4\3\2\2\2\u00a4\u00a6\3\2\2\2\u00a5\u00a3\3\2\2\2\u00a6\u00a7\7\24"+ + "\2\2\u00a7\u00a9\3\2\2\2\u00a8\u009d\3\2\2\2\u00a8\u00a9\3\2\2\2\u00a9"+ + "\25\3\2\2\2\u00aa\u00ad\5\24\13\2\u00ab\u00ad\5\30\r\2\u00ac\u00aa\3\2"+ + "\2\2\u00ac\u00ab\3\2\2\2\u00ad\27\3\2\2\2\u00ae\u00b1\7\26\2\2\u00af\u00b0"+ + "\t\3\2\2\u00b0\u00b2\5\24\13\2\u00b1\u00af\3\2\2\2\u00b1\u00b2\3\2\2\2"+ + "\u00b2\31\3\2\2\2\u00b3\u00b6\5\36\20\2\u00b4\u00b5\7\30\2\2\u00b5\u00b7"+ + "\7<\2\2\u00b6\u00b4\3\2\2\2\u00b6\u00b7\3\2\2\2\u00b7\u00bf\3\2\2\2\u00b8"+ + "\u00ba\5\34\17\2\u00b9\u00b8\3\2\2\2\u00ba\u00bd\3\2\2\2\u00bb\u00b9\3"+ + "\2\2\2\u00bb\u00bc\3\2\2\2\u00bc\u00be\3\2\2\2\u00bd\u00bb\3\2\2\2\u00be"+ + "\u00c0\5\34\17\2\u00bf\u00bb\3\2\2\2\u00bf\u00c0\3\2\2\2\u00c0\33\3\2"+ + "\2\2\u00c1\u00c3\7\31\2\2\u00c2\u00c4\7\32\2\2\u00c3\u00c2\3\2\2\2\u00c3"+ + "\u00c4\3\2\2\2\u00c4\u00c5\3\2\2\2\u00c5\u00c8\5\36\20\2\u00c6\u00c7\7"+ + "\30\2\2\u00c7\u00c9\7<\2\2\u00c8\u00c6\3\2\2\2\u00c8\u00c9\3\2\2\2\u00c9"+ + "\35\3\2\2\2\u00ca\u00f5\5 \21\2\u00cb\u00f5\7\t\2\2\u00cc\u00f5\7\33\2"+ + "\2\u00cd\u00f5\7\34\2\2\u00ce\u00f5\7\35\2\2\u00cf\u00f5\7\n\2\2\u00d0"+ + "\u00f5\7\36\2\2\u00d1\u00f5\7\16\2\2\u00d2\u00f5\7\37\2\2\u00d3\u00f5"+ + "\7 \2\2\u00d4\u00f5\7!\2\2\u00d5\u00f5\7\17\2\2\u00d6\u00f5\7\"\2\2\u00d7"+ + "\u00f5\7\f\2\2\u00d8\u00f5\7#\2\2\u00d9\u00f5\7$\2\2\u00da\u00f5\7%\2"+ + "\2\u00db\u00f5\7\13\2\2\u00dc\u00f5\7&\2\2\u00dd\u00f5\7\'\2\2\u00de\u00f5"+ + "\7(\2\2\u00df\u00f5\7)\2\2\u00e0\u00f5\7\3\2\2\u00e1\u00f5\7*\2\2\u00e2"+ + "\u00f5\7+\2\2\u00e3\u00f5\7,\2\2\u00e4\u00f5\7-\2\2\u00e5\u00f5\7.\2\2"+ + "\u00e6\u00f5\7/\2\2\u00e7\u00f5\7\60\2\2\u00e8\u00f5\7\61\2\2\u00e9\u00f5"+ + "\7\62\2\2\u00ea\u00f5\7\63\2\2\u00eb\u00f5\7\64\2\2\u00ec\u00f5\7\65\2"+ + "\2\u00ed\u00f5\7\66\2\2\u00ee\u00f5\7\67\2\2\u00ef\u00f5\78\2\2\u00f0"+ + "\u00f5\79\2\2\u00f1\u00f5\7:\2\2\u00f2\u00f5\7;\2\2\u00f3\u00f5\7\'\2"+ + "\2\u00f4\u00ca\3\2\2\2\u00f4\u00cb\3\2\2\2\u00f4\u00cc\3\2\2\2\u00f4\u00cd"+ + "\3\2\2\2\u00f4\u00ce\3\2\2\2\u00f4\u00cf\3\2\2\2\u00f4\u00d0\3\2\2\2\u00f4"+ + "\u00d1\3\2\2\2\u00f4\u00d2\3\2\2\2\u00f4\u00d3\3\2\2\2\u00f4\u00d4\3\2"+ + "\2\2\u00f4\u00d5\3\2\2\2\u00f4\u00d6\3\2\2\2\u00f4\u00d7\3\2\2\2\u00f4"+ + "\u00d8\3\2\2\2\u00f4\u00d9\3\2\2\2\u00f4\u00da\3\2\2\2\u00f4\u00db\3\2"+ + "\2\2\u00f4\u00dc\3\2\2\2\u00f4\u00dd\3\2\2\2\u00f4\u00de\3\2\2\2\u00f4"+ + "\u00df\3\2\2\2\u00f4\u00e0\3\2\2\2\u00f4\u00e1\3\2\2\2\u00f4\u00e2\3\2"+ + "\2\2\u00f4\u00e3\3\2\2\2\u00f4\u00e4\3\2\2\2\u00f4\u00e5\3\2\2\2\u00f4"+ + "\u00e6\3\2\2\2\u00f4\u00e7\3\2\2\2\u00f4\u00e8\3\2\2\2\u00f4\u00e9\3\2"+ + "\2\2\u00f4\u00ea\3\2\2\2\u00f4\u00eb\3\2\2\2\u00f4\u00ec\3\2\2\2\u00f4"+ + "\u00ed\3\2\2\2\u00f4\u00ee\3\2\2\2\u00f4\u00ef\3\2\2\2\u00f4\u00f0\3\2"+ + "\2\2\u00f4\u00f1\3\2\2\2\u00f4\u00f2\3\2\2\2\u00f4\u00f3\3\2\2\2\u00f5"+ + "\37\3\2\2\2\u00f6\u00f7\7=\2\2\u00f7!\3\2\2\2#%+/<>CGKNQUYadimqu~\u0080"+ + "\u008b\u0097\u009a\u00a3\u00a8\u00ac\u00b1\u00b6\u00bb\u00bf\u00c3\u00c8"+ + "\u00f4"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsVisitor.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsVisitor.java new file mode 100644 index 00000000..4dc88f96 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/ImportsVisitor.java @@ -0,0 +1,142 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +// Generated from /home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/imports/Imports.g4 by ANTLR 4.6 +package eu.modelwriter.core.alloyinecore.recognizer.imports; + +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedPackage; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedClass; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedInterface; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedDataType; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedEnum; +import eu.modelwriter.core.alloyinecore.structure.model.Import; + +import org.antlr.v4.runtime.tree.ParseTreeVisitor; + +/** + * This interface defines a complete generic visitor for a parse tree produced + * by {@link ImportsParser}. + * + * @param The return type of the visit operation. Use {@link Void} for + * operations with no return type. + */ +public interface ImportsVisitor extends ParseTreeVisitor { + /** + * Visit a parse tree produced by {@link ImportsParser#importModel}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitImportModel(ImportsParser.ImportModelContext ctx); + /** + * Visit a parse tree produced by {@link ImportsParser#iPackage}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIPackage(ImportsParser.IPackageContext ctx); + /** + * Visit a parse tree produced by {@link ImportsParser#iClassifier}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIClassifier(ImportsParser.IClassifierContext ctx); + /** + * Visit a parse tree produced by {@link ImportsParser#iClass}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIClass(ImportsParser.IClassContext ctx); + /** + * Visit a parse tree produced by {@link ImportsParser#iDataType}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIDataType(ImportsParser.IDataTypeContext ctx); + /** + * Visit a parse tree produced by {@link ImportsParser#visibility}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitVisibility(ImportsParser.VisibilityContext ctx); + /** + * Visit a parse tree produced by {@link ImportsParser#block}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitBlock(ImportsParser.BlockContext ctx); + /** + * Visit a parse tree produced by {@link ImportsParser#templateSignature}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitTemplateSignature(ImportsParser.TemplateSignatureContext ctx); + /** + * Visit a parse tree produced by {@link ImportsParser#iTypeParameter}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitITypeParameter(ImportsParser.ITypeParameterContext ctx); + /** + * Visit a parse tree produced by {@link ImportsParser#iGenericType}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIGenericType(ImportsParser.IGenericTypeContext ctx); + /** + * Visit a parse tree produced by {@link ImportsParser#iGenericTypeArgument}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIGenericTypeArgument(ImportsParser.IGenericTypeArgumentContext ctx); + /** + * Visit a parse tree produced by {@link ImportsParser#iGenericWildcard}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIGenericWildcard(ImportsParser.IGenericWildcardContext ctx); + /** + * Visit a parse tree produced by {@link ImportsParser#pathName}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitPathName(ImportsParser.PathNameContext ctx); + /** + * Visit a parse tree produced by {@link ImportsParser#segment}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSegment(ImportsParser.SegmentContext ctx); + /** + * Visit a parse tree produced by {@link ImportsParser#unrestrictedName}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitUnrestrictedName(ImportsParser.UnrestrictedNameContext ctx); + /** + * Visit a parse tree produced by {@link ImportsParser#identifier}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIdentifier(ImportsParser.IdentifierContext ctx); +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/Element.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/Element.java new file mode 100644 index 00000000..0113432a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/Element.java @@ -0,0 +1,274 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.base; + +import eu.modelwriter.core.alloyinecore.internal.Console; +import eu.modelwriter.core.alloyinecore.structure.model.*; +import eu.modelwriter.core.alloyinecore.structure.model.Class; +import eu.modelwriter.core.alloyinecore.visitor.IVisitable; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.misc.Interval; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +public abstract class Element implements IVisitable { + private final C context; + private Element owner; + private final List ownedElements = new ArrayList<>(); + + public Element(C context) { + this.context = context; + } + + public final C getContext() { + return this.context; + } + + public final List getOwnedElements() { + return ownedElements; + } + + public final List getAllOwnedElements() { + List result = new ArrayList<>(); + for (Element ownedElement : ownedElements) { + result.add(ownedElement); + result.addAll(ownedElement.getAllOwnedElements()); + } + return result; + } + + public final List getAllOwnedElements(java.lang.Class type, boolean skipAnnotationOwneds) { + List elements = new ArrayList<>(); + for (Element e : getOwnedElements()) { + if (type.isInstance(e)) elements.add(type.cast(e)); + if (e instanceof Annotation && skipAnnotationOwneds) + continue; + elements.addAll(e.getAllOwnedElements(type, skipAnnotationOwneds)); + } + return elements; + } + + public final boolean hasOwnedElements() { + return !ownedElements.isEmpty(); + } + + public final boolean deleteOwnedElement(K child) { + return this.ownedElements.remove(child); + } + + public void addOwnedElement(K child) { + if (child != null) { + ownedElements.add(child); + child.setOwner(this); + } + } + + public final void addOwnedElements(final K... child) { + for (K aChild : child) { + addOwnedElement(aChild); + } + } + + public final void addOwnedElements(final List children) { + for (K child : children) { + addOwnedElement(child); + } + } + + protected String getName() { + if (this.getOwner() != null) { + return "::" + this.getClass().getSimpleName() + "." + this.getContext().getText().hashCode(); + } else + return this.getClass().getSimpleName(); + } + + public final String getUniqueName() { + String name = this.getName(); + for (Element parent = this.getOwner(); parent != null; parent = parent.getOwner()) { + name = parent.getName() + name; + } + return name; + } + + private String getLocation() { + if (this.getOwner() != null) + return "/" + this.getClass().getSimpleName() + "@" + this.getOwner().getOwnedElements().indexOf(this); + else + return "/"; + } + + public final String getFullLocation() { + String location = this.getLocation(); + for (Element parent = this.getOwner(); parent != null; parent = parent.getOwner()) { + location = parent.getLocation() + location; + } + return location; + } + + public Token getToken() { + return this.context.start; + } + + public final List getOwnedElements(java.lang.Class type) { + List elements = new ArrayList<>(); + for (Element e : getOwnedElements()) + if (type.isInstance(e)) elements.add(type.cast(e)); + return elements; + } + + public final T getOwnedElement(java.lang.Class type) { + Optional optional = this.getOwnedElements().stream().filter(type::isInstance).findFirst(); + return optional.map(type::cast).orElse(null); + } + + public final void setOwner(final Element owner) { + this.owner = owner; + } + + public final Element getOwner() { + return owner; + } + + public final T getOwner(java.lang.Class type) { + for (Element owner = this.getOwner(); owner != null; owner = owner.getOwner()) { + if (type.isInstance(owner)) + return type.cast(owner); + } + return null; + } + + public String getSuffix() { + return ""; + } + + public String getLabel() { + return Element.getNormalizedText(getContext()); + } + + public void printTree() { + System.out.println(Console.BOLD + "[OUTLINE]" + Console.RESET); + traverse(this, 0); + } + +// private void traverse(Element element, int tabCount){ +// for (int i = 0; i < tabCount; i++) { +// System.out.print("\t"); +// } +// if (element instanceof IVisibility) +// System.out.print(((IVisibility) element).getVisibility() + " "); +// else System.out.print(" "); +// System.out.print("[" + (element instanceof Class && ((Class)element).isAbstract() ? "abstract " : "") + element.getClass().getSimpleName() + "] " +// + element.getLabel() + element.getSuffix() ); +//// System.out.print(" -- [" + element.getFullLocation() + "]"); +//// System.out.print( " -- (" + String.join(",", String.valueOf(element.getLine()), String.valueOf(element.getStart()), String.valueOf(element.getStop())) + ") "); +//// if (element instanceof Object) +//// System.out.print(" -- [" + ((Object)element).getURI() + "]"); +// // if (element instanceof Class) System.out.println("{" + element.getOwnedElements(Operation.class)+ "}"); +// System.out.println(); +// List elements = element.getOwnedElements(); +// for(Element e: elements) { +// traverse(e, tabCount + 1); +// } +// } + + private void traverse(Element element, int tabCount) { + for (int i = 0; i < tabCount; i++) { + System.out.print("\t"); + } + + if (element instanceof IVisibility) + System.out.print(((IVisibility) element).getVisibility() + " "); + else System.out.print(" "); + + System.out.print("[" + (element instanceof Class && ((eu.modelwriter.core.alloyinecore.structure.model.Class) element).isAbstract() ? Console.UNDERLINE : "") + element.getClass().getSimpleName() + Console.RESET + "] "); + + if (element instanceof PrimitiveType && ((Object) element).getEObject() != null) { + System.out.print(Console.BOLD + Console.RED + element.getLabel() + Console.RESET + " "); + } else if ((element instanceof GenericElementType || element instanceof GenericTypeArgument || + element instanceof GenericException || element instanceof GenericSuperType) && ((Object) element).getEObject() != null) { + System.out.print(Console.BOLD + Console.RED + element.getLabel() + Console.RESET + " "); + } else System.out.print(Console.RED + element.getLabel() + Console.RESET + " "); + + if (!element.getSuffix().equals("")) System.out.print(Console.PURPLE + element.getSuffix() + Console.RESET); +// System.out.print(" -- [" + Console.YELLOW + element.getFullLocation() + Console.RESET + "]"); + + if (element instanceof Object && ((Object) element).getEObject() != null) { + String name = ((Object) element).getEObject().getClass().getSimpleName(); + System.out.print(" -- [" + Console.CYAN + name.substring(0, name.lastIndexOf("Imp")) + Console.RESET + "]"); + } + if (element instanceof NamedElement || element instanceof Import) + System.out.print(" -- [" + Console.GREEN + element.getUniqueName() + Console.RESET + "]"); +// System.out.print( " -- (" + String.join(",", String.valueOf(element.getLine()), String.valueOf(element.getStart()), String.valueOf(element.getStop())) + ") "); + if (element instanceof Object && ((Object) element).getEObject() != null) { + System.out.print(" -- [" + Console.BLUE + ((Object) element).getURI().toString() + Console.RESET + "]"); + } +// if (element instanceof Class) System.out.println("{" + element.getOwnedElements(Operation.class)+ "}"); + if (element instanceof ITarget) + System.out.print(" (Path: " + Console.CYAN + ((ITarget) element).getRelativeSegment() + Console.RESET + ")"); + System.out.println(); + List elements = element.getOwnedElements(); + for (Element e : elements) { + traverse(e, tabCount + 1); + } + } + + public int getLine() { + return context.start.getLine(); + } + + public int getStart() { + return context.start.getStartIndex(); + } + + public int getStop() { + return context.start.getStopIndex(); + } + + /*https://www.mkyong.com/java/java-how-to-overrides-equals-and-hashcode/*/ + @Override + public int hashCode() { + return Objects.hash(this.getContext().getText()); + } + + @Override + public boolean equals(java.lang.Object obj) { + return obj == this || obj instanceof Element && this.getUniqueName().equals(((Element) obj).getUniqueName()); + } + + protected static String getNormalizedText(ParserRuleContext ctx) { + return ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex())) + .replaceAll("\\s+", " ").replaceAll("(\\w)(\\s)(<)", "$1$3"); + } + + protected static String getNormalizedText(final ParserRuleContext ctx, final int start, final int stop) { + return ctx.start.getInputStream().getText(new Interval(start, stop)) + .replaceAll("\\s+", " ").replaceAll("(\\w)(\\s)(<)", "$1$3"); + } +} + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/INamespace.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/INamespace.java new file mode 100644 index 00000000..7bd6caef --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/INamespace.java @@ -0,0 +1,134 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.base; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; + +import java.util.List; + +public interface INamespace extends ISegment { + + String getKey(); + + String getPath(); + + EObject getEObject(); + + void loadNamespace(Repository repository); + + default Resource getResource(){ + return getEObject().eResource(); + } + + default EObject getRootObject() { + return getEObject().eContents().get(0); + } + + default EObject getElement(final List relativePathFragments) { + EObject result; + try { + final String rootFragment = getResource().getURIFragment(getRootObject()); + relativePathFragments.add(0, rootFragment); + result = getResource().getEObject(String.join("/", relativePathFragments)); + if (result == null) { + throw new Exception(); + } + } catch (final Exception e) { + relativePathFragments.remove(0); + result = getResource().getEObject(String.join("/", relativePathFragments)); + } + return result; + } + +// static void loadNamespace(final T namespace){ +// //http://docs.oracle.com/javase/7/docs/technotes/guides/lang/resources.html +// if (namespace.getPath() != null) { +// +// Resource resource = namespace.getResource(); +// +// final String loc = new File(".").getAbsolutePath() +// + namespace.getPath(); +// +// System.out.println(new File(".").getAbsolutePath()); +// System.out.println(loc); +// +// ClassLoader classLoader = INamespace.class.getClassLoader(); +// InputStream inputStream = classLoader.getResourceAsStream(namespace.getPath()); +// System.out.println(inputStream); +// +// if (resource.getURI().isFile()) { +// System.out.println("Resource is file"); +// } else if (resource.getURI().isPlatform()) { +// System.out.println("Resource is platform"); +// } else if (resource.getURI().isPlatformPlugin()) { +// System.out.println("Resource is platform plugin"); +// } else if (resource.getURI().isPlatformResource()) { +// System.out.println("Resource is platform resource"); +// } else { +// System.out.println("Resource is ?"); +// } +// ANTLRInputStream input = null; +// try { +// input = new ANTLRInputStream(inputStream); +// } catch (final IOException e) { +// e.printStackTrace(); +// } +// final ImportsLexer lexer = new ImportsLexer(input); +// final CommonTokenStream tokens = new CommonTokenStream(lexer); +// final ImportsParser parser = new ImportsParser(tokens); +// // parser.removeErrorListeners(); +// // parser.addErrorListener(new UnderlineErrorListener()); +// // parser.importedFile(); +// +// parser.getInterpreter().setPredictionMode(PredictionMode.SLL); // try with simpler/faster SLL(*) +// // we don't want error messages or recovery during first try +// parser.removeErrorListeners(); +// parser.setErrorHandler(new BailErrorStrategy()); +// try { +// parser.importedFile(namespace); +// // if we get here, there was no syntax error and SLL(*) was enough; +// // there is no need to try full LL(*) +// } +// catch (RuntimeException ex) { +// if (ex.getClass() == RuntimeException.class && +// ex.getCause() instanceof RecognitionException) +// { +// // The BailErrorStrategy wraps the RecognitionExceptions in +// // RuntimeExceptions so we have to make sure we're detecting +// // a true RecognitionException not some other kind +// tokens.reset(); // rewind input stream +// // back to standard listeners/handlers +// parser.addErrorListener(new UnderlineErrorListener()); +// parser.setErrorHandler(new DefaultErrorStrategy()); +// parser.getInterpreter().setPredictionMode(PredictionMode.LL); // try full LL(*) +// parser.importedFile(namespace); +// } +// } +// } +// } + + +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/ISegment.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/ISegment.java new file mode 100644 index 00000000..11d68d45 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/ISegment.java @@ -0,0 +1,35 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.base; + +public interface ISegment { + + Element getOwner(); + + default String getSegment() { + return this.getClass().getSimpleName(); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/ISource.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/ISource.java new file mode 100644 index 00000000..0d6ce832 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/ISource.java @@ -0,0 +1,17 @@ +package eu.modelwriter.core.alloyinecore.structure.base; + +import eu.modelwriter.core.alloyinecore.structure.model.Model; + +import java.util.List; +import java.util.stream.Collectors; + +public interface ISource extends ISegment { + + default List getTargets() { + Element model = this.getOwner().getOwner(Model.class); + return model.getAllOwnedElements().stream() + .filter(e -> e instanceof ITarget) + .map(e -> (ISegment) e) + .collect(Collectors.toList()); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/ITarget.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/ITarget.java new file mode 100644 index 00000000..cb30b7d2 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/ITarget.java @@ -0,0 +1,24 @@ +package eu.modelwriter.core.alloyinecore.structure.base; + +import eu.modelwriter.core.alloyinecore.structure.model.Import; +import eu.modelwriter.core.alloyinecore.structure.model.RootPackage; + +public interface ITarget extends ISegment { + + default String getRelativeSegment() { + String path = this.getSegment(); + for (Element parent = this.getOwner(); parent != null; parent = parent.getOwner()) { + if (parent instanceof ISegment) { + String parentsPathName = ((ISegment) parent).getSegment(); + if (!parentsPathName.isEmpty()) { + path = parentsPathName + "::" + path; + } + if (parent instanceof RootPackage || parent instanceof Import) { + break; + } + } + } + return path; + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/Object.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/Object.java new file mode 100644 index 00000000..fdb3956b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/Object.java @@ -0,0 +1,53 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.base; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.util.EcoreUtil; + + +public abstract class Object extends Element { + private E eObject; + + public Object(E eObject, C context){ + super(context); + this.eObject = eObject; + } + + public Object(C context){ + super(context); + } + + public void setEObject(E eObject) { this.eObject = eObject; } + + public E getEObject() { return eObject; } + + public URI getURI() { + return EcoreUtil.getURI(this.eObject); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/Repository.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/Repository.java new file mode 100644 index 00000000..41339c2b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/base/Repository.java @@ -0,0 +1,275 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.base; + +import eu.modelwriter.core.alloyinecore.internal.Console; +import eu.modelwriter.core.alloyinecore.recognizer.imports.ImportsLexer; +import eu.modelwriter.core.alloyinecore.recognizer.imports.ImportsParser; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser; +import eu.modelwriter.core.alloyinecore.recognizer.UnderlineErrorListener; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.atn.PredictionMode; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; + +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; + + +public final class Repository { + public final Map name2Import; + private ResourceSetImpl resourceSet; + private Resource aieResource; + + /** + * folder path segments of aieResource + */ + private List relativeComplementerSegments; + /** + * if load resource is called recursively to try to complete relative path, it is true. else it is + * false. + */ + private boolean isRelativePass = false; + + + public Repository() { + name2Import = new HashMap<>(); + resourceSet = new ResourceSetImpl(); + resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap() + .put(Resource.Factory.Registry.DEFAULT_EXTENSION, new XMIResourceFactoryImpl()); + } + + public Repository(URI uri){ + this(); + relativeComplementerSegments = new ArrayList<>(uri.segmentsList()); + relativeComplementerSegments.remove(relativeComplementerSegments.size() - 1); + if (uri.scheme() != null && uri.scheme().equals("platform")) { + relativeComplementerSegments.remove(0); + } + } + + public void printNamespaces(){ + System.out.println(Console.BOLD + "[NAMESPACES]" + Console.RESET); + name2Import.values().forEach(anImport -> System.out.println(Console.CYAN + "[" + anImport.getKey() + "] " + Console.RESET + anImport.getEObject().toString() )); + } + + public EObject loadAndClearAIEResource(final URI uri) { + // try to get folder path of aieResource + relativeComplementerSegments = new ArrayList<>(uri.segmentsList()); + relativeComplementerSegments.remove(relativeComplementerSegments.size() - 1); + if (uri.scheme() != null && uri.scheme().equals("platform")) { + relativeComplementerSegments.remove(0); + } + + aieResource = resourceSet.createResource(uri); + try { + aieResource.load(null); + EObject rootElement = null; + if (!aieResource.getContents().isEmpty()) { + rootElement = aieResource.getContents().get(0); + } + aieResource.getContents().clear(); + return rootElement; + } catch (final IOException e) { + return null; + } + } + + public Resource loadResource(String path) { + while (path.startsWith("../") && relativeComplementerSegments.size() > 0) { + // remove from path if starts with '../', and go up one directory + path = path.substring(3, path.length()); + relativeComplementerSegments.remove(relativeComplementerSegments.size() - 1); + } + while (path.startsWith("./")) { + // remove from path if starts with './' + path = path.substring(2, path.length()); + } + while (path.startsWith("/")) { + // remove from path if starts with '/' + path = path.substring(1, path.length()); + } + + Resource resource; + try { + // try to load with default URI + resource = resourceSet.getResource(URI.createURI(path, true), true); + if (resource.getContents().isEmpty()) { + throw new Exception(); + } + return resource; + } catch (final Exception e1) { + try { + // try to load with platform resource URI + resource = resourceSet.getResource(URI.createPlatformResourceURI(path, true), true); + if (resource.getContents().isEmpty()) { + throw new Exception(); + } + return resource; + } catch (final Exception e2) { + try { + // try to load with platform plugin URI + resource = resourceSet.getResource(URI.createPlatformPluginURI(path, true), true); + if (resource.getContents().isEmpty()) { + throw new Exception(); + } + return resource; + } catch (final Exception e3) { + try { + // try to load with file URI + resource = resourceSet.getResource(URI.createFileURI(path), true); + if (resource.getContents().isEmpty()) { + throw new Exception(); + } + return resource; + } catch (final Exception e4) { + try { + // if any URI that created from path couldn't be loaded + // then we could think that is it relative path? + // so, add 'folder path of aieResource' to beginning of the 'path' + // and complete relative 'path' to full 'path' + final List completedRelativePath = + new ArrayList<>(relativeComplementerSegments); + completedRelativePath.add(path); + // now we have full 'path' + // we can try to load resource again. + if (!isRelativePass) { + isRelativePass = true; + resource = loadResource(String.join("/", completedRelativePath)); + if (resource.getContents().isEmpty()) { + throw new Exception(); + } + isRelativePass = false; + return resource; + } else { + isRelativePass = false; + throw new Exception(); + } + } catch (final Exception e5) { + // path could not be loaded anyway. + return null; + } + } + } + } + } + } + + public void saveResource(final EObject root, final URI saveURI) { + final Resource resource = resourceSet.getResource(saveURI, true); + resource.getContents().clear(); + resource.getContents().add(root); + try { + resource.save(null); + } catch (final IOException e) { + e.printStackTrace(); + } + } + + public EObject getEObject(final Stack qualifiedNameStack) { + final List relativePathFragments = + qualifiedNameStack.stream().collect(Collectors.toList()); + relativePathFragments.remove(0); + + final String importName = qualifiedNameStack.get(0); + final INamespace imported = name2Import.get(importName); + return imported.getElement(relativePathFragments); + } + + public EObject getEObject(final String importName, final List relativePathFragments) { + final INamespace aIEImport = name2Import.get(importName); + return aIEImport.getElement(relativePathFragments); + } + + public EPackage getRootPackage() { + return (EPackage) aieResource.getContents().get(0); + } + + public static void importPackage(ANTLRInputStream input, final T owner){ + final ImportsLexer lexer = new ImportsLexer(input); + final CommonTokenStream tokens = new CommonTokenStream(lexer); + final ImportsParser parser = new ImportsParser(tokens); + parser.getInterpreter().setPredictionMode(PredictionMode.SLL); // try with simpler/faster SLL(*) + // we don't want error messages or recovery during first try + parser.removeErrorListeners(); + parser.setErrorHandler(new BailErrorStrategy()); + try { + parser.importModel(owner); + // if we get here, there was no syntax error and SLL(*) was enough; + // there is no need to try full LL(*) + } + catch (RuntimeException ex) { + if (ex.getClass() == RuntimeException.class && + ex.getCause() instanceof RecognitionException) + { + // The BailErrorStrategy wraps the RecognitionExceptions in + // RuntimeExceptions so we have to make sure we're detecting + // a true RecognitionException not some other kind + tokens.reset(); // rewind input stream + // back to standard listeners/handlers + parser.addErrorListener(new UnderlineErrorListener()); + parser.setErrorHandler(new DefaultErrorStrategy()); + parser.getInterpreter().setPredictionMode(PredictionMode.LL); // try full LL(*) + parser.importModel(owner); + } + } + } + + public static void importInstance(ANTLRInputStream input, final T owner){ + final AlloyInEcoreLexer lexer = new AlloyInEcoreLexer(input); + final CommonTokenStream tokens = new CommonTokenStream(lexer); + final AlloyInEcoreParser parser = new AlloyInEcoreParser(tokens, owner.getEObject().eResource().getURI(), false); + parser.getInterpreter().setPredictionMode(PredictionMode.SLL); // try with simpler/faster SLL(*) + // we don't want error messages or recovery during first try + parser.removeErrorListeners(); + parser.setErrorHandler(new BailErrorStrategy()); + try { + parser.instance(owner); + // if we get here, there was no syntax error and SLL(*) was enough; + // there is no need to try full LL(*) + } + catch (RuntimeException ex) { + if (ex.getClass() == RuntimeException.class && + ex.getCause() instanceof RecognitionException) + { + // The BailErrorStrategy wraps the RecognitionExceptions in + // RuntimeExceptions so we have to make sure we're detecting + // a true RecognitionException not some other kind + tokens.reset(); // rewind input stream + // back to standard listeners/handlers + parser.addErrorListener(new UnderlineErrorListener()); + parser.setErrorHandler(new DefaultErrorStrategy()); + parser.getInterpreter().setPredictionMode(PredictionMode.LL); // try full LL(*) + parser.instance(owner); + } + } + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/ComprehensionDeclaration.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/ComprehensionDeclaration.java new file mode 100644 index 00000000..a2c8be60 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/ComprehensionDeclaration.java @@ -0,0 +1,40 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.constraints; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ComprehensionDeclarationContext; +import eu.modelwriter.core.alloyinecore.structure.model.Declaration; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +public class ComprehensionDeclaration extends Declaration { + public ComprehensionDeclaration(ComprehensionDeclarationContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitComprehensionDeclaration(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/Expression.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/Expression.java new file mode 100644 index 00000000..ce266e6f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/Expression.java @@ -0,0 +1,270 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.constraints; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ExpressionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.TransposeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ClosureContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ReflexiveContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.IntersectionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.DifferenceContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.JoinContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.BoxJoinContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ProductContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.OverrideContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ComprehensionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.IfExpressionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.IdenContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.NoneContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.UnivContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.IntsContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.TypeRefContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +public abstract class Expression extends Element { + + private Expression(C context) { super(context); } + + @Override + public int getStop(){ return getContext().stop.getStopIndex(); } + + public static Expression create(C ctx) { + Expression expression = null; + if (ctx instanceof TransposeContext) { + expression = new Transpose((TransposeContext) ctx); + expression.addOwnedElement(((TransposeContext) ctx).expression().element); + } else if (ctx instanceof ClosureContext){ + expression = new Closure((ClosureContext) ctx); + expression.addOwnedElement(((ClosureContext) ctx).expression().element); + }else if (ctx instanceof ReflexiveContext){ + expression = new Reflexive((ReflexiveContext) ctx); + expression.addOwnedElement(((ReflexiveContext) ctx).expression().element); + }else if (ctx instanceof UnionContext){ + expression = new Union((UnionContext) ctx); + expression.addOwnedElements(((UnionContext) ctx).left.element, ((UnionContext) ctx).right.element); + }else if (ctx instanceof IntersectionContext){ + expression = new Intersection((IntersectionContext) ctx); + expression.addOwnedElements(((IntersectionContext) ctx).left.element, ((IntersectionContext) ctx).right.element); + }else if (ctx instanceof DifferenceContext){ + expression = new Difference((DifferenceContext) ctx); + expression.addOwnedElements(((DifferenceContext) ctx).left.element, ((DifferenceContext) ctx).right.element); + }else if (ctx instanceof JoinContext){ + expression = new Join((JoinContext) ctx); + expression.addOwnedElements(((JoinContext) ctx).left.element, ((JoinContext) ctx).right.element); + }else if (ctx instanceof BoxJoinContext){ + expression = new BoxJoin((BoxJoinContext) ctx); + expression.addOwnedElements(((BoxJoinContext) ctx).right.element, ((BoxJoinContext) ctx).left.element); + }else if (ctx instanceof ProductContext){ + expression = new Product((ProductContext) ctx); + expression.addOwnedElements(((ProductContext) ctx).left.element, ((ProductContext) ctx).right.element); + }else if (ctx instanceof OverrideContext){ + expression = new RelationalOverride((OverrideContext) ctx); + expression.addOwnedElements(((OverrideContext) ctx).left.element, ((OverrideContext) ctx).right.element); + }else if (ctx instanceof ComprehensionContext){ + expression = new Comprehension((ComprehensionContext) ctx); + expression.addOwnedElements(((ComprehensionContext) ctx).comprehensionDeclarations().elements); + expression.addOwnedElements(((ComprehensionContext) ctx).formula().element); + }else if (ctx instanceof IfExpressionContext){ + expression = new IfExpression((IfExpressionContext) ctx); + expression.addOwnedElements(((IfExpressionContext) ctx).condition.element, ((IfExpressionContext) ctx).thenExpr.element, ((IfExpressionContext) ctx).elseExpr.element); + }else if (ctx instanceof IdenContext){ + expression = new Iden((IdenContext) ctx); + }else if (ctx instanceof NoneContext){ + expression = new None((NoneContext) ctx); + }else if (ctx instanceof UnivContext){ + expression = new Univ((UnivContext) ctx); + }else if (ctx instanceof IntsContext){ + expression = new Ints((IntsContext) ctx); + }else if (ctx instanceof TypeRefContext){ + expression = new Relation((TypeRefContext) ctx); + } + + return expression; + } + + public static final class Transpose extends Expression { + public Transpose(TransposeContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitTranspose(this); + } + } + + public static final class Closure extends Expression { + public Closure(ClosureContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitClosure(this); + } + } + + public static final class Reflexive extends Expression { + public Reflexive(ReflexiveContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitReflexive(this); + } + } + + public static final class Union extends Expression { + public Union(UnionContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitUnion(this); + } + } + + public static final class Intersection extends Expression { + public Intersection(IntersectionContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitIntersection(this); + } + } + + public static final class Difference extends Expression { + public Difference(DifferenceContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitDifference(this); + } + } + + public static final class Join extends Expression { + public Join(JoinContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitJoin(this); + } + } + + public static final class BoxJoin extends Expression { + public BoxJoin(BoxJoinContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitBoxJoin(this); + } + } + + public static final class Product extends Expression { + public Product(ProductContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitProduct(this); + } + } + + public static final class RelationalOverride extends Expression { + public RelationalOverride(OverrideContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitRelationalOverride(this); + } + } + + public static final class Comprehension extends Expression { + public Comprehension(ComprehensionContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitComprehension(this); + } + } + + public static final class IfExpression extends Expression { + public IfExpression(IfExpressionContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitIfExpression(this); + } + } + + public static final class Iden extends Expression { + public Iden(IdenContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitIden(this); + } + } + + public static final class None extends Expression { + public None(NoneContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitNone(this); + } + } + + public static final class Univ extends Expression { + public Univ(UnivContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitUniv(this); + } + } + + public static final class Ints extends Expression { + public Ints(IntsContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitInts(this); + } + } + + public static final class Binding extends Expression { + public Binding(TypeRefContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitBinding(this); + } + } + + public static final class Relation extends Expression { + public Relation(TypeRefContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitRelation(this); + } + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/Formula.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/Formula.java new file mode 100644 index 00000000..074f0f3f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/Formula.java @@ -0,0 +1,536 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.constraints; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.*; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +public abstract class Formula extends Element { + + private Formula(C context) { + super(context); + } + + @Override + public int getStop(){ return getContext().stop.getStopIndex(); } + + public static Formula create(C ctx) { + Formula formula = null; + if (ctx instanceof NoContext) { + formula = new No((NoContext) ctx); + formula.addOwnedElement(((NoContext) ctx).expression().element); + } else if (ctx instanceof LoneContext) { + formula = new Lone((LoneContext) ctx); + formula.addOwnedElement(((LoneContext) ctx).expression().element); + } else if (ctx instanceof OneContext) { + formula = new One((OneContext) ctx); + formula.addOwnedElement(((OneContext) ctx).expression().element); + } else if (ctx instanceof SomeContext) { + formula = new Some((SomeContext) ctx); + formula.addOwnedElement(((SomeContext) ctx).expression().element); + } else if (ctx instanceof InContext) { + if (((InContext) ctx).not != null) + formula = new NotIn((InContext) ctx); + else + formula = new In((InContext) ctx); + formula.addOwnedElements(((InContext) ctx).left.element, ((InContext) ctx).right.element); + } else if (ctx instanceof EqualContext) { + if (((EqualContext) ctx).not != null) + formula = new NotEqual((EqualContext) ctx); + else + formula = new Equal((EqualContext) ctx); + formula.addOwnedElements(((EqualContext) ctx).left.element, ((EqualContext) ctx).right.element); + } else if (ctx instanceof EqContext) { + if (((EqContext) ctx).not != null) + formula = new NotEq((EqContext) ctx); + else + formula = new Eq((EqContext) ctx); + formula.addOwnedElements(((EqContext) ctx).ileft.element, ((EqContext) ctx).iright.element); + } else if (ctx instanceof LtContext) { + if (((LtContext) ctx).not != null) + formula = new NotLt((LtContext) ctx); + else + formula = new Lt((LtContext) ctx); + formula.addOwnedElements(((LtContext) ctx).ileft.element, ((LtContext) ctx).iright.element); + } else if (ctx instanceof LteContext) { + if (((LteContext) ctx).not != null) + formula = new NotLte((LteContext) ctx); + else + formula = new Lte((LteContext) ctx); + formula.addOwnedElements(((LteContext) ctx).ileft.element, ((LteContext) ctx).iright.element); + } else if (ctx instanceof GtContext) { + if (((GtContext) ctx).not != null) + formula = new NotGt((GtContext) ctx); + else + formula = new Gt((GtContext) ctx); + formula.addOwnedElements(((GtContext) ctx).ileft.element, ((GtContext) ctx).iright.element); + } else if (ctx instanceof GteContext) { + if (((GteContext) ctx).not != null) + formula = new NotGte((GteContext) ctx); + else + formula = new Gte((GteContext) ctx); + formula.addOwnedElements(((GteContext) ctx).ileft.element, ((GteContext) ctx).iright.element); + } else if (ctx instanceof SumDeclarationContext) { + formula = new SumDeclaration((SumDeclarationContext) ctx); + formula.addOwnedElements(((SumDeclarationContext) ctx).quantifierDeclarations().elements); + formula.addOwnedElements(((SumDeclarationContext) ctx).intExpression().element); + } else if (ctx instanceof AcyclicContext) { + formula = new Acyclic((AcyclicContext) ctx); + } else if (ctx instanceof FunctionContext) { + if (((FunctionContext) ctx).partial != null) + formula = new PartialFunction((FunctionContext) ctx); + else + formula = new Function((FunctionContext) ctx); + formula.addOwnedElements(((FunctionContext) ctx).domain.element, ((FunctionContext) ctx).range.element); + } else if (ctx instanceof TotalOrderContext) { + formula = new TotalOrder((TotalOrderContext) ctx); + } else if (ctx instanceof NotContext) { + formula = new Not((NotContext) ctx); + formula.addOwnedElements(((NotContext) ctx).formula.element); + } else if (ctx instanceof AndContext) { + formula = new And((AndContext) ctx); + formula.addOwnedElements(((AndContext) ctx).fleft.element, ((AndContext) ctx).fright.element); + } else if (ctx instanceof OrContext) { + formula = new Or((OrContext) ctx); + formula.addOwnedElements(((OrContext) ctx).fleft.element, ((OrContext) ctx).fright.element); + } else if (ctx instanceof ImpliesContext) { + formula = new Implies((ImpliesContext) ctx); + formula.addOwnedElements(((ImpliesContext) ctx).fleft.element, ((ImpliesContext) ctx).fright.element); + } else if (ctx instanceof IffContext) { + formula = new Iff((IffContext) ctx); + formula.addOwnedElements(((IffContext) ctx).fleft.element, ((IffContext) ctx).fright.element); + } else if (ctx instanceof ForAllContext) { + formula = new ForAll((ForAllContext) ctx); + formula.addOwnedElements(((ForAllContext) ctx).quantifierDeclarations().elements); + formula.addOwnedElements(((ForAllContext) ctx).formula.element); + } else if (ctx instanceof ForSomeContext) { + formula = new ForSome((ForSomeContext) ctx); + formula.addOwnedElements(((ForSomeContext) ctx).quantifierDeclarations().elements); + formula.addOwnedElements(((ForSomeContext) ctx).formula.element); + } else if (ctx instanceof ForNoContext) { + formula = new ForNo((ForNoContext) ctx); + formula.addOwnedElements(((ForNoContext) ctx).quantifierDeclarations().elements); + formula.addOwnedElements(((ForNoContext) ctx).formula.element); + } else if (ctx instanceof ForOneContext) { + formula = new ForOne((ForOneContext) ctx); + formula.addOwnedElements(((ForOneContext) ctx).quantifierDeclarations().elements); + formula.addOwnedElements(((ForOneContext) ctx).formula.element); + } else if (ctx instanceof ForLoneContext) { + formula = new ForLone((ForLoneContext) ctx); + formula.addOwnedElements(((ForLoneContext) ctx).quantifierDeclarations().elements); + formula.addOwnedElements(((ForLoneContext) ctx).formula.element); + } else if (ctx instanceof TrueContext) { + formula = new True((TrueContext) ctx); + } else if (ctx instanceof FalseContext) { + formula = new False((FalseContext) ctx); + } + + return formula; + } + + public static final class No extends Formula { + public No(NoContext context) { super(context);} + + @Override + public T accept(IVisitor visitor) { + return visitor.visitNo(this); + } + } + + public static final class Lone extends Formula { + public Lone(AlloyInEcoreParser.LoneContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitLone(this); + } + } + + public static final class One extends Formula { + public One(OneContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitOne(this); + } + } + + public static final class Some extends Formula { + public Some(SomeContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitSome(this); + } + } + + public static class In extends Formula { + public In(InContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitIn(this); + } + } + + public static final class NotIn extends In { + public NotIn(InContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitNotIn(this); + } + } + + public static class Equal extends Formula { + public Equal(EqualContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitEqual(this); + } + } + + public static final class NotEqual extends Equal { + public NotEqual(EqualContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitNotEqual(this); + } + } + + public static class Eq extends Formula { + public Eq(EqContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitEq(this); + } + } + + public static final class NotEq extends Eq { + public NotEq(EqContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitNotEq(this); + } + } + + public static class Lt extends Formula { + public Lt(LtContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitLt(this); + } + } + + public static final class NotLt extends Lt { + public NotLt(LtContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitNotLt(this); + } + } + + public static class Lte extends Formula { + public Lte(LteContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitLte(this); + } + } + + public static final class NotLte extends Lte { + public NotLte(LteContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitNotLte(this); + } + } + + public static class Gt extends Formula { + public Gt(GtContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitGt(this); + } + } + + public static final class NotGt extends Gt { + public NotGt(GtContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitNotGt(this); + } + } + + public static class Gte extends Formula { + public Gte(GteContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitGte(this); + } + } + + public static final class NotGte extends Gte { + public NotGte(GteContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitNotGte(this); + } + } + + public static class SumDeclaration extends Formula { + public SumDeclaration(SumDeclarationContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitSumDeclaration(this); + } + } + + public static final class Acyclic extends Formula { + public Acyclic(AcyclicContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitAcyclic(this); + } + } + + public static class Function extends Formula { + public Function(FunctionContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitFunction(this); + } + } + + public static final class PartialFunction extends Function { + public PartialFunction(FunctionContext context) { super(context);} + + @Override + public T accept(IVisitor visitor) { + return visitor.visitPartialFunction(this); + } + } + + public static final class TotalOrder extends Formula { + public TotalOrder(TotalOrderContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitTotalOrder(this); + } + } + + public static final class Not extends Formula { + public Not(NotContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitNot(this); + } + } + + public static final class And extends Formula { + public And(AndContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitAnd(this); + } + } + + public static final class Or extends Formula { + public Or(OrContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitOr(this); + } + } + + public static final class Implies extends Formula { + public Implies(ImpliesContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitImplies(this); + } + } + + public static final class Iff extends Formula { + public Iff(IffContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitIff(this); + } + } + + public static final class ForAll extends Formula { + public ForAll(ForAllContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitForAll(this); + } + } + + public static final class ForSome extends Formula { + public ForSome(ForSomeContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitForSome(this); + } + } + + public static final class ForNo extends Formula { + public ForNo(ForNoContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitForNo(this); + } + } + + public static final class ForOne extends Formula { + public ForOne(ForOneContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitForOne(this); + } + } + + public static final class ForLone extends Formula { + public ForLone(ForLoneContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitForLone(this); + } + } + + public static final class True extends Formula { + public True(TrueContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitTrue(this); + } + } + + public static final class False extends Formula { + public False(FalseContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitFalse(this); + } + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/IntExpression.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/IntExpression.java new file mode 100644 index 00000000..8f1a4c84 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/IntExpression.java @@ -0,0 +1,162 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.constraints; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.IntExpressionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.IfIntExpressionContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.SumContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.CountContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.PlusContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.MinusContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.MultiplyContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.DivideContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ModuloContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.IntConstantContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +public abstract class IntExpression extends Element { + + private IntExpression(C context) { + super(context); + } + + @Override + public int getStop(){ return getContext().stop.getStopIndex(); } + + public static IntExpression create(C ctx) { + IntExpression expression = null; + if (ctx instanceof IfIntExpressionContext) { + expression = new IfIntExpression((IfIntExpressionContext) ctx); + expression.addOwnedElements(((IfIntExpressionContext) ctx).condition.element, ((IfIntExpressionContext) ctx).thenExpr.element, ((IfIntExpressionContext) ctx).elseExpr.element); + } else if (ctx instanceof SumContext) { + expression = new Sum((SumContext) ctx); + expression.addOwnedElement(((SumContext) ctx).expression().element); + }else if (ctx instanceof CountContext) { + expression = new Count((CountContext) ctx); + expression.addOwnedElement(((CountContext) ctx).expression().element); + }else if (ctx instanceof PlusContext) { + expression = new Plus((PlusContext) ctx); + expression.addOwnedElements(((PlusContext) ctx).ileft.element, ((PlusContext) ctx).iright.element); + }else if (ctx instanceof MinusContext) { + expression = new Minus((MinusContext) ctx); + expression.addOwnedElements(((MinusContext) ctx).ileft.element, ((MinusContext) ctx).iright.element); + }else if (ctx instanceof MultiplyContext) { + expression = new Multiply((MultiplyContext) ctx); + expression.addOwnedElements(((MultiplyContext) ctx).ileft.element, ((MultiplyContext) ctx).iright.element); + }else if (ctx instanceof DivideContext) { + expression = new Divide((DivideContext) ctx); + expression.addOwnedElements(((DivideContext) ctx).ileft.element, ((DivideContext) ctx).iright.element); + }else if (ctx instanceof ModuloContext) { + expression = new Modulo((ModuloContext) ctx); + expression.addOwnedElements(((ModuloContext) ctx).ileft.element, ((ModuloContext) ctx).iright.element); + }else if (ctx instanceof IntConstantContext) { + expression = new IntConstant((IntConstantContext) ctx); + } + + return expression; + } + + public static class IfIntExpression extends IntExpression{ + public IfIntExpression(IfIntExpressionContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitIfIntExpression(this); + } + } + + public static class Sum extends IntExpression{ + public Sum(SumContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitSum(this); + } + } + + public static class Count extends IntExpression{ + public Count(CountContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitCount(this); + } + } + + public static class Plus extends IntExpression{ + public Plus(PlusContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitPlus(this); + } + } + + public static class Minus extends IntExpression{ + public Minus(MinusContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitMinus(this); + } + } + + public static class Multiply extends IntExpression{ + public Multiply(MultiplyContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitMultiply(this); + } + } + + public static class Divide extends IntExpression{ + public Divide(DivideContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitDivide(this); + } + } + + public static class Modulo extends IntExpression{ + public Modulo(ModuloContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitModulo(this); + } + } + + public static class IntConstant extends IntExpression{ + public IntConstant(IntConstantContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitIntConstant(this); + } + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/LetDeclaration.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/LetDeclaration.java new file mode 100644 index 00000000..7a6e2c72 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/LetDeclaration.java @@ -0,0 +1,40 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.constraints; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.LetDeclarationContext; +import eu.modelwriter.core.alloyinecore.structure.model.Declaration; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +public final class LetDeclaration extends Declaration { + public LetDeclaration(LetDeclarationContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitLetDeclaration(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/QuantifierDeclaration.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/QuantifierDeclaration.java new file mode 100644 index 00000000..55216d7b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/QuantifierDeclaration.java @@ -0,0 +1,96 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.constraints; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.QuantifierDeclarationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.OneOfContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.LoneOfContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.SomeOfContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.SetOfContext; +import eu.modelwriter.core.alloyinecore.structure.model.Declaration; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +public abstract class QuantifierDeclaration extends Declaration { + + private QuantifierDeclaration(C context) { super(context); } + + public static QuantifierDeclaration create(C ctx) { + QuantifierDeclaration declaration = null; + if (ctx instanceof OneOfContext) { + declaration = new OneOf((OneOfContext) ctx); + for(AlloyInEcoreParser.VariableContext varCtx: ((OneOfContext) ctx).variable()){ + declaration.addOwnedElement(varCtx.element); + } + declaration.addOwnedElement(((OneOfContext) ctx).expression().element); + } else if (ctx instanceof LoneOfContext) { + declaration = new LoneOf((LoneOfContext) ctx); + declaration.addOwnedElement(((LoneOfContext) ctx).expression().element); + } else if (ctx instanceof SomeOfContext) { + declaration = new SomeOf((SomeOfContext) ctx); + declaration.addOwnedElement(((SomeOfContext) ctx).expression().element); + } else if (ctx instanceof SetOfContext) { + declaration = new SetOf((SetOfContext) ctx); + declaration.addOwnedElement(((SetOfContext) ctx).expression().element); + } + return declaration; + } + + public static final class OneOf extends QuantifierDeclaration { + public OneOf(OneOfContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitOneOf(this); + } + } + + public static final class LoneOf extends QuantifierDeclaration { + public LoneOf(LoneOfContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitLoneOf(this); + } + } + + public static final class SomeOf extends QuantifierDeclaration { + public SomeOf(SomeOfContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitSomeOf(this); + } + } + + public static final class SetOf extends QuantifierDeclaration { + public SetOf(SetOfContext context) { super(context); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitSetOf(this); + } + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/Variable.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/Variable.java new file mode 100644 index 00000000..7cadf684 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/constraints/Variable.java @@ -0,0 +1,44 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.constraints; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.VariableContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +public final class Variable extends Element { + public Variable(VariableContext context) { + super(context); + } + + public String getText(){ + return getContext().getText(); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitVariable(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/imports/ImportedClass.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/imports/ImportedClass.java new file mode 100644 index 00000000..40e3861b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/imports/ImportedClass.java @@ -0,0 +1,136 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.imports; + +import eu.modelwriter.core.alloyinecore.recognizer.imports.ImportsParser; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.base.ITarget; +import eu.modelwriter.core.alloyinecore.structure.model.IVisibility; +import eu.modelwriter.core.alloyinecore.structure.model.Visibility; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.antlr.v4.runtime.RuleContext; +import org.antlr.v4.runtime.Token; + +import java.util.stream.Collectors; + +public class ImportedClass extends Element implements IVisibility, ITarget { + + public ImportedClass(ImportsParser.IClassContext context) { + super(context); + } + + @Override + public Visibility getVisibility() { + Visibility visibility = Visibility.PACKAGE; + if (getContext().visibility() != null) { + String text = getContext().visibility().getText(); + try { + visibility = Visibility.valueOf(text.toUpperCase(java.util.Locale.ENGLISH)); + } catch (IllegalArgumentException e) { + visibility = Visibility.PACKAGE; + } + } + return visibility; + } + + @Override + public String getSegment() { + return getContext().name != null ? getContext().name.getText() : ITarget.super.getSegment(); + } + + @Override + protected String getName() { + if (this.getContext().name != null) + return ":" + this.getContext().name.getText(); + else + return super.getName(); + } + + @Override + public Token getToken() { + if (getContext().name != null) + return getContext().name.start; + else + return super.getToken(); + } + + @Override + public String getLabel() { + int start; + int stop; + if (getContext().name != null) { + start = getContext().name.start.getStartIndex(); + stop = getContext().name.stop.getStopIndex(); + } else { + start = getContext().start.getStartIndex(); + stop = getContext().stop.getStopIndex(); + } + + if (getContext().templateSignature() != null) { + stop = getContext().templateSignature().stop.getStopIndex(); + } + return Element.getNormalizedText(getContext(), start, stop); + } + + @Override + public String getSuffix() { + if (!getContext().iGenericType().isEmpty()) { + return ": " + String.join(", ", this.getContext().iGenericType().stream().map(RuleContext::getText).collect(Collectors.toList())); + } else { + return ""; + } + } + + @Override + public int getLine() { + if (getContext().name != null) + return getContext().name.start.getLine(); + else return super.getLine(); + } + + @Override + public int getStart() { + if (getContext().name != null) + return getContext().name.start.getStartIndex(); + else return super.getLine(); + } + + @Override + public int getStop() { + if (getContext().name != null) + return getContext().name.start.getStopIndex(); + else return super.getLine(); + } + + public boolean isAbstract() { + return getContext().isAbstract != null; + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitImportedClass(this); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/imports/ImportedDataType.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/imports/ImportedDataType.java new file mode 100644 index 00000000..8a67b603 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/imports/ImportedDataType.java @@ -0,0 +1,119 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.imports; + +import eu.modelwriter.core.alloyinecore.recognizer.imports.ImportsParser.IDataTypeContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.base.ITarget; +import eu.modelwriter.core.alloyinecore.structure.model.IVisibility; +import eu.modelwriter.core.alloyinecore.structure.model.Visibility; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.antlr.v4.runtime.Token; + +public class ImportedDataType extends Element implements IVisibility, ITarget { + + public ImportedDataType(IDataTypeContext context) { + super(context); + } + + @Override + public Visibility getVisibility() { + Visibility visibility = Visibility.PACKAGE; + if (getContext().visibility() != null) { + String text = getContext().visibility().getText(); + try { + visibility = Visibility.valueOf(text.toUpperCase(java.util.Locale.ENGLISH)); + } catch (IllegalArgumentException e) { + visibility = Visibility.PACKAGE; + } + } + return visibility; + } + + @Override + public String getSegment() { + return getContext().name != null ? getContext().name.getText() : ITarget.super.getSegment(); + } + + @Override + public Token getToken() { + if (getContext().name != null) + return getContext().name.start; + else + return super.getToken(); + } + + @Override + public String getLabel() { + int start; + int stop; + if (getContext().name != null) { + start = getContext().name.start.getStartIndex(); + stop = getContext().name.stop.getStopIndex(); + } else { + start = getContext().start.getStartIndex(); + stop = getContext().stop.getStopIndex(); + } + + if (getContext().templateSignature() != null) { + stop = getContext().templateSignature().stop.getStopIndex(); + } + return Element.getNormalizedText(getContext(), start, stop); + } + + @Override + protected String getName() { + if (this.getContext().name != null) + return ":" + this.getContext().name.getText(); + else + return super.getName(); + } + + @Override + public int getLine() { + if (getContext().name != null) + return getContext().name.start.getLine(); + else return super.getLine(); + } + + @Override + public int getStart() { + if (getContext().name != null) + return getContext().name.start.getStartIndex(); + else return super.getLine(); + } + + @Override + public int getStop() { + if (getContext().name != null) + return getContext().name.start.getStopIndex(); + else return super.getLine(); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitImportedDataType(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/imports/ImportedEnum.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/imports/ImportedEnum.java new file mode 100644 index 00000000..2d40cf0d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/imports/ImportedEnum.java @@ -0,0 +1,40 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.imports; + +import eu.modelwriter.core.alloyinecore.recognizer.imports.ImportsParser.IDataTypeContext; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +public final class ImportedEnum extends ImportedDataType { + + public ImportedEnum(IDataTypeContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitImportedEnum(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/imports/ImportedInterface.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/imports/ImportedInterface.java new file mode 100644 index 00000000..81c3bff6 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/imports/ImportedInterface.java @@ -0,0 +1,40 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.imports; + +import eu.modelwriter.core.alloyinecore.recognizer.imports.ImportsParser.IClassContext; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +public final class ImportedInterface extends ImportedClass { + + public ImportedInterface(IClassContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitImportedInterface(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/imports/ImportedPackage.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/imports/ImportedPackage.java new file mode 100644 index 00000000..fe98a774 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/imports/ImportedPackage.java @@ -0,0 +1,113 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.imports; + +import eu.modelwriter.core.alloyinecore.recognizer.imports.ImportsParser.IPackageContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.base.ISegment; +import eu.modelwriter.core.alloyinecore.structure.model.IVisibility; +import eu.modelwriter.core.alloyinecore.structure.model.Import; +import eu.modelwriter.core.alloyinecore.structure.model.Visibility; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.antlr.v4.runtime.Token; + +public final class ImportedPackage extends Element implements IVisibility, ISegment { + + public ImportedPackage(IPackageContext context) { + super(context); + } + + @Override + public Token getToken() { + if (getContext().name != null) + return getContext().name.start; + else + return super.getToken(); + } + + @Override + public String getLabel() { + String name; + String nsURI; + if (getContext().name != null) { + name = getContext().name.getText(); + } else { + name = "Package"; + } + if (getContext().nsURI != null) { + nsURI = getContext().nsURI.getText(); + } else { + nsURI = ""; + } + return name + " : " + nsURI; + } + + @Override + public Visibility getVisibility() { + Visibility visibility = Visibility.PACKAGE; + if (getContext().visibility() != null) { + String text = getContext().visibility().getText(); + try { + visibility = Visibility.valueOf(text.toUpperCase(java.util.Locale.ENGLISH)); + } catch (IllegalArgumentException e) { + visibility = Visibility.PACKAGE; + } + } + return visibility; + } + + @Override + public String getSegment() { + if (getOwner() != null && getOwner() instanceof Import) + return ""; + return getContext().name != null ? getContext().name.getText() : ISegment.super.getSegment(); + } + + @Override + public int getLine() { + if (getContext().name != null) + return getContext().name.start.getLine(); + else return super.getLine(); + } + + @Override + public int getStart() { + if (getContext().name != null) + return getContext().name.start.getStartIndex(); + else return super.getLine(); + } + + @Override + public int getStop() { + if (getContext().name != null) + return getContext().name.start.getStopIndex(); + else return super.getLine(); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitImportedPackage(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/BooleanValue.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/BooleanValue.java new file mode 100644 index 00000000..6ad3aed2 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/BooleanValue.java @@ -0,0 +1,41 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.instance; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.BooleanValueContext; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + + +public final class BooleanValue extends Literal { + + public BooleanValue(BooleanValueContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitBooleanValue(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/CharValue.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/CharValue.java new file mode 100644 index 00000000..b6e3691b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/CharValue.java @@ -0,0 +1,42 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.instance; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.CharValueContext; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + + +public final class CharValue extends Literal { + + + public CharValue(CharValueContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitCharValue(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/EnumValue.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/EnumValue.java new file mode 100644 index 00000000..a1f71923 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/EnumValue.java @@ -0,0 +1,39 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.instance; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EnumValueContext; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +public final class EnumValue extends Literal { + public EnumValue(EnumValueContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitEnumValue(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/Instance.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/Instance.java new file mode 100644 index 00000000..27a39b5f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/Instance.java @@ -0,0 +1,54 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.instance; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.InstanceContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.base.Object; +import eu.modelwriter.core.alloyinecore.structure.model.Class; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +public final class Instance extends Element { + + public Instance(InstanceContext context) { + super(context); + } + + public Object getRootObject(){ + if (getOwnedElements(Object.class).isEmpty()) + return null; + return getOwnedElements(Object.class).get(0); + } + + @Override + public String getLabel() { + return getContext().name != null ? "Instance " + getContext().name.getText() : "Instance"; + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitInstance(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/IntegerValue.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/IntegerValue.java new file mode 100644 index 00000000..e0bd06b9 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/IntegerValue.java @@ -0,0 +1,39 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.instance; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.IntegerValueContext; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +public final class IntegerValue extends Literal { + public IntegerValue(IntegerValueContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitIntegerValue(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/Literal.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/Literal.java new file mode 100644 index 00000000..8e402507 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/Literal.java @@ -0,0 +1,34 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.instance; + +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import org.antlr.v4.runtime.ParserRuleContext; + +public abstract class Literal extends Element { + public Literal(C context) { + super(context); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/ModelImport.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/ModelImport.java new file mode 100644 index 00000000..28e6c9e7 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/ModelImport.java @@ -0,0 +1,125 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.instance; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ModelImportContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.base.INamespace; +import eu.modelwriter.core.alloyinecore.structure.base.Object; +import eu.modelwriter.core.alloyinecore.structure.base.Repository; +import eu.modelwriter.core.alloyinecore.translator.EcoreTranslator; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.antlr.v4.runtime.ANTLRInputStream; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; + +import java.io.IOException; + +public final class ModelImport extends Object implements INamespace { + + public ModelImport(EObject eObject, ModelImportContext context) { + super(eObject, context); + } + + public ModelImport(ModelImportContext context) { + super(context); + } + + @Override + public String getLabel() { + int start; + int stop; + if (getContext().name != null) { + start = getContext().name.start.getStartIndex(); + } else { + start = getContext().start.getStartIndex(); + } + + if (getContext().ownedPathName != null) { + stop = getContext().ownedPathName.getStopIndex(); + } else { + stop = getContext().stop.getStopIndex(); + } + return Element.getNormalizedText(getContext(), start, stop); + } + + @Override + public T accept(IVisitor visitor) { + return null; + } + + @Override + public String getKey(){ + return getContext().name != null ? getContext().name.getText() + : getRootObject() instanceof ENamedElement + ? ((ENamedElement) getRootObject()).getName() : null; + } + + @Override + public String getPath() { + if (getContext().ownedPathName != null) + return getContext().ownedPathName.getText().replace("'", ""); + else return null; + } + + @Override + public void loadNamespace(Repository repository){ + if (getPath() != null) { + Resource resource = getResource(); + EcoreTranslator ecoreTranslator; + String recore; + try { + ecoreTranslator = new EcoreTranslator(repository); + recore= ecoreTranslator.translate(getPath()); + } catch (IOException | NullPointerException e) { + e.printStackTrace(); + return; + } + + if (resource.getURI().isFile()) { + System.out.println("[" + getKey() +"] Resource is file in the classpath"); + } else if (resource.getURI().isPlatform()) { + System.out.println("[" + getKey() +"] Resource is platform"); + } else if (resource.getURI().isPlatformPlugin()) { + System.out.println("[" + getKey() +"] Resource is platform plugin"); + } else if (resource.getURI().isPlatformResource()) { + System.out.println("[" + getKey() +"] Resource is platform resource"); + } else { + System.out.println("[" + getKey() +" ]Resource is file in the JAR"); + } + + System.out.print(" [" + resource.getURI().toFileString() + "]"); + System.out.println(); + + if (recore == null){ + System.out.println(" [We cannot import model instance yet, but I'm sure we'll do that soon.]"); + return; + } + ANTLRInputStream input = new ANTLRInputStream(recore.toCharArray(), recore.length()); + Repository.importPackage(input, this); + } + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/NullValue.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/NullValue.java new file mode 100644 index 00000000..d4af3318 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/NullValue.java @@ -0,0 +1,42 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.instance; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.NullValueContext; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + + +public final class NullValue extends Literal { + + + public NullValue(NullValueContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitNullValue(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/Object.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/Object.java new file mode 100644 index 00000000..94c28a89 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/Object.java @@ -0,0 +1,74 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.instance; + + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.model.Class; +import eu.modelwriter.core.alloyinecore.structure.model.TypedElement; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.eclipse.emf.ecore.EObject; + +import java.util.List; + +public class Object extends eu.modelwriter.core.alloyinecore.structure.base.Object { + public Object(EObject eObject, AlloyInEcoreParser.EObjectContext context) { + super(eObject, context); + } + + public Object(AlloyInEcoreParser.EObjectContext context) { + super(context); + } + + public Class getClassifier(){ + return null; + } + + public List getSlots(){ + return this.getOwnedElements(Slot.class); + } + + @Override + public String getLabel() { + String type = ""; + if (getContext().name != null) { + int start = getContext().name.start.getStartIndex(); + int stop = getContext().name.stop.getStopIndex(); + type = Element.getNormalizedText(getContext(), start, stop); + } + return type; + } + + @Override + public String getSuffix() { + return getContext().id != null ? ": " + getContext().id.getText().replace("\"", "") : ""; + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitObject(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/ObjectValue.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/ObjectValue.java new file mode 100644 index 00000000..a3b0d848 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/ObjectValue.java @@ -0,0 +1,44 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.instance; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EObjectValueContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +public final class ObjectValue extends Element { + public ObjectValue(EObjectValueContext context) { + super(context); + } + + public Object getObject(){ + return null; + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitObjectValue(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/RealValue.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/RealValue.java new file mode 100644 index 00000000..57aa2c4e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/RealValue.java @@ -0,0 +1,40 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.instance; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.RealValueContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +public final class RealValue extends Literal { + public RealValue(RealValueContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitRealValue(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/Slot.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/Slot.java new file mode 100644 index 00000000..332a5e2f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/Slot.java @@ -0,0 +1,77 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.instance; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.SlotContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.model.StructuralFeature; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.antlr.v4.runtime.RuleContext; + +import java.util.stream.Collectors; + +public final class Slot extends Element { + public Slot(SlotContext context) { + super(context); + } + + public StructuralFeature getDefiningFeature() { + return null; + } + + @Override + public String getLabel() { + int start; + int stop; + if (getContext().name != null) { + start = getContext().name.start.getStartIndex(); + stop = getContext().name.stop.getStopIndex(); + } else { + start = getContext().start.getStartIndex(); + stop = getContext().start.getStopIndex(); + } + return Element.getNormalizedText(getContext(), start, stop); + } + + @Override + public String getSuffix() { + if (!getContext().eObject().isEmpty()) { + return ": { " + String.join(", " , this.getOwnedElements(Object.class).stream().map(object -> object.getLabel().concat(object.getSuffix())).collect(Collectors.toList()) ) + " }"; + } else if (!getContext().eObjectValue().isEmpty()) { + return ": [ " + String.join(", " , this.getOwnedElements(ObjectValue.class).stream().map(object -> object.getLabel().concat(object.getSuffix())).collect(Collectors.toList()) ) + " ]"; + } else if (getContext().dataValue() != null){ + int start = getContext().dataValue().start.getStartIndex(); + int stop = getContext().dataValue().stop.getStopIndex(); + return ": " + Element.getNormalizedText(getContext(), start, stop); + } else { + return ""; + } + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitSlot(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/StringValue.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/StringValue.java new file mode 100644 index 00000000..146c3a8b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/instance/StringValue.java @@ -0,0 +1,42 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.instance; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.StringValueContext; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + + +public final class StringValue extends Literal { + + + public StringValue(StringValueContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitStringValue(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Annotation.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Annotation.java new file mode 100644 index 00000000..07d41c6f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Annotation.java @@ -0,0 +1,54 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EAnnotationContext; +import eu.modelwriter.core.alloyinecore.structure.base.ISource; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.eclipse.emf.ecore.EAnnotation; + +public class Annotation extends ModelElement implements ISource{ + + public Annotation(EAnnotation eAnnotation, EAnnotationContext context) { + super(eAnnotation, context); + } + + @Override + public String getLabel() { + if (getContext().source != null) { + String source = getContext().source.getText().replace("'", ""); + if (source.lastIndexOf("/") > -1) + return source.substring(source.lastIndexOf("/") + 1, source.length()); + else return source; + } else { + return ""; + } + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitAnnotation(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/AnnotationDetail.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/AnnotationDetail.java new file mode 100644 index 00000000..c4bcc643 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/AnnotationDetail.java @@ -0,0 +1,57 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EDetailContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +public final class AnnotationDetail extends Element { + public AnnotationDetail(EDetailContext context) { + super(context); + } + + @Override + public String getLabel() { + String k,v; + k = getContext().key != null ? getContext().key.getText().replace("'", "") : null; + v = getContext().value != null ? getContext().value.getText().replace("'", "") : null; + return k + " : " + v; + } + + @Override + public int getLine(){ return getContext().start.getLine(); } + + @Override + public int getStart() { return getContext().start.getStartIndex();} + + @Override + public int getStop(){ return getContext().stop.getStopIndex(); } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitAnnotationDetail(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/AnnotationReference.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/AnnotationReference.java new file mode 100644 index 00000000..516977af --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/AnnotationReference.java @@ -0,0 +1,56 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EModelElementRefContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.base.Object; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.eclipse.emf.ecore.EObject; + +public class AnnotationReference extends Object { + public AnnotationReference(EModelElementRefContext context) { + super(context); + } + + public AnnotationReference(EObject eObject, EModelElementRefContext context) { + super(eObject, context); + } + + @Override + public String getSuffix() { + return ": " + (getContext().ownedPathName != null ? Element.getNormalizedText(getContext().ownedPathName) : ""); + } + + @Override + public String getLabel() { + return "reference"; + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitAnnotationReference(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Attribute.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Attribute.java new file mode 100644 index 00000000..d82eff94 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Attribute.java @@ -0,0 +1,143 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EAttributeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericElementTypeContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.base.ISegment; +import eu.modelwriter.core.alloyinecore.structure.base.ISource; +import eu.modelwriter.core.alloyinecore.structure.base.ITarget; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedClass; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedDataType; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.antlr.v4.runtime.Token; +import org.eclipse.emf.ecore.EAttribute; + +import java.util.List; +import java.util.stream.Collectors; + +public final class Attribute extends StructuralFeature implements IVisibility, ISource, ITarget { + public Attribute(EAttribute eAttribute, EAttributeContext context) { + super(eAttribute, context); + } + + @Override + public Visibility getVisibility() { + Visibility visibility = Visibility.PACKAGE; + if (getContext().visibility != null) { + String text = getContext().visibility.getText(); + try { + visibility = Visibility.valueOf(text.toUpperCase(java.util.Locale.ENGLISH)); + } catch (IllegalArgumentException e) { + visibility = Visibility.PACKAGE; + } + } + return visibility; + } + + @Override + public Token getToken() { + if (getContext().name != null) + return getContext().name.start; + else + return super.getToken(); + } + + @Override + protected String getName() { + if (this.getContext().name != null) + return "::" + this.getContext().name.getText(); + else + return super.getName(); + } + + @Override + public String getLabel() { + int start; + int stop; + if (getContext().name != null) { + start = getContext().name.start.getStartIndex(); + stop = getContext().name.stop.getStopIndex(); + } else { + start = getContext().start.getStartIndex(); + stop = getContext().start.getStopIndex(); + } + + return Element.getNormalizedText(getContext(), start, stop); + } + + @Override + public String getSuffix() { + String multiplicity = getContext().ownedMultiplicity != null ? TypedElement.getMultiplicity(getContext().ownedMultiplicity) : "[1]"; + if (getContext().eAttributeType != null) { + EGenericElementTypeContext ctx = getContext().eAttributeType; + String typeRefText = Element.getNormalizedText(ctx); + return ": " + typeRefText + "" + multiplicity; + } else { + return ": " + multiplicity; + } + } + + @Override + public int getLine() { + if (getContext().name != null) + return getContext().name.start.getLine(); + else return super.getLine(); + } + + @Override + public int getStart() { + if (getContext().name != null) + return getContext().name.start.getStartIndex(); + else return super.getLine(); + } + + @Override + public int getStop() { + if (getContext().name != null) + return getContext().name.start.getStopIndex(); + else return super.getLine(); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitAttribute(this); + } + + @Override + public String getSegment() { + return getContext().name != null ? getContext().name.getText() : ITarget.super.getSegment(); + } + + @Override + public List getTargets() { + return ISource.super.getTargets().stream() + .filter(e -> e instanceof Classifier || + e instanceof ImportedClass || + e instanceof ImportedDataType) + .collect(Collectors.toList()); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Body.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Body.java new file mode 100644 index 00000000..65460d24 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Body.java @@ -0,0 +1,54 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.BodyContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.antlr.v4.runtime.misc.Interval; + +public final class Body extends Element { + public Body(BodyContext context) { + super(context); + } + + @Override + public String getLabel() { + int start; + int stop; + if (getContext().name != null) { + start = getContext().name.start.getStartIndex(); + stop = getContext().name.stop.getStopIndex(); + return getContext().start.getInputStream().getText(new Interval(start, stop)).replaceAll("\\s+", " ").replaceAll("(\\w)(\\s)(<)","$1$3"); //.replace(" extends ", " -> ") + } else { + return "implementation"; + } + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitBody(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Class.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Class.java new file mode 100644 index 00000000..6e1648cb --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Class.java @@ -0,0 +1,146 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EClassContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.base.ISegment; +import eu.modelwriter.core.alloyinecore.structure.base.ISource; +import eu.modelwriter.core.alloyinecore.structure.base.ITarget; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedClass; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.antlr.v4.runtime.RuleContext; +import org.antlr.v4.runtime.Token; +import org.eclipse.emf.ecore.EClass; + +import java.util.List; +import java.util.stream.Collectors; + +public class Class extends Classifier implements IVisibility, ISource, ITarget { + + public Class(EClass eClass, EClassContext context) { + super(eClass, context); + } + + @Override + public Visibility getVisibility() { + Visibility visibility = Visibility.PACKAGE; + if (getContext().visibility != null) { + String text = getContext().visibility.getText(); + try { + visibility = Visibility.valueOf(text.toUpperCase(java.util.Locale.ENGLISH)); + } catch (IllegalArgumentException e) { + visibility = Visibility.PACKAGE; + } + } + return visibility; + } + + @Override + protected String getName() { + if (this.getContext().name != null) + return ":" + this.getContext().name.getText(); + else + return super.getName(); + } + + @Override + public Token getToken() { + if (getContext().name != null) + return getContext().name.start; + else + return super.getToken(); + } + + @Override + public String getSegment() { + return getContext().name != null ? getContext().name.getText() : ITarget.super.getSegment(); + } + + @Override + public String getLabel() { + int start; + int stop; + if (getContext().name != null) { + start = getContext().name.start.getStartIndex(); + stop = getContext().name.stop.getStopIndex(); + } else { + start = getContext().start.getStartIndex(); + stop = getContext().stop.getStopIndex(); + } + + if (getContext().templateSignature != null) { + stop = getContext().templateSignature.stop.getStopIndex(); + } + return Element.getNormalizedText(getContext(), start, stop); + } + + @Override + public String getSuffix() { + if (!getContext().eSuperTypes.isEmpty()) { + return ": " + String.join(", ", this.getContext().eGenericSuperType().stream().map(RuleContext::getText).collect(Collectors.toList())); + } else { + return ""; + } + } + + @Override + public int getLine() { + if (getContext().name != null) + return getContext().name.start.getLine(); + else return super.getLine(); + } + + @Override + public int getStart() { + if (getContext().name != null) + return getContext().name.start.getStartIndex(); + else return super.getLine(); + } + + @Override + public int getStop() { + if (getContext().name != null) + return getContext().name.start.getStopIndex(); + else return super.getLine(); + } + + public boolean isAbstract() { + return getContext().isAbstract != null; + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitClass(this); + } + + @Override + public List getTargets() { + return ISource.super.getTargets().stream() + .filter(e -> e instanceof Class || + e instanceof ImportedClass) + .collect(Collectors.toList()); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Classifier.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Classifier.java new file mode 100644 index 00000000..c2da7a94 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Classifier.java @@ -0,0 +1,35 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.eclipse.emf.ecore.EClassifier; + +public abstract class Classifier extends NamedElement { + + public Classifier(EClassifier eNamedElement, C context) { + super(eNamedElement, context); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Constraint.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Constraint.java new file mode 100644 index 00000000..e5c7e6bf --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Constraint.java @@ -0,0 +1,35 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import org.antlr.v4.runtime.ParserRuleContext; + +public abstract class Constraint extends Element { + + public Constraint(C context) { + super(context); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/DataType.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/DataType.java new file mode 100644 index 00000000..0957ccbb --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/DataType.java @@ -0,0 +1,117 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EDataTypeContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.base.ITarget; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.antlr.v4.runtime.Token; +import org.eclipse.emf.ecore.EDataType; + +public class DataType extends Classifier implements IVisibility, ITarget { + public DataType(EDataType eDataType, EDataTypeContext context) { + super(eDataType, context); + } + + @Override + public Visibility getVisibility() { + Visibility visibility = Visibility.PACKAGE; + if (getContext().visibility != null) { + String text = getContext().visibility.getText(); + try { + visibility = Visibility.valueOf(text.toUpperCase(java.util.Locale.ENGLISH)); + } catch (IllegalArgumentException e) { + visibility = Visibility.PACKAGE; + } + } + return visibility; + } + + @Override + public Token getToken() { + if (getContext().name != null) + return getContext().name.start; + else + return super.getToken(); + } + + @Override + public String getSegment() { + return getContext().name != null ? getContext().name.getText() : ITarget.super.getSegment(); + } + + @Override + public String getLabel() { + int start; + int stop; + if (getContext().name != null) { + start = getContext().name.start.getStartIndex(); + stop = getContext().name.stop.getStopIndex(); + } else { + start = getContext().start.getStartIndex(); + stop = getContext().stop.getStopIndex(); + } + + if (getContext().templateSignature != null) { + stop = getContext().templateSignature.stop.getStopIndex(); + } + return Element.getNormalizedText(getContext(), start, stop); + } + + @Override + protected String getName() { + if (this.getContext().name != null) + return ":" + this.getContext().name.getText(); + else + return super.getName(); + } + + @Override + public int getLine() { + if (getContext().name != null) + return getContext().name.start.getLine(); + else return super.getLine(); + } + + @Override + public int getStart() { + if (getContext().name != null) + return getContext().name.start.getStartIndex(); + else return super.getLine(); + } + + @Override + public int getStop() { + if (getContext().name != null) + return getContext().name.start.getStopIndex(); + else return super.getLine(); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitDataType(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Declaration.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Declaration.java new file mode 100644 index 00000000..9a435784 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Declaration.java @@ -0,0 +1,48 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.constraints.Variable; +import org.antlr.v4.runtime.ParserRuleContext; + +import java.util.List; + +public abstract class Declaration extends Element { + public Declaration(C context) { + super(context); + } + + @Override + public int getStop(){ return getContext().stop.getStopIndex(); } + + public Variable getVariable(String name) { + List vars = this.getOwnedElements(Variable.class); + for(Variable var: vars) + if (var.getText() != null && var.getText().equals(name)) + return var; + return null; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Derivation.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Derivation.java new file mode 100644 index 00000000..f5353c56 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Derivation.java @@ -0,0 +1,56 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.DerivationContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.antlr.v4.runtime.misc.Interval; + +public final class Derivation extends Element { + public Derivation(DerivationContext context) { + super(context); + } + + @Override + public String getLabel() { + int start; + int stop; + if (getContext().name != null) { + start = getContext().name.start.getStartIndex(); + stop = getContext().name.stop.getStopIndex(); + } else { + start = getContext().start.getStartIndex(); + stop = getContext().stop.getStopIndex(); + } + + return getContext().start.getInputStream().getText(new Interval(start, stop)).replaceAll("\\s+", " ").replaceAll("(\\w)(\\s)(<)","$1$3"); //.replace(" extends ", " -> ") + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitDerivation(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/EcoreImport.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/EcoreImport.java new file mode 100644 index 00000000..e5c0d2df --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/EcoreImport.java @@ -0,0 +1,85 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.PackageImportContext; +import eu.modelwriter.core.alloyinecore.structure.base.INamespace; +import eu.modelwriter.core.alloyinecore.structure.base.Repository; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.antlr.v4.runtime.ANTLRInputStream; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; + +import java.io.IOException; +import java.io.InputStream; + +public final class EcoreImport extends Import { + + public EcoreImport(EObject eObject, PackageImportContext context) { + super(eObject, context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitEcoreImport(this); + } + + @Override + public String getPath() { + return "Ecore.recore"; + } + + @Override + public void loadNamespace(Repository repository) { + //http://docs.oracle.com/javase/7/docs/technotes/guides/lang/resources.html + Resource resource = getResource(); + + ClassLoader classLoader = INamespace.class.getClassLoader(); + InputStream inputStream = classLoader.getResourceAsStream(getPath()); + + if (resource.getURI().isFile()) { + System.out.println("[" + getKey() + "] Resource is file in the classpath"); + } else if (resource.getURI().isPlatform()) { + System.out.println("[" + getKey() + "] Resource is platform"); + } else if (resource.getURI().isPlatformPlugin()) { + System.out.println("[" + getKey() + "] Resource is platform plugin"); + } else if (resource.getURI().isPlatformResource()) { + System.out.println("[" + getKey() + "] Resource is platform resource"); + } else { + System.out.println("[" + getKey() + "] Resource is file in the JAR"); + } + + System.out.print(" [" + classLoader.getResource(getPath()).getFile() + "]"); + System.out.println(); + + ANTLRInputStream input = null; + try { + input = new ANTLRInputStream(inputStream); + } catch (final IOException e) { + e.printStackTrace(); + } + Repository.importPackage(input, this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Enum.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Enum.java new file mode 100644 index 00000000..41bc6a0f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Enum.java @@ -0,0 +1,118 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EEnumContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.base.ITarget; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.antlr.v4.runtime.Token; +import org.eclipse.emf.ecore.EClassifier; +import org.eclipse.emf.ecore.EEnum; + +public final class Enum extends Classifier implements IVisibility, ITarget { + public Enum(EClassifier eClassifier, EEnumContext context) { + super(eClassifier, context); + } + + @Override + public Visibility getVisibility() { + Visibility visibility = Visibility.PACKAGE; + if (getContext().visibility != null) { + String text = getContext().visibility.getText(); + try { + visibility = Visibility.valueOf(text.toUpperCase(java.util.Locale.ENGLISH)); + } catch (IllegalArgumentException e) { + visibility = Visibility.PACKAGE; + } + } + return visibility; + } + + @Override + public Token getToken() { + if (getContext().name != null) + return getContext().name.start; + else + return super.getToken(); + } + + @Override + public String getSegment() { + return this.getContext().name != null ? this.getContext().name.getText() : ITarget.super.getSegment(); + } + + @Override + public String getLabel() { + int start; + int stop; + if (getContext().name != null) { + start = getContext().name.start.getStartIndex(); + stop = getContext().name.stop.getStopIndex(); + } else { + start = getContext().start.getStartIndex(); + stop = getContext().stop.getStopIndex(); + } + + if (getContext().templateSignature != null) { + stop = getContext().templateSignature.stop.getStopIndex(); + } + return Element.getNormalizedText(getContext(), start, stop); + } + + @Override + protected String getName() { + if (this.getContext().name != null) + return ":" + this.getContext().name.getText(); + else + return super.getName(); + } + + @Override + public int getLine() { + if (getContext().name != null) + return getContext().name.start.getLine(); + else return super.getLine(); + } + + @Override + public int getStart() { + if (getContext().name != null) + return getContext().name.start.getStartIndex(); + else return super.getLine(); + } + + @Override + public int getStop() { + if (getContext().name != null) + return getContext().name.start.getStopIndex(); + else return super.getLine(); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitEnum(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/EnumLiteral.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/EnumLiteral.java new file mode 100644 index 00000000..34e8a5a1 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/EnumLiteral.java @@ -0,0 +1,97 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EEnumLiteralContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.antlr.v4.runtime.Token; +import org.eclipse.emf.ecore.EEnumLiteral; + +public final class EnumLiteral extends NamedElement { + public EnumLiteral(EEnumLiteral eEnumLiteral, EEnumLiteralContext context) { + super(eEnumLiteral, context); + } + + @Override + public Token getToken() { + if (getContext().name != null) + return getContext().name.start; + else + return super.getToken(); + } + + @Override + public String getLabel() { + int start; + int stop; + if (getContext().name != null) { + start = getContext().name.start.getStartIndex(); + stop = getContext().name.stop.getStopIndex(); + } else { + start = getContext().start.getStartIndex(); + stop = getContext().stop.getStopIndex(); + } + + if (getContext().value != null) { + stop = getContext().value.getStopIndex(); + } + return Element.getNormalizedText(getContext(), start, stop); + } + + @Override + protected String getName(){ + if (this.getContext().name != null) + return "::" + this.getContext().name.getText(); + else + return super.getName(); + } + + @Override + public int getLine() { + if (getContext().name != null) + return getContext().name.start.getLine(); + else return super.getLine(); + } + + @Override + public int getStart() { + if (getContext().name != null) + return getContext().name.start.getStartIndex(); + else return super.getLine(); + } + + @Override + public int getStop() { + if (getContext().name != null) + return getContext().name.start.getStopIndex(); + else return super.getLine(); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitEnumLiteral(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/GenericElementType.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/GenericElementType.java new file mode 100644 index 00000000..6f29fb94 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/GenericElementType.java @@ -0,0 +1,46 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericElementTypeContext; +import eu.modelwriter.core.alloyinecore.structure.base.Object; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.eclipse.emf.ecore.EGenericType; + +//GenericElementType +public final class GenericElementType extends Object { + public GenericElementType(EGenericType eObject, EGenericElementTypeContext context) { + super(eObject, context); + } + + public GenericElementType(EGenericElementTypeContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitGenericElementType(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/GenericException.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/GenericException.java new file mode 100644 index 00000000..7e0d7236 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/GenericException.java @@ -0,0 +1,45 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericExceptionContext; +import eu.modelwriter.core.alloyinecore.structure.base.Object; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.eclipse.emf.ecore.EGenericType; + +public final class GenericException extends Object { + public GenericException(EGenericType eObject, EGenericExceptionContext context) { + super(eObject, context); + } + + public GenericException(EGenericExceptionContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitGenericException(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/GenericSuperType.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/GenericSuperType.java new file mode 100644 index 00000000..5e064e34 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/GenericSuperType.java @@ -0,0 +1,46 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericSuperTypeContext; +import eu.modelwriter.core.alloyinecore.structure.base.Object; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.eclipse.emf.ecore.EGenericType; + +public final class GenericSuperType extends Object { + public GenericSuperType(EGenericType eObject, EGenericSuperTypeContext context) { + super(eObject, context); + } + + public GenericSuperType(EGenericSuperTypeContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitGenericSuperType(this); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/GenericType.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/GenericType.java new file mode 100644 index 00000000..dd1aadec --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/GenericType.java @@ -0,0 +1,47 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericTypeContext; +import eu.modelwriter.core.alloyinecore.structure.base.Object; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.eclipse.emf.ecore.EGenericType; + +public class GenericType extends Object { + + + public GenericType(EGenericType eObject, EGenericTypeContext context) { + super(eObject, context); + } + + public GenericType(EGenericTypeContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitGenericType(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/GenericTypeArgument.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/GenericTypeArgument.java new file mode 100644 index 00000000..1db4eb1b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/GenericTypeArgument.java @@ -0,0 +1,45 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericTypeArgumentContext; +import eu.modelwriter.core.alloyinecore.structure.base.Object; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.eclipse.emf.ecore.EGenericType; + +public class GenericTypeArgument extends Object { + public GenericTypeArgument(EGenericType eObject, EGenericTypeArgumentContext context) { + super(eObject, context); + } + + public GenericTypeArgument(EGenericTypeArgumentContext context) { + super(context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitGenericTypeArgument(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/GenericWildcard.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/GenericWildcard.java new file mode 100644 index 00000000..677b622a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/GenericWildcard.java @@ -0,0 +1,72 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericWildcardContext; +import eu.modelwriter.core.alloyinecore.structure.base.Object; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.eclipse.emf.ecore.EGenericType; + +public class GenericWildcard extends Object { + + public GenericWildcard(EGenericType eObject, EGenericWildcardContext context) { + super(eObject, context); + } + + public GenericWildcard(EGenericWildcardContext context) { + super(context); + } + + @Override + public String getLabel() { + AlloyInEcoreParser.EGenericTypeContext ownedExtend= getContext().ownedExtend; + return ownedExtend != null ? getNormalizedText(getContext(), ownedExtend.start.getStartIndex(), ownedExtend.stop.getStopIndex()) : "?"; + } + + @Override + public int getLine(){ + AlloyInEcoreParser.EGenericTypeContext ownedExtend= getContext().ownedExtend; + return ownedExtend != null ? ownedExtend.stop.getLine() : getContext().start.getLine(); + } + + @Override + public int getStart() { + AlloyInEcoreParser.EGenericTypeContext ownedExtend= getContext().ownedExtend; + return ownedExtend != null ? ownedExtend.stop.getStartIndex() : getContext().start.getStartIndex(); + } + + @Override + public int getStop(){ + AlloyInEcoreParser.EGenericTypeContext ownedExtend= getContext().ownedExtend; + return ownedExtend != null ? ownedExtend.stop.getStopIndex() : getContext().start.getStopIndex(); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitGenericWildcard(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/IVisibility.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/IVisibility.java new file mode 100644 index 00000000..0b26e645 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/IVisibility.java @@ -0,0 +1,30 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + + +public interface IVisibility { + Visibility getVisibility(); +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Import.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Import.java new file mode 100644 index 00000000..9b7aece3 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Import.java @@ -0,0 +1,179 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.PackageImportContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.base.INamespace; +import eu.modelwriter.core.alloyinecore.structure.base.Object; +import eu.modelwriter.core.alloyinecore.structure.base.Repository; +import eu.modelwriter.core.alloyinecore.translator.EcoreInstanceTranslator; +import eu.modelwriter.core.alloyinecore.translator.EcoreTranslator; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.Token; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; + +import java.io.IOException; + +public class Import extends Object implements INamespace { + + public Import(EObject eObject, PackageImportContext context) { + super(eObject, context); + } + + @Override + public String getPath() { + if (getContext().ownedPathName != null) + return getContext().ownedPathName.getText().replace("'", ""); + else return null; + } + + @Override + public void loadNamespace(Repository repository) { + if (getPath() != null) { + Resource resource = getResource(); + String recore; + if (resource.getURI().isFile()) { + System.out.println("[" + getKey() + "] Resource is file in the classpath"); + } else if (resource.getURI().isPlatform()) { + System.out.println("[" + getKey() + "] Resource is platform"); + } else if (resource.getURI().isPlatformPlugin()) { + System.out.println("[" + getKey() + "] Resource is platform plugin"); + } else if (resource.getURI().isPlatformResource()) { + System.out.println("[" + getKey() + "] Resource is platform resource"); + } else { + System.out.println("[" + getKey() + " ]Resource is file in the JAR"); + } + System.out.print(" [" + resource.getURI().toFileString() + "]"); + System.out.println(); + + if (getEObject() instanceof ENamedElement) { + EcoreTranslator modelTranslator; + try { + modelTranslator = new EcoreTranslator(repository); + recore = modelTranslator.translate(getPath()); + } catch (IOException | NullPointerException e) { + e.printStackTrace(); + return; + } + ANTLRInputStream input = new ANTLRInputStream(recore.toCharArray(), recore.length()); + Repository.importPackage(input, this); + } else { + EcoreInstanceTranslator instanceTranslator; + try { + instanceTranslator = new EcoreInstanceTranslator(repository); + recore = instanceTranslator.translate(getPath()); + } catch (IOException | NullPointerException e) { + e.printStackTrace(); + return; + } + ANTLRInputStream input = new ANTLRInputStream(recore.toCharArray(), recore.length()); + Repository.importInstance(input, this); + } + + } + } + + @Override + public String getKey() { + return getContext().name != null ? getContext().name.getText() + : getRootObject() instanceof ENamedElement + ? ((ENamedElement) getRootObject()).getName() : null; + } + + @Override + public String getSegment() { + return this.getContext().name != null ? this.getContext().name.getText() : INamespace.super.getSegment(); + } + + protected String getName() { + String name = ""; + if (this.getContext().name != null) { + name = "::" + this.getContext().name.getText(); + } else if (this.getEObject() != null && this.getEObject() instanceof ENamedElement) { + ENamedElement pack = (ENamedElement) this.getEObject(); + if (pack.getName() != null && !pack.getName().isEmpty()) + name = "::" + pack.getName(); + } else if (this.getURI() != null) + name = this.getURI().lastSegment(); + return name; + } + + @Override + public Token getToken() { + if (getContext().name != null) + return getContext().name.start; + else + return super.getToken(); + } + + @Override + public String getLabel() { + int start; + int stop; + if (getContext().name != null) { + start = getContext().name.start.getStartIndex(); + } else { + start = getContext().start.getStartIndex(); + } + + if (getContext().ownedPathName != null) { + stop = getContext().ownedPathName.getStopIndex(); + } else { + stop = getContext().stop.getStopIndex(); + } + return Element.getNormalizedText(getContext(), start, stop); + } + + @Override + public int getLine() { + if (getContext().name != null) + return getContext().name.start.getLine(); + else return super.getLine(); + } + + @Override + public int getStart() { + if (getContext().name != null) + return getContext().name.start.getStartIndex(); + else return super.getLine(); + } + + @Override + public int getStop() { + if (getContext().name != null) + return getContext().name.start.getStopIndex(); + else return super.getLine(); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitImport(this); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Initial.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Initial.java new file mode 100644 index 00000000..8f52ef0e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Initial.java @@ -0,0 +1,57 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.InitialContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +public final class Initial extends Element { + + public Initial(InitialContext context) { + super(context); + } + + @Override + public String getLabel() { + int start; + int stop; + if (getContext().name != null) { + start = getContext().name.start.getStartIndex(); + stop = getContext().name.stop.getStopIndex(); + } else { + start = getContext().start.getStartIndex(); + stop = getContext().stop.getStopIndex(); + } + + return Element.getNormalizedText(getContext(), start, stop); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitInitial(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Interface.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Interface.java new file mode 100644 index 00000000..1a228095 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Interface.java @@ -0,0 +1,40 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EClassContext; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.eclipse.emf.ecore.EClass; + +public final class Interface extends Class { + public Interface(EClass eClass, EClassContext context) { + super(eClass, context); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitInterface(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Invariant.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Invariant.java new file mode 100644 index 00000000..a37bdd72 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Invariant.java @@ -0,0 +1,71 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.InvariantContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +public final class Invariant extends Constraint{ + public Invariant(InvariantContext context) { + super(context); + } + + @Override + public String getLabel() { + int start; + int stop; + if (getContext().name != null) { + start = getContext().name.start.getStartIndex(); + stop = getContext().name.stop.getStopIndex(); + } else { + start = getContext().start.getStartIndex(); + stop = getContext().stop.getStopIndex(); + } + + return Element.getNormalizedText(getContext(), start, stop); + } + + @Override + public int getLine() { + return super.getLine(); + } + + @Override + public int getStart() { + return super.getStart(); + } + + @Override + public int getStop() { + return super.getStop(); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitInvariant(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/MappingVisitor.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/MappingVisitor.java new file mode 100644 index 00000000..a00be928 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/MappingVisitor.java @@ -0,0 +1,201 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreBaseVisitor; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser; +import eu.modelwriter.core.alloyinecore.structure.base.Repository; +import org.eclipse.emf.ecore.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class MappingVisitor extends AlloyInEcoreBaseVisitor{ + + final Repository repository; + public MappingVisitor(Repository repository){ + this.repository = repository; + } + + @Override + public EClass visitEClass(AlloyInEcoreParser.EClassContext ctx) { + final EClass eClass = ctx.element; + if (ctx.eSuperTypes != null) { + ctx.eSuperTypes.forEach(est -> { + final EGenericType superType = visitEGenericSuperType(est); + if (superType != null) { + eClass.getEGenericSuperTypes().add(superType); + } + }); + } + return eClass; + } + + @Override + public EObject visitEAttribute(AlloyInEcoreParser.EAttributeContext ctx) { + return super.visitEAttribute(ctx); + } + + @Override + public EObject visitEReference(AlloyInEcoreParser.EReferenceContext ctx) { + return super.visitEReference(ctx); + } + + @Override + public EObject visitEOperation(AlloyInEcoreParser.EOperationContext ctx) { + return super.visitEOperation(ctx); + } + + @Override + public EObject visitEGenericException(AlloyInEcoreParser.EGenericExceptionContext ctx) { + return super.visitEGenericException(ctx); + } + + @Override + public EGenericType visitEGenericSuperType(AlloyInEcoreParser.EGenericSuperTypeContext ctx) { + if (ctx.eGenericType != null) { + return visitEGenericType(ctx.eGenericType); + } + return null; + } + + @Override + public EObject visitTemplateSignature(AlloyInEcoreParser.TemplateSignatureContext ctx) { + return super.visitTemplateSignature(ctx); + } + + @Override + public EObject visitETypeParameter(AlloyInEcoreParser.ETypeParameterContext ctx) { + return super.visitETypeParameter(ctx); + } + + @Override + public EGenericType visitEGenericTypeArgument(AlloyInEcoreParser.EGenericTypeArgumentContext ctx) { + if (ctx.eGenericType != null) { + return visitEGenericType(ctx.eGenericType); + } + if (ctx.eGenericWildcard != null) { + return visitEGenericWildcard(ctx.eGenericWildcard); + } + return null; + } + + @Override + public EGenericType visitEGenericType(AlloyInEcoreParser.EGenericTypeContext ctx) { + final EGenericType eGenericType = ctx.element; + + if (ctx.ownedPathName == null) { + return null; + } + + final EObject object = visitPathName(ctx.ownedPathName); + if (object instanceof EClassifier) { + eGenericType.setEClassifier((EClassifier) object); + } else if (object instanceof ETypeParameter) { + eGenericType.setETypeParameter((ETypeParameter) object); + } else { + return null; + } + + if (ctx.ownedETypeArguments != null) { + if (object instanceof EClassifier) { + ctx.ownedETypeArguments.forEach(eta -> { + final EGenericType eGenericTypeArgument = visitEGenericTypeArgument(eta); + if (eGenericTypeArgument != null) { + eGenericType.getETypeArguments().add(eGenericTypeArgument); + } + }); + } + } + + return eGenericType; + } + + @Override + public EGenericType visitEGenericWildcard(AlloyInEcoreParser.EGenericWildcardContext ctx) { + final EGenericType eGenericType = ctx.element; + + if (ctx.ownedExtend != null) { + final EGenericType boundType = visitEGenericType(ctx.ownedExtend); + if (boundType != null) { + if (ctx.bound != null) { + if (ctx.bound.getText().equals("extends")) { + eGenericType.setEUpperBound(boundType); + } else if (ctx.bound.getText().equals("super")) { + eGenericType.setELowerBound(boundType); + } + } + } + } + + return eGenericType; + } + + @Override + public EObject visitPathName(AlloyInEcoreParser.PathNameContext ctx) { + String rootElementName; + final List relativePathFragments = + new ArrayList<>(Arrays.asList(ctx.getText().split("::"))); + + if (repository.name2Import.containsKey(ctx.firstSegment.getText())) { // full path + rootElementName = ctx.firstSegment.getText(); + relativePathFragments.remove(0); // root is unnecessary. + + return repository.getEObject(rootElementName, relativePathFragments); + } else { // relative path + rootElementName = repository.getRootPackage().getName(); + + //TODO buradan emin degilim + final List complementPathFragments = new ArrayList<>(Arrays.asList(ctx.owner.getUniqueName().split("::"))); + //qualifiedNameStack.stream().collect(Collectors.toList()); + complementPathFragments.remove(0); // root is unnecessary. + + // 1. trying to find inner reference (like reference to TypeParameter): + final List tempFragments = new ArrayList<>(relativePathFragments); + tempFragments.addAll(0, complementPathFragments); + final EObject result = repository.getEObject(rootElementName, tempFragments); + if (result != null) { + return result; + } + + // 2. trying to find outer reference (like reference to sibling et cetera.) + complementPathFragments.remove(complementPathFragments.size() - 1); + // first remove reference holder (last item of qualified name stack.). + relativePathFragments.addAll(0, complementPathFragments); + return repository.getEObject(rootElementName, relativePathFragments); + } + } + + @Override + public EObject visitSegment(AlloyInEcoreParser.SegmentContext ctx) { + return super.visitSegment(ctx); + } + + @Override + public EObject visitEPrimitiveType(AlloyInEcoreParser.EPrimitiveTypeContext ctx) { + return super.visitEPrimitiveType(ctx); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Model.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Model.java new file mode 100644 index 00000000..1e4f17bb --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Model.java @@ -0,0 +1,53 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ModelContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + + +public final class Model extends Element { + + public Model(ModelContext context) { + super(context); + } + + public RootPackage getOwnedPackage(){ + if (getOwnedElements(RootPackage.class).isEmpty()) + return null; + return getOwnedElements(RootPackage.class).get(0); + } + + @Override + public String getLabel() { + return getContext().name != null ? "Model " + getContext().name.getText() : "Model"; + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitModule(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/ModelElement.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/ModelElement.java new file mode 100644 index 00000000..436fc489 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/ModelElement.java @@ -0,0 +1,40 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.structure.base.Object; +import org.antlr.v4.runtime.ParserRuleContext; +import org.eclipse.emf.ecore.EModelElement; + +public abstract class ModelElement extends Object { + + public ModelElement(E eModelElement, C context) { + super(eModelElement, context); + } + + public ModelElement(C context){ + super(context); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Multiplicity.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Multiplicity.java new file mode 100644 index 00000000..fdc6bc61 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Multiplicity.java @@ -0,0 +1,102 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EMultiplicityContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +import java.util.Arrays; + +public class Multiplicity extends Element { + public Multiplicity(EMultiplicityContext context) { + super(context); + } + + @Override + public String getLabel() { + int l = 1; + int u = 1; + + if (getContext().stringBound != null) { + switch (getContext().stringBound.getText()) { + case "*": + l = 0; + u = -1; + break; + case "+": + l = 1; + u = -1; + break; + case "?": + l = 0; + u = 1; + break; + default: + break; + } + } else { + try { + l = Integer.valueOf(getContext().lowerBound.getText()); + } catch (NumberFormatException ex) { + System.out.println(Arrays.toString(ex.getStackTrace())); + } + if (getContext().upperBound != null) { + if (getContext().upperBound.getText().equals("*")) u = -1; + else try { + u = Integer.valueOf(getContext().upperBound.getText()); + } catch (NumberFormatException ex) { + System.out.println(Arrays.toString(ex.getStackTrace())); + } + } else { + u = l; + } + } + String multiplicity; + if (l == 0 && u == -1) + multiplicity = "[*]"; + else if (l == 1 && u == -1) + multiplicity = "[+]"; + else if (l == 0 && u == 1) + multiplicity = "[?]"; + else if (l == 1 && u == 1) + multiplicity = "[1]"; + else if (l == u) + multiplicity = "[" + l + "]"; + else + multiplicity = "[" + l + ".." + u + "]"; + return multiplicity; + } + + public boolean isMany() { + String label = getLabel(); + return !label.equals("[1]") && !label.equals("[?]"); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitMultiplicity(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/NamedElement.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/NamedElement.java new file mode 100644 index 00000000..42decdeb --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/NamedElement.java @@ -0,0 +1,40 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.eclipse.emf.ecore.ENamedElement; + +public abstract class NamedElement extends ModelElement { + + public NamedElement(E eNamedElement, C context){ + super(eNamedElement, context); + } + + public NamedElement(C context){ + super(context); + + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Operation.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Operation.java new file mode 100644 index 00000000..e5ac9140 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Operation.java @@ -0,0 +1,180 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericElementTypeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EOperationContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EParameterContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.base.ISegment; +import eu.modelwriter.core.alloyinecore.structure.base.ISource; +import eu.modelwriter.core.alloyinecore.structure.base.ITarget; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedClass; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedDataType; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.antlr.v4.runtime.Token; +import org.eclipse.emf.ecore.EOperation; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public final class Operation extends TypedElement implements IVisibility, ISource, ITarget { + + public Operation(EOperation eOperation, EOperationContext context) { + super(eOperation, context); + } + + public Operation(EOperationContext context) { + super(context); + } + + public List getParameters() { + List parameters = new ArrayList<>(); + for (Element e : getOwnedElements()) + if (e instanceof Parameter) parameters.add((Parameter) e); + return parameters; + } + + @Override + public Visibility getVisibility() { + Visibility visibility = Visibility.PACKAGE; + if (getContext().visibility != null) { + String text = getContext().visibility.getText(); + try { + visibility = Visibility.valueOf(text.toUpperCase(java.util.Locale.ENGLISH)); + } catch (IllegalArgumentException e) { + visibility = Visibility.PACKAGE; + } + } + return visibility; + } + + @Override + public Token getToken() { + if (getContext().name != null) + return getContext().name.start; + else + return super.getToken(); + } + + @Override + public String getLabel() { + String name = ""; + if (getContext().name != null) { + name = getContext().name.getText(); + } + List parameterTypeTexts = new ArrayList<>(); + for (Parameter e : this.getOwnedElements(Parameter.class)) { + EGenericElementTypeContext typeRef = e.getContext().eParameterType; + if (typeRef != null) parameterTypeTexts.add(Element.getNormalizedText(typeRef)); + } + return name + "(" + String.join(", ", parameterTypeTexts) + ")"; + } + + @Override + public String getSegment() { + return getContext().name != null ? getContext().name.getText() : ISource.super.getSegment(); + } + + @Override + public String getSuffix() { + String throwsText = ""; + if (!getContext().ownedException.isEmpty()) { + throwsText = "throws " + String.join(", ", getContext().ownedException.stream() + .map(eGenericExceptionContext -> Element.getNormalizedText(eGenericExceptionContext.eGenericType)).collect(Collectors.toList())); + } + + if (getContext().eReturnType == null) { + return ": void" + " " + throwsText; + } else if (getContext().ownedMultiplicity != null) { + String multiplicity = TypedElement.getMultiplicity(getContext().ownedMultiplicity); + if (getContext().eReturnType != null) { + EGenericElementTypeContext ctx = getContext().eReturnType; + String typeRefText = Element.getNormalizedText(ctx); + return ": " + typeRefText + "" + multiplicity + " " + throwsText; + } else { + return ": " + multiplicity + " " + throwsText; + } + } else { + return "[1]" + " " + throwsText; + } + } + + @Override + public int getLine() { + if (getContext().name != null) + return getContext().name.start.getLine(); + else return super.getLine(); + } + + @Override + protected String getName() { + String name = ""; + if (this.getContext().name != null) + name = "->" + this.getContext().name.getText(); + if (!this.getContext().eParameter().isEmpty()) { + name = name + "#" + String.valueOf(this.getContext().eParameter().size()); + for (EParameterContext p : this.getContext().eParameter()) { + if (p.eParameterType != null) { + if (p.eParameterType.eGenericType() != null && p.eParameterType.eGenericType().ownedPathName != null) + name = String.join("#", name, p.eParameterType.eGenericType().ownedPathName.getText()); + else name = String.join("#", name, p.eParameterType.getText()); + } + } + } else { + name = name + "#0"; + } + return name; + } + + @Override + public int getStart() { + if (getContext().name != null) + return getContext().name.start.getStartIndex(); + else return super.getLine(); + } + + @Override + public int getStop() { + if (getContext().name != null) + return getContext().name.start.getStopIndex(); + else return super.getLine(); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitOperation(this); + } + + @Override + public List getTargets() { + return ISource.super.getTargets().stream() + .filter(e -> e instanceof Classifier || + e instanceof ImportedClass || + e instanceof ImportedDataType) + .collect(Collectors.toList()); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Package.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Package.java new file mode 100644 index 00000000..a40318b4 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Package.java @@ -0,0 +1,137 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EPackageContext; +import eu.modelwriter.core.alloyinecore.structure.base.INamespace; +import eu.modelwriter.core.alloyinecore.structure.base.Repository; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.antlr.v4.runtime.Token; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EPackage; + +public class Package extends NamedElement implements IVisibility, INamespace { + + public Package(EPackage ePackage, EPackageContext context) { + super(ePackage, context); + } + + @Override + public Token getToken() { + if (getContext().name != null) + return getContext().name.start; + else + return super.getToken(); + } + + @Override + public String getSegment() { + return getContext().name != null ? getContext().name.getText() : "Package"; + } + + @Override + public String getLabel() { + String name; + String nsURI; + if (getContext().name != null) { + name = getContext().name.getText(); + } else { + name = "Package"; + } + if (getContext().nsURI != null) { + nsURI = getContext().nsURI.getText(); + } else { + nsURI = ""; + } + return name + " : " + nsURI; + } + + @Override + public Visibility getVisibility() { + Visibility visibility = Visibility.PACKAGE; + if (getContext().visibility != null) { + String text = getContext().visibility.getText(); + try { + visibility = Visibility.valueOf(text.toUpperCase(java.util.Locale.ENGLISH)); + } catch (IllegalArgumentException e) { + visibility = Visibility.PACKAGE; + } + } + return visibility; + } + + protected String getName() { + if (this.getContext().name != null) + return "::" + this.getContext().name.getText(); + else + return super.getName(); + } + + @Override + public int getLine() { + if (getContext().name != null) + return getContext().name.start.getLine(); + else return super.getLine(); + } + + @Override + public int getStart() { + if (getContext().name != null) + return getContext().name.start.getStartIndex(); + else return super.getLine(); + } + + @Override + public int getStop() { + if (getContext().name != null) + return getContext().name.start.getStopIndex(); + else return super.getLine(); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitPackage(this); + } + + + @Override + public String getPath() { + if (getContext().nsURI != null) + return getContext().nsURI.getText().replace("'", ""); + else return null; + } + + @Override + public void loadNamespace(Repository repository) { + + } + + @Override + public String getKey() { + return getContext().name != null ? getContext().name.getText() + : getRootObject() instanceof ENamedElement + ? ((ENamedElement) getRootObject()).getName() : null; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Parameter.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Parameter.java new file mode 100644 index 00000000..cd923c4a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Parameter.java @@ -0,0 +1,107 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericElementTypeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EParameterContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.antlr.v4.runtime.Token; +import org.eclipse.emf.ecore.EParameter; + +public final class Parameter extends TypedElement { + public Parameter(EParameter eParameter, EParameterContext context) { + super(eParameter, context); + } + + @Override + public Token getToken() { + if (getContext().name != null) + return getContext().name.start; + else + return super.getToken(); + } + + @Override + public String getLabel() { + int start; + int stop; + if (getContext().name != null) { + start = getContext().name.start.getStartIndex(); + stop = getContext().name.stop.getStopIndex(); + } else { + start = getContext().start.getStartIndex(); + stop = getContext().start.getStopIndex(); + } + + return Element.getNormalizedText(getContext(), start, stop); + } + + @Override + public String getSuffix() { + String multiplicity = getContext().ownedMultiplicity != null ? TypedElement.getMultiplicity(getContext().ownedMultiplicity) : "[1]"; + if (getContext().eParameterType != null) { + EGenericElementTypeContext ctx = getContext().eParameterType; + String typeRefText = Element.getNormalizedText(ctx); + return ": " + typeRefText + "" + multiplicity; + } else { + return ": " + multiplicity; + } + } + + protected String getName(){ + if (this.getContext().name != null) + return "::" + this.getContext().name.getText(); + else + return super.getName(); + } + + @Override + public int getLine() { + if (getContext().name != null) + return getContext().name.start.getLine(); + else return super.getLine(); + } + + @Override + public int getStart() { + if (getContext().name != null) + return getContext().name.start.getStartIndex(); + else return super.getLine(); + } + + @Override + public int getStop() { + if (getContext().name != null) + return getContext().name.start.getStopIndex(); + else return super.getLine(); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitParameter(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/PostCondition.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/PostCondition.java new file mode 100644 index 00000000..4fc10b64 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/PostCondition.java @@ -0,0 +1,53 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.PostconditionContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +public final class PostCondition extends Constraint { + public PostCondition(PostconditionContext context) { + super(context); + } + + @Override + public String getLabel() { + int start; + int stop; + if (getContext().name != null) { + start = getContext().name.start.getStartIndex(); + stop = getContext().name.stop.getStopIndex(); + return Element.getNormalizedText(getContext(), start, stop); + } else { + return "postcondition"; + } + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitPostCondition(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/PreCondition.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/PreCondition.java new file mode 100644 index 00000000..51770e45 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/PreCondition.java @@ -0,0 +1,55 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.PreconditionContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; + +public final class PreCondition extends Constraint { + public PreCondition(PreconditionContext context) { + super(context); + } + + @Override + public String getLabel() { + int start; + int stop; + if (getContext().name != null) { + start = getContext().name.start.getStartIndex(); + stop = getContext().name.stop.getStopIndex(); + return Element.getNormalizedText(getContext(), start, stop); + } else { + return "precondition"; + } + + + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitPreCondition(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/PrimitiveType.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/PrimitiveType.java new file mode 100644 index 00000000..65e017e6 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/PrimitiveType.java @@ -0,0 +1,60 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EPrimitiveTypeContext; +import eu.modelwriter.core.alloyinecore.structure.base.Object; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.eclipse.emf.ecore.EGenericType; + +public final class PrimitiveType extends Object { + + public PrimitiveType(EGenericType eObject, EPrimitiveTypeContext context) { + super(eObject, context); + } + + public PrimitiveType(EPrimitiveTypeContext context) { + super(context); + } + + @Override + public String getLabel() { + String label = super.getLabel(); + switch (label){ + case "Boolean": return "EBoolean"; + case "Integer": return "EInt"; + case "String": return "EString"; + case "Real": return "EBigDecimal"; + case "UnlimitedNatural": return "EBigInteger"; + default: return label; + } + + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitPrimitiveType(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Reference.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Reference.java new file mode 100644 index 00000000..833d5534 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Reference.java @@ -0,0 +1,142 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EGenericElementTypeContext; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EReferenceContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.base.ISegment; +import eu.modelwriter.core.alloyinecore.structure.base.ISource; +import eu.modelwriter.core.alloyinecore.structure.base.ITarget; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedClass; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedDataType; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.antlr.v4.runtime.Token; +import org.eclipse.emf.ecore.EReference; + +import java.util.List; +import java.util.stream.Collectors; + +public final class Reference extends StructuralFeature implements IVisibility, ITarget, ISource { + public Reference(EReference eReference, EReferenceContext context) { + super(eReference, context); + } + + @Override + public Visibility getVisibility() { + Visibility visibility = Visibility.PACKAGE; + if (getContext().visibility != null) { + String text = getContext().visibility.getText(); + try { + visibility = Visibility.valueOf(text.toUpperCase(java.util.Locale.ENGLISH)); + } catch (IllegalArgumentException e) { + visibility = Visibility.PACKAGE; + } + } + return visibility; + } + + @Override + protected String getName() { + if (this.getContext().name != null) + return "::" + this.getContext().name.getText(); + else + return super.getName(); + } + + @Override + public Token getToken() { + if (getContext().name != null) + return getContext().name.start; + else + return super.getToken(); + } + + @Override + public String getLabel() { + int start; + int stop; + if (getContext().name != null) { + start = getContext().name.start.getStartIndex(); + stop = getContext().name.stop.getStopIndex(); + } else { + start = getContext().start.getStartIndex(); + stop = getContext().start.getStopIndex(); + } + return Element.getNormalizedText(getContext(), start, stop); + } + + @Override + public String getSuffix() { + String multiplicity = getContext().ownedMultiplicity != null ? TypedElement.getMultiplicity(getContext().ownedMultiplicity) : "[1]"; + if (getContext().eReferenceType != null) { + EGenericElementTypeContext ctx = getContext().eReferenceType; + String typeRefText = Element.getNormalizedText(ctx); + return ": " + typeRefText + "" + multiplicity; + } else { + return ": " + multiplicity; + } + } + + @Override + public int getLine() { + if (getContext().name != null) + return getContext().name.start.getLine(); + else return super.getLine(); + } + + @Override + public int getStart() { + if (getContext().name != null) + return getContext().name.start.getStartIndex(); + else return super.getLine(); + } + + @Override + public int getStop() { + if (getContext().name != null) + return getContext().name.start.getStopIndex(); + else return super.getLine(); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitReference(this); + } + + @Override + public String getSegment() { + return getContext().name != null ? getContext().name.getText() : ITarget.super.getSegment(); + } + + @Override + public List getTargets() { + return ISource.super.getTargets().stream() + .filter(e -> e instanceof Classifier || + e instanceof ImportedClass || + e instanceof ImportedDataType) + .collect(Collectors.toList()); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Relationship.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Relationship.java new file mode 100644 index 00000000..c6ba5a24 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Relationship.java @@ -0,0 +1,61 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + + +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import org.antlr.v4.runtime.ParserRuleContext; + +/** + * A relationship represents a relationship between source and target elements + * @param source or owner element + * @param target element + * @param context + */ +public abstract class Relationship extends Element { + + private final S source; + private T target; + + public Relationship(S source, C context) { + super(context); + this.source = source; + } + + public Relationship(S source, T target, C context) { + super(context); + this.source = source; + this.target = target; + } + + @Override + public String getLabel() { + return Element.getNormalizedText(getContext()); + } + + public void setTarget(T target) { + this.target = target; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/RootPackage.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/RootPackage.java new file mode 100644 index 00000000..4f1b128b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/RootPackage.java @@ -0,0 +1,51 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EPackageContext; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.eclipse.emf.ecore.EPackage; + +public final class RootPackage extends Package { + + public RootPackage(EPackage ePackage, EPackageContext context) { + super(ePackage, context); + } + + @Override + public String getSegment() { + return ""; + } + + @Override + public String getKey() { + return getContext().name != null ? getContext().name.getText() : "Root"; + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitRootPackage(this); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/StructuralFeature.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/StructuralFeature.java new file mode 100644 index 00000000..51e02373 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/StructuralFeature.java @@ -0,0 +1,35 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.eclipse.emf.ecore.EStructuralFeature; + +public abstract class StructuralFeature extends TypedElement{ + + public StructuralFeature(EStructuralFeature eStructuralFeature, C context) { + super(eStructuralFeature, context); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/TypeParameter.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/TypeParameter.java new file mode 100644 index 00000000..4cd2e369 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/TypeParameter.java @@ -0,0 +1,82 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.ETypeParameterContext; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.base.ISegment; +import eu.modelwriter.core.alloyinecore.structure.base.ISource; +import eu.modelwriter.core.alloyinecore.structure.base.ITarget; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedClass; +import eu.modelwriter.core.alloyinecore.visitor.IVisitor; +import org.antlr.v4.runtime.Token; +import org.eclipse.emf.ecore.ETypeParameter; + +import java.util.List; +import java.util.stream.Collectors; + +public class TypeParameter extends NamedElement implements ITarget, ISource { + public TypeParameter(ETypeParameter eTypeParameter, ETypeParameterContext context) { + super(eTypeParameter, context); + } + + @Override + public String getSegment() { + return getContext().start != null ? getContext().start.getText() : ITarget.super.getSegment(); + } + + @Override + public Token getToken() { + if (getContext().name != null) + return getContext().name.start; + else + return super.getToken(); + } + + @Override + public String getLabel() { + return Element.getNormalizedText(getContext()); + } + + protected String getName() { + if (this.getContext().name != null) + return "<" + this.getContext().name.getText() + ">"; + else + return super.getName(); + } + + @Override + public T accept(IVisitor visitor) { + return visitor.visitTypeParameter(this); + } + + @Override + public List getTargets() { + return ISource.super.getTargets().stream() + .filter(e -> e instanceof Classifier || + e instanceof ImportedClass) + .collect(Collectors.toList()); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/TypedElement.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/TypedElement.java new file mode 100644 index 00000000..d35ebe6f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/TypedElement.java @@ -0,0 +1,92 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser.EMultiplicityContext; +import org.antlr.v4.runtime.ParserRuleContext; +import org.eclipse.emf.ecore.ETypedElement; + +import java.util.Arrays; + +public abstract class TypedElement extends NamedElement { + + public TypedElement(ETypedElement eTypedElement, C context) { + super(eTypedElement, context); + } + + public TypedElement(C context) { + super(context); + } + + static String getMultiplicity(EMultiplicityContext ctx) { + int l = 1; + int u = 1; + boolean nullable = false; + + if (ctx.stringBound != null) { + switch (ctx.stringBound.getText()) { + case "*": l = 0; u = -1; break; + case "+": l = 1; u = -1; break; + case "?": l = 0; u = 1; break; + default: break; + } + } else { + try { + if (ctx.lowerBound != null) l = Integer.valueOf(ctx.lowerBound.getText()); + }catch (NumberFormatException ex){ + System.out.println(Arrays.toString(ex.getStackTrace())); + } + if (ctx.upperBound != null) { + if (ctx.upperBound.getText().equals("*")) u = -1; + else + try { u = Integer.valueOf(ctx.upperBound.getText());} + catch (NumberFormatException ex){ + System.out.println(Arrays.toString(ex.getStackTrace())); + } + } else { u = l;} + } + + if ((u > 1 || u == -1) && ctx.nullable != null ) + nullable = true; + + String multiplicity; + if (l==0 && u==-1) { + multiplicity = "[*"+ (nullable ? "|?]" : "]"); + } else if (l==1 && u==-1) { + multiplicity = "[+"+ (nullable ? "|?]" : "]"); + } else if (l==0 && u==1) { + multiplicity = "[?]"; + } else if (l==1 && u==1) + multiplicity = "[1]"; + else if (l==u) { + multiplicity = "[" + l + (nullable ? "|?]" : "]"); + } else if (u == -1) { + multiplicity = "[" + l + "..*" + (nullable ? "|?]" : "]"); + } else { + multiplicity = "[" + l + ".." + u + (nullable ? "|?]" : "]"); + } + return multiplicity; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Visibility.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Visibility.java new file mode 100644 index 00000000..254e08a7 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/structure/model/Visibility.java @@ -0,0 +1,49 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.structure.model; + +public enum Visibility { + PACKAGE("~"), + PUBLIC("+"), + PRIVATE("-"), + PROTECTED("#"); + + private final String value; + + /** + * @param value + */ + Visibility(final String value) { + this.value = value; + } + + /* (non-Javadoc) + * @see java.lang.Enum#toString() + */ + @Override + public String toString() { + return value; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/translator/EcoreInstanceTranslator.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/translator/EcoreInstanceTranslator.java new file mode 100644 index 00000000..7cf5ef62 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/translator/EcoreInstanceTranslator.java @@ -0,0 +1,296 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.translator; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EEnumLiteral; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.impl.EPackageImpl; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.stringtemplate.v4.ST; +import org.stringtemplate.v4.STGroupFile; + +import eu.modelwriter.core.alloyinecore.structure.base.Repository; + +public class EcoreInstanceTranslator { + + private STGroupFile templateGroup; + private final Map imports = new HashMap<>(); + private EObject root; + private Repository repository = new Repository(); + + public EcoreInstanceTranslator() { + templateGroup = new STGroupFile("EcoreInstance.stg"); + } + + public EcoreInstanceTranslator(Repository repository) { + this(); + this.repository = repository; + } + + public String translate(String pathToFile) throws IOException { + Resource resource = repository.loadResource(pathToFile); + if (resource != null && !resource.getContents().isEmpty()) + return translate(resource.getContents().get(0)); + return ""; + } + + public String translate(EObject root) { + this.root = root; + StringBuilder builder = new StringBuilder(); + builder.append(getModelToString(root)); + builder.append(eObjectToString(root)); + builder.insert(0, importsToString()); + return builder.toString(); + } + + private String importsToString() { + StringBuilder importsBuilder = new StringBuilder(); + imports.entrySet().forEach(entry -> { + ST template = templateGroup.getInstanceOf("load"); + template.add("name", entry.getValue()); + template.add("path", entry.getKey()); + importsBuilder.append(template.render().trim()); + importsBuilder.append("\n"); + }); + if (importsBuilder.length() > 0) + importsBuilder.append("\n"); + return importsBuilder.toString(); + } + + private String getModelToString(EObject eObject) { + ST template = templateGroup.getInstanceOf("model"); + EPackageImpl eContainer = (EPackageImpl) eObject.eClass().eContainer(); + template.add("name", eContainer.getName()); + template.add("nsPrefix", eContainer.getNsPrefix()); + template.add("nsURI", eContainer.getNsURI()); + template.add("path", getLocation(eContainer.eResource().getURI())); + return template.render(); + } + + private String eObjectToString(EObject eObject) { + ST template = templateGroup.getInstanceOf("eObject"); + template.add("className", getClassName(eObject)); + EClass eClass = eObject.eClass(); + EAttribute idAttr = eClass.getEIDAttribute(); + if (idAttr != null) { + Object eGet = eObject.eGet(idAttr); + template.add("id", objectToString(eGet)); + } + // Append Attributes + for (EAttribute eAttribute : eClass.getEAllAttributes()) { + Object value = eObject.eGet(eAttribute); + if (value != null && !eAttribute.isID()) + template.add("content", attrToString(eAttribute, value)); + } + // Append References + for (EReference eReference : eClass.getEAllReferences()) { + Object value = eObject.eGet(eReference); + if (value != null) { + template.add("content", eReference.isContainment() ? conRefToString(eReference, value) + : refToString(eReference, value)); + } + } + return template.render(); + } + + /** + * Converts containment reference to string + * + * @param eReference + * @param value + * @return + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + private String conRefToString(EReference eReference, Object value) { + if (value instanceof EList && ((EList) value).isEmpty()) + return null; + ST template = templateGroup.getInstanceOf("containmentRef"); + template.add("name", eReference.getName()); + if (value instanceof EList) { + EList list = (EList) value; + list.forEach(eObj -> { + template.add("content", eObjectToString(eObj)); + }); + } else if (value instanceof EObject) { + template.add("content", eObjectToString((EObject) value)); + } + return template.render(); + } + + @SuppressWarnings("rawtypes") + private String attrToString(EAttribute attr, Object value) { + if (value instanceof EList && ((EList) value).isEmpty()) + return null; + return attr.getName() + ": " + objectToString(value); + } + + /** + * Converts non-containment reference to string + * + * @param ref + * @param value + * @return + */ + @SuppressWarnings("rawtypes") + private String refToString(EReference ref, Object value) { + if (value instanceof EList && ((EList) value).isEmpty()) + return null; + return ref.getName() + ": " + objectToString(value); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private String objectToString(Object obj) { + if (obj instanceof EList) { + EList list = (EList) obj; + StringBuilder builder = new StringBuilder(); + if (list.size() > 1) + builder.append("["); + for (Object eObj : list) { + builder.append(objectToString(eObj)); + builder.append(", "); + } + if (builder.length() > 1) + builder.delete(builder.length() - 2, builder.length()); + if (list.size() > 1) + builder.append("]"); + return builder.toString(); + } + if (obj instanceof Number || obj instanceof Boolean || obj instanceof EEnumLiteral) + return obj.toString(); + + if (obj instanceof Character) + return "\'" + obj.toString() + "\'"; + + if (obj instanceof EObject) { + return getEObjectRefString((EObject) obj); + } + // Return as string + return "\"" + obj.toString().replaceAll("\"", "\\\\\"").replaceAll("\'", "\\\\\'") + "\""; + } + + /** + * Get DynamicEObjectImpl's EClass name with package information + * + * @param eObject + * @return + */ + private String getClassName(EObject eObject) { + return getPackageName(root.eClass(), eObject.eClass()) + getURIString(eObject.eClass()); + } + + /** + * Get an EObject's path with package information + * + * @param eObject + * @return + */ + private String getEObjectRefString(EObject eObject) { + return getPackageName(root, eObject) + getURIString(eObject); + } + + private String getURIString(EObject eObject) { + return EcoreUtil.getURI(eObject).fragment().replaceAll("//", "").replaceAll("@", "") + .replaceAll("/", "::"); + } + + /** + * Returns root package name of given EObject. If EObject directly inside of root returns empty + * string. Also if given EObject is part of another EMF file imports that file and returns + * import's name. + * + * @param root + * @param eObject + * @return + */ + private String getPackageName(EObject root, EObject eObject) { + URI eObjectURI = EcoreUtil.getURI(eObject); + URI rootURI = EcoreUtil.getURI(root); + + if (!rootURI.trimFragment().equals(eObjectURI.trimFragment())) { + String fileLocation = getLocation(eObject); + // Check if its already imported + String importName = imports.get(fileLocation); + if (importName == null) { + importName = handleImportName(eObjectURI.trimFileExtension().lastSegment()); + imports.put(fileLocation, importName); + } + return importName + "::"; + } + return ""; + + } + + /** + * Configures import names. If given name already in imports map, adds numbers as suffix until the + * name becomes unique + * + * @param baseName + * @return + */ + private String handleImportName(String baseName) { + if (imports.values().contains(baseName)) { + // Gotta find new name for this + int suffix = 1; + while (imports.get(baseName + ++suffix) != null); + return baseName + suffix; + } + return baseName; + } + + /** + * Get EObject's file location relative to root object. + * + * @param eObject + * @return + */ + private String getLocation(EObject eObject) { + return getLocation(EcoreUtil.getURI(eObject)); + } + + /** + * Get EObject's file location relative to root object. + * + * @param uri + * @return + */ + private String getLocation(URI uri) { + URI rootURI = EcoreUtil.getURI(root).trimFragment(); + URI deresolvedUri = uri.trimFragment().deresolve(rootURI, true, true, true); + if (deresolvedUri.isFile()) + return deresolvedUri.toFileString(); + else + return deresolvedUri.toString(); + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/translator/EcoreTranslator.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/translator/EcoreTranslator.java new file mode 100644 index 00000000..c430484e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/translator/EcoreTranslator.java @@ -0,0 +1,619 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.translator; + +import eu.modelwriter.core.alloyinecore.internal.AIEConstants; +import eu.modelwriter.core.alloyinecore.internal.AnnotationSources; +import eu.modelwriter.core.alloyinecore.structure.base.Repository; +import org.eclipse.emf.common.util.EMap; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.*; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.stringtemplate.v4.ST; +import org.stringtemplate.v4.STGroup; +import org.stringtemplate.v4.STGroupFile; + +import java.io.IOException; +import java.util.*; +import java.util.Map.Entry; + +public class EcoreTranslator implements AnnotationSources { + + private final Map imports = new HashMap<>(); + private final Map primitives = new HashMap<>(); + private final STGroup templateGroup; + + private EModelElement root; + + private Repository repository = new Repository(); + + public EcoreTranslator() { + templateGroup = new STGroupFile("AlloyInEcore.stg"); + primitives.put("Ecore::EString", "String"); + primitives.put("Ecore::EBoolean", "Boolean"); + primitives.put("Ecore::EBigDecimal", "Real"); + primitives.put("Ecore::EInt", "Integer"); + primitives.put("Ecore::EBigInteger", "UnlimitedNatural"); + } + + public EcoreTranslator(Repository repository) { + this(); + this.repository = repository; + } + + public String translate(String pathToEcore) throws IOException { + if (repository.loadResource(pathToEcore) != null) { + Resource resource = repository.loadResource(pathToEcore); + assert resource != null; + EObject eObject = resource.getEObject("/"); + if ( eObject instanceof EModelElement) + return translate((EModelElement)eObject); + } + return null; + } + + public String translate(EModelElement element) { + if (element.getEAnnotation(AnnotationSources.SOURCE) != null) { + EAnnotation sourceAnno = element.getEAnnotation(AnnotationSources.SOURCE); + String source = sourceAnno.getDetails().get(AIEConstants.SOURCE.toString()); + if (source != null) + return source; + } + // If there is no source annotation, translate it. + imports.clear(); + StringBuilder builder = new StringBuilder(); + if (element != null) { + root = element; + collectImports(element); + builder.append(eObjectToString(element)); + builder.insert(0, importsToString()); + builder.insert(0, modelToString(element)); + } + return builder.toString(); + } + + private void collectImports(EModelElement element) { + AnnotationSources.getImports(element).forEach(anno -> { + if (!anno.getDetails().isEmpty()) { + String name = anno.getDetails().get(0).getKey(); + String ns = anno.getDetails().get(0).getValue(); + imports.put(ns, name); + } + }); + } + + private String eObjectToString(EObject eObject) { + if (eObject instanceof EPackage) + return packageToString((EPackage) eObject); + if (eObject instanceof EClassifier) + return classifierToString((EClassifier) eObject); + if (eObject instanceof EAttribute) + return attrToString((EAttribute) eObject); + if (eObject instanceof EReference) + return referenceToString((EReference) eObject); + if (eObject instanceof EOperation) + return operationToString((EOperation) eObject); + return ""; + } + + private String classifierToString(EClassifier eClassifier) { + if (eClassifier instanceof EEnum) + return enumToString((EEnum) eClassifier); + if (eClassifier instanceof EClass) + return classToString((EClass) eClassifier); + if (eClassifier instanceof EDataType) + return datatypeToString((EDataType) eClassifier); + return ""; + } + + private String modelToString(EModelElement element) { + ST template = templateGroup.getInstanceOf("model"); + EAnnotation options = element.getEAnnotation(AnnotationSources.OPTIONS); + if (options != null && !options.getDetails().isEmpty()) { + options.getDetails().forEach(entry -> template.add("option", entry.getKey() + " : " + entry.getValue())); + } + EAnnotation model = element.getEAnnotation(AnnotationSources.MODULE); + if (model != null && model.getDetails().get("name") != null) { + template.add("modelName", model.getDetails().get("name")); + } + return template.render(); + } + + private void addAnnotations(ST template, EModelElement element) { + AnnotationSources.getAnnotations(element).forEach(anno -> template.add("subElement", annoToString(anno).trim())); + } + + private Object invariantToString(EAnnotation invAnno) { + ST template = templateGroup.getInstanceOf("inv"); + EMap details = invAnno.getDetails(); + template.add("isCallable", Boolean.parseBoolean(AIEConstants.CALLABLE.toString())); + template.add("name", details.get(AIEConstants.NAME.toString())); + template.add("message", details.get(AIEConstants.MESSAGE.toString())); + template.add("formula", details.get(AIEConstants.FORMULA.toString())); + return template.render().trim(); + } + + private String packageToString(EPackage ePackage) { + ST template = templateGroup.getInstanceOf("package"); + template.add("visibility", getVisibility(ePackage)); + template.add("name", ePackage.getName()); + template.add("prefix", ePackage.getNsPrefix()); + template.add("namespace", ePackage.getNsURI()); + for (EClassifier eClassifier : ePackage.getEClassifiers()) { + template.add("subElement", classifierToString(eClassifier)); + } + for (EPackage subPackage : ePackage.getESubpackages()) { + template.add("subElement", packageToString(subPackage)); + } + AnnotationSources.getInvariants(ePackage).forEach(invAnno -> { + template.add("subElement", invariantToString(invAnno)); + }); + addAnnotations(template, ePackage); + return template.render().trim(); + } + + private String datatypeToString(EDataType eDataType) { + ST template = templateGroup.getInstanceOf("datatype"); + template.add("visibility", getVisibility(eDataType)); + template.add("isPrimitive", AnnotationSources.isPrimitive(eDataType)); + // template.add("nullable", AnnotationSources.isNullable(eDataType)); + template.add("name", eDataType.getName()); + for (ETypeParameter typeParameter : eDataType.getETypeParameters()) { + template.add("typeParameter", typeParameterToString(typeParameter)); + } + template.add("instanceName", eDataType.getInstanceClassName()); + if (!eDataType.isSerializable()) + template.add("isSerializable", AIEConstants.NOT_SERIALIZABLE.toString()); + AnnotationSources.getInvariants(eDataType).forEach(invAnno -> { + template.add("subElement", invariantToString(invAnno)); + }); + addAnnotations(template, eDataType); + return template.render().trim(); + } + + private String enumToString(EEnum eEnum) { + ST template = templateGroup.getInstanceOf("enum"); + template.add("visibility", getVisibility(eEnum)); + template.add("name", eEnum.getName()); + for (ETypeParameter typeParameter : eEnum.getETypeParameters()) { + template.add("typeParameter", typeParameterToString(typeParameter)); + } + template.add("instanceName", eEnum.getInstanceClassName()); + if (!eEnum.isSerializable()) + template.add("isSerializable", AIEConstants.NOT_SERIALIZABLE.toString()); + AnnotationSources.getInvariants(eEnum).forEach(invAnno -> { + template.add("subElement", invariantToString(invAnno)); + }); + for (EEnumLiteral eEnumLiteral : eEnum.getELiterals()) { + template.add("subElement", enumLiteralToString(eEnumLiteral)); + } + addAnnotations(template, eEnum); + return template.render().trim(); + } + + private String enumLiteralToString(EEnumLiteral literal) { + ST template = templateGroup.getInstanceOf("enumLiteral"); + template.add("name", literal.getName()); + template.add("enumValue", literal.getValue()); + addAnnotations(template, literal); + return template.render().trim(); + } + + private String classToString(EClass eClass) { + ST template = templateGroup.getInstanceOf("class"); + template.add("visibility", getVisibility(eClass)); + template.add("isAbstract", eClass.isAbstract()); + template.add("isInterface", eClass.isInterface()); + template.add("name", eClass.getName()); + for (ETypeParameter typeParameter : eClass.getETypeParameters()) { + template.add("typeParameter", typeParameterToString(typeParameter)); + } + template.add("instanceName", eClass.getInstanceClassName()); + for (EGenericType genericSuperClass : eClass.getEGenericSuperTypes()) { + template.add("superClass", genericTypeToString(genericSuperClass)); + } + eClass.getEAttributes().forEach(attr -> template.add("subElement", attrToString(attr))); + eClass.getEReferences().forEach(eRef -> template.add("subElement", referenceToString(eRef))); + eClass.getEOperations().forEach(op -> template.add("subElement", operationToString(op))); + AnnotationSources.getInvariants(eClass).forEach(invAnno -> template.add("subElement", invariantToString(invAnno))); + addAnnotations(template, eClass); + return template.render().trim(); + } + + private Object typeParameterToString(ETypeParameter typeParameter) { + ST template = templateGroup.getInstanceOf("typeParameter"); + template.add("name", typeParameter.getName()); + for (EGenericType genericType : typeParameter.getEBounds()) { + template.add("eBound", genericTypeToString(genericType)); + } + return template.render().trim(); + } + + private String genericTypeToString(EGenericType genericType) { + ST template = templateGroup.getInstanceOf("genericType"); + + if (genericType.getEClassifier() != null) { + template.add("classifier", getTypeName(genericType, genericType.getEClassifier())); + } else if (genericType.getETypeParameter() != null) { + template.add("typeParameter", genericType.getETypeParameter().getName()); + } else { + if (genericType.getEUpperBound() != null) { + template.add("upperBound", genericTypeToString(genericType.getEUpperBound())); + } else if (genericType.getELowerBound() != null) { + template.add("lowerBound", genericTypeToString(genericType.getELowerBound())); + } + } + for (EGenericType eTypeArgument : genericType.getETypeArguments()) { + template.add("typeArgument", genericTypeToString(eTypeArgument)); + } + + return template.render().trim(); + } + + private String operationToString(EOperation op) { + ST template = templateGroup.getInstanceOf("op"); + template.add("visibility", getVisibility(op)); + template.add("isStatic", AnnotationSources.isStatic(op)); + // template.add("nullable", AnnotationSources.isNullable(op)); + for (ETypeParameter typeParameter : op.getETypeParameters()) { + template.add("typeParameter", typeParameterToString(typeParameter)); + } + template.add("name", op.getName()); + if (op.getEGenericType() != null) { + template.add("type", genericTypeToString(op.getEGenericType())); + template.add("multiplicity", getMultiplicity(op)); + template.add("qualifier", getQualifiers(op)); + } + op.getEGenericExceptions().forEach(eGenericException -> template.add("throws", genericTypeToString(eGenericException))); + op.getEParameters().forEach(param -> template.add("params", paramToString(param))); + + AnnotationSources.getPreconditions(op).forEach(anno -> template.add("subElement", preconditionToString(anno))); + AnnotationSources.getBodyExpressions(op).forEach(anno -> template.add("subElement", bodyToString(anno))); + AnnotationSources.getPostconditions(op).forEach(anno -> template.add("subElement", postconditionToString(anno))); + + addAnnotations(template, op); + return template.render().trim(); + } + + private String paramToString(EParameter param) { + ST template = templateGroup.getInstanceOf("opParameter"); + // template.add("nullable", AnnotationSources.isNullable(param)); + template.add("name", param.getName()); + if (param.getEGenericType() != null) { + template.add("type", genericTypeToString(param.getEGenericType())); + template.add("multiplicity", getMultiplicity(param)); + } + template.add("qualifier", getQualifiers(param)); + addAnnotations(template, param); + return template.render(); + } + + private String postconditionToString(EAnnotation eAnnotation) { + ST template = templateGroup.getInstanceOf("postcondition"); + EMap details = eAnnotation.getDetails(); + template.add("name", details.get(AIEConstants.NAME.toString())); + template.add("message", details.get(AIEConstants.MESSAGE.toString())); + template.add("formula", details.get(AIEConstants.FORMULA.toString())); + return template.render().trim(); + } + + private Object bodyToString(EAnnotation eAnnotation) { + ST template = templateGroup.getInstanceOf("body"); + EMap details = eAnnotation.getDetails(); + template.add("name", details.get(AIEConstants.NAME.toString())); + template.add("expression", details.get(AIEConstants.EXPRESSION.toString())); + return template.render().replace(" ", ""); + } + + private String preconditionToString(EAnnotation invAnno) { + ST template = templateGroup.getInstanceOf("precondition"); + EMap details = invAnno.getDetails(); + template.add("name", details.get(AIEConstants.NAME.toString())); + template.add("message", details.get(AIEConstants.MESSAGE.toString())); + template.add("formula", details.get(AIEConstants.FORMULA.toString())); + return template.render().trim(); + } + + private String referenceToString(EReference eRef) { + ST template = templateGroup.getInstanceOf("ref"); + template.add("visibility", getVisibility(eRef)); + template.add("isStatic", AnnotationSources.isStatic(eRef)); + template.add("transient", eRef.isTransient()); + template.add("volatile", eRef.isVolatile()); + template.add("model", eRef.getEAnnotation(AnnotationSources.MODEL) != null); + template.add("ghost", eRef.getEAnnotation(AnnotationSources.GHOST) != null); + // template.add("nullable", AnnotationSources.isNullable(eRef)); + template.add("readonly", !eRef.isChangeable()); + template.add("name", eRef.getName()); + if (eRef.getEOpposite() != null) + template.add("opposite", eRef.getEOpposite().getName()); + template.add("defaultValue", eRef.getDefaultValueLiteral()); + if (eRef.getEGenericType() != null) { + template.add("type", genericTypeToString(eRef.getEGenericType())); + template.add("multiplicity", getMultiplicity(eRef)); + } + template.add("qualifier", getQualifiers(eRef)); + addAnnotations(template, eRef); + addReferenceKeys(template, eRef); + addSFExpressions(template, eRef); + return template.render().trim(); + } + + private void addReferenceKeys(ST refTemplate, EReference eRef) { + if (eRef.getEKeys().isEmpty()) + return; + ST template = templateGroup.getInstanceOf("referenceKey"); + eRef.getEKeys().forEach(attr -> template.add("referredKeys", attr.getName())); + refTemplate.add("subElement", template.render()); + } + + private void addSFExpressions(ST template, EStructuralFeature sf) { + EAnnotation derivationAnno = sf.getEAnnotation(AnnotationSources.DERIVATION); + if (derivationAnno != null && !derivationAnno.getDetails().isEmpty()) + template.add("subElement", derivationToString(derivationAnno)); + else { + EAnnotation initialAnno = sf.getEAnnotation(AnnotationSources.INITIAL); + if (initialAnno != null && !initialAnno.getDetails().isEmpty()) + template.add("subElement", initialToString(initialAnno)); + } + } + + private Object initialToString(EAnnotation eAnnotation) { + ST template = templateGroup.getInstanceOf("initial"); + template.add("name", eAnnotation.getDetails().get("name")); + template.add("expression", eAnnotation.getDetails().get("expression")); + return template.render(); + } + + private String derivationToString(EAnnotation eAnnotation) { + ST template = templateGroup.getInstanceOf("derivation"); + template.add("name", eAnnotation.getDetails().get("name")); + template.add("expression", eAnnotation.getDetails().get("expression")); + return template.render(); + } + + private String attrToString(EAttribute eAttr) { + ST template = templateGroup.getInstanceOf("attr"); + template.add("visibility", getVisibility(eAttr)); + template.add("isStatic", AnnotationSources.isStatic(eAttr)); + template.add("transient", eAttr.isTransient()); + template.add("volatile", eAttr.isVolatile()); + template.add("model", eAttr.getEAnnotation(AnnotationSources.MODEL) != null); + template.add("ghost", eAttr.getEAnnotation(AnnotationSources.GHOST) != null); + // template.add("nullable", AnnotationSources.isNullable(eAttr)); + template.add("readonly", !eAttr.isChangeable()); + template.add("name", eAttr.getName()); + if (eAttr.getEGenericType() != null) { + template.add("type", genericTypeToString(eAttr.getEGenericType())); + template.add("multiplicity", getMultiplicity(eAttr)); + template.add("defaultValue", eAttr.getDefaultValueLiteral()); + } + template.add("qualifier", getQualifiers(eAttr)); + addAnnotations(template, eAttr); + addSFExpressions(template, eAttr); + return template.render().trim(); + } + + private String annoToString(EAnnotation eAnnotation) { + ST template = templateGroup.getInstanceOf("anno"); + template.add("name", eAnnotation.getSource()); + eAnnotation.getDetails().forEach(entry -> template.add("detail", edetailToString(entry.getKey(), entry.getValue()))); + eAnnotation.getReferences().forEach(ref -> { + if (!(ref instanceof EAnnotation)) + template.add("subElement", "reference " + getQualifiedName(eAnnotation, ref) + ";"); + }); + eAnnotation.getContents().forEach(eObject -> { + String subElement = eObjectToString(eObject); + template.add("subElement", subElement); + }); + addAnnotations(template, eAnnotation); + return template.render().trim(); + } + + + private String edetailToString(String name, String value) { + ST template = templateGroup.getInstanceOf("edetail"); + template.add("name", name); + template.add("val", value); + return template.render(); + } + + private String importsToString() { + StringBuilder importsBuilder = new StringBuilder(); + imports.entrySet().forEach(entry -> { + ST template = templateGroup.getInstanceOf("load"); + template.add("namespace", entry.getKey()); + template.add("name", entry.getValue()); + importsBuilder.append(template.render().trim()); + importsBuilder.append("\n"); + }); + if (importsBuilder.length() > 0) + importsBuilder.append("\n"); + return importsBuilder.toString(); + } + + private boolean isInSamePackage(EObject obj1, EObject obj2) { + EPackage pac1 = getContainerPackage(obj1); + EPackage pac2 = getContainerPackage(obj2); + return pac1 != null && pac2 != null && pac1.equals(pac2); + } + + private EPackage getContainerPackage(EObject obj) { + try { + EObject container = obj; + while (container.eContainer() != null && !(container instanceof EPackage)) { + container = container.eContainer(); + } + return (EPackage) container; + } catch (ClassCastException e) { + return null; + } + } + + private String getQualifiedName(EObject rel, EObject eObject) { + if (eObject == null && !(eObject instanceof ENamedElement)) // No annotation allowed + return ""; + + if (!root.equals(EcoreUtil.getRootContainer(eObject, true))) + return getImportedQualifiedName(eObject); + + // Annotation references must be fully qualified + boolean relative = isInSamePackage(rel, eObject) && !(rel instanceof EAnnotation); + ENamedElement element = (ENamedElement) eObject; + EPackage relPackage = getContainerPackage(rel); + + String qualifiedName; + ENamedElement container = (ENamedElement) eObject.eContainer(); + List containerNames = new ArrayList<>(); + + while (container != null) { + if (relative && container.equals(relPackage)) + break; + containerNames.add(container.getName()); + container = (ENamedElement) container.eContainer(); + } + + Collections.reverse(containerNames); + qualifiedName = String.join(AIEConstants.SEPARATOR, containerNames); + + String lastSeparator = getSeparator(eObject); + qualifiedName += + qualifiedName.isEmpty() ? element.getName() : lastSeparator + element.getName(); + + return qualifiedName; + } + + private String getImportedQualifiedName(EObject eObject) { + // Use file name + String packageName = imports.computeIfAbsent(getLocation(eObject), k -> EcoreUtil.getURI(eObject).trimFileExtension().lastSegment()); + return packageName + AIEConstants.SEPARATOR + + EcoreUtil.getURI(eObject).fragment().replace("//", "") + .replaceAll("/([^/]*)$", getSeparator(eObject) + "$1") + .replaceAll("/", AIEConstants.SEPARATOR); + } + + private String getSeparator(EObject eObject) { + // if (eObject instanceof EStructuralFeature) + // return AIEConstants.SEPARATOR; + // if (eObject instanceof EOperation) + // return AIEConstants.SEPARATOR; + // if (eObject instanceof EClassifier) + // return AIEConstants.SEPARATOR; + return AIEConstants.SEPARATOR; + } + + private String getLocation(EObject eObject) { + URI rootURI = EcoreUtil.getURI(root).trimFragment(); + URI uri = EcoreUtil.getURI(eObject).trimFragment().deresolve(rootURI, true, true, true); + if (uri.isFile()) + return uri.toFileString(); + else + return uri.toString(); + } + + private String getTypeName(EObject rel, EClassifier eClassifier) { + String type = getQualifiedName(rel, eClassifier); + if (type != null) { + for (Entry e : primitives.entrySet()) { + if (type.equals(e.getKey())) { + return e.getValue(); + } + } + } + return type; + } + + private String getMultiplicity(ETypedElement eTypedElement) { + int l = eTypedElement.getLowerBound(); + int u = eTypedElement.getUpperBound(); + String mul = null; + if (l == 0 && u == 1) + mul = "?"; + else if (l == 0 && u == -1) + mul = "*"; + else if (l == 1 && u == -1) + mul = "+"; + else if (l == u && l != 1) + mul = l + ""; + else if (!(l == 1 && u == 1)) + mul = l + ".." + u; + + if (mul != null && AnnotationSources.isNullable(eTypedElement)) + mul += "|?"; + + // If EAttribure is ID, its bounds must be 1 + if (eTypedElement instanceof EAttribute && ((EAttribute) eTypedElement).isID()) { + // Since 1 is default multiplicity, return empty + return "1"; + } + + return mul != null ? mul.replace("-1", "*") : mul; + } + + private String getVisibility(ENamedElement element) { + String visibility = ""; + EAnnotation visibilityAnno = element.getEAnnotation(VISIBILITY); + if (visibilityAnno != null && !visibilityAnno.getDetails().isEmpty()) + visibility = visibilityAnno.getDetails().get(AIEConstants.VISIBILITY.toString()); + return visibility; + } + + private String getQualifiers(ETypedElement element) { + StringBuilder builder = new StringBuilder(); + if (!element.isUnique() && (element.getUpperBound() > 1 || element.getUpperBound() == -1)) + builder.append(AIEConstants.NOT_UNIQUE + " "); + if (element.isOrdered() && (element.getUpperBound() > 1 || element.getUpperBound() == -1)) + builder.append(AIEConstants.ORDERED + " "); + + if (element instanceof EStructuralFeature) + appendSFQualifiers(builder, (EStructuralFeature) element); + + // Wrap with curly bracket + if (builder.length() > 0) { + builder.insert(0, " { "); + builder.append("}"); + } + return builder.toString(); + } + + private void appendSFQualifiers(StringBuilder builder, EStructuralFeature eStructuralFeature) { + if (eStructuralFeature.isDerived()) + builder.append(AIEConstants.DERIVED + " "); + if (eStructuralFeature.isUnsettable()) + builder.append(AIEConstants.UNSETTABLE + " "); + + if (eStructuralFeature instanceof EAttribute && ((EAttribute) eStructuralFeature).isID()) + builder.append(AIEConstants.ID + " "); + + if (eStructuralFeature instanceof EReference) { + if (!((EReference) eStructuralFeature).isResolveProxies()) + builder.append(AIEConstants.NOT_RESOLVE + " "); + if (((EReference) eStructuralFeature).isContainment()) + builder.append(AIEConstants.COMPOSES + " "); + } + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/typechecking/JavaInterfaceGenerator.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/typechecking/JavaInterfaceGenerator.java new file mode 100644 index 00000000..30dec592 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/typechecking/JavaInterfaceGenerator.java @@ -0,0 +1,399 @@ +package eu.modelwriter.core.alloyinecore.typechecking; + +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.base.ITarget; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedClass; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedDataType; +import eu.modelwriter.core.alloyinecore.structure.imports.ImportedPackage; +import eu.modelwriter.core.alloyinecore.structure.model.*; +import eu.modelwriter.core.alloyinecore.structure.model.Class; +import eu.modelwriter.core.alloyinecore.structure.model.Package; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.Token; + +import javax.tools.Diagnostic; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.stream.Collectors; + +public class JavaInterfaceGenerator { + + private JavaInterfaceGenerator importGenerator = null; + + private Set generatedFiles = new HashSet<>(); + private Set traces = new HashSet<>(); + private String currentFileName = ""; + private String outDir; + private int currentLineNumber = 0; + private boolean save; + private String currentPackageName; + + public JavaInterfaceGenerator(String outDir, boolean save) { + this.outDir = outDir; + this.save = save; + } + + public JavaInterfaceGenerator getImportGenerator() { + if (importGenerator == null) + importGenerator = new JavaInterfaceGenerator(outDir, save); + importGenerator.clearTraces(); + return importGenerator; + } + + public Set getGeneratedFiles() { + return generatedFiles; + } + + public Set getTraces() { + return traces; + } + + public Set findTokens(Diagnostic diagnostic) { + for (Trace trace : getTraces()) { + if (trace.overlaps(diagnostic)) + return trace.getTokens(); + } + return new HashSet<>(); + } + + public String getTokensAsString(Diagnostic diagnostic) { + return findTokens(diagnostic).stream().map(tk -> tk.getText() + " at line " + tk.getLine()).collect(Collectors.joining(", ")); + } + + public void clearTraces() { + traces.clear(); + } + + public JavaSourceFromString generate(Element claz) { + currentLineNumber = 0; + currentFileName = getJavaPath(claz, "/", true); + currentPackageName = getJavaPath(claz, ".", false); + StringBuilder builder = new StringBuilder(); + classToJavaInterface(builder, claz); + String code2 = builder.toString(); + JavaSourceFromString generated = new JavaSourceFromString(currentFileName, code2); + generatedFiles.add(generated); + if (save) saveFile(generated); + return generated; + } + + private void saveFile(JavaSourceFromString generated) { + try { + Path path = Paths.get(outDir + "/" + generated.getRawName() + ".java"); + if (!Files.exists(path.getParent())) + Files.createDirectories(path.getParent()); + Files.write(path, generated.code.getBytes()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void classToJavaInterface(StringBuilder builder, Element element) { + appendPackage(builder, element); + builder.append(newLine()); + appendImports(builder, element); + builder.append(newLine()); + appendInterface(builder, element); + } + + private void appendPackage(StringBuilder builder, Element element) { + builder.append("package "); + builder.append(getJavaPath(element, ".", false)); + builder.append(";"); + Trace packageTrace = new Trace(currentFileName, 0, 0, builder.length() - 1); + packageTrace.addToken(element.getOwner().getToken()); + traces.add(packageTrace); + } + + private void appendImports(StringBuilder builder, Element element) { + element.getAllOwnedElements(GenericSuperType.class, true) + .forEach(gst -> appendImport(builder, gst)); + element.getAllOwnedElements(GenericType.class, true) + .forEach(gt -> appendImport(builder, gt)); + element.getAllOwnedElements(GenericElementType.class, true) + .forEach(gt -> appendImport(builder, gt)); + } + + private void appendImport(StringBuilder builder, Element element) { + if (!element.getContext().getText().contains("::")) { + String text = element.getContext().start.getText(); + // Skip primitives + if (isPrimitive(text)) { + return; + } + // Skip type parameters + List typeParameters = element.getOwner(Class.class).getOwnedElements(TypeParameter.class); + String finalText = text; + if (typeParameters.stream().anyMatch(tp -> tp.getContext().start.getText().equals(finalText))) { + return; + } + // Append element import + Package containerPackage = element.getOwner(Package.class); + if (containerPackage != null) text = containerPackage.getEObject().getName() + "." + text; + builder.append("import "); + appendWithToken(builder, text, element.getToken()); + builder.append(";"); + builder.append(newLine()); + } else { + String importText = ""; + Element targetElement = findElementBySegment(element, element.getContext().getText()); + // Check if its imported class + if (targetElement != null && targetElement instanceof ImportedClass || targetElement instanceof ImportedDataType) { + // If so generate Java file + JavaSourceFromString generated = getImportGenerator().generate(targetElement); + generatedFiles.add(generated); + traces.addAll(getImportGenerator().getTraces()); + // And use its path for import + importText = generated.getRawName().replaceAll("/", "."); + } else if (targetElement != null) { + // Get its package info and append it + importText = getJavaPath(targetElement, ".", true); + } + // Else, assume this is a relative path + // importText = currentPackageName + "." + element.getContext().getText().replaceAll("::", ".").replaceAll(":", "."); + if (!importText.isEmpty()) { + builder.append("import "); + appendWithToken(builder, importText, element.getContext().stop); + builder.append(";"); + builder.append(newLine()); + } + } + } + + private Element findElementBySegment(Element element, String segmentsToFind) { + Element result = null; + Element parent = element.getOwner(); + while (result == null && parent != null) { + List ownedElements = parent.getOwnedElements(ITarget.class); + if (parent instanceof Package || parent instanceof ImportedPackage) + ownedElements = parent.getAllOwnedElements(ITarget.class, true); + if (parent instanceof Model) { + ownedElements = parent.getAllOwnedElements(ImportedClass.class, true); + ownedElements.addAll(parent.getAllOwnedElements(ImportedDataType.class, true)); + } + + result = ownedElements + .stream() + .filter(e -> ((ITarget) e).getRelativeSegment().equals(segmentsToFind)) + .findFirst() + .orElse(null); + parent = parent.getOwner(); + } + return result; + } + + @Deprecated + private ImportedClass findImportedClass(Element element) { + Element model = element.getOwner(Model.class); + assert model != null; + List importedClasses = model.getAllOwnedElements(ImportedClass.class, true); + String text = element.getContext().getText(); + String midPart = text.substring(0, text.lastIndexOf("::")); + String uniqueClassName = "Model::" + midPart + ":" + text.substring(text.lastIndexOf("::") + 2); + ImportedClass importedClass = null; + for (ImportedClass cls : importedClasses) { + String finalName = ""; + String uniqueName = cls.getUniqueName(); + String[] first = uniqueName.split("::"); + String[] mid = first[2].split(":"); + if (mid.length == 2) { + finalName = String.join("::", first[0], first[1]) + ":" + mid[1]; + } else { + for (int i = 0; i < first.length; i++) { + if (i == 2) + continue; + finalName += first[i]; + if (i != first.length - 1) + finalName += "::"; + } + } + if (finalName.equals(uniqueClassName)) { + importedClass = cls; + break; + } + } + return importedClass; + } + + private void appendInterface(StringBuilder builder, Element element) { + appendVisibility(builder, element); + builder.append("interface "); + // Append Class label as interface name + appendInterfaceName(builder, element); + appendSuperTypes(builder, element); + + builder.append(newLine()); + builder.append("{"); + builder.append(newLine()); + + appendStructuralFeatures(builder, element); + appendOperations(builder, element); + builder.append("}"); + } + + private void appendOperations(StringBuilder builder, Element element) { + for (Operation op : element.getOwnedElements(Operation.class)) { + builder.append("\t"); + appendVisibility(builder, op); + TypeParameter typeParameter = op.getOwnedElement(TypeParameter.class); + if (typeParameter != null) { + appendTypeParameters(builder, Collections.singletonList(typeParameter)); + } + GenericElementType elementType = op.getOwnedElement(GenericElementType.class); + if (elementType != null) { + appendGenericElementType(builder, elementType); + Multiplicity mul = op.getOwnedElement(Multiplicity.class); + if (mul != null && mul.isMany()) + builder.append("[]"); + + } else builder.append("void"); + builder.append(" "); + appendWithToken(builder, op.getToken().getText(), op.getToken()); + builder.append("("); + appendParameters(builder, op); + builder.append(");"); + builder.append(newLine()); + } + } + + private void appendTypeParameters(StringBuilder builder, List typeParameters) { + builder.append("<"); + for (Iterator iterator = typeParameters.iterator(); iterator.hasNext(); ) { + TypeParameter tp = iterator.next(); + int baseIndex = builder.length() - 1; + String text = tp.getLabel(); + builder.append(text); + addTrace(text, baseIndex, tp.getContext().start.getText(), tp.getToken()); + tp.getOwnedElements(GenericType.class) + .forEach(gt -> addTrace(text, baseIndex, gt.getToken().getText(), gt.getToken())); + if (iterator.hasNext()) builder.append(", "); + } + builder.append("> "); + } + + private void appendParameters(StringBuilder builder, Operation op) { + for (Iterator iterator = op.getOwnedElements(Parameter.class).iterator(); iterator.hasNext(); ) { + Parameter param = iterator.next(); + appendGenericElementType(builder, param.getOwnedElement(GenericElementType.class)); + builder.append(" "); + appendWithToken(builder, param.getToken().getText(), param.getToken()); + if (iterator.hasNext()) builder.append(", "); + } + } + + private void appendGenericElementType(StringBuilder builder, GenericElementType type) { + int baseIndex = builder.length() - 1; + String baseText = type.getLabel(); + Token typeToken = type.getToken(); + // Get last part of path + if (baseText.contains("::")) { + baseText = baseText.substring(baseText.lastIndexOf("::") + 2); + typeToken = type.getContext().stop; + } + builder.append(baseText); + addTrace(baseText, baseIndex, type.getToken().getText(), typeToken); + type.getAllOwnedElements(GenericWildcard.class, true) + .forEach(gw -> addTrace(type.getLabel(), baseIndex, gw.getLabel(), + gw.getContext().ownedExtend != null ? gw.getContext().stop : gw.getToken())); + } + + private void appendStructuralFeatures(StringBuilder builder, Element element) { + List sfs = new ArrayList<>(); + sfs.addAll(element.getOwnedElements(Attribute.class)); + sfs.addAll(element.getOwnedElements(Reference.class)); + for (StructuralFeature sf : sfs) { + builder.append("\t"); + appendVisibility(builder, sf); + GenericElementType elementType = sf.getOwnedElement(GenericElementType.class); + String typeName = elementType.getContext().getText(); + // Get last part of path + if (typeName.contains("::")) + typeName = typeName.substring(typeName.lastIndexOf("::") + 2); + appendWithToken(builder, typeName, elementType.getToken()); + Multiplicity mul = sf.getOwnedElement(Multiplicity.class); + if (mul != null && mul.isMany()) + builder.append("[]"); + builder.append(" "); + appendWithToken(builder, sf.getLabel(), sf.getToken()); + builder.append("();"); + builder.append(newLine()); + } + } + + private void appendInterfaceName(StringBuilder builder, Element element) { + int baseIndex = builder.length() - 1; + String baseText = element.getLabel(); + builder.append(element.getLabel()); + // Trace of Class name + addTrace(baseText, baseIndex, element.getToken().getText(), element.getToken()); + element.getOwnedElements(TypeParameter.class).forEach(tp -> { + // Trace of TypeParameters + addTrace(baseText, baseIndex, tp.getEObject().getName(), tp.getToken()); + tp.getOwnedElements(GenericType.class).forEach(gt -> { + // Trace of GenericType + addTrace(baseText, baseIndex, gt.getEObject().eClass().getName(), gt.getToken()); + }); + }); + } + + private void appendVisibility(StringBuilder builder, Element element) { + if (element instanceof IVisibility) { + Visibility value = ((IVisibility) element).getVisibility(); + if (value == Visibility.PUBLIC || value == Visibility.PROTECTED) { + appendWithToken(builder, value.name().toLowerCase(), element.getToken()); + builder.append(" "); + } + } + } + + private void appendSuperTypes(StringBuilder builder, Element element) { + List supers = element.getOwnedElements(GenericSuperType.class); + if (!supers.isEmpty()) + builder.append(" extends "); + supers.forEach(sp -> { + appendWithToken(builder, sp.getContext().getText(), sp.getToken()); + if (supers.indexOf(sp) != supers.size() - 1) + builder.append(", "); + }); + } + + private void appendWithToken(StringBuilder builder, String text, Token token) { + int start = builder.length() - 1; + Trace trace = new Trace(currentFileName, currentLineNumber, start, start + text.length()); + trace.addToken(token); + traces.add(trace); + builder.append(text); + } + + private void addTrace(String baseText, int baseIndex, String text, Token token) { + int start = baseIndex + baseText.indexOf(text); + int end = start + text.length(); + Trace trace = new Trace(currentFileName, currentLineNumber, start, end); + trace.addToken(token); + traces.add(trace); + } + + public boolean isPrimitive(String text) { + return text.equals("String") || text.equals("Boolean") || text.equals("Integer") || text.equals("Real") || text.equals("BigInteger"); + } + + private String newLine() { + currentLineNumber++; + return System.getProperty("line.separator"); + } + + private String getJavaPath(Element element, String separator, boolean includeItself) { + Element ownerPackage = element.getOwner(); + String result = ownerPackage.getToken().getText(); + if (includeItself) result += separator + element.getToken().getText(); + while (ownerPackage.getOwner() != null && + (ownerPackage.getOwner() instanceof Package || ownerPackage.getOwner() instanceof ImportedPackage)) { + ownerPackage = ownerPackage.getOwner(); + result = ownerPackage.getToken().getText() + separator + result; + } + return result; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/typechecking/JavaSourceFromString.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/typechecking/JavaSourceFromString.java new file mode 100644 index 00000000..ec04a75d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/typechecking/JavaSourceFromString.java @@ -0,0 +1,34 @@ +package eu.modelwriter.core.alloyinecore.typechecking; + +import javax.tools.SimpleJavaFileObject; +import java.net.URI; + +public class JavaSourceFromString extends SimpleJavaFileObject { + /** + * The source code of this "file". + */ + final String code; + final String rawName; + + /** + * Constructs a new JavaSourceFromString. + * + * @param name the name of the compilation unit represented by this file object + * @param code the source code for the compilation unit represented by this file object + */ + JavaSourceFromString(String name, String code) { + super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), + Kind.SOURCE); + this.code = code; + this.rawName = name; + } + + public String getRawName() { + return rawName; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return code; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/typechecking/Trace.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/typechecking/Trace.java new file mode 100644 index 00000000..3e067404 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/typechecking/Trace.java @@ -0,0 +1,40 @@ +package eu.modelwriter.core.alloyinecore.typechecking; + +import org.antlr.v4.runtime.Token; + +import javax.tools.Diagnostic; +import java.util.HashSet; +import java.util.Set; + +public class Trace { + private Set tokens; + private String fileName; + private int lineNumber, startOffset, endOffset; + + public Trace(String fileName, int lineNumber, int startOffset, int endOffset) { + this.fileName = fileName; + this.lineNumber = lineNumber; + this.startOffset = startOffset; + this.endOffset = endOffset; + tokens = new HashSet<>(); + } + + public void addToken(Token token) { + tokens.add(token); + } + + public Set getTokens() { + return tokens; + } + + public boolean overlaps(Diagnostic diagnostic) { + return ((JavaSourceFromString) diagnostic.getSource()).getRawName().equals(fileName) && + startOffset <= diagnostic.getStartPosition() - 1 + && diagnostic.getEndPosition() - 1 <= endOffset + && diagnostic.getLineNumber() - 1 == lineNumber; + } + + public boolean overlaps(int start, int end) { + return startOffset <= start && end <= endOffset; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/typechecking/TypeChecker.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/typechecking/TypeChecker.java new file mode 100644 index 00000000..ffd3af6d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/typechecking/TypeChecker.java @@ -0,0 +1,93 @@ +package eu.modelwriter.core.alloyinecore.typechecking; + +import eu.modelwriter.core.alloyinecore.structure.model.Class; +import eu.modelwriter.core.alloyinecore.structure.model.Interface; +import eu.modelwriter.core.alloyinecore.structure.model.Model; +import eu.modelwriter.core.alloyinecore.structure.model.Package; +import eu.modelwriter.core.alloyinecore.visitor.BaseVisitorImpl; +import org.antlr.v4.runtime.Token; + +import javax.tools.*; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; + +public class TypeChecker { + + private Set errorListeners; + private JavaInterfaceGenerator generator; + private String outDir; + + public TypeChecker() { + outDir = new File(".").getAbsolutePath() + File.separator + "target" + File.separator + "aie-typechecking"; + try { + Files.createDirectories(Paths.get(outDir)); + } catch (IOException e) { + outDir = ""; + e.printStackTrace(); + } + errorListeners = new HashSet<>(); + generator = new JavaInterfaceGenerator(outDir, true); + } + + public void addErrorListener(TypeErrorListener listener) { + errorListeners.add(listener); + } + + public void removeErrorListener(TypeErrorListener listener) { + errorListeners.remove(listener); + } + + public void check(Model model) { + ClassVisitor classVisitor = new ClassVisitor(); + classVisitor.visit(model); + Set generatedJavaFiles = generator.getGeneratedFiles(); + + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + DiagnosticCollector diagnostics = new DiagnosticCollector<>(); + StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null); + List options = Arrays.asList("-d", outDir); // -d: output dir + compiler.getTask(null, fileManager, diagnostics, options, null, generatedJavaFiles).call(); + for (Diagnostic diagnostic : diagnostics.getDiagnostics()) { + Set elements = generator.findTokens(diagnostic); + for (TypeErrorListener listener : errorListeners) { + String message = diagnostic.getMessage(Locale.getDefault()); + message += System.getProperty("line.separator") + "(" + diagnostic.getCode() + ")"; + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) + listener.onTypeError(message, elements); + else if (diagnostic.getKind() == Diagnostic.Kind.WARNING || diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING) + listener.onTypeWarning(message, elements); + } + System.err.format("%s %nMapped to: %s %n%n", diagnostic.toString(), generator.getTokensAsString(diagnostic)); + } + try { + // Try to close fileManager + fileManager.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private class ClassVisitor extends BaseVisitorImpl { + + @Override + public Object visitClass(Class _class) { + if (_class.getOwner() instanceof Package) { + JavaSourceFromString javaSource = generator.generate(_class); + System.out.println(javaSource.code + "\n\n"); + } + return null; + } + + @Override + public Object visitInterface(Interface _interface) { + if (_interface.getOwner() instanceof Package) { + JavaSourceFromString javaSource = generator.generate(_interface); + System.out.println(javaSource.code + "\n\n"); + } + return null; + } + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/typechecking/TypeErrorListener.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/typechecking/TypeErrorListener.java new file mode 100644 index 00000000..a58a99bb --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/typechecking/TypeErrorListener.java @@ -0,0 +1,12 @@ +package eu.modelwriter.core.alloyinecore.typechecking; + +import org.antlr.v4.runtime.Token; + +import java.util.Set; + +public interface TypeErrorListener { + + void onTypeError(String message, Set relatedElements); + + void onTypeWarning(String message, Set relatedElements); +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/visitor/BaseVisitorImpl.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/visitor/BaseVisitorImpl.java new file mode 100644 index 00000000..04d8ff58 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/visitor/BaseVisitorImpl.java @@ -0,0 +1,641 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.visitor; + +import eu.modelwriter.core.alloyinecore.structure.constraints.*; +import eu.modelwriter.core.alloyinecore.structure.instance.*; +import eu.modelwriter.core.alloyinecore.structure.instance.Object; +import eu.modelwriter.core.alloyinecore.structure.model.*; +import eu.modelwriter.core.alloyinecore.structure.imports.*; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.model.Class; +import eu.modelwriter.core.alloyinecore.structure.model.Enum; +import eu.modelwriter.core.alloyinecore.structure.model.Package; +import org.antlr.v4.runtime.ParserRuleContext; + +public abstract class BaseVisitorImpl implements IVisitor { + + @Override + public T visit(Element element) { + return element.accept(this); + } + + @Override + public T visitChildren(Element element) { + T result = defaultResult(); + for (Element ownedElement : element.getOwnedElements()) { + if (!shouldVisitNextChild(ownedElement, result)) { + break; + } + T childResult = ownedElement.accept(this); + result = aggregateResult(result, childResult); + } + return result; + } + + protected T defaultResult() { + return null; + } + + protected T aggregateResult(T aggregate, T nextResult) { + return nextResult; + } + + protected boolean shouldVisitNextChild(Element element, T currentResult) { + return true; + } + + @Override + public T visitAnnotationReference(AnnotationReference annotationReference) { return visitChildren(annotationReference); } + + @Override + public T visitOperation(Operation operation) { + return visitChildren(operation); + } + + @Override + public T visitIntConstant(IntExpression.IntConstant intConstant) { + return visitChildren(intConstant); + } + + @Override + public T visitPreCondition(PreCondition preCondition) { + return visitChildren(preCondition); + } + + @Override + public T visitNot(Formula.Not not) { + return visitChildren(not); + } + + @Override + public T visitProduct(Expression.Product product) { + return visitChildren(product); + } + + @Override + public T visitDivide(IntExpression.Divide divide) { + return visitChildren(divide); + } + + @Override + public T visitSumDeclaration(Formula.SumDeclaration sumDeclaration) { + return visitChildren(sumDeclaration); + } + + @Override + public T visitEnumLiteral(EnumLiteral enumLiteral) { + return visitChildren(enumLiteral); + } + + @Override + public T visitClosure(Expression.Closure closure) { + return visitChildren(closure); + } + + @Override + public T visitOneOf(QuantifierDeclaration.OneOf oneOf) { + return visitChildren(oneOf); + } + + @Override + public T visitFalse(Formula.False _false) { + return visitChildren(_false); + } + + @Override + public T visitAnnotationDetail(AnnotationDetail annotationDetail) { + return visitChildren(annotationDetail); + } + + @Override + public T visitModulo(IntExpression.Modulo modulo) { + return visitChildren(modulo); + } + + @Override + public T visitInterface(Interface _interface) { + return visitChildren(_interface); + } + + @Override + public T visitIfExpression(Expression.IfExpression ifExpression) { + return visitChildren(ifExpression); + } + + @Override + public T visitBoxJoin(Expression.BoxJoin boxJoin) { + return visitChildren(boxJoin); + } + + @Override + public T visitMultiply(IntExpression.Multiply multiply) { + return visitChildren(multiply); + } + + @Override + public T visitGenericSuperType(GenericSuperType genericSuperType) { + return visitChildren(genericSuperType); + } + + @Override + public T visitLone(Formula.Lone lone) { + return visitChildren(lone); + } + + @Override + public T visitAnd(Formula.And and) { + return visitChildren(and); + } + + @Override + public T visitInts(Expression.Ints ints) { + return visitChildren(ints); + } + + @Override + public T visitImplies(Formula.Implies implies) { + return visitChildren(implies); + } + + @Override + public T visitImport(Import _import) { + return visitChildren(_import); + } + + @Override + public T visitEcoreImport(EcoreImport ecoreImport) { + return visitChildren(ecoreImport); + } + + @Override + public T visitImportedClass(ImportedClass importedClass) { + return visitChildren(importedClass); + } + + @Override + public T visitImportedInterface(ImportedInterface _importInterface) { + return visitChildren(_importInterface); + } + + @Override + public T visitImportedPackage(ImportedPackage importedPackage) { + return visitChildren(importedPackage); + } + + @Override + public T visitImportedDataType(ImportedDataType importedDataType) { + return visitChildren(importedDataType); + } + + @Override + public T visitImportedEnum(ImportedEnum importedEnum) { + return visitChildren(importedEnum); + } + + @Override + public T visitComprehensionDeclaration(ComprehensionDeclaration comprehensionDeclaration) { return visitChildren(comprehensionDeclaration); } + + @Override + public T visitSetOf(QuantifierDeclaration.SetOf setOf) { + return visitChildren(setOf); + } + + @Override + public T visitForNo(Formula.ForNo forNo) { + return visitChildren(forNo); + } + + @Override + public T visitParameter(Parameter parameter) { + return visitChildren(parameter); + } + + @Override + public T visitInitial(Initial initial) { + return visitChildren(initial); + } + + @Override + public T visitTypeParameter(TypeParameter typeParameter) { + return visitChildren(typeParameter); + } + + @Override + public T visitDerivation(Derivation derivation) { + return visitChildren(derivation); + } + + @Override + public T visitPrimitiveType(PrimitiveType primitiveType) { + return visitChildren(primitiveType); + } + + @Override + public T visitEnum(Enum _enum) { + return visitChildren(_enum); + } + + @Override + public T visitIntersection(Expression.Intersection intersection) { + return visitChildren(intersection); + } + + @Override + public T visitReflexive(Expression.Reflexive reflexive) { + return visitChildren(reflexive); + } + + @Override + public T visitTrue(Formula.True _true) { + return visitChildren(_true); + } + + @Override + public T visitCount(IntExpression.Count count) { + return visitChildren(count); + } + + @Override + public T visitGenericException(GenericException genericException) { + return visitChildren(genericException); + } + + @Override + public T visitLt(Formula.Lt lt) { + return visitChildren(lt); + } + + @Override + public T visitRelationalOverride(Expression.RelationalOverride relationalOverride) { return visitChildren(relationalOverride); } + + @Override + public T visitForAll(Formula.ForAll forAll) { + return visitChildren(forAll); + } + + @Override + public T visitBody(Body body) { + return visitChildren(body); + } + + @Override + public T visitGenericTypeArgument(GenericTypeArgument genericTypeArgument) { return visitChildren(genericTypeArgument); } + + @Override + public T visitFunction(Formula.Function function) { + return visitChildren(function); + } + + @Override + public T visitPlus(IntExpression.Plus plus) { + return visitChildren(plus); + } + + @Override + public T visitJoin(Expression.Join join) { + return visitChildren(join); + } + + @Override + public T visitUniv(Expression.Univ univ) { + return visitChildren(univ); + } + + @Override + public T visitIfIntExpression(IntExpression.IfIntExpression ifIntExpression) { return visitChildren(ifIntExpression); } + + @Override + public T visitInvariant(Invariant invariant) { + return visitChildren(invariant); + } + + @Override + public T visitVariable(Variable variable) { + return visitChildren(variable); + } + + @Override + public T visitDifference(Expression.Difference difference) { + return visitChildren(difference); + } + + @Override + public T visitEqual(Formula.Equal equal) { + return visitChildren(equal); + } + + @Override + public T visitBinding(Expression.Binding var) { + return visitChildren(var); + } + + @Override + public T visitIff(Formula.Iff iff) { + return visitChildren(iff); + } + + @Override + public T visitSome(Formula.Some some) { + return visitChildren(some); + } + + @Override + public T visitGenericType(GenericType genericType) { + return visitChildren(genericType); + } + + @Override + public T visitMinus(IntExpression.Minus minus) { + return visitChildren(minus); + } + + @Override + public T visitEq(Formula.Eq eq) { + return visitChildren(eq); + } + + @Override + public T visitMultiplicity(Multiplicity multiplicity) { + return visitChildren(multiplicity); + } + + @Override + public T visitSomeOf(QuantifierDeclaration.SomeOf someOf) { + return visitChildren(someOf); + } + + @Override + public T visitOr(Formula.Or or) { + return visitChildren(or); + } + + @Override + public T visitGenericWildcard(GenericWildcard genericWildcard) { + return visitChildren(genericWildcard); + } + + @Override + public T visitNone(Expression.None none) { + return visitChildren(none); + } + + @Override + public T visitUnion(Expression.Union union) { + return visitChildren(union); + } + + @Override + public T visitReference(Reference reference) { + return visitChildren(reference); + } + + @Override + public T visitPackage(Package _package) { + return visitChildren(_package); + } + + @Override + public T visitRootPackage(RootPackage _package) { + return visitChildren(_package); + } + + @Override + public T visitForSome(Formula.ForSome forSome) { + return visitChildren(forSome); + } + + @Override + public T visitGenericElementType(GenericElementType genericElementType) { return visitChildren(genericElementType); } + + @Override + public T visitComprehension(Expression.Comprehension comprehension) { + return visitChildren(comprehension); + } + + @Override + public T visitGte(Formula.Gte gte) { + return visitChildren(gte); + } + + @Override + public T visitClass(Class _class) { + return visitChildren(_class); + } + + @Override + public T visitForOne(Formula.ForOne forOne) { + return visitChildren(forOne); + } + + @Override + public T visitAttribute(Attribute attribute) { + return visitChildren(attribute); + } + + @Override + public T visitSum(IntExpression.Sum sum) { + return visitChildren(sum); + } + + @Override + public T visitGt(Formula.Gt gt) { + return visitChildren(gt); + } + + @Override + public T visitTranspose(Expression.Transpose transpose) { + return visitChildren(transpose); + } + + @Override + public T visitAnnotation(Annotation annotation) { + return visitChildren(annotation); + } + + @Override + public T visitOne(Formula.One one) { + return visitChildren(one); + } + + @Override + public T visitModule(Model model) { + return visitChildren(model); + } + + @Override + public T visitRelation(Expression.Relation relation) { + return visitChildren(relation); + } + + @Override + public T visitLte(Formula.Lte lte) { + return visitChildren(lte); + } + + @Override + public T visitLetDeclaration(LetDeclaration letDeclaration) { + return visitChildren(letDeclaration); + } + + @Override + public T visitPostCondition(PostCondition postCondition) { + return visitChildren(postCondition); + } + + @Override + public T visitTotalOrder(Formula.TotalOrder totalOrder) { + return visitChildren(totalOrder); + } + + @Override + public T visitIn(Formula.In in) { + return visitChildren(in); + } + + @Override + public T visitAcyclic(Formula.Acyclic acyclic) { + return visitChildren(acyclic); + } + + @Override + public T visitForLone(Formula.ForLone forLone) { + return visitChildren(forLone); + } + + @Override + public T visitNo(Formula.No no) { + return visitChildren(no); + } + + @Override + public T visitLoneOf(QuantifierDeclaration.LoneOf loneOf) { + return visitChildren(loneOf); + } + + @Override + public T visitIden(Expression.Iden iden) { + return visitChildren(iden); + } + + @Override + public T visitDataType(DataType dataType) { + return visitChildren(dataType); + } + + @Override + public T visitNotIn(Formula.NotIn notIn) { + return visitChildren(notIn); + } + + @Override + public T visitNotEqual(Formula.NotEqual notEqual) { + return visitChildren(notEqual); + } + + @Override + public T visitNotEq(Formula.NotEq notEq) { + return visitChildren(notEq); + } + + @Override + public T visitNotLt(Formula.NotLt notLt) { + return visitChildren(notLt); + } + + @Override + public T visitNotLte(Formula.NotLte notLte) { + return visitChildren(notLte); + } + + @Override + public T visitNotGt(Formula.NotGt notGt) { + return visitChildren(notGt); + } + + @Override + public T visitNotGte(Formula.NotGte notGte) { + return visitChildren(notGte); + } + + @Override + public T visitPartialFunction(Formula.PartialFunction partialFunction) { + return visitChildren(partialFunction); + } + + @Override + public T visitInstance(Instance instance) { + return visitChildren(instance); + } + + @Override + public T visitObject(Object object) { + return visitChildren(object); + } + + @Override + public T visitSlot(Slot slot){ + return visitChildren(slot); + } + + @Override + public T visitObjectValue(ObjectValue objectValue){ + return visitChildren(objectValue); + } + + @Override + public T visitBooleanValue(BooleanValue booleanValue){ + return visitChildren(booleanValue); + } + + @Override + public T visitCharValue(CharValue charValue){ + return visitChildren(charValue); + } + + @Override + public T visitEnumValue(EnumValue enumValue){ + return visitChildren(enumValue); + } + + @Override + public T visitIntegerValue(IntegerValue integerValue){ + return visitChildren(integerValue); + } + + @Override + public T visitNullValue(NullValue nullValue){ return visitChildren(nullValue);} + + @Override + public T visitRealValue(RealValue realValue){ + return visitChildren(realValue); + } + + @Override + public T visitStringValue(StringValue stringValue){ + return visitChildren(stringValue); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/visitor/ElementVisitorImpl.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/visitor/ElementVisitorImpl.java new file mode 100644 index 00000000..ab09115b --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/visitor/ElementVisitorImpl.java @@ -0,0 +1,55 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.visitor; + +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import org.antlr.v4.runtime.ParserRuleContext; + +public abstract class ElementVisitorImpl extends BaseVisitorImpl { + + @Override + public T visit(Element element) { + visitElement(element); + return element.accept(this); + } + + @Override + public T visitChildren(Element element) { + T result = defaultResult(); + for (Element ownedElement : element.getOwnedElements()) { + if (!shouldVisitNextChild(ownedElement, result)) { + break; + } + visitElement(ownedElement); + T childResult = ownedElement.accept(this); + result = aggregateResult(result, childResult); + } + return result; + } + + public T visitElement(Element element) { + return null; + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/visitor/IVisitable.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/visitor/IVisitable.java new file mode 100644 index 00000000..b7e6dd56 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/visitor/IVisitable.java @@ -0,0 +1,29 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.visitor; + +public interface IVisitable { + T accept(IVisitor visitor); +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/visitor/IVisitor.java b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/visitor/IVisitor.java new file mode 100644 index 00000000..85b4f13f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/visitor/IVisitor.java @@ -0,0 +1,276 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package eu.modelwriter.core.alloyinecore.visitor; + +import eu.modelwriter.core.alloyinecore.structure.constraints.*; +import eu.modelwriter.core.alloyinecore.structure.instance.*; +import eu.modelwriter.core.alloyinecore.structure.instance.Object; +import eu.modelwriter.core.alloyinecore.structure.model.*; +import eu.modelwriter.core.alloyinecore.structure.imports.*; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.structure.model.Class; +import eu.modelwriter.core.alloyinecore.structure.model.Enum; +import eu.modelwriter.core.alloyinecore.structure.model.Package; +import org.antlr.v4.runtime.ParserRuleContext; + +public interface IVisitor { + T visit(Element element); + + T visitChildren(Element element); + + T visitAnnotationReference(AnnotationReference annotationReference); + + T visitOperation(Operation operation); + + T visitIntConstant(IntExpression.IntConstant intConstant); + + T visitPreCondition(PreCondition preCondition); + + T visitNot(Formula.Not not); + + T visitProduct(Expression.Product product); + + T visitDivide(IntExpression.Divide divide); + + T visitSumDeclaration(Formula.SumDeclaration sumDeclaration); + + T visitEnumLiteral(EnumLiteral enumLiteral); + + T visitClosure(Expression.Closure closure); + + T visitOneOf(QuantifierDeclaration.OneOf oneOf); + + T visitFalse(Formula.False _false); + + T visitAnnotationDetail(AnnotationDetail annotationDetail); + + T visitModulo(IntExpression.Modulo modulo); + + T visitInterface(Interface _interface); + + T visitIfExpression(Expression.IfExpression ifExpression); + + T visitBoxJoin(Expression.BoxJoin boxJoin); + + T visitMultiply(IntExpression.Multiply multiply); + + T visitGenericSuperType(GenericSuperType genericSuperType); + + T visitLone(Formula.Lone lone); + + T visitAnd(Formula.And and); + + T visitInts(Expression.Ints ints); + + T visitImplies(Formula.Implies implies); + + T visitImport(Import _import); + + T visitImportedClass(ImportedClass importedClass); + + T visitImportedPackage(ImportedPackage importedPackage); + + T visitImportedInterface(ImportedInterface importedInterface); + + T visitImportedDataType(ImportedDataType importedDataType); + + T visitImportedEnum(ImportedEnum importedEnum); + + T visitEcoreImport(EcoreImport ecoreImport); + + T visitComprehensionDeclaration(ComprehensionDeclaration comprehensionDeclaration); + + T visitSetOf(QuantifierDeclaration.SetOf setOf); + + T visitForNo(Formula.ForNo forNo); + + T visitParameter(Parameter parameter); + + T visitInitial(Initial initial); + + T visitTypeParameter(TypeParameter typeParameter); + + T visitDerivation(Derivation derivation); + + T visitPrimitiveType(PrimitiveType primitiveType); + + T visitEnum(Enum _enum); + + T visitIntersection(Expression.Intersection intersection); + + T visitReflexive(Expression.Reflexive reflexive); + + T visitTrue(Formula.True _true); + + T visitCount(IntExpression.Count count); + + T visitGenericException(GenericException genericException); + + T visitLt(Formula.Lt lt); + + T visitRelationalOverride(Expression.RelationalOverride relationalOverride); + + T visitForAll(Formula.ForAll forAll); + + T visitBody(Body body); + + T visitGenericTypeArgument(GenericTypeArgument genericTypeArgument); + + T visitFunction(Formula.Function function); + + T visitPlus(IntExpression.Plus plus); + + T visitJoin(Expression.Join join); + + T visitUniv(Expression.Univ univ); + + T visitIfIntExpression(IntExpression.IfIntExpression ifIntExpression); + + T visitInvariant(Invariant invariant); + + T visitVariable(Variable variable); + + T visitDifference(Expression.Difference difference); + + T visitEqual(Formula.Equal equal); + + T visitIff(Formula.Iff iff); + + T visitSome(Formula.Some some); + + T visitGenericType(GenericType genericType); + + T visitMinus(IntExpression.Minus minus); + + T visitEq(Formula.Eq eq); + + T visitMultiplicity(Multiplicity multiplicity); + + T visitSomeOf(QuantifierDeclaration.SomeOf someOf); + + T visitOr(Formula.Or or); + + T visitGenericWildcard(GenericWildcard genericWildcard); + + T visitNone(Expression.None none); + + T visitUnion(Expression.Union union); + + T visitReference(Reference reference); + + T visitPackage(Package _package); + + T visitRootPackage(RootPackage _package); + + T visitForSome(Formula.ForSome forSome); + + T visitGenericElementType(GenericElementType genericElementType); + + T visitComprehension(Expression.Comprehension comprehension); + + T visitGte(Formula.Gte gte); + + T visitClass(Class _class); + + T visitForOne(Formula.ForOne forOne); + + T visitAttribute(Attribute attribute); + + T visitSum(IntExpression.Sum sum); + + T visitGt(Formula.Gt gt); + + T visitTranspose(Expression.Transpose transpose); + + T visitAnnotation(Annotation annotation); + + T visitOne(Formula.One one); + + T visitModule(Model model); + + T visitBinding(Expression.Binding binding); + + T visitRelation(Expression.Relation relation); + + T visitLte(Formula.Lte lte); + + T visitLetDeclaration(LetDeclaration letDeclaration); + + T visitPostCondition(PostCondition postCondition); + + T visitTotalOrder(Formula.TotalOrder totalOrder); + + T visitIn(Formula.In in); + + T visitAcyclic(Formula.Acyclic acyclic); + + T visitForLone(Formula.ForLone forLone); + + T visitNo(Formula.No no); + + T visitLoneOf(QuantifierDeclaration.LoneOf loneOf); + + T visitIden(Expression.Iden iden); + + T visitDataType(DataType dataType); + + T visitNotIn(Formula.NotIn notIn); + + T visitNotEqual(Formula.NotEqual notEqual); + + T visitNotEq(Formula.NotEq notEq); + + T visitNotLt(Formula.NotLt notLt); + + T visitNotLte(Formula.NotLte notLte); + + T visitNotGt(Formula.NotGt notGt); + + T visitNotGte(Formula.NotGte notGte); + + T visitPartialFunction(Formula.PartialFunction partialFunction); + + T visitInstance(Instance instance); + + T visitObject(Object object); + + T visitSlot(Slot slot); + + T visitObjectValue(ObjectValue objectValue); + + T visitBooleanValue(BooleanValue booleanValue); + + T visitCharValue(CharValue charValue); + + T visitEnumValue(EnumValue enumValue); + + T visitIntegerValue(IntegerValue integerValue); + + T visitNullValue(NullValue nullValue); + + T visitRealValue(RealValue realValue); + + T visitStringValue(StringValue stringValue); +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/resources/AlloyInEcore.stg b/Source/eu.modelwriter.core.alloyinecore/src/main/resources/AlloyInEcore.stg new file mode 100644 index 00000000..0ebcf640 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/resources/AlloyInEcore.stg @@ -0,0 +1,147 @@ +model(options, modelName) ::= +<< +<\n><\u007B> + +<\u007D><\n> +model ;<\n><\n> +>> + +load(name, namespace) ::= +<< +import : ; +>> + +package(visibility, name, prefix, namespace, subElement) ::= +<< +package : = <\n><\u007B>; + +<\u007D><\n> +>> + +enum(visibility, name, typeParameter, instanceName, isSerializable, subElement)::= +<< +enum <\u003C><\u003E><\n><\u007B>; + +<\u007D><\n> +>> + +enumLiteral(name, enumValue, subElement) ::= +<< +literal = <\n><\u007B>; + +<\u007D><\n> +>> + +datatype(visibility, isPrimitive, nullable, name, typeParameter, instanceName, isSerializable, subElement)::= +<< +primitive nullable datatype <\u003C><\u003E><(instanceName:singleQuote()):semicolon():ls()><\n><\u007B>; + +<\u007D><\n> +>> + +class(visibility, isAbstract, name, typeParameter, superClass, instanceName, isInterface, subElement) ::= +<< +interfaceabstract class<\u003C><\u003E> extends <\n><\u007B>; + +<\u007D><\n> +>> + +attr(visibility, isStatic, model,ghost, transient, volatile, nullable, readonly, name, defaultValue, type, multiplicity, qualifier, subElement)::= +<< +static model ghost transient volatile nullable readonly attribute<\n><\u007B>; + +<\u007D><\n> +>> + +ref(visibility, isStatic, model,ghost, transient, volatile, nullable, readonly, name, opposite, defaultValue, type, multiplicity, qualifier, subElement)::= +<< +static model ghost transient volatile nullable readonly property<\n><\u007B>; + +<\u007D><\n> +>> + +op(visibility, isStatic, nullable, name, typeParameter, params, throws, type, multiplicity, qualifier, subElement) ::= +<< +static nullable operation <\u003C><\u003E>() throws <\n><\u007B>; + +<\u007D><\n> +>> + +opParameter(nullable, name, type, multiplicity, qualifier, subElement) ::= +<< +nullable +>> + +anno(name, detail, subElement)::= +<< +annotation; +( + +); +<\u007B> + +<\u007D><\n> +>> + +edetail(name, val)::= +<< + = +>> + +inv(isCallable, name, message, formula)::= +<< +callable invariant; +>> + +precondition(name, message, formula)::= +<< +requires; +>> + +postcondition(name, message, formula)::= +<< +ensures; +>> + +body(name, expression)::= +<< +body; +>> + +derivation(name, expression) ::= +<< +derivation; +>> + +initial(name, expression) ::= +<< +initial; +>> + +referenceKey(referredKeys) ::= +<< +key ; +>> + +typeParameter(name, eBound) ::= +<< + extends +>> + +genericType(classifier, typeParameter, typeArgument, upperBound, lowerBound) ::= +<< +?<\u003C><\u003E> extends super +>> + +ds(x) ::= " " +ls(x) ::= "<\ >" +rs(x) ::= " " +throw(x)::=" throws " +parenthesis(x) ::= "()" +sharp(x) ::= "#" +equals(x) ::= "= " +bracket(x) ::= "[]" +semicolon(x) ::=": " +curlyBracket(x) ::="<\u007B> <\u007D>" +singleQuote(x)::="''" +doubleQuote(x)::="\"\"" \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/resources/Ecore.recore b/Source/eu.modelwriter.core.alloyinecore/src/main/resources/Ecore.recore new file mode 100644 index 00000000..bc1149ad --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/resources/Ecore.recore @@ -0,0 +1,443 @@ +package ecore : ecore = 'http://www.eclipse.org/emf/2002/Ecore' +{ + class EAttribute extends EStructuralFeature + { + attribute iD : EBoolean[?]; + transient volatile readonly property eAttributeType : EDataType { derived }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ConsistentTransient' + ); + } + class EAnnotation extends EModelElement + { + attribute source : EString[?]; + property details : EStringToStringMapEntry[*] { ordered !resolve composes }; + transient property eModelElement#eAnnotations : EModelElement[?] { !resolve }; + property contents : EObject[*] { ordered !resolve composes }; + property references : EObject[*] { ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedSourceURI' + ); + } + class EClass extends EClassifier + { + attribute abstract : EBoolean[?]; + attribute interface : EBoolean[?]; + operation isSuperTypeOf(someClass : EClass[?]) : EBoolean[?]; + operation getFeatureCount() : EInt[?]; + operation getEStructuralFeature(featureID : EInt[?]) : EStructuralFeature[?]; + operation getFeatureID(feature : EStructuralFeature[?]) : EInt[?]; + operation getEStructuralFeature(featureName : EString[?]) : EStructuralFeature[?]; + operation getOperationCount() : EInt[?]; + operation getEOperation(operationID : EInt[?]) : EOperation[?]; + operation getOperationID(operation : EOperation[?]) : EInt[?]; + operation getOverride(operation : EOperation[?]) : EOperation[?]; + operation getFeatureType(feature : EStructuralFeature[?]) : EGenericType[?]; + property eSuperTypes : EClass[*] { ordered unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + property eOperations#eContainingClass : EOperation[*] { ordered !resolve composes }; + transient volatile readonly property eAllAttributes : EAttribute[*] { ordered derived }; + transient volatile readonly property eAllReferences : EReference[*] { ordered derived }; + transient volatile readonly property eReferences : EReference[*] { ordered derived }; + transient volatile readonly property eAttributes : EAttribute[*] { ordered derived }; + transient volatile readonly property eAllContainments : EReference[*] { ordered derived }; + transient volatile readonly property eAllOperations : EOperation[*] { ordered derived }; + transient volatile readonly property eAllStructuralFeatures : EStructuralFeature[*] { ordered derived }; + transient volatile readonly property eAllSuperTypes : EClass[*] { ordered derived }; + transient volatile readonly property eIDAttribute : EAttribute[?] { derived !resolve }; + property eStructuralFeatures#eContainingClass : EStructuralFeature[*] { ordered !resolve composes }; + property eGenericSuperTypes : EGenericType[*] { ordered unsettable !resolve composes } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + transient volatile readonly property eAllGenericSuperTypes : EGenericType[*] { ordered derived }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'InterfaceIsAbstract AtMostOneID UniqueFeatureNames UniqueOperationSignatures NoCircularSuperTypes WellFormedMapEntryClass ConsistentSuperTypes DisjointFeatureAndOperationSignatures' + ); + } + abstract class EClassifier extends ENamedElement + { + volatile attribute instanceClassName : EString[?] { unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + transient volatile readonly attribute instanceClass : EJavaClass[?] { derived }; + transient volatile readonly attribute defaultValue : EJavaObject[?] { derived }; + volatile attribute instanceTypeName : EString[?] { unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + operation isInstance(object : EJavaObject[?]) : EBoolean[?]; + operation getClassifierID() : EInt[?]; + transient readonly property ePackage#eClassifiers : EPackage[?]; + property eTypeParameters : ETypeParameter[*] { ordered composes }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedInstanceTypeName UniqueTypeParameterNames' + ); + } + class EDataType extends EClassifier + { + attribute serializable : EBoolean[?] = 'true'; + } + class EEnum extends EDataType + { + operation getEEnumLiteral(name : EString[?]) : EEnumLiteral[?]; + operation getEEnumLiteral(value : EInt[?]) : EEnumLiteral[?]; + operation getEEnumLiteralByLiteral(literal : EString[?]) : EEnumLiteral[?]; + property eLiterals#eEnum : EEnumLiteral[*] { ordered !resolve composes }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'UniqueEnumeratorNames UniqueEnumeratorLiterals' + ); + } + class EEnumLiteral extends ENamedElement + { + attribute value : EInt[?]; + transient attribute instance : EEnumerator[?]; + attribute literal : EString[?]; + transient readonly property eEnum#eLiterals : EEnum[?] { !resolve }; + } + class EFactory extends EModelElement + { + operation create(eClass : EClass[?]) : EObject[?]; + operation createFromString(eDataType : EDataType[?], literalValue : EString[?]) : EJavaObject[?]; + operation convertToString(eDataType : EDataType[?], instanceValue : EJavaObject[?]) : EString[?]; + transient property ePackage#eFactoryInstance : EPackage { !resolve }; + } + abstract class EModelElement + { + operation getEAnnotation(source : EString[?]) : EAnnotation[?]; + property eAnnotations#eModelElement : EAnnotation[*] { ordered !resolve composes }; + } + abstract class ENamedElement extends EModelElement + { + attribute name : EString[?]; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedName' + ); + } + class EObject + { + operation eClass() : EClass[?]; + operation eIsProxy() : EBoolean[?]; + operation eResource() : EResource[?]; + operation eContainer() : EObject[?]; + operation eContainingFeature() : EStructuralFeature[?]; + operation eContainmentFeature() : EReference[?]; + operation eContents() : EEList[?]; + operation eAllContents() : ETreeIterator[?]; + operation eCrossReferences() : EEList[?]; + operation eGet(feature : EStructuralFeature[?]) : EJavaObject[?]; + operation eGet(feature : EStructuralFeature[?], resolve : EBoolean[?]) : EJavaObject[?]; + operation eSet(feature : EStructuralFeature[?], newValue : EJavaObject[?]); + operation eIsSet(feature : EStructuralFeature[?]) : EBoolean[?]; + operation eUnset(feature : EStructuralFeature[?]); + operation eInvoke(operation : EOperation[?], arguments : EEList[?]) : EJavaObject[?] throws EInvocationTargetException; + } + class EOperation extends ETypedElement + { + operation getOperationID() : EInt[?]; + operation isOverrideOf(someOperation : EOperation[?]) : EBoolean[?]; + transient readonly property eContainingClass#eOperations : EClass[?] { !resolve }; + property eTypeParameters : ETypeParameter[*] { ordered composes }; + property eParameters#eOperation : EParameter[*] { ordered !resolve composes }; + property eExceptions : EClassifier[*] { ordered unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + property eGenericExceptions : EGenericType[*] { ordered unsettable !resolve composes } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'UniqueParameterNames UniqueTypeParameterNames NoRepeatingVoid' + ); + } + class EPackage extends ENamedElement + { + attribute nsURI : EString[?]; + attribute nsPrefix : EString[?]; + operation getEClassifier(name : EString[?]) : EClassifier[?]; + transient property eFactoryInstance#ePackage : EFactory { !resolve }; + property eClassifiers#ePackage : EClassifier[*] { ordered composes }; + property eSubpackages#eSuperPackage : EPackage[*] { ordered composes }; + transient readonly property eSuperPackage#eSubpackages : EPackage[?]; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedNsURI WellFormedNsPrefix UniqueSubpackageNames UniqueClassifierNames UniqueNsURIs' + ); + } + class EParameter extends ETypedElement + { + transient readonly property eOperation#eParameters : EOperation[?] { !resolve }; + } + class EReference extends EStructuralFeature + { + attribute containment : EBoolean[?]; + transient volatile readonly attribute container : EBoolean[?] { derived }; + attribute resolveProxies : EBoolean[?] = 'true'; + property eOpposite : EReference[?]; + transient volatile readonly property eReferenceType : EClass { derived }; + property eKeys : EAttribute[*] { ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ConsistentOpposite SingleContainer ConsistentKeys ConsistentUnique ConsistentContainer' + ); + } + abstract class EStructuralFeature extends ETypedElement + { + attribute changeable : EBoolean[?] = 'true'; + attribute volatile : EBoolean[?]; + attribute transient : EBoolean[?]; + attribute defaultValueLiteral : EString[?]; + transient volatile readonly attribute defaultValue : EJavaObject[?] { derived }; + attribute unsettable : EBoolean[?]; + attribute derived : EBoolean[?]; + operation getFeatureID() : EInt[?]; + operation getContainerClass() : EJavaClass[?]; + transient readonly property eContainingClass#eStructuralFeatures : EClass[?] { !resolve }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ValidDefaultValueLiteral' + ); + } + abstract class ETypedElement extends ENamedElement + { + attribute ordered : EBoolean[?] = 'true'; + attribute unique : EBoolean[?] = 'true'; + attribute lowerBound : EInt[?]; + attribute upperBound : EInt[?] = '1'; + transient volatile readonly attribute many : EBoolean[?] { derived }; + transient volatile readonly attribute required : EBoolean[?] { derived }; + volatile property eType : EClassifier[?] { unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + volatile property eGenericType : EGenericType[?] { unsettable !resolve composes } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ValidLowerBound ValidUpperBound ConsistentBounds ValidType' + ); + } + datatype EBigDecimal : 'java.math.BigDecimal' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#decimal' + ); + } + datatype EBigInteger : 'java.math.BigInteger' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#integer' + ); + } + datatype EBoolean : 'boolean' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#boolean' + ); + } + datatype EBooleanObject : 'java.lang.Boolean' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EBoolean', + 'name' = 'EBoolean:Object' + ); + } + datatype EByte : 'byte' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#byte' + ); + } + datatype EByteArray : 'byte[]' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#hexBinary' + ); + } + datatype EByteObject : 'java.lang.Byte' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EByte', + 'name' = 'EByte:Object' + ); + } + datatype EChar : 'char'; + datatype ECharacterObject : 'java.lang.Character' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EChar', + 'name' = 'EChar:Object' + ); + } + datatype EDate : 'java.util.Date'; + datatype EDiagnosticChain : 'org.eclipse.emf.common.util.DiagnosticChain' { !serializable }; + datatype EDouble : 'double' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#double' + ); + } + datatype EDoubleObject : 'java.lang.Double' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EDouble', + 'name' = 'EDouble:Object' + ); + } + datatype EEList : 'org.eclipse.emf.common.util.EList' { !serializable }; + datatype EEnumerator : 'org.eclipse.emf.common.util.Enumerator' { !serializable }; + datatype EFeatureMap : 'org.eclipse.emf.ecore.util.FeatureMap' { !serializable }; + datatype EFeatureMapEntry : 'org.eclipse.emf.ecore.util.FeatureMap$Entry' { !serializable }; + datatype EFloat : 'float' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#float' + ); + } + datatype EFloatObject : 'java.lang.Float' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EFloat', + 'name' = 'EFloat:Object' + ); + } + datatype EInt : 'int' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#int' + ); + } + datatype EIntegerObject : 'java.lang.Integer' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EInt', + 'name' = 'EInt:Object' + ); + } + datatype EJavaClass : 'java.lang.Class'; + datatype EJavaObject : 'java.lang.Object'; + datatype ELong : 'long' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#long' + ); + } + datatype ELongObject : 'java.lang.Long' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'ELong', + 'name' = 'ELong:Object' + ); + } + datatype EMap : 'java.util.Map' { !serializable }; + datatype EResource : 'org.eclipse.emf.ecore.resource.Resource' { !serializable }; + datatype EResourceSet : 'org.eclipse.emf.ecore.resource.ResourceSet' { !serializable }; + datatype EShort : 'short' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#short' + ); + } + datatype EShortObject : 'java.lang.Short' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EShort', + 'name' = 'EShort:Object' + ); + } + datatype EString : 'java.lang.String' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#string' + ); + } + class EStringToStringMapEntry : 'java.util.Map$Entry' + { + attribute key : EString[?]; + attribute value : EString[?]; + } + datatype ETreeIterator : 'org.eclipse.emf.common.util.TreeIterator' { !serializable }; + class EGenericType + { + operation isInstance(object : EJavaObject[?]) : EBoolean[?]; + property eUpperBound : EGenericType[?] { !resolve composes }; + property eTypeArguments : EGenericType[*] { ordered !resolve composes }; + transient readonly property eRawType : EClassifier { derived }; + property eLowerBound : EGenericType[?] { !resolve composes }; + property eTypeParameter : ETypeParameter[?] { !resolve }; + property eClassifier : EClassifier[?]; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ConsistentType ConsistentBounds ConsistentArguments' + ); + } + class ETypeParameter extends ENamedElement + { + property eBounds : EGenericType[*] { ordered !resolve composes }; + } + datatype EInvocationTargetException : 'java.lang.reflect.InvocationTargetException' { !serializable }; +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/resources/EcoreInstance.stg b/Source/eu.modelwriter.core.alloyinecore/src/main/resources/EcoreInstance.stg new file mode 100644 index 00000000..8e7d03f9 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/resources/EcoreInstance.stg @@ -0,0 +1,34 @@ +load(name, path) ::= +<< +import : ; +>> + +model(name, nsPrefix, nsURI, path) ::= +<< +model : ;<\n><\n> +>> + +eObject(className, id, content) ::= +<< +<\n>{; + +} +>> + +containmentRef(name, content) ::= +<< +: <\n>{; + +} +>> + +ds(x) ::= " " +ls(x) ::= "<\ >" +rs(x) ::= " " +throw(x)::=" throws " +parenthesis(x) ::= "()" +bracket(x) ::= "[]" +semicolon(x) ::=": " +curlyBracket(x) ::="{ }" +singleQuote(x)::="''" +doubleQuote(x)::="\"\"" \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/main/resources/META-INF/MANIFEST.MF b/Source/eu.modelwriter.core.alloyinecore/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 00000000..f45bdc8a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1,7 @@ +Manifest-Version: 1.0 +Class-Path: antlr-4.6-complete.jar kodkod.jar guava-21.0.jar org.sat4j + .core-2.3.1.jar org.eclipse.emf.common_2.12.0.v20160420-0247.jar org. + eclipse.emf.ecore.xmi_2.12.0.v20160420-0247.jar org.eclipse.emf.ecore + _2.12.0.v20160420-0247.jar +Main-Class: eu.modelwriter.core.alloyinecore.AlloyInECoreFrontEnd_Test + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/java/DummyVisitor.java b/Source/eu.modelwriter.core.alloyinecore/src/test/java/DummyVisitor.java new file mode 100644 index 00000000..bc94d307 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/java/DummyVisitor.java @@ -0,0 +1,50 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import eu.modelwriter.core.alloyinecore.structure.model.Class; +import eu.modelwriter.core.alloyinecore.structure.base.Element; +import eu.modelwriter.core.alloyinecore.visitor.ElementVisitorImpl; + +public class DummyVisitor extends ElementVisitorImpl { + private StringBuilder b = new StringBuilder(); + + @Override + public StringBuilder visitElement(Element element) { + b.append(""); + b.append(element.getLabel()); + b.append("\n"); + return b; + } + + @Override + public StringBuilder visitClass(Class _class) { + b.append("* "); + b.append(_class.getLabel()); + b.append(" *\n"); + // Call super or visitChildren(_class) to visit the children + super.visitClass(_class); + return b; + } +} + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/java/DynamicEmf_Test.java b/Source/eu.modelwriter.core.alloyinecore/src/test/java/DynamicEmf_Test.java new file mode 100644 index 00000000..e37abf1a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/java/DynamicEmf_Test.java @@ -0,0 +1,237 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * Created by ferhat on 12/20/16. + */ + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.*; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl; + +public class DynamicEmf_Test { + + private static String getQualifiedName(EPackage pkg) { + return pkg.getESuperPackage() == null ? pkg.getName() : getQualifiedName(pkg.getESuperPackage()) + "." + pkg.getName(); + } + + private static String getQualifiedName(EClassifier cls) { + return getQualifiedName(cls.getEPackage()) + "." + cls.getName(); + } + + private static String getQualifiedName(EStructuralFeature sf) { + return getQualifiedName(sf.getEContainingClass()) + "::" + sf.getName(); + } + + public static void main(final String[] args) { + /* + * Instantiate EcoreFactory + */ + EcoreFactory theCoreFactory = EcoreFactory.eINSTANCE; + + /* + * Create EClass instance to model BookStore class + */ + EClass bookStoreEClass = theCoreFactory.createEClass(); + bookStoreEClass.setName("BookStore"); + bookStoreEClass.setInstanceClassName("instanceClass"); + + EAnnotation annotation1 = theCoreFactory.createEAnnotation(); + bookStoreEClass.getEAnnotations().add(annotation1); + annotation1.setSource("modelwriter/Ferhat"); + annotation1.getDetails().put(null, "value"); + EClass annotationClass = theCoreFactory.createEClass(); + annotationClass.setName("AnnotationClass"); + annotation1.getContents().add(annotationClass); + + /* + * Create EClass instance to model Book class + */ + EClass bookEClass = theCoreFactory.createEClass(); + bookEClass.setName("Book"); + bookEClass.setAbstract(false); + annotation1.getReferences().add(bookEClass); + + /* + * Instantiate EPackage and provide unique URI + * to identify this package + */ + EPackage bookStoreEPackage = theCoreFactory.createEPackage(); + bookStoreEPackage.setName("BookStorePackage"); + bookStoreEPackage.setNsPrefix("bookStore"); + bookStoreEPackage.setNsURI("http:///com.ibm.dynamic.example.bookstore.ecore"); + + +// EPackage innerEPackage = theCoreFactory.createEPackage(); +// innerEPackage.setName("TypeParameterTest1"); +// innerEPackage.setNsPrefix("Type1"); +// innerEPackage.setNsURI("http:///com.ibm.dynamic.example.bookstore.Type1.ecore"); +// EClass x = theCoreFactory.createEClass(); +// x.setName("XClass"); +// innerEPackage.getEClassifiers().add(x); +// EClass y = theCoreFactory.createEClass(); +// y.setName("YClass"); +// innerEPackage.getEClassifiers().add(y); +// EClass z = theCoreFactory.createEClass(); +// z.setName("ZClass"); +// innerEPackage.getEClassifiers().add(z); +// ETypeParameter t = theCoreFactory.createETypeParameter(); t.setName("T"); +// ETypeParameter k = theCoreFactory.createETypeParameter(); k.setName("K"); +// x.getETypeParameters().add(t); +// x.getETypeParameters().add(k); +// EGenericType gt_Y = theCoreFactory.createEGenericType(); +// gt_Y.setEClassifier(y); +// EGenericType gt_Z = theCoreFactory.createEGenericType(); +// gt_Z.setEClassifier(z); +// k.getEBounds().add(gt_Y); +// k.getEBounds().add(gt_Z); + + EPackage innerEPackage = theCoreFactory.createEPackage(); + innerEPackage.setName("TypeParameterTest1"); + innerEPackage.setNsPrefix("Type1"); + innerEPackage.setNsURI("http:///com.ibm.dynamic.example.bookstore.Type1.ecore"); + EClass x = theCoreFactory.createEClass(); + x.setName("XClass"); + innerEPackage.getEClassifiers().add(x); + EClass y = theCoreFactory.createEClass(); + y.setName("YClass"); + innerEPackage.getEClassifiers().add(y); + EClass z = theCoreFactory.createEClass(); + z.setName("ZClass"); + innerEPackage.getEClassifiers().add(z); + ETypeParameter t = theCoreFactory.createETypeParameter(); t.setName("T"); + ETypeParameter k = theCoreFactory.createETypeParameter(); k.setName("K"); + x.getETypeParameters().add(t); + x.getETypeParameters().add(k); + EGenericType gt_Y = theCoreFactory.createEGenericType(); + gt_Y.setEClassifier(y); + EGenericType gt_Z = theCoreFactory.createEGenericType(); + gt_Z.setEClassifier(z); + k.getEBounds().add(gt_Y); + k.getEBounds().add(gt_Z); + + + EAttribute innerAttribute = theCoreFactory.createEAttribute(); + innerAttribute.setName("owner"); + innerAttribute.setEType(EcorePackage.eINSTANCE.getEString()); + + x.getEStructuralFeatures().add(innerAttribute); + + bookStoreEPackage.getESubpackages().add(innerEPackage); + + System.out.println(getQualifiedName(innerEPackage)); + System.out.println(getQualifiedName(innerAttribute)); + + + /* + * Instantiate EcorePackage + */ + EcorePackage theCorePackage = EcorePackage.eINSTANCE; + + /* + * Create attributes for BookStore class as specified in the model + */ + + EAttribute bookStoreOwner = theCoreFactory.createEAttribute(); + bookStoreOwner.setName("owner"); + bookStoreOwner.setEType(theCorePackage.getEString()); + EAttribute bookStoreLocation = theCoreFactory.createEAttribute(); + bookStoreLocation.setName("location"); + bookStoreLocation.setEType(theCorePackage.getEString()); + EReference bookStore_Books = theCoreFactory.createEReference(); + bookStore_Books.setName("books"); + bookStore_Books.setEType(bookEClass); + bookStore_Books.setUpperBound(EStructuralFeature.UNBOUNDED_MULTIPLICITY); + bookStore_Books.setContainment(true); + + EOperation op = theCoreFactory.createEOperation(); + + + + + + /* + * Create attributes for Book class as defined in the model + */ + EAttribute bookName = theCoreFactory.createEAttribute(); + bookName.setName("name"); + bookName.setEType(theCorePackage.getEString()); + EAttribute bookISBN = theCoreFactory.createEAttribute(); + bookISBN.setName("isbn"); + bookISBN.setEType(theCorePackage.getEInt()); + + /* + * Add owner, location and books attributes/references + * to BookStore class + */ + bookStoreEClass.getEStructuralFeatures().add(bookStoreOwner); + bookStoreEClass.getEStructuralFeatures().add(bookStoreLocation); + bookStoreEClass.getEStructuralFeatures().add(bookStore_Books); + + + + + /* + * Add name and isbn attributes to Book class + */ + bookEClass.getEStructuralFeatures().add(bookName); + bookEClass.getEStructuralFeatures().add(bookISBN); + + /* + * Place BookStore and Book classes in bookStoreEPackage + */ + bookStoreEPackage.getEClassifiers().add(bookStoreEClass); + bookStoreEPackage.getEClassifiers().add(bookEClass); + + ResourceSet metaResourceSet = new ResourceSetImpl(); + + /* + * Register XML Factory implementation to handle .ecore files + */ + metaResourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put( + "ecore", new XMLResourceFactoryImpl()); + + /* + * Create empty resource with the given URI + */ + Resource metaResource = metaResourceSet.createResource(URI.createURI("./src/test/resources/out/bookstore.ecore")); + + /* + * Add bookStoreEPackage to contents list of the resource + */ + metaResource.getContents().add(bookStoreEPackage); + + try { + /* + * Save the resource + */ + metaResource.save(null); + } catch (java.io.IOException e) { + e.printStackTrace(); + } + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/java/LoadResourceFileTest.java b/Source/eu.modelwriter.core.alloyinecore/src/test/java/LoadResourceFileTest.java new file mode 100644 index 00000000..0fa756df --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/java/LoadResourceFileTest.java @@ -0,0 +1,45 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl; + +import java.io.IOException; + +public class LoadResourceFileTest { + + public static void main(final String[] args) { + URI resourceURI = URI.createFileURI("./Instance.requirements"); + Resource resource = new XMLResourceImpl(resourceURI); + try { + resource.load(null); + } catch (IOException e) { + e.printStackTrace(); + } + System.out.println(resource); + + + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/java/Utilities.java b/Source/eu.modelwriter.core.alloyinecore/src/test/java/Utilities.java new file mode 100644 index 00000000..df7e18e2 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/java/Utilities.java @@ -0,0 +1,58 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import java.awt.Toolkit; +import java.util.Arrays; + +import javax.swing.JFrame; +import javax.swing.JScrollPane; + +//import org.antlr.v4.gui.TreeViewer; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser; + +public class Utilities { + + + public static void showParseTree(AlloyInEcoreParser parser, ParseTree tree) { + // // show AST in GUI +// final JFrame frame = new JFrame("AlloyInECore AST"); +// +// final JScrollPane scrollPane = new JScrollPane(); +// scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); +// scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); +// scrollPane.setBounds(0, 0, 500, 700); +// +// final TreeViewer viewr = new TreeViewer(Arrays.asList(parser.getRuleNames()), tree); +// viewr.setScale(1); +// scrollPane.getViewport().add(viewr); +// +// frame.add(scrollPane); +// frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); +// frame.setSize(Toolkit.getDefaultToolkit().getScreenSize().width, 500); +// frame.setVisible(true); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/java/VisitorTest.java b/Source/eu.modelwriter.core.alloyinecore/src/test/java/VisitorTest.java new file mode 100644 index 00000000..b27c1388 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/java/VisitorTest.java @@ -0,0 +1,88 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreLexer; +import eu.modelwriter.core.alloyinecore.recognizer.AlloyInEcoreParser; +import eu.modelwriter.core.alloyinecore.recognizer.UnderlineErrorListener; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.atn.PredictionMode; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; + +public class VisitorTest { + + public static void main(final String[] args) { + visit(); + } + + @Test + public void testVisit() { + visit(); + } + + private static void visit() { + long start = System.currentTimeMillis(); + ANTLRInputStream input = null; + final File file = new File("./src/test/resources/AlloyInECore/Generics1.recore"); + try { + input = new ANTLRFileStream(file.getAbsolutePath()); + } catch (final IOException e) { + e.printStackTrace(); + } + final AlloyInEcoreLexer lexer = new AlloyInEcoreLexer(input); + final CommonTokenStream tokens = new CommonTokenStream(lexer); + final AlloyInEcoreParser parser = new AlloyInEcoreParser(tokens); + parser.getInterpreter().setPredictionMode(PredictionMode.SLL); // try with simpler/faster SLL(*) + // we don't want error messages or recovery during first try + parser.removeErrorListeners(); + parser.setErrorHandler(new BailErrorStrategy()); + try { + parser.model(); + // if we get here, there was no syntax error and SLL(*) was enough; + // there is no need to try full LL(*) + } + catch (RuntimeException ex) { + if (ex.getClass() == RuntimeException.class && + ex.getCause() instanceof RecognitionException) + { + // The BailErrorStrategy wraps the RecognitionExceptions in + // RuntimeExceptions so we have to make sure we're detecting + // a true RecognitionException not some other kind + tokens.reset(); // rewind input stream + // back to standard listeners/handlers + parser.addErrorListener(new UnderlineErrorListener()); + parser.setErrorHandler(new DefaultErrorStrategy()); + parser.getInterpreter().setPredictionMode(PredictionMode.LL); // try full LL(*) + parser.model(); + } + } + DummyVisitor visitor = new DummyVisitor(); + System.out.println(visitor.visit(parser.model)); + long finish = System.currentTimeMillis(); + System.out.println(finish - start); + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/java/instance/Instance.g4 b/Source/eu.modelwriter.core.alloyinecore/src/test/java/instance/Instance.g4 new file mode 100644 index 00000000..15cd7b08 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/java/instance/Instance.g4 @@ -0,0 +1,123 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +grammar Instance; + +/* +Identifying class instance (objects) +===================================== +Since the value of the attribute selected as the identifying attribute is presented in the class instance’s introduction, +its normal representation within the body of the instance’s definition is superfluous, and is thus omitted. + +By default, identifying strings (be they arbitrary or the value of an attribute) are required to be unique over the +set of instance of the class, and over all instance of its subtypes. + +Attributes whose lower multiplicity bound is 0 may be explicitly unset by assigning them to the ‘null’ keyword. + +The association name is optionally displayed before the contained class instance to allow disambiguation for MOF models +that have more than one possible containment association between the container and the contained instance. + +Three reserved words: “true” and “false” for representing boolean values, and “null” for unsetting attribute values. + +‘+’ and ‘-’ can be used to indicate the positive/negative sign of the value. + +*/ +instance : + packageImport* model (rootObject= eObject | ';') + ; + +packageImport: + ('import') (name= unrestrictedName ':')? ownedPathName= SINGLE_QUOTED_STRING ';' + ; + +model: + ('model') (name= unrestrictedName ':')? ownedPathName= SINGLE_QUOTED_STRING ';' + ; + +eObject: + name= className id= value? ('{' slot+= content (',' slot+= content)* '}' | ';') ; + +className: pathName; + +content: + name= unrestrictedName (':' (dataValue | '{' eObject* '}' | objectReference))?; + +dataValue: value | multiValueData; + +multiValueData: '[' dataValue (',' dataValue)* ']' ; + +objectReference: pathName | ('[' pathName (',' pathName)* ']'); + +pathName: firstSegment= unrestrictedName ('.' index= INT)? (midSegments+= segment* lastSegment= segment)? ; + +segment:'::' '@'? name= unrestrictedName ('.' index= INT)?; + +value: + identifier + | numericValue + | stringValue + | charValue + | booleanValue + | nullValue + ; + +unrestrictedName: + identifier + | 'import' + | 'model' +; + +booleanValue: 'true' | 'false'; + +numericValue: ('+' | '-')? INT? '.'? INT ; + +identifier: IDENTIFIER; + +stringValue: DOUBLE_QUOTED_STRING; + +charValue: SINGLE_CHARACTER; + +nullValue: 'null'; + +INT : DIGIT+ ; + +IDENTIFIER : (UNDERSCORE | LETTER) (LETTER | APOSTROPHE | DIGIT | UNDERSCORE | DOLLAR)* ; +SINGLE_CHARACTER: '\'' ~['\\] '\''; +DOUBLE_QUOTED_STRING: '"' ( ESCAPED_CHARACTER | ~('\\' | '"' ) )* '"' ; +SINGLE_QUOTED_STRING: '\'' ( ESCAPED_CHARACTER | ~('\'' | '\\') )* '\'' ; + + +fragment LETTER: [a-zA-Z]; +fragment DIGITS : DIGIT+ ; +fragment DIGIT: [0-9]; +fragment ESCAPED_CHARACTER: '\\' ('b' | 't' | 'n' | 'f' | 'r' | 'u' | '"' | '\'' | '\\'); +fragment UNDERSCORE: '_'; +fragment APOSTROPHE: '\''; +fragment DOLLAR: '$'; +fragment MINUS: '-'; +ML_SINGLE_QUOTED_STRING : '\'' .*? '\'' -> skip; +MULTILINE_COMMENT : '/*' .*? '*/' -> skip; +SINGLELINE_COMMENT : '--' .*? '\r'? '\n' -> skip; + +WS : [ \r\t\n]+ -> skip ; \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/java/instance/temp/Instance.requirement b/Source/eu.modelwriter.core.alloyinecore/src/test/java/instance/temp/Instance.requirement new file mode 100644 index 00000000..ec4fefa0 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/java/instance/temp/Instance.requirement @@ -0,0 +1,56 @@ +model RequirementsMetamodel : 'Requirements.ecore'; + +RequirementsModel +{ + name: "My requirements", + requirements: + { + Requirement "A" + { + ID: 0, + reason: "", + parts: + { + test::PartTypeA + { + name: "s" + } + test::PartTypeB + { + name: "s" + } + } + } + Requirement "D" + { + ID: 0 + } + Requirement "B" + { + ID: 1 + } + Requirement "E" + { + ID: 0 + } + Requirement "D" + { + ID: 0 + } + }, + relationships: + { + Require + { + source: A, + target: [B, C] + } + }, + composedOf: + { + Requirement "C" + { + ID: 2 + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/java/instance/temp/Instance.xmi b/Source/eu.modelwriter.core.alloyinecore/src/test/java/instance/temp/Instance.xmi new file mode 100644 index 00000000..9fd845c7 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/java/instance/temp/Instance.xmi @@ -0,0 +1,25 @@ + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/java/instance/temp/Requirement.ecore b/Source/eu.modelwriter.core.alloyinecore/src/test/java/instance/temp/Requirement.ecore new file mode 100644 index 00000000..70fd43cb --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/java/instance/temp/Requirement.ecore @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/java/instance/temp/Requirement.recore b/Source/eu.modelwriter.core.alloyinecore/src/test/java/instance/temp/Requirement.recore new file mode 100644 index 00000000..7f22fe46 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/java/instance/temp/Requirement.recore @@ -0,0 +1,51 @@ +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package RequirementsMetamodel : Req = 'eu.modelwriter.demonstrations.alloyinecore.requirement' +{ + class RequirementsModel + { + attribute name : String[?]; + property requirements : Requirement[*] { ordered composes }; + property relationships : Relationship[*] { ordered composes }; + } + class Requirement + { + attribute ID : Integer[?]; + attribute name : String[?] { id }; + attribute description : String[?]; + attribute reason : String[?]; + property parts : RequirementsMetamodel::test::RequirementPart[*] { ordered composes }; + } + abstract class Relationship + { + property source : Requirement[?]; + property target : Requirement[*] { ordered }; + } + enum Status + { + literal proposed = 0; + literal analyzed = 1; + literal accepted = 2; + literal rejected = 3; + literal replaced = 4; + } + enum Priority + { + literal neutral = 0; + literal lowCritical = 1; + literal critical = 2; + literal veryCritical = 3; + } + class Require extends Relationship; + class Refine extends Relationship; + class PartiallyRefine extends Relationship; + class Conflict extends Relationship; + class Contain extends Relationship; + package test : tt = 'test/test' + { + class RequirementPart + { + attribute name : String[?]; + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/java/instance/temp/test.xmi b/Source/eu.modelwriter.core.alloyinecore/src/test/java/instance/temp/test.xmi new file mode 100644 index 00000000..dee58669 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/java/instance/temp/test.xmi @@ -0,0 +1,71 @@ +import Tutorial : 'Tutorial.ecore'; +import Tutorial2 : 'Tutorial.xmi'; + +model RequirementsMetamodel : 'Requirements.ecore' + +RequirementsModel +{ + name: "My requirements", + requirements: + { + Requirement "A" + { + ID: 0, + reason: "", + parts: + { + test::PartTypeA + { + name: "s\"s", + enum: analyzed + } + test::PartTypeB + { + name: "s", + enum: proposed + } + } + } + Requirement "D" + { + ID, + reason: null, + outref: + { + Tutorial::Loan + { + date: "Tue Jan 01 00:00:00 EET 205", + book: Tutorial2::b2, + member: Tutorial2::members.0 + } + } + } + Requirement "B"; + Requirement "B" + { + ID: 1, + reason: "defff" + } + Requirement "E" + { + ID: 0, + reason: 0.125 + } + }, + relationships: + { + Require + { + source: A, + target: [B, C] + } + }, + composedOf: + { + Requirement "C" + { + ID: 2, + reason: "defff" + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/java/playground/GuavaTester_MultiMap.java b/Source/eu.modelwriter.core.alloyinecore/src/test/java/playground/GuavaTester_MultiMap.java new file mode 100644 index 00000000..c21e30c4 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/java/playground/GuavaTester_MultiMap.java @@ -0,0 +1,93 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package playground; + +import com.google.common.collect.LinkedListMultimap; +import com.google.common.collect.Multimap; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +//https://www.tutorialspoint.com/guava/guava_multimap.htm +public class GuavaTester_MultiMap { + public static void main(String args[]) { + + //Map> + // lower -> a, b, c, d, e + // upper -> A, B, C, D + + Multimap multimap = LinkedListMultimap.create(); + + multimap.put("lower", "a"); + multimap.put("lower", "b"); + multimap.put("lower", "c"); + multimap.put("lower", "d"); + multimap.put("lower", "e"); + + multimap.put("upper", "A"); + multimap.put("upper", "B"); + multimap.put("upper", "C"); + multimap.put("upper", "D"); + + Collection lowerList = multimap.get("lower"); + System.out.println("Initial lower case list"); + System.out.println(lowerList.toString()); + + lowerList.add("f"); + System.out.println("Modified lower case list"); + System.out.println(lowerList.toString()); + + Collection upperList = multimap.get("upper"); + System.out.println("Initial upper case list"); + System.out.println(upperList.toString()); + + upperList.remove("D"); + System.out.println("Modified upper case list"); + System.out.println(upperList.toString()); + + Map> map = multimap.asMap(); + System.out.println("Multimap as a map"); + + for (Map.Entry> entry : map.entrySet()) { + String key = entry.getKey(); + Collection value = multimap.get("lower"); + System.out.println(key + ":" + value); + } + + System.out.println("Keys of Multimap"); + Set keys = multimap.keySet(); + + for(String key:keys){ + System.out.println(key); + } + + System.out.println("Values of Multimap"); + Collection values = multimap.values(); + System.out.println(values); + + } + +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/java/playground/GuavaTester_MultiMap1.java b/Source/eu.modelwriter.core.alloyinecore/src/test/java/playground/GuavaTester_MultiMap1.java new file mode 100644 index 00000000..a0075fb3 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/java/playground/GuavaTester_MultiMap1.java @@ -0,0 +1,79 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package playground; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; + +import java.util.*; + +public class GuavaTester_MultiMap1 { + private static final Set farmAnimals = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("Cow","Pig","Sheep"))); + private static final Set farmAnimals1 = ImmutableSet.of("Cow","Pig","Sheep"); + + // use copyOf()... + public void doStuffWithList(List unsafeList) { + List safeList = ImmutableList.copyOf(unsafeList); + } + + public static void main(String... args) { + + Multimap myMultimap = ArrayListMultimap.create(); + // Adding some key/value + myMultimap.put("Fruits", "Banana"); + myMultimap.put("Fruits", "Apple"); + myMultimap.put("Fruits", "Pear"); + myMultimap.put("Vegetables", "Carrot"); + + // Getting the size + int size = myMultimap.size(); + System.out.println(size); // 4 + + // Getting values + Collection fruits = myMultimap.get("Fruits"); + System.out.println(fruits); // [Bannana, Apple, Pear] + + Collection vegetables = myMultimap.get("Vegetables"); + System.out.println(vegetables); // [Carrot] + + // Iterating over entire Mutlimap + for(String value : myMultimap.values()) { + System.out.println(value); + } + + // Removing a single value + myMultimap.remove("Fruits","Pear"); + System.out.println(myMultimap.get("Fruits")); // [Bannana, Pear] + + // Remove all values for a key + myMultimap.removeAll("Fruits"); + System.out.println(myMultimap.get("Fruits")); // [] (Empty Collection!) + + } +} + + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/java/playground/GuavaTester_MultiSet.java b/Source/eu.modelwriter.core.alloyinecore/src/test/java/playground/GuavaTester_MultiSet.java new file mode 100644 index 00000000..4d6c7e91 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/java/playground/GuavaTester_MultiSet.java @@ -0,0 +1,118 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package playground;/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import com.google.common.collect.HashMultiset; +import com.google.common.collect.Multiset; + +import java.util.Iterator; +import java.util.Set; + +//https://www.tutorialspoint.com/guava/guava_multiset.htm +public class GuavaTester_MultiSet { + + public static void main(String args[]) { + + //create a multiset collection + Multiset multiset = HashMultiset.create(); + + multiset.add("a"); + multiset.add("b"); + multiset.add("c"); + multiset.add("d"); + multiset.add("a"); + multiset.add("b"); + multiset.add("c"); + multiset.add("b"); + multiset.add("b"); + multiset.add("b"); + + //print the occurrence of an element + System.out.println("Occurrence of 'b' : "+multiset.count("b")); + + //print the total size of the multiset + System.out.println("Total Size : "+multiset.size()); + + //get the distinct elements of the multiset as set + Set set = multiset.elementSet(); + + //display the elements of the set + System.out.print("Set ["); + + for (String s : set) { + System.out.print(s + ", "); + } + + System.out.print("]"); + System.out.println(); + + //display all the elements of the multiset using iterator + Iterator iterator = multiset.iterator(); + System.out.print("MultiSet ["); + + while(iterator.hasNext()){ + System.out.print(iterator.next() + ", "); + } + + System.out.println("]"); + + //display the distinct elements of the multiset with their occurrence count + System.out.println("MultiSet ["); + + for (Multiset.Entry entry : multiset.entrySet()) + { + System.out.println("[ModelElement: " + entry.getElement() + ", Occurrence(s): " + entry.getCount() + "]"); + } + System.out.println("]"); + + //remove extra occurrences + multiset.remove("b",2); + + //print the occurrence of an element + System.out.println("Occurence of 'b' : " + multiset.count("b")); + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/java/playground/GuavaTester_Table.java b/Source/eu.modelwriter.core.alloyinecore/src/test/java/playground/GuavaTester_Table.java new file mode 100644 index 00000000..8b4eb196 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/java/playground/GuavaTester_Table.java @@ -0,0 +1,93 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package playground; + +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; + +import java.util.Map; +import java.util.Set; + +//https://www.tutorialspoint.com/guava/guava_table.htm +public class GuavaTester_Table { + public static void main(String args[]) { + + //Table == Map> + /* + * Company: IBM, Microsoft, TCS + * IBM -> {101:Mahesh, 102:Ramesh, 103:Suresh} + * Microsoft -> {101:Sohan, 102:Mohan, 103:Rohan } + * TCS -> {101:Ram, 102: Shyam, 103: Sun il } + * + * */ + + //create a table + Table employeeTable = HashBasedTable.create(); + + //initialize the table with employee details + employeeTable.put("IBM", "101","Mahesh"); + employeeTable.put("IBM", "102","Ramesh"); + employeeTable.put("IBM", "103","Suresh"); + + employeeTable.put("Microsoft", "101","Sohan"); + employeeTable.put("Microsoft", "112","Mohan"); + employeeTable.put("Microsoft", "113","Rohan"); + + employeeTable.put("TCS", "121","Ram"); + employeeTable.put("TCS", "122","Shyam"); + employeeTable.put("TCS", "123","Sunil"); + + //get Map corresponding to IBM + Map ibmEmployees = employeeTable.row("IBM"); + + System.out.println("List of IBM Employees"); + + for(Map.Entry entry : ibmEmployees.entrySet()){ + System.out.println("Emp Id: " + entry.getKey() + ", Name: " + entry.getValue()); + } + + //get all the unique keys of the table + Set employers = employeeTable.rowKeySet(); + System.out.print("Employers: "); + + for(String employer: employers){ + System.out.print(employer + " "); + } + + System.out.println(); + + //get a Map corresponding to 102 + Map EmployerMap = employeeTable.column("102"); + + for(Map.Entry entry : EmployerMap.entrySet()){ + System.out.println("Employer: " + entry.getKey() + ", Name: " + entry.getValue()); + } + + final Map microsoft = employeeTable.row("Microsoft"); + System.out.println(microsoft.get("111")); + + + } +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/java/playground/Test.java b/Source/eu.modelwriter.core.alloyinecore/src/test/java/playground/Test.java new file mode 100644 index 00000000..50288f0f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/java/playground/Test.java @@ -0,0 +1,31 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017, Ferhat Erata + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package playground; + +/** + * Created by ferhat on 1/16/17. + */ +public class Test { +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/AttrTest.recore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/AttrTest.recore new file mode 100644 index 00000000..2cb68cb9 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/AttrTest.recore @@ -0,0 +1,41 @@ +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package TestPackage : tp = 'www.testpackage.org' +{ + private class TestClass extends SuperClass, UberClass : 'TCname' + { + private static model transient volatile nullable readonly attribute testAttr : Ecore::EDate[?] = '2017-01-01' { !unique derived unsettable ordered id } + { + derivation : ~testAttr; + } + model nullable attribute testStringAttr : String[?] = '' { ordered }; + ghost attribute testRealAttr : Real[?] = '0.0' { ordered }; + transient volatile attribute testBooleanAttr : Boolean[?] = 'false' { ordered }; + private transient attribute testIntAttr : Integer[?] = '1' { ordered }; + attribute testAttr1 : Integer[1] = '1' { ordered }; + attribute testAttr2 : Integer[+] = '1' { ordered }; + attribute testAttr3 : Integer[*] = '1' { ordered }; + attribute testAttr4 : Integer[2..5] = '1' { ordered }; + attribute testAttr5 : Integer[?] = '1' { ordered }; + attribute testUnlimitedNaturalAttr : UnlimitedNatural[?] = '1' { ordered }; + } + interface TestInterface extends SuperClass : 'TIname'; + enum TestEnum : 'TEname' { !serializable }; + primitive datatype TestDataType : 'TDTname' { !serializable }; + abstract class SuperClass; + abstract class UberClass; + package SubPackage : sp = 'www.sub.testpackage.org' + { + class SubTestClass + { + attribute testIntAttr : Integer[?] = '0' { ordered }; + attribute testStringAttr : String[?] = '' { ordered }; + attribute testRealAttr : Real[?] = '0' { ordered }; + transient volatile attribute testBooleanAttr : Boolean[?] = 'false' { ordered }; + transient attribute testAttr : Ecore::EDate[?] = '2016-09-09' { ordered }; + } + interface SubTestInterface; + enum SubTestEnum; + datatype SubTestDataType : 'STDTname'; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Ecore.ecore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Ecore.ecore new file mode 100644 index 00000000..15a3569f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Ecore.ecore @@ -0,0 +1,526 @@ + + + + +
+ + + + + + +
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + +
+
+ + + + + + +
+ + + + + + + +
+
+ + + + + + + + + + +
+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + +
+
+ + + + +
+
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+
+ + + + +
+ + + + +
+ + + + +
+
+ + + + + +
+
+ + + + + + +
+ + + + +
+
+ + + + + + + + + + +
+ + + + +
+
+ + + + +
+ + + + +
+
+ + + + + + + + +
+ + + + +
+
+ + + + + + + + + + +
+ + + + +
+
+ + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Ecore.recore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Ecore.recore new file mode 100644 index 00000000..1ef27747 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Ecore.recore @@ -0,0 +1,443 @@ +package ecore : ecore = 'http://www.eclipse.org/emf/2002/Ecore' +{ + class EAttribute extends EStructuralFeature + { + attribute iD : EBoolean[?] { ordered }; + transient volatile readonly property eAttributeType : EDataType[1] { derived ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ConsistentTransient' + ); + } + class EAnnotation extends EModelElement + { + attribute source : EString[?] { ordered }; + property details : EStringToStringMapEntry[*] { ordered !resolve composes }; + transient property eModelElement#eAnnotations : EModelElement[?] { ordered !resolve }; + property contents : EObject[*] { ordered !resolve composes }; + property references : EObject[*] { ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedSourceURI' + ); + } + class EClass extends EClassifier + { + attribute abstract : EBoolean[?] { ordered }; + attribute interface : EBoolean[?] { ordered }; + operation isSuperTypeOf(someClass : EClass[?] { ordered }) : EBoolean[?] { ordered }; + operation getFeatureCount() : EInt[?] { ordered }; + operation getEStructuralFeature(featureID : EInt[?] { ordered }) : EStructuralFeature[?] { ordered }; + operation getFeatureID(feature : EStructuralFeature[?] { ordered }) : EInt[?] { ordered }; + operation getEStructuralFeature(featureName : EString[?] { ordered }) : EStructuralFeature[?] { ordered }; + operation getOperationCount() : EInt[?] { ordered }; + operation getEOperation(operationID : EInt[?] { ordered }) : EOperation[?] { ordered }; + operation getOperationID(operation : EOperation[?] { ordered }) : EInt[?] { ordered }; + operation getOverride(operation : EOperation[?] { ordered }) : EOperation[?] { ordered }; + operation getFeatureType(feature : EStructuralFeature[?] { ordered }) : EGenericType[?] { ordered }; + property eSuperTypes : EClass[*] { unsettable ordered } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + property eOperations#eContainingClass : EOperation[*] { ordered !resolve composes }; + transient volatile readonly property eAllAttributes : EAttribute[*] { derived ordered }; + transient volatile readonly property eAllReferences : EReference[*] { derived ordered }; + transient volatile readonly property eReferences : EReference[*] { derived ordered }; + transient volatile readonly property eAttributes : EAttribute[*] { derived ordered }; + transient volatile readonly property eAllContainments : EReference[*] { derived ordered }; + transient volatile readonly property eAllOperations : EOperation[*] { derived ordered }; + transient volatile readonly property eAllStructuralFeatures : EStructuralFeature[*] { derived ordered }; + transient volatile readonly property eAllSuperTypes : EClass[*] { derived ordered }; + transient volatile readonly property eIDAttribute : EAttribute[?] { derived ordered !resolve }; + property eStructuralFeatures#eContainingClass : EStructuralFeature[*] { ordered !resolve composes }; + property eGenericSuperTypes : EGenericType[*] { unsettable ordered !resolve composes } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + transient volatile readonly property eAllGenericSuperTypes : EGenericType[*] { derived ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'InterfaceIsAbstract AtMostOneID UniqueFeatureNames UniqueOperationSignatures NoCircularSuperTypes WellFormedMapEntryClass ConsistentSuperTypes DisjointFeatureAndOperationSignatures' + ); + } + abstract class EClassifier extends ENamedElement + { + volatile attribute instanceClassName : EString[?] { unsettable ordered } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + transient volatile readonly attribute instanceClass : EJavaClass[?] { derived ordered }; + transient volatile readonly attribute defaultValue : EJavaObject[?] { derived ordered }; + volatile attribute instanceTypeName : EString[?] { unsettable ordered } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + operation isInstance(object : EJavaObject[?] { ordered }) : EBoolean[?] { ordered }; + operation getClassifierID() : EInt[?] { ordered }; + transient readonly property ePackage#eClassifiers : EPackage[?] { ordered }; + property eTypeParameters : ETypeParameter[*] { ordered composes }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedInstanceTypeName UniqueTypeParameterNames' + ); + } + class EDataType extends EClassifier + { + attribute serializable : EBoolean[?] = 'true' { ordered }; + } + class EEnum extends EDataType + { + operation getEEnumLiteral(name : EString[?] { ordered }) : EEnumLiteral[?] { ordered }; + operation getEEnumLiteral(value : EInt[?] { ordered }) : EEnumLiteral[?] { ordered }; + operation getEEnumLiteralByLiteral(literal : EString[?] { ordered }) : EEnumLiteral[?] { ordered }; + property eLiterals#eEnum : EEnumLiteral[*] { ordered !resolve composes }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'UniqueEnumeratorNames UniqueEnumeratorLiterals' + ); + } + class EEnumLiteral extends ENamedElement + { + attribute value : EInt[?] { ordered }; + transient attribute instance : EEnumerator[?] { ordered }; + attribute literal : EString[?] { ordered }; + transient readonly property eEnum#eLiterals : EEnum[?] { ordered !resolve }; + } + class EFactory extends EModelElement + { + operation create(eClass : EClass[?] { ordered }) : EObject[?] { ordered }; + operation createFromString(eDataType : EDataType[?] { ordered }, literalValue : EString[?] { ordered }) : EJavaObject[?] { ordered }; + operation convertToString(eDataType : EDataType[?] { ordered }, instanceValue : EJavaObject[?] { ordered }) : EString[?] { ordered }; + transient property ePackage#eFactoryInstance : EPackage[1] { ordered !resolve }; + } + abstract class EModelElement + { + operation getEAnnotation(source : EString[?] { ordered }) : EAnnotation[?] { ordered }; + property eAnnotations#eModelElement : EAnnotation[*] { ordered !resolve composes }; + } + abstract class ENamedElement extends EModelElement + { + attribute name : EString[?] { ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedName' + ); + } + class EObject + { + operation eClass() : EClass[?] { ordered }; + operation eIsProxy() : EBoolean[?] { ordered }; + operation eResource() : EResource[?] { ordered }; + operation eContainer() : EObject[?] { ordered }; + operation eContainingFeature() : EStructuralFeature[?] { ordered }; + operation eContainmentFeature() : EReference[?] { ordered }; + operation eContents() : EEList[?] { ordered }; + operation eAllContents() : ETreeIterator[?] { ordered }; + operation eCrossReferences() : EEList[?] { ordered }; + operation eGet(feature : EStructuralFeature[?] { ordered }) : EJavaObject[?] { ordered }; + operation eGet(feature : EStructuralFeature[?] { ordered }, resolve : EBoolean[?] { ordered }) : EJavaObject[?] { ordered }; + operation eSet(feature : EStructuralFeature[?] { ordered }, newValue : EJavaObject[?] { ordered }) { ordered }; + operation eIsSet(feature : EStructuralFeature[?] { ordered }) : EBoolean[?] { ordered }; + operation eUnset(feature : EStructuralFeature[?] { ordered }) { ordered }; + operation eInvoke(operation : EOperation[?] { ordered }, arguments : EEList[?] { ordered }) : EJavaObject[?] throws EInvocationTargetException { ordered }; + } + class EOperation extends ETypedElement + { + operation getOperationID() : EInt[?] { ordered }; + operation isOverrideOf(someOperation : EOperation[?] { ordered }) : EBoolean[?] { ordered }; + transient readonly property eContainingClass#eOperations : EClass[?] { ordered !resolve }; + property eTypeParameters : ETypeParameter[*] { ordered composes }; + property eParameters#eOperation : EParameter[*] { ordered !resolve composes }; + property eExceptions : EClassifier[*] { unsettable ordered } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + property eGenericExceptions : EGenericType[*] { unsettable ordered !resolve composes } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'UniqueParameterNames UniqueTypeParameterNames NoRepeatingVoid' + ); + } + class EPackage extends ENamedElement + { + attribute nsURI : EString[?] { ordered }; + attribute nsPrefix : EString[?] { ordered }; + operation getEClassifier(name : EString[?] { ordered }) : EClassifier[?] { ordered }; + transient property eFactoryInstance#ePackage : EFactory[1] { ordered !resolve }; + property eClassifiers#ePackage : EClassifier[*] { ordered composes }; + property eSubpackages#eSuperPackage : EPackage[*] { ordered composes }; + transient readonly property eSuperPackage#eSubpackages : EPackage[?] { ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedNsURI WellFormedNsPrefix UniqueSubpackageNames UniqueClassifierNames UniqueNsURIs' + ); + } + class EParameter extends ETypedElement + { + transient readonly property eOperation#eParameters : EOperation[?] { ordered !resolve }; + } + class EReference extends EStructuralFeature + { + attribute containment : EBoolean[?] { ordered }; + transient volatile readonly attribute container : EBoolean[?] { derived ordered }; + attribute resolveProxies : EBoolean[?] = 'true' { ordered }; + property eOpposite : EReference[?] { ordered }; + transient volatile readonly property eReferenceType : EClass[1] { derived ordered }; + property eKeys : EAttribute[*] { ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ConsistentOpposite SingleContainer ConsistentKeys ConsistentUnique ConsistentContainer' + ); + } + abstract class EStructuralFeature extends ETypedElement + { + attribute changeable : EBoolean[?] = 'true' { ordered }; + attribute volatile : EBoolean[?] { ordered }; + attribute transient : EBoolean[?] { ordered }; + attribute defaultValueLiteral : EString[?] { ordered }; + transient volatile readonly attribute defaultValue : EJavaObject[?] { derived ordered }; + attribute unsettable : EBoolean[?] { ordered }; + attribute derived : EBoolean[?] { ordered }; + operation getFeatureID() : EInt[?] { ordered }; + operation getContainerClass() : EJavaClass[?] { ordered }; + transient readonly property eContainingClass#eStructuralFeatures : EClass[?] { ordered !resolve }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ValidDefaultValueLiteral' + ); + } + abstract class ETypedElement extends ENamedElement + { + attribute ordered : EBoolean[?] = 'true' { ordered }; + attribute unique : EBoolean[?] = 'true' { ordered }; + attribute lowerBound : EInt[?] { ordered }; + attribute upperBound : EInt[?] = '1' { ordered }; + transient volatile readonly attribute many : EBoolean[?] { derived ordered }; + transient volatile readonly attribute required : EBoolean[?] { derived ordered }; + volatile property eType : EClassifier[?] { unsettable ordered } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + volatile property eGenericType : EGenericType[?] { unsettable ordered !resolve composes } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ValidLowerBound ValidUpperBound ConsistentBounds ValidType' + ); + } + datatype EBigDecimal : 'java.math.BigDecimal' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#decimal' + ); + } + datatype EBigInteger : 'java.math.BigInteger' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#integer' + ); + } + datatype EBoolean : 'boolean' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#boolean' + ); + } + datatype EBooleanObject : 'java.lang.Boolean' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EBoolean', + 'name' = 'EBoolean:Object' + ); + } + datatype EByte : 'byte' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#byte' + ); + } + datatype EByteArray : 'byte[]' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#hexBinary' + ); + } + datatype EByteObject : 'java.lang.Byte' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EByte', + 'name' = 'EByte:Object' + ); + } + datatype EChar : 'char'; + datatype ECharacterObject : 'java.lang.Character' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EChar', + 'name' = 'EChar:Object' + ); + } + datatype EDate : 'java.util.Date'; + datatype EDiagnosticChain : 'org.eclipse.emf.common.util.DiagnosticChain' { !serializable }; + datatype EDouble : 'double' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#double' + ); + } + datatype EDoubleObject : 'java.lang.Double' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EDouble', + 'name' = 'EDouble:Object' + ); + } + datatype EEList : 'org.eclipse.emf.common.util.EList' { !serializable }; + datatype EEnumerator : 'org.eclipse.emf.common.util.Enumerator' { !serializable }; + datatype EFeatureMap : 'org.eclipse.emf.ecore.util.FeatureMap' { !serializable }; + datatype EFeatureMapEntry : 'org.eclipse.emf.ecore.util.FeatureMap$Entry' { !serializable }; + datatype EFloat : 'float' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#float' + ); + } + datatype EFloatObject : 'java.lang.Float' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EFloat', + 'name' = 'EFloat:Object' + ); + } + datatype EInt : 'int' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#int' + ); + } + datatype EIntegerObject : 'java.lang.Integer' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EInt', + 'name' = 'EInt:Object' + ); + } + datatype EJavaClass : 'java.lang.Class'; + datatype EJavaObject : 'java.lang.Object'; + datatype ELong : 'long' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#long' + ); + } + datatype ELongObject : 'java.lang.Long' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'ELong', + 'name' = 'ELong:Object' + ); + } + datatype EMap : 'java.util.Map' { !serializable }; + datatype EResource : 'org.eclipse.emf.ecore.resource.Resource' { !serializable }; + datatype EResourceSet : 'org.eclipse.emf.ecore.resource.ResourceSet' { !serializable }; + datatype EShort : 'short' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#short' + ); + } + datatype EShortObject : 'java.lang.Short' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EShort', + 'name' = 'EShort:Object' + ); + } + datatype EString : 'java.lang.String' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#string' + ); + } + class EStringToStringMapEntry : 'java.util.Map$Entry' + { + attribute key : EString[?] { ordered }; + attribute value : EString[?] { ordered }; + } + datatype ETreeIterator : 'org.eclipse.emf.common.util.TreeIterator' { !serializable }; + class EGenericType + { + operation isInstance(object : EJavaObject[?] { ordered }) : EBoolean[?] { ordered }; + property eUpperBound : EGenericType[?] { ordered !resolve composes }; + property eTypeArguments : EGenericType[*] { ordered !resolve composes }; + transient readonly property eRawType : EClassifier[1] { derived ordered }; + property eLowerBound : EGenericType[?] { ordered !resolve composes }; + property eTypeParameter : ETypeParameter[?] { ordered !resolve }; + property eClassifier : EClassifier[?] { ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ConsistentType ConsistentBounds ConsistentArguments' + ); + } + class ETypeParameter extends ENamedElement + { + property eBounds : EGenericType[*] { ordered !resolve composes }; + } + datatype EInvocationTargetException : 'java.lang.reflect.InvocationTargetException' { !serializable }; +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Erroneous.kodkod b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Erroneous.kodkod new file mode 100644 index 00000000..2be8b6e8 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Erroneous.kodkod @@ -0,0 +1,15 @@ +universe {d0, d1, d2, d3, f0, f0, f1, f2, f3,} + +relations { + File : [ {(f0), (f1), (f2)} ] + Dir : [ {(d0), (d1), (d2)} ] + Root: [{(d0)}] + Root: [{(d0)}] + contents:[{[d0, d1], [d0, f0], [kk, f0], [d0, f1], [d0, f2]}, {[d0, d1], [d0, f0], [d0, f1], [d0, f2], [d1, d2]}] +} + +contents in Dir lone -> some (Dir + File) +all d:Dir | not (x in d.^contents) +Root in Dir +all d: dir | not (x in d.^contents) +(File + Dir) in Root.*contents \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Filesystem.kodkod b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Filesystem.kodkod new file mode 100644 index 00000000..dcc9c70f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Filesystem.kodkod @@ -0,0 +1,13 @@ +universe {d0, d1, d2, d3, f0, f1, f2, f3} + +relations { + File : [ {(f0), (f1), (f2)} ] + Dir : [ {(d0), (d1), (d2)} ] + Root: [{(d0)}] + contents: [{[d0, d1], [d0, f0], [d0, f1], [d0, f2]}, {[d0, d1], [d0, f0], [d0, f1], [d0, f2], [d1, d2]}] +} + +contents in Dir lone -> some (Dir + File) +all d:Dir | not (d in d.^contents) +Root in Dir +(File + Dir) in Root.*contents \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Generics1.recore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Generics1.recore new file mode 100644 index 00000000..7c9ae017 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Generics1.recore @@ -0,0 +1,72 @@ +import My : 'My.ecore'; +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; +import Instance : 'Instance.requirements'; + +package generics : gns = 'eu.modelwriter.generics' +{ + abstract class List + { + --invariant test: all c: Canvas | lone c; + invariant test: ~Canvas = *Iterator; + operation add(element : E); + operation iterator() : Iterator[?]; + invariant quantifier: all d:List | not (d in d.^contents); + } + invariant test1: contents in Dir -> (Dir + File); + interface Iterator + { + invariant test2: (File + Dir) in Root.*contents; + operation next() : E[?] throws MyException; + operation hasNext() : Boolean; + } + class ArrayList extends List; + class Car; + abstract class Person { attribute name: String [1]; } + class Owner + { + property cars : ArrayList[?]; + property owner : V[1..*]; + } + abstract class Shape; + class Canvas + { + operation draw(shapes : List, x: Integer, y: Integer) : Boolean[?]; + operation create(name : String); + operation create(arg : ArrayList[?]) + { + requires : one ArrayList; + body; + } + property ref : List[?]; + property heyRef: sub::Hey; + property noWay: sub::subsub::CantTouchThis; + property b : My::A[2..5|?]; + attribute c: String; + attribute d: V[*|?]; + annotation; + annotation 'modelwriter/Ferhat' ('key' = , 'key' = 'value', =) + { + reference Library::books; + class AnnotationClass extends Person , Car; + property mehmet: type[+|1]; + reference Instance::B; + reference Instance::@requirements.0::@parts.1; + reference Instance::@requirements.0::@parts.0; + reference Instance::@relationships.0; + } + } + class MyException; + enum BookCategory + { + literal Mystery = 0; + literal ScienceFiction = 1; + literal Biography = 2; + } + package sub : s = 'subsubsub' + { + public class Hey; + package subsub : s2 = 'wow such sub'{ + class CantTouchThis; + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Java.g4 b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Java.g4 new file mode 100644 index 00000000..2d804a4a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Java.g4 @@ -0,0 +1,1016 @@ +/* + [The "BSD licence"] + Copyright (c) 2013 Terence Parr, Sam Harwell + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** A Java 1.7 grammar for ANTLR v4 derived from ANTLR v3 Java grammar. + * Uses ANTLR v4's left-recursive expression notation. + * It parses ECJ, Netbeans, JDK etc... + * + * Sam Harwell cleaned this up significantly and updated to 1.7! + * + * You can test with + * + * $ antlr4 Java.g4 + * $ javac *.java + * $ grun Java compilationUnit *.java + */ +grammar Java; + +// starting point for parsing a java file +compilationUnit + : packageDeclaration? importDeclaration* typeDeclaration* EOF + ; + +packageDeclaration + : annotation* 'package' qualifiedName ';' + ; + +importDeclaration + : 'import' 'static'? qualifiedName ('.' '*')? ';' + ; + +typeDeclaration + : classOrInterfaceModifier* classDeclaration + | classOrInterfaceModifier* enumDeclaration + | classOrInterfaceModifier* interfaceDeclaration + | classOrInterfaceModifier* annotationTypeDeclaration + | ';' + ; + +modifier + : classOrInterfaceModifier + | ( 'native' + | 'synchronized' + | 'transient' + | 'volatile' + ) + ; + +classOrInterfaceModifier + : annotation // class or interface + | ( 'public' // class or interface + | 'protected' // class or interface + | 'private' // class or interface + | 'static' // class or interface + | 'abstract' // class or interface + | 'final' // class only -- does not apply to interfaces + | 'strictfp' // class or interface + ) + ; + +variableModifier + : 'final' + | annotation + ; + +classDeclaration + : 'class' Identifier typeParameters? + ('extends' typeType)? + ('implements' typeList)? + classBody + ; + +typeParameters + : '<' typeParameter (',' typeParameter)* '>' + ; + +typeParameter + : Identifier ('extends' typeBound)? + ; + +typeBound + : typeType ('&' typeType)* + ; + +enumDeclaration + : ENUM Identifier ('implements' typeList)? + '{' enumConstants? ','? enumBodyDeclarations? '}' + ; + +enumConstants + : enumConstant (',' enumConstant)* + ; + +enumConstant + : annotation* Identifier arguments? classBody? + ; + +enumBodyDeclarations + : ';' classBodyDeclaration* + ; + +interfaceDeclaration + : 'interface' Identifier typeParameters? ('extends' typeList)? interfaceBody + ; + +typeList + : typeType (',' typeType)* + ; + +classBody + : '{' classBodyDeclaration* '}' + ; + +interfaceBody + : '{' interfaceBodyDeclaration* '}' + ; + +classBodyDeclaration + : ';' + | 'static'? block + | modifier* memberDeclaration + ; + +memberDeclaration + : methodDeclaration + | genericMethodDeclaration + | fieldDeclaration + | constructorDeclaration + | genericConstructorDeclaration + | interfaceDeclaration + | annotationTypeDeclaration + | classDeclaration + | enumDeclaration + ; + +/* We use rule this even for void methods which cannot have [] after parameters. + This simplifies grammar and we can consider void to be a type, which + renders the [] matching as a context-sensitive issue or a semantic check + for invalid return type after parsing. + */ +methodDeclaration + : (typeType|'void') Identifier formalParameters ('[' ']')* + ('throws' qualifiedNameList)? + ( methodBody + | ';' + ) + ; + +genericMethodDeclaration + : typeParameters methodDeclaration + ; + +constructorDeclaration + : Identifier formalParameters ('throws' qualifiedNameList)? + constructorBody + ; + +genericConstructorDeclaration + : typeParameters constructorDeclaration + ; + +fieldDeclaration + : typeType variableDeclarators ';' + ; + +interfaceBodyDeclaration + : modifier* interfaceMemberDeclaration + | ';' + ; + +interfaceMemberDeclaration + : constDeclaration + | interfaceMethodDeclaration + | genericInterfaceMethodDeclaration + | interfaceDeclaration + | annotationTypeDeclaration + | classDeclaration + | enumDeclaration + ; + +constDeclaration + : typeType constantDeclarator (',' constantDeclarator)* ';' + ; + +constantDeclarator + : Identifier ('[' ']')* '=' variableInitializer + ; + +// see matching of [] comment in methodDeclaratorRest +interfaceMethodDeclaration + : (typeType|'void') Identifier formalParameters ('[' ']')* + ('throws' qualifiedNameList)? + ';' + ; + +genericInterfaceMethodDeclaration + : typeParameters interfaceMethodDeclaration + ; + +variableDeclarators + : variableDeclarator (',' variableDeclarator)* + ; + +variableDeclarator + : variableDeclaratorId ('=' variableInitializer)? + ; + +variableDeclaratorId + : Identifier ('[' ']')* + ; + +variableInitializer + : arrayInitializer + | expression + ; + +arrayInitializer + : '{' (variableInitializer (',' variableInitializer)* (',')? )? '}' + ; + +enumConstantName + : Identifier + ; + +typeType + : classOrInterfaceType ('[' ']')* + | primitiveType ('[' ']')* + ; + +classOrInterfaceType + : Identifier typeArguments? ('.' Identifier typeArguments? )* + ; + +primitiveType + : 'boolean' + | 'char' + | 'byte' + | 'short' + | 'int' + | 'long' + | 'float' + | 'double' + ; + +typeArguments + : '<' typeArgument (',' typeArgument)* '>' + ; + +typeArgument + : typeType + | '?' (('extends' | 'super') typeType)? + ; + +qualifiedNameList + : qualifiedName (',' qualifiedName)* + ; + +formalParameters + : '(' formalParameterList? ')' + ; + +formalParameterList + : formalParameter (',' formalParameter)* (',' lastFormalParameter)? + | lastFormalParameter + ; + +formalParameter + : variableModifier* typeType variableDeclaratorId + ; + +lastFormalParameter + : variableModifier* typeType '...' variableDeclaratorId + ; + +methodBody + : block + ; + +constructorBody + : block + ; + +qualifiedName + : Identifier ('.' Identifier)* + ; + +literal + : IntegerLiteral + | FloatingPointLiteral + | CharacterLiteral + | StringLiteral + | BooleanLiteral + | 'null' + ; + +// ANNOTATIONS + +annotation + : '@' annotationName ( '(' ( elementValuePairs | elementValue )? ')' )? + ; + +annotationName : qualifiedName ; + +elementValuePairs + : elementValuePair (',' elementValuePair)* + ; + +elementValuePair + : Identifier '=' elementValue + ; + +elementValue + : expression + | annotation + | elementValueArrayInitializer + ; + +elementValueArrayInitializer + : '{' (elementValue (',' elementValue)*)? (',')? '}' + ; + +annotationTypeDeclaration + : '@' 'interface' Identifier annotationTypeBody + ; + +annotationTypeBody + : '{' (annotationTypeElementDeclaration)* '}' + ; + +annotationTypeElementDeclaration + : modifier* annotationTypeElementRest + | ';' // this is not allowed by the grammar, but apparently allowed by the actual compiler + ; + +annotationTypeElementRest + : typeType annotationMethodOrConstantRest ';' + | classDeclaration ';'? + | interfaceDeclaration ';'? + | enumDeclaration ';'? + | annotationTypeDeclaration ';'? + ; + +annotationMethodOrConstantRest + : annotationMethodRest + | annotationConstantRest + ; + +annotationMethodRest + : Identifier '(' ')' defaultValue? + ; + +annotationConstantRest + : variableDeclarators + ; + +defaultValue + : 'default' elementValue + ; + +// STATEMENTS / BLOCKS + +block + : '{' blockStatement* '}' + ; + +blockStatement + : localVariableDeclarationStatement + | statement + | typeDeclaration + ; + +localVariableDeclarationStatement + : localVariableDeclaration ';' + ; + +localVariableDeclaration + : variableModifier* typeType variableDeclarators + ; + +statement + : block + | ASSERT expression (':' expression)? ';' + | 'if' parExpression statement ('else' statement)? + | 'for' '(' forControl ')' statement + | 'while' parExpression statement + | 'do' statement 'while' parExpression ';' + | 'try' block (catchClause+ finallyBlock? | finallyBlock) + | 'try' resourceSpecification block catchClause* finallyBlock? + | 'switch' parExpression '{' switchBlockStatementGroup* switchLabel* '}' + | 'synchronized' parExpression block + | 'return' expression? ';' + | 'throw' expression ';' + | 'break' Identifier? ';' + | 'continue' Identifier? ';' + | ';' + | statementExpression ';' + | Identifier ':' statement + ; + +catchClause + : 'catch' '(' variableModifier* catchType Identifier ')' block + ; + +catchType + : qualifiedName ('|' qualifiedName)* + ; + +finallyBlock + : 'finally' block + ; + +resourceSpecification + : '(' resources ';'? ')' + ; + +resources + : resource (';' resource)* + ; + +resource + : variableModifier* classOrInterfaceType variableDeclaratorId '=' expression + ; + +/** Matches cases then statements, both of which are mandatory. + * To handle empty cases at the end, we add switchLabel* to statement. + */ +switchBlockStatementGroup + : switchLabel+ blockStatement+ + ; + +switchLabel + : 'case' constantExpression ':' + | 'case' enumConstantName ':' + | 'default' ':' + ; + +forControl + : enhancedForControl + | forInit? ';' expression? ';' forUpdate? + ; + +forInit + : localVariableDeclaration + | expressionList + ; + +enhancedForControl + : variableModifier* typeType variableDeclaratorId ':' expression + ; + +forUpdate + : expressionList + ; + +// EXPRESSIONS + +parExpression + : '(' expression ')' + ; + +expressionList + : expression (',' expression)* + ; + +statementExpression + : expression + ; + +constantExpression + : expression + ; + +expression + : primary + | expression '.' Identifier + | expression '.' 'this' + | expression '.' 'new' nonWildcardTypeArguments? innerCreator + | expression '.' 'super' superSuffix + | expression '.' explicitGenericInvocation + | expression '[' expression ']' + | expression '(' expressionList? ')' + | 'new' creator + | '(' typeType ')' expression + | expression ('++' | '--') + | ('+'|'-'|'++'|'--') expression + | ('~'|'!') expression + | expression ('*'|'/'|'%') expression + | expression ('+'|'-') expression + | expression ('<' '<' | '>' '>' '>' | '>' '>') expression + | expression ('<=' | '>=' | '>' | '<') expression + | expression 'instanceof' typeType + | expression ('==' | '!=') expression + | expression '&' expression + | expression '^' expression + | expression '|' expression + | expression '&&' expression + | expression '||' expression + | expression '?' expression ':' expression + | expression + ( '=' + | '+=' + | '-=' + | '*=' + | '/=' + | '&=' + | '|=' + | '^=' + | '>>=' + | '>>>=' + | '<<=' + | '%=' + ) + expression + ; + +primary + : '(' expression ')' + | 'this' + | 'super' + | literal + | Identifier + | typeType '.' 'class' + | 'void' '.' 'class' + | nonWildcardTypeArguments (explicitGenericInvocationSuffix | 'this' arguments) + ; + +creator + : nonWildcardTypeArguments createdName classCreatorRest + | createdName (arrayCreatorRest | classCreatorRest) + ; + +createdName + : Identifier typeArgumentsOrDiamond? ('.' Identifier typeArgumentsOrDiamond?)* + | primitiveType + ; + +innerCreator + : Identifier nonWildcardTypeArgumentsOrDiamond? classCreatorRest + ; + +arrayCreatorRest + : '[' + ( ']' ('[' ']')* arrayInitializer + | expression ']' ('[' expression ']')* ('[' ']')* + ) + ; + +classCreatorRest + : arguments classBody? + ; + +explicitGenericInvocation + : nonWildcardTypeArguments explicitGenericInvocationSuffix + ; + +nonWildcardTypeArguments + : '<' typeList '>' + ; + +typeArgumentsOrDiamond + : '<' '>' + | typeArguments + ; + +nonWildcardTypeArgumentsOrDiamond + : '<' '>' + | nonWildcardTypeArguments + ; + +superSuffix + : arguments + | '.' Identifier arguments? + ; + +explicitGenericInvocationSuffix + : 'super' superSuffix + | Identifier arguments + ; + +arguments + : '(' expressionList? ')' + ; + +// LEXER + +// §3.9 Keywords + +ABSTRACT : 'abstract'; +ASSERT : 'assert'; +BOOLEAN : 'boolean'; +BREAK : 'break'; +BYTE : 'byte'; +CASE : 'case'; +CATCH : 'catch'; +CHAR : 'char'; +CLASS : 'class'; +CONST : 'const'; +CONTINUE : 'continue'; +DEFAULT : 'default'; +DO : 'do'; +DOUBLE : 'double'; +ELSE : 'else'; +ENUM : 'enum'; +EXTENDS : 'extends'; +FINAL : 'final'; +FINALLY : 'finally'; +FLOAT : 'float'; +FOR : 'for'; +IF : 'if'; +GOTO : 'goto'; +IMPLEMENTS : 'implements'; +IMPORT : 'import'; +INSTANCEOF : 'instanceof'; +INT : 'int'; +INTERFACE : 'interface'; +LONG : 'long'; +NATIVE : 'native'; +NEW : 'new'; +PACKAGE : 'package'; +PRIVATE : 'private'; +PROTECTED : 'protected'; +PUBLIC : 'public'; +RETURN : 'return'; +SHORT : 'short'; +STATIC : 'static'; +STRICTFP : 'strictfp'; +SUPER : 'super'; +SWITCH : 'switch'; +SYNCHRONIZED : 'synchronized'; +THIS : 'this'; +THROW : 'throw'; +THROWS : 'throws'; +TRANSIENT : 'transient'; +TRY : 'try'; +VOID : 'void'; +VOLATILE : 'volatile'; +WHILE : 'while'; + +// §3.10.1 Integer Literals + +IntegerLiteral + : DecimalIntegerLiteral + | HexIntegerLiteral + | OctalIntegerLiteral + | BinaryIntegerLiteral + ; + +fragment +DecimalIntegerLiteral + : DecimalNumeral IntegerTypeSuffix? + ; + +fragment +HexIntegerLiteral + : HexNumeral IntegerTypeSuffix? + ; + +fragment +OctalIntegerLiteral + : OctalNumeral IntegerTypeSuffix? + ; + +fragment +BinaryIntegerLiteral + : BinaryNumeral IntegerTypeSuffix? + ; + +fragment +IntegerTypeSuffix + : [lL] + ; + +fragment +DecimalNumeral + : '0' + | NonZeroDigit (Digits? | Underscores Digits) + ; + +fragment +Digits + : Digit (DigitOrUnderscore* Digit)? + ; + +fragment +Digit + : '0' + | NonZeroDigit + ; + +fragment +NonZeroDigit + : [1-9] + ; + +fragment +DigitOrUnderscore + : Digit + | '_' + ; + +fragment +Underscores + : '_'+ + ; + +fragment +HexNumeral + : '0' [xX] HexDigits + ; + +fragment +HexDigits + : HexDigit (HexDigitOrUnderscore* HexDigit)? + ; + +fragment +HexDigit + : [0-9a-fA-F] + ; + +fragment +HexDigitOrUnderscore + : HexDigit + | '_' + ; + +fragment +OctalNumeral + : '0' Underscores? OctalDigits + ; + +fragment +OctalDigits + : OctalDigit (OctalDigitOrUnderscore* OctalDigit)? + ; + +fragment +OctalDigit + : [0-7] + ; + +fragment +OctalDigitOrUnderscore + : OctalDigit + | '_' + ; + +fragment +BinaryNumeral + : '0' [bB] BinaryDigits + ; + +fragment +BinaryDigits + : BinaryDigit (BinaryDigitOrUnderscore* BinaryDigit)? + ; + +fragment +BinaryDigit + : [01] + ; + +fragment +BinaryDigitOrUnderscore + : BinaryDigit + | '_' + ; + +// §3.10.2 Floating-Point Literals + +FloatingPointLiteral + : DecimalFloatingPointLiteral + | HexadecimalFloatingPointLiteral + ; + +fragment +DecimalFloatingPointLiteral + : Digits '.' Digits? ExponentPart? FloatTypeSuffix? + | '.' Digits ExponentPart? FloatTypeSuffix? + | Digits ExponentPart FloatTypeSuffix? + | Digits FloatTypeSuffix + ; + +fragment +ExponentPart + : ExponentIndicator SignedInteger + ; + +fragment +ExponentIndicator + : [eE] + ; + +fragment +SignedInteger + : Sign? Digits + ; + +fragment +Sign + : [+-] + ; + +fragment +FloatTypeSuffix + : [fFdD] + ; + +fragment +HexadecimalFloatingPointLiteral + : HexSignificand BinaryExponent FloatTypeSuffix? + ; + +fragment +HexSignificand + : HexNumeral '.'? + | '0' [xX] HexDigits? '.' HexDigits + ; + +fragment +BinaryExponent + : BinaryExponentIndicator SignedInteger + ; + +fragment +BinaryExponentIndicator + : [pP] + ; + +// §3.10.3 Boolean Literals + +BooleanLiteral + : 'true' + | 'false' + ; + +// §3.10.4 Character Literals + +CharacterLiteral + : '\'' SingleCharacter '\'' + | '\'' EscapeSequence '\'' + ; + +fragment +SingleCharacter + : ~['\\] + ; + +// §3.10.5 String Literals + +StringLiteral + : '"' StringCharacters? '"' + ; + +fragment +StringCharacters + : StringCharacter+ + ; + +fragment +StringCharacter + : ~["\\] + | EscapeSequence + ; + +// §3.10.6 Escape Sequences for Character and String Literals + +fragment +EscapeSequence + : '\\' [btnfr"'\\] + | OctalEscape + | UnicodeEscape + ; + +fragment +OctalEscape + : '\\' OctalDigit + | '\\' OctalDigit OctalDigit + | '\\' ZeroToThree OctalDigit OctalDigit + ; + +fragment +UnicodeEscape + : '\\' 'u' HexDigit HexDigit HexDigit HexDigit + ; + +fragment +ZeroToThree + : [0-3] + ; + +// §3.10.7 The Null Literal + +NullLiteral + : 'null' + ; + +// §3.11 Separators + +LPAREN : '('; +RPAREN : ')'; +LBRACE : '{'; +RBRACE : '}'; +LBRACK : '['; +RBRACK : ']'; +SEMI : ';'; +COMMA : ','; +DOT : '.'; + +// §3.12 Operators + +ASSIGN : '='; +GT : '>'; +LT : '<'; +BANG : '!'; +TILDE : '~'; +QUESTION : '?'; +COLON : ':'; +EQUAL : '=='; +LE : '<='; +GE : '>='; +NOTEQUAL : '!='; +AND : '&&'; +OR : '||'; +INC : '++'; +DEC : '--'; +ADD : '+'; +SUB : '-'; +MUL : '*'; +DIV : '/'; +BITAND : '&'; +BITOR : '|'; +CARET : '^'; +MOD : '%'; + +ADD_ASSIGN : '+='; +SUB_ASSIGN : '-='; +MUL_ASSIGN : '*='; +DIV_ASSIGN : '/='; +AND_ASSIGN : '&='; +OR_ASSIGN : '|='; +XOR_ASSIGN : '^='; +MOD_ASSIGN : '%='; +LSHIFT_ASSIGN : '<<='; +RSHIFT_ASSIGN : '>>='; +URSHIFT_ASSIGN : '>>>='; + +// §3.8 Identifiers (must appear after all keywords in the grammar) + +Identifier + : JavaLetter JavaLetterOrDigit* + ; + +fragment +JavaLetter + : [a-zA-Z$_] // these are the "java letters" below 0x7F + | // covers all characters above 0x7F which are not a surrogate + ~[\u0000-\u007F\uD800-\uDBFF] + | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF + [\uD800-\uDBFF] [\uDC00-\uDFFF] + ; + +fragment +JavaLetterOrDigit + : [a-zA-Z0-9$_] // these are the "java letters or digits" below 0x7F + | // covers all characters above 0x7F which are not a surrogate + ~[\u0000-\u007F\uD800-\uDBFF] + | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF + [\uD800-\uDBFF] [\uDC00-\uDFFF] + ; + +// +// Additional symbols not defined in the lexical specification +// + +AT : '@'; +ELLIPSIS : '...'; + +// +// Whitespace and comments +// + +WS : [ \t\r\n\u000C]+ -> skip + ; + +COMMENT + : '/*' .*? '*/' -> channel(HIDDEN) + ; + +LINE_COMMENT + : '//' ~[\r\n]* -> channel(HIDDEN) + ; diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/JavaParser2.g4 b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/JavaParser2.g4 new file mode 100644 index 00000000..85de3603 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/JavaParser2.g4 @@ -0,0 +1,1063 @@ +parser grammar JavaParser2; + +options { + tokenVocab = JavaLexer; +} + +packageName + : Identifier (DOT Identifier)* + ; + +typeName + : Identifier + | packageOrTypeName DOT Identifier + ; + +packageOrTypeName + : Identifier (DOT Identifier)* + ; + +expressionName + : Identifier + | ambiguousName DOT Identifier + ; + +methodName + : Identifier + ; + +ambiguousName + : Identifier (DOT Identifier)* + ; + +simpleTypeName + : Identifier + ; + +typeParameterModifier + : annotation + ; + +literal + : IntegerLiteral + | FloatingPointLiteral + | BooleanLiteral + | CharacterLiteral + | StringLiteral + | NullLiteral + ; + +type + : primitiveType + | referenceType + ; + +primitiveType + : (annotation)* numericType + | (annotation)* BOOLEAN + ; + +numericType + : integralType + | floatingPointType + ; + +integralType + : BYTE + | SHORT + | INT + | LONG + | CHAR + ; + +floatingPointType + : FLOAT + | DOUBLE + ; + +referenceType + : classOrInterfaceType + | typeVariable + | arrayType + ; + +classOrInterfaceType + : classType + | interfaceType + ; + +classType + : (annotation)* Identifier (typeArguments)? + | classType DOT (annotation)* Identifier (typeArguments)? + ; + +interfaceType + : classType + ; + +typeVariable + : (annotation)* Identifier + ; + +arrayType + : primitiveType dims + | classOrInterfaceType dims + | typeVariable dims + ; + +dims + : (annotation)* L_BRACKET R_BRACKET ((annotation)* L_BRACKET R_BRACKET)* + ; + +typeParameter + : (typeParameterModifier)* Identifier (typeBound)? + ; + +typeBound + : EXTENDS typeVariable + | EXTENDS classOrInterfaceType (additionalBound)* + ; + +additionalBound + : B_AND interfaceType + ; + +typeArguments + : LT typeArgumentList GT + ; + +typeArgumentList + : typeArgument (COMMA typeArgument)* + ; + +typeArgument + : referenceType + | wildcard + ; + +wildcard + : (annotation)* QUES (wildcardBounds)? + ; + +wildcardBounds + : EXTENDS referenceType + | SUPER referenceType + ; + +compilationUnit + : (packageDeclaration)? (importDeclaration)* (typeDeclaration)* + ; + +packageDeclaration + : (packageModifier)* PACKAGE Identifier (DOT Identifier)* SEMI + ; + +packageModifier + : annotation + ; + +importDeclaration + : singleTypeImportDeclaration + | typeImportOnDemandDeclaration + | singleStaticImportDeclaration + | staticImportOnDemandDeclaration + ; + +singleTypeImportDeclaration + : IMPORT typeName SEMI + ; + +typeImportOnDemandDeclaration + : IMPORT packageOrTypeName DOT MULT SEMI + ; + +singleStaticImportDeclaration + : IMPORT STATIC typeName DOT Identifier SEMI + ; + +staticImportOnDemandDeclaration + : IMPORT STATIC typeName DOT MULT SEMI + ; + +typeDeclaration + : classDeclaration + | interfaceDeclaration + | SEMI + ; + +classDeclaration + : normalClassDeclaration + | enumDeclaration + ; + +normalClassDeclaration + : (classModifier)* CLASS Identifier (typeParameters)? (superclass)? (superinterfaces)? classBody + ; + +classModifier + : annotation + | PUBLIC + | PROTECTED + | PRIVATE + | ABSTRACT + | STATIC + | FINAL + | STRICTFP + ; + +typeParameters + : LT typeParameterList GT + ; + +typeParameterList + : typeParameter (COMMA typeParameter)* + ; + +superclass + : EXTENDS classType + ; + +superinterfaces + : IMPLEMENTS interfaceTypeList + ; + +interfaceTypeList + : interfaceType (COMMA interfaceType)* + ; + +classBody + : L_CURLY (classBodyDeclaration)* R_CURLY + ; + +classBodyDeclaration + : classMemberDeclaration + | instanceInitializer + | staticInitializer + | constructorDeclaration + ; + +classMemberDeclaration + : fieldDeclaration + | methodDeclaration + | classDeclaration + | interfaceDeclaration + | SEMI + ; + +fieldDeclaration + : (fieldModifier)* unannType variableDeclaratorList SEMI + ; + +fieldModifier + : annotation + | PUBLIC + | PROTECTED + | PRIVATE + | STATIC + | FINAL + | TRANSIENT + | VOLATILE + ; + +variableDeclaratorList + : variableDeclarator (COMMA variableDeclarator)* + ; + +variableDeclarator + : variableDeclaratorId (ASSIGN variableInitializer)? + ; + +variableDeclaratorId + : Identifier (dims)? + ; + +variableInitializer + : expression + | arrayInitializer + ; + +unannType + : unannPrimitiveType + | unannReferenceType + ; + +unannPrimitiveType + : numericType + | BOOLEAN + ; + +unannReferenceType + : unannClassOrInterfaceType + | unannTypeVariable + | unannArrayType + ; + +unannClassOrInterfaceType + : unannClassType + | unannInterfaceType + ; + +unannClassType + : Identifier (typeArguments)? + | unannClassType DOT (annotation)* Identifier (typeArguments)? + ; + +unannInterfaceType + : unannClassType + ; + +unannTypeVariable + : Identifier + ; + +unannArrayType + : unannPrimitiveType dims + | unannClassOrInterfaceType dims + | unannTypeVariable dims + ; + +methodDeclaration + : (methodModifier)* methodHeader methodBody + ; + +methodModifier + : annotation + | PUBLIC + | PROTECTED + | PRIVATE + | ABSTRACT + | STATIC + | FINAL + | SYNCHRONIZED + | NATIVE + | STRICTFP + ; + +methodHeader + : result methodDeclarator (thro)? + | typeParameters (annotation)* result methodDeclarator (thro)? + ; + +result + : unannType + | VOID + ; + +methodDeclarator + : Identifier L_PARENS (formalParameterList)? R_PARENS (dims)? + ; + +formalParameterList + : formalParameters COMMA lastFormalParameter + | lastFormalParameter + ; + +formalParameters + : formalParameter (COMMA formalParameter)* + | receiverParameter (COMMA formalParameter)* + ; + +formalParameter + : (variableModifier)* unannType variableDeclaratorId + ; + +variableModifier + : annotation + | FINAL + ; + +lastFormalParameter + : (variableModifier)* unannType (annotation)* ELLIPSES variableDeclaratorId + | formalParameter + ; + +receiverParameter + : (annotation)* unannType (Identifier DOT)? THIS + ; + +thro + : THROWS exceptionTypeList + ; + +exceptionTypeList + : exceptionType (COMMA exceptionType)* + ; + +exceptionType + : classType + | typeVariable + ; + +methodBody + : block + | SEMI + ; + +instanceInitializer + : block + ; + +staticInitializer + : STATIC block + ; + +constructorDeclaration + : (constructorModifier)* constructorDeclarator (thro)? constructorBody + ; + +constructorModifier + : annotation + | PUBLIC + | PROTECTED + | PRIVATE + ; + +constructorDeclarator + : (typeParameters)? simpleTypeName L_PARENS (formalParameterList)? R_PARENS + ; + +constructorBody + : L_CURLY (explicitConstructorInvocation)? (blockStatements)? R_CURLY + ; + +explicitConstructorInvocation + : (typeArguments)? THIS L_PARENS (argumentList)? R_PARENS SEMI + | (typeArguments)? SUPER L_PARENS (argumentList)? R_PARENS SEMI + | expressionName DOT (typeArguments)? SUPER L_PARENS (argumentList)? R_PARENS SEMI + | primary DOT (typeArguments)? SUPER L_PARENS (argumentList)? R_PARENS SEMI + ; + +enumDeclaration + : (classModifier)* ENUM Identifier (superinterfaces)? enumBody + ; + +enumBody + : L_CURLY (enumConstantList)? (COMMA)? (enumBodyDeclarations)? R_CURLY + ; + +enumConstantList + : enumConstant (COMMA enumConstant)* + ; + +enumConstant + : (enumConstantModifier)* Identifier (L_PARENS (argumentList)? R_PARENS)? (classBody)? + ; + +enumConstantModifier + : annotation + ; + +enumBodyDeclarations + : SEMI (classBodyDeclaration)* + ; + +interfaceDeclaration + : normalInterfaceDeclaration + | annotationTypeDeclaration + ; + +normalInterfaceDeclaration + : (interfaceModifier)* INTERFACE Identifier (typeParameters)? (extendsInterfaces)? interfaceBody + ; + +interfaceModifier + : annotation + | PUBLIC + | PROTECTED + | PRIVATE + | ABSTRACT + | STATIC + | STRICTFP + ; + +extendsInterfaces + : EXTENDS interfaceTypeList + ; + +interfaceBody + : L_CURLY (interfaceMemberDeclaration)* R_CURLY + ; + +interfaceMemberDeclaration + : constantDeclaration + | interfaceMethodDeclaration + | classDeclaration + | interfaceDeclaration + | SEMI + ; + +constantDeclaration + : (constantModifier)* unannType variableDeclaratorList SEMI + ; + +constantModifier + : annotation + | PUBLIC + | STATIC + | FINAL + ; + +interfaceMethodDeclaration + : (interfaceMethodModifier)* methodHeader methodBody + ; + +interfaceMethodModifier + : annotation + | PUBLIC + | ABSTRACT + | DEFAULT + | STATIC + | STRICTFP + ; + +annotationTypeDeclaration + : (interfaceModifier)* AT INTERFACE Identifier annotationTypeBody + ; + +annotationTypeBody + : L_CURLY (annotationTypeMemberDeclaration)* R_CURLY + ; + +annotationTypeMemberDeclaration + : annotationTypeElementDeclaration + | constantDeclaration + | classDeclaration + | interfaceDeclaration + | SEMI + ; + +annotationTypeElementDeclaration + : (annotationTypeElementModifier)* unannType Identifier L_PARENS R_PARENS (dims)? (defaultValue)? SEMI + ; + +annotationTypeElementModifier + : annotation + | PUBLIC + | ABSTRACT + ; + +defaultValue + : DEFAULT elementValue + ; + +annotation + : normalAnnotation + | markerAnnotation + | singleElementAnnotation + ; + +normalAnnotation + : AT typeName L_PARENS (elementValuePairList)? R_PARENS + ; + +elementValuePairList + : elementValuePair (COMMA elementValuePair)* + ; + +elementValuePair + : Identifier ASSIGN elementValue + ; + +elementValue + : conditionalExpression + | elementValueArrayInitializer + | annotation + ; + +elementValueArrayInitializer + : L_CURLY (elementValueList)? (COMMA)? R_CURLY + ; + +elementValueList + : elementValue (COMMA elementValue)* + ; + +markerAnnotation + : AT typeName + ; + +singleElementAnnotation + : AT typeName L_PARENS elementValue R_PARENS + ; + +arrayInitializer + : L_CURLY (variableInitializerList)? (COMMA)? R_CURLY + ; + +variableInitializerList + : variableInitializer (COMMA variableInitializer)* + ; + +block + : L_CURLY (blockStatements)? R_CURLY + ; + +blockStatements + : blockStatement (blockStatement)* + ; + +blockStatement + : localVariableDeclarationStatement + | classDeclaration + | statement + ; + +localVariableDeclarationStatement + : localVariableDeclaration SEMI + ; + +localVariableDeclaration + : (variableModifier)* unannType variableDeclaratorList + ; + +statement + : statementWithoutTrailingSubstatement + | labeledStatement + | ifThenStatement + | ifThenElseStatement + | whileStatement + | forStatement + ; + +statementNoShortIf + : statementWithoutTrailingSubstatement + | labeledStatementNoShortIf + | ifThenElseStatementNoShortIf + | whileStatementNoShortIf + | forStatementNoShortIf + ; + +statementWithoutTrailingSubstatement + : block + | emptyStatement + | expressionStatement + | assertStatement + | switchStatement + | doStatement + | breakStatement + | continueStatement + | returnStatement + | synchronizedStatement + | throwStatement + | tryStatement + ; + +emptyStatement + : SEMI + ; + +labeledStatement + : Identifier COLON statement + ; + +labeledStatementNoShortIf + : Identifier COLON statementNoShortIf + ; + +expressionStatement + : statementExpression SEMI + ; + +statementExpression + : assignment + | preIncrementExpression + | preDecrementExpression + | postfixExpression INCREMENT + | postfixExpression DECREMENT + | methodInvocation + | classInstanceCreationExpression + ; + +ifThenStatement + : IF L_PARENS expression R_PARENS statement + ; + +ifThenElseStatement + : IF L_PARENS expression R_PARENS statementNoShortIf ELSE statement + ; + +ifThenElseStatementNoShortIf + : IF L_PARENS expression R_PARENS statementNoShortIf ELSE statementNoShortIf + ; + +assertStatement + : ASSERT expression SEMI + | ASSERT expression COLON expression SEMI + ; + +switchStatement + : SWITCH L_PARENS expression R_PARENS switchBlock + ; + +switchBlock + : L_CURLY (switchBlockStatementGroup)* (switchLabel)* R_CURLY + ; + +switchBlockStatementGroup + : switchLabels blockStatements + ; + +switchLabels + : switchLabel (switchLabel)* + ; + +switchLabel + : CASE constantExpression COLON + | CASE enumConstantName COLON + | DEFAULT COLON + ; + +enumConstantName + : Identifier + ; + +whileStatement + : WHILE L_PARENS expression R_PARENS statement + ; + +whileStatementNoShortIf + : WHILE L_PARENS expression R_PARENS statementNoShortIf + ; + +doStatement + : DO statement WHILE L_PARENS expression R_PARENS SEMI + ; + +forStatement + : basicForStatement + | enhancedForStatement + ; + +forStatementNoShortIf + : basicForStatementNoShortIf + | enhancedForStatementNoShortIf + ; + +basicForStatement + : FOR L_PARENS (forInit)? SEMI (expression)? SEMI (forUpdate)? R_PARENS statement + ; + +basicForStatementNoShortIf + : FOR L_PARENS (forInit)? SEMI (expression)? SEMI (forUpdate)? R_PARENS statementNoShortIf + ; + +forInit + : statementExpressionList + | localVariableDeclaration + ; + +forUpdate + : statementExpressionList + ; + +statementExpressionList + : statementExpression (COMMA statementExpression)* + ; + +enhancedForStatement + : FOR L_PARENS (variableModifier)* unannType variableDeclaratorId COLON expression R_PARENS statement + ; + +enhancedForStatementNoShortIf + : FOR L_PARENS (variableModifier)* unannType variableDeclaratorId COLON expression R_PARENS statementNoShortIf + ; + +breakStatement + : BREAK (Identifier)? SEMI + ; + +continueStatement + : CONTINUE (Identifier)? SEMI + ; + +returnStatement + : RETURN (expression)? SEMI + ; + +throwStatement + : THROW expression SEMI + ; + +synchronizedStatement + : SYNCHRONIZED L_PARENS expression R_PARENS block + ; + +tryStatement + : TRY block catches + | TRY block (catches)? finall + | tryWithResourcesStatement + ; + +catches + : catchClause (catchClause)* + ; + +catchClause + : CATCH L_PARENS catchFormalParameter R_PARENS block + ; + +catchFormalParameter + : (variableModifier)* catchType variableDeclaratorId + ; + +catchType + : unannClassType (B_OR classType)* + ; + +finall + : FINALLY block + ; + +tryWithResourcesStatement + : TRY resourceSpecification block (catches)? (finall)? + ; + +resourceSpecification + : L_PARENS resourceList (SEMI)? R_PARENS + ; + +resourceList + : resource (SEMI resource)* + ; + +resource + : (variableModifier)* unannType variableDeclaratorId ASSIGN expression + ; + +primary + : primaryNoNewArray + | arrayCreationExpression + ; + +primaryNoNewArray + : literal + | typeName (L_BRACKET R_BRACKET)* DOT CLASS + | VOID DOT CLASS + | THIS + | typeName DOT THIS + | L_PARENS expression R_PARENS + | classInstanceCreationExpression + | fieldAccess + | arrayAccess + | methodInvocation + | methodReference + ; + +classInstanceCreationExpression + : NEW (typeArguments)? (annotation)* Identifier (typeArgumentsOrDiamond)? L_PARENS (argumentList)? R_PARENS (classBody)? + | expressionName DOT NEW (typeArguments)? (annotation)* Identifier (typeArgumentsOrDiamond)? L_PARENS (argumentList)? R_PARENS (classBody)? + | primary DOT NEW (typeArguments)? (annotation)* Identifier (typeArgumentsOrDiamond)? L_PARENS (argumentList)? R_PARENS (classBody)? + ; + +typeArgumentsOrDiamond + : typeArguments + | DIAMOND + ; + +fieldAccess + : primary DOT Identifier + | SUPER DOT Identifier + | typeName DOT SUPER DOT Identifier + ; + +arrayAccess + : expressionName L_BRACKET expression R_BRACKET + | primaryNoNewArray L_BRACKET expression R_BRACKET + ; + +methodInvocation + : methodName L_PARENS (argumentList)? R_PARENS + | typeName DOT (typeArguments)? Identifier L_PARENS (argumentList)? R_PARENS + | expressionName DOT (typeArguments)? Identifier L_PARENS (argumentList)? R_PARENS + | primary DOT (typeArguments)? Identifier L_PARENS (argumentList)? R_PARENS + | SUPER DOT (typeArguments)? Identifier L_PARENS (argumentList)? R_PARENS + | typeName DOT SUPER DOT (typeArguments)? Identifier L_PARENS (argumentList)? R_PARENS + ; + +argumentList + : expression (COMMA expression)* + ; + +methodReference + : expressionName METHOD_REF (typeArguments)? Identifier + | referenceType METHOD_REF (typeArguments)? Identifier + | primary METHOD_REF (typeArguments)? Identifier + | SUPER METHOD_REF (typeArguments)? Identifier + | typeName DOT SUPER METHOD_REF (typeArguments)? Identifier + | classType METHOD_REF (typeArguments)? NEW + | arrayType METHOD_REF NEW + ; + +arrayCreationExpression + : NEW primitiveType dimExprs (dims)? + | NEW classOrInterfaceType dimExprs (dims)? + | NEW primitiveType dims arrayInitializer + | NEW classOrInterfaceType dims arrayInitializer + ; + +dimExprs + : dimExpr (dimExpr)* + ; + +dimExpr + : (annotation)* L_BRACKET expression R_BRACKET + ; + +constantExpression + : expression + ; + +expression + : lambdaExpression + | assignmentExpression + ; + +lambdaExpression + : lambdaParameters ARROW lambdaBody + ; + +lambdaParameters + : Identifier + | L_PARENS (formalParameterList)? R_PARENS + | L_PARENS inferredFormalParameterList R_PARENS + ; + +inferredFormalParameterList + : Identifier (COMMA Identifier)* + ; + +lambdaBody + : expression + | block + ; + +assignmentExpression + : conditionalExpression + | assignment + ; + +assignment + : leftHandSide assignmentOperator expression + ; + +leftHandSide + : expressionName + | fieldAccess + | arrayAccess + ; + +assignmentOperator + : ASSIGN + | MULT_ASSIGN + | DIV_ASSIGN + | MOD_ASSIGN + | PLUS_ASSIGN + | MINUS_ASSIGN + | L_SHIFT_ASSIGN + | R_SHIFT_ASSIGN + | UR_SHIFT_ASSIGN + | AND_ASSIGN + | XOR_ASSIGN + | OR_ASSIGN + ; + +conditionalExpression + : conditionalOrExpression + | conditionalOrExpression QUES expression COLON conditionalExpression + ; + +conditionalOrExpression + : conditionalAndExpression + | conditionalOrExpression L_OR conditionalAndExpression + ; + +conditionalAndExpression + : inclusiveOrExpression + | conditionalAndExpression L_AND inclusiveOrExpression + ; + +inclusiveOrExpression + : exclusiveOrExpression + | inclusiveOrExpression B_OR exclusiveOrExpression + ; + +exclusiveOrExpression + : andExpression + | exclusiveOrExpression XOR andExpression + ; + +andExpression + : equalityExpression + | andExpression B_AND equalityExpression + ; + +equalityExpression + : relationalExpression + | equalityExpression EQ relationalExpression + | equalityExpression NEQ relationalExpression + ; + +relationalExpression + : shiftExpression + | relationalExpression LT shiftExpression + | relationalExpression GT shiftExpression + | relationalExpression LE shiftExpression + | relationalExpression GE shiftExpression + | relationalExpression INSTANCEOF referenceType + ; + +shiftExpression + : additiveExpression + | shiftExpression L_SHIFT additiveExpression + | shiftExpression GT GT additiveExpression + | shiftExpression GT GT GT additiveExpression + ; + +additiveExpression + : multiplicativeExpression + | additiveExpression PLUS multiplicativeExpression + | additiveExpression MINUS multiplicativeExpression + ; + +multiplicativeExpression + : unaryExpression + | multiplicativeExpression MULT unaryExpression + | multiplicativeExpression DIV unaryExpression + | multiplicativeExpression MOD unaryExpression + ; + +unaryExpression + : preIncrementExpression + | preDecrementExpression + | PLUS unaryExpression + | MINUS unaryExpression + | unaryExpressionNotPlusMinus + ; + +preIncrementExpression + : INCREMENT unaryExpression + ; + +preDecrementExpression + : DECREMENT unaryExpression + ; + +unaryExpressionNotPlusMinus + : postfixExpression + | TILD unaryExpression + | BANG unaryExpression + | castExpression + ; + +postfixExpression + : primary + | expressionName + | postfixExpression INCREMENT + | postfixExpression DECREMENT + ; + +castExpression + : L_PARENS primitiveType R_PARENS unaryExpression + | L_PARENS referenceType (additionalBound)* R_PARENS unaryExpressionNotPlusMinus + | L_PARENS referenceType (additionalBound)* R_PARENS lambdaExpression + ; \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/My.recore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/My.recore new file mode 100644 index 00000000..15914ec5 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/My.recore @@ -0,0 +1,28 @@ +import Instance : 'Instance.requirements'; +import Requirements : 'Requirements.ecore'; +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package BookStorePackage : bookStore = 'http:///com.ibm.dynamic.example.bookstore.ecore' +{ + class A + { + attribute owner : String[+] { !unique }; + operation method() : String; + property ref2 : BookStorePackage::pack::B; + } + package pack : p = 'bla bla' + { + class B + { + attribute instance : Requirements::Priority[?]; + annotation 'ferhat' + { + reference BookStorePackage::A::owner; + reference Instance::B; + reference Instance::@requirements.0::@parts.1; + reference Instance::@requirements.0::@parts.0; + reference Instance::@relationships.0; + } + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/OperationTest.recore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/OperationTest.recore new file mode 100644 index 00000000..a769d8fc --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/OperationTest.recore @@ -0,0 +1,39 @@ +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package TestPackage : tp = 'www.testpackage.org' +{ + private class TestClass extends SuperClass, UberClass : 'TCname' + { + private static operation testOp(nullable testParam : Boolean[?] { ordered }, testParam2 : Ecore.EChar[+] { ordered }) : String[?] throws SubTestInterface, SubTestClass { !unique ordered } + { + requires testPre ("Hey!") : lone testOp; + body testPre : testOp; + ensures testPost ("Hey!") : one testOp; + } + operation testOp1() : TestDataType[?] { ordered }; + operation testOp2() : TestDataType[1] { ordered }; + operation testOp3() : TestDataType[*] { ordered }; + operation testOp4() : TestDataType[+] { ordered }; + operation testOp5() : TestDataType[3..6] { ordered }; + operation testVoidOp() { ordered } + { + requires : lone testOp; + body testBody : testOp; + body testBody2 : testOp; + ensures testPost ("Hey!") : one testOp; + ensures testPost2 ("Hey!") : one testOp; + } + } + interface TestInterface extends SuperClass : 'TIname'; + enum TestEnum : 'TEname' { serializable }; + primitive datatype TestDataType : 'TDTname' { serializable }; + abstract class SuperClass; + abstract class UberClass; + package SubPackage : sp = 'www.sub.testpackage.org' + { + class SubTestClass; + interface SubTestInterface; + enum SubTestEnum; + datatype SubTestDataType : 'STDTname'; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Templates.ecore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Templates.ecore new file mode 100644 index 00000000..20cad202 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Templates.ecore @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + +
+
+ + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Templates.recore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Templates.recore new file mode 100644 index 00000000..6641628c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Templates.recore @@ -0,0 +1,98 @@ +model ferhat; + +import ecore : 'http://www.eclipse.org/emf/2002/Ecore'; +import tepe : + 'http://www.eclipse.org/emf/2002/Tepe'; + +package generics : gns = 'eu.modelwriter.generics' +{ + public package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' + { + public class Library + { + nullable attribute name : String; + property books#library : Book[*|1] { composes }; + property loans : Loan[*|?] { composes }; + nullable property members#library : Member[*] { composes }; + annotation 'modelwriter/Ferhat' ('key' = , 'key' = 'value', =) + { + reference Library::books; + class AnnotationClass; + property mehmet: type; + } + annotation ; + annotation ; + } + public class Book + { + operation isAvailable() : Boolean[?]; + attribute name : String[1]; + attribute copies : Integer[1]; + property library#books : Library[?]; + volatile property loans : Loan[*|1] { derived }; + } + public class Member + { + model nullable attribute name : String[1]; + property library#members : Library[?]; + volatile property loans : Loan[*|1] { derived }; /*{derivation : library.loans->select;}*/ + volatile property books : Book[*|1] { !unique derived}; /*{derivation : loans->collect;}*/ + } + class Loan + { + property book : Book[1]; + property member : Member[1] = 'Ferhat Erata'; + annotation + { + reference tutorial::Organization::Librarian::orgOpp; + } + nullable attribute date : ecore::EDate[?]; + } + protected package enterprise : ent = 'http://www.eclipse.org/mdt/ocl/oclinecore/enterprise' + { + public interface Employee { + attribute name : String[1] = 'Ferhat Erata'; + model attribute copies : Integer[1]; + } + datatype JavaPackage : 'java.lang.Package' { !serializable }; + enum Type { serializable } + { + type1 = 2; + literal type2; + } + } + /*invariant inv_name ("this rule is violated.") : all x: Employee | lone x.model ;*/ + annotation 'test'; + annotation ; + } + + package Iterator : itr = 'iterator'; + class Iterator; + abstract class List + { + operation add(); + operation add(element : E[1]); + operation iterator() : Iterator[?]; + } + class Iterator + { + operation next() : E[?] throws MyException ; + operation hasNext() : Boolean[1]; + } + class ArrayList extends List; + class test; + abstract class Person; + class Owner + { + property cars : ArrayList[?]; + property attr1: K; + } + interface Shape; + class Canvas + { + operation draw(shapes : List[1]) : Boolean[?]; + operation create(name : String[1]); + operation create(name: String, arg : ArrayList[?]); + } + class MyException; +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Test.g4 b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Test.g4 new file mode 100644 index 00000000..4b29bcea --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Test.g4 @@ -0,0 +1,17 @@ +grammar Test; + +model: formula* ; + +formula: + left=expression 'in' right=expression #in + | left=formula 'and' right=formula #and + ; + +expression: + left=expression '+' right=expression #union + | variable #var + ; + +variable: IDENTIFIER; + +IDENTIFIER : [a-zA-Z]; diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Test.recore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Test.recore new file mode 100644 index 00000000..92658d61 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Test.recore @@ -0,0 +1,95 @@ +import FordOtosan: 'FordOtosan.ecore'; +import extlibrary: 'extlibrary.ecore'; +import Ecore: 'http://www.eclipse.org/emf/2002/Ecore'; + +package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' +{ + public class Library + { + attribute name : String[1] + { + annotation; + derivation : library.loans->select; + annotation 'sadasdas'; + } + property books#library : Book[*] { resolve composes } + { + annotation; + annotation 'sadasdas'; + derivation : library.loans->select; + } + static property loans : Loan[*] { resolve composes }; + property members#library : Member[*] { resolve composes }; + } + class Book + { + attribute name : String[1]; + attribute copies : UnlimitedNatural[1]; + operation isAvailable(param1 : Boolean[?] { ordered }, param2 : Book[?] { ordered }) : Boolean[?] + { + body; + ensures sup ("this is a precondition") : ; + } + property library#books : Library[?] { resolve }; + volatile property loans : Loan[*] { derived resolve } {derivation : library.loans->select;} + invariant importantConstraint ("multi + lined + message") : ; + } + class Member + { + attribute name : String[1]; + operation tespOP() { ordered }; + property library#members : Library[?] { resolve }; + volatile property loans : Loan[*] { derived resolve } {derivation : library.loans->select;} + volatile property books : Book[*] { !unique derived resolve } {initial : loans->collect;} + } + class Loan + { + attribute date : Ecore::EDate[?]; + property book : tutorial::Organization::SubOrg1::sb1C[1] { resolve }; + property member : Member[1] { resolve }; + annotation + { + reference tutorial::Organization::Librarian::orgOpp; + } + } + package Organization : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization' + { + enum Type { !serializable } + { + literal asd = 0; + } + datatype JavaPackage : 'java.lang.Package' { !serializable }; + class Librarian extends extlibrary::Employee + { + operation orgOpp() : Ecore::ELong[?] { ordered }; + property workOn : tutorial::Organization::SubOrg2::sb2C[?] { ordered resolve }; + } + class Ref extends tutorial::Library + { + property RefOutsideEcore : extlibrary::Item[?] { ordered resolve }; + } + package SubOrg1 : sb = 'suborg1' + { + class sb1C; + } + package SubOrg2 : sb2 = 'SubOrg2' + { + class sb2C; + } + annotation 'extAnno' + { + reference extlibrary::Item; + reference extlibrary::Item::publicationDate; + reference FordOtosan::Container::vehicle; + reference FordOtosan::Vehicle::ElectricalPowerSupplySystem::ElectricalPowerSupplySystem::electricalPowerSupplySystemPart; + } + } + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'invocationDelegates' = 'http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot', + 'settingDelegates' = 'http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot', + 'validationDelegates' = 'http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot' + ); +} diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Tutorial.ecore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Tutorial.ecore new file mode 100644 index 00000000..c9aa0207 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/Tutorial.ecore @@ -0,0 +1,76 @@ + + + +
+ + +
+
+
+ + + + + + + + + +
+ + +
+ + + +
+ + + + + + + +
+ + + + + +
+ + +
+
+ + + + + +
+ + + + +
+ + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/extlibrary.ecore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/extlibrary.ecore new file mode 100644 index 00000000..1a6e74b5 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/extlibrary.ecore @@ -0,0 +1,129 @@ + + + +
+ + +
+ + + +
+ + + +
+ + + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/package.recore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/package.recore new file mode 100644 index 00000000..b95110f5 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/package.recore @@ -0,0 +1,36 @@ +import ecore : 'http://www.eclipse.org/emf/2002/Ecore' ; + +protected package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' +{ + public class Library + { + attribute name : String[1]; + property books#library : Book[*|1] { composes }; + property loans : Loan[*|1] { composes }; + property members#library : Member[*|1] { composes }; + } + public abstract class Employee { + attribute name : String[1]; + model attribute copies : Integer[1]; + } + package Enterprise0 : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/enterprise' + { + private class Car { + nullable readonly attribute name : String[1] {ordered}; + attribute copies : Integer[1]; + } + } + public package Enterprise1 : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/enterprise' + {} + package Organization1 : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization' + { + abstract interface Librarian extends Employee + { + + } + package Level2'' : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization/Level2' {} + package Level2 : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization/Level3' {} + } + package Enterprise2 : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/enterprise' + {} +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/simple.recore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/simple.recore new file mode 100644 index 00000000..7a656224 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/simple.recore @@ -0,0 +1,50 @@ +import ecore : 'http://www.eclipse.org/emf/2002/Ecore' ; + +package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' +{ + public class Library + { + attribute name : String[1]; + property books#library : Book[*|1] { composes }; + property loans : Loan[*|1] { composes }; + property members#library : Member[*|1] { composes }; + } + public class Book + { + operation isAvailable() : Boolean[?]; + attribute name : String[1]; + attribute copies : Integer[1]; + property library#books : Library[?]; + volatile property loans : Loan[*|1] { derived }; + } + public class Member + { + model attribute name : String[1]; + property library#members : Library[?]; + volatile property loans : Loan[*|1] { derived }; + volatile property books : Book[*|1] { !unique derived}; + } + class Loan + { + property book : Book[1]; + property member : Member[1]; + attribute date : ecore::EDate[?]; + } + package Organization : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization' + { + abstract class Librarian extends Employee + { + property workOn : tutorial::Library[1]; + } + abstract class Employee extends tutorial::Library + { + property RefOutsideEcore : extlib::Item[+]; + } + datatype JavaPackage : 'java.lang.Package' { !serializable }; + enum Type { serializable } + { + type1 = 2; + literal type2; + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/test.recore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/test.recore new file mode 100644 index 00000000..c5bfb61e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/test.recore @@ -0,0 +1,85 @@ +import FordOtosan: 'FordOtosan.ecore'; +import extlibrary: 'extlibrary.ecore'; +import Ecore: 'http://www.eclipse.org/emf/2002/Ecore'; + +package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' +{ + public class Library + { + attribute name : String[1] + { + annotation; + } + property books#library : Book[*] { resolve composes } + { + annotation 'sadasdas'; + } + static property loans : Loan[*] { resolve composes }; + property members#library : Member[*] { resolve composes }; + } + class Book + { + attribute name : String[1]; + attribute copies : UnlimitedNatural[1]; + operation isAvailable(param1 : Boolean[?] { ordered }, param2 : Book[?] { ordered }) : Boolean[?] + { + body; + ensures sup ("this is a precondition") : ; + } + property library#books : Library[?] { resolve }; + volatile property loans : Loan[*] { derived resolve } {derivation : library.loans->select;} + invariant importantConstraint ("multi + lined + message") : ; + } + class Member + { + attribute name : String[1]; + operation tespOP() { ordered }; + property library#members : Library[?] { resolve }; + volatile property loans : Loan[*] { derived resolve } {derivation : library.loans->select;} + volatile property books : Book[*] { !unique derived resolve } {derivation : loans->collect;} + } + class Loan + { + attribute date : Ecore.EDate[?]; + property book : tutorial.Organization.SubOrg1.sb1C[1] { resolve }; + property member : Member[1] { resolve }; + annotation + { + reference tutorial.Organization.Librarian->orgOpp; + } + } + package Organization : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization' + { + enum Type { serializable } + { + literal asd = 0; + } + datatype JavaPackage : 'java.lang.Package' { serializable }; + class Librarian extends extlibrary.Employee + { + operation orgOpp() : Ecore.ELong[?] { ordered }; + property workOn : tutorial.Organization.SubOrg2.sb2C[?] { ordered resolve }; + + class Ref extends Library + { + property RefOutsideEcore : extlibrary.Item[?] { ordered resolve }; + } + package SubOrg1 : sb = 'suborg1' + { + class sb1C; + } + package SubOrg2 : sb2 = 'SubOrg2' + { + class sb2C; + } + annotation 'extAnno' + { + reference extlibrary.Item; + reference extlibrary.Item.publicationDate; + reference FordOtosan.Container.vehicle; + reference FordOtosan.Vehicle.ElectricalPowerSupplySystem.ElectricalPowerSupplySystem.electricalPowerSupplySystemPart; + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/test1.g4 b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/test1.g4 new file mode 100644 index 00000000..61e0cc7f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/test1.g4 @@ -0,0 +1,12 @@ +grammar test1; + +example: + left=integer '*' right=integer #integerExample + | left=string '+' right=string #stringExample + ; + +integer: IDENTIFIER; +string: INTEGER; + +STRING: [a-zA-Z]; +INTEGER: [a-zA-Z]; \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/test1.recore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/test1.recore new file mode 100644 index 00000000..159b7fb8 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/test1.recore @@ -0,0 +1,78 @@ +import extlibrary : 'MF4SEA_ML/extlibrary.ecore'; +import extlibrary : 'extlibrary.ecore'; +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' +{ + public abstract class Library + { + attribute name : String; + property books#library : Book[*] { composes } + { + annotation 'sadasdas'; + } + static property loans : Loan[*] { composes }; + property members#library : Member[*] { composes }; + } + class Book + { + attribute name : String; + attribute copies : UnlimitedNatural; + operation isAvailable(param1 : Boolean[?], param2 : Book[?]) : Boolean[?] + { + body; + ensures sup ("this is a precondition"); + } + property library#books : Library[?]; + volatile property loans : Loan[*] { derived }; + invariant importantConstraint ("asdasd"); + } + class Member + { + attribute name : String; + operation tespOP(); + property library#members : Library[?]; + volatile property loans : Loan[*] { derived }; + volatile property books : Book[*] { !unique derived }; + } + class Loan + { + attribute date : Ecore::EDate[?]; + property book : tutorial::Organization::SubOrg1::sb1C; + property member : Member; + annotation + { + reference tutorial::Organization::Librarian::orgOpp; + } + } + package Organization : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization' + { + enum Type { !serializable } + { + literal asd = 0; + } + datatype JavaPackage : 'java.lang.Package' { !serializable }; + class Librarian extends extlibrary::Employee + { + operation orgOpp() : Ecore::ELong[?]; + property workOn : tutorial::Organization::SubOrg2::sb2C[?]; + } + class Ref extends tutorial::Library + { + property RefOutsideEcore : extlibrary::Item[?]; + } + package SubOrg1 : sb = 'suborg1' + { + class sb1C; + } + package SubOrg2 : sb2 = 'SubOrg2' + { + class sb2C; + } + annotation 'extAnno' + { + reference extlibrary::Item; + reference extlibrary::Item::publicationDate; + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/test2.g4 b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/test2.g4 new file mode 100644 index 00000000..da72925d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/test2.g4 @@ -0,0 +1,14 @@ +grammar test2; + +example: + left=example '*' right=example #integerExample + | left=inner '+' right=inner #stringExample + ; + +inner: integer | string; + +integer: INTEGER; +string: STRING; + +STRING: [a-zA-Z]; +INTEGER: [a-zA-Z]; \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/tutorial.recore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/tutorial.recore new file mode 100644 index 00000000..cd6c744a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/tutorial.recore @@ -0,0 +1,44 @@ +import ecore : 'http://www.eclipse.org/emf/2002/Ecore' ; + +package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' +{ + class Library + { + attribute name : String[1]; + property books#library : Book[*|1] { composes }; + property loans : Loan[*|1] { composes }; + property members#library : Member[*|1] { composes }; + } + class Book + { + operation isAvailable() : Boolean[?]; + attribute name : String[1]; + attribute copies : Integer[1]; + property library#books : Library[?]; + property loans : Loan[*|1] { derived }; + } + class Member extends Employee + { + attribute name : String[1]; + property library#members : Library[?]; + volatile property loans : Loan[*|1] { derived }; + volatile property books : Book[*|1] { !unique derived }; + } + class Loan + { + property book : Book[1]; + property member : Member[1]; + attribute date : Book[?]; + } + package Organization : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization' + { + abstract class Librarian extends Employee + { + property workOn : tutorial.Library[1]; + } + abstract class Employee + { + property books : tutorial.Book[+]; + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/tutorialExtended.recore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/tutorialExtended.recore new file mode 100644 index 00000000..7ef63d6d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/tutorialExtended.recore @@ -0,0 +1,110 @@ +import ecore : 'http://www.eclipse.org/emf/2002/Ecore' ; import extlib : 'extlibrary.ecore#/' ; + +package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' +{ + package Organization : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization' + { + abstract class Librarian extends Employee + { + property workOn : tutorial::Library[1]; + } + abstract class Employee extends tutorial::Library + { + property RefOutsideEcore : extlib::Item[+]; + } + datatype JavaPackage : 'java.lang.Package' { serializable }; + enum Type + { + annotation 'MODELWRITER' + ( + 'constraint' = 'formula...', + 'constraints' = ' ' + ); + literal type1; + literal type2; + } + } + abstract class Library { interface } + { + attribute name : String[1] { id }; + property books#library : Book[*] { composes }; + property loans : Loan[*] { composes }; + property members#library : Member[*] { composes }; + } + class Book + { + annotation 'MODELWRITER' + ( + 'constraint' = 'formula...', + 'constraints' = '' + ) + { + annotation 'MODELWRITERs' + ( + 'constraint' = 'formula. -> ..', + 'constraints' = 'formula...' + ) + { + property books : Book[*] { composes }; + attribute name : String[1] { id }; + enum Test { serializable } + { + literal entry1; + } + operation isAvailable() : Boolean[?] + { + annotation 'modelwriter.eu' + ( + 'constraint' = 'formula...' + ); + body: expr; + } + datatype JavaPackage : 'java.lang.Package' { serializable }; + reference extlib::Book; + reference extlib::BookOnTape::author; + reference extlib::Addressable; + } + reference extlib::Book; + reference extlib::BookOnTape::author; + reference extlib::Addressable; + } + annotation; + operation isAvailable() : Boolean[?] + { + precondition:; + precondition test:; + body test: expr; + body: expr; + } + attribute name : String[1]; + attribute copies : Integer[1]; + property library#books : Library[?]; + property loans : Loan[*] { derived volatile } + { + initial: A.r; + } + invariant SufficientCopies: all x: A | one x.r; + } + class Member + { + attribute name : String[1]; + property library#members : Library[?]; + property loans : Loan[*] { derived volatile } + { + initial: x.r; + derivation: x.r; + } + property books : Book[*] { !unique derived volatile } + { + initial: x.r; + } + invariant AtMostTwoLoans: all x: A | one x.r; + invariant UniqueLoans: all x: A | one x.r; + } + class Loan + { + property book : Book[1]; + property member : Member[1]; + attribute date : ecore::EDate[?]; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/yunus.recore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/yunus.recore new file mode 100644 index 00000000..6a06d6e1 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/AlloyInECore/yunus.recore @@ -0,0 +1,108 @@ +model asd; + +import asdasd : 'http://www.eclipse.org/emf/2002/Ecore'; + +package extlibrary : extlib = 'http:///org/eclipse/emf/examples/library/extlibrary.ecore/1.0.0' +{ + public class Book extends CirculatingItem + { + private attribute title : asdasd::EString[?]; + public attribute pages : asdasd::EInt[?] = '100'; + attribute category : BookCategory[?] { unsettable }; + property author#books : Writer; + } + class Library extends Addressable + { + private attribute name : asdasd::EString[?]; + transient volatle attribute people : asdasd::EFeatureMapEntry[*] { ordered } + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'kind' = 'group' + ); + } + transient volatile property writers : Writer[*] { ordered derived !resolve composes } + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'group' = '#people' + ); + } + transient volatile property employees : Employee[*] { ordered derived !resolve composes } + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'group' = '#people' + ); + } + transient volatile property borrowers : Borrower[*] { ordered derived !resolve composes } + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'group' = '#people' + ); + } + property stock : Item[*] { !resolve composes }; + transient property books : Book[*] { derived }; + property branches#parentBranch : Library[*] { ordered composes }; + property parentBranch#branches : Library[?]; + } + class Writer extends Person + { + transient volatile attribute name : asdasd::EString[?]; + property books#author : Book[*] { ordered }; + } + enum BookCategory + { + literal Mystery = 0; + literal ScienceFiction = 1; + literal Biography = 2; + } + abstract class Item + { + attribute publicationDate : asdasd::EDate[?]; + } + interface Lendable + { + attribute copies : asdasd::EInt; + property borrowers#borrowed : Borrower[*]; + } + abstract class CirculatingItem extends Item, Lendable; + abstract class Periodical extends Item + { + attribute title : asdasd::EString[?]; + attribute issuesPerYear : asdasd::EInt; + } + abstract class AudioVisualItem extends CirculatingItem + { + attribute title : asdasd::EString[?]; + attribute minutesLength : asdasd::EInt; + attribute damaged : asdasd::EBoolean[?]; + } + class BookOnTape extends AudioVisualItem + { + property reader : Person[?]; + property author : Writer[?]; + } + class VideoCassette extends AudioVisualItem + { + property cast : Person[*] { ordered }; + } + class Borrower extends Person + { + property borrowed#borrowers : Lendable[*] { ordered }; + } + class Person extends Addressable + { + attribute firstName : asdasd::EString; + attribute lastName : asdasd::EString; + } + class Employee extends Person + { + property manager : Employee[?]; + } + interface Addressable + { + attribute address : asdasd::EString[?]; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/GenericTypeAnalysis.g4 b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/GenericTypeAnalysis.g4 new file mode 100644 index 00000000..69d9c806 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/GenericTypeAnalysis.g4 @@ -0,0 +1,84 @@ +grammar GenericTypeAnalysis; + +classifierTemplateSignature: + '<' ownedTypeParameters+= classifierTypeParameter (',' ownedTypeParameters+= classifierTypeParameter)* '>' +; + +classifierTypeParameter: + name= unrestrictedName ('extends' ownedEBounds+= classifierGenericBoundType ('&' ownedEBounds+= classifierGenericBoundType)*)? +; + +classifierGenericBoundType: + // classifierref, generictypeclassref, not primitive, not typeparameterref, not wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. + // wildcardref's extend should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, not wildcardref. + ownedPathName= pathName ('<' ownedETypeArguments= templateBinding '>')? +; + +operationTemplateSignature: + '<' ownedTypeParameters+= operationTypeParameter (',' ownedTypeParameters+= operationTypeParameter)* '>' +; + +operationTypeParameter: + name= unrestrictedName ('extends' ownedEBounds+= operationGenericBoundType ('&' ownedEBounds+= operationGenericBoundType)*)? +; + +operationGenericBoundType: + // classifierref, generictypeclassref, not primitive, , not wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. + // wildcardref's extend should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, not wildcardref. + ownedPathName= pathName ('<' ownedETypeArguments= templateBinding '>')? +; + + + +classSuperTypeRef: + // should be: + // classifierref, generictypeclassref, not primitive, not typeparameterref, not wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. +; + + +attributeTypeRef: + // should be: + // enumRef, datatypeRef, not classref, generictypeclassref, primitive, typeparameterref, not wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. +; + +referenceTypeRef: + // should be: + // not enumRef, not datatypeRef, classref, generictypeclassref, not primitive, typeparameterref, not wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. +; + +operationReturnTypeRef: + // should be: + // classifierref, generictypeclassref, primitive, typeparameterref, not wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. +; + +operationParameterTypeRef: + // should be: + // classifierref, generictypeclassref, primitive, typeparameterref, not wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. +; + +operationExceptionTypeRef: + // should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, not wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. +; \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/InstanceTestFolder/Instance.requirement b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/InstanceTestFolder/Instance.requirement new file mode 100644 index 00000000..c5c9a5fe --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/InstanceTestFolder/Instance.requirement @@ -0,0 +1,56 @@ +model RequirementsMetamodel : 'Requirements.ecore'; + +RequirementsModel +{ + name: "My requirements", + requirements: + { + Requirement "A" + { + ID: 0, + reason: "", + parts: + { + test::PartTypeA + { + name: "s" + } + test::PartTypeB + { + name: "s" + } + } + } + Requirement "D" + { + ID: 0 + } + Requirement "B" + { + ID: 1.1 + } + Requirement "E" + { + ID: .1 + } + Requirement "D" + { + ID: 0 + } + }, + relationships: + { + Require + { + source: A, + target: [B, C] + } + }, + composedOf: + { + Requirement "C" + { + ID: 2 + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/InstanceTestFolder/Instance.xmi b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/InstanceTestFolder/Instance.xmi new file mode 100644 index 00000000..9fd845c7 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/InstanceTestFolder/Instance.xmi @@ -0,0 +1,25 @@ + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/InstanceTestFolder/Requirement.ecore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/InstanceTestFolder/Requirement.ecore new file mode 100644 index 00000000..70fd43cb --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/InstanceTestFolder/Requirement.ecore @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/InstanceTestFolder/Requirement.recore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/InstanceTestFolder/Requirement.recore new file mode 100644 index 00000000..7f22fe46 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/InstanceTestFolder/Requirement.recore @@ -0,0 +1,51 @@ +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package RequirementsMetamodel : Req = 'eu.modelwriter.demonstrations.alloyinecore.requirement' +{ + class RequirementsModel + { + attribute name : String[?]; + property requirements : Requirement[*] { ordered composes }; + property relationships : Relationship[*] { ordered composes }; + } + class Requirement + { + attribute ID : Integer[?]; + attribute name : String[?] { id }; + attribute description : String[?]; + attribute reason : String[?]; + property parts : RequirementsMetamodel::test::RequirementPart[*] { ordered composes }; + } + abstract class Relationship + { + property source : Requirement[?]; + property target : Requirement[*] { ordered }; + } + enum Status + { + literal proposed = 0; + literal analyzed = 1; + literal accepted = 2; + literal rejected = 3; + literal replaced = 4; + } + enum Priority + { + literal neutral = 0; + literal lowCritical = 1; + literal critical = 2; + literal veryCritical = 3; + } + class Require extends Relationship; + class Refine extends Relationship; + class PartiallyRefine extends Relationship; + class Conflict extends Relationship; + class Contain extends Relationship; + package test : tt = 'test/test' + { + class RequirementPart + { + attribute name : String[?]; + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/InstanceTestFolder/test.xmi b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/InstanceTestFolder/test.xmi new file mode 100644 index 00000000..dee58669 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/InstanceTestFolder/test.xmi @@ -0,0 +1,71 @@ +import Tutorial : 'Tutorial.ecore'; +import Tutorial2 : 'Tutorial.xmi'; + +model RequirementsMetamodel : 'Requirements.ecore' + +RequirementsModel +{ + name: "My requirements", + requirements: + { + Requirement "A" + { + ID: 0, + reason: "", + parts: + { + test::PartTypeA + { + name: "s\"s", + enum: analyzed + } + test::PartTypeB + { + name: "s", + enum: proposed + } + } + } + Requirement "D" + { + ID, + reason: null, + outref: + { + Tutorial::Loan + { + date: "Tue Jan 01 00:00:00 EET 205", + book: Tutorial2::b2, + member: Tutorial2::members.0 + } + } + } + Requirement "B"; + Requirement "B" + { + ID: 1, + reason: "defff" + } + Requirement "E" + { + ID: 0, + reason: 0.125 + } + }, + relationships: + { + Require + { + source: A, + target: [B, C] + } + }, + composedOf: + { + Requirement "C" + { + ID: 2, + reason: "defff" + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/Types/Filesystem.kodkod b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/Types/Filesystem.kodkod new file mode 100644 index 00000000..52ea874e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/Types/Filesystem.kodkod @@ -0,0 +1,14 @@ +universe {d0, d1, d2, d3, f0, f1, f2, f3} + +relations { + File : [ {(f0), (f1), (f2)} ] + Dir : [ {(d0), (d1), (d2)} ] + Root: Dir [{(d0)}] + contents: Dir -> File [{[d0, d1], [d0, f0], [d0, f1], [d0, f2]}, {[d0, d1], [d0, f0], [d0, f1], [d0, f2], [d1, d2]}] +} + +contents in Dir -> (Dir + File) +all d:Dir | not (d in d.^contents) +Root in Dir +(File + Dir) in Root.*contents + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/Types/TypeDefinitions.kodkod b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/Types/TypeDefinitions.kodkod new file mode 100644 index 00000000..e295b878 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/Types/TypeDefinitions.kodkod @@ -0,0 +1,24 @@ +universe {d0, d1, d2, d3, f0, f1, f2, f3} + +relations { +File 1: [ {(f0), (f1), (f2), (f3)} ] +Dir 1 : [ {(d0), (d1), (d2)} ] +Root 1 : Dir [{(d0)}] --type checking : arity check must be performed +contents 2: Dir -> File.r3 [[[d0, d1], [d0, d2], [d0, f0], [d0, f1], [d0, f2] ]] --type checking : arity check must be performed +A: Root [[(a0), (a1)]] +B: [[(b1), (b2)]] +C: [[(c1), (c2)]] +r0: A one -> one B [[[d0, d1], [d0, d2], [d0, f0], [d0, f1], [d0, f2] ]] --bounds are now irrelavant +r1: A -> (B one -> C) [[[a0, b1, c1], [a0, b2, c2], [a0, b0, c1], [a0, b1, c2], [a0, b2, c1]]] --if it is defined as exact bounds, it may be checked! +r2: (A -> B) -> C [[[a0, b1, c1], [a0, b2, c2], [a0, b0, c1], [a0, b1, c2], [a0, b2, c1]]] +r3: (A -> B -> C) [[[a0, b1, c1], [a0, b2, c2], [a0, b0, c1], [a0, b1, c2], [a0, b2, c1]]] +r4: (A -> B) lone -> C [[]] --if type is defined and but not bounds, LB is set to empty set, but upper bound is set to the cartesian product defined +r5: A -> B -> C [[[d0, d1], [d0, d2], [d0, f0], [d0, f1], [d0, f2] ]] --type checking error, arity does not conform to bounds. +r6: (Alias -> Addr) + (Group -> (Addr + Alias + Group)) [[]] --type checking error, undefined relations + +} + +contents in Dir -> (Dir + File) +all d:Dir | not (d in d.^contents) +Root in Dir +(File + Dir) in Root.*contents diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/Types/program.als b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/Types/program.als new file mode 100644 index 00000000..a6d8cda6 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/Types/program.als @@ -0,0 +1,109 @@ +model appendixA/addressBook2 + +sig Addr, Name { } + +sig Book { + addr: Name -> (Name + Addr) + } + +/* + +---------------- +x: m e + +---------------- +r: A m -> n B +all a: A | n a.r +all b: B | m r.b + +---------------- +r: A -> (B m -> n C) +all a: A | a.r in B m -> n C + +---------------- +r: (A m -> n B) -> C +all c: C | r.c in A m -> n B +---------------- + +*/ + +--addr: Book -> (Name lone -> Addr) +pred show1 { + all b: Book | b.addr in Name lone -> Addr +} + +//r: (A m -> n B) -> C +pred show2 { + all b: Book | b.addr in Name lone -> Addr +} + +run show1 for 3 + +/* +A +B:A +C:A +D:A + +no (B & C) +no (B + C) & D +*/ + +/* +A +B +rel: A -> one B +--> +all a: A | one a.rel && a.rel in B +*/ + +/* +A +B +rel: A -> set B + +all a: A | one a.rel && a.rel in B +--> +all a: A | a.rel in B +rel.univ in A +*/ + +/* +A +B +C +rel: A -> B -> C +--> +all a: A | a.rel in B -> C +rel.univ.univ in A +*/ + +/* +A +B +C +D +rel: A -> B -> C -> D +--> +all a: A | a.rel in B -> C -> D +rel.univ.univ.univ in A +*/ + +/* +A +B +C +rel: A -> (B lone -> one C) +--> +all a: A | a.rel in B -> C && + (all b: B | one b.(a.rel) && b.(a.rel) in C) && + (all c: C | lone (a.rel).c && (a.rel).c in B) + +rel.univ.univ in A + +*/ + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/java/Java.g4 b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/java/Java.g4 new file mode 100644 index 00000000..2d804a4a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/java/Java.g4 @@ -0,0 +1,1016 @@ +/* + [The "BSD licence"] + Copyright (c) 2013 Terence Parr, Sam Harwell + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** A Java 1.7 grammar for ANTLR v4 derived from ANTLR v3 Java grammar. + * Uses ANTLR v4's left-recursive expression notation. + * It parses ECJ, Netbeans, JDK etc... + * + * Sam Harwell cleaned this up significantly and updated to 1.7! + * + * You can test with + * + * $ antlr4 Java.g4 + * $ javac *.java + * $ grun Java compilationUnit *.java + */ +grammar Java; + +// starting point for parsing a java file +compilationUnit + : packageDeclaration? importDeclaration* typeDeclaration* EOF + ; + +packageDeclaration + : annotation* 'package' qualifiedName ';' + ; + +importDeclaration + : 'import' 'static'? qualifiedName ('.' '*')? ';' + ; + +typeDeclaration + : classOrInterfaceModifier* classDeclaration + | classOrInterfaceModifier* enumDeclaration + | classOrInterfaceModifier* interfaceDeclaration + | classOrInterfaceModifier* annotationTypeDeclaration + | ';' + ; + +modifier + : classOrInterfaceModifier + | ( 'native' + | 'synchronized' + | 'transient' + | 'volatile' + ) + ; + +classOrInterfaceModifier + : annotation // class or interface + | ( 'public' // class or interface + | 'protected' // class or interface + | 'private' // class or interface + | 'static' // class or interface + | 'abstract' // class or interface + | 'final' // class only -- does not apply to interfaces + | 'strictfp' // class or interface + ) + ; + +variableModifier + : 'final' + | annotation + ; + +classDeclaration + : 'class' Identifier typeParameters? + ('extends' typeType)? + ('implements' typeList)? + classBody + ; + +typeParameters + : '<' typeParameter (',' typeParameter)* '>' + ; + +typeParameter + : Identifier ('extends' typeBound)? + ; + +typeBound + : typeType ('&' typeType)* + ; + +enumDeclaration + : ENUM Identifier ('implements' typeList)? + '{' enumConstants? ','? enumBodyDeclarations? '}' + ; + +enumConstants + : enumConstant (',' enumConstant)* + ; + +enumConstant + : annotation* Identifier arguments? classBody? + ; + +enumBodyDeclarations + : ';' classBodyDeclaration* + ; + +interfaceDeclaration + : 'interface' Identifier typeParameters? ('extends' typeList)? interfaceBody + ; + +typeList + : typeType (',' typeType)* + ; + +classBody + : '{' classBodyDeclaration* '}' + ; + +interfaceBody + : '{' interfaceBodyDeclaration* '}' + ; + +classBodyDeclaration + : ';' + | 'static'? block + | modifier* memberDeclaration + ; + +memberDeclaration + : methodDeclaration + | genericMethodDeclaration + | fieldDeclaration + | constructorDeclaration + | genericConstructorDeclaration + | interfaceDeclaration + | annotationTypeDeclaration + | classDeclaration + | enumDeclaration + ; + +/* We use rule this even for void methods which cannot have [] after parameters. + This simplifies grammar and we can consider void to be a type, which + renders the [] matching as a context-sensitive issue or a semantic check + for invalid return type after parsing. + */ +methodDeclaration + : (typeType|'void') Identifier formalParameters ('[' ']')* + ('throws' qualifiedNameList)? + ( methodBody + | ';' + ) + ; + +genericMethodDeclaration + : typeParameters methodDeclaration + ; + +constructorDeclaration + : Identifier formalParameters ('throws' qualifiedNameList)? + constructorBody + ; + +genericConstructorDeclaration + : typeParameters constructorDeclaration + ; + +fieldDeclaration + : typeType variableDeclarators ';' + ; + +interfaceBodyDeclaration + : modifier* interfaceMemberDeclaration + | ';' + ; + +interfaceMemberDeclaration + : constDeclaration + | interfaceMethodDeclaration + | genericInterfaceMethodDeclaration + | interfaceDeclaration + | annotationTypeDeclaration + | classDeclaration + | enumDeclaration + ; + +constDeclaration + : typeType constantDeclarator (',' constantDeclarator)* ';' + ; + +constantDeclarator + : Identifier ('[' ']')* '=' variableInitializer + ; + +// see matching of [] comment in methodDeclaratorRest +interfaceMethodDeclaration + : (typeType|'void') Identifier formalParameters ('[' ']')* + ('throws' qualifiedNameList)? + ';' + ; + +genericInterfaceMethodDeclaration + : typeParameters interfaceMethodDeclaration + ; + +variableDeclarators + : variableDeclarator (',' variableDeclarator)* + ; + +variableDeclarator + : variableDeclaratorId ('=' variableInitializer)? + ; + +variableDeclaratorId + : Identifier ('[' ']')* + ; + +variableInitializer + : arrayInitializer + | expression + ; + +arrayInitializer + : '{' (variableInitializer (',' variableInitializer)* (',')? )? '}' + ; + +enumConstantName + : Identifier + ; + +typeType + : classOrInterfaceType ('[' ']')* + | primitiveType ('[' ']')* + ; + +classOrInterfaceType + : Identifier typeArguments? ('.' Identifier typeArguments? )* + ; + +primitiveType + : 'boolean' + | 'char' + | 'byte' + | 'short' + | 'int' + | 'long' + | 'float' + | 'double' + ; + +typeArguments + : '<' typeArgument (',' typeArgument)* '>' + ; + +typeArgument + : typeType + | '?' (('extends' | 'super') typeType)? + ; + +qualifiedNameList + : qualifiedName (',' qualifiedName)* + ; + +formalParameters + : '(' formalParameterList? ')' + ; + +formalParameterList + : formalParameter (',' formalParameter)* (',' lastFormalParameter)? + | lastFormalParameter + ; + +formalParameter + : variableModifier* typeType variableDeclaratorId + ; + +lastFormalParameter + : variableModifier* typeType '...' variableDeclaratorId + ; + +methodBody + : block + ; + +constructorBody + : block + ; + +qualifiedName + : Identifier ('.' Identifier)* + ; + +literal + : IntegerLiteral + | FloatingPointLiteral + | CharacterLiteral + | StringLiteral + | BooleanLiteral + | 'null' + ; + +// ANNOTATIONS + +annotation + : '@' annotationName ( '(' ( elementValuePairs | elementValue )? ')' )? + ; + +annotationName : qualifiedName ; + +elementValuePairs + : elementValuePair (',' elementValuePair)* + ; + +elementValuePair + : Identifier '=' elementValue + ; + +elementValue + : expression + | annotation + | elementValueArrayInitializer + ; + +elementValueArrayInitializer + : '{' (elementValue (',' elementValue)*)? (',')? '}' + ; + +annotationTypeDeclaration + : '@' 'interface' Identifier annotationTypeBody + ; + +annotationTypeBody + : '{' (annotationTypeElementDeclaration)* '}' + ; + +annotationTypeElementDeclaration + : modifier* annotationTypeElementRest + | ';' // this is not allowed by the grammar, but apparently allowed by the actual compiler + ; + +annotationTypeElementRest + : typeType annotationMethodOrConstantRest ';' + | classDeclaration ';'? + | interfaceDeclaration ';'? + | enumDeclaration ';'? + | annotationTypeDeclaration ';'? + ; + +annotationMethodOrConstantRest + : annotationMethodRest + | annotationConstantRest + ; + +annotationMethodRest + : Identifier '(' ')' defaultValue? + ; + +annotationConstantRest + : variableDeclarators + ; + +defaultValue + : 'default' elementValue + ; + +// STATEMENTS / BLOCKS + +block + : '{' blockStatement* '}' + ; + +blockStatement + : localVariableDeclarationStatement + | statement + | typeDeclaration + ; + +localVariableDeclarationStatement + : localVariableDeclaration ';' + ; + +localVariableDeclaration + : variableModifier* typeType variableDeclarators + ; + +statement + : block + | ASSERT expression (':' expression)? ';' + | 'if' parExpression statement ('else' statement)? + | 'for' '(' forControl ')' statement + | 'while' parExpression statement + | 'do' statement 'while' parExpression ';' + | 'try' block (catchClause+ finallyBlock? | finallyBlock) + | 'try' resourceSpecification block catchClause* finallyBlock? + | 'switch' parExpression '{' switchBlockStatementGroup* switchLabel* '}' + | 'synchronized' parExpression block + | 'return' expression? ';' + | 'throw' expression ';' + | 'break' Identifier? ';' + | 'continue' Identifier? ';' + | ';' + | statementExpression ';' + | Identifier ':' statement + ; + +catchClause + : 'catch' '(' variableModifier* catchType Identifier ')' block + ; + +catchType + : qualifiedName ('|' qualifiedName)* + ; + +finallyBlock + : 'finally' block + ; + +resourceSpecification + : '(' resources ';'? ')' + ; + +resources + : resource (';' resource)* + ; + +resource + : variableModifier* classOrInterfaceType variableDeclaratorId '=' expression + ; + +/** Matches cases then statements, both of which are mandatory. + * To handle empty cases at the end, we add switchLabel* to statement. + */ +switchBlockStatementGroup + : switchLabel+ blockStatement+ + ; + +switchLabel + : 'case' constantExpression ':' + | 'case' enumConstantName ':' + | 'default' ':' + ; + +forControl + : enhancedForControl + | forInit? ';' expression? ';' forUpdate? + ; + +forInit + : localVariableDeclaration + | expressionList + ; + +enhancedForControl + : variableModifier* typeType variableDeclaratorId ':' expression + ; + +forUpdate + : expressionList + ; + +// EXPRESSIONS + +parExpression + : '(' expression ')' + ; + +expressionList + : expression (',' expression)* + ; + +statementExpression + : expression + ; + +constantExpression + : expression + ; + +expression + : primary + | expression '.' Identifier + | expression '.' 'this' + | expression '.' 'new' nonWildcardTypeArguments? innerCreator + | expression '.' 'super' superSuffix + | expression '.' explicitGenericInvocation + | expression '[' expression ']' + | expression '(' expressionList? ')' + | 'new' creator + | '(' typeType ')' expression + | expression ('++' | '--') + | ('+'|'-'|'++'|'--') expression + | ('~'|'!') expression + | expression ('*'|'/'|'%') expression + | expression ('+'|'-') expression + | expression ('<' '<' | '>' '>' '>' | '>' '>') expression + | expression ('<=' | '>=' | '>' | '<') expression + | expression 'instanceof' typeType + | expression ('==' | '!=') expression + | expression '&' expression + | expression '^' expression + | expression '|' expression + | expression '&&' expression + | expression '||' expression + | expression '?' expression ':' expression + | expression + ( '=' + | '+=' + | '-=' + | '*=' + | '/=' + | '&=' + | '|=' + | '^=' + | '>>=' + | '>>>=' + | '<<=' + | '%=' + ) + expression + ; + +primary + : '(' expression ')' + | 'this' + | 'super' + | literal + | Identifier + | typeType '.' 'class' + | 'void' '.' 'class' + | nonWildcardTypeArguments (explicitGenericInvocationSuffix | 'this' arguments) + ; + +creator + : nonWildcardTypeArguments createdName classCreatorRest + | createdName (arrayCreatorRest | classCreatorRest) + ; + +createdName + : Identifier typeArgumentsOrDiamond? ('.' Identifier typeArgumentsOrDiamond?)* + | primitiveType + ; + +innerCreator + : Identifier nonWildcardTypeArgumentsOrDiamond? classCreatorRest + ; + +arrayCreatorRest + : '[' + ( ']' ('[' ']')* arrayInitializer + | expression ']' ('[' expression ']')* ('[' ']')* + ) + ; + +classCreatorRest + : arguments classBody? + ; + +explicitGenericInvocation + : nonWildcardTypeArguments explicitGenericInvocationSuffix + ; + +nonWildcardTypeArguments + : '<' typeList '>' + ; + +typeArgumentsOrDiamond + : '<' '>' + | typeArguments + ; + +nonWildcardTypeArgumentsOrDiamond + : '<' '>' + | nonWildcardTypeArguments + ; + +superSuffix + : arguments + | '.' Identifier arguments? + ; + +explicitGenericInvocationSuffix + : 'super' superSuffix + | Identifier arguments + ; + +arguments + : '(' expressionList? ')' + ; + +// LEXER + +// §3.9 Keywords + +ABSTRACT : 'abstract'; +ASSERT : 'assert'; +BOOLEAN : 'boolean'; +BREAK : 'break'; +BYTE : 'byte'; +CASE : 'case'; +CATCH : 'catch'; +CHAR : 'char'; +CLASS : 'class'; +CONST : 'const'; +CONTINUE : 'continue'; +DEFAULT : 'default'; +DO : 'do'; +DOUBLE : 'double'; +ELSE : 'else'; +ENUM : 'enum'; +EXTENDS : 'extends'; +FINAL : 'final'; +FINALLY : 'finally'; +FLOAT : 'float'; +FOR : 'for'; +IF : 'if'; +GOTO : 'goto'; +IMPLEMENTS : 'implements'; +IMPORT : 'import'; +INSTANCEOF : 'instanceof'; +INT : 'int'; +INTERFACE : 'interface'; +LONG : 'long'; +NATIVE : 'native'; +NEW : 'new'; +PACKAGE : 'package'; +PRIVATE : 'private'; +PROTECTED : 'protected'; +PUBLIC : 'public'; +RETURN : 'return'; +SHORT : 'short'; +STATIC : 'static'; +STRICTFP : 'strictfp'; +SUPER : 'super'; +SWITCH : 'switch'; +SYNCHRONIZED : 'synchronized'; +THIS : 'this'; +THROW : 'throw'; +THROWS : 'throws'; +TRANSIENT : 'transient'; +TRY : 'try'; +VOID : 'void'; +VOLATILE : 'volatile'; +WHILE : 'while'; + +// §3.10.1 Integer Literals + +IntegerLiteral + : DecimalIntegerLiteral + | HexIntegerLiteral + | OctalIntegerLiteral + | BinaryIntegerLiteral + ; + +fragment +DecimalIntegerLiteral + : DecimalNumeral IntegerTypeSuffix? + ; + +fragment +HexIntegerLiteral + : HexNumeral IntegerTypeSuffix? + ; + +fragment +OctalIntegerLiteral + : OctalNumeral IntegerTypeSuffix? + ; + +fragment +BinaryIntegerLiteral + : BinaryNumeral IntegerTypeSuffix? + ; + +fragment +IntegerTypeSuffix + : [lL] + ; + +fragment +DecimalNumeral + : '0' + | NonZeroDigit (Digits? | Underscores Digits) + ; + +fragment +Digits + : Digit (DigitOrUnderscore* Digit)? + ; + +fragment +Digit + : '0' + | NonZeroDigit + ; + +fragment +NonZeroDigit + : [1-9] + ; + +fragment +DigitOrUnderscore + : Digit + | '_' + ; + +fragment +Underscores + : '_'+ + ; + +fragment +HexNumeral + : '0' [xX] HexDigits + ; + +fragment +HexDigits + : HexDigit (HexDigitOrUnderscore* HexDigit)? + ; + +fragment +HexDigit + : [0-9a-fA-F] + ; + +fragment +HexDigitOrUnderscore + : HexDigit + | '_' + ; + +fragment +OctalNumeral + : '0' Underscores? OctalDigits + ; + +fragment +OctalDigits + : OctalDigit (OctalDigitOrUnderscore* OctalDigit)? + ; + +fragment +OctalDigit + : [0-7] + ; + +fragment +OctalDigitOrUnderscore + : OctalDigit + | '_' + ; + +fragment +BinaryNumeral + : '0' [bB] BinaryDigits + ; + +fragment +BinaryDigits + : BinaryDigit (BinaryDigitOrUnderscore* BinaryDigit)? + ; + +fragment +BinaryDigit + : [01] + ; + +fragment +BinaryDigitOrUnderscore + : BinaryDigit + | '_' + ; + +// §3.10.2 Floating-Point Literals + +FloatingPointLiteral + : DecimalFloatingPointLiteral + | HexadecimalFloatingPointLiteral + ; + +fragment +DecimalFloatingPointLiteral + : Digits '.' Digits? ExponentPart? FloatTypeSuffix? + | '.' Digits ExponentPart? FloatTypeSuffix? + | Digits ExponentPart FloatTypeSuffix? + | Digits FloatTypeSuffix + ; + +fragment +ExponentPart + : ExponentIndicator SignedInteger + ; + +fragment +ExponentIndicator + : [eE] + ; + +fragment +SignedInteger + : Sign? Digits + ; + +fragment +Sign + : [+-] + ; + +fragment +FloatTypeSuffix + : [fFdD] + ; + +fragment +HexadecimalFloatingPointLiteral + : HexSignificand BinaryExponent FloatTypeSuffix? + ; + +fragment +HexSignificand + : HexNumeral '.'? + | '0' [xX] HexDigits? '.' HexDigits + ; + +fragment +BinaryExponent + : BinaryExponentIndicator SignedInteger + ; + +fragment +BinaryExponentIndicator + : [pP] + ; + +// §3.10.3 Boolean Literals + +BooleanLiteral + : 'true' + | 'false' + ; + +// §3.10.4 Character Literals + +CharacterLiteral + : '\'' SingleCharacter '\'' + | '\'' EscapeSequence '\'' + ; + +fragment +SingleCharacter + : ~['\\] + ; + +// §3.10.5 String Literals + +StringLiteral + : '"' StringCharacters? '"' + ; + +fragment +StringCharacters + : StringCharacter+ + ; + +fragment +StringCharacter + : ~["\\] + | EscapeSequence + ; + +// §3.10.6 Escape Sequences for Character and String Literals + +fragment +EscapeSequence + : '\\' [btnfr"'\\] + | OctalEscape + | UnicodeEscape + ; + +fragment +OctalEscape + : '\\' OctalDigit + | '\\' OctalDigit OctalDigit + | '\\' ZeroToThree OctalDigit OctalDigit + ; + +fragment +UnicodeEscape + : '\\' 'u' HexDigit HexDigit HexDigit HexDigit + ; + +fragment +ZeroToThree + : [0-3] + ; + +// §3.10.7 The Null Literal + +NullLiteral + : 'null' + ; + +// §3.11 Separators + +LPAREN : '('; +RPAREN : ')'; +LBRACE : '{'; +RBRACE : '}'; +LBRACK : '['; +RBRACK : ']'; +SEMI : ';'; +COMMA : ','; +DOT : '.'; + +// §3.12 Operators + +ASSIGN : '='; +GT : '>'; +LT : '<'; +BANG : '!'; +TILDE : '~'; +QUESTION : '?'; +COLON : ':'; +EQUAL : '=='; +LE : '<='; +GE : '>='; +NOTEQUAL : '!='; +AND : '&&'; +OR : '||'; +INC : '++'; +DEC : '--'; +ADD : '+'; +SUB : '-'; +MUL : '*'; +DIV : '/'; +BITAND : '&'; +BITOR : '|'; +CARET : '^'; +MOD : '%'; + +ADD_ASSIGN : '+='; +SUB_ASSIGN : '-='; +MUL_ASSIGN : '*='; +DIV_ASSIGN : '/='; +AND_ASSIGN : '&='; +OR_ASSIGN : '|='; +XOR_ASSIGN : '^='; +MOD_ASSIGN : '%='; +LSHIFT_ASSIGN : '<<='; +RSHIFT_ASSIGN : '>>='; +URSHIFT_ASSIGN : '>>>='; + +// §3.8 Identifiers (must appear after all keywords in the grammar) + +Identifier + : JavaLetter JavaLetterOrDigit* + ; + +fragment +JavaLetter + : [a-zA-Z$_] // these are the "java letters" below 0x7F + | // covers all characters above 0x7F which are not a surrogate + ~[\u0000-\u007F\uD800-\uDBFF] + | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF + [\uD800-\uDBFF] [\uDC00-\uDFFF] + ; + +fragment +JavaLetterOrDigit + : [a-zA-Z0-9$_] // these are the "java letters or digits" below 0x7F + | // covers all characters above 0x7F which are not a surrogate + ~[\u0000-\u007F\uD800-\uDBFF] + | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF + [\uD800-\uDBFF] [\uDC00-\uDFFF] + ; + +// +// Additional symbols not defined in the lexical specification +// + +AT : '@'; +ELLIPSIS : '...'; + +// +// Whitespace and comments +// + +WS : [ \t\r\n\u000C]+ -> skip + ; + +COMMENT + : '/*' .*? '*/' -> channel(HIDDEN) + ; + +LINE_COMMENT + : '//' ~[\r\n]* -> channel(HIDDEN) + ; diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/java/Java8.g4 b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/java/Java8.g4 new file mode 100644 index 00000000..f63f01a5 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/java/Java8.g4 @@ -0,0 +1,1779 @@ +/* + * [The "BSD license"] + * Copyright (c) 2014 Terence Parr + * Copyright (c) 2014 Sam Harwell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * A Java 8 grammar for ANTLR 4 derived from the Java Language Specification + * chapter 19. + * + * NOTE: This grammar results in a generated parser that is much slower + * than the Java 7 grammar in the grammars-v4/java directory. This + * one is, however, extremely close to the spec. + * + * You can test with + * + * $ antlr4 Java8.g4 + * $ javac *.java + * $ grun Java8 compilationUnit *.java + * + * Or, +~/antlr/code/grammars-v4/java8 $ java Test . +/Users/parrt/antlr/code/grammars-v4/java8/./Java8BaseListener.java +/Users/parrt/antlr/code/grammars-v4/java8/./Java8Lexer.java +/Users/parrt/antlr/code/grammars-v4/java8/./Java8Listener.java +/Users/parrt/antlr/code/grammars-v4/java8/./Java8Parser.java +/Users/parrt/antlr/code/grammars-v4/java8/./Test.java +Total lexer+parser time 30844ms. + */ +grammar Java8; + +/* + * Productions from §3 (Lexical Structure) + */ + +literal + : IntegerLiteral + | FloatingPointLiteral + | BooleanLiteral + | CharacterLiteral + | StringLiteral + | NullLiteral + ; + +/* + * Productions from §4 (Types, Values, and Variables) + */ + +type + : primitiveType + | referenceType + ; + +primitiveType + : annotation* numericType + | annotation* 'boolean' + ; + +numericType + : integralType + | floatingPointType + ; + +integralType + : 'byte' + | 'short' + | 'int' + | 'long' + | 'char' + ; + +floatingPointType + : 'float' + | 'double' + ; + +referenceType + : classOrInterfaceType + | typeVariable + | arrayType + ; + +classOrInterfaceType + : ( classType_lfno_classOrInterfaceType + | interfaceType_lfno_classOrInterfaceType + ) + ( classType_lf_classOrInterfaceType + | interfaceType_lf_classOrInterfaceType + )* + ; + +classType + : annotation* Identifier typeArguments? + | classOrInterfaceType '.' annotation* Identifier typeArguments? + ; + +classType_lf_classOrInterfaceType + : '.' annotation* Identifier typeArguments? + ; + +classType_lfno_classOrInterfaceType + : annotation* Identifier typeArguments? + ; + +interfaceType + : classType + ; + +interfaceType_lf_classOrInterfaceType + : classType_lf_classOrInterfaceType + ; + +interfaceType_lfno_classOrInterfaceType + : classType_lfno_classOrInterfaceType + ; + +typeVariable + : annotation* Identifier + ; + +arrayType + : primitiveType dims + | classOrInterfaceType dims + | typeVariable dims + ; + +dims + : annotation* '[' ']' (annotation* '[' ']')* + ; + +typeParameter + : typeParameterModifier* Identifier typeBound? + ; + +typeParameterModifier + : annotation + ; + +typeBound + : 'extends' typeVariable + | 'extends' classOrInterfaceType additionalBound* + ; + +additionalBound + : '&' interfaceType + ; + +typeArguments + : '<' typeArgumentList '>' + ; + +typeArgumentList + : typeArgument (',' typeArgument)* + ; + +typeArgument + : referenceType + | wildcard + ; + +wildcard + : annotation* '?' wildcardBounds? + ; + +wildcardBounds + : 'extends' referenceType + | 'super' referenceType + ; + +/* + * Productions from §6 (Names) + */ + +packageName + : Identifier + | packageName '.' Identifier + ; + +typeName + : Identifier + | packageOrTypeName '.' Identifier + ; + +packageOrTypeName + : Identifier + | packageOrTypeName '.' Identifier + ; + +expressionName + : Identifier + | ambiguousName '.' Identifier + ; + +methodName + : Identifier + ; + +ambiguousName + : Identifier + | ambiguousName '.' Identifier + ; + +/* + * Productions from §7 (Packages) + */ + +compilationUnit + : packageDeclaration? importDeclaration* typeDeclaration* EOF + ; + +packageDeclaration + : packageModifier* 'package' Identifier ('.' Identifier)* ';' + ; + +packageModifier + : annotation + ; + +importDeclaration + : singleTypeImportDeclaration + | typeImportOnDemandDeclaration + | singleStaticImportDeclaration + | staticImportOnDemandDeclaration + ; + +singleTypeImportDeclaration + : 'import' typeName ';' + ; + +typeImportOnDemandDeclaration + : 'import' packageOrTypeName '.' '*' ';' + ; + +singleStaticImportDeclaration + : 'import' 'static' typeName '.' Identifier ';' + ; + +staticImportOnDemandDeclaration + : 'import' 'static' typeName '.' '*' ';' + ; + +typeDeclaration + : classDeclaration + | interfaceDeclaration + | ';' + ; + +/* + * Productions from §8 (Classes) + */ + +classDeclaration + : normalClassDeclaration + | enumDeclaration + ; + +normalClassDeclaration + : classModifier* 'class' Identifier typeParameters? superclass? superinterfaces? classBody + ; + +classModifier + : annotation + | 'public' + | 'protected' + | 'private' + | 'abstract' + | 'static' + | 'final' + | 'strictfp' + ; + +typeParameters + : '<' typeParameterList '>' + ; + +typeParameterList + : typeParameter (',' typeParameter)* + ; + +superclass + : 'extends' classType + ; + +superinterfaces + : 'implements' interfaceTypeList + ; + +interfaceTypeList + : interfaceType (',' interfaceType)* + ; + +classBody + : '{' classBodyDeclaration* '}' + ; + +classBodyDeclaration + : classMemberDeclaration + | instanceInitializer + | staticInitializer + | constructorDeclaration + ; + +classMemberDeclaration + : fieldDeclaration + | methodDeclaration + | classDeclaration + | interfaceDeclaration + | ';' + ; + +fieldDeclaration + : fieldModifier* unannType variableDeclaratorList ';' + ; + +fieldModifier + : annotation + | 'public' + | 'protected' + | 'private' + | 'static' + | 'final' + | 'transient' + | 'volatile' + ; + +variableDeclaratorList + : variableDeclarator (',' variableDeclarator)* + ; + +variableDeclarator + : variableDeclaratorId ('=' variableInitializer)? + ; + +variableDeclaratorId + : Identifier dims? + ; + +variableInitializer + : expression + | arrayInitializer + ; + +unannType + : unannPrimitiveType + | unannReferenceType + ; + +unannPrimitiveType + : numericType + | 'boolean' + ; + +unannReferenceType + : unannClassOrInterfaceType + | unannTypeVariable + | unannArrayType + ; + +unannClassOrInterfaceType + : ( unannClassType_lfno_unannClassOrInterfaceType + | unannInterfaceType_lfno_unannClassOrInterfaceType + ) + ( unannClassType_lf_unannClassOrInterfaceType + | unannInterfaceType_lf_unannClassOrInterfaceType + )* + ; + +unannClassType + : Identifier typeArguments? + | unannClassOrInterfaceType '.' annotation* Identifier typeArguments? + ; + +unannClassType_lf_unannClassOrInterfaceType + : '.' annotation* Identifier typeArguments? + ; + +unannClassType_lfno_unannClassOrInterfaceType + : Identifier typeArguments? + ; + +unannInterfaceType + : unannClassType + ; + +unannInterfaceType_lf_unannClassOrInterfaceType + : unannClassType_lf_unannClassOrInterfaceType + ; + +unannInterfaceType_lfno_unannClassOrInterfaceType + : unannClassType_lfno_unannClassOrInterfaceType + ; + +unannTypeVariable + : Identifier + ; + +unannArrayType + : unannPrimitiveType dims + | unannClassOrInterfaceType dims + | unannTypeVariable dims + ; + +methodDeclaration + : methodModifier* methodHeader methodBody + ; + +methodModifier + : annotation + | 'public' + | 'protected' + | 'private' + | 'abstract' + | 'static' + | 'final' + | 'synchronized' + | 'native' + | 'strictfp' + ; + +methodHeader + : result methodDeclarator throws_? + | typeParameters annotation* result methodDeclarator throws_? + ; + +result + : unannType + | 'void' + ; + +methodDeclarator + : Identifier '(' formalParameterList? ')' dims? + ; + +formalParameterList + : formalParameters ',' lastFormalParameter + | lastFormalParameter + ; + +formalParameters + : formalParameter (',' formalParameter)* + | receiverParameter (',' formalParameter)* + ; + +formalParameter + : variableModifier* unannType variableDeclaratorId + ; + +variableModifier + : annotation + | 'final' + ; + +lastFormalParameter + : variableModifier* unannType annotation* '...' variableDeclaratorId + | formalParameter + ; + +receiverParameter + : annotation* unannType (Identifier '.')? 'this' + ; + +throws_ + : 'throws' exceptionTypeList + ; + +exceptionTypeList + : exceptionType (',' exceptionType)* + ; + +exceptionType + : classType + | typeVariable + ; + +methodBody + : block + | ';' + ; + +instanceInitializer + : block + ; + +staticInitializer + : 'static' block + ; + +constructorDeclaration + : constructorModifier* constructorDeclarator throws_? constructorBody + ; + +constructorModifier + : annotation + | 'public' + | 'protected' + | 'private' + ; + +constructorDeclarator + : typeParameters? simpleTypeName '(' formalParameterList? ')' + ; + +simpleTypeName + : Identifier + ; + +constructorBody + : '{' explicitConstructorInvocation? blockStatements? '}' + ; + +explicitConstructorInvocation + : typeArguments? 'this' '(' argumentList? ')' ';' + | typeArguments? 'super' '(' argumentList? ')' ';' + | expressionName '.' typeArguments? 'super' '(' argumentList? ')' ';' + | primary '.' typeArguments? 'super' '(' argumentList? ')' ';' + ; + +enumDeclaration + : classModifier* 'enum' Identifier superinterfaces? enumBody + ; + +enumBody + : '{' enumConstantList? ','? enumBodyDeclarations? '}' + ; + +enumConstantList + : enumConstant (',' enumConstant)* + ; + +enumConstant + : enumConstantModifier* Identifier ('(' argumentList? ')')? classBody? + ; + +enumConstantModifier + : annotation + ; + +enumBodyDeclarations + : ';' classBodyDeclaration* + ; + +/* + * Productions from §9 (Interfaces) + */ + +interfaceDeclaration + : normalInterfaceDeclaration + | annotationTypeDeclaration + ; + +normalInterfaceDeclaration + : interfaceModifier* 'interface' Identifier typeParameters? extendsInterfaces? interfaceBody + ; + +interfaceModifier + : annotation + | 'public' + | 'protected' + | 'private' + | 'abstract' + | 'static' + | 'strictfp' + ; + +extendsInterfaces + : 'extends' interfaceTypeList + ; + +interfaceBody + : '{' interfaceMemberDeclaration* '}' + ; + +interfaceMemberDeclaration + : constantDeclaration + | interfaceMethodDeclaration + | classDeclaration + | interfaceDeclaration + | ';' + ; + +constantDeclaration + : constantModifier* unannType variableDeclaratorList ';' + ; + +constantModifier + : annotation + | 'public' + | 'static' + | 'final' + ; + +interfaceMethodDeclaration + : interfaceMethodModifier* methodHeader methodBody + ; + +interfaceMethodModifier + : annotation + | 'public' + | 'abstract' + | 'default' + | 'static' + | 'strictfp' + ; + +annotationTypeDeclaration + : interfaceModifier* '@' 'interface' Identifier annotationTypeBody + ; + +annotationTypeBody + : '{' annotationTypeMemberDeclaration* '}' + ; + +annotationTypeMemberDeclaration + : annotationTypeElementDeclaration + | constantDeclaration + | classDeclaration + | interfaceDeclaration + | ';' + ; + +annotationTypeElementDeclaration + : annotationTypeElementModifier* unannType Identifier '(' ')' dims? defaultValue? ';' + ; + +annotationTypeElementModifier + : annotation + | 'public' + | 'abstract' + ; + +defaultValue + : 'default' elementValue + ; + +annotation + : normalAnnotation + | markerAnnotation + | singleElementAnnotation + ; + +normalAnnotation + : '@' typeName '(' elementValuePairList? ')' + ; + +elementValuePairList + : elementValuePair (',' elementValuePair)* + ; + +elementValuePair + : Identifier '=' elementValue + ; + +elementValue + : conditionalExpression + | elementValueArrayInitializer + | annotation + ; + +elementValueArrayInitializer + : '{' elementValueList? ','? '}' + ; + +elementValueList + : elementValue (',' elementValue)* + ; + +markerAnnotation + : '@' typeName + ; + +singleElementAnnotation + : '@' typeName '(' elementValue ')' + ; + +/* + * Productions from §10 (Arrays) + */ + +arrayInitializer + : '{' variableInitializerList? ','? '}' + ; + +variableInitializerList + : variableInitializer (',' variableInitializer)* + ; + +/* + * Productions from §14 (Blocks and Statements) + */ + +block + : '{' blockStatements? '}' + ; + +blockStatements + : blockStatement blockStatement* + ; + +blockStatement + : localVariableDeclarationStatement + | classDeclaration + | statement + ; + +localVariableDeclarationStatement + : localVariableDeclaration ';' + ; + +localVariableDeclaration + : variableModifier* unannType variableDeclaratorList + ; + +statement + : statementWithoutTrailingSubstatement + | labeledStatement + | ifThenStatement + | ifThenElseStatement + | whileStatement + | forStatement + ; + +statementNoShortIf + : statementWithoutTrailingSubstatement + | labeledStatementNoShortIf + | ifThenElseStatementNoShortIf + | whileStatementNoShortIf + | forStatementNoShortIf + ; + +statementWithoutTrailingSubstatement + : block + | emptyStatement + | expressionStatement + | assertStatement + | switchStatement + | doStatement + | breakStatement + | continueStatement + | returnStatement + | synchronizedStatement + | throwStatement + | tryStatement + ; + +emptyStatement + : ';' + ; + +labeledStatement + : Identifier ':' statement + ; + +labeledStatementNoShortIf + : Identifier ':' statementNoShortIf + ; + +expressionStatement + : statementExpression ';' + ; + +statementExpression + : assignment + | preIncrementExpression + | preDecrementExpression + | postIncrementExpression + | postDecrementExpression + | methodInvocation + | classInstanceCreationExpression + ; + +ifThenStatement + : 'if' '(' expression ')' statement + ; + +ifThenElseStatement + : 'if' '(' expression ')' statementNoShortIf 'else' statement + ; + +ifThenElseStatementNoShortIf + : 'if' '(' expression ')' statementNoShortIf 'else' statementNoShortIf + ; + +assertStatement + : 'assert' expression ';' + | 'assert' expression ':' expression ';' + ; + +switchStatement + : 'switch' '(' expression ')' switchBlock + ; + +switchBlock + : '{' switchBlockStatementGroup* switchLabel* '}' + ; + +switchBlockStatementGroup + : switchLabels blockStatements + ; + +switchLabels + : switchLabel switchLabel* + ; + +switchLabel + : 'case' constantExpression ':' + | 'case' enumConstantName ':' + | 'default' ':' + ; + +enumConstantName + : Identifier + ; + +whileStatement + : 'while' '(' expression ')' statement + ; + +whileStatementNoShortIf + : 'while' '(' expression ')' statementNoShortIf + ; + +doStatement + : 'do' statement 'while' '(' expression ')' ';' + ; + +forStatement + : basicForStatement + | enhancedForStatement + ; + +forStatementNoShortIf + : basicForStatementNoShortIf + | enhancedForStatementNoShortIf + ; + +basicForStatement + : 'for' '(' forInit? ';' expression? ';' forUpdate? ')' statement + ; + +basicForStatementNoShortIf + : 'for' '(' forInit? ';' expression? ';' forUpdate? ')' statementNoShortIf + ; + +forInit + : statementExpressionList + | localVariableDeclaration + ; + +forUpdate + : statementExpressionList + ; + +statementExpressionList + : statementExpression (',' statementExpression)* + ; + +enhancedForStatement + : 'for' '(' variableModifier* unannType variableDeclaratorId ':' expression ')' statement + ; + +enhancedForStatementNoShortIf + : 'for' '(' variableModifier* unannType variableDeclaratorId ':' expression ')' statementNoShortIf + ; + +breakStatement + : 'break' Identifier? ';' + ; + +continueStatement + : 'continue' Identifier? ';' + ; + +returnStatement + : 'return' expression? ';' + ; + +throwStatement + : 'throw' expression ';' + ; + +synchronizedStatement + : 'synchronized' '(' expression ')' block + ; + +tryStatement + : 'try' block catches + | 'try' block catches? finally_ + | tryWithResourcesStatement + ; + +catches + : catchClause catchClause* + ; + +catchClause + : 'catch' '(' catchFormalParameter ')' block + ; + +catchFormalParameter + : variableModifier* catchType variableDeclaratorId + ; + +catchType + : unannClassType ('|' classType)* + ; + +finally_ + : 'finally' block + ; + +tryWithResourcesStatement + : 'try' resourceSpecification block catches? finally_? + ; + +resourceSpecification + : '(' resourceList ';'? ')' + ; + +resourceList + : resource (';' resource)* + ; + +resource + : variableModifier* unannType variableDeclaratorId '=' expression + ; + +/* + * Productions from §15 (Expressions) + */ + +primary + : ( primaryNoNewArray_lfno_primary + | arrayCreationExpression + ) + ( primaryNoNewArray_lf_primary + )* + ; + +primaryNoNewArray + : literal + | typeName ('[' ']')* '.' 'class' + | 'void' '.' 'class' + | 'this' + | typeName '.' 'this' + | '(' expression ')' + | classInstanceCreationExpression + | fieldAccess + | arrayAccess + | methodInvocation + | methodReference + ; + +primaryNoNewArray_lf_arrayAccess + : + ; + +primaryNoNewArray_lfno_arrayAccess + : literal + | typeName ('[' ']')* '.' 'class' + | 'void' '.' 'class' + | 'this' + | typeName '.' 'this' + | '(' expression ')' + | classInstanceCreationExpression + | fieldAccess + | methodInvocation + | methodReference + ; + +primaryNoNewArray_lf_primary + : classInstanceCreationExpression_lf_primary + | fieldAccess_lf_primary + | arrayAccess_lf_primary + | methodInvocation_lf_primary + | methodReference_lf_primary + ; + +primaryNoNewArray_lf_primary_lf_arrayAccess_lf_primary + : + ; + +primaryNoNewArray_lf_primary_lfno_arrayAccess_lf_primary + : classInstanceCreationExpression_lf_primary + | fieldAccess_lf_primary + | methodInvocation_lf_primary + | methodReference_lf_primary + ; + +primaryNoNewArray_lfno_primary + : literal + | typeName ('[' ']')* '.' 'class' + | unannPrimitiveType ('[' ']')* '.' 'class' + | 'void' '.' 'class' + | 'this' + | typeName '.' 'this' + | '(' expression ')' + | classInstanceCreationExpression_lfno_primary + | fieldAccess_lfno_primary + | arrayAccess_lfno_primary + | methodInvocation_lfno_primary + | methodReference_lfno_primary + ; + +primaryNoNewArray_lfno_primary_lf_arrayAccess_lfno_primary + : + ; + +primaryNoNewArray_lfno_primary_lfno_arrayAccess_lfno_primary + : literal + | typeName ('[' ']')* '.' 'class' + | unannPrimitiveType ('[' ']')* '.' 'class' + | 'void' '.' 'class' + | 'this' + | typeName '.' 'this' + | '(' expression ')' + | classInstanceCreationExpression_lfno_primary + | fieldAccess_lfno_primary + | methodInvocation_lfno_primary + | methodReference_lfno_primary + ; + +classInstanceCreationExpression + : 'new' typeArguments? annotation* Identifier ('.' annotation* Identifier)* typeArgumentsOrDiamond? '(' argumentList? ')' classBody? + | expressionName '.' 'new' typeArguments? annotation* Identifier typeArgumentsOrDiamond? '(' argumentList? ')' classBody? + | primary '.' 'new' typeArguments? annotation* Identifier typeArgumentsOrDiamond? '(' argumentList? ')' classBody? + ; + +classInstanceCreationExpression_lf_primary + : '.' 'new' typeArguments? annotation* Identifier typeArgumentsOrDiamond? '(' argumentList? ')' classBody? + ; + +classInstanceCreationExpression_lfno_primary + : 'new' typeArguments? annotation* Identifier ('.' annotation* Identifier)* typeArgumentsOrDiamond? '(' argumentList? ')' classBody? + | expressionName '.' 'new' typeArguments? annotation* Identifier typeArgumentsOrDiamond? '(' argumentList? ')' classBody? + ; + +typeArgumentsOrDiamond + : typeArguments + | '<' '>' + ; + +fieldAccess + : primary '.' Identifier + | 'super' '.' Identifier + | typeName '.' 'super' '.' Identifier + ; + +fieldAccess_lf_primary + : '.' Identifier + ; + +fieldAccess_lfno_primary + : 'super' '.' Identifier + | typeName '.' 'super' '.' Identifier + ; + +arrayAccess + : ( expressionName '[' expression ']' + | primaryNoNewArray_lfno_arrayAccess '[' expression ']' + ) + ( primaryNoNewArray_lf_arrayAccess '[' expression ']' + )* + ; + +arrayAccess_lf_primary + : ( primaryNoNewArray_lf_primary_lfno_arrayAccess_lf_primary '[' expression ']' + ) + ( primaryNoNewArray_lf_primary_lf_arrayAccess_lf_primary '[' expression ']' + )* + ; + +arrayAccess_lfno_primary + : ( expressionName '[' expression ']' + | primaryNoNewArray_lfno_primary_lfno_arrayAccess_lfno_primary '[' expression ']' + ) + ( primaryNoNewArray_lfno_primary_lf_arrayAccess_lfno_primary '[' expression ']' + )* + ; + +methodInvocation + : methodName '(' argumentList? ')' + | typeName '.' typeArguments? Identifier '(' argumentList? ')' + | expressionName '.' typeArguments? Identifier '(' argumentList? ')' + | primary '.' typeArguments? Identifier '(' argumentList? ')' + | 'super' '.' typeArguments? Identifier '(' argumentList? ')' + | typeName '.' 'super' '.' typeArguments? Identifier '(' argumentList? ')' + ; + +methodInvocation_lf_primary + : '.' typeArguments? Identifier '(' argumentList? ')' + ; + +methodInvocation_lfno_primary + : methodName '(' argumentList? ')' + | typeName '.' typeArguments? Identifier '(' argumentList? ')' + | expressionName '.' typeArguments? Identifier '(' argumentList? ')' + | 'super' '.' typeArguments? Identifier '(' argumentList? ')' + | typeName '.' 'super' '.' typeArguments? Identifier '(' argumentList? ')' + ; + +argumentList + : expression (',' expression)* + ; + +methodReference + : expressionName '::' typeArguments? Identifier + | referenceType '::' typeArguments? Identifier + | primary '::' typeArguments? Identifier + | 'super' '::' typeArguments? Identifier + | typeName '.' 'super' '::' typeArguments? Identifier + | classType '::' typeArguments? 'new' + | arrayType '::' 'new' + ; + +methodReference_lf_primary + : '::' typeArguments? Identifier + ; + +methodReference_lfno_primary + : expressionName '::' typeArguments? Identifier + | referenceType '::' typeArguments? Identifier + | 'super' '::' typeArguments? Identifier + | typeName '.' 'super' '::' typeArguments? Identifier + | classType '::' typeArguments? 'new' + | arrayType '::' 'new' + ; + +arrayCreationExpression + : 'new' primitiveType dimExprs dims? + | 'new' classOrInterfaceType dimExprs dims? + | 'new' primitiveType dims arrayInitializer + | 'new' classOrInterfaceType dims arrayInitializer + ; + +dimExprs + : dimExpr dimExpr* + ; + +dimExpr + : annotation* '[' expression ']' + ; + +constantExpression + : expression + ; + +expression + : lambdaExpression + | assignmentExpression + ; + +lambdaExpression + : lambdaParameters '->' lambdaBody + ; + +lambdaParameters + : Identifier + | '(' formalParameterList? ')' + | '(' inferredFormalParameterList ')' + ; + +inferredFormalParameterList + : Identifier (',' Identifier)* + ; + +lambdaBody + : expression + | block + ; + +assignmentExpression + : conditionalExpression + | assignment + ; + +assignment + : leftHandSide assignmentOperator expression + ; + +leftHandSide + : expressionName + | fieldAccess + | arrayAccess + ; + +assignmentOperator + : '=' + | '*=' + | '/=' + | '%=' + | '+=' + | '-=' + | '<<=' + | '>>=' + | '>>>=' + | '&=' + | '^=' + | '|=' + ; + +conditionalExpression + : conditionalOrExpression + | conditionalOrExpression '?' expression ':' conditionalExpression + ; + +conditionalOrExpression + : conditionalAndExpression + | conditionalOrExpression '||' conditionalAndExpression + ; + +conditionalAndExpression + : inclusiveOrExpression + | conditionalAndExpression '&&' inclusiveOrExpression + ; + +inclusiveOrExpression + : exclusiveOrExpression + | inclusiveOrExpression '|' exclusiveOrExpression + ; + +exclusiveOrExpression + : andExpression + | exclusiveOrExpression '^' andExpression + ; + +andExpression + : equalityExpression + | andExpression '&' equalityExpression + ; + +equalityExpression + : relationalExpression + | equalityExpression '==' relationalExpression + | equalityExpression '!=' relationalExpression + ; + +relationalExpression + : shiftExpression + | relationalExpression '<' shiftExpression + | relationalExpression '>' shiftExpression + | relationalExpression '<=' shiftExpression + | relationalExpression '>=' shiftExpression + | relationalExpression 'instanceof' referenceType + ; + +shiftExpression + : additiveExpression + | shiftExpression '<' '<' additiveExpression + | shiftExpression '>' '>' additiveExpression + | shiftExpression '>' '>' '>' additiveExpression + ; + +additiveExpression + : multiplicativeExpression + | additiveExpression '+' multiplicativeExpression + | additiveExpression '-' multiplicativeExpression + ; + +multiplicativeExpression + : unaryExpression + | multiplicativeExpression '*' unaryExpression + | multiplicativeExpression '/' unaryExpression + | multiplicativeExpression '%' unaryExpression + ; + +unaryExpression + : preIncrementExpression + | preDecrementExpression + | '+' unaryExpression + | '-' unaryExpression + | unaryExpressionNotPlusMinus + ; + +preIncrementExpression + : '++' unaryExpression + ; + +preDecrementExpression + : '--' unaryExpression + ; + +unaryExpressionNotPlusMinus + : postfixExpression + | '~' unaryExpression + | '!' unaryExpression + | castExpression + ; + +postfixExpression + : ( primary + | expressionName + ) + ( postIncrementExpression_lf_postfixExpression + | postDecrementExpression_lf_postfixExpression + )* + ; + +postIncrementExpression + : postfixExpression '++' + ; + +postIncrementExpression_lf_postfixExpression + : '++' + ; + +postDecrementExpression + : postfixExpression '--' + ; + +postDecrementExpression_lf_postfixExpression + : '--' + ; + +castExpression + : '(' primitiveType ')' unaryExpression + | '(' referenceType additionalBound* ')' unaryExpressionNotPlusMinus + | '(' referenceType additionalBound* ')' lambdaExpression + ; + +// LEXER + +// §3.9 Keywords + +ABSTRACT : 'abstract'; +ASSERT : 'assert'; +BOOLEAN : 'boolean'; +BREAK : 'break'; +BYTE : 'byte'; +CASE : 'case'; +CATCH : 'catch'; +CHAR : 'char'; +CLASS : 'class'; +CONST : 'const'; +CONTINUE : 'continue'; +DEFAULT : 'default'; +DO : 'do'; +DOUBLE : 'double'; +ELSE : 'else'; +ENUM : 'enum'; +EXTENDS : 'extends'; +FINAL : 'final'; +FINALLY : 'finally'; +FLOAT : 'float'; +FOR : 'for'; +IF : 'if'; +GOTO : 'goto'; +IMPLEMENTS : 'implements'; +IMPORT : 'import'; +INSTANCEOF : 'instanceof'; +INT : 'int'; +INTERFACE : 'interface'; +LONG : 'long'; +NATIVE : 'native'; +NEW : 'new'; +PACKAGE : 'package'; +PRIVATE : 'private'; +PROTECTED : 'protected'; +PUBLIC : 'public'; +RETURN : 'return'; +SHORT : 'short'; +STATIC : 'static'; +STRICTFP : 'strictfp'; +SUPER : 'super'; +SWITCH : 'switch'; +SYNCHRONIZED : 'synchronized'; +THIS : 'this'; +THROW : 'throw'; +THROWS : 'throws'; +TRANSIENT : 'transient'; +TRY : 'try'; +VOID : 'void'; +VOLATILE : 'volatile'; +WHILE : 'while'; + +// §3.10.1 Integer Literals + +IntegerLiteral + : DecimalIntegerLiteral + | HexIntegerLiteral + | OctalIntegerLiteral + | BinaryIntegerLiteral + ; + +fragment +DecimalIntegerLiteral + : DecimalNumeral IntegerTypeSuffix? + ; + +fragment +HexIntegerLiteral + : HexNumeral IntegerTypeSuffix? + ; + +fragment +OctalIntegerLiteral + : OctalNumeral IntegerTypeSuffix? + ; + +fragment +BinaryIntegerLiteral + : BinaryNumeral IntegerTypeSuffix? + ; + +fragment +IntegerTypeSuffix + : [lL] + ; + +fragment +DecimalNumeral + : '0' + | NonZeroDigit (Digits? | Underscores Digits) + ; + +fragment +Digits + : Digit (DigitsAndUnderscores? Digit)? + ; + +fragment +Digit + : '0' + | NonZeroDigit + ; + +fragment +NonZeroDigit + : [1-9] + ; + +fragment +DigitsAndUnderscores + : DigitOrUnderscore+ + ; + +fragment +DigitOrUnderscore + : Digit + | '_' + ; + +fragment +Underscores + : '_'+ + ; + +fragment +HexNumeral + : '0' [xX] HexDigits + ; + +fragment +HexDigits + : HexDigit (HexDigitsAndUnderscores? HexDigit)? + ; + +fragment +HexDigit + : [0-9a-fA-F] + ; + +fragment +HexDigitsAndUnderscores + : HexDigitOrUnderscore+ + ; + +fragment +HexDigitOrUnderscore + : HexDigit + | '_' + ; + +fragment +OctalNumeral + : '0' Underscores? OctalDigits + ; + +fragment +OctalDigits + : OctalDigit (OctalDigitsAndUnderscores? OctalDigit)? + ; + +fragment +OctalDigit + : [0-7] + ; + +fragment +OctalDigitsAndUnderscores + : OctalDigitOrUnderscore+ + ; + +fragment +OctalDigitOrUnderscore + : OctalDigit + | '_' + ; + +fragment +BinaryNumeral + : '0' [bB] BinaryDigits + ; + +fragment +BinaryDigits + : BinaryDigit (BinaryDigitsAndUnderscores? BinaryDigit)? + ; + +fragment +BinaryDigit + : [01] + ; + +fragment +BinaryDigitsAndUnderscores + : BinaryDigitOrUnderscore+ + ; + +fragment +BinaryDigitOrUnderscore + : BinaryDigit + | '_' + ; + +// §3.10.2 Floating-Point Literals + +FloatingPointLiteral + : DecimalFloatingPointLiteral + | HexadecimalFloatingPointLiteral + ; + +fragment +DecimalFloatingPointLiteral + : Digits '.' Digits? ExponentPart? FloatTypeSuffix? + | '.' Digits ExponentPart? FloatTypeSuffix? + | Digits ExponentPart FloatTypeSuffix? + | Digits FloatTypeSuffix + ; + +fragment +ExponentPart + : ExponentIndicator SignedInteger + ; + +fragment +ExponentIndicator + : [eE] + ; + +fragment +SignedInteger + : Sign? Digits + ; + +fragment +Sign + : [+-] + ; + +fragment +FloatTypeSuffix + : [fFdD] + ; + +fragment +HexadecimalFloatingPointLiteral + : HexSignificand BinaryExponent FloatTypeSuffix? + ; + +fragment +HexSignificand + : HexNumeral '.'? + | '0' [xX] HexDigits? '.' HexDigits + ; + +fragment +BinaryExponent + : BinaryExponentIndicator SignedInteger + ; + +fragment +BinaryExponentIndicator + : [pP] + ; + +// §3.10.3 Boolean Literals + +BooleanLiteral + : 'true' + | 'false' + ; + +// §3.10.4 Character Literals + +CharacterLiteral + : '\'' SingleCharacter '\'' + | '\'' EscapeSequence '\'' + ; + +fragment +SingleCharacter + : ~['\\] + ; + +// §3.10.5 String Literals + +StringLiteral + : '"' StringCharacters? '"' + ; + +fragment +StringCharacters + : StringCharacter+ + ; + +fragment +StringCharacter + : ~["\\] + | EscapeSequence + ; + +// §3.10.6 Escape Sequences for Character and String Literals + +fragment +EscapeSequence + : '\\' [btnfr"'\\] + | OctalEscape + | UnicodeEscape // This is not in the spec but prevents having to preprocess the input + ; + +fragment +OctalEscape + : '\\' OctalDigit + | '\\' OctalDigit OctalDigit + | '\\' ZeroToThree OctalDigit OctalDigit + ; + +fragment +ZeroToThree + : [0-3] + ; + +// This is not in the spec but prevents having to preprocess the input +fragment +UnicodeEscape + : '\\' 'u' HexDigit HexDigit HexDigit HexDigit + ; + +// §3.10.7 The Null Literal + +NullLiteral + : 'null' + ; + +// §3.11 Separators + +LPAREN : '('; +RPAREN : ')'; +LBRACE : '{'; +RBRACE : '}'; +LBRACK : '['; +RBRACK : ']'; +SEMI : ';'; +COMMA : ','; +DOT : '.'; + +// §3.12 Operators + +ASSIGN : '='; +GT : '>'; +LT : '<'; +BANG : '!'; +TILDE : '~'; +QUESTION : '?'; +COLON : ':'; +EQUAL : '=='; +LE : '<='; +GE : '>='; +NOTEQUAL : '!='; +AND : '&&'; +OR : '||'; +INC : '++'; +DEC : '--'; +ADD : '+'; +SUB : '-'; +MUL : '*'; +DIV : '/'; +BITAND : '&'; +BITOR : '|'; +CARET : '^'; +MOD : '%'; +ARROW : '->'; +COLONCOLON : '::'; + +ADD_ASSIGN : '+='; +SUB_ASSIGN : '-='; +MUL_ASSIGN : '*='; +DIV_ASSIGN : '/='; +AND_ASSIGN : '&='; +OR_ASSIGN : '|='; +XOR_ASSIGN : '^='; +MOD_ASSIGN : '%='; +LSHIFT_ASSIGN : '<<='; +RSHIFT_ASSIGN : '>>='; +URSHIFT_ASSIGN : '>>>='; + +// §3.8 Identifiers (must appear after all keywords in the grammar) + +Identifier + : JavaLetter JavaLetterOrDigit* + ; + +fragment +JavaLetter + : [a-zA-Z$_] // these are the "java letters" below 0x7F + | // covers all characters above 0x7F which are not a surrogate + ~[\u0000-\u007F\uD800-\uDBFF] + {Character.isJavaIdentifierStart(_input.LA(-1))}? + | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF + [\uD800-\uDBFF] [\uDC00-\uDFFF] + {Character.isJavaIdentifierStart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}? + ; + +fragment +JavaLetterOrDigit + : [a-zA-Z0-9$_] // these are the "java letters or digits" below 0x7F + | // covers all characters above 0x7F which are not a surrogate + ~[\u0000-\u007F\uD800-\uDBFF] + {Character.isJavaIdentifierPart(_input.LA(-1))}? + | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF + [\uD800-\uDBFF] [\uDC00-\uDFFF] + {Character.isJavaIdentifierPart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}? + ; + +// +// Additional symbols not defined in the lexical specification +// + +AT : '@'; +ELLIPSIS : '...'; + +// +// Whitespace and comments +// + +WS : [ \t\r\n\u000C]+ -> skip + ; + +COMMENT + : '/*' .*? '*/' -> skip + ; + +LINE_COMMENT + : '//' ~[\r\n]* -> skip + ; diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/Arithmetic b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/Arithmetic new file mode 100644 index 00000000..5a6b661c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/Arithmetic @@ -0,0 +1,61 @@ +a00: [[], [[a]]] +a01: [[], [[a]]] +a02: [[], [[a]]] +a03: [[], [[a]]] +a04: [[], [[a]]] +a05: [[], [[a]]] +a06: [[], [[a]]] +a07: [[], [[a]]] +a10: [[], [[a]]] +a11: [[], [[a]]] +a12: [[], [[a]]] +a13: [[], [[a]]] +a14: [[], [[a]]] +a15: [[], [[a]]] +a16: [[], [[a]]] +a17: [[], [[a]]] +a20: [[], [[a]]] +a21: [[], [[a]]] +a22: [[], [[a]]] +a23: [[], [[a]]] +a24: [[], [[a]]] +a25: [[], [[a]]] +a26: [[], [[a]]] +a27: [[], [[a]]] +x0: [[], [[0], [1], [2], [3], [4], [5], [6], [7]]] +x1: [[], [[0], [1], [2], [3], [4], [5], [6], [7]]] +x2: [[], [[0], [1], [2], [3], [4], [5], [6], [7]]] +x3: [[], [[0], [1], [2], [3], [4], [5], [6], [7]]] +x4: [[], [[0], [1], [2], [3], [4], [5], [6], [7]]] +x5: [[], [[0], [1], [2], [3], [4], [5], [6], [7]]] +x6: [[], [[0], [1], [2], [3], [4], [5], [6], [7]]] +x7: [[], [[0], [1], [2], [3], [4], [5], [6], [7]]] +( + ( + ( + ( + ( + ( + ( + ((true && one x0) && one x1) && + one x2 + ) && one x3 + ) && one x4 + ) && one x5 + ) && one x6 + ) && one x7 + ) && + ( + ( + ( + (true && ( + ( + ( + ((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0)) + ) + + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0))) + ) <= 7 + ) + ) && (((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))) <= 7)) && (((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))) <= 7)) && ((((((((((((((((((((((((((((((((((((((((((((((((((((((((true && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a01 then sum(y1) else 0)) + (if some a02 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a11 then sum(y1) else 0)) + (if some a12 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a21 then sum(y1) else 0)) + (if some a22 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a01 then sum(y1) else 0)) + (if some a03 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a11 then sum(y1) else 0)) + (if some a13 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a21 then sum(y1) else 0)) + (if some a23 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a01 then sum(y1) else 0)) + (if some a04 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a11 then sum(y1) else 0)) + (if some a14 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a21 then sum(y1) else 0)) + (if some a24 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a01 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a11 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a21 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a01 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a11 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a21 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a01 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a11 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a21 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a03 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a13 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a23 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a04 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a14 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a24 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a04 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a14 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a24 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a06 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a16 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a26 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a03 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a13 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a23 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a04 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a14 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a24 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a04 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a14 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a24 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a06 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a16 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a26 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a04 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a14 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a24 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a06 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a16 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a26 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a03 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a13 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a23 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a03 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a13 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a23 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a03 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a13 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a23 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a03 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a13 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a23 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a03 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a13 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a23 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a03 then sum(y0) else 0) + (if some a06 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a13 then sum(y0) else 0) + (if some a16 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a23 then sum(y0) else 0) + (if some a26 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a04 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a14 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a24 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a04 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a14 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a24 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a04 then sum(y0) else 0) + (if some a06 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a14 then sum(y0) else 0) + (if some a16 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a24 then sum(y0) else 0) + (if some a26 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a05 then sum(y0) else 0) + (if some a06 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a15 then sum(y0) else 0) + (if some a16 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a25 then sum(y0) else 0) + (if some a26 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))))) diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/DiffEg b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/DiffEg new file mode 100644 index 00000000..c544d1ec --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/DiffEg @@ -0,0 +1,14 @@ +{Subject0, Subject1, Resource0, Resource1, Action0, Action1, Conflicted0, Conflicted1, Request0, Request1} + +Subject: [{}, {(Subject0), (Subject1)}] +Resource: [{}, {(Resource0), (Resource1)}] +Action: [{}, {(Action0), (Action1)}] +Conflicted: [{}, {(Conflicted0), (Conflicted1)}] +Request: [{}, {(Request0), (Request1)}] +s: [{}, {(Request0, Subject0), (Request0, Subject1), (Request1, Subject0), (Request1, Subject1)}] +r: [{}, {(Request0, Resource0), (Request0, Resource1), (Request1, Resource0), (Request1, Resource1)}] +a: [{}, {(Request0, Action0), (Request0, Action1), (Request1, Action0), (Request1, Action1)}] +s: [{}, {(Conflicted0, Subject0), (Conflicted0, Subject1), (Conflicted1, Subject0), (Conflicted1, Subject1)}] +r: [{}, {(Conflicted0, Resource0), (Conflicted0, Resource1), (Conflicted1, Resource0), (Conflicted1, Resource1)}] + +some req: one Request | all conf: one Conflicted | !(req.s in conf.s && req.r in conf.r) \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/DiffEg.kodkod b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/DiffEg.kodkod new file mode 100644 index 00000000..c544d1ec --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/DiffEg.kodkod @@ -0,0 +1,14 @@ +{Subject0, Subject1, Resource0, Resource1, Action0, Action1, Conflicted0, Conflicted1, Request0, Request1} + +Subject: [{}, {(Subject0), (Subject1)}] +Resource: [{}, {(Resource0), (Resource1)}] +Action: [{}, {(Action0), (Action1)}] +Conflicted: [{}, {(Conflicted0), (Conflicted1)}] +Request: [{}, {(Request0), (Request1)}] +s: [{}, {(Request0, Subject0), (Request0, Subject1), (Request1, Subject0), (Request1, Subject1)}] +r: [{}, {(Request0, Resource0), (Request0, Resource1), (Request1, Resource0), (Request1, Resource1)}] +a: [{}, {(Request0, Action0), (Request0, Action1), (Request1, Action0), (Request1, Action1)}] +s: [{}, {(Conflicted0, Subject0), (Conflicted0, Subject1), (Conflicted1, Subject0), (Conflicted1, Subject1)}] +r: [{}, {(Conflicted0, Resource0), (Conflicted0, Resource1), (Conflicted1, Resource0), (Conflicted1, Resource1)}] + +some req: one Request | all conf: one Conflicted | !(req.s in conf.s && req.r in conf.r) \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/FileSystem1.api b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/FileSystem1.api new file mode 100644 index 00000000..df871688 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/FileSystem1.api @@ -0,0 +1,54 @@ +relations: { + Object = [[Object0], [Object1], [Object2]] + Root=[[Object0]] + Cur=[] + File=[] + Dir=[[Object0], [Object1], [Object2]] + Name=[[Name0], [Name1], [Name2]] + DirEntry=[[DirEntry0], [DirEntry1], [DirEntry2]] + entries=[[Object0, DirEntry0], [Object0, DirEntry1], [Object2, DirEntry2]] + parent=[[Object1, Object2], [Object2, Object0]] + name=[[DirEntry0, Name2], [DirEntry1, Name1], [DirEntry2, Name0]], + contents=[[DirEntry0, Object2], [DirEntry1, Object2], [DirEntry2, Object1]], + $o=[[Object2]] +} + +( + ( + ( + ( + ( + ( + ( + ((Object = (File + Dir)) && no (File & Dir)) && + ( + ((Root in Dir) && (Cur in Dir)) && + no (Root & Cur) + ) + ) && (entries in (Dir -> DirEntry)) + ) && FUNCTION(parent, Dir ->lone Dir) + ) && FUNCTION(name, DirEntry ->one Name) + ) && FUNCTION(contents, DirEntry ->one Object) + ) && + ( + ( + ( + ( + (all this: one File | (some d: one Dir | (this in ((d . entries) . contents)))) && + (all this: one Dir | + ( + ( + ( + ((this . parent) = ((this . ~contents) . ~entries)) && + (all [e1: one (this . entries), e2: one (this . entries)] | (((e1 . name) = (e2 . name)) => (e1 = e2))) + ) && !(this in (this . ^parent)) + ) && (!(this = Root) => (Root in (this . ^parent))) + ) + ) + ) && no (Root . parent) + ) && (all this: one DirEntry | one (this . ~entries)) + ) && (all d: one (Dir - Root) | one (d . parent)) + ) + ) && !(all o: one Dir | lone (o . ~contents)) +) + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/FileSystem1.kodkod b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/FileSystem1.kodkod new file mode 100644 index 00000000..df871688 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/FileSystem1.kodkod @@ -0,0 +1,54 @@ +relations: { + Object = [[Object0], [Object1], [Object2]] + Root=[[Object0]] + Cur=[] + File=[] + Dir=[[Object0], [Object1], [Object2]] + Name=[[Name0], [Name1], [Name2]] + DirEntry=[[DirEntry0], [DirEntry1], [DirEntry2]] + entries=[[Object0, DirEntry0], [Object0, DirEntry1], [Object2, DirEntry2]] + parent=[[Object1, Object2], [Object2, Object0]] + name=[[DirEntry0, Name2], [DirEntry1, Name1], [DirEntry2, Name0]], + contents=[[DirEntry0, Object2], [DirEntry1, Object2], [DirEntry2, Object1]], + $o=[[Object2]] +} + +( + ( + ( + ( + ( + ( + ( + ((Object = (File + Dir)) && no (File & Dir)) && + ( + ((Root in Dir) && (Cur in Dir)) && + no (Root & Cur) + ) + ) && (entries in (Dir -> DirEntry)) + ) && FUNCTION(parent, Dir ->lone Dir) + ) && FUNCTION(name, DirEntry ->one Name) + ) && FUNCTION(contents, DirEntry ->one Object) + ) && + ( + ( + ( + ( + (all this: one File | (some d: one Dir | (this in ((d . entries) . contents)))) && + (all this: one Dir | + ( + ( + ( + ((this . parent) = ((this . ~contents) . ~entries)) && + (all [e1: one (this . entries), e2: one (this . entries)] | (((e1 . name) = (e2 . name)) => (e1 = e2))) + ) && !(this in (this . ^parent)) + ) && (!(this = Root) => (Root in (this . ^parent))) + ) + ) + ) && no (Root . parent) + ) && (all this: one DirEntry | one (this . ~entries)) + ) && (all d: one (Dir - Root) | one (d . parent)) + ) + ) && !(all o: one Dir | lone (o . ~contents)) +) + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/FileSystemKodKod1 b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/FileSystemKodKod1 new file mode 100644 index 00000000..e102c86e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/FileSystemKodKod1 @@ -0,0 +1,12 @@ +{d0, d1, d2, d3, f0, f1, f2} + +File: 1 [ {(f0), (f1), (f2)} ] +Dir: 1 [ {(d0), (d1), (d2)} ] +Root :1 [{(d0)}] +contents: [[[d0, d1], [d0, d2], [d1, f0], [d2, d3], [d3, f1], [d3, f2] ]] + +contents in Dir -> (Dir + File) +all d:Dir | not (d in d.^contents) +Root in Dir +(File + Dir) in Root.*contents + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/FileSystemKodKod2 b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/FileSystemKodKod2 new file mode 100644 index 00000000..dd856fb1 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/FileSystemKodKod2 @@ -0,0 +1,12 @@ +{d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, f0, f1, f2, f3, f4, f5, f6, f7, f8, f9} + +File: 1 [ {(f0), (f1), (f2), (f3), (f4), (f5), (f6), (f7), (f8), (f9)} ] +Dir: 1 [ {(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7), (d8), (d9), (d10)} ] +Root :1 [{(d0)}] +contents: [[[d0, d1], [d0, d2], [d1, f0], [d1, d4], [d2, d3], [d2, d5], [d2, d6], [d3, f1], [d3, f2], [d4, f3], [d4, f4], [d5, f5], [d5, f6], [d6, f7], [d6, d7], [d7, f8], [d7, d8], [d8, f9], [d8, d9], [d8, d10] ]] + +contents in Dir -> (Dir + File) +all d:Dir | not (d in d.^contents) +Root in Dir +(File + Dir) in Root.*contents + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/Filesystem-ex.kodkod b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/Filesystem-ex.kodkod new file mode 100644 index 00000000..00aee0d0 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/Filesystem-ex.kodkod @@ -0,0 +1,39 @@ +{l0, l1, l2, t0, t1, t2, a, 0, 1, 2, 3, 4, 5, 6, 7, ferhat} + +List: [{}, {(l0),(l1),(l2)}] +Nil :1 [{}, {(l0),(l1),(l2)}] +Cons: [{}, {(l0),(l1),(l2)}] +Thing :1 [{}, {(t0),(t1),(t2)}] +car :2 [{}, {(l0, t0), (l0, t1), (l0, t2), (l1, t0), (l1, t1), (l1, t2), (l2, t0), (l2, t1), (l2, t2)}] +cdr :2 [{}, {(l0, l0), (l0, l1), (l0, l2), (l1, l0), (l1, l1), (l1, l2), (l2, l0), (l2, l1), (l2, l2)}] +equivTo :2 [{}, {(l0, l0), (l0, l1), (l0, l2), (l1, l0), (l1, l1), (l1, l2), (l2, l0), (l2, l1), (l2, l2)}] +prefixes :2 [{}, {(l0, l0), (l0, l1), (l0, l2), (l1, l0), (l1, l1), (l1, l2), (l2, l0), (l2, l1), (l2, l2)}] + +List = Cons + Nil +no Cons & Nil + +car in Cons -> Thing +all a: Cons { + one a.car + one a.cdr +} + +cdr in Cons -> List + +all a: List | some e: some Nil | e in a.^cdr +equivTo in List -> List +all a, b: List | (a in b.equivTo) iff (a.car = b.car and a.cdr.equivTo = b.cdr.equivTo) +prefixes in List -> List +all e: Nil, a: List | e in a.prefixes +all e: Nil, a: Cons | not (a in e.prefixes) +all a, b: Cons | (a in b.prefixes) iff (a.car = b.car and a.cdr in b.cdr.prefixes) + +function[car: List -> one Thing] +/* +true && ((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) <= - 7 + +let parent = mother + father { + no m: Man | some m.wife and m.wife in m.*parent.mother + no w: Woman | some w.husband and w.husband in w.*parent.father +} +*/ diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/Filesystem.als b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/Filesystem.als new file mode 100644 index 00000000..80dc9379 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/Filesystem.als @@ -0,0 +1,59 @@ +model examples/systems/file_system + +/* + * Model of a generic file system. + */ + +abstract sig Object {} + +sig Name {} + +sig File extends Object {} { some d: Dir | this in d.entries.contents } + +sig Dir extends Object { + entries: set DirEntry, + parent: lone Dir +} { + parent = this.~@contents.~@entries + all e1, e2 : entries | e1.name = e2.name => e1 = e2 + this !in this.^@parent + this != Root => Root in this.^@parent +} + +one sig Root extends Dir {} { no parent } + +lone sig Cur extends Dir {} + +sig DirEntry { + name: Name, + contents: Object +} { + one this.~entries +} + + +/** + * all directories besides root have one parent + */ +pred OneParent_buggyVersion { + all d: Dir - Root | one d.parent +} + +/** + * all directories besides root have one parent + */ +pred OneParent_correctVersion { + all d: Dir - Root | (one d.parent && one contents.d) +} + +/** + * Only files may be linked (that is, have more than one entry) + * That is, all directories are the contents of at most one directory entry + */ +pred NoDirAliases { + all o: Dir | lone o.~contents +} + +check { OneParent_buggyVersion => NoDirAliases } for 5 expect 1 + +check { OneParent_correctVersion => NoDirAliases } for 5 expect 0 diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/Filesystem.kodkod b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/Filesystem.kodkod new file mode 100644 index 00000000..52ea874e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/Filesystem.kodkod @@ -0,0 +1,14 @@ +universe {d0, d1, d2, d3, f0, f1, f2, f3} + +relations { + File : [ {(f0), (f1), (f2)} ] + Dir : [ {(d0), (d1), (d2)} ] + Root: Dir [{(d0)}] + contents: Dir -> File [{[d0, d1], [d0, f0], [d0, f1], [d0, f2]}, {[d0, d1], [d0, f0], [d0, f1], [d0, f2], [d1, d2]}] +} + +contents in Dir -> (Dir + File) +all d:Dir | not (d in d.^contents) +Root in Dir +(File + Dir) in Root.*contents + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/Filesystem_wrong.kodkod b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/Filesystem_wrong.kodkod new file mode 100644 index 00000000..5057b0ea --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/Filesystem_wrong.kodkod @@ -0,0 +1,11 @@ +{d0, d1, f0, f1, f2} + +File: 1 [ {(d0), (d1)}, {(d1)} ] +Dir: 1 [ {} , {(d0), (d1)} ] +Root :1 [{(d0)}, {(d0)}] +contents: 2 [ {(d0, d1)}, {(d0, d0), (d0,d1)} ] + +contents in Dir -> (Dir + s File) +all d:Dir | not (d in d.^contents) +Root in Dir +(File + Dir) in Root.*contents diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/Hotel.kodkod b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/Hotel.kodkod new file mode 100644 index 00000000..aab0014d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/Hotel.kodkod @@ -0,0 +1,111 @@ +[Time0, Time1, Event0, Event1, Room0, Room1, Card0, Card1, Key0, Key1, Guest0, Guest1] + +Time: [[], [[Time0], [Time1]]] +Event: [[], [[Event0], [Event1]]] +Room: [[], [[Room0], [Room1]]] +Card: [[], [[Card0], [Card1]]] +Key: [[], [[Key0], [Key1]]] +Guest: [[], [[Guest0], [Guest1]]] +first: [[], [[Time0], [Time1]]] +last: [[], [[Time0], [Time1]]] +next: [[], [[Time0, Time0], [Time0, Time1], [Time1, Time0], [Time1, Time1]]] +pre: [[], [[Event0, Time0], [Event0, Time1], [Event1, Time0], [Event1, Time1]]] +post: [[], [[Event0, Time0], [Event0, Time1], [Event1, Time0], [Event1, Time1]]] +HotelEvent: [[], [[Event0], [Event1]]] +RoomCardEvent: [[], [[Event0], [Event1]]] +Enter: [[], [[Event0], [Event1]]] +NormalEnter: [[], [[Event0], [Event1]]] +RecodeEnter: [[], [[Event0], [Event1]]] +Checkin: [[], [[Event0], [Event1]]] +Checkout: [[], [[Event0], [Event1]]] +k1: [[], [[Card0, Key0], [Card0, Key1], [Card1, Key0], [Card1, Key1]]] +k2: [[], [[Card0, Key0], [Card0, Key1], [Card1, Key0], [Card1, Key1]]] +key: [[], [[Room0, Key0, Time0], [Room0, Key0, Time1], [Room0, Key1, Time0], [Room0, Key1, Time1], [Room1, Key0, Time0], [Room1, Key0, Time1], [Room1, Key1, Time0], [Room1, Key1, Time1]]] +prev: [[], [[Room0, Key0, Time0], [Room0, Key0, Time1], [Room0, Key1, Time0], [Room0, Key1, Time1], [Room1, Key0, Time0], [Room1, Key0, Time1], [Room1, Key1, Time0], [Room1, Key1, Time1]]] +occ: [[], [[Room0, Guest0, Time0], [Room0, Guest0, Time1], [Room0, Guest1, Time0], [Room0, Guest1, Time1], [Room1, Guest0, Time0], [Room1, Guest0, Time1], [Room1, Guest1, Time0], [Room1, Guest1, Time1]]] +holds: [[], [[Guest0, Card0, Time0], [Guest0, Card0, Time1], [Guest0, Card1, Time0], [Guest0, Card1, Time1], [Guest1, Card0, Time0], [Guest1, Card0, Time1], [Guest1, Card1, Time0], [Guest1, Card1, Time1]]] +guest: [[], [[Event0, Guest0], [Event0, Guest1], [Event1, Guest0], [Event1, Guest1]]] +room: [[], [[Event0, Room0], [Event0, Room1], [Event1, Room0], [Event1, Room1]]] +card: [[], [[Event0, Card0], [Event0, Card1], [Event1, Card0], [Event1, Card1]]] + + +ord[next, Time, first, last] +function[pre: Event -> one Time] +function[post: Event -> one Time] + +all t: Time - last | one {e: Event | e.pre = t && e.post = t.next} + +function[k1: Card -> one Key] +function[k2: Card -> one Key] + +key in (Room -> Key -> Time) +prev in (Room -> Key -> Time) +occ in (Room -> Guest -> Time) + +all r: Room, t: Time | one r . key . t +all r: Room, t: Time | lone r . prev . t + +holds in Guest -> Card -> Time + +prev.first = key.first +key.first in Room -> Key +all k: Key | lone key.first.k +no holds.first +no occ.first +HotelEvent = Event +HotelEvent = (RoomCardEvent + Checkout) +no (RoomCardEvent & Checkout) + +function[guest: HotelEvent -> one Guest] + +RoomCardEvent in HotelEvent +RoomCardEvent = (Checkin + Enter) + +no (Checkin & Enter) + +function[room: RoomCardEvent -> one Room] +function[card: RoomCardEvent -> one Card] + +Checkin in RoomCardEvent +all c: Checkin | no c.room.occ.c.pre +all c: Checkin | c.card.k1 = c.room.prev.c.pre +all c: Checkin | (holds . (c . post)) = ((holds . (c . pre)) + ((c . guest) -> (c . card))) +all c: Checkin | (prev . (c . post)) = ((prev . (c . pre)) ++ ((c . room) -> ((c . card) . k2))) +all c: Checkin | (occ . (c . post)) = ((occ . (c . pre)) + ((c . room) -> (c . guest))) +all c: Checkin | (key . (c . pre)) = (key . (c . post)) + +Enter in RoomCardEvent +Enter = (NormalEnter + RecodeEnter) +no (NormalEnter & RecodeEnter) +all e: Enter | e.card in (((e . guest) . holds) . (e . pre)) + +NormalEnter in Enter && (all n: NormalEnter | ((n . card) . k2) = (((n . room) . key) . (n . pre))) +all n: NormalEnter | (prev . (n . pre)) = (prev . (n . post)) +all n: NormalEnter | (holds . (n . pre)) = (holds . (n . post)) +all n: NormalEnter | (occ . (n . pre)) = (occ . (n . post)) +all n: NormalEnter | (key . (n . pre)) = (key . (n . post)) + +RecodeEnter in Enter +all n: RecodeEnter | ((n . card) . k1) = (((n . room) . key) . (n . pre)) +all n: RecodeEnter | (key . (n . post)) = ((key . (n . pre)) ++ ((n . room) -> ((n . card) . k2))) +all n: RecodeEnter | (prev . (n . pre)) = (prev . (n . post)) +all n: RecodeEnter | (holds . (n . pre)) = (holds . (n . post)) +all n: RecodeEnter | (occ . (n . pre)) = (occ . (n . post)) + +Checkout in HotelEvent +all n: Checkout | some ((occ . (n . pre)) . (n . guest)) +all n: Checkout | (occ . (n . post)) = ((occ . (n . pre)) - (Room -> (n . guest))) +all n: Checkout | (prev . (n . pre)) = (prev . (n . post)) +all n: Checkout | (holds . (n . pre)) = (holds . (n . post)) +all n: Checkout | (key . (n . pre)) = (key . (n . post)) + +all e1: Checkin, e2: Checkin | !(e1 = e2) => !(((e1 . card) . k2) = ((e2 . card) . k2)) + +all e: Checkin | !(((e . card) . k2) in ((Room . key) . first)) + +all c: Checkin - (pre . last) | some e: Enter | (e . pre) = (c . post) && (e . room) = (c . room) && (e . guest) = (c . guest) + +!(all e: Enter | some ((e.room) . (occ.(e.pre))) => (e . guest) in ((e . room) . (occ . (e . pre)))) + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/KodKodTestFile.kodkod b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/KodKodTestFile.kodkod new file mode 100644 index 00000000..e65db0b4 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/KodKodTestFile.kodkod @@ -0,0 +1,12 @@ +{d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31, d32, d33, d34, d35, d36, d37, d38, d39, d40, d41, d42, d43, d44, d45, d46, d47, d48, d49, d50, d51, d52, d53, d54, d55, d56, d57, d58, d59, d60, d61, d62, d63, d64, d65, d66, d67, d68, d69, d70, d71, d72, d73, d74, d75, d76, d77, d78, d79, d80, d81, d82, d83, d84, d85, d86, d87, d88, d89, d90, d91, d92, d93, d94, d95, d96, d97, d98, d99, d100, d101, d102, d103, d104, d105, d106, d107, d108, d109, d110, d111, d112, d113, d114, d115, d116, d117, d118, d119, d120, d121, d122, d123, d124, d125, d126, d127, d128, d129, d130, d131, d132, d133, d134, d135, d136, d137, d138, d139, d140, d141, d142, d143, d144, d145, d146, d147, d148, d149, d150, d151, d152, d153, d154, d155, d156, d157, d158, d159, d160, d161, d162, d163, d164, d165, d166, d167, d168, d169, d170, d171, d172, d173, d174, d175, d176, d177, d178, d179, d180, d181, d182, d183, d184, d185, d186, d187, d188, d189, d190, d191, d192, d193, d194, d195, d196, d197, d198, d199, d200, d201, d202, d203, d204, d205, d206, d207, d208, d209, d210, d211, d212, d213, d214, d215, d216, d217, d218, d219, d220, d221, d222, d223, d224, d225, d226, d227, d228, d229, d230, d231, d232, d233, d234, d235, d236, d237, d238, d239, d240, d241, d242, d243, d244, d245, d246, d247, d248, d249, d250, d251, d252, d253, d254, d255, d256, d257, d258, d259, d260, d261, d262, d263, d264, d265, d266, d267, d268, d269, d270, d271, d272, d273, d274, d275, d276, d277, d278, d279, d280, d281, d282, d283, d284, d285, d286, d287, d288, d289, d290, d291, d292, d293, d294, d295, d296, d297, d298, d299, d300, d301, d302, d303, d304, d305, d306, d307, d308, d309, d310, d311, d312, d313, d314, d315, d316, d317, d318, d319, d320, d321, d322, d323, d324, d325, d326, d327, d328, d329, d330, d331, d332, d333, d334, d335, d336, d337, d338, d339, d340, d341, d342, d343, d344, d345, d346, d347, d348, d349, d350, d351, d352, d353, d354, d355, d356, d357, d358, d359, d360, d361, d362, d363, d364, d365, d366, d367, d368, d369, d370, d371, d372, d373, d374, d375, d376, d377, d378, d379, d380, d381, d382, d383, d384, d385, d386, d387, d388, d389, d390, d391, d392, d393, d394, d395, d396, d397, d398, d399, d400, d401, d402, d403, d404, d405, d406, d407, d408, d409, d410, d411, d412, d413, d414, d415, d416, d417, d418, d419, d420, d421, d422, d423, d424, d425, d426, d427, d428, d429, d430, d431, d432, d433, d434, d435, d436, d437, d438, d439, d440, d441, d442, d443, d444, d445, d446, d447, d448, d449, d450, d451, d452, d453, d454, d455, d456, d457, d458, d459, d460, d461, d462, d463, d464, d465, d466, d467, d468, d469, d470, d471, d472, d473, d474, d475, d476, d477, d478, d479, d480, d481, d482, d483, d484, d485, d486, d487, d488, d489, d490, d491, d492, d493, d494, d495, d496, d497, d498, d499, d500, d501, d502, d503, d504, d505, d506, d507, d508, d509, d510, d511, d512, d513, d514, d515, d516, d517, d518, d519, d520, d521, d522, d523, d524, d525, d526, d527, d528, d529, d530, d531, d532, d533, d534, d535, d536, d537, d538, d539, d540, d541, d542, d543, d544, d545, d546, d547, d548, d549, d550, d551, d552, d553, d554, d555, d556, d557, d558, d559, d560, d561, d562, d563, d564, d565, d566, d567, d568, d569, d570, d571, d572, d573, d574, d575, d576, d577, d578, d579, d580, d581, d582, d583, d584, d585, d586, d587, d588, d589, d590, d591, d592, d593, d594, d595, d596, d597, d598, d599, d600, d601, d602, d603, d604, d605, d606, d607, d608, d609, d610, d611, d612, d613, d614, d615, d616, d617, d618, d619, d620, d621, d622, d623, d624, d625, d626, d627, d628, d629, d630, d631, d632, d633, d634, d635, d636, d637, d638, d639, d640, d641, d642, d643, d644, d645, d646, d647, d648, d649, d650, d651, d652, d653, d654, d655, d656, d657, d658, d659, d660, d661, d662, d663, d664, d665, d666, d667, d668, d669, d670, d671, d672, d673, d674, d675, d676, d677, d678, d679, d680, d681, d682, d683, d684, d685, d686, d687, d688, d689, d690, d691, d692, d693, d694, d695, d696, d697, d698, d699, d700, d701, d702, d703, d704, d705, d706, d707, d708, d709, d710, d711, d712, d713, d714, d715, d716, d717, d718, d719, d720, d721, d722, d723, d724, d725, d726, d727, d728, d729, d730, d731, d732, d733, d734, d735, d736, d737, d738, d739, d740, d741, d742, d743, d744, d745, d746, d747, d748, d749, d750, d751, d752, d753, d754, d755, d756, d757, d758, d759, d760, d761, d762, d763, d764, d765, d766, d767, d768, d769, d770, d771, d772, d773, d774, d775, d776, d777, d778, d779, d780, d781, d782, d783, d784, d785, d786, d787, d788, d789, d790, d791, d792, d793, d794, d795, d796, d797, d798, d799, d800, d801, d802, d803, d804, d805, d806, d807, d808, d809, d810, d811, d812, d813, d814, d815, d816, d817, d818, d819, d820, d821, d822, d823, d824, d825, d826, d827, d828, d829, d830, d831, d832, d833, d834, d835, d836, d837, d838, d839, d840, d841, d842, d843, d844, d845, d846, d847, d848, d849, d850, d851, d852, d853, d854, d855, d856, d857, d858, d859, d860, d861, d862, d863, d864, d865, d866, d867, d868, d869, d870, d871, d872, d873, d874, d875, d876, d877, d878, d879, d880, d881, d882, d883, d884, d885, d886, d887, d888, d889, d890, d891, d892, d893, d894, d895, d896, d897, d898, d899, d900, d901, d902, d903, d904, d905, d906, d907, d908, d909, d910, d911, d912, d913, d914, d915, d916, d917, d918, d919, d920, d921, d922, d923, d924, d925, d926, d927, d928, d929, d930, d931, d932, d933, d934, d935, d936, d937, d938, d939, d940, d941, d942, d943, d944, d945, d946, d947, d948, d949, d950, d951, d952, d953, d954, d955, d956, d957, d958, d959, d960, d961, d962, d963, d964, d965, d966, d967, d968, d969, d970, d971, d972, d973, d974, d975, d976, d977, d978, d979, d980, d981, d982, d983, d984, d985, d986, d987, d988, d989, d990, d991, d992, d993, d994, d995, d996, d997, d998, d999, d1000, d1001, d1002, d1003, d1004, d1005, d1006, d1007, d1008, d1009, d1010, d1011, d1012, d1013, d1014, d1015, d1016, d1017, d1018, d1019, d1020, d1021, d1022, d1023, d1024, d1025, d1026, d1027, d1028, d1029, d1030, d1031, d1032, d1033, d1034, d1035, d1036, d1037, d1038, d1039, d1040, d1041, d1042, d1043, d1044, d1045, d1046, d1047, d1048, d1049, d1050, d1051, d1052, d1053, d1054, d1055, d1056, d1057, d1058, d1059, d1060, d1061, d1062, d1063, d1064, d1065, d1066, d1067, d1068, d1069, d1070, d1071, d1072, d1073, d1074, d1075, d1076, d1077, d1078, d1079, d1080, d1081, d1082, d1083, d1084, d1085, d1086, d1087, d1088, d1089, d1090, d1091, d1092, d1093, d1094, d1095, d1096, d1097, d1098, d1099, d1100, d1101, d1102, d1103, d1104, d1105, d1106, d1107, d1108, d1109, d1110, d1111, d1112, d1113, d1114, d1115, d1116, d1117, d1118, d1119, d1120, d1121, d1122, d1123, d1124, d1125, d1126, d1127, d1128, d1129, d1130, d1131, d1132, d1133, d1134, d1135, d1136, d1137, d1138, d1139, d1140, d1141, d1142, d1143, d1144, d1145, d1146, d1147, d1148, d1149, d1150, d1151, d1152, d1153, d1154, d1155, d1156, d1157, d1158, d1159, d1160, d1161, d1162, d1163, d1164, d1165, d1166, d1167, d1168, d1169, d1170, d1171, d1172, d1173, d1174, d1175, d1176, d1177, d1178, d1179, d1180, d1181, d1182, d1183, d1184, d1185, d1186, d1187, d1188, d1189, d1190, d1191, d1192, d1193, d1194, d1195, d1196, d1197, d1198, d1199, d1200, d1201, d1202, d1203, d1204, d1205, d1206, d1207, d1208, d1209, d1210, d1211, d1212, d1213, d1214, d1215, d1216, d1217, d1218, d1219, d1220, d1221, d1222, d1223, d1224, d1225, d1226, d1227, d1228, d1229, d1230, d1231, d1232, d1233, d1234, d1235, d1236, d1237, d1238, d1239, d1240, d1241, d1242, d1243, d1244, d1245, d1246, d1247, d1248, d1249, d1250, d1251, d1252, d1253, d1254, d1255, d1256, d1257, d1258, d1259, d1260, d1261, d1262, d1263, d1264, d1265, d1266, d1267, d1268, d1269, d1270, d1271, d1272, d1273, d1274, d1275, d1276, d1277, d1278, d1279, d1280, d1281, d1282, d1283, d1284, d1285, d1286, d1287, d1288, d1289, d1290, d1291, d1292, d1293, d1294, d1295, d1296, d1297, d1298, d1299, d1300, d1301, d1302, d1303, d1304, d1305, d1306, d1307, d1308, d1309, d1310, d1311, d1312, d1313, d1314, d1315, d1316, d1317, d1318, d1319, d1320, d1321, d1322, d1323, d1324, d1325, d1326, d1327, d1328, d1329, d1330, d1331, d1332, d1333, d1334, d1335, d1336, d1337, d1338, d1339, d1340, d1341, d1342, d1343, d1344, d1345, d1346, d1347, d1348, d1349, d1350, d1351, d1352, d1353, d1354, d1355, d1356, d1357, d1358, d1359, d1360, d1361, d1362, d1363, d1364, d1365, d1366, d1367, d1368, d1369, d1370, d1371, d1372, d1373, d1374, d1375, d1376, d1377, d1378, d1379, d1380, d1381, d1382, d1383, d1384, d1385, d1386, d1387, d1388, d1389, d1390, d1391, d1392, d1393, d1394, d1395, d1396, d1397, d1398, d1399, d1400, d1401, d1402, d1403, d1404, d1405, d1406, d1407, d1408, d1409, d1410, d1411, d1412, d1413, d1414, d1415, d1416, d1417, d1418, d1419, d1420, d1421, d1422, d1423, d1424, d1425, d1426, d1427, d1428, d1429, d1430, d1431, d1432, d1433, d1434, d1435, d1436, d1437, d1438, d1439, d1440, d1441, d1442, d1443, d1444, d1445, d1446, d1447, d1448, d1449, d1450, d1451, d1452, d1453, d1454, d1455, d1456, d1457, d1458, d1459, d1460, d1461, d1462, d1463, d1464, d1465, d1466, d1467, d1468, d1469, d1470, d1471, d1472, d1473, d1474, d1475, d1476, d1477, d1478, d1479, d1480, d1481, d1482, d1483, d1484, d1485, d1486, d1487, d1488, d1489, d1490, d1491, d1492, d1493, d1494, d1495, d1496, d1497, d1498, d1499, d1500, d1501, d1502, d1503, d1504, d1505, d1506, d1507, d1508, d1509, d1510, d1511, d1512, d1513, d1514, d1515, d1516, d1517, d1518, d1519, d1520, d1521, d1522, d1523, d1524, d1525, d1526, d1527, d1528, d1529, d1530, d1531, d1532, d1533, d1534, d1535, d1536, d1537, d1538, d1539, d1540, d1541, d1542, d1543, d1544, d1545, d1546, d1547, d1548, d1549, d1550, d1551, d1552, d1553, d1554, d1555, d1556, d1557, d1558, d1559, d1560, d1561, d1562, d1563, d1564, d1565, d1566, d1567, d1568, d1569, d1570, d1571, d1572, d1573, d1574, d1575, d1576, d1577, d1578, d1579, d1580, d1581, d1582, d1583, d1584, d1585, d1586, d1587, d1588, d1589, d1590, d1591, d1592, d1593, d1594, d1595, d1596, d1597, d1598, d1599, d1600, d1601, d1602, d1603, d1604, d1605, d1606, d1607, d1608, d1609, d1610, d1611, d1612, d1613, d1614, d1615, d1616, d1617, d1618, d1619, d1620, d1621, d1622, d1623, d1624, d1625, d1626, d1627, d1628, d1629, d1630, d1631, d1632, d1633, d1634, d1635, d1636, d1637, d1638, d1639, d1640, d1641, d1642, d1643, d1644, d1645, d1646, d1647, d1648, d1649, d1650, d1651, d1652, d1653, d1654, d1655, d1656, d1657, d1658, d1659, d1660, d1661, d1662, d1663, d1664, d1665, d1666, d1667, d1668, d1669, d1670, d1671, d1672, d1673, d1674, d1675, d1676, d1677, d1678, d1679, d1680, d1681, d1682, d1683, d1684, d1685, d1686, d1687, d1688, d1689, d1690, d1691, d1692, d1693, d1694, d1695, d1696, d1697, d1698, d1699, d1700, d1701, d1702, d1703, d1704, d1705, d1706, d1707, d1708, d1709, d1710, d1711, d1712, d1713, d1714, d1715, d1716, d1717, d1718, d1719, d1720, d1721, d1722, d1723, d1724, d1725, d1726, d1727, d1728, d1729, d1730, d1731, d1732, d1733, d1734, d1735, d1736, d1737, d1738, d1739, d1740, d1741, d1742, d1743, d1744, d1745, d1746, d1747, d1748, d1749, d1750, d1751, d1752, d1753, d1754, d1755, d1756, d1757, d1758, d1759, d1760, d1761, d1762, d1763, d1764, d1765, d1766, d1767, d1768, d1769, d1770, d1771, d1772, d1773, d1774, d1775, d1776, d1777, d1778, d1779, d1780, d1781, d1782, d1783, d1784, d1785, d1786, d1787, d1788, d1789, d1790, d1791, d1792, d1793, d1794, d1795, d1796, d1797, d1798, d1799, d1800, d1801, d1802, d1803, d1804, d1805, d1806, d1807, d1808, d1809, d1810, d1811, d1812, d1813, d1814, d1815, d1816, d1817, d1818, d1819, d1820, d1821, d1822, d1823, d1824, d1825, d1826, d1827, d1828, d1829, d1830, d1831, d1832, d1833, d1834, d1835, d1836, d1837, d1838, d1839, d1840, d1841, d1842, d1843, d1844, d1845, d1846, d1847, d1848, d1849, d1850, d1851, d1852, d1853, d1854, d1855, d1856, d1857, d1858, d1859, d1860, d1861, d1862, d1863, d1864, d1865, d1866, d1867, d1868, d1869, d1870, d1871, d1872, d1873, d1874, d1875, d1876, d1877, d1878, d1879, d1880, d1881, d1882, d1883, d1884, d1885, d1886, d1887, d1888, d1889, d1890, d1891, d1892, d1893, d1894, d1895, d1896, d1897, d1898, d1899, d1900, d1901, d1902, d1903, d1904, d1905, d1906, d1907, d1908, d1909, d1910, d1911, d1912, d1913, d1914, d1915, d1916, d1917, d1918, d1919, d1920, d1921, d1922, d1923, d1924, d1925, d1926, d1927, d1928, d1929, d1930, d1931, d1932, d1933, d1934, d1935, d1936, d1937, d1938, d1939, d1940, d1941, d1942, d1943, d1944, d1945, d1946, d1947, d1948, d1949, d1950, d1951, d1952, d1953, d1954, d1955, d1956, d1957, d1958, d1959, d1960, d1961, d1962, d1963, d1964, d1965, d1966, d1967, d1968, d1969, d1970, d1971, d1972, d1973, d1974, d1975, d1976, d1977, d1978, d1979, d1980, d1981, d1982, d1983, d1984, d1985, d1986, d1987, d1988, d1989, d1990, d1991, d1992, d1993, d1994, d1995, d1996, d1997, d1998, d1999, d2000, d2001, d2002, d2003, d2004, d2005, d2006, d2007, d2008, d2009, d2010, d2011, d2012, d2013, d2014, d2015, d2016, d2017, d2018, d2019, d2020, d2021, d2022, d2023, d2024, d2025, d2026, d2027, d2028, d2029, d2030, d2031, d2032, d2033, d2034, d2035, d2036, d2037, d2038, d2039, d2040, d2041, d2042, d2043, d2044, d2045, d2046, d2047, d2048, d2049, d2050, d2051, d2052, d2053, d2054, d2055, d2056, d2057, d2058, d2059, d2060, d2061, d2062, d2063, d2064, d2065, d2066, d2067, d2068, d2069, d2070, d2071, d2072, d2073, d2074, d2075, d2076, d2077, d2078, d2079, d2080, d2081, d2082, d2083, d2084, d2085, d2086, d2087, d2088, d2089, d2090, d2091, d2092, d2093, d2094, d2095, d2096, d2097, d2098, d2099, d2100, d2101, d2102, d2103, d2104, d2105, d2106, d2107, d2108, d2109, d2110, d2111, d2112, d2113, d2114, d2115, d2116, d2117, d2118, d2119, d2120, d2121, d2122, d2123, d2124, d2125, d2126, d2127, d2128, d2129, d2130, d2131, d2132, d2133, d2134, d2135, d2136, d2137, d2138, d2139, d2140, d2141, d2142, d2143, d2144, d2145, d2146, d2147, d2148, d2149, d2150, d2151, d2152, d2153, d2154, d2155, d2156, d2157, d2158, d2159, d2160, d2161, d2162, d2163, d2164, d2165, d2166, d2167, d2168, d2169, d2170, d2171, d2172, d2173, d2174, d2175, d2176, d2177, d2178, d2179, d2180, d2181, d2182, d2183, d2184, d2185, d2186, d2187, d2188, d2189, d2190, d2191, d2192, d2193, d2194, d2195, d2196, d2197, d2198, d2199, d2200, d2201, d2202, d2203, d2204, d2205, d2206, d2207, d2208, d2209, d2210, d2211, d2212, d2213, d2214, d2215, d2216, d2217, d2218, d2219, d2220, d2221, d2222, d2223, d2224, d2225, d2226, d2227, d2228, d2229, d2230, d2231, d2232, d2233, d2234, d2235, d2236, d2237, d2238, d2239, d2240, d2241, d2242, d2243, d2244, d2245, d2246, d2247, d2248, d2249, d2250, d2251, d2252, d2253, d2254, d2255, d2256, d2257, d2258, d2259, d2260, d2261, d2262, d2263, d2264, d2265, d2266, d2267, d2268, d2269, d2270, d2271, d2272, d2273, d2274, d2275, d2276, d2277, d2278, d2279, d2280, d2281, d2282, d2283, d2284, d2285, d2286, d2287, d2288, d2289, d2290, d2291, d2292, d2293, d2294, d2295, d2296, d2297, d2298, d2299, d2300, d2301, d2302, d2303, d2304, d2305, d2306, d2307, d2308, d2309, d2310, d2311, d2312, d2313, d2314, d2315, d2316, d2317, d2318, d2319, d2320, d2321, d2322, d2323, d2324, d2325, d2326, d2327, d2328, d2329, d2330, d2331, d2332, d2333, d2334, d2335, d2336, d2337, d2338, d2339, d2340, d2341, d2342, d2343, d2344, d2345, d2346, d2347, d2348, d2349, d2350, d2351, d2352, d2353, d2354, d2355, d2356, d2357, d2358, d2359, d2360, d2361, d2362, d2363, d2364, d2365, d2366, d2367, d2368, d2369, d2370, d2371, d2372, d2373, d2374, d2375, d2376, d2377, d2378, d2379, d2380, d2381, d2382, d2383, d2384, d2385, d2386, d2387, d2388, d2389, d2390, d2391, d2392, d2393, d2394, d2395, d2396, d2397, d2398, d2399, d2400, d2401, d2402, d2403, d2404, d2405, d2406, d2407, d2408, d2409, d2410, d2411, d2412, d2413, d2414, d2415, d2416, d2417, d2418, d2419, d2420, d2421, d2422, d2423, d2424, d2425, d2426, d2427, d2428, d2429, d2430, d2431, d2432, d2433, d2434, d2435, d2436, d2437, d2438, d2439, d2440, d2441, d2442, d2443, d2444, d2445, d2446, d2447, d2448, d2449, d2450, d2451, d2452, d2453, d2454, d2455, d2456, d2457, d2458, d2459, d2460, d2461, d2462, d2463, d2464, d2465, d2466, d2467, d2468, d2469, d2470, d2471, d2472, d2473, d2474, d2475, d2476, d2477, d2478, d2479, d2480, d2481, d2482, d2483, d2484, d2485, d2486, d2487, d2488, d2489, d2490, d2491, d2492, d2493, d2494, d2495, d2496, d2497, d2498, d2499, d2500, d2501, d2502, d2503, d2504, d2505, d2506, d2507, d2508, d2509, d2510, d2511, d2512, d2513, d2514, d2515, d2516, d2517, d2518, d2519, d2520, d2521, d2522, d2523, d2524, d2525, d2526, d2527, d2528, d2529, d2530, d2531, d2532, d2533, d2534, d2535, d2536, d2537, d2538, d2539, d2540, d2541, d2542, d2543, d2544, d2545, d2546, d2547, d2548, d2549, d2550, d2551, d2552, d2553, d2554, d2555, d2556, d2557, d2558, d2559, d2560, d2561, d2562, d2563, d2564, d2565, d2566, d2567, d2568, d2569, d2570, d2571, d2572, d2573, d2574, d2575, d2576, d2577, d2578, d2579, d2580, d2581, d2582, d2583, d2584, d2585, d2586, d2587, d2588, d2589, d2590, d2591, d2592, d2593, d2594, d2595, d2596, d2597, d2598, d2599, d2600, d2601, d2602, d2603, d2604, d2605, d2606, d2607, d2608, d2609, d2610, d2611, d2612, d2613, d2614, d2615, d2616, d2617, d2618, d2619, d2620, d2621, d2622, d2623, d2624, d2625, d2626, d2627, d2628, d2629, d2630, d2631, d2632, d2633, d2634, d2635, d2636, d2637, d2638, d2639, d2640, d2641, d2642, d2643, d2644, d2645, d2646, d2647, d2648, d2649, d2650, d2651, d2652, d2653, d2654, d2655, d2656, d2657, d2658, d2659, d2660, d2661, d2662, d2663, d2664, d2665, d2666, d2667, d2668, d2669, d2670, d2671, d2672, d2673, d2674, d2675, d2676, d2677, d2678, d2679, d2680, d2681, d2682, d2683, d2684, d2685, d2686, d2687, d2688, d2689, d2690, d2691, d2692, d2693, d2694, d2695, d2696, d2697, d2698, d2699, d2700, d2701, d2702, d2703, d2704, d2705, d2706, d2707, d2708, d2709, d2710, d2711, d2712, d2713, d2714, d2715, d2716, d2717, d2718, d2719, d2720, d2721, d2722, d2723, d2724, d2725, d2726, d2727, d2728, d2729, d2730, d2731, d2732, d2733, d2734, d2735, d2736, d2737, d2738, d2739, d2740, d2741, d2742, d2743, d2744, d2745, d2746, d2747, d2748, d2749, d2750, d2751, d2752, d2753, d2754, d2755, d2756, d2757, d2758, d2759, d2760, d2761, d2762, d2763, d2764, d2765, d2766, d2767, d2768, d2769, d2770, d2771, d2772, d2773, d2774, d2775, d2776, d2777, d2778, d2779, d2780, d2781, d2782, d2783, d2784, d2785, d2786, d2787, d2788, d2789, d2790, d2791, d2792, d2793, d2794, d2795, d2796, d2797, d2798, d2799, d2800, d2801, d2802, d2803, d2804, d2805, d2806, d2807, d2808, d2809, d2810, d2811, d2812, d2813, d2814, d2815, d2816, d2817, d2818, d2819, d2820, d2821, d2822, d2823, d2824, d2825, d2826, d2827, d2828, d2829, d2830, d2831, d2832, d2833, d2834, d2835, d2836, d2837, d2838, d2839, d2840, d2841, d2842, d2843, d2844, d2845, d2846, d2847, d2848, d2849, d2850, d2851, d2852, d2853, d2854, d2855, d2856, d2857, d2858, d2859, d2860, d2861, d2862, d2863, d2864, d2865, d2866, d2867, d2868, d2869, d2870, d2871, d2872, d2873, d2874, d2875, d2876, d2877, d2878, d2879, d2880, d2881, d2882, d2883, d2884, d2885, d2886, d2887, d2888, d2889, d2890, d2891, d2892, d2893, d2894, d2895, d2896, d2897, d2898, d2899, d2900, d2901, d2902, d2903, d2904, d2905, d2906, d2907, d2908, d2909, d2910, d2911, d2912, d2913, d2914, d2915, d2916, d2917, d2918, d2919, d2920, d2921, d2922, d2923, d2924, d2925, d2926, d2927, d2928, d2929, d2930, d2931, d2932, d2933, d2934, d2935, d2936, d2937, d2938, d2939, d2940, d2941, d2942, d2943, d2944, d2945, d2946, d2947, d2948, d2949, d2950, d2951, d2952, d2953, d2954, d2955, d2956, d2957, d2958, d2959, d2960, d2961, d2962, d2963, d2964, d2965, d2966, d2967, d2968, d2969, d2970, d2971, d2972, d2973, d2974, d2975, d2976, d2977, d2978, d2979, d2980, d2981, d2982, d2983, d2984, d2985, d2986, d2987, d2988, d2989, d2990, d2991, d2992, d2993, d2994, d2995, d2996, d2997, d2998, d2999, d3000, d3001, d3002, d3003, d3004, d3005, d3006, d3007, d3008, d3009, d3010, d3011, d3012, d3013, d3014, d3015, d3016, d3017, d3018, d3019, d3020, d3021, d3022, d3023, d3024, d3025, d3026, d3027, d3028, d3029, d3030, d3031, d3032, d3033, d3034, d3035, d3036, d3037, d3038, d3039, d3040, d3041, d3042, d3043, d3044, d3045, d3046, d3047, d3048, d3049, d3050, d3051, d3052, d3053, d3054, d3055, d3056, d3057, d3058, d3059, d3060, d3061, d3062, d3063, d3064, d3065, d3066, d3067, d3068, d3069, d3070, d3071, d3072, d3073, d3074, d3075, d3076, d3077, d3078, d3079, d3080, d3081, d3082, d3083, d3084, d3085, d3086, d3087, d3088, d3089, d3090, d3091, d3092, d3093, d3094, d3095, d3096, d3097, d3098, d3099, d3100, d3101, d3102, d3103, d3104, d3105, d3106, d3107, d3108, d3109, d3110, d3111, d3112, d3113, d3114, d3115, d3116, d3117, d3118, d3119, d3120, d3121, d3122, d3123, d3124, d3125, d3126, d3127, d3128, d3129, d3130, d3131, d3132, d3133, d3134, d3135, d3136, d3137, d3138, d3139, d3140, d3141, d3142, d3143, d3144, d3145, d3146, d3147, d3148, d3149, d3150, d3151, d3152, d3153, d3154, d3155, d3156, d3157, d3158, d3159, d3160, d3161, d3162, d3163, d3164, d3165, d3166, d3167, d3168, d3169, d3170, d3171, d3172, d3173, d3174, d3175, d3176, d3177, d3178, d3179, d3180, d3181, d3182, d3183, d3184, d3185, d3186, d3187, d3188, d3189, d3190, d3191, d3192, d3193, d3194, d3195, d3196, d3197, d3198, d3199, d3200, d3201, d3202, d3203, d3204, d3205, d3206, d3207, d3208, d3209, d3210, d3211, d3212, d3213, d3214, d3215, d3216, d3217, d3218, d3219, d3220, d3221, d3222, d3223, d3224, d3225, d3226, d3227, d3228, d3229, d3230, d3231, d3232, d3233, d3234, d3235, d3236, d3237, d3238, d3239, d3240, d3241, d3242, d3243, d3244, d3245, d3246, d3247, d3248, d3249, d3250, d3251, d3252, d3253, d3254, d3255, d3256, d3257, d3258, d3259, d3260, d3261, d3262, d3263, d3264, d3265, d3266, d3267, d3268, d3269, d3270, d3271, d3272, d3273, d3274, d3275, d3276, d3277, d3278, d3279, d3280, d3281, d3282, d3283, d3284, d3285, d3286, d3287, d3288, d3289, d3290, d3291, d3292, d3293, d3294, d3295, d3296, d3297, d3298, d3299, d3300, d3301, d3302, d3303, d3304, d3305, d3306, d3307, d3308, d3309, d3310, d3311, d3312, d3313, d3314, d3315, d3316, d3317, d3318, d3319, d3320, d3321, d3322, d3323, d3324, d3325, d3326, d3327, d3328, d3329, d3330, d3331, d3332, d3333, d3334, d3335, d3336, d3337, d3338, d3339, d3340, d3341, d3342, d3343, d3344, d3345, d3346, d3347, d3348, d3349, d3350, d3351, d3352, d3353, d3354, d3355, d3356, d3357, d3358, d3359, d3360, d3361, d3362, d3363, d3364, d3365, d3366, d3367, d3368, d3369, d3370, d3371, d3372, d3373, d3374, d3375, d3376, d3377, d3378, d3379, d3380, d3381, d3382, d3383, d3384, d3385, d3386, d3387, d3388, d3389, d3390, d3391, d3392, d3393, d3394, d3395, d3396, d3397, d3398, d3399, d3400, d3401, d3402, d3403, d3404, d3405, d3406, d3407, d3408, d3409, d3410, d3411, d3412, d3413, d3414, d3415, d3416, d3417, d3418, d3419, d3420, d3421, d3422, d3423, d3424, d3425, d3426, d3427, d3428, d3429, d3430, d3431, d3432, d3433, d3434, d3435, d3436, d3437, d3438, d3439, d3440, d3441, d3442, d3443, d3444, d3445, d3446, d3447, d3448, d3449, d3450, d3451, d3452, d3453, d3454, d3455, d3456, d3457, d3458, d3459, d3460, d3461, d3462, d3463, d3464, d3465, d3466, d3467, d3468, d3469, d3470, d3471, d3472, d3473, d3474, d3475, d3476, d3477, d3478, d3479, d3480, d3481, d3482, d3483, d3484, d3485, d3486, d3487, d3488, d3489, d3490, d3491, d3492, d3493, d3494, d3495, d3496, d3497, d3498, d3499, d3500, d3501, d3502, d3503, d3504, d3505, d3506, d3507, d3508, d3509, d3510, d3511, d3512, d3513, d3514, d3515, d3516, d3517, d3518, d3519, d3520, d3521, d3522, d3523, d3524, d3525, d3526, d3527, d3528, d3529, d3530, d3531, d3532, d3533, d3534, d3535, d3536, d3537, d3538, d3539, d3540, d3541, d3542, d3543, d3544, d3545, d3546, d3547, d3548, d3549, d3550, d3551, d3552, d3553, d3554, d3555, d3556, d3557, d3558, d3559, d3560, d3561, d3562, d3563, d3564, d3565, d3566, d3567, d3568, d3569, d3570, d3571, d3572, d3573, d3574, d3575, d3576, d3577, d3578, d3579, d3580, d3581, d3582, d3583, d3584, d3585, d3586, d3587, d3588, d3589, d3590, d3591, d3592, d3593, d3594, d3595, d3596, d3597, d3598, d3599, d3600, d3601, d3602, d3603, d3604, d3605, d3606, d3607, d3608, d3609, d3610, d3611, d3612, d3613, d3614, d3615, d3616, d3617, d3618, d3619, d3620, d3621, d3622, d3623, d3624, d3625, d3626, d3627, d3628, d3629, d3630, d3631, d3632, d3633, d3634, d3635, d3636, d3637, d3638, d3639, d3640, d3641, d3642, d3643, d3644, d3645, d3646, d3647, d3648, d3649, d3650, d3651, d3652, d3653, d3654, d3655, d3656, d3657, d3658, d3659, d3660, d3661, d3662, d3663, d3664, d3665, d3666, d3667, d3668, d3669, d3670, d3671, d3672, d3673, d3674, d3675, d3676, d3677, d3678, d3679, d3680, d3681, d3682, d3683, d3684, d3685, d3686, d3687, d3688, d3689, d3690, d3691, d3692, d3693, d3694, d3695, d3696, d3697, d3698, d3699, d3700, d3701, d3702, d3703, d3704, d3705, d3706, d3707, d3708, d3709, d3710, d3711, d3712, d3713, d3714, d3715, d3716, d3717, d3718, d3719, d3720, d3721, d3722, d3723, d3724, d3725, d3726, d3727, d3728, d3729, d3730, d3731, d3732, d3733, d3734, d3735, d3736, d3737, d3738, d3739, d3740, d3741, d3742, d3743, d3744, d3745, d3746, d3747, d3748, d3749, d3750, d3751, d3752, d3753, d3754, d3755, d3756, d3757, d3758, d3759, d3760, d3761, d3762, d3763, d3764, d3765, d3766, d3767, d3768, d3769, d3770, d3771, d3772, d3773, d3774, d3775, d3776, d3777, d3778, d3779, d3780, d3781, d3782, d3783, d3784, d3785, d3786, d3787, d3788, d3789, d3790, d3791, d3792, d3793, d3794, d3795, d3796, d3797, d3798, d3799, d3800, d3801, d3802, d3803, d3804, d3805, d3806, d3807, d3808, d3809, d3810, d3811, d3812, d3813, d3814, d3815, d3816, d3817, d3818, d3819, d3820, d3821, d3822, d3823, d3824, d3825, d3826, d3827, d3828, d3829, d3830, d3831, d3832, d3833, d3834, d3835, d3836, d3837, d3838, d3839, d3840, d3841, d3842, d3843, d3844, d3845, d3846, d3847, d3848, d3849, d3850, d3851, d3852, d3853, d3854, d3855, d3856, d3857, d3858, d3859, d3860, d3861, d3862, d3863, d3864, d3865, d3866, d3867, d3868, d3869, d3870, d3871, d3872, d3873, d3874, d3875, d3876, d3877, d3878, d3879, d3880, d3881, d3882, d3883, d3884, d3885, d3886, d3887, d3888, d3889, d3890, d3891, d3892, d3893, d3894, d3895, d3896, d3897, d3898, d3899, d3900, d3901, d3902, d3903, d3904, d3905, d3906, d3907, d3908, d3909, d3910, d3911, d3912, d3913, d3914, d3915, d3916, d3917, d3918, d3919, d3920, d3921, d3922, d3923, d3924, d3925, d3926, d3927, d3928, d3929, d3930, d3931, d3932, d3933, d3934, d3935, d3936, d3937, d3938, d3939, d3940, d3941, d3942, d3943, d3944, d3945, d3946, d3947, d3948, d3949, d3950, d3951, d3952, d3953, d3954, d3955, d3956, d3957, d3958, d3959, d3960, d3961, d3962, d3963, d3964, d3965, d3966, d3967, d3968, d3969, d3970, d3971, d3972, d3973, d3974, d3975, d3976, d3977, d3978, d3979, d3980, d3981, d3982, d3983, d3984, d3985, d3986, d3987, d3988, d3989, d3990, d3991, d3992, d3993, d3994, d3995, d3996, d3997, d3998, d3999, d4000, d4001, d4002, d4003, d4004, d4005, d4006, d4007, d4008, d4009, d4010, d4011, d4012, d4013, d4014, d4015, d4016, d4017, d4018, d4019, d4020, d4021, d4022, d4023, d4024, d4025, d4026, d4027, d4028, d4029, d4030, d4031, d4032, d4033, d4034, d4035, d4036, d4037, d4038, d4039, d4040, d4041, d4042, d4043, d4044, d4045, d4046, d4047, d4048, d4049, d4050, d4051, d4052, d4053, d4054, d4055, d4056, d4057, d4058, d4059, d4060, d4061, d4062, d4063, d4064, d4065, d4066, d4067, d4068, d4069, d4070, d4071, d4072, d4073, d4074, d4075, d4076, d4077, d4078, d4079, d4080, d4081, d4082, d4083, d4084, d4085, d4086, d4087, d4088, d4089, d4090, d4091, d4092, d4093, d4094, d4095, d4096, d4097, d4098, d4099, d4100, d4101, d4102, d4103, d4104, d4105, d4106, d4107, d4108, d4109, d4110, d4111, d4112, d4113, d4114, d4115, d4116, d4117, d4118, d4119, d4120, d4121, d4122, d4123, d4124, d4125, d4126, d4127, d4128, d4129, d4130, d4131, d4132, d4133, d4134, d4135, d4136, d4137, d4138, d4139, d4140, d4141, d4142, d4143, d4144, d4145, d4146, d4147, d4148, d4149, d4150, d4151, d4152, d4153, d4154, d4155, d4156, d4157, d4158, d4159, d4160, d4161, d4162, d4163, d4164, d4165, d4166, d4167, d4168, d4169, d4170, d4171, d4172, d4173, d4174, d4175, d4176, d4177, d4178, d4179, d4180, d4181, d4182, d4183, d4184, d4185, d4186, d4187, d4188, d4189, d4190, d4191, d4192, d4193, d4194, d4195, d4196, d4197, d4198, d4199, d4200, d4201, d4202, d4203, d4204, d4205, d4206, d4207, d4208, d4209, d4210, d4211, d4212, d4213, d4214, d4215, d4216, d4217, d4218, d4219, d4220, d4221, d4222, d4223, d4224, d4225, d4226, d4227, d4228, d4229, d4230, d4231, d4232, d4233, d4234, d4235, d4236, d4237, d4238, d4239, d4240, d4241, d4242, d4243, d4244, d4245, d4246, d4247, d4248, d4249, d4250, d4251, d4252, d4253, d4254, d4255, d4256, d4257, d4258, d4259, d4260, d4261, d4262, d4263, d4264, d4265, d4266, d4267, d4268, d4269, d4270, d4271, d4272, d4273, d4274, d4275, d4276, d4277, d4278, d4279, d4280, d4281, d4282, d4283, d4284, d4285, d4286, d4287, d4288, d4289, d4290, d4291, d4292, d4293, d4294, d4295, d4296, d4297, d4298, d4299, d4300, d4301, d4302, d4303, d4304, d4305, d4306, d4307, d4308, d4309, d4310, d4311, d4312, d4313, d4314, d4315, d4316, d4317, d4318, d4319, d4320, d4321, d4322, d4323, d4324, d4325, d4326, d4327, d4328, d4329, d4330, d4331, d4332, d4333, d4334, d4335, d4336, d4337, d4338, d4339, d4340, d4341, d4342, d4343, d4344, d4345, d4346, d4347, d4348, d4349, d4350, d4351, d4352, d4353, d4354, d4355, d4356, d4357, d4358, d4359, d4360, d4361, d4362, d4363, d4364, d4365, d4366, d4367, d4368, d4369, d4370, d4371, d4372, d4373, d4374, d4375, d4376, d4377, d4378, d4379, d4380, d4381, d4382, d4383, d4384, d4385, d4386, d4387, d4388, d4389, d4390, d4391, d4392, d4393, d4394, d4395, d4396, d4397, d4398, d4399, d4400, d4401, d4402, d4403, d4404, d4405, d4406, d4407, d4408, d4409, d4410, d4411, d4412, d4413, d4414, d4415, d4416, d4417, d4418, d4419, d4420, d4421, d4422, d4423, d4424, d4425, d4426, d4427, d4428, d4429, d4430, d4431, d4432, d4433, d4434, d4435, d4436, d4437, d4438, d4439, d4440, d4441, d4442, d4443, d4444, d4445, d4446, d4447, d4448, d4449, d4450, d4451, d4452, d4453, d4454, d4455, d4456, d4457, d4458, d4459, d4460, d4461, d4462, d4463, d4464, d4465, d4466, d4467, d4468, d4469, d4470, d4471, d4472, d4473, d4474, d4475, d4476, d4477, d4478, d4479, d4480, d4481, d4482, d4483, d4484, d4485, d4486, d4487, d4488, d4489, d4490, d4491, d4492, d4493, d4494, d4495, d4496, d4497, d4498, d4499, d4500, d4501, d4502, d4503, d4504, d4505, d4506, d4507, d4508, d4509, d4510, d4511, d4512, d4513, d4514, d4515, d4516, d4517, d4518, d4519, d4520, d4521, d4522, d4523, d4524, d4525, d4526, d4527, d4528, d4529, d4530, d4531, d4532, d4533, d4534, d4535, d4536, d4537, d4538, d4539, d4540, d4541, d4542, d4543, d4544, d4545, d4546, d4547, d4548, d4549, d4550, d4551, d4552, d4553, d4554, d4555, d4556, d4557, d4558, d4559, d4560, d4561, d4562, d4563, d4564, d4565, d4566, d4567, d4568, d4569, d4570, d4571, d4572, d4573, d4574, d4575, d4576, d4577, d4578, d4579, d4580, d4581, d4582, d4583, d4584, d4585, d4586, d4587, d4588, d4589, d4590, d4591, d4592, d4593, d4594, d4595, d4596, d4597, d4598, d4599, d4600, d4601, d4602, d4603, d4604, d4605, d4606, d4607, d4608, d4609, d4610, d4611, d4612, d4613, d4614, d4615, d4616, d4617, d4618, d4619, d4620, d4621, d4622, d4623, d4624, d4625, d4626, d4627, d4628, d4629, d4630, d4631, d4632, d4633, d4634, d4635, d4636, d4637, d4638, d4639, d4640, d4641, d4642, d4643, d4644, d4645, d4646, d4647, d4648, d4649, d4650, d4651, d4652, d4653, d4654, d4655, d4656, d4657, d4658, d4659, d4660, d4661, d4662, d4663, d4664, d4665, d4666, d4667, d4668, d4669, d4670, d4671, d4672, d4673, d4674, d4675, d4676, d4677, d4678, d4679, d4680, d4681, d4682, d4683, d4684, d4685, d4686, d4687, d4688, d4689, d4690, d4691, d4692, d4693, d4694, d4695, d4696, d4697, d4698, d4699, d4700, d4701, d4702, d4703, d4704, d4705, d4706, d4707, d4708, d4709, d4710, d4711, d4712, d4713, d4714, d4715, d4716, d4717, d4718, d4719, d4720, d4721, d4722, d4723, d4724, d4725, d4726, d4727, d4728, d4729, d4730, d4731, d4732, d4733, d4734, d4735, d4736, d4737, d4738, d4739, d4740, d4741, d4742, d4743, d4744, d4745, d4746, d4747, d4748, d4749, d4750, d4751, d4752, d4753, d4754, d4755, d4756, d4757, d4758, d4759, d4760, d4761, d4762, d4763, d4764, d4765, d4766, d4767, d4768, d4769, d4770, d4771, d4772, d4773, d4774, d4775, d4776, d4777, d4778, d4779, d4780, d4781, d4782, d4783, d4784, d4785, d4786, d4787, d4788, d4789, d4790, d4791, d4792, d4793, d4794, d4795, d4796, d4797, d4798, d4799, d4800, d4801, d4802, d4803, d4804, d4805, d4806, d4807, d4808, d4809, d4810, d4811, d4812, d4813, d4814, d4815, d4816, d4817, d4818, d4819, d4820, d4821, d4822, d4823, d4824, d4825, d4826, d4827, d4828, d4829, d4830, d4831, d4832, d4833, d4834, d4835, d4836, d4837, d4838, d4839, d4840, d4841, d4842, d4843, d4844, d4845, d4846, d4847, d4848, d4849, d4850, d4851, d4852, d4853, d4854, d4855, d4856, d4857, d4858, d4859, d4860, d4861, d4862, d4863, d4864, d4865, d4866, d4867, d4868, d4869, d4870, d4871, d4872, d4873, d4874, d4875, d4876, d4877, d4878, d4879, d4880, d4881, d4882, d4883, d4884, d4885, d4886, d4887, d4888, d4889, d4890, d4891, d4892, d4893, d4894, d4895, d4896, d4897, d4898, d4899, d4900, d4901, d4902, d4903, d4904, d4905, d4906, d4907, d4908, d4909, d4910, d4911, d4912, d4913, d4914, d4915, d4916, d4917, d4918, d4919, d4920, d4921, d4922, d4923, d4924, d4925, d4926, d4927, d4928, d4929, d4930, d4931, d4932, d4933, d4934, d4935, d4936, d4937, d4938, d4939, d4940, d4941, d4942, d4943, d4944, d4945, d4946, d4947, d4948, d4949, d4950, d4951, d4952, d4953, d4954, d4955, d4956, d4957, d4958, d4959, d4960, d4961, d4962, d4963, d4964, d4965, d4966, d4967, d4968, d4969, d4970, d4971, d4972, d4973, d4974, d4975, d4976, d4977, d4978, d4979, d4980, d4981, d4982, d4983, d4984, d4985, d4986, d4987, d4988, d4989, d4990, d4991, d4992, d4993, d4994, d4995, d4996, d4997, d4998, d4999, d5000, d5001, d5002, d5003, d5004, d5005, d5006, d5007, d5008, d5009, d5010, d5011, d5012, d5013, d5014, d5015, d5016, d5017, d5018, d5019, d5020, d5021, d5022, d5023, d5024, d5025, d5026, d5027, d5028, d5029, d5030, d5031, d5032, d5033, d5034, d5035, d5036, d5037, d5038, d5039, d5040, d5041, d5042, d5043, d5044, d5045, d5046, d5047, d5048, d5049, d5050, d5051, d5052, d5053, d5054, d5055, d5056, d5057, d5058, d5059, d5060, d5061, d5062, d5063, d5064, d5065, d5066, d5067, d5068, d5069, d5070, d5071, d5072, d5073, d5074, d5075, d5076, d5077, d5078, d5079, d5080, d5081, d5082, d5083, d5084, d5085, d5086, d5087, d5088, d5089, d5090, d5091, d5092, d5093, d5094, d5095, d5096, d5097, d5098, d5099, d5100, d5101, d5102, d5103, d5104, d5105, d5106, d5107, d5108, d5109, d5110, d5111, d5112, d5113, d5114, d5115, d5116, d5117, d5118, d5119, d5120, d5121, d5122, d5123, d5124, d5125, d5126, d5127, d5128, d5129, d5130, d5131, d5132, d5133, d5134, d5135, d5136, d5137, d5138, d5139, d5140, d5141, d5142, d5143, d5144, d5145, d5146, d5147, d5148, d5149, d5150, d5151, d5152, d5153, d5154, d5155, d5156, d5157, d5158, d5159, d5160, d5161, d5162, d5163, d5164, d5165, d5166, d5167, d5168, d5169, d5170, d5171, d5172, d5173, d5174, d5175, d5176, d5177, d5178, d5179, d5180, d5181, d5182, d5183, d5184, d5185, d5186, d5187, d5188, d5189, d5190, d5191, d5192, d5193, d5194, d5195, d5196, d5197, d5198, d5199, d5200, d5201, d5202, d5203, d5204, d5205, d5206, d5207, d5208, d5209, d5210, d5211, d5212, d5213, d5214, d5215, d5216, d5217, d5218, d5219, d5220, d5221, d5222, d5223, d5224, d5225, d5226, d5227, d5228, d5229, d5230, d5231, d5232, d5233, d5234, d5235, d5236, d5237, d5238, d5239, d5240, d5241, d5242, d5243, d5244, d5245, d5246, d5247, d5248, d5249, d5250, d5251, d5252, d5253, d5254, d5255, d5256, d5257, d5258, d5259, d5260, d5261, d5262, d5263, d5264, d5265, d5266, d5267, d5268, d5269, d5270, d5271, d5272, d5273, d5274, d5275, d5276, d5277, d5278, d5279, d5280, d5281, d5282, d5283, d5284, d5285, d5286, d5287, d5288, d5289, d5290, d5291, d5292, d5293, d5294, d5295, d5296, d5297, d5298, d5299, d5300, d5301, d5302, d5303, d5304, d5305, d5306, d5307, d5308, d5309, d5310, d5311, d5312, d5313, d5314, d5315, d5316, d5317, d5318, d5319, d5320, d5321, d5322, d5323, d5324, d5325, d5326, d5327, d5328, d5329, d5330, d5331, d5332, d5333, d5334, d5335, d5336, d5337, d5338, d5339, d5340, d5341, d5342, d5343, d5344, d5345, d5346, d5347, d5348, d5349, d5350, d5351, d5352, d5353, d5354, d5355, d5356, d5357, d5358, d5359, d5360, d5361, d5362, d5363, d5364, d5365, d5366, d5367, d5368, d5369, d5370, d5371, d5372, d5373, d5374, d5375, d5376, d5377, d5378, d5379, d5380, d5381, d5382, d5383, d5384, d5385, d5386, d5387, d5388, d5389, d5390, d5391, d5392, d5393, d5394, d5395, d5396, d5397, d5398, d5399, d5400, d5401, d5402, d5403, d5404, d5405, d5406, d5407, d5408, d5409, d5410, d5411, d5412, d5413, d5414, d5415, d5416, d5417, d5418, d5419, d5420, d5421, d5422, d5423, d5424, d5425, d5426, d5427, d5428, d5429, d5430, d5431, d5432, d5433, d5434, d5435, d5436, d5437, d5438, d5439, d5440, d5441, d5442, d5443, d5444, d5445, d5446, d5447, d5448, d5449, d5450, d5451, d5452, d5453, d5454, d5455, d5456, d5457, d5458, d5459, d5460, d5461, d5462, d5463, d5464, d5465, d5466, d5467, d5468, d5469, d5470, d5471, d5472, d5473, d5474, d5475, d5476, d5477, d5478, d5479, d5480, d5481, d5482, d5483, d5484, d5485, d5486, d5487, d5488, d5489, d5490, d5491, d5492, d5493, d5494, d5495, d5496, d5497, d5498, d5499, d5500, d5501, d5502, d5503, d5504, d5505, d5506, d5507, d5508, d5509, d5510, d5511, d5512, d5513, d5514, d5515, d5516, d5517, d5518, d5519, d5520, d5521, d5522, d5523, d5524, d5525, d5526, d5527, d5528, d5529, d5530, d5531, d5532, d5533, d5534, d5535, d5536, d5537, d5538, d5539, d5540, d5541, d5542, d5543, d5544, d5545, d5546, d5547, d5548, d5549, d5550, d5551, d5552, d5553, d5554, d5555, d5556, d5557, d5558, d5559, d5560, d5561, d5562, d5563, d5564, d5565, d5566, d5567, d5568, d5569, d5570, d5571, d5572, d5573, d5574, d5575, d5576, d5577, d5578, d5579, d5580, d5581, d5582, d5583, d5584, d5585, d5586, d5587, d5588, d5589, d5590, d5591, d5592, d5593, d5594, d5595, d5596, d5597, d5598, d5599, d5600, d5601, d5602, d5603, d5604, d5605, d5606, d5607, d5608, d5609, d5610, d5611, d5612, d5613, d5614, d5615, d5616, d5617, d5618, d5619, d5620, d5621, d5622, d5623, d5624, d5625, d5626, d5627, d5628, d5629, d5630, d5631, d5632, d5633, d5634, d5635, d5636, d5637, d5638, d5639, d5640, d5641, d5642, d5643, d5644, d5645, d5646, d5647, d5648, d5649, d5650, d5651, d5652, d5653, d5654, d5655, d5656, d5657, d5658, d5659, d5660, d5661, d5662, d5663, d5664, d5665, d5666, d5667, d5668, d5669, d5670, d5671, d5672, d5673, d5674, d5675, d5676, d5677, d5678, d5679, d5680, d5681, d5682, d5683, d5684, d5685, d5686, d5687, d5688, d5689, d5690, d5691, d5692, d5693, d5694, d5695, d5696, d5697, d5698, d5699, d5700, d5701, d5702, d5703, d5704, d5705, d5706, d5707, d5708, d5709, d5710, d5711, d5712, d5713, d5714, d5715, d5716, d5717, d5718, d5719, d5720, d5721, d5722, d5723, d5724, d5725, d5726, d5727, d5728, d5729, d5730, d5731, d5732, d5733, d5734, d5735, d5736, d5737, d5738, d5739, d5740, d5741, d5742, d5743, d5744, d5745, d5746, d5747, d5748, d5749, d5750, d5751, d5752, d5753, d5754, d5755, d5756, d5757, d5758, d5759, d5760, d5761, d5762, d5763, d5764, d5765, d5766, d5767, d5768, d5769, d5770, d5771, d5772, d5773, d5774, d5775, d5776, d5777, d5778, d5779, d5780, d5781, d5782, d5783, d5784, d5785, d5786, d5787, d5788, d5789, d5790, d5791, d5792, d5793, d5794, d5795, d5796, d5797, d5798, d5799, d5800, d5801, d5802, d5803, d5804, d5805, d5806, d5807, d5808, d5809, d5810, d5811, d5812, d5813, d5814, d5815, d5816, d5817, d5818, d5819, d5820, d5821, d5822, d5823, d5824, d5825, d5826, d5827, d5828, d5829, d5830, d5831, d5832, d5833, d5834, d5835, d5836, d5837, d5838, d5839, d5840, d5841, d5842, d5843, d5844, d5845, d5846, d5847, d5848, d5849, d5850, d5851, d5852, d5853, d5854, d5855, d5856, d5857, d5858, d5859, d5860, d5861, d5862, d5863, d5864, d5865, d5866, d5867, d5868, d5869, d5870, d5871, d5872, d5873, d5874, d5875, d5876, d5877, d5878, d5879, d5880, d5881, d5882, d5883, d5884, d5885, d5886, d5887, d5888, d5889, d5890, d5891, d5892, d5893, d5894, d5895, d5896, d5897, d5898, d5899, d5900, d5901, d5902, d5903, d5904, d5905, d5906, d5907, d5908, d5909, d5910, d5911, d5912, d5913, d5914, d5915, d5916, d5917, d5918, d5919, d5920, d5921, d5922, d5923, d5924, d5925, d5926, d5927, d5928, d5929, d5930, d5931, d5932, d5933, d5934, d5935, d5936, d5937, d5938, d5939, d5940, d5941, d5942, d5943, d5944, d5945, d5946, d5947, d5948, d5949, d5950, d5951, d5952, d5953, d5954, d5955, d5956, d5957, d5958, d5959, d5960, d5961, d5962, d5963, d5964, d5965, d5966, d5967, d5968, d5969, d5970, d5971, d5972, d5973, d5974, d5975, d5976, d5977, d5978, d5979, d5980, d5981, d5982, d5983, d5984, d5985, d5986, d5987, d5988, d5989, d5990, d5991, d5992, d5993, d5994, d5995, d5996, d5997, d5998, d5999, d6000, d6001, d6002, d6003, d6004, d6005, d6006, d6007, d6008, d6009, d6010, d6011, d6012, d6013, d6014, d6015, d6016, d6017, d6018, d6019, d6020, d6021, d6022, d6023, d6024, d6025, d6026, d6027, d6028, d6029, d6030, d6031, d6032, d6033, d6034, d6035, d6036, d6037, d6038, d6039, d6040, d6041, d6042, d6043, d6044, d6045, d6046, d6047, d6048, d6049, d6050, d6051, d6052, d6053, d6054, d6055, d6056, d6057, d6058, d6059, d6060, d6061, d6062, d6063, d6064, d6065, d6066, d6067, d6068, d6069, d6070, d6071, d6072, d6073, d6074, d6075, d6076, d6077, d6078, d6079, d6080, d6081, d6082, d6083, d6084, d6085, d6086, d6087, d6088, d6089, d6090, d6091, d6092, d6093, d6094, d6095, d6096, d6097, d6098, d6099, d6100, d6101, d6102, d6103, d6104, d6105, d6106, d6107, d6108, d6109, d6110, d6111, d6112, d6113, d6114, d6115, d6116, d6117, d6118, d6119, d6120, d6121, d6122, d6123, d6124, d6125, d6126, d6127, d6128, d6129, d6130, d6131, d6132, d6133, d6134, d6135, d6136, d6137, d6138, d6139, d6140, d6141, d6142, d6143, d6144, d6145, d6146, d6147, d6148, d6149, d6150, d6151, d6152, d6153, d6154, d6155, d6156, d6157, d6158, d6159, d6160, d6161, d6162, d6163, d6164, d6165, d6166, d6167, d6168, d6169, d6170, d6171, d6172, d6173, d6174, d6175, d6176, d6177, d6178, d6179, d6180, d6181, d6182, d6183, d6184, d6185, d6186, d6187, d6188, d6189, d6190, d6191, d6192, d6193, d6194, d6195, d6196, d6197, d6198, d6199, d6200, d6201, d6202, d6203, d6204, d6205, d6206, d6207, d6208, d6209, d6210, d6211, d6212, d6213, d6214, d6215, d6216, d6217, d6218, d6219, d6220, d6221, d6222, d6223, d6224, d6225, d6226, d6227, d6228, d6229, d6230, d6231, d6232, d6233, d6234, d6235, d6236, d6237, d6238, d6239, d6240, d6241, d6242, d6243, d6244, d6245, d6246, d6247, d6248, d6249, d6250, d6251, d6252, d6253, d6254, d6255, d6256, d6257, d6258, d6259, d6260, d6261, d6262, d6263, d6264, d6265, d6266, d6267, d6268, d6269, d6270, d6271, d6272, d6273, d6274, d6275, d6276, d6277, d6278, d6279, d6280, d6281, d6282, d6283, d6284, d6285, d6286, d6287, d6288, d6289, d6290, d6291, d6292, d6293, d6294, d6295, d6296, d6297, d6298, d6299, d6300, d6301, d6302, d6303, d6304, d6305, d6306, d6307, d6308, d6309, d6310, d6311, d6312, d6313, d6314, d6315, d6316, d6317, d6318, d6319, d6320, d6321, d6322, d6323, d6324, d6325, d6326, d6327, d6328, d6329, d6330, d6331, d6332, d6333, d6334, d6335, d6336, d6337, d6338, d6339, d6340, d6341, d6342, d6343, d6344, d6345, d6346, d6347, d6348, d6349, d6350, d6351, d6352, d6353, d6354, d6355, d6356, d6357, d6358, d6359, d6360, d6361, d6362, d6363, d6364, d6365, d6366, d6367, d6368, d6369, d6370, d6371, d6372, d6373, d6374, d6375, d6376, d6377, d6378, d6379, d6380, d6381, d6382, d6383, d6384, d6385, d6386, d6387, d6388, d6389, d6390, d6391, d6392, d6393, d6394, d6395, d6396, d6397, d6398, d6399, d6400, d6401, d6402, d6403, d6404, d6405, d6406, d6407, d6408, d6409, d6410, d6411, d6412, d6413, d6414, d6415, d6416, d6417, d6418, d6419, d6420, d6421, d6422, d6423, d6424, d6425, d6426, d6427, d6428, d6429, d6430, d6431, d6432, d6433, d6434, d6435, d6436, d6437, d6438, d6439, d6440, d6441, d6442, d6443, d6444, d6445, d6446, d6447, d6448, d6449, d6450, d6451, d6452, d6453, d6454, d6455, d6456, d6457, d6458, d6459, d6460, d6461, d6462, d6463, d6464, d6465, d6466, d6467, d6468, d6469, d6470, d6471, d6472, d6473, d6474, d6475, d6476, d6477, d6478, d6479, d6480, d6481, d6482, d6483, d6484, d6485, d6486, d6487, d6488, d6489, d6490, d6491, d6492, d6493, d6494, d6495, d6496, d6497, d6498, d6499, d6500, d6501, d6502, d6503, d6504, d6505, d6506, d6507, d6508, d6509, d6510, d6511, d6512, d6513, d6514, d6515, d6516, d6517, d6518, d6519, d6520, d6521, d6522, d6523, d6524, d6525, d6526, d6527, d6528, d6529, d6530, d6531, d6532, d6533, d6534, d6535, d6536, d6537, d6538, d6539, d6540, d6541, d6542, d6543, d6544, d6545, d6546, d6547, d6548, d6549, d6550, d6551, d6552, d6553, d6554, d6555, d6556, d6557, d6558, d6559, d6560, d6561, d6562, d6563, d6564, d6565, d6566, d6567, d6568, d6569, d6570, d6571, d6572, d6573, d6574, d6575, d6576, d6577, d6578, d6579, d6580, d6581, d6582, d6583, d6584, d6585, d6586, d6587, d6588, d6589, d6590, d6591, d6592, d6593, d6594, d6595, d6596, d6597, d6598, d6599, d6600, d6601, d6602, d6603, d6604, d6605, d6606, d6607, d6608, d6609, d6610, d6611, d6612, d6613, d6614, d6615, d6616, d6617, d6618, d6619, d6620, d6621, d6622, d6623, d6624, d6625, d6626, d6627, d6628, d6629, d6630, d6631, d6632, d6633, d6634, d6635, d6636, d6637, d6638, d6639, d6640, d6641, d6642, d6643, d6644, d6645, d6646, d6647, d6648, d6649, d6650, d6651, d6652, d6653, d6654, d6655, d6656, d6657, d6658, d6659, d6660, d6661, d6662, d6663, d6664, d6665, d6666, d6667, d6668, d6669, d6670, d6671, d6672, d6673, d6674, d6675, d6676, d6677, d6678, d6679, d6680, d6681, d6682, d6683, d6684, d6685, d6686, d6687, d6688, d6689, d6690, d6691, d6692, d6693, d6694, d6695, d6696, d6697, d6698, d6699, d6700, d6701, d6702, d6703, d6704, d6705, d6706, d6707, d6708, d6709, d6710, d6711, d6712, d6713, d6714, d6715, d6716, d6717, d6718, d6719, d6720, d6721, d6722, d6723, d6724, d6725, d6726, d6727, d6728, d6729, d6730, d6731, d6732, d6733, d6734, d6735, d6736, d6737, d6738, d6739, d6740, d6741, d6742, d6743, d6744, d6745, d6746, d6747, d6748, d6749, d6750, d6751, d6752, d6753, d6754, d6755, d6756, d6757, d6758, d6759, d6760, d6761, d6762, d6763, d6764, d6765, d6766, d6767, d6768, d6769, d6770, d6771, d6772, d6773, d6774, d6775, d6776, d6777, d6778, d6779, d6780, d6781, d6782, d6783, d6784, d6785, d6786, d6787, d6788, d6789, d6790, d6791, d6792, d6793, d6794, d6795, d6796, d6797, d6798, d6799, d6800, d6801, d6802, d6803, d6804, d6805, d6806, d6807, d6808, d6809, d6810, d6811, d6812, d6813, d6814, d6815, d6816, d6817, d6818, d6819, d6820, d6821, d6822, d6823, d6824, d6825, d6826, d6827, d6828, d6829, d6830, d6831, d6832, d6833, d6834, d6835, d6836, d6837, d6838, d6839, d6840, d6841, d6842, d6843, d6844, d6845, d6846, d6847, d6848, d6849, d6850, d6851, d6852, d6853, d6854, d6855, d6856, d6857, d6858, d6859, d6860, d6861, d6862, d6863, d6864, d6865, d6866, d6867, d6868, d6869, d6870, d6871, d6872, d6873, d6874, d6875, d6876, d6877, d6878, d6879, d6880, d6881, d6882, d6883, d6884, d6885, d6886, d6887, d6888, d6889, d6890, d6891, d6892, d6893, d6894, d6895, d6896, d6897, d6898, d6899, d6900, d6901, d6902, d6903, d6904, d6905, d6906, d6907, d6908, d6909, d6910, d6911, d6912, d6913, d6914, d6915, d6916, d6917, d6918, d6919, d6920, d6921, d6922, d6923, d6924, d6925, d6926, d6927, d6928, d6929, d6930, d6931, d6932, d6933, d6934, d6935, d6936, d6937, d6938, d6939, d6940, d6941, d6942, d6943, d6944, d6945, d6946, d6947, d6948, d6949, d6950, d6951, d6952, d6953, d6954, d6955, d6956, d6957, d6958, d6959, d6960, d6961, d6962, d6963, d6964, d6965, d6966, d6967, d6968, d6969, d6970, d6971, d6972, d6973, d6974, d6975, d6976, d6977, d6978, d6979, d6980, d6981, d6982, d6983, d6984, d6985, d6986, d6987, d6988, d6989, d6990, d6991, d6992, d6993, d6994, d6995, d6996, d6997, d6998, d6999, d7000, d7001, d7002, d7003, d7004, d7005, d7006, d7007, d7008, d7009, d7010, d7011, d7012, d7013, d7014, d7015, d7016, d7017, d7018, d7019, d7020, d7021, d7022, d7023, d7024, d7025, d7026, d7027, d7028, d7029, d7030, d7031, d7032, d7033, d7034, d7035, d7036, d7037, d7038, d7039, d7040, d7041, d7042, d7043, d7044, d7045, d7046, d7047, d7048, d7049, d7050, d7051, d7052, d7053, d7054, d7055, d7056, d7057, d7058, d7059, d7060, d7061, d7062, d7063, d7064, d7065, d7066, d7067, d7068, d7069, d7070, d7071, d7072, d7073, d7074, d7075, d7076, d7077, d7078, d7079, d7080, d7081, d7082, d7083, d7084, d7085, d7086, d7087, d7088, d7089, d7090, d7091, d7092, d7093, d7094, d7095, d7096, d7097, d7098, d7099, d7100, d7101, d7102, d7103, d7104, d7105, d7106, d7107, d7108, d7109, d7110, d7111, d7112, d7113, d7114, d7115, d7116, d7117, d7118, d7119, d7120, d7121, d7122, d7123, d7124, d7125, d7126, d7127, d7128, d7129, d7130, d7131, d7132, d7133, d7134, d7135, d7136, d7137, d7138, d7139, d7140, d7141, d7142, d7143, d7144, d7145, d7146, d7147, d7148, d7149, d7150, d7151, d7152, d7153, d7154, d7155, d7156, d7157, d7158, d7159, d7160, d7161, d7162, d7163, d7164, d7165, d7166, d7167, d7168, d7169, d7170, d7171, d7172, d7173, d7174, d7175, d7176, d7177, d7178, d7179, d7180, d7181, d7182, d7183, d7184, d7185, d7186, d7187, d7188, d7189, d7190, d7191, d7192, d7193, d7194, d7195, d7196, d7197, d7198, d7199, d7200, d7201, d7202, d7203, d7204, d7205, d7206, d7207, d7208, d7209, d7210, d7211, d7212, d7213, d7214, d7215, d7216, d7217, d7218, d7219, d7220, d7221, d7222, d7223, d7224, d7225, d7226, d7227, d7228, d7229, d7230, d7231, d7232, d7233, d7234, d7235, d7236, d7237, d7238, d7239, d7240, d7241, d7242, d7243, d7244, d7245, d7246, d7247, d7248, d7249, d7250, d7251, d7252, d7253, d7254, d7255, d7256, d7257, d7258, d7259, d7260, d7261, d7262, d7263, d7264, d7265, d7266, d7267, d7268, d7269, d7270, d7271, d7272, d7273, d7274, d7275, d7276, d7277, d7278, d7279, d7280, d7281, d7282, d7283, d7284, d7285, d7286, d7287, d7288, d7289, d7290, d7291, d7292, d7293, d7294, d7295, d7296, d7297, d7298, d7299, d7300, d7301, d7302, d7303, d7304, d7305, d7306, d7307, d7308, d7309, d7310, d7311, d7312, d7313, d7314, d7315, d7316, d7317, d7318, d7319, d7320, d7321, d7322, d7323, d7324, d7325, d7326, d7327, d7328, d7329, d7330, d7331, d7332, d7333, d7334, d7335, d7336, d7337, d7338, d7339, d7340, d7341, d7342, d7343, d7344, d7345, d7346, d7347, d7348, d7349, d7350, d7351, d7352, d7353, d7354, d7355, d7356, d7357, d7358, d7359, d7360, d7361, d7362, d7363, d7364, d7365, d7366, d7367, d7368, d7369, d7370, d7371, d7372, d7373, d7374, d7375, d7376, d7377, d7378, d7379, d7380, d7381, d7382, d7383, d7384, d7385, d7386, d7387, d7388, d7389, d7390, d7391, d7392, d7393, d7394, d7395, d7396, d7397, d7398, d7399, d7400, d7401, d7402, d7403, d7404, d7405, d7406, d7407, d7408, d7409, d7410, d7411, d7412, d7413, d7414, d7415, d7416, d7417, d7418, d7419, d7420, d7421, d7422, d7423, d7424, d7425, d7426, d7427, d7428, d7429, d7430, d7431, d7432, d7433, d7434, d7435, d7436, d7437, d7438, d7439, d7440, d7441, d7442, d7443, d7444, d7445, d7446, d7447, d7448, d7449, d7450, d7451, d7452, d7453, d7454, d7455, d7456, d7457, d7458, d7459, d7460, d7461, d7462, d7463, d7464, d7465, d7466, d7467, d7468, d7469, d7470, d7471, d7472, d7473, d7474, d7475, d7476, d7477, d7478, d7479, d7480, d7481, d7482, d7483, d7484, d7485, d7486, d7487, d7488, d7489, d7490, d7491, d7492, d7493, d7494, d7495, d7496, d7497, d7498, d7499, d7500, d7501, d7502, d7503, d7504, d7505, d7506, d7507, d7508, d7509, d7510, d7511, d7512, d7513, d7514, d7515, d7516, d7517, d7518, d7519, d7520, d7521, d7522, d7523, d7524, d7525, d7526, d7527, d7528, d7529, d7530, d7531, d7532, d7533, d7534, d7535, d7536, d7537, d7538, d7539, d7540, d7541, d7542, d7543, d7544, d7545, d7546, d7547, d7548, d7549, d7550, d7551, d7552, d7553, d7554, d7555, d7556, d7557, d7558, d7559, d7560, d7561, d7562, d7563, d7564, d7565, d7566, d7567, d7568, d7569, d7570, d7571, d7572, d7573, d7574, d7575, d7576, d7577, d7578, d7579, d7580, d7581, d7582, d7583, d7584, d7585, d7586, d7587, d7588, d7589, d7590, d7591, d7592, d7593, d7594, d7595, d7596, d7597, d7598, d7599, d7600, d7601, d7602, d7603, d7604, d7605, d7606, d7607, d7608, d7609, d7610, d7611, d7612, d7613, d7614, d7615, d7616, d7617, d7618, d7619, d7620, d7621, d7622, d7623, d7624, d7625, d7626, d7627, d7628, d7629, d7630, d7631, d7632, d7633, d7634, d7635, d7636, d7637, d7638, d7639, d7640, d7641, d7642, d7643, d7644, d7645, d7646, d7647, d7648, d7649, d7650, d7651, d7652, d7653, d7654, d7655, d7656, d7657, d7658, d7659, d7660, d7661, d7662, d7663, d7664, d7665, d7666, d7667, d7668, d7669, d7670, d7671, d7672, d7673, d7674, d7675, d7676, d7677, d7678, d7679, d7680, d7681, d7682, d7683, d7684, d7685, d7686, d7687, d7688, d7689, d7690, d7691, d7692, d7693, d7694, d7695, d7696, d7697, d7698, d7699, d7700, d7701, d7702, d7703, d7704, d7705, d7706, d7707, d7708, d7709, d7710, d7711, d7712, d7713, d7714, d7715, d7716, d7717, d7718, d7719, d7720, d7721, d7722, d7723, d7724, d7725, d7726, d7727, d7728, d7729, d7730, d7731, d7732, d7733, d7734, d7735, d7736, d7737, d7738, d7739, d7740, d7741, d7742, d7743, d7744, d7745, d7746, d7747, d7748, d7749, d7750, d7751, d7752, d7753, d7754, d7755, d7756, d7757, d7758, d7759, d7760, d7761, d7762, d7763, d7764, d7765, d7766, d7767, d7768, d7769, d7770, d7771, d7772, d7773, d7774, d7775, d7776, d7777, d7778, d7779, d7780, d7781, d7782, d7783, d7784, d7785, d7786, d7787, d7788, d7789, d7790, d7791, d7792, d7793, d7794, d7795, d7796, d7797, d7798, d7799, d7800, d7801, d7802, d7803, d7804, d7805, d7806, d7807, d7808, d7809, d7810, d7811, d7812, d7813, d7814, d7815, d7816, d7817, d7818, d7819, d7820, d7821, d7822, d7823, d7824, d7825, d7826, d7827, d7828, d7829, d7830, d7831, d7832, d7833, d7834, d7835, d7836, d7837, d7838, d7839, d7840, d7841, d7842, d7843, d7844, d7845, d7846, d7847, d7848, d7849, d7850, d7851, d7852, d7853, d7854, d7855, d7856, d7857, d7858, d7859, d7860, d7861, d7862, d7863, d7864, d7865, d7866, d7867, d7868, d7869, d7870, d7871, d7872, d7873, d7874, d7875, d7876, d7877, d7878, d7879, d7880, d7881, d7882, d7883, d7884, d7885, d7886, d7887, d7888, d7889, d7890, d7891, d7892, d7893, d7894, d7895, d7896, d7897, d7898, d7899, d7900, d7901, d7902, d7903, d7904, d7905, d7906, d7907, d7908, d7909, d7910, d7911, d7912, d7913, d7914, d7915, d7916, d7917, d7918, d7919, d7920, d7921, d7922, d7923, d7924, d7925, d7926, d7927, d7928, d7929, d7930, d7931, d7932, d7933, d7934, d7935, d7936, d7937, d7938, d7939, d7940, d7941, d7942, d7943, d7944, d7945, d7946, d7947, d7948, d7949, d7950, d7951, d7952, d7953, d7954, d7955, d7956, d7957, d7958, d7959, d7960, d7961, d7962, d7963, d7964, d7965, d7966, d7967, d7968, d7969, d7970, d7971, d7972, d7973, d7974, d7975, d7976, d7977, d7978, d7979, d7980, d7981, d7982, d7983, d7984, d7985, d7986, d7987, d7988, d7989, d7990, d7991, d7992, d7993, d7994, d7995, d7996, d7997, d7998, d7999, d8000, d8001, d8002, d8003, d8004, d8005, d8006, d8007, d8008, d8009, d8010, d8011, d8012, d8013, d8014, d8015, d8016, d8017, d8018, d8019, d8020, d8021, d8022, d8023, d8024, d8025, d8026, d8027, d8028, d8029, d8030, d8031, d8032, d8033, d8034, d8035, d8036, d8037, d8038, d8039, d8040, d8041, d8042, d8043, d8044, d8045, d8046, d8047, d8048, d8049, d8050, d8051, d8052, d8053, d8054, d8055, d8056, d8057, d8058, d8059, d8060, d8061, d8062, d8063, d8064, d8065, d8066, d8067, d8068, d8069, d8070, d8071, d8072, d8073, d8074, d8075, d8076, d8077, d8078, d8079, d8080, d8081, d8082, d8083, d8084, d8085, d8086, d8087, d8088, d8089, d8090, d8091, d8092, d8093, d8094, d8095, d8096, d8097, d8098, d8099, d8100, d8101, d8102, d8103, d8104, d8105, d8106, d8107, d8108, d8109, d8110, d8111, d8112, d8113, d8114, d8115, d8116, d8117, d8118, d8119, d8120, d8121, d8122, d8123, d8124, d8125, d8126, d8127, d8128, d8129, d8130, d8131, d8132, d8133, d8134, d8135, d8136, d8137, d8138, d8139, d8140, d8141, d8142, d8143, d8144, d8145, d8146, d8147, d8148, d8149, d8150, d8151, d8152, d8153, d8154, d8155, d8156, d8157, d8158, d8159, d8160, d8161, d8162, d8163, d8164, d8165, d8166, d8167, d8168, d8169, d8170, d8171, d8172, d8173, d8174, d8175, d8176, d8177, d8178, d8179, d8180, d8181, d8182, d8183, d8184, d8185, d8186, d8187, d8188, d8189, d8190, d8191, d8192, d8193, d8194, d8195, d8196, d8197, d8198, d8199, d8200, d8201, d8202, d8203, d8204, d8205, d8206, d8207, d8208, d8209, d8210, d8211, d8212, d8213, d8214, d8215, d8216, d8217, d8218, d8219, d8220, d8221, d8222, d8223, d8224, d8225, d8226, d8227, d8228, d8229, d8230, d8231, d8232, d8233, d8234, d8235, d8236, d8237, d8238, d8239, d8240, d8241, d8242, d8243, d8244, d8245, d8246, d8247, d8248, d8249, d8250, d8251, d8252, d8253, d8254, d8255, d8256, d8257, d8258, d8259, d8260, d8261, d8262, d8263, d8264, d8265, d8266, d8267, d8268, d8269, d8270, d8271, d8272, d8273, d8274, d8275, d8276, d8277, d8278, d8279, d8280, d8281, d8282, d8283, d8284, d8285, d8286, d8287, d8288, d8289, d8290, d8291, d8292, d8293, d8294, d8295, d8296, d8297, d8298, d8299, d8300, d8301, d8302, d8303, d8304, d8305, d8306, d8307, d8308, d8309, d8310, d8311, d8312, d8313, d8314, d8315, d8316, d8317, d8318, d8319, d8320, d8321, d8322, d8323, d8324, d8325, d8326, d8327, d8328, d8329, d8330, d8331, d8332, d8333, d8334, d8335, d8336, d8337, d8338, d8339, d8340, d8341, d8342, d8343, d8344, d8345, d8346, d8347, d8348, d8349, d8350, d8351, d8352, d8353, d8354, d8355, d8356, d8357, d8358, d8359, d8360, d8361, d8362, d8363, d8364, d8365, d8366, d8367, d8368, d8369, d8370, d8371, d8372, d8373, d8374, d8375, d8376, d8377, d8378, d8379, d8380, d8381, d8382, d8383, d8384, d8385, d8386, d8387, d8388, d8389, d8390, d8391, d8392, d8393, d8394, d8395, d8396, d8397, d8398, d8399, d8400, d8401, d8402, d8403, d8404, d8405, d8406, d8407, d8408, d8409, d8410, d8411, d8412, d8413, d8414, d8415, d8416, d8417, d8418, d8419, d8420, d8421, d8422, d8423, d8424, d8425, d8426, d8427, d8428, d8429, d8430, d8431, d8432, d8433, d8434, d8435, d8436, d8437, d8438, d8439, d8440, d8441, d8442, d8443, d8444, d8445, d8446, d8447, d8448, d8449, d8450, d8451, d8452, d8453, d8454, d8455, d8456, d8457, d8458, d8459, d8460, d8461, d8462, d8463, d8464, d8465, d8466, d8467, d8468, d8469, d8470, d8471, d8472, d8473, d8474, d8475, d8476, d8477, d8478, d8479, d8480, d8481, d8482, d8483, d8484, d8485, d8486, d8487, d8488, d8489, d8490, d8491, d8492, d8493, d8494, d8495, d8496, d8497, d8498, d8499, d8500, d8501, d8502, d8503, d8504, d8505, d8506, d8507, d8508, d8509, d8510, d8511, d8512, d8513, d8514, d8515, d8516, d8517, d8518, d8519, d8520, d8521, d8522, d8523, d8524, d8525, d8526, d8527, d8528, d8529, d8530, d8531, d8532, d8533, d8534, d8535, d8536, d8537, d8538, d8539, d8540, d8541, d8542, d8543, d8544, d8545, d8546, d8547, d8548, d8549, d8550, d8551, d8552, d8553, d8554, d8555, d8556, d8557, d8558, d8559, d8560, d8561, d8562, d8563, d8564, d8565, d8566, d8567, d8568, d8569, d8570, d8571, d8572, d8573, d8574, d8575, d8576, d8577, d8578, d8579, d8580, d8581, d8582, d8583, d8584, d8585, d8586, d8587, d8588, d8589, d8590, d8591, d8592, d8593, d8594, d8595, d8596, d8597, d8598, d8599, d8600, d8601, d8602, d8603, d8604, d8605, d8606, d8607, d8608, d8609, d8610, d8611, d8612, d8613, d8614, d8615, d8616, d8617, d8618, d8619, d8620, d8621, d8622, d8623, d8624, d8625, d8626, d8627, d8628, d8629, d8630, d8631, d8632, d8633, d8634, d8635, d8636, d8637, d8638, d8639, d8640, d8641, d8642, d8643, d8644, d8645, d8646, d8647, d8648, d8649, d8650, d8651, d8652, d8653, d8654, d8655, d8656, d8657, d8658, d8659, d8660, d8661, d8662, d8663, d8664, d8665, d8666, d8667, d8668, d8669, d8670, d8671, d8672, d8673, d8674, d8675, d8676, d8677, d8678, d8679, d8680, d8681, d8682, d8683, d8684, d8685, d8686, d8687, d8688, d8689, d8690, d8691, d8692, d8693, d8694, d8695, d8696, d8697, d8698, d8699, d8700, d8701, d8702, d8703, d8704, d8705, d8706, d8707, d8708, d8709, d8710, d8711, d8712, d8713, d8714, d8715, d8716, d8717, d8718, d8719, d8720, d8721, d8722, d8723, d8724, d8725, d8726, d8727, d8728, d8729, d8730, d8731, d8732, d8733, d8734, d8735, d8736, d8737, d8738, d8739, d8740, d8741, d8742, d8743, d8744, d8745, d8746, d8747, d8748, d8749, d8750, d8751, d8752, d8753, d8754, d8755, d8756, d8757, d8758, d8759, d8760, d8761, d8762, d8763, d8764, d8765, d8766, d8767, d8768, d8769, d8770, d8771, d8772, d8773, d8774, d8775, d8776, d8777, d8778, d8779, d8780, d8781, d8782, d8783, d8784, d8785, d8786, d8787, d8788, d8789, d8790, d8791, d8792, d8793, d8794, d8795, d8796, d8797, d8798, d8799, d8800, d8801, d8802, d8803, d8804, d8805, d8806, d8807, d8808, d8809, d8810, d8811, d8812, d8813, d8814, d8815, d8816, d8817, d8818, d8819, d8820, d8821, d8822, d8823, d8824, d8825, d8826, d8827, d8828, d8829, d8830, d8831, d8832, d8833, d8834, d8835, d8836, d8837, d8838, d8839, d8840, d8841, d8842, d8843, d8844, d8845, d8846, d8847, d8848, d8849, d8850, d8851, d8852, d8853, d8854, d8855, d8856, d8857, d8858, d8859, d8860, d8861, d8862, d8863, d8864, d8865, d8866, d8867, d8868, d8869, d8870, d8871, d8872, d8873, d8874, d8875, d8876, d8877, d8878, d8879, d8880, d8881, d8882, d8883, d8884, d8885, d8886, d8887, d8888, d8889, d8890, d8891, d8892, d8893, d8894, d8895, d8896, d8897, d8898, d8899, d8900, d8901, d8902, d8903, d8904, d8905, d8906, d8907, d8908, d8909, d8910, d8911, d8912, d8913, d8914, d8915, d8916, d8917, d8918, d8919, d8920, d8921, d8922, d8923, d8924, d8925, d8926, d8927, d8928, d8929, d8930, d8931, d8932, d8933, d8934, d8935, d8936, d8937, d8938, d8939, d8940, d8941, d8942, d8943, d8944, d8945, d8946, d8947, d8948, d8949, d8950, d8951, d8952, d8953, d8954, d8955, d8956, d8957, d8958, d8959, d8960, d8961, d8962, d8963, d8964, d8965, d8966, d8967, d8968, d8969, d8970, d8971, d8972, d8973, d8974, d8975, d8976, d8977, d8978, d8979, d8980, d8981, d8982, d8983, d8984, d8985, d8986, d8987, d8988, d8989, d8990, d8991, d8992, d8993, d8994, d8995, d8996, d8997, d8998, d8999, d9000, d9001, d9002, d9003, d9004, d9005, d9006, d9007, d9008, d9009, d9010, d9011, d9012, d9013, d9014, d9015, d9016, d9017, d9018, d9019, d9020, d9021, d9022, d9023, d9024, d9025, d9026, d9027, d9028, d9029, d9030, d9031, d9032, d9033, d9034, d9035, d9036, d9037, d9038, d9039, d9040, d9041, d9042, d9043, d9044, d9045, d9046, d9047, d9048, d9049, d9050, d9051, d9052, d9053, d9054, d9055, d9056, d9057, d9058, d9059, d9060, d9061, d9062, d9063, d9064, d9065, d9066, d9067, d9068, d9069, d9070, d9071, d9072, d9073, d9074, d9075, d9076, d9077, d9078, d9079, d9080, d9081, d9082, d9083, d9084, d9085, d9086, d9087, d9088, d9089, d9090, d9091, d9092, d9093, d9094, d9095, d9096, d9097, d9098, d9099, d9100, d9101, d9102, d9103, d9104, d9105, d9106, d9107, d9108, d9109, d9110, d9111, d9112, d9113, d9114, d9115, d9116, d9117, d9118, d9119, d9120, d9121, d9122, d9123, d9124, d9125, d9126, d9127, d9128, d9129, d9130, d9131, d9132, d9133, d9134, d9135, d9136, d9137, d9138, d9139, d9140, d9141, d9142, d9143, d9144, d9145, d9146, d9147, d9148, d9149, d9150, d9151, d9152, d9153, d9154, d9155, d9156, d9157, d9158, d9159, d9160, d9161, d9162, d9163, d9164, d9165, d9166, d9167, d9168, d9169, d9170, d9171, d9172, d9173, d9174, d9175, d9176, d9177, d9178, d9179, d9180, d9181, d9182, d9183, d9184, d9185, d9186, d9187, d9188, d9189, d9190, d9191, d9192, d9193, d9194, d9195, d9196, d9197, d9198, d9199, d9200, d9201, d9202, d9203, d9204, d9205, d9206, d9207, d9208, d9209, d9210, d9211, d9212, d9213, d9214, d9215, d9216, d9217, d9218, d9219, d9220, d9221, d9222, d9223, d9224, d9225, d9226, d9227, d9228, d9229, d9230, d9231, d9232, d9233, d9234, d9235, d9236, d9237, d9238, d9239, d9240, d9241, d9242, d9243, d9244, d9245, d9246, d9247, d9248, d9249, d9250, d9251, d9252, d9253, d9254, d9255, d9256, d9257, d9258, d9259, d9260, d9261, d9262, d9263, d9264, d9265, d9266, d9267, d9268, d9269, d9270, d9271, d9272, d9273, d9274, d9275, d9276, d9277, d9278, d9279, d9280, d9281, d9282, d9283, d9284, d9285, d9286, d9287, d9288, d9289, d9290, d9291, d9292, d9293, d9294, d9295, d9296, d9297, d9298, d9299, d9300, d9301, d9302, d9303, d9304, d9305, d9306, d9307, d9308, d9309, d9310, d9311, d9312, d9313, d9314, d9315, d9316, d9317, d9318, d9319, d9320, d9321, d9322, d9323, d9324, d9325, d9326, d9327, d9328, d9329, d9330, d9331, d9332, d9333, d9334, d9335, d9336, d9337, d9338, d9339, d9340, d9341, d9342, d9343, d9344, d9345, d9346, d9347, d9348, d9349, d9350, d9351, d9352, d9353, d9354, d9355, d9356, d9357, d9358, d9359, d9360, d9361, d9362, d9363, d9364, d9365, d9366, d9367, d9368, d9369, d9370, d9371, d9372, d9373, d9374, d9375, d9376, d9377, d9378, d9379, d9380, d9381, d9382, d9383, d9384, d9385, d9386, d9387, d9388, d9389, d9390, d9391, d9392, d9393, d9394, d9395, d9396, d9397, d9398, d9399, d9400, d9401, d9402, d9403, d9404, d9405, d9406, d9407, d9408, d9409, d9410, d9411, d9412, d9413, d9414, d9415, d9416, d9417, d9418, d9419, d9420, d9421, d9422, d9423, d9424, d9425, d9426, d9427, d9428, d9429, d9430, d9431, d9432, d9433, d9434, d9435, d9436, d9437, d9438, d9439, d9440, d9441, d9442, d9443, d9444, d9445, d9446, d9447, d9448, d9449, d9450, d9451, d9452, d9453, d9454, d9455, d9456, d9457, d9458, d9459, d9460, d9461, d9462, d9463, d9464, d9465, d9466, d9467, d9468, d9469, d9470, d9471, d9472, d9473, d9474, d9475, d9476, d9477, d9478, d9479, d9480, d9481, d9482, d9483, d9484, d9485, d9486, d9487, d9488, d9489, d9490, d9491, d9492, d9493, d9494, d9495, d9496, d9497, d9498, d9499, d9500, d9501, d9502, d9503, d9504, d9505, d9506, d9507, d9508, d9509, d9510, d9511, d9512, d9513, d9514, d9515, d9516, d9517, d9518, d9519, d9520, d9521, d9522, d9523, d9524, d9525, d9526, d9527, d9528, d9529, d9530, d9531, d9532, d9533, d9534, d9535, d9536, d9537, d9538, d9539, d9540, d9541, d9542, d9543, d9544, d9545, d9546, d9547, d9548, d9549, d9550, d9551, d9552, d9553, d9554, d9555, d9556, d9557, d9558, d9559, d9560, d9561, d9562, d9563, d9564, d9565, d9566, d9567, d9568, d9569, d9570, d9571, d9572, d9573, d9574, d9575, d9576, d9577, d9578, d9579, d9580, d9581, d9582, d9583, d9584, d9585, d9586, d9587, d9588, d9589, d9590, d9591, d9592, d9593, d9594, d9595, d9596, d9597, d9598, d9599, d9600, d9601, d9602, d9603, d9604, d9605, d9606, d9607, d9608, d9609, d9610, d9611, d9612, d9613, d9614, d9615, d9616, d9617, d9618, d9619, d9620, d9621, d9622, d9623, d9624, d9625, d9626, d9627, d9628, d9629, d9630, d9631, d9632, d9633, d9634, d9635, d9636, d9637, d9638, d9639, d9640, d9641, d9642, d9643, d9644, d9645, d9646, d9647, d9648, d9649, d9650, d9651, d9652, d9653, d9654, d9655, d9656, d9657, d9658, d9659, d9660, d9661, d9662, d9663, d9664, d9665, d9666, d9667, d9668, d9669, d9670, d9671, d9672, d9673, d9674, d9675, d9676, d9677, d9678, d9679, d9680, d9681, d9682, d9683, d9684, d9685, d9686, d9687, d9688, d9689, d9690, d9691, d9692, d9693, d9694, d9695, d9696, d9697, d9698, d9699, d9700, d9701, d9702, d9703, d9704, d9705, d9706, d9707, d9708, d9709, d9710, d9711, d9712, d9713, d9714, d9715, d9716, d9717, d9718, d9719, d9720, d9721, d9722, d9723, d9724, d9725, d9726, d9727, d9728, d9729, d9730, d9731, d9732, d9733, d9734, d9735, d9736, d9737, d9738, d9739, d9740, d9741, d9742, d9743, d9744, d9745, d9746, d9747, d9748, d9749, d9750, d9751, d9752, d9753, d9754, d9755, d9756, d9757, d9758, d9759, d9760, d9761, d9762, d9763, d9764, d9765, d9766, d9767, d9768, d9769, d9770, d9771, d9772, d9773, d9774, d9775, d9776, d9777, d9778, d9779, d9780, d9781, d9782, d9783, d9784, d9785, d9786, d9787, d9788, d9789, d9790, d9791, d9792, d9793, d9794, d9795, d9796, d9797, d9798, d9799, d9800, d9801, d9802, d9803, d9804, d9805, d9806, d9807, d9808, d9809, d9810, d9811, d9812, d9813, d9814, d9815, d9816, d9817, d9818, d9819, d9820, d9821, d9822, d9823, d9824, d9825, d9826, d9827, d9828, d9829, d9830, d9831, d9832, d9833, d9834, d9835, d9836, d9837, d9838, d9839, d9840, d9841, d9842, d9843, d9844, d9845, d9846, d9847, d9848, d9849, d9850, d9851, d9852, d9853, d9854, d9855, d9856, d9857, d9858, d9859, d9860, d9861, d9862, d9863, d9864, d9865, d9866, d9867, d9868, d9869, d9870, d9871, d9872, d9873, d9874, d9875, d9876, d9877, d9878, d9879, d9880, d9881, d9882, d9883, d9884, d9885, d9886, d9887, d9888, d9889, d9890, d9891, d9892, d9893, d9894, d9895, d9896, d9897, d9898, d9899, d9900, d9901, d9902, d9903, d9904, d9905, d9906, d9907, d9908, d9909, d9910, d9911, d9912, d9913, d9914, d9915, d9916, d9917, d9918, d9919, d9920, d9921, d9922, d9923, d9924, d9925, d9926, d9927, d9928, d9929, d9930, d9931, d9932, d9933, d9934, d9935, d9936, d9937, d9938, d9939, d9940, d9941, d9942, d9943, d9944, d9945, d9946, d9947, d9948, d9949, d9950, d9951, d9952, d9953, d9954, d9955, d9956, d9957, d9958, d9959, d9960, d9961, d9962, d9963, d9964, d9965, d9966, d9967, d9968, d9969, d9970, d9971, d9972, d9973, d9974, d9975, d9976, d9977, d9978, d9979, d9980, d9981, d9982, d9983, d9984, d9985, d9986, d9987, d9988, d9989, d9990, d9991, d9992, d9993, d9994, d9995, d9996, d9997, d9998, f0,f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18,f19,f20,f21,f22,f23,f24,f25,f26,f27,f28,f29,f30,f31,f32,f33,f34,f35,f36,f37,f38,f39,f40,f41,f42,f43,f44,f45,f46,f47,f48,f49,f50,f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f62,f63,f64,f65,f66,f67,f68,f69,f70,f71,f72,f73,f74,f75,f76,f77,f78,f79,f80,f81,f82,f83,f84,f85,f86,f87,f88,f89,f90,f91,f92,f93,f94,f95,f96,f97,f98,f99,f100,f101,f102,f103,f104,f105,f106,f107,f108,f109,f110,f111,f112,f113,f114,f115,f116,f117,f118,f119,f120,f121,f122,f123,f124,f125,f126,f127,f128,f129,f130,f131,f132,f133,f134,f135,f136,f137,f138,f139,f140,f141,f142,f143,f144,f145,f146,f147,f148,f149,f150,f151,f152,f153,f154,f155,f156,f157,f158,f159,f160,f161,f162,f163,f164,f165,f166,f167,f168,f169,f170,f171,f172,f173,f174,f175,f176,f177,f178,f179,f180,f181,f182,f183,f184,f185,f186,f187,f188,f189,f190,f191,f192,f193,f194,f195,f196,f197,f198,f199,f200,f201,f202,f203,f204,f205,f206,f207,f208,f209,f210,f211,f212,f213,f214,f215,f216,f217,f218,f219,f220,f221,f222,f223,f224,f225,f226,f227,f228,f229,f230,f231,f232,f233,f234,f235,f236,f237,f238,f239,f240,f241,f242,f243,f244,f245,f246,f247,f248,f249,f250,f251,f252,f253,f254,f255,f256,f257,f258,f259,f260,f261,f262,f263,f264,f265,f266,f267,f268,f269,f270,f271,f272,f273,f274,f275,f276,f277,f278,f279,f280,f281,f282,f283,f284,f285,f286,f287,f288,f289,f290,f291,f292,f293,f294,f295,f296,f297,f298,f299,f300,f301,f302,f303,f304,f305,f306,f307,f308,f309,f310,f311,f312,f313,f314,f315,f316,f317,f318,f319,f320,f321,f322,f323,f324,f325,f326,f327,f328,f329,f330,f331,f332,f333,f334,f335,f336,f337,f338,f339,f340,f341,f342,f343,f344,f345,f346,f347,f348,f349,f350,f351,f352,f353,f354,f355,f356,f357,f358,f359,f360,f361,f362,f363,f364,f365,f366,f367,f368,f369,f370,f371,f372,f373,f374,f375,f376,f377,f378,f379,f380,f381,f382,f383,f384,f385,f386,f387,f388,f389,f390,f391,f392,f393,f394,f395,f396,f397,f398,f399,f400,f401,f402,f403,f404,f405,f406,f407,f408,f409,f410,f411,f412,f413,f414,f415,f416,f417,f418,f419,f420,f421,f422,f423,f424,f425,f426,f427,f428,f429,f430,f431,f432,f433,f434,f435,f436,f437,f438,f439,f440,f441,f442,f443,f444,f445,f446,f447,f448,f449,f450,f451,f452,f453,f454,f455,f456,f457,f458,f459,f460,f461,f462,f463,f464,f465,f466,f467,f468,f469,f470,f471,f472,f473,f474,f475,f476,f477,f478,f479,f480,f481,f482,f483,f484,f485,f486,f487,f488,f489,f490,f491,f492,f493,f494,f495,f496,f497,f498,f499,f500,f501,f502,f503,f504,f505,f506,f507,f508,f509,f510,f511,f512,f513,f514,f515,f516,f517,f518,f519,f520,f521,f522,f523,f524,f525,f526,f527,f528,f529,f530,f531,f532,f533,f534,f535,f536,f537,f538,f539,f540,f541,f542,f543,f544,f545,f546,f547,f548,f549,f550,f551,f552,f553,f554,f555,f556,f557,f558,f559,f560,f561,f562,f563,f564,f565,f566,f567,f568,f569,f570,f571,f572,f573,f574,f575,f576,f577,f578,f579,f580,f581,f582,f583,f584,f585,f586,f587,f588,f589,f590,f591,f592,f593,f594,f595,f596,f597,f598,f599,f600,f601,f602,f603,f604,f605,f606,f607,f608,f609,f610,f611,f612,f613,f614,f615,f616,f617,f618,f619,f620,f621,f622,f623,f624,f625,f626,f627,f628,f629,f630,f631,f632,f633,f634,f635,f636,f637,f638,f639,f640,f641,f642,f643,f644,f645,f646,f647,f648,f649,f650,f651,f652,f653,f654,f655,f656,f657,f658,f659,f660,f661,f662,f663,f664,f665,f666,f667,f668,f669,f670,f671,f672,f673,f674,f675,f676,f677,f678,f679,f680,f681,f682,f683,f684,f685,f686,f687,f688,f689,f690,f691,f692,f693,f694,f695,f696,f697,f698,f699,f700,f701,f702,f703,f704,f705,f706,f707,f708,f709,f710,f711,f712,f713,f714,f715,f716,f717,f718,f719,f720,f721,f722,f723,f724,f725,f726,f727,f728,f729,f730,f731,f732,f733,f734,f735,f736,f737,f738,f739,f740,f741,f742,f743,f744,f745,f746,f747,f748,f749,f750,f751,f752,f753,f754,f755,f756,f757,f758,f759,f760,f761,f762,f763,f764,f765,f766,f767,f768,f769,f770,f771,f772,f773,f774,f775,f776,f777,f778,f779,f780,f781,f782,f783,f784,f785,f786,f787,f788,f789,f790,f791,f792,f793,f794,f795,f796,f797,f798,f799,f800,f801,f802,f803,f804,f805,f806,f807,f808,f809,f810,f811,f812,f813,f814,f815,f816,f817,f818,f819,f820,f821,f822,f823,f824,f825,f826,f827,f828,f829,f830,f831,f832,f833,f834,f835,f836,f837,f838,f839,f840,f841,f842,f843,f844,f845,f846,f847,f848,f849,f850,f851,f852,f853,f854,f855,f856,f857,f858,f859,f860,f861,f862,f863,f864,f865,f866,f867,f868,f869,f870,f871,f872,f873,f874,f875,f876,f877,f878,f879,f880,f881,f882,f883,f884,f885,f886,f887,f888,f889,f890,f891,f892,f893,f894,f895,f896,f897,f898,f899,f900,f901,f902,f903,f904,f905,f906,f907,f908,f909,f910,f911,f912,f913,f914,f915,f916,f917,f918,f919,f920,f921,f922,f923,f924,f925,f926,f927,f928,f929,f930,f931,f932,f933,f934,f935,f936,f937,f938,f939,f940,f941,f942,f943,f944,f945,f946,f947,f948,f949,f950,f951,f952,f953,f954,f955,f956,f957,f958,f959,f960,f961,f962,f963,f964,f965,f966,f967,f968,f969,f970,f971,f972,f973,f974,f975,f976,f977,f978,f979,f980,f981,f982,f983,f984,f985,f986,f987,f988,f989,f990,f991,f992,f993,f994,f995,f996,f997,f998,f999,f1000,f1001,f1002,f1003,f1004,f1005,f1006,f1007,f1008,f1009,f1010,f1011,f1012,f1013,f1014,f1015,f1016,f1017,f1018,f1019,f1020,f1021,f1022,f1023,f1024,f1025,f1026,f1027,f1028,f1029,f1030,f1031,f1032,f1033,f1034,f1035,f1036,f1037,f1038,f1039,f1040,f1041,f1042,f1043,f1044,f1045,f1046,f1047,f1048,f1049,f1050,f1051,f1052,f1053,f1054,f1055,f1056,f1057,f1058,f1059,f1060,f1061,f1062,f1063,f1064,f1065,f1066,f1067,f1068,f1069,f1070,f1071,f1072,f1073,f1074,f1075,f1076,f1077,f1078,f1079,f1080,f1081,f1082,f1083,f1084,f1085,f1086,f1087,f1088,f1089,f1090,f1091,f1092,f1093,f1094,f1095,f1096,f1097,f1098,f1099,f1100,f1101,f1102,f1103,f1104,f1105,f1106,f1107,f1108,f1109,f1110,f1111,f1112,f1113,f1114,f1115,f1116,f1117,f1118,f1119,f1120,f1121,f1122,f1123,f1124,f1125,f1126,f1127,f1128,f1129,f1130,f1131,f1132,f1133,f1134,f1135,f1136,f1137,f1138,f1139,f1140,f1141,f1142,f1143,f1144,f1145,f1146,f1147,f1148,f1149,f1150,f1151,f1152,f1153,f1154,f1155,f1156,f1157,f1158,f1159,f1160,f1161,f1162,f1163,f1164,f1165,f1166,f1167,f1168,f1169,f1170,f1171,f1172,f1173,f1174,f1175,f1176,f1177,f1178,f1179,f1180,f1181,f1182,f1183,f1184,f1185,f1186,f1187,f1188,f1189,f1190,f1191,f1192,f1193,f1194,f1195,f1196,f1197,f1198,f1199,f1200,f1201,f1202,f1203,f1204,f1205,f1206,f1207,f1208,f1209,f1210,f1211,f1212,f1213,f1214,f1215,f1216,f1217,f1218,f1219,f1220,f1221,f1222,f1223,f1224,f1225,f1226,f1227,f1228,f1229,f1230,f1231,f1232,f1233,f1234,f1235,f1236,f1237,f1238,f1239,f1240,f1241,f1242,f1243,f1244,f1245,f1246,f1247,f1248,f1249,f1250,f1251,f1252,f1253,f1254,f1255,f1256,f1257,f1258,f1259,f1260,f1261,f1262,f1263,f1264,f1265,f1266,f1267,f1268,f1269,f1270,f1271,f1272,f1273,f1274,f1275,f1276,f1277,f1278,f1279,f1280,f1281,f1282,f1283,f1284,f1285,f1286,f1287,f1288,f1289,f1290,f1291,f1292,f1293,f1294,f1295,f1296,f1297,f1298,f1299,f1300,f1301,f1302,f1303,f1304,f1305,f1306,f1307,f1308,f1309,f1310,f1311,f1312,f1313,f1314,f1315,f1316,f1317,f1318,f1319,f1320,f1321,f1322,f1323,f1324,f1325,f1326,f1327,f1328,f1329,f1330,f1331,f1332,f1333,f1334,f1335,f1336,f1337,f1338,f1339,f1340,f1341,f1342,f1343,f1344,f1345,f1346,f1347,f1348,f1349,f1350,f1351,f1352,f1353,f1354,f1355,f1356,f1357,f1358,f1359,f1360,f1361,f1362,f1363,f1364,f1365,f1366,f1367,f1368,f1369,f1370,f1371,f1372,f1373,f1374,f1375,f1376,f1377,f1378,f1379,f1380,f1381,f1382,f1383,f1384,f1385,f1386,f1387,f1388,f1389,f1390,f1391,f1392,f1393,f1394,f1395,f1396,f1397,f1398,f1399,f1400,f1401,f1402,f1403,f1404,f1405,f1406,f1407,f1408,f1409,f1410,f1411,f1412,f1413,f1414,f1415,f1416,f1417,f1418,f1419,f1420,f1421,f1422,f1423,f1424,f1425,f1426,f1427,f1428,f1429,f1430,f1431,f1432,f1433,f1434,f1435,f1436,f1437,f1438,f1439,f1440,f1441,f1442,f1443,f1444,f1445,f1446,f1447,f1448,f1449,f1450,f1451,f1452,f1453,f1454,f1455,f1456,f1457,f1458,f1459,f1460,f1461,f1462,f1463,f1464,f1465,f1466,f1467,f1468,f1469,f1470,f1471,f1472,f1473,f1474,f1475,f1476,f1477,f1478,f1479,f1480,f1481,f1482,f1483,f1484,f1485,f1486,f1487,f1488,f1489,f1490,f1491,f1492,f1493,f1494,f1495,f1496,f1497,f1498,f1499,f1500,f1501,f1502,f1503,f1504,f1505,f1506,f1507,f1508,f1509,f1510,f1511,f1512,f1513,f1514,f1515,f1516,f1517,f1518,f1519,f1520,f1521,f1522,f1523,f1524,f1525,f1526,f1527,f1528,f1529,f1530,f1531,f1532,f1533,f1534,f1535,f1536,f1537,f1538,f1539,f1540,f1541,f1542,f1543,f1544,f1545,f1546,f1547,f1548,f1549,f1550,f1551,f1552,f1553,f1554,f1555,f1556,f1557,f1558,f1559,f1560,f1561,f1562,f1563,f1564,f1565,f1566,f1567,f1568,f1569,f1570,f1571,f1572,f1573,f1574,f1575,f1576,f1577,f1578,f1579,f1580,f1581,f1582,f1583,f1584,f1585,f1586,f1587,f1588,f1589,f1590,f1591,f1592,f1593,f1594,f1595,f1596,f1597,f1598,f1599,f1600,f1601,f1602,f1603,f1604,f1605,f1606,f1607,f1608,f1609,f1610,f1611,f1612,f1613,f1614,f1615,f1616,f1617,f1618,f1619,f1620,f1621,f1622,f1623,f1624,f1625,f1626,f1627,f1628,f1629,f1630,f1631,f1632,f1633,f1634,f1635,f1636,f1637,f1638,f1639,f1640,f1641,f1642,f1643,f1644,f1645,f1646,f1647,f1648,f1649,f1650,f1651,f1652,f1653,f1654,f1655,f1656,f1657,f1658,f1659,f1660,f1661,f1662,f1663,f1664,f1665,f1666,f1667,f1668,f1669,f1670,f1671,f1672,f1673,f1674,f1675,f1676,f1677,f1678,f1679,f1680,f1681,f1682,f1683,f1684,f1685,f1686,f1687,f1688,f1689,f1690,f1691,f1692,f1693,f1694,f1695,f1696,f1697,f1698,f1699,f1700,f1701,f1702,f1703,f1704,f1705,f1706,f1707,f1708,f1709,f1710,f1711,f1712,f1713,f1714,f1715,f1716,f1717,f1718,f1719,f1720,f1721,f1722,f1723,f1724,f1725,f1726,f1727,f1728,f1729,f1730,f1731,f1732,f1733,f1734,f1735,f1736,f1737,f1738,f1739,f1740,f1741,f1742,f1743,f1744,f1745,f1746,f1747,f1748,f1749,f1750,f1751,f1752,f1753,f1754,f1755,f1756,f1757,f1758,f1759,f1760,f1761,f1762,f1763,f1764,f1765,f1766,f1767,f1768,f1769,f1770,f1771,f1772,f1773,f1774,f1775,f1776,f1777,f1778,f1779,f1780,f1781,f1782,f1783,f1784,f1785,f1786,f1787,f1788,f1789,f1790,f1791,f1792,f1793,f1794,f1795,f1796,f1797,f1798,f1799,f1800,f1801,f1802,f1803,f1804,f1805,f1806,f1807,f1808,f1809,f1810,f1811,f1812,f1813,f1814,f1815,f1816,f1817,f1818,f1819,f1820,f1821,f1822,f1823,f1824,f1825,f1826,f1827,f1828,f1829,f1830,f1831,f1832,f1833,f1834,f1835,f1836,f1837,f1838,f1839,f1840,f1841,f1842,f1843,f1844,f1845,f1846,f1847,f1848,f1849,f1850,f1851,f1852,f1853,f1854,f1855,f1856,f1857,f1858,f1859,f1860,f1861,f1862,f1863,f1864,f1865,f1866,f1867,f1868,f1869,f1870,f1871,f1872,f1873,f1874,f1875,f1876,f1877,f1878,f1879,f1880,f1881,f1882,f1883,f1884,f1885,f1886,f1887,f1888,f1889,f1890,f1891,f1892,f1893,f1894,f1895,f1896,f1897,f1898,f1899,f1900,f1901,f1902,f1903,f1904,f1905,f1906,f1907,f1908,f1909,f1910,f1911,f1912,f1913,f1914,f1915,f1916,f1917,f1918,f1919,f1920,f1921,f1922,f1923,f1924,f1925,f1926,f1927,f1928,f1929,f1930,f1931,f1932,f1933,f1934,f1935,f1936,f1937,f1938,f1939,f1940,f1941,f1942,f1943,f1944,f1945,f1946,f1947,f1948,f1949,f1950,f1951,f1952,f1953,f1954,f1955,f1956,f1957,f1958,f1959,f1960,f1961,f1962,f1963,f1964,f1965,f1966,f1967,f1968,f1969,f1970,f1971,f1972,f1973,f1974,f1975,f1976,f1977,f1978,f1979,f1980,f1981,f1982,f1983,f1984,f1985,f1986,f1987,f1988,f1989,f1990,f1991,f1992,f1993,f1994,f1995,f1996,f1997,f1998,f1999,f2000,f2001,f2002,f2003,f2004,f2005,f2006,f2007,f2008,f2009,f2010,f2011,f2012,f2013,f2014,f2015,f2016,f2017,f2018,f2019,f2020,f2021,f2022,f2023,f2024,f2025,f2026,f2027,f2028,f2029,f2030,f2031,f2032,f2033,f2034,f2035,f2036,f2037,f2038,f2039,f2040,f2041,f2042,f2043,f2044,f2045,f2046,f2047,f2048,f2049,f2050,f2051,f2052,f2053,f2054,f2055,f2056,f2057,f2058,f2059,f2060,f2061,f2062,f2063,f2064,f2065,f2066,f2067,f2068,f2069,f2070,f2071,f2072,f2073,f2074,f2075,f2076,f2077,f2078,f2079,f2080,f2081,f2082,f2083,f2084,f2085,f2086,f2087,f2088,f2089,f2090,f2091,f2092,f2093,f2094,f2095,f2096,f2097,f2098,f2099,f2100,f2101,f2102,f2103,f2104,f2105,f2106,f2107,f2108,f2109,f2110,f2111,f2112,f2113,f2114,f2115,f2116,f2117,f2118,f2119,f2120,f2121,f2122,f2123,f2124,f2125,f2126,f2127,f2128,f2129,f2130,f2131,f2132,f2133,f2134,f2135,f2136,f2137,f2138,f2139,f2140,f2141,f2142,f2143,f2144,f2145,f2146,f2147,f2148,f2149,f2150,f2151,f2152,f2153,f2154,f2155,f2156,f2157,f2158,f2159,f2160,f2161,f2162,f2163,f2164,f2165,f2166,f2167,f2168,f2169,f2170,f2171,f2172,f2173,f2174,f2175,f2176,f2177,f2178,f2179,f2180,f2181,f2182,f2183,f2184,f2185,f2186,f2187,f2188,f2189,f2190,f2191,f2192,f2193,f2194,f2195,f2196,f2197,f2198,f2199,f2200,f2201,f2202,f2203,f2204,f2205,f2206,f2207,f2208,f2209,f2210,f2211,f2212,f2213,f2214,f2215,f2216,f2217,f2218,f2219,f2220,f2221,f2222,f2223,f2224,f2225,f2226,f2227,f2228,f2229,f2230,f2231,f2232,f2233,f2234,f2235,f2236,f2237,f2238,f2239,f2240,f2241,f2242,f2243,f2244,f2245,f2246,f2247,f2248,f2249,f2250,f2251,f2252,f2253,f2254,f2255,f2256,f2257,f2258,f2259,f2260,f2261,f2262,f2263,f2264,f2265,f2266,f2267,f2268,f2269,f2270,f2271,f2272,f2273,f2274,f2275,f2276,f2277,f2278,f2279,f2280,f2281,f2282,f2283,f2284,f2285,f2286,f2287,f2288,f2289,f2290,f2291,f2292,f2293,f2294,f2295,f2296,f2297,f2298,f2299,f2300,f2301,f2302,f2303,f2304,f2305,f2306,f2307,f2308,f2309,f2310,f2311,f2312,f2313,f2314,f2315,f2316,f2317,f2318,f2319,f2320,f2321,f2322,f2323,f2324,f2325,f2326,f2327,f2328,f2329,f2330,f2331,f2332,f2333,f2334,f2335,f2336,f2337,f2338,f2339,f2340,f2341,f2342,f2343,f2344,f2345,f2346,f2347,f2348,f2349,f2350,f2351,f2352,f2353,f2354,f2355,f2356,f2357,f2358,f2359,f2360,f2361,f2362,f2363,f2364,f2365,f2366,f2367,f2368,f2369,f2370,f2371,f2372,f2373,f2374,f2375,f2376,f2377,f2378,f2379,f2380,f2381,f2382,f2383,f2384,f2385,f2386,f2387,f2388,f2389,f2390,f2391,f2392,f2393,f2394,f2395,f2396,f2397,f2398,f2399,f2400,f2401,f2402,f2403,f2404,f2405,f2406,f2407,f2408,f2409,f2410,f2411,f2412,f2413,f2414,f2415,f2416,f2417,f2418,f2419,f2420,f2421,f2422,f2423,f2424,f2425,f2426,f2427,f2428,f2429,f2430,f2431,f2432,f2433,f2434,f2435,f2436,f2437,f2438,f2439,f2440,f2441,f2442,f2443,f2444,f2445,f2446,f2447,f2448,f2449,f2450,f2451,f2452,f2453,f2454,f2455,f2456,f2457,f2458,f2459,f2460,f2461,f2462,f2463,f2464,f2465,f2466,f2467,f2468,f2469,f2470,f2471,f2472,f2473,f2474,f2475,f2476,f2477,f2478,f2479,f2480,f2481,f2482,f2483,f2484,f2485,f2486,f2487,f2488,f2489,f2490,f2491,f2492,f2493,f2494,f2495,f2496,f2497,f2498,f2499,f2500,f2501,f2502,f2503,f2504,f2505,f2506,f2507,f2508,f2509,f2510,f2511,f2512,f2513,f2514,f2515,f2516,f2517,f2518,f2519,f2520,f2521,f2522,f2523,f2524,f2525,f2526,f2527,f2528,f2529,f2530,f2531,f2532,f2533,f2534,f2535,f2536,f2537,f2538,f2539,f2540,f2541,f2542,f2543,f2544,f2545,f2546,f2547,f2548,f2549,f2550,f2551,f2552,f2553,f2554,f2555,f2556,f2557,f2558,f2559,f2560,f2561,f2562,f2563,f2564,f2565,f2566,f2567,f2568,f2569,f2570,f2571,f2572,f2573,f2574,f2575,f2576,f2577,f2578,f2579,f2580,f2581,f2582,f2583,f2584,f2585,f2586,f2587,f2588,f2589,f2590,f2591,f2592,f2593,f2594,f2595,f2596,f2597,f2598,f2599,f2600,f2601,f2602,f2603,f2604,f2605,f2606,f2607,f2608,f2609,f2610,f2611,f2612,f2613,f2614,f2615,f2616,f2617,f2618,f2619,f2620,f2621,f2622,f2623,f2624,f2625,f2626,f2627,f2628,f2629,f2630,f2631,f2632,f2633,f2634,f2635,f2636,f2637,f2638,f2639,f2640,f2641,f2642,f2643,f2644,f2645,f2646,f2647,f2648,f2649,f2650,f2651,f2652,f2653,f2654,f2655,f2656,f2657,f2658,f2659,f2660,f2661,f2662,f2663,f2664,f2665,f2666,f2667,f2668,f2669,f2670,f2671,f2672,f2673,f2674,f2675,f2676,f2677,f2678,f2679,f2680,f2681,f2682,f2683,f2684,f2685,f2686,f2687,f2688,f2689,f2690,f2691,f2692,f2693,f2694,f2695,f2696,f2697,f2698,f2699,f2700,f2701,f2702,f2703,f2704,f2705,f2706,f2707,f2708,f2709,f2710,f2711,f2712,f2713,f2714,f2715,f2716,f2717,f2718,f2719,f2720,f2721,f2722,f2723,f2724,f2725,f2726,f2727,f2728,f2729,f2730,f2731,f2732,f2733,f2734,f2735,f2736,f2737,f2738,f2739,f2740,f2741,f2742,f2743,f2744,f2745,f2746,f2747,f2748,f2749,f2750,f2751,f2752,f2753,f2754,f2755,f2756,f2757,f2758,f2759,f2760,f2761,f2762,f2763,f2764,f2765,f2766,f2767,f2768,f2769,f2770,f2771,f2772,f2773,f2774,f2775,f2776,f2777,f2778,f2779,f2780,f2781,f2782,f2783,f2784,f2785,f2786,f2787,f2788,f2789,f2790,f2791,f2792,f2793,f2794,f2795,f2796,f2797,f2798,f2799,f2800,f2801,f2802,f2803,f2804,f2805,f2806,f2807,f2808,f2809,f2810,f2811,f2812,f2813,f2814,f2815,f2816,f2817,f2818,f2819,f2820,f2821,f2822,f2823,f2824,f2825,f2826,f2827,f2828,f2829,f2830,f2831,f2832,f2833,f2834,f2835,f2836,f2837,f2838,f2839,f2840,f2841,f2842,f2843,f2844,f2845,f2846,f2847,f2848,f2849,f2850,f2851,f2852,f2853,f2854,f2855,f2856,f2857,f2858,f2859,f2860,f2861,f2862,f2863,f2864,f2865,f2866,f2867,f2868,f2869,f2870,f2871,f2872,f2873,f2874,f2875,f2876,f2877,f2878,f2879,f2880,f2881,f2882,f2883,f2884,f2885,f2886,f2887,f2888,f2889,f2890,f2891,f2892,f2893,f2894,f2895,f2896,f2897,f2898,f2899,f2900,f2901,f2902,f2903,f2904,f2905,f2906,f2907,f2908,f2909,f2910,f2911,f2912,f2913,f2914,f2915,f2916,f2917,f2918,f2919,f2920,f2921,f2922,f2923,f2924,f2925,f2926,f2927,f2928,f2929,f2930,f2931,f2932,f2933,f2934,f2935,f2936,f2937,f2938,f2939,f2940,f2941,f2942,f2943,f2944,f2945,f2946,f2947,f2948,f2949,f2950,f2951,f2952,f2953,f2954,f2955,f2956,f2957,f2958,f2959,f2960,f2961,f2962,f2963,f2964,f2965,f2966,f2967,f2968,f2969,f2970,f2971,f2972,f2973,f2974,f2975,f2976,f2977,f2978,f2979,f2980,f2981,f2982,f2983,f2984,f2985,f2986,f2987,f2988,f2989,f2990,f2991,f2992,f2993,f2994,f2995,f2996,f2997,f2998,f2999,f3000,f3001,f3002,f3003,f3004,f3005,f3006,f3007,f3008,f3009,f3010,f3011,f3012,f3013,f3014,f3015,f3016,f3017,f3018,f3019,f3020,f3021,f3022,f3023,f3024,f3025,f3026,f3027,f3028,f3029,f3030,f3031,f3032,f3033,f3034,f3035,f3036,f3037,f3038,f3039,f3040,f3041,f3042,f3043,f3044,f3045,f3046,f3047,f3048,f3049,f3050,f3051,f3052,f3053,f3054,f3055,f3056,f3057,f3058,f3059,f3060,f3061,f3062,f3063,f3064,f3065,f3066,f3067,f3068,f3069,f3070,f3071,f3072,f3073,f3074,f3075,f3076,f3077,f3078,f3079,f3080,f3081,f3082,f3083,f3084,f3085,f3086,f3087,f3088,f3089,f3090,f3091,f3092,f3093,f3094,f3095,f3096,f3097,f3098,f3099,f3100,f3101,f3102,f3103,f3104,f3105,f3106,f3107,f3108,f3109,f3110,f3111,f3112,f3113,f3114,f3115,f3116,f3117,f3118,f3119,f3120,f3121,f3122,f3123,f3124,f3125,f3126,f3127,f3128,f3129,f3130,f3131,f3132,f3133,f3134,f3135,f3136,f3137,f3138,f3139,f3140,f3141,f3142,f3143,f3144,f3145,f3146,f3147,f3148,f3149,f3150,f3151,f3152,f3153,f3154,f3155,f3156,f3157,f3158,f3159,f3160,f3161,f3162,f3163,f3164,f3165,f3166,f3167,f3168,f3169,f3170,f3171,f3172,f3173,f3174,f3175,f3176,f3177,f3178,f3179,f3180,f3181,f3182,f3183,f3184,f3185,f3186,f3187,f3188,f3189,f3190,f3191,f3192,f3193,f3194,f3195,f3196,f3197,f3198,f3199,f3200,f3201,f3202,f3203,f3204,f3205,f3206,f3207,f3208,f3209,f3210,f3211,f3212,f3213,f3214,f3215,f3216,f3217,f3218,f3219,f3220,f3221,f3222,f3223,f3224,f3225,f3226,f3227,f3228,f3229,f3230,f3231,f3232,f3233,f3234,f3235,f3236,f3237,f3238,f3239,f3240,f3241,f3242,f3243,f3244,f3245,f3246,f3247,f3248,f3249,f3250,f3251,f3252,f3253,f3254,f3255,f3256,f3257,f3258,f3259,f3260,f3261,f3262,f3263,f3264,f3265,f3266,f3267,f3268,f3269,f3270,f3271,f3272,f3273,f3274,f3275,f3276,f3277,f3278,f3279,f3280,f3281,f3282,f3283,f3284,f3285,f3286,f3287,f3288,f3289,f3290,f3291,f3292,f3293,f3294,f3295,f3296,f3297,f3298,f3299,f3300,f3301,f3302,f3303,f3304,f3305,f3306,f3307,f3308,f3309,f3310,f3311,f3312,f3313,f3314,f3315,f3316,f3317,f3318,f3319,f3320,f3321,f3322,f3323,f3324,f3325,f3326,f3327,f3328,f3329,f3330,f3331,f3332,f3333,f3334,f3335,f3336,f3337,f3338,f3339,f3340,f3341,f3342,f3343,f3344,f3345,f3346,f3347,f3348,f3349,f3350,f3351,f3352,f3353,f3354,f3355,f3356,f3357,f3358,f3359,f3360,f3361,f3362,f3363,f3364,f3365,f3366,f3367,f3368,f3369,f3370,f3371,f3372,f3373,f3374,f3375,f3376,f3377,f3378,f3379,f3380,f3381,f3382,f3383,f3384,f3385,f3386,f3387,f3388,f3389,f3390,f3391,f3392,f3393,f3394,f3395,f3396,f3397,f3398,f3399,f3400,f3401,f3402,f3403,f3404,f3405,f3406,f3407,f3408,f3409,f3410,f3411,f3412,f3413,f3414,f3415,f3416,f3417,f3418,f3419,f3420,f3421,f3422,f3423,f3424,f3425,f3426,f3427,f3428,f3429,f3430,f3431,f3432,f3433,f3434,f3435,f3436,f3437,f3438,f3439,f3440,f3441,f3442,f3443,f3444,f3445,f3446,f3447,f3448,f3449,f3450,f3451,f3452,f3453,f3454,f3455,f3456,f3457,f3458,f3459,f3460,f3461,f3462,f3463,f3464,f3465,f3466,f3467,f3468,f3469,f3470,f3471,f3472,f3473,f3474,f3475,f3476,f3477,f3478,f3479,f3480,f3481,f3482,f3483,f3484,f3485,f3486,f3487,f3488,f3489,f3490,f3491,f3492,f3493,f3494,f3495,f3496,f3497,f3498,f3499,f3500,f3501,f3502,f3503,f3504,f3505,f3506,f3507,f3508,f3509,f3510,f3511,f3512,f3513,f3514,f3515,f3516,f3517,f3518,f3519,f3520,f3521,f3522,f3523,f3524,f3525,f3526,f3527,f3528,f3529,f3530,f3531,f3532,f3533,f3534,f3535,f3536,f3537,f3538,f3539,f3540,f3541,f3542,f3543,f3544,f3545,f3546,f3547,f3548,f3549,f3550,f3551,f3552,f3553,f3554,f3555,f3556,f3557,f3558,f3559,f3560,f3561,f3562,f3563,f3564,f3565,f3566,f3567,f3568,f3569,f3570,f3571,f3572,f3573,f3574,f3575,f3576,f3577,f3578,f3579,f3580,f3581,f3582,f3583,f3584,f3585,f3586,f3587,f3588,f3589,f3590,f3591,f3592,f3593,f3594,f3595,f3596,f3597,f3598,f3599,f3600,f3601,f3602,f3603,f3604,f3605,f3606,f3607,f3608,f3609,f3610,f3611,f3612,f3613,f3614,f3615,f3616,f3617,f3618,f3619,f3620,f3621,f3622,f3623,f3624,f3625,f3626,f3627,f3628,f3629,f3630,f3631,f3632,f3633,f3634,f3635,f3636,f3637,f3638,f3639,f3640,f3641,f3642,f3643,f3644,f3645,f3646,f3647,f3648,f3649,f3650,f3651,f3652,f3653,f3654,f3655,f3656,f3657,f3658,f3659,f3660,f3661,f3662,f3663,f3664,f3665,f3666,f3667,f3668,f3669,f3670,f3671,f3672,f3673,f3674,f3675,f3676,f3677,f3678,f3679,f3680,f3681,f3682,f3683,f3684,f3685,f3686,f3687,f3688,f3689,f3690,f3691,f3692,f3693,f3694,f3695,f3696,f3697,f3698,f3699,f3700,f3701,f3702,f3703,f3704,f3705,f3706,f3707,f3708,f3709,f3710,f3711,f3712,f3713,f3714,f3715,f3716,f3717,f3718,f3719,f3720,f3721,f3722,f3723,f3724,f3725,f3726,f3727,f3728,f3729,f3730,f3731,f3732,f3733,f3734,f3735,f3736,f3737,f3738,f3739,f3740,f3741,f3742,f3743,f3744,f3745,f3746,f3747,f3748,f3749,f3750,f3751,f3752,f3753,f3754,f3755,f3756,f3757,f3758,f3759,f3760,f3761,f3762,f3763,f3764,f3765,f3766,f3767,f3768,f3769,f3770,f3771,f3772,f3773,f3774,f3775,f3776,f3777,f3778,f3779,f3780,f3781,f3782,f3783,f3784,f3785,f3786,f3787,f3788,f3789,f3790,f3791,f3792,f3793,f3794,f3795,f3796,f3797,f3798,f3799,f3800,f3801,f3802,f3803,f3804,f3805,f3806,f3807,f3808,f3809,f3810,f3811,f3812,f3813,f3814,f3815,f3816,f3817,f3818,f3819,f3820,f3821,f3822,f3823,f3824,f3825,f3826,f3827,f3828,f3829,f3830,f3831,f3832,f3833,f3834,f3835,f3836,f3837,f3838,f3839,f3840,f3841,f3842,f3843,f3844,f3845,f3846,f3847,f3848,f3849,f3850,f3851,f3852,f3853,f3854,f3855,f3856,f3857,f3858,f3859,f3860,f3861,f3862,f3863,f3864,f3865,f3866,f3867,f3868,f3869,f3870,f3871,f3872,f3873,f3874,f3875,f3876,f3877,f3878,f3879,f3880,f3881,f3882,f3883,f3884,f3885,f3886,f3887,f3888,f3889,f3890,f3891,f3892,f3893,f3894,f3895,f3896,f3897,f3898,f3899,f3900,f3901,f3902,f3903,f3904,f3905,f3906,f3907,f3908,f3909,f3910,f3911,f3912,f3913,f3914,f3915,f3916,f3917,f3918,f3919,f3920,f3921,f3922,f3923,f3924,f3925,f3926,f3927,f3928,f3929,f3930,f3931,f3932,f3933,f3934,f3935,f3936,f3937,f3938,f3939,f3940,f3941,f3942,f3943,f3944,f3945,f3946,f3947,f3948,f3949,f3950,f3951,f3952,f3953,f3954,f3955,f3956,f3957,f3958,f3959,f3960,f3961,f3962,f3963,f3964,f3965,f3966,f3967,f3968,f3969,f3970,f3971,f3972,f3973,f3974,f3975,f3976,f3977,f3978,f3979,f3980,f3981,f3982,f3983,f3984,f3985,f3986,f3987,f3988,f3989,f3990,f3991,f3992,f3993,f3994,f3995,f3996,f3997,f3998,f3999,f4000,f4001,f4002,f4003,f4004,f4005,f4006,f4007,f4008,f4009,f4010,f4011,f4012,f4013,f4014,f4015,f4016,f4017,f4018,f4019,f4020,f4021,f4022,f4023,f4024,f4025,f4026,f4027,f4028,f4029,f4030,f4031,f4032,f4033,f4034,f4035,f4036,f4037,f4038,f4039,f4040,f4041,f4042,f4043,f4044,f4045,f4046,f4047,f4048,f4049,f4050,f4051,f4052,f4053,f4054,f4055,f4056,f4057,f4058,f4059,f4060,f4061,f4062,f4063,f4064,f4065,f4066,f4067,f4068,f4069,f4070,f4071,f4072,f4073,f4074,f4075,f4076,f4077,f4078,f4079,f4080,f4081,f4082,f4083,f4084,f4085,f4086,f4087,f4088,f4089,f4090,f4091,f4092,f4093,f4094,f4095,f4096,f4097,f4098,f4099,f4100,f4101,f4102,f4103,f4104,f4105,f4106,f4107,f4108,f4109,f4110,f4111,f4112,f4113,f4114,f4115,f4116,f4117,f4118,f4119,f4120,f4121,f4122,f4123,f4124,f4125,f4126,f4127,f4128,f4129,f4130,f4131,f4132,f4133,f4134,f4135,f4136,f4137,f4138,f4139,f4140,f4141,f4142,f4143,f4144,f4145,f4146,f4147,f4148,f4149,f4150,f4151,f4152,f4153,f4154,f4155,f4156,f4157,f4158,f4159,f4160,f4161,f4162,f4163,f4164,f4165,f4166,f4167,f4168,f4169,f4170,f4171,f4172,f4173,f4174,f4175,f4176,f4177,f4178,f4179,f4180,f4181,f4182,f4183,f4184,f4185,f4186,f4187,f4188,f4189,f4190,f4191,f4192,f4193,f4194,f4195,f4196,f4197,f4198,f4199,f4200,f4201,f4202,f4203,f4204,f4205,f4206,f4207,f4208,f4209,f4210,f4211,f4212,f4213,f4214,f4215,f4216,f4217,f4218,f4219,f4220,f4221,f4222,f4223,f4224,f4225,f4226,f4227,f4228,f4229,f4230,f4231,f4232,f4233,f4234,f4235,f4236,f4237,f4238,f4239,f4240,f4241,f4242,f4243,f4244,f4245,f4246,f4247,f4248,f4249,f4250,f4251,f4252,f4253,f4254,f4255,f4256,f4257,f4258,f4259,f4260,f4261,f4262,f4263,f4264,f4265,f4266,f4267,f4268,f4269,f4270,f4271,f4272,f4273,f4274,f4275,f4276,f4277,f4278,f4279,f4280,f4281,f4282,f4283,f4284,f4285,f4286,f4287,f4288,f4289,f4290,f4291,f4292,f4293,f4294,f4295,f4296,f4297,f4298,f4299,f4300,f4301,f4302,f4303,f4304,f4305,f4306,f4307,f4308,f4309,f4310,f4311,f4312,f4313,f4314,f4315,f4316,f4317,f4318,f4319,f4320,f4321,f4322,f4323,f4324,f4325,f4326,f4327,f4328,f4329,f4330,f4331,f4332,f4333,f4334,f4335,f4336,f4337,f4338,f4339,f4340,f4341,f4342,f4343,f4344,f4345,f4346,f4347,f4348,f4349,f4350,f4351,f4352,f4353,f4354,f4355,f4356,f4357,f4358,f4359,f4360,f4361,f4362,f4363,f4364,f4365,f4366,f4367,f4368,f4369,f4370,f4371,f4372,f4373,f4374,f4375,f4376,f4377,f4378,f4379,f4380,f4381,f4382,f4383,f4384,f4385,f4386,f4387,f4388,f4389,f4390,f4391,f4392,f4393,f4394,f4395,f4396,f4397,f4398,f4399,f4400,f4401,f4402,f4403,f4404,f4405,f4406,f4407,f4408,f4409,f4410,f4411,f4412,f4413,f4414,f4415,f4416,f4417,f4418,f4419,f4420,f4421,f4422,f4423,f4424,f4425,f4426,f4427,f4428,f4429,f4430,f4431,f4432,f4433,f4434,f4435,f4436,f4437,f4438,f4439,f4440,f4441,f4442,f4443,f4444,f4445,f4446,f4447,f4448,f4449,f4450,f4451,f4452,f4453,f4454,f4455,f4456,f4457,f4458,f4459,f4460,f4461,f4462,f4463,f4464,f4465,f4466,f4467,f4468,f4469,f4470,f4471,f4472,f4473,f4474,f4475,f4476,f4477,f4478,f4479,f4480,f4481,f4482,f4483,f4484,f4485,f4486,f4487,f4488,f4489,f4490,f4491,f4492,f4493,f4494,f4495,f4496,f4497,f4498,f4499,f4500,f4501,f4502,f4503,f4504,f4505,f4506,f4507,f4508,f4509,f4510,f4511,f4512,f4513,f4514,f4515,f4516,f4517,f4518,f4519,f4520,f4521,f4522,f4523,f4524,f4525,f4526,f4527,f4528,f4529,f4530,f4531,f4532,f4533,f4534,f4535,f4536,f4537,f4538,f4539,f4540,f4541,f4542,f4543,f4544,f4545,f4546,f4547,f4548,f4549,f4550,f4551,f4552,f4553,f4554,f4555,f4556,f4557,f4558,f4559,f4560,f4561,f4562,f4563,f4564,f4565,f4566,f4567,f4568,f4569,f4570,f4571,f4572,f4573,f4574,f4575,f4576,f4577,f4578,f4579,f4580,f4581,f4582,f4583,f4584,f4585,f4586,f4587,f4588,f4589,f4590,f4591,f4592,f4593,f4594,f4595,f4596,f4597,f4598,f4599,f4600,f4601,f4602,f4603,f4604,f4605,f4606,f4607,f4608,f4609,f4610,f4611,f4612,f4613,f4614,f4615,f4616,f4617,f4618,f4619,f4620,f4621,f4622,f4623,f4624,f4625,f4626,f4627,f4628,f4629,f4630,f4631,f4632,f4633,f4634,f4635,f4636,f4637,f4638,f4639,f4640,f4641,f4642,f4643,f4644,f4645,f4646,f4647,f4648,f4649,f4650,f4651,f4652,f4653,f4654,f4655,f4656,f4657,f4658,f4659,f4660,f4661,f4662,f4663,f4664,f4665,f4666,f4667,f4668,f4669,f4670,f4671,f4672,f4673,f4674,f4675,f4676,f4677,f4678,f4679,f4680,f4681,f4682,f4683,f4684,f4685,f4686,f4687,f4688,f4689,f4690,f4691,f4692,f4693,f4694,f4695,f4696,f4697,f4698,f4699,f4700,f4701,f4702,f4703,f4704,f4705,f4706,f4707,f4708,f4709,f4710,f4711,f4712,f4713,f4714,f4715,f4716,f4717,f4718,f4719,f4720,f4721,f4722,f4723,f4724,f4725,f4726,f4727,f4728,f4729,f4730,f4731,f4732,f4733,f4734,f4735,f4736,f4737,f4738,f4739,f4740,f4741,f4742,f4743,f4744,f4745,f4746,f4747,f4748,f4749,f4750,f4751,f4752,f4753,f4754,f4755,f4756,f4757,f4758,f4759,f4760,f4761,f4762,f4763,f4764,f4765,f4766,f4767,f4768,f4769,f4770,f4771,f4772,f4773,f4774,f4775,f4776,f4777,f4778,f4779,f4780,f4781,f4782,f4783,f4784,f4785,f4786,f4787,f4788,f4789,f4790,f4791,f4792,f4793,f4794,f4795,f4796,f4797,f4798,f4799,f4800,f4801,f4802,f4803,f4804,f4805,f4806,f4807,f4808,f4809,f4810,f4811,f4812,f4813,f4814,f4815,f4816,f4817,f4818,f4819,f4820,f4821,f4822,f4823,f4824,f4825,f4826,f4827,f4828,f4829,f4830,f4831,f4832,f4833,f4834,f4835,f4836,f4837,f4838,f4839,f4840,f4841,f4842,f4843,f4844,f4845,f4846,f4847,f4848,f4849,f4850,f4851,f4852,f4853,f4854,f4855,f4856,f4857,f4858,f4859,f4860,f4861,f4862,f4863,f4864,f4865,f4866,f4867,f4868,f4869,f4870,f4871,f4872,f4873,f4874,f4875,f4876,f4877,f4878,f4879,f4880,f4881,f4882,f4883,f4884,f4885,f4886,f4887,f4888,f4889,f4890,f4891,f4892,f4893,f4894,f4895,f4896,f4897,f4898,f4899,f4900,f4901,f4902,f4903,f4904,f4905,f4906,f4907,f4908,f4909,f4910,f4911,f4912,f4913,f4914,f4915,f4916,f4917,f4918,f4919,f4920,f4921,f4922,f4923,f4924,f4925,f4926,f4927,f4928,f4929,f4930,f4931,f4932,f4933,f4934,f4935,f4936,f4937,f4938,f4939,f4940,f4941,f4942,f4943,f4944,f4945,f4946,f4947,f4948,f4949,f4950,f4951,f4952,f4953,f4954,f4955,f4956,f4957,f4958,f4959,f4960,f4961,f4962,f4963,f4964,f4965,f4966,f4967,f4968,f4969,f4970,f4971,f4972,f4973,f4974,f4975,f4976,f4977,f4978,f4979,f4980,f4981,f4982,f4983,f4984,f4985,f4986,f4987,f4988,f4989,f4990,f4991,f4992,f4993,f4994,f4995,f4996,f4997,f4998,f4999,f5000,f5001,f5002,f5003,f5004,f5005,f5006,f5007,f5008,f5009,f5010,f5011,f5012,f5013,f5014,f5015,f5016,f5017,f5018,f5019,f5020,f5021,f5022,f5023,f5024,f5025,f5026,f5027,f5028,f5029,f5030,f5031,f5032,f5033,f5034,f5035,f5036,f5037,f5038,f5039,f5040,f5041,f5042,f5043,f5044,f5045,f5046,f5047,f5048,f5049,f5050,f5051,f5052,f5053,f5054,f5055,f5056,f5057,f5058,f5059,f5060,f5061,f5062,f5063,f5064,f5065,f5066,f5067,f5068,f5069,f5070,f5071,f5072,f5073,f5074,f5075,f5076,f5077,f5078,f5079,f5080,f5081,f5082,f5083,f5084,f5085,f5086,f5087,f5088,f5089,f5090,f5091,f5092,f5093,f5094,f5095,f5096,f5097,f5098,f5099,f5100,f5101,f5102,f5103,f5104,f5105,f5106,f5107,f5108,f5109,f5110,f5111,f5112,f5113,f5114,f5115,f5116,f5117,f5118,f5119,f5120,f5121,f5122,f5123,f5124,f5125,f5126,f5127,f5128,f5129,f5130,f5131,f5132,f5133,f5134,f5135,f5136,f5137,f5138,f5139,f5140,f5141,f5142,f5143,f5144,f5145,f5146,f5147,f5148,f5149,f5150,f5151,f5152,f5153,f5154,f5155,f5156,f5157,f5158,f5159,f5160,f5161,f5162,f5163,f5164,f5165,f5166,f5167,f5168,f5169,f5170,f5171,f5172,f5173,f5174,f5175,f5176,f5177,f5178,f5179,f5180,f5181,f5182,f5183,f5184,f5185,f5186,f5187,f5188,f5189,f5190,f5191,f5192,f5193,f5194,f5195,f5196,f5197,f5198,f5199,f5200,f5201,f5202,f5203,f5204,f5205,f5206,f5207,f5208,f5209,f5210,f5211,f5212,f5213,f5214,f5215,f5216,f5217,f5218,f5219,f5220,f5221,f5222,f5223,f5224,f5225,f5226,f5227,f5228,f5229,f5230,f5231,f5232,f5233,f5234,f5235,f5236,f5237,f5238,f5239,f5240,f5241,f5242,f5243,f5244,f5245,f5246,f5247,f5248,f5249,f5250,f5251,f5252,f5253,f5254,f5255,f5256,f5257,f5258,f5259,f5260,f5261,f5262,f5263,f5264,f5265,f5266,f5267,f5268,f5269,f5270,f5271,f5272,f5273,f5274,f5275,f5276,f5277,f5278,f5279,f5280,f5281,f5282,f5283,f5284,f5285,f5286,f5287,f5288,f5289,f5290,f5291,f5292,f5293,f5294,f5295,f5296,f5297,f5298,f5299,f5300,f5301,f5302,f5303,f5304,f5305,f5306,f5307,f5308,f5309,f5310,f5311,f5312,f5313,f5314,f5315,f5316,f5317,f5318,f5319,f5320,f5321,f5322,f5323,f5324,f5325,f5326,f5327,f5328,f5329,f5330,f5331,f5332,f5333,f5334,f5335,f5336,f5337,f5338,f5339,f5340,f5341,f5342,f5343,f5344,f5345,f5346,f5347,f5348,f5349,f5350,f5351,f5352,f5353,f5354,f5355,f5356,f5357,f5358,f5359,f5360,f5361,f5362,f5363,f5364,f5365,f5366,f5367,f5368,f5369,f5370,f5371,f5372,f5373,f5374,f5375,f5376,f5377,f5378,f5379,f5380,f5381,f5382,f5383,f5384,f5385,f5386,f5387,f5388,f5389,f5390,f5391,f5392,f5393,f5394,f5395,f5396,f5397,f5398,f5399,f5400,f5401,f5402,f5403,f5404,f5405,f5406,f5407,f5408,f5409,f5410,f5411,f5412,f5413,f5414,f5415,f5416,f5417,f5418,f5419,f5420,f5421,f5422,f5423,f5424,f5425,f5426,f5427,f5428,f5429,f5430,f5431,f5432,f5433,f5434,f5435,f5436,f5437,f5438,f5439,f5440,f5441,f5442,f5443,f5444,f5445,f5446,f5447,f5448,f5449,f5450,f5451,f5452,f5453,f5454,f5455,f5456,f5457,f5458,f5459,f5460,f5461,f5462,f5463,f5464,f5465,f5466,f5467,f5468,f5469,f5470,f5471,f5472,f5473,f5474,f5475,f5476,f5477,f5478,f5479,f5480,f5481,f5482,f5483,f5484,f5485,f5486,f5487,f5488,f5489,f5490,f5491,f5492,f5493,f5494,f5495,f5496,f5497,f5498,f5499,f5500,f5501,f5502,f5503,f5504,f5505,f5506,f5507,f5508,f5509,f5510,f5511,f5512,f5513,f5514,f5515,f5516,f5517,f5518,f5519,f5520,f5521,f5522,f5523,f5524,f5525,f5526,f5527,f5528,f5529,f5530,f5531,f5532,f5533,f5534,f5535,f5536,f5537,f5538,f5539,f5540,f5541,f5542,f5543,f5544,f5545,f5546,f5547,f5548,f5549,f5550,f5551,f5552,f5553,f5554,f5555,f5556,f5557,f5558,f5559,f5560,f5561,f5562,f5563,f5564,f5565,f5566,f5567,f5568,f5569,f5570,f5571,f5572,f5573,f5574,f5575,f5576,f5577,f5578,f5579,f5580,f5581,f5582,f5583,f5584,f5585,f5586,f5587,f5588,f5589,f5590,f5591,f5592,f5593,f5594,f5595,f5596,f5597,f5598,f5599,f5600,f5601,f5602,f5603,f5604,f5605,f5606,f5607,f5608,f5609,f5610,f5611,f5612,f5613,f5614,f5615,f5616,f5617,f5618,f5619,f5620,f5621,f5622,f5623,f5624,f5625,f5626,f5627,f5628,f5629,f5630,f5631,f5632,f5633,f5634,f5635,f5636,f5637,f5638,f5639,f5640,f5641,f5642,f5643,f5644,f5645,f5646,f5647,f5648,f5649,f5650,f5651,f5652,f5653,f5654,f5655,f5656,f5657,f5658,f5659,f5660,f5661,f5662,f5663,f5664,f5665,f5666,f5667,f5668,f5669,f5670,f5671,f5672,f5673,f5674,f5675,f5676,f5677,f5678,f5679,f5680,f5681,f5682,f5683,f5684,f5685,f5686,f5687,f5688,f5689,f5690,f5691,f5692,f5693,f5694,f5695,f5696,f5697,f5698,f5699,f5700,f5701,f5702,f5703,f5704,f5705,f5706,f5707,f5708,f5709,f5710,f5711,f5712,f5713,f5714,f5715,f5716,f5717,f5718,f5719,f5720,f5721,f5722,f5723,f5724,f5725,f5726,f5727,f5728,f5729,f5730,f5731,f5732,f5733,f5734,f5735,f5736,f5737,f5738,f5739,f5740,f5741,f5742,f5743,f5744,f5745,f5746,f5747,f5748,f5749,f5750,f5751,f5752,f5753,f5754,f5755,f5756,f5757,f5758,f5759,f5760,f5761,f5762,f5763,f5764,f5765,f5766,f5767,f5768,f5769,f5770,f5771,f5772,f5773,f5774,f5775,f5776,f5777,f5778,f5779,f5780,f5781,f5782,f5783,f5784,f5785,f5786,f5787,f5788,f5789,f5790,f5791,f5792,f5793,f5794,f5795,f5796,f5797,f5798,f5799,f5800,f5801,f5802,f5803,f5804,f5805,f5806,f5807,f5808,f5809,f5810,f5811,f5812,f5813,f5814,f5815,f5816,f5817,f5818,f5819,f5820,f5821,f5822,f5823,f5824,f5825,f5826,f5827,f5828,f5829,f5830,f5831,f5832,f5833,f5834,f5835,f5836,f5837,f5838,f5839,f5840,f5841,f5842,f5843,f5844,f5845,f5846,f5847,f5848,f5849,f5850,f5851,f5852,f5853,f5854,f5855,f5856,f5857,f5858,f5859,f5860,f5861,f5862,f5863,f5864,f5865,f5866,f5867,f5868,f5869,f5870,f5871,f5872,f5873,f5874,f5875,f5876,f5877,f5878,f5879,f5880,f5881,f5882,f5883,f5884,f5885,f5886,f5887,f5888,f5889,f5890,f5891,f5892,f5893,f5894,f5895,f5896,f5897,f5898,f5899,f5900,f5901,f5902,f5903,f5904,f5905,f5906,f5907,f5908,f5909,f5910,f5911,f5912,f5913,f5914,f5915,f5916,f5917,f5918,f5919,f5920,f5921,f5922,f5923,f5924,f5925,f5926,f5927,f5928,f5929,f5930,f5931,f5932,f5933,f5934,f5935,f5936,f5937,f5938,f5939,f5940,f5941,f5942,f5943,f5944,f5945,f5946,f5947,f5948,f5949,f5950,f5951,f5952,f5953,f5954,f5955,f5956,f5957,f5958,f5959,f5960,f5961,f5962,f5963,f5964,f5965,f5966,f5967,f5968,f5969,f5970,f5971,f5972,f5973,f5974,f5975,f5976,f5977,f5978,f5979,f5980,f5981,f5982,f5983,f5984,f5985,f5986,f5987,f5988,f5989,f5990,f5991,f5992,f5993,f5994,f5995,f5996,f5997,f5998,f5999,f6000,f6001,f6002,f6003,f6004,f6005,f6006,f6007,f6008,f6009,f6010,f6011,f6012,f6013,f6014,f6015,f6016,f6017,f6018,f6019,f6020,f6021,f6022,f6023,f6024,f6025,f6026,f6027,f6028,f6029,f6030,f6031,f6032,f6033,f6034,f6035,f6036,f6037,f6038,f6039,f6040,f6041,f6042,f6043,f6044,f6045,f6046,f6047,f6048,f6049,f6050,f6051,f6052,f6053,f6054,f6055,f6056,f6057,f6058,f6059,f6060,f6061,f6062,f6063,f6064,f6065,f6066,f6067,f6068,f6069,f6070,f6071,f6072,f6073,f6074,f6075,f6076,f6077,f6078,f6079,f6080,f6081,f6082,f6083,f6084,f6085,f6086,f6087,f6088,f6089,f6090,f6091,f6092,f6093,f6094,f6095,f6096,f6097,f6098,f6099,f6100,f6101,f6102,f6103,f6104,f6105,f6106,f6107,f6108,f6109,f6110,f6111,f6112,f6113,f6114,f6115,f6116,f6117,f6118,f6119,f6120,f6121,f6122,f6123,f6124,f6125,f6126,f6127,f6128,f6129,f6130,f6131,f6132,f6133,f6134,f6135,f6136,f6137,f6138,f6139,f6140,f6141,f6142,f6143,f6144,f6145,f6146,f6147,f6148,f6149,f6150,f6151,f6152,f6153,f6154,f6155,f6156,f6157,f6158,f6159,f6160,f6161,f6162,f6163,f6164,f6165,f6166,f6167,f6168,f6169,f6170,f6171,f6172,f6173,f6174,f6175,f6176,f6177,f6178,f6179,f6180,f6181,f6182,f6183,f6184,f6185,f6186,f6187,f6188,f6189,f6190,f6191,f6192,f6193,f6194,f6195,f6196,f6197,f6198,f6199,f6200,f6201,f6202,f6203,f6204,f6205,f6206,f6207,f6208,f6209,f6210,f6211,f6212,f6213,f6214,f6215,f6216,f6217,f6218,f6219,f6220,f6221,f6222,f6223,f6224,f6225,f6226,f6227,f6228,f6229,f6230,f6231,f6232,f6233,f6234,f6235,f6236,f6237,f6238,f6239,f6240,f6241,f6242,f6243,f6244,f6245,f6246,f6247,f6248,f6249,f6250,f6251,f6252,f6253,f6254,f6255,f6256,f6257,f6258,f6259,f6260,f6261,f6262,f6263,f6264,f6265,f6266,f6267,f6268,f6269,f6270,f6271,f6272,f6273,f6274,f6275,f6276,f6277,f6278,f6279,f6280,f6281,f6282,f6283,f6284,f6285,f6286,f6287,f6288,f6289,f6290,f6291,f6292,f6293,f6294,f6295,f6296,f6297,f6298,f6299,f6300,f6301,f6302,f6303,f6304,f6305,f6306,f6307,f6308,f6309,f6310,f6311,f6312,f6313,f6314,f6315,f6316,f6317,f6318,f6319,f6320,f6321,f6322,f6323,f6324,f6325,f6326,f6327,f6328,f6329,f6330,f6331,f6332,f6333,f6334,f6335,f6336,f6337,f6338,f6339,f6340,f6341,f6342,f6343,f6344,f6345,f6346,f6347,f6348,f6349,f6350,f6351,f6352,f6353,f6354,f6355,f6356,f6357,f6358,f6359,f6360,f6361,f6362,f6363,f6364,f6365,f6366,f6367,f6368,f6369,f6370,f6371,f6372,f6373,f6374,f6375,f6376,f6377,f6378,f6379,f6380,f6381,f6382,f6383,f6384,f6385,f6386,f6387,f6388,f6389,f6390,f6391,f6392,f6393,f6394,f6395,f6396,f6397,f6398,f6399,f6400,f6401,f6402,f6403,f6404,f6405,f6406,f6407,f6408,f6409,f6410,f6411,f6412,f6413,f6414,f6415,f6416,f6417,f6418,f6419,f6420,f6421,f6422,f6423,f6424,f6425,f6426,f6427,f6428,f6429,f6430,f6431,f6432,f6433,f6434,f6435,f6436,f6437,f6438,f6439,f6440,f6441,f6442,f6443,f6444,f6445,f6446,f6447,f6448,f6449,f6450,f6451,f6452,f6453,f6454,f6455,f6456,f6457,f6458,f6459,f6460,f6461,f6462,f6463,f6464,f6465,f6466,f6467,f6468,f6469,f6470,f6471,f6472,f6473,f6474,f6475,f6476,f6477,f6478,f6479,f6480,f6481,f6482,f6483,f6484,f6485,f6486,f6487,f6488,f6489,f6490,f6491,f6492,f6493,f6494,f6495,f6496,f6497,f6498,f6499,f6500,f6501,f6502,f6503,f6504,f6505,f6506,f6507,f6508,f6509,f6510,f6511,f6512,f6513,f6514,f6515,f6516,f6517,f6518,f6519,f6520,f6521,f6522,f6523,f6524,f6525,f6526,f6527,f6528,f6529,f6530,f6531,f6532,f6533,f6534,f6535,f6536,f6537,f6538,f6539,f6540,f6541,f6542,f6543,f6544,f6545,f6546,f6547,f6548,f6549,f6550,f6551,f6552,f6553,f6554,f6555,f6556,f6557,f6558,f6559,f6560,f6561,f6562,f6563,f6564,f6565,f6566,f6567,f6568,f6569,f6570,f6571,f6572,f6573,f6574,f6575,f6576,f6577,f6578,f6579,f6580,f6581,f6582,f6583,f6584,f6585,f6586,f6587,f6588,f6589,f6590,f6591,f6592,f6593,f6594,f6595,f6596,f6597,f6598,f6599,f6600,f6601,f6602,f6603,f6604,f6605,f6606,f6607,f6608,f6609,f6610,f6611,f6612,f6613,f6614,f6615,f6616,f6617,f6618,f6619,f6620,f6621,f6622,f6623,f6624,f6625,f6626,f6627,f6628,f6629,f6630,f6631,f6632,f6633,f6634,f6635,f6636,f6637,f6638,f6639,f6640,f6641,f6642,f6643,f6644,f6645,f6646,f6647,f6648,f6649,f6650,f6651,f6652,f6653,f6654,f6655,f6656,f6657,f6658,f6659,f6660,f6661,f6662,f6663,f6664,f6665,f6666,f6667,f6668,f6669,f6670,f6671,f6672,f6673,f6674,f6675,f6676,f6677,f6678,f6679,f6680,f6681,f6682,f6683,f6684,f6685,f6686,f6687,f6688,f6689,f6690,f6691,f6692,f6693,f6694,f6695,f6696,f6697,f6698,f6699,f6700,f6701,f6702,f6703,f6704,f6705,f6706,f6707,f6708,f6709,f6710,f6711,f6712,f6713,f6714,f6715,f6716,f6717,f6718,f6719,f6720,f6721,f6722,f6723,f6724,f6725,f6726,f6727,f6728,f6729,f6730,f6731,f6732,f6733,f6734,f6735,f6736,f6737,f6738,f6739,f6740,f6741,f6742,f6743,f6744,f6745,f6746,f6747,f6748,f6749,f6750,f6751,f6752,f6753,f6754,f6755,f6756,f6757,f6758,f6759,f6760,f6761,f6762,f6763,f6764,f6765,f6766,f6767,f6768,f6769,f6770,f6771,f6772,f6773,f6774,f6775,f6776,f6777,f6778,f6779,f6780,f6781,f6782,f6783,f6784,f6785,f6786,f6787,f6788,f6789,f6790,f6791,f6792,f6793,f6794,f6795,f6796,f6797,f6798,f6799,f6800,f6801,f6802,f6803,f6804,f6805,f6806,f6807,f6808,f6809,f6810,f6811,f6812,f6813,f6814,f6815,f6816,f6817,f6818,f6819,f6820,f6821,f6822,f6823,f6824,f6825,f6826,f6827,f6828,f6829,f6830,f6831,f6832,f6833,f6834,f6835,f6836,f6837,f6838,f6839,f6840,f6841,f6842,f6843,f6844,f6845,f6846,f6847,f6848,f6849,f6850,f6851,f6852,f6853,f6854,f6855,f6856,f6857,f6858,f6859,f6860,f6861,f6862,f6863,f6864,f6865,f6866,f6867,f6868,f6869,f6870,f6871,f6872,f6873,f6874,f6875,f6876,f6877,f6878,f6879,f6880,f6881,f6882,f6883,f6884,f6885,f6886,f6887,f6888,f6889,f6890,f6891,f6892,f6893,f6894,f6895,f6896,f6897,f6898,f6899,f6900,f6901,f6902,f6903,f6904,f6905,f6906,f6907,f6908,f6909,f6910,f6911,f6912,f6913,f6914,f6915,f6916,f6917,f6918,f6919,f6920,f6921,f6922,f6923,f6924,f6925,f6926,f6927,f6928,f6929,f6930,f6931,f6932,f6933,f6934,f6935,f6936,f6937,f6938,f6939,f6940,f6941,f6942,f6943,f6944,f6945,f6946,f6947,f6948,f6949,f6950,f6951,f6952,f6953,f6954,f6955,f6956,f6957,f6958,f6959,f6960,f6961,f6962,f6963,f6964,f6965,f6966,f6967,f6968,f6969,f6970,f6971,f6972,f6973,f6974,f6975,f6976,f6977,f6978,f6979,f6980,f6981,f6982,f6983,f6984,f6985,f6986,f6987,f6988,f6989,f6990,f6991,f6992,f6993,f6994,f6995,f6996,f6997,f6998,f6999,f7000,f7001,f7002,f7003,f7004,f7005,f7006,f7007,f7008,f7009,f7010,f7011,f7012,f7013,f7014,f7015,f7016,f7017,f7018,f7019,f7020,f7021,f7022,f7023,f7024,f7025,f7026,f7027,f7028,f7029,f7030,f7031,f7032,f7033,f7034,f7035,f7036,f7037,f7038,f7039,f7040,f7041,f7042,f7043,f7044,f7045,f7046,f7047,f7048,f7049,f7050,f7051,f7052,f7053,f7054,f7055,f7056,f7057,f7058,f7059,f7060,f7061,f7062,f7063,f7064,f7065,f7066,f7067,f7068,f7069,f7070,f7071,f7072,f7073,f7074,f7075,f7076,f7077,f7078,f7079,f7080,f7081,f7082,f7083,f7084,f7085,f7086,f7087,f7088,f7089,f7090,f7091,f7092,f7093,f7094,f7095,f7096,f7097,f7098,f7099,f7100,f7101,f7102,f7103,f7104,f7105,f7106,f7107,f7108,f7109,f7110,f7111,f7112,f7113,f7114,f7115,f7116,f7117,f7118,f7119,f7120,f7121,f7122,f7123,f7124,f7125,f7126,f7127,f7128,f7129,f7130,f7131,f7132,f7133,f7134,f7135,f7136,f7137,f7138,f7139,f7140,f7141,f7142,f7143,f7144,f7145,f7146,f7147,f7148,f7149,f7150,f7151,f7152,f7153,f7154,f7155,f7156,f7157,f7158,f7159,f7160,f7161,f7162,f7163,f7164,f7165,f7166,f7167,f7168,f7169,f7170,f7171,f7172,f7173,f7174,f7175,f7176,f7177,f7178,f7179,f7180,f7181,f7182,f7183,f7184,f7185,f7186,f7187,f7188,f7189,f7190,f7191,f7192,f7193,f7194,f7195,f7196,f7197,f7198,f7199,f7200,f7201,f7202,f7203,f7204,f7205,f7206,f7207,f7208,f7209,f7210,f7211,f7212,f7213,f7214,f7215,f7216,f7217,f7218,f7219,f7220,f7221,f7222,f7223,f7224,f7225,f7226,f7227,f7228,f7229,f7230,f7231,f7232,f7233,f7234,f7235,f7236,f7237,f7238,f7239,f7240,f7241,f7242,f7243,f7244,f7245,f7246,f7247,f7248,f7249,f7250,f7251,f7252,f7253,f7254,f7255,f7256,f7257,f7258,f7259,f7260,f7261,f7262,f7263,f7264,f7265,f7266,f7267,f7268,f7269,f7270,f7271,f7272,f7273,f7274,f7275,f7276,f7277,f7278,f7279,f7280,f7281,f7282,f7283,f7284,f7285,f7286,f7287,f7288,f7289,f7290,f7291,f7292,f7293,f7294,f7295,f7296,f7297,f7298,f7299,f7300,f7301,f7302,f7303,f7304,f7305,f7306,f7307,f7308,f7309,f7310,f7311,f7312,f7313,f7314,f7315,f7316,f7317,f7318,f7319,f7320,f7321,f7322,f7323,f7324,f7325,f7326,f7327,f7328,f7329,f7330,f7331,f7332,f7333,f7334,f7335,f7336,f7337,f7338,f7339,f7340,f7341,f7342,f7343,f7344,f7345,f7346,f7347,f7348,f7349,f7350,f7351,f7352,f7353,f7354,f7355,f7356,f7357,f7358,f7359,f7360,f7361,f7362,f7363,f7364,f7365,f7366,f7367,f7368,f7369,f7370,f7371,f7372,f7373,f7374,f7375,f7376,f7377,f7378,f7379,f7380,f7381,f7382,f7383,f7384,f7385,f7386,f7387,f7388,f7389,f7390,f7391,f7392,f7393,f7394,f7395,f7396,f7397,f7398,f7399,f7400,f7401,f7402,f7403,f7404,f7405,f7406,f7407,f7408,f7409,f7410,f7411,f7412,f7413,f7414,f7415,f7416,f7417,f7418,f7419,f7420,f7421,f7422,f7423,f7424,f7425,f7426,f7427,f7428,f7429,f7430,f7431,f7432,f7433,f7434,f7435,f7436,f7437,f7438,f7439,f7440,f7441,f7442,f7443,f7444,f7445,f7446,f7447,f7448,f7449,f7450,f7451,f7452,f7453,f7454,f7455,f7456,f7457,f7458,f7459,f7460,f7461,f7462,f7463,f7464,f7465,f7466,f7467,f7468,f7469,f7470,f7471,f7472,f7473,f7474,f7475,f7476,f7477,f7478,f7479,f7480,f7481,f7482,f7483,f7484,f7485,f7486,f7487,f7488,f7489,f7490,f7491,f7492,f7493,f7494,f7495,f7496,f7497,f7498,f7499,f7500,f7501,f7502,f7503,f7504,f7505,f7506,f7507,f7508,f7509,f7510,f7511,f7512,f7513,f7514,f7515,f7516,f7517,f7518,f7519,f7520,f7521,f7522,f7523,f7524,f7525,f7526,f7527,f7528,f7529,f7530,f7531,f7532,f7533,f7534,f7535,f7536,f7537,f7538,f7539,f7540,f7541,f7542,f7543,f7544,f7545,f7546,f7547,f7548,f7549,f7550,f7551,f7552,f7553,f7554,f7555,f7556,f7557,f7558,f7559,f7560,f7561,f7562,f7563,f7564,f7565,f7566,f7567,f7568,f7569,f7570,f7571,f7572,f7573,f7574,f7575,f7576,f7577,f7578,f7579,f7580,f7581,f7582,f7583,f7584,f7585,f7586,f7587,f7588,f7589,f7590,f7591,f7592,f7593,f7594,f7595,f7596,f7597,f7598,f7599,f7600,f7601,f7602,f7603,f7604,f7605,f7606,f7607,f7608,f7609,f7610,f7611,f7612,f7613,f7614,f7615,f7616,f7617,f7618,f7619,f7620,f7621,f7622,f7623,f7624,f7625,f7626,f7627,f7628,f7629,f7630,f7631,f7632,f7633,f7634,f7635,f7636,f7637,f7638,f7639,f7640,f7641,f7642,f7643,f7644,f7645,f7646,f7647,f7648,f7649,f7650,f7651,f7652,f7653,f7654,f7655,f7656,f7657,f7658,f7659,f7660,f7661,f7662,f7663,f7664,f7665,f7666,f7667,f7668,f7669,f7670,f7671,f7672,f7673,f7674,f7675,f7676,f7677,f7678,f7679,f7680,f7681,f7682,f7683,f7684,f7685,f7686,f7687,f7688,f7689,f7690,f7691,f7692,f7693,f7694,f7695,f7696,f7697,f7698,f7699,f7700,f7701,f7702,f7703,f7704,f7705,f7706,f7707,f7708,f7709,f7710,f7711,f7712,f7713,f7714,f7715,f7716,f7717,f7718,f7719,f7720,f7721,f7722,f7723,f7724,f7725,f7726,f7727,f7728,f7729,f7730,f7731,f7732,f7733,f7734,f7735,f7736,f7737,f7738,f7739,f7740,f7741,f7742,f7743,f7744,f7745,f7746,f7747,f7748,f7749,f7750,f7751,f7752,f7753,f7754,f7755,f7756,f7757,f7758,f7759,f7760,f7761,f7762,f7763,f7764,f7765,f7766,f7767,f7768,f7769,f7770,f7771,f7772,f7773,f7774,f7775,f7776,f7777,f7778,f7779,f7780,f7781,f7782,f7783,f7784,f7785,f7786,f7787,f7788,f7789,f7790,f7791,f7792,f7793,f7794,f7795,f7796,f7797,f7798,f7799,f7800,f7801,f7802,f7803,f7804,f7805,f7806,f7807,f7808,f7809,f7810,f7811,f7812,f7813,f7814,f7815,f7816,f7817,f7818,f7819,f7820,f7821,f7822,f7823,f7824,f7825,f7826,f7827,f7828,f7829,f7830,f7831,f7832,f7833,f7834,f7835,f7836,f7837,f7838,f7839,f7840,f7841,f7842,f7843,f7844,f7845,f7846,f7847,f7848,f7849,f7850,f7851,f7852,f7853,f7854,f7855,f7856,f7857,f7858,f7859,f7860,f7861,f7862,f7863,f7864,f7865,f7866,f7867,f7868,f7869,f7870,f7871,f7872,f7873,f7874,f7875,f7876,f7877,f7878,f7879,f7880,f7881,f7882,f7883,f7884,f7885,f7886,f7887,f7888,f7889,f7890,f7891,f7892,f7893,f7894,f7895,f7896,f7897,f7898,f7899,f7900,f7901,f7902,f7903,f7904,f7905,f7906,f7907,f7908,f7909,f7910,f7911,f7912,f7913,f7914,f7915,f7916,f7917,f7918,f7919,f7920,f7921,f7922,f7923,f7924,f7925,f7926,f7927,f7928,f7929,f7930,f7931,f7932,f7933,f7934,f7935,f7936,f7937,f7938,f7939,f7940,f7941,f7942,f7943,f7944,f7945,f7946,f7947,f7948,f7949,f7950,f7951,f7952,f7953,f7954,f7955,f7956,f7957,f7958,f7959,f7960,f7961,f7962,f7963,f7964,f7965,f7966,f7967,f7968,f7969,f7970,f7971,f7972,f7973,f7974,f7975,f7976,f7977,f7978,f7979,f7980,f7981,f7982,f7983,f7984,f7985,f7986,f7987,f7988,f7989,f7990,f7991,f7992,f7993,f7994,f7995,f7996,f7997,f7998,f7999,f8000,f8001,f8002,f8003,f8004,f8005,f8006,f8007,f8008,f8009,f8010,f8011,f8012,f8013,f8014,f8015,f8016,f8017,f8018,f8019,f8020,f8021,f8022,f8023,f8024,f8025,f8026,f8027,f8028,f8029,f8030,f8031,f8032,f8033,f8034,f8035,f8036,f8037,f8038,f8039,f8040,f8041,f8042,f8043,f8044,f8045,f8046,f8047,f8048,f8049,f8050,f8051,f8052,f8053,f8054,f8055,f8056,f8057,f8058,f8059,f8060,f8061,f8062,f8063,f8064,f8065,f8066,f8067,f8068,f8069,f8070,f8071,f8072,f8073,f8074,f8075,f8076,f8077,f8078,f8079,f8080,f8081,f8082,f8083,f8084,f8085,f8086,f8087,f8088,f8089,f8090,f8091,f8092,f8093,f8094,f8095,f8096,f8097,f8098,f8099,f8100,f8101,f8102,f8103,f8104,f8105,f8106,f8107,f8108,f8109,f8110,f8111,f8112,f8113,f8114,f8115,f8116,f8117,f8118,f8119,f8120,f8121,f8122,f8123,f8124,f8125,f8126,f8127,f8128,f8129,f8130,f8131,f8132,f8133,f8134,f8135,f8136,f8137,f8138,f8139,f8140,f8141,f8142,f8143,f8144,f8145,f8146,f8147,f8148,f8149,f8150,f8151,f8152,f8153,f8154,f8155,f8156,f8157,f8158,f8159,f8160,f8161,f8162,f8163,f8164,f8165,f8166,f8167,f8168,f8169,f8170,f8171,f8172,f8173,f8174,f8175,f8176,f8177,f8178,f8179,f8180,f8181,f8182,f8183,f8184,f8185,f8186,f8187,f8188,f8189,f8190,f8191,f8192,f8193,f8194,f8195,f8196,f8197,f8198,f8199,f8200,f8201,f8202,f8203,f8204,f8205,f8206,f8207,f8208,f8209,f8210,f8211,f8212,f8213,f8214,f8215,f8216,f8217,f8218,f8219,f8220,f8221,f8222,f8223,f8224,f8225,f8226,f8227,f8228,f8229,f8230,f8231,f8232,f8233,f8234,f8235,f8236,f8237,f8238,f8239,f8240,f8241,f8242,f8243,f8244,f8245,f8246,f8247,f8248,f8249,f8250,f8251,f8252,f8253,f8254,f8255,f8256,f8257,f8258,f8259,f8260,f8261,f8262,f8263,f8264,f8265,f8266,f8267,f8268,f8269,f8270,f8271,f8272,f8273,f8274,f8275,f8276,f8277,f8278,f8279,f8280,f8281,f8282,f8283,f8284,f8285,f8286,f8287,f8288,f8289,f8290,f8291,f8292,f8293,f8294,f8295,f8296,f8297,f8298,f8299,f8300,f8301,f8302,f8303,f8304,f8305,f8306,f8307,f8308,f8309,f8310,f8311,f8312,f8313,f8314,f8315,f8316,f8317,f8318,f8319,f8320,f8321,f8322,f8323,f8324,f8325,f8326,f8327,f8328,f8329,f8330,f8331,f8332,f8333,f8334,f8335,f8336,f8337,f8338,f8339,f8340,f8341,f8342,f8343,f8344,f8345,f8346,f8347,f8348,f8349,f8350,f8351,f8352,f8353,f8354,f8355,f8356,f8357,f8358,f8359,f8360,f8361,f8362,f8363,f8364,f8365,f8366,f8367,f8368,f8369,f8370,f8371,f8372,f8373,f8374,f8375,f8376,f8377,f8378,f8379,f8380,f8381,f8382,f8383,f8384,f8385,f8386,f8387,f8388,f8389,f8390,f8391,f8392,f8393,f8394,f8395,f8396,f8397,f8398,f8399,f8400,f8401,f8402,f8403,f8404,f8405,f8406,f8407,f8408,f8409,f8410,f8411,f8412,f8413,f8414,f8415,f8416,f8417,f8418,f8419,f8420,f8421,f8422,f8423,f8424,f8425,f8426,f8427,f8428,f8429,f8430,f8431,f8432,f8433,f8434,f8435,f8436,f8437,f8438,f8439,f8440,f8441,f8442,f8443,f8444,f8445,f8446,f8447,f8448,f8449,f8450,f8451,f8452,f8453,f8454,f8455,f8456,f8457,f8458,f8459,f8460,f8461,f8462,f8463,f8464,f8465,f8466,f8467,f8468,f8469,f8470,f8471,f8472,f8473,f8474,f8475,f8476,f8477,f8478,f8479,f8480,f8481,f8482,f8483,f8484,f8485,f8486,f8487,f8488,f8489,f8490,f8491,f8492,f8493,f8494,f8495,f8496,f8497,f8498,f8499,f8500,f8501,f8502,f8503,f8504,f8505,f8506,f8507,f8508,f8509,f8510,f8511,f8512,f8513,f8514,f8515,f8516,f8517,f8518,f8519,f8520,f8521,f8522,f8523,f8524,f8525,f8526,f8527,f8528,f8529,f8530,f8531,f8532,f8533,f8534,f8535,f8536,f8537,f8538,f8539,f8540,f8541,f8542,f8543,f8544,f8545,f8546,f8547,f8548,f8549,f8550,f8551,f8552,f8553,f8554,f8555,f8556,f8557,f8558,f8559,f8560,f8561,f8562,f8563,f8564,f8565,f8566,f8567,f8568,f8569,f8570,f8571,f8572,f8573,f8574,f8575,f8576,f8577,f8578,f8579,f8580,f8581,f8582,f8583,f8584,f8585,f8586,f8587,f8588,f8589,f8590,f8591,f8592,f8593,f8594,f8595,f8596,f8597,f8598,f8599,f8600,f8601,f8602,f8603,f8604,f8605,f8606,f8607,f8608,f8609,f8610,f8611,f8612,f8613,f8614,f8615,f8616,f8617,f8618,f8619,f8620,f8621,f8622,f8623,f8624,f8625,f8626,f8627,f8628,f8629,f8630,f8631,f8632,f8633,f8634,f8635,f8636,f8637,f8638,f8639,f8640,f8641,f8642,f8643,f8644,f8645,f8646,f8647,f8648,f8649,f8650,f8651,f8652,f8653,f8654,f8655,f8656,f8657,f8658,f8659,f8660,f8661,f8662,f8663,f8664,f8665,f8666,f8667,f8668,f8669,f8670,f8671,f8672,f8673,f8674,f8675,f8676,f8677,f8678,f8679,f8680,f8681,f8682,f8683,f8684,f8685,f8686,f8687,f8688,f8689,f8690,f8691,f8692,f8693,f8694,f8695,f8696,f8697,f8698,f8699,f8700,f8701,f8702,f8703,f8704,f8705,f8706,f8707,f8708,f8709,f8710,f8711,f8712,f8713,f8714,f8715,f8716,f8717,f8718,f8719,f8720,f8721,f8722,f8723,f8724,f8725,f8726,f8727,f8728,f8729,f8730,f8731,f8732,f8733,f8734,f8735,f8736,f8737,f8738,f8739,f8740,f8741,f8742,f8743,f8744,f8745,f8746,f8747,f8748,f8749,f8750,f8751,f8752,f8753,f8754,f8755,f8756,f8757,f8758,f8759,f8760,f8761,f8762,f8763,f8764,f8765,f8766,f8767,f8768,f8769,f8770,f8771,f8772,f8773,f8774,f8775,f8776,f8777,f8778,f8779,f8780,f8781,f8782,f8783,f8784,f8785,f8786,f8787,f8788,f8789,f8790,f8791,f8792,f8793,f8794,f8795,f8796,f8797,f8798,f8799,f8800,f8801,f8802,f8803,f8804,f8805,f8806,f8807,f8808,f8809,f8810,f8811,f8812,f8813,f8814,f8815,f8816,f8817,f8818,f8819,f8820,f8821,f8822,f8823,f8824,f8825,f8826,f8827,f8828,f8829,f8830,f8831,f8832,f8833,f8834,f8835,f8836,f8837,f8838,f8839,f8840,f8841,f8842,f8843,f8844,f8845,f8846,f8847,f8848,f8849,f8850,f8851,f8852,f8853,f8854,f8855,f8856,f8857,f8858,f8859,f8860,f8861,f8862,f8863,f8864,f8865,f8866,f8867,f8868,f8869,f8870,f8871,f8872,f8873,f8874,f8875,f8876,f8877,f8878,f8879,f8880,f8881,f8882,f8883,f8884,f8885,f8886,f8887,f8888,f8889,f8890,f8891,f8892,f8893,f8894,f8895,f8896,f8897,f8898,f8899,f8900,f8901,f8902,f8903,f8904,f8905,f8906,f8907,f8908,f8909,f8910,f8911,f8912,f8913,f8914,f8915,f8916,f8917,f8918,f8919,f8920,f8921,f8922,f8923,f8924,f8925,f8926,f8927,f8928,f8929,f8930,f8931,f8932,f8933,f8934,f8935,f8936,f8937,f8938,f8939,f8940,f8941,f8942,f8943,f8944,f8945,f8946,f8947,f8948,f8949,f8950,f8951,f8952,f8953,f8954,f8955,f8956,f8957,f8958,f8959,f8960,f8961,f8962,f8963,f8964,f8965,f8966,f8967,f8968,f8969,f8970,f8971,f8972,f8973,f8974,f8975,f8976,f8977,f8978,f8979,f8980,f8981,f8982,f8983,f8984,f8985,f8986,f8987,f8988,f8989,f8990,f8991,f8992,f8993,f8994,f8995,f8996,f8997,f8998,f8999,f9000,f9001,f9002,f9003,f9004,f9005,f9006,f9007,f9008,f9009,f9010,f9011,f9012,f9013,f9014,f9015,f9016,f9017,f9018,f9019,f9020,f9021,f9022,f9023,f9024,f9025,f9026,f9027,f9028,f9029,f9030,f9031,f9032,f9033,f9034,f9035,f9036,f9037,f9038,f9039,f9040,f9041,f9042,f9043,f9044,f9045,f9046,f9047,f9048,f9049,f9050,f9051,f9052,f9053,f9054,f9055,f9056,f9057,f9058,f9059,f9060,f9061,f9062,f9063,f9064,f9065,f9066,f9067,f9068,f9069,f9070,f9071,f9072,f9073,f9074,f9075,f9076,f9077,f9078,f9079,f9080,f9081,f9082,f9083,f9084,f9085,f9086,f9087,f9088,f9089,f9090,f9091,f9092,f9093,f9094,f9095,f9096,f9097,f9098,f9099,f9100,f9101,f9102,f9103,f9104,f9105,f9106,f9107,f9108,f9109,f9110,f9111,f9112,f9113,f9114,f9115,f9116,f9117,f9118,f9119,f9120,f9121,f9122,f9123,f9124,f9125,f9126,f9127,f9128,f9129,f9130,f9131,f9132,f9133,f9134,f9135,f9136,f9137,f9138,f9139,f9140,f9141,f9142,f9143,f9144,f9145,f9146,f9147,f9148,f9149,f9150,f9151,f9152,f9153,f9154,f9155,f9156,f9157,f9158,f9159,f9160,f9161,f9162,f9163,f9164,f9165,f9166,f9167,f9168,f9169,f9170,f9171,f9172,f9173,f9174,f9175,f9176,f9177,f9178,f9179,f9180,f9181,f9182,f9183,f9184,f9185,f9186,f9187,f9188,f9189,f9190,f9191,f9192,f9193,f9194,f9195,f9196,f9197,f9198,f9199,f9200,f9201,f9202,f9203,f9204,f9205,f9206,f9207,f9208,f9209,f9210,f9211,f9212,f9213,f9214,f9215,f9216,f9217,f9218,f9219,f9220,f9221,f9222,f9223,f9224,f9225,f9226,f9227,f9228,f9229,f9230,f9231,f9232,f9233,f9234,f9235,f9236,f9237,f9238,f9239,f9240,f9241,f9242,f9243,f9244,f9245,f9246,f9247,f9248,f9249,f9250,f9251,f9252,f9253,f9254,f9255,f9256,f9257,f9258,f9259,f9260,f9261,f9262,f9263,f9264,f9265,f9266,f9267,f9268,f9269,f9270,f9271,f9272,f9273,f9274,f9275,f9276,f9277,f9278,f9279,f9280,f9281,f9282,f9283,f9284,f9285,f9286,f9287,f9288,f9289,f9290,f9291,f9292,f9293,f9294,f9295,f9296,f9297,f9298,f9299,f9300,f9301,f9302,f9303,f9304,f9305,f9306,f9307,f9308,f9309,f9310,f9311,f9312,f9313,f9314,f9315,f9316,f9317,f9318,f9319,f9320,f9321,f9322,f9323,f9324,f9325,f9326,f9327,f9328,f9329,f9330,f9331,f9332,f9333,f9334,f9335,f9336,f9337,f9338,f9339,f9340,f9341,f9342,f9343,f9344,f9345,f9346,f9347,f9348,f9349,f9350,f9351,f9352,f9353,f9354,f9355,f9356,f9357,f9358,f9359,f9360,f9361,f9362,f9363,f9364,f9365,f9366,f9367,f9368,f9369,f9370,f9371,f9372,f9373,f9374,f9375,f9376,f9377,f9378,f9379,f9380,f9381,f9382,f9383,f9384,f9385,f9386,f9387,f9388,f9389,f9390,f9391,f9392,f9393,f9394,f9395,f9396,f9397,f9398,f9399,f9400,f9401,f9402,f9403,f9404,f9405,f9406,f9407,f9408,f9409,f9410,f9411,f9412,f9413,f9414,f9415,f9416,f9417,f9418,f9419,f9420,f9421,f9422,f9423,f9424,f9425,f9426,f9427,f9428,f9429,f9430,f9431,f9432,f9433,f9434,f9435,f9436,f9437,f9438,f9439,f9440,f9441,f9442,f9443,f9444,f9445,f9446,f9447,f9448,f9449,f9450,f9451,f9452,f9453,f9454,f9455,f9456,f9457,f9458,f9459,f9460,f9461,f9462,f9463,f9464,f9465,f9466,f9467,f9468,f9469,f9470,f9471,f9472,f9473,f9474,f9475,f9476,f9477,f9478,f9479,f9480,f9481,f9482,f9483,f9484,f9485,f9486,f9487,f9488,f9489,f9490,f9491,f9492,f9493,f9494,f9495,f9496,f9497,f9498,f9499,f9500,f9501,f9502,f9503,f9504,f9505,f9506,f9507,f9508,f9509,f9510,f9511,f9512,f9513,f9514,f9515,f9516,f9517,f9518,f9519,f9520,f9521,f9522,f9523,f9524,f9525,f9526,f9527,f9528,f9529,f9530,f9531,f9532,f9533,f9534,f9535,f9536,f9537,f9538,f9539,f9540,f9541,f9542,f9543,f9544,f9545,f9546,f9547,f9548,f9549,f9550,f9551,f9552,f9553,f9554,f9555,f9556,f9557,f9558,f9559,f9560,f9561,f9562,f9563,f9564,f9565,f9566,f9567,f9568,f9569,f9570,f9571,f9572,f9573,f9574,f9575,f9576,f9577,f9578,f9579,f9580,f9581,f9582,f9583,f9584,f9585,f9586,f9587,f9588,f9589,f9590,f9591,f9592,f9593,f9594,f9595,f9596,f9597,f9598,f9599,f9600,f9601,f9602,f9603,f9604,f9605,f9606,f9607,f9608,f9609,f9610,f9611,f9612,f9613,f9614,f9615,f9616,f9617,f9618,f9619,f9620,f9621,f9622,f9623,f9624,f9625,f9626,f9627,f9628,f9629,f9630,f9631,f9632,f9633,f9634,f9635,f9636,f9637,f9638,f9639,f9640,f9641,f9642,f9643,f9644,f9645,f9646,f9647,f9648,f9649,f9650,f9651,f9652,f9653,f9654,f9655,f9656,f9657,f9658,f9659,f9660,f9661,f9662,f9663,f9664,f9665,f9666,f9667,f9668,f9669,f9670,f9671,f9672,f9673,f9674,f9675,f9676,f9677,f9678,f9679,f9680,f9681,f9682,f9683,f9684,f9685,f9686,f9687,f9688,f9689,f9690,f9691,f9692,f9693,f9694,f9695,f9696,f9697,f9698,f9699,f9700,f9701,f9702,f9703,f9704,f9705,f9706,f9707,f9708,f9709,f9710,f9711,f9712,f9713,f9714,f9715,f9716,f9717,f9718,f9719,f9720,f9721,f9722,f9723,f9724,f9725,f9726,f9727,f9728,f9729,f9730,f9731,f9732,f9733,f9734,f9735,f9736,f9737,f9738,f9739,f9740,f9741,f9742,f9743,f9744,f9745,f9746,f9747,f9748,f9749,f9750,f9751,f9752,f9753,f9754,f9755,f9756,f9757,f9758,f9759,f9760,f9761,f9762,f9763,f9764,f9765,f9766,f9767,f9768,f9769,f9770,f9771,f9772,f9773,f9774,f9775,f9776,f9777,f9778,f9779,f9780,f9781,f9782,f9783,f9784,f9785,f9786,f9787,f9788,f9789,f9790,f9791,f9792,f9793,f9794,f9795,f9796,f9797,f9798,f9799,f9800,f9801,f9802,f9803,f9804,f9805,f9806,f9807,f9808,f9809,f9810,f9811,f9812,f9813,f9814,f9815,f9816,f9817,f9818,f9819,f9820,f9821,f9822,f9823,f9824,f9825,f9826,f9827,f9828,f9829,f9830,f9831,f9832,f9833,f9834,f9835,f9836,f9837,f9838,f9839,f9840,f9841,f9842,f9843,f9844,f9845,f9846,f9847,f9848,f9849,f9850,f9851,f9852,f9853,f9854,f9855,f9856,f9857,f9858,f9859,f9860,f9861,f9862,f9863,f9864,f9865,f9866,f9867,f9868,f9869,f9870,f9871,f9872,f9873,f9874,f9875,f9876,f9877,f9878,f9879,f9880,f9881,f9882,f9883,f9884,f9885,f9886,f9887,f9888,f9889,f9890,f9891,f9892,f9893,f9894,f9895,f9896,f9897,f9898,f9899,f9900,f9901,f9902,f9903,f9904,f9905,f9906,f9907,f9908,f9909,f9910,f9911,f9912,f9913,f9914,f9915,f9916,f9917,f9918,f9919,f9920,f9921,f9922,f9923,f9924,f9925,f9926,f9927,f9928,f9929,f9930,f9931,f9932,f9933,f9934,f9935,f9936,f9937,f9938,f9939,f9940,f9941,f9942,f9943,f9944,f9945,f9946,f9947,f9948,f9949,f9950,f9951,f9952,f9953,f9954,f9955,f9956,f9957,f9958,f9959,f9960,f9961,f9962,f9963,f9964,f9965,f9966,f9967,f9968,f9969,f9970,f9971,f9972,f9973,f9974,f9975,f9976,f9977,f9978,f9979,f9980,f9981,f9982,f9983,f9984,f9985,f9986,f9987,f9988,f9989,f9990,f9991,f9992,f9993,f9994,f9995,f9996,f9997,f9998} + +File: 1 [ { (f0),(f1),(f2),(f3),(f4),(f5),(f6),(f7),(f8),(f9),(f10),(f11),(f12),(f13),(f14),(f15),(f16),(f17),(f18),(f19),(f20),(f21),(f22),(f23),(f24),(f25),(f26),(f27),(f28),(f29),(f30),(f31),(f32),(f33),(f34),(f35),(f36),(f37),(f38),(f39),(f40),(f41),(f42),(f43),(f44),(f45),(f46),(f47),(f48),(f49),(f50),(f51),(f52),(f53),(f54),(f55),(f56),(f57),(f58),(f59),(f60),(f61),(f62),(f63),(f64),(f65),(f66),(f67),(f68),(f69),(f70),(f71),(f72),(f73),(f74),(f75),(f76),(f77),(f78),(f79),(f80),(f81),(f82),(f83),(f84),(f85),(f86),(f87),(f88),(f89),(f90),(f91),(f92),(f93),(f94),(f95),(f96),(f97),(f98),(f99),(f100),(f101),(f102),(f103),(f104),(f105),(f106),(f107),(f108),(f109),(f110),(f111),(f112),(f113),(f114),(f115),(f116),(f117),(f118),(f119),(f120),(f121),(f122),(f123),(f124),(f125),(f126),(f127),(f128),(f129),(f130),(f131),(f132),(f133),(f134),(f135),(f136),(f137),(f138),(f139),(f140),(f141),(f142),(f143),(f144),(f145),(f146),(f147),(f148),(f149),(f150),(f151),(f152),(f153),(f154),(f155),(f156),(f157),(f158),(f159),(f160),(f161),(f162),(f163),(f164),(f165),(f166),(f167),(f168),(f169),(f170),(f171),(f172),(f173),(f174),(f175),(f176),(f177),(f178),(f179),(f180),(f181),(f182),(f183),(f184),(f185),(f186),(f187),(f188),(f189),(f190),(f191),(f192),(f193),(f194),(f195),(f196),(f197),(f198),(f199),(f200),(f201),(f202),(f203),(f204),(f205),(f206),(f207),(f208),(f209),(f210),(f211),(f212),(f213),(f214),(f215),(f216),(f217),(f218),(f219),(f220),(f221),(f222),(f223),(f224),(f225),(f226),(f227),(f228),(f229),(f230),(f231),(f232),(f233),(f234),(f235),(f236),(f237),(f238),(f239),(f240),(f241),(f242),(f243),(f244),(f245),(f246),(f247),(f248),(f249),(f250),(f251),(f252),(f253),(f254),(f255),(f256),(f257),(f258),(f259),(f260),(f261),(f262),(f263),(f264),(f265),(f266),(f267),(f268),(f269),(f270),(f271),(f272),(f273),(f274),(f275),(f276),(f277),(f278),(f279),(f280),(f281),(f282),(f283),(f284),(f285),(f286),(f287),(f288),(f289),(f290),(f291),(f292),(f293),(f294),(f295),(f296),(f297),(f298),(f299),(f300),(f301),(f302),(f303),(f304),(f305),(f306),(f307),(f308),(f309),(f310),(f311),(f312),(f313),(f314),(f315),(f316),(f317),(f318),(f319),(f320),(f321),(f322),(f323),(f324),(f325),(f326),(f327),(f328),(f329),(f330),(f331),(f332),(f333),(f334),(f335),(f336),(f337),(f338),(f339),(f340),(f341),(f342),(f343),(f344),(f345),(f346),(f347),(f348),(f349),(f350),(f351),(f352),(f353),(f354),(f355),(f356),(f357),(f358),(f359),(f360),(f361),(f362),(f363),(f364),(f365),(f366),(f367),(f368),(f369),(f370),(f371),(f372),(f373),(f374),(f375),(f376),(f377),(f378),(f379),(f380),(f381),(f382),(f383),(f384),(f385),(f386),(f387),(f388),(f389),(f390),(f391),(f392),(f393),(f394),(f395),(f396),(f397),(f398),(f399),(f400),(f401),(f402),(f403),(f404),(f405),(f406),(f407),(f408),(f409),(f410),(f411),(f412),(f413),(f414),(f415),(f416),(f417),(f418),(f419),(f420),(f421),(f422),(f423),(f424),(f425),(f426),(f427),(f428),(f429),(f430),(f431),(f432),(f433),(f434),(f435),(f436),(f437),(f438),(f439),(f440),(f441),(f442),(f443),(f444),(f445),(f446),(f447),(f448),(f449),(f450),(f451),(f452),(f453),(f454),(f455),(f456),(f457),(f458),(f459),(f460),(f461),(f462),(f463),(f464),(f465),(f466),(f467),(f468),(f469),(f470),(f471),(f472),(f473),(f474),(f475),(f476),(f477),(f478),(f479),(f480),(f481),(f482),(f483),(f484),(f485),(f486),(f487),(f488),(f489),(f490),(f491),(f492),(f493),(f494),(f495),(f496),(f497),(f498),(f499),(f500),(f501),(f502),(f503),(f504),(f505),(f506),(f507),(f508),(f509),(f510),(f511),(f512),(f513),(f514),(f515),(f516),(f517),(f518),(f519),(f520),(f521),(f522),(f523),(f524),(f525),(f526),(f527),(f528),(f529),(f530),(f531),(f532),(f533),(f534),(f535),(f536),(f537),(f538),(f539),(f540),(f541),(f542),(f543),(f544),(f545),(f546),(f547),(f548),(f549),(f550),(f551),(f552),(f553),(f554),(f555),(f556),(f557),(f558),(f559),(f560),(f561),(f562),(f563),(f564),(f565),(f566),(f567),(f568),(f569),(f570),(f571),(f572),(f573),(f574),(f575),(f576),(f577),(f578),(f579),(f580),(f581),(f582),(f583),(f584),(f585),(f586),(f587),(f588),(f589),(f590),(f591),(f592),(f593),(f594),(f595),(f596),(f597),(f598),(f599),(f600),(f601),(f602),(f603),(f604),(f605),(f606),(f607),(f608),(f609),(f610),(f611),(f612),(f613),(f614),(f615),(f616),(f617),(f618),(f619),(f620),(f621),(f622),(f623),(f624),(f625),(f626),(f627),(f628),(f629),(f630),(f631),(f632),(f633),(f634),(f635),(f636),(f637),(f638),(f639),(f640),(f641),(f642),(f643),(f644),(f645),(f646),(f647),(f648),(f649),(f650),(f651),(f652),(f653),(f654),(f655),(f656),(f657),(f658),(f659),(f660),(f661),(f662),(f663),(f664),(f665),(f666),(f667),(f668),(f669),(f670),(f671),(f672),(f673),(f674),(f675),(f676),(f677),(f678),(f679),(f680),(f681),(f682),(f683),(f684),(f685),(f686),(f687),(f688),(f689),(f690),(f691),(f692),(f693),(f694),(f695),(f696),(f697),(f698),(f699),(f700),(f701),(f702),(f703),(f704),(f705),(f706),(f707),(f708),(f709),(f710),(f711),(f712),(f713),(f714),(f715),(f716),(f717),(f718),(f719),(f720),(f721),(f722),(f723),(f724),(f725),(f726),(f727),(f728),(f729),(f730),(f731),(f732),(f733),(f734),(f735),(f736),(f737),(f738),(f739),(f740),(f741),(f742),(f743),(f744),(f745),(f746),(f747),(f748),(f749),(f750),(f751),(f752),(f753),(f754),(f755),(f756),(f757),(f758),(f759),(f760),(f761),(f762),(f763),(f764),(f765),(f766),(f767),(f768),(f769),(f770),(f771),(f772),(f773),(f774),(f775),(f776),(f777),(f778),(f779),(f780),(f781),(f782),(f783),(f784),(f785),(f786),(f787),(f788),(f789),(f790),(f791),(f792),(f793),(f794),(f795),(f796),(f797),(f798),(f799),(f800),(f801),(f802),(f803),(f804),(f805),(f806),(f807),(f808),(f809),(f810),(f811),(f812),(f813),(f814),(f815),(f816),(f817),(f818),(f819),(f820),(f821),(f822),(f823),(f824),(f825),(f826),(f827),(f828),(f829),(f830),(f831),(f832),(f833),(f834),(f835),(f836),(f837),(f838),(f839),(f840),(f841),(f842),(f843),(f844),(f845),(f846),(f847),(f848),(f849),(f850),(f851),(f852),(f853),(f854),(f855),(f856),(f857),(f858),(f859),(f860),(f861),(f862),(f863),(f864),(f865),(f866),(f867),(f868),(f869),(f870),(f871),(f872),(f873),(f874),(f875),(f876),(f877),(f878),(f879),(f880),(f881),(f882),(f883),(f884),(f885),(f886),(f887),(f888),(f889),(f890),(f891),(f892),(f893),(f894),(f895),(f896),(f897),(f898),(f899),(f900),(f901),(f902),(f903),(f904),(f905),(f906),(f907),(f908),(f909),(f910),(f911),(f912),(f913),(f914),(f915),(f916),(f917),(f918),(f919),(f920),(f921),(f922),(f923),(f924),(f925),(f926),(f927),(f928),(f929),(f930),(f931),(f932),(f933),(f934),(f935),(f936),(f937),(f938),(f939),(f940),(f941),(f942),(f943),(f944),(f945),(f946),(f947),(f948),(f949),(f950),(f951),(f952),(f953),(f954),(f955),(f956),(f957),(f958),(f959),(f960),(f961),(f962),(f963),(f964),(f965),(f966),(f967),(f968),(f969),(f970),(f971),(f972),(f973),(f974),(f975),(f976),(f977),(f978),(f979),(f980),(f981),(f982),(f983),(f984),(f985),(f986),(f987),(f988),(f989),(f990),(f991),(f992),(f993),(f994),(f995),(f996),(f997),(f998),(f999),(f1000),(f1001),(f1002),(f1003),(f1004),(f1005),(f1006),(f1007),(f1008),(f1009),(f1010),(f1011),(f1012),(f1013),(f1014),(f1015),(f1016),(f1017),(f1018),(f1019),(f1020),(f1021),(f1022),(f1023),(f1024),(f1025),(f1026),(f1027),(f1028),(f1029),(f1030),(f1031),(f1032),(f1033),(f1034),(f1035),(f1036),(f1037),(f1038),(f1039),(f1040),(f1041),(f1042),(f1043),(f1044),(f1045),(f1046),(f1047),(f1048),(f1049),(f1050),(f1051),(f1052),(f1053),(f1054),(f1055),(f1056),(f1057),(f1058),(f1059),(f1060),(f1061),(f1062),(f1063),(f1064),(f1065),(f1066),(f1067),(f1068),(f1069),(f1070),(f1071),(f1072),(f1073),(f1074),(f1075),(f1076),(f1077),(f1078),(f1079),(f1080),(f1081),(f1082),(f1083),(f1084),(f1085),(f1086),(f1087),(f1088),(f1089),(f1090),(f1091),(f1092),(f1093),(f1094),(f1095),(f1096),(f1097),(f1098),(f1099),(f1100),(f1101),(f1102),(f1103),(f1104),(f1105),(f1106),(f1107),(f1108),(f1109),(f1110),(f1111),(f1112),(f1113),(f1114),(f1115),(f1116),(f1117),(f1118),(f1119),(f1120),(f1121),(f1122),(f1123),(f1124),(f1125),(f1126),(f1127),(f1128),(f1129),(f1130),(f1131),(f1132),(f1133),(f1134),(f1135),(f1136),(f1137),(f1138),(f1139),(f1140),(f1141),(f1142),(f1143),(f1144),(f1145),(f1146),(f1147),(f1148),(f1149),(f1150),(f1151),(f1152),(f1153),(f1154),(f1155),(f1156),(f1157),(f1158),(f1159),(f1160),(f1161),(f1162),(f1163),(f1164),(f1165),(f1166),(f1167),(f1168),(f1169),(f1170),(f1171),(f1172),(f1173),(f1174),(f1175),(f1176),(f1177),(f1178),(f1179),(f1180),(f1181),(f1182),(f1183),(f1184),(f1185),(f1186),(f1187),(f1188),(f1189),(f1190),(f1191),(f1192),(f1193),(f1194),(f1195),(f1196),(f1197),(f1198),(f1199),(f1200),(f1201),(f1202),(f1203),(f1204),(f1205),(f1206),(f1207),(f1208),(f1209),(f1210),(f1211),(f1212),(f1213),(f1214),(f1215),(f1216),(f1217),(f1218),(f1219),(f1220),(f1221),(f1222),(f1223),(f1224),(f1225),(f1226),(f1227),(f1228),(f1229),(f1230),(f1231),(f1232),(f1233),(f1234),(f1235),(f1236),(f1237),(f1238),(f1239),(f1240),(f1241),(f1242),(f1243),(f1244),(f1245),(f1246),(f1247),(f1248),(f1249),(f1250),(f1251),(f1252),(f1253),(f1254),(f1255),(f1256),(f1257),(f1258),(f1259),(f1260),(f1261),(f1262),(f1263),(f1264),(f1265),(f1266),(f1267),(f1268),(f1269),(f1270),(f1271),(f1272),(f1273),(f1274),(f1275),(f1276),(f1277),(f1278),(f1279),(f1280),(f1281),(f1282),(f1283),(f1284),(f1285),(f1286),(f1287),(f1288),(f1289),(f1290),(f1291),(f1292),(f1293),(f1294),(f1295),(f1296),(f1297),(f1298),(f1299),(f1300),(f1301),(f1302),(f1303),(f1304),(f1305),(f1306),(f1307),(f1308),(f1309),(f1310),(f1311),(f1312),(f1313),(f1314),(f1315),(f1316),(f1317),(f1318),(f1319),(f1320),(f1321),(f1322),(f1323),(f1324),(f1325),(f1326),(f1327),(f1328),(f1329),(f1330),(f1331),(f1332),(f1333),(f1334),(f1335),(f1336),(f1337),(f1338),(f1339),(f1340),(f1341),(f1342),(f1343),(f1344),(f1345),(f1346),(f1347),(f1348),(f1349),(f1350),(f1351),(f1352),(f1353),(f1354),(f1355),(f1356),(f1357),(f1358),(f1359),(f1360),(f1361),(f1362),(f1363),(f1364),(f1365),(f1366),(f1367),(f1368),(f1369),(f1370),(f1371),(f1372),(f1373),(f1374),(f1375),(f1376),(f1377),(f1378),(f1379),(f1380),(f1381),(f1382),(f1383),(f1384),(f1385),(f1386),(f1387),(f1388),(f1389),(f1390),(f1391),(f1392),(f1393),(f1394),(f1395),(f1396),(f1397),(f1398),(f1399),(f1400),(f1401),(f1402),(f1403),(f1404),(f1405),(f1406),(f1407),(f1408),(f1409),(f1410),(f1411),(f1412),(f1413),(f1414),(f1415),(f1416),(f1417),(f1418),(f1419),(f1420),(f1421),(f1422),(f1423),(f1424),(f1425),(f1426),(f1427),(f1428),(f1429),(f1430),(f1431),(f1432),(f1433),(f1434),(f1435),(f1436),(f1437),(f1438),(f1439),(f1440),(f1441),(f1442),(f1443),(f1444),(f1445),(f1446),(f1447),(f1448),(f1449),(f1450),(f1451),(f1452),(f1453),(f1454),(f1455),(f1456),(f1457),(f1458),(f1459),(f1460),(f1461),(f1462),(f1463),(f1464),(f1465),(f1466),(f1467),(f1468),(f1469),(f1470),(f1471),(f1472),(f1473),(f1474),(f1475),(f1476),(f1477),(f1478),(f1479),(f1480),(f1481),(f1482),(f1483),(f1484),(f1485),(f1486),(f1487),(f1488),(f1489),(f1490),(f1491),(f1492),(f1493),(f1494),(f1495),(f1496),(f1497),(f1498),(f1499),(f1500),(f1501),(f1502),(f1503),(f1504),(f1505),(f1506),(f1507),(f1508),(f1509),(f1510),(f1511),(f1512),(f1513),(f1514),(f1515),(f1516),(f1517),(f1518),(f1519),(f1520),(f1521),(f1522),(f1523),(f1524),(f1525),(f1526),(f1527),(f1528),(f1529),(f1530),(f1531),(f1532),(f1533),(f1534),(f1535),(f1536),(f1537),(f1538),(f1539),(f1540),(f1541),(f1542),(f1543),(f1544),(f1545),(f1546),(f1547),(f1548),(f1549),(f1550),(f1551),(f1552),(f1553),(f1554),(f1555),(f1556),(f1557),(f1558),(f1559),(f1560),(f1561),(f1562),(f1563),(f1564),(f1565),(f1566),(f1567),(f1568),(f1569),(f1570),(f1571),(f1572),(f1573),(f1574),(f1575),(f1576),(f1577),(f1578),(f1579),(f1580),(f1581),(f1582),(f1583),(f1584),(f1585),(f1586),(f1587),(f1588),(f1589),(f1590),(f1591),(f1592),(f1593),(f1594),(f1595),(f1596),(f1597),(f1598),(f1599),(f1600),(f1601),(f1602),(f1603),(f1604),(f1605),(f1606),(f1607),(f1608),(f1609),(f1610),(f1611),(f1612),(f1613),(f1614),(f1615),(f1616),(f1617),(f1618),(f1619),(f1620),(f1621),(f1622),(f1623),(f1624),(f1625),(f1626),(f1627),(f1628),(f1629),(f1630),(f1631),(f1632),(f1633),(f1634),(f1635),(f1636),(f1637),(f1638),(f1639),(f1640),(f1641),(f1642),(f1643),(f1644),(f1645),(f1646),(f1647),(f1648),(f1649),(f1650),(f1651),(f1652),(f1653),(f1654),(f1655),(f1656),(f1657),(f1658),(f1659),(f1660),(f1661),(f1662),(f1663),(f1664),(f1665),(f1666),(f1667),(f1668),(f1669),(f1670),(f1671),(f1672),(f1673),(f1674),(f1675),(f1676),(f1677),(f1678),(f1679),(f1680),(f1681),(f1682),(f1683),(f1684),(f1685),(f1686),(f1687),(f1688),(f1689),(f1690),(f1691),(f1692),(f1693),(f1694),(f1695),(f1696),(f1697),(f1698),(f1699),(f1700),(f1701),(f1702),(f1703),(f1704),(f1705),(f1706),(f1707),(f1708),(f1709),(f1710),(f1711),(f1712),(f1713),(f1714),(f1715),(f1716),(f1717),(f1718),(f1719),(f1720),(f1721),(f1722),(f1723),(f1724),(f1725),(f1726),(f1727),(f1728),(f1729),(f1730),(f1731),(f1732),(f1733),(f1734),(f1735),(f1736),(f1737),(f1738),(f1739),(f1740),(f1741),(f1742),(f1743),(f1744),(f1745),(f1746),(f1747),(f1748),(f1749),(f1750),(f1751),(f1752),(f1753),(f1754),(f1755),(f1756),(f1757),(f1758),(f1759),(f1760),(f1761),(f1762),(f1763),(f1764),(f1765),(f1766),(f1767),(f1768),(f1769),(f1770),(f1771),(f1772),(f1773),(f1774),(f1775),(f1776),(f1777),(f1778),(f1779),(f1780),(f1781),(f1782),(f1783),(f1784),(f1785),(f1786),(f1787),(f1788),(f1789),(f1790),(f1791),(f1792),(f1793),(f1794),(f1795),(f1796),(f1797),(f1798),(f1799),(f1800),(f1801),(f1802),(f1803),(f1804),(f1805),(f1806),(f1807),(f1808),(f1809),(f1810),(f1811),(f1812),(f1813),(f1814),(f1815),(f1816),(f1817),(f1818),(f1819),(f1820),(f1821),(f1822),(f1823),(f1824),(f1825),(f1826),(f1827),(f1828),(f1829),(f1830),(f1831),(f1832),(f1833),(f1834),(f1835),(f1836),(f1837),(f1838),(f1839),(f1840),(f1841),(f1842),(f1843),(f1844),(f1845),(f1846),(f1847),(f1848),(f1849),(f1850),(f1851),(f1852),(f1853),(f1854),(f1855),(f1856),(f1857),(f1858),(f1859),(f1860),(f1861),(f1862),(f1863),(f1864),(f1865),(f1866),(f1867),(f1868),(f1869),(f1870),(f1871),(f1872),(f1873),(f1874),(f1875),(f1876),(f1877),(f1878),(f1879),(f1880),(f1881),(f1882),(f1883),(f1884),(f1885),(f1886),(f1887),(f1888),(f1889),(f1890),(f1891),(f1892),(f1893),(f1894),(f1895),(f1896),(f1897),(f1898),(f1899),(f1900),(f1901),(f1902),(f1903),(f1904),(f1905),(f1906),(f1907),(f1908),(f1909),(f1910),(f1911),(f1912),(f1913),(f1914),(f1915),(f1916),(f1917),(f1918),(f1919),(f1920),(f1921),(f1922),(f1923),(f1924),(f1925),(f1926),(f1927),(f1928),(f1929),(f1930),(f1931),(f1932),(f1933),(f1934),(f1935),(f1936),(f1937),(f1938),(f1939),(f1940),(f1941),(f1942),(f1943),(f1944),(f1945),(f1946),(f1947),(f1948),(f1949),(f1950),(f1951),(f1952),(f1953),(f1954),(f1955),(f1956),(f1957),(f1958),(f1959),(f1960),(f1961),(f1962),(f1963),(f1964),(f1965),(f1966),(f1967),(f1968),(f1969),(f1970),(f1971),(f1972),(f1973),(f1974),(f1975),(f1976),(f1977),(f1978),(f1979),(f1980),(f1981),(f1982),(f1983),(f1984),(f1985),(f1986),(f1987),(f1988),(f1989),(f1990),(f1991),(f1992),(f1993),(f1994),(f1995),(f1996),(f1997),(f1998),(f1999),(f2000),(f2001),(f2002),(f2003),(f2004),(f2005),(f2006),(f2007),(f2008),(f2009),(f2010),(f2011),(f2012),(f2013),(f2014),(f2015),(f2016),(f2017),(f2018),(f2019),(f2020),(f2021),(f2022),(f2023),(f2024),(f2025),(f2026),(f2027),(f2028),(f2029),(f2030),(f2031),(f2032),(f2033),(f2034),(f2035),(f2036),(f2037),(f2038),(f2039),(f2040),(f2041),(f2042),(f2043),(f2044),(f2045),(f2046),(f2047),(f2048),(f2049),(f2050),(f2051),(f2052),(f2053),(f2054),(f2055),(f2056),(f2057),(f2058),(f2059),(f2060),(f2061),(f2062),(f2063),(f2064),(f2065),(f2066),(f2067),(f2068),(f2069),(f2070),(f2071),(f2072),(f2073),(f2074),(f2075),(f2076),(f2077),(f2078),(f2079),(f2080),(f2081),(f2082),(f2083),(f2084),(f2085),(f2086),(f2087),(f2088),(f2089),(f2090),(f2091),(f2092),(f2093),(f2094),(f2095),(f2096),(f2097),(f2098),(f2099),(f2100),(f2101),(f2102),(f2103),(f2104),(f2105),(f2106),(f2107),(f2108),(f2109),(f2110),(f2111),(f2112),(f2113),(f2114),(f2115),(f2116),(f2117),(f2118),(f2119),(f2120),(f2121),(f2122),(f2123),(f2124),(f2125),(f2126),(f2127),(f2128),(f2129),(f2130),(f2131),(f2132),(f2133),(f2134),(f2135),(f2136),(f2137),(f2138),(f2139),(f2140),(f2141),(f2142),(f2143),(f2144),(f2145),(f2146),(f2147),(f2148),(f2149),(f2150),(f2151),(f2152),(f2153),(f2154),(f2155),(f2156),(f2157),(f2158),(f2159),(f2160),(f2161),(f2162),(f2163),(f2164),(f2165),(f2166),(f2167),(f2168),(f2169),(f2170),(f2171),(f2172),(f2173),(f2174),(f2175),(f2176),(f2177),(f2178),(f2179),(f2180),(f2181),(f2182),(f2183),(f2184),(f2185),(f2186),(f2187),(f2188),(f2189),(f2190),(f2191),(f2192),(f2193),(f2194),(f2195),(f2196),(f2197),(f2198),(f2199),(f2200),(f2201),(f2202),(f2203),(f2204),(f2205),(f2206),(f2207),(f2208),(f2209),(f2210),(f2211),(f2212),(f2213),(f2214),(f2215),(f2216),(f2217),(f2218),(f2219),(f2220),(f2221),(f2222),(f2223),(f2224),(f2225),(f2226),(f2227),(f2228),(f2229),(f2230),(f2231),(f2232),(f2233),(f2234),(f2235),(f2236),(f2237),(f2238),(f2239),(f2240),(f2241),(f2242),(f2243),(f2244),(f2245),(f2246),(f2247),(f2248),(f2249),(f2250),(f2251),(f2252),(f2253),(f2254),(f2255),(f2256),(f2257),(f2258),(f2259),(f2260),(f2261),(f2262),(f2263),(f2264),(f2265),(f2266),(f2267),(f2268),(f2269),(f2270),(f2271),(f2272),(f2273),(f2274),(f2275),(f2276),(f2277),(f2278),(f2279),(f2280),(f2281),(f2282),(f2283),(f2284),(f2285),(f2286),(f2287),(f2288),(f2289),(f2290),(f2291),(f2292),(f2293),(f2294),(f2295),(f2296),(f2297),(f2298),(f2299),(f2300),(f2301),(f2302),(f2303),(f2304),(f2305),(f2306),(f2307),(f2308),(f2309),(f2310),(f2311),(f2312),(f2313),(f2314),(f2315),(f2316),(f2317),(f2318),(f2319),(f2320),(f2321),(f2322),(f2323),(f2324),(f2325),(f2326),(f2327),(f2328),(f2329),(f2330),(f2331),(f2332),(f2333),(f2334),(f2335),(f2336),(f2337),(f2338),(f2339),(f2340),(f2341),(f2342),(f2343),(f2344),(f2345),(f2346),(f2347),(f2348),(f2349),(f2350),(f2351),(f2352),(f2353),(f2354),(f2355),(f2356),(f2357),(f2358),(f2359),(f2360),(f2361),(f2362),(f2363),(f2364),(f2365),(f2366),(f2367),(f2368),(f2369),(f2370),(f2371),(f2372),(f2373),(f2374),(f2375),(f2376),(f2377),(f2378),(f2379),(f2380),(f2381),(f2382),(f2383),(f2384),(f2385),(f2386),(f2387),(f2388),(f2389),(f2390),(f2391),(f2392),(f2393),(f2394),(f2395),(f2396),(f2397),(f2398),(f2399),(f2400),(f2401),(f2402),(f2403),(f2404),(f2405),(f2406),(f2407),(f2408),(f2409),(f2410),(f2411),(f2412),(f2413),(f2414),(f2415),(f2416),(f2417),(f2418),(f2419),(f2420),(f2421),(f2422),(f2423),(f2424),(f2425),(f2426),(f2427),(f2428),(f2429),(f2430),(f2431),(f2432),(f2433),(f2434),(f2435),(f2436),(f2437),(f2438),(f2439),(f2440),(f2441),(f2442),(f2443),(f2444),(f2445),(f2446),(f2447),(f2448),(f2449),(f2450),(f2451),(f2452),(f2453),(f2454),(f2455),(f2456),(f2457),(f2458),(f2459),(f2460),(f2461),(f2462),(f2463),(f2464),(f2465),(f2466),(f2467),(f2468),(f2469),(f2470),(f2471),(f2472),(f2473),(f2474),(f2475),(f2476),(f2477),(f2478),(f2479),(f2480),(f2481),(f2482),(f2483),(f2484),(f2485),(f2486),(f2487),(f2488),(f2489),(f2490),(f2491),(f2492),(f2493),(f2494),(f2495),(f2496),(f2497),(f2498),(f2499),(f2500),(f2501),(f2502),(f2503),(f2504),(f2505),(f2506),(f2507),(f2508),(f2509),(f2510),(f2511),(f2512),(f2513),(f2514),(f2515),(f2516),(f2517),(f2518),(f2519),(f2520),(f2521),(f2522),(f2523),(f2524),(f2525),(f2526),(f2527),(f2528),(f2529),(f2530),(f2531),(f2532),(f2533),(f2534),(f2535),(f2536),(f2537),(f2538),(f2539),(f2540),(f2541),(f2542),(f2543),(f2544),(f2545),(f2546),(f2547),(f2548),(f2549),(f2550),(f2551),(f2552),(f2553),(f2554),(f2555),(f2556),(f2557),(f2558),(f2559),(f2560),(f2561),(f2562),(f2563),(f2564),(f2565),(f2566),(f2567),(f2568),(f2569),(f2570),(f2571),(f2572),(f2573),(f2574),(f2575),(f2576),(f2577),(f2578),(f2579),(f2580),(f2581),(f2582),(f2583),(f2584),(f2585),(f2586),(f2587),(f2588),(f2589),(f2590),(f2591),(f2592),(f2593),(f2594),(f2595),(f2596),(f2597),(f2598),(f2599),(f2600),(f2601),(f2602),(f2603),(f2604),(f2605),(f2606),(f2607),(f2608),(f2609),(f2610),(f2611),(f2612),(f2613),(f2614),(f2615),(f2616),(f2617),(f2618),(f2619),(f2620),(f2621),(f2622),(f2623),(f2624),(f2625),(f2626),(f2627),(f2628),(f2629),(f2630),(f2631),(f2632),(f2633),(f2634),(f2635),(f2636),(f2637),(f2638),(f2639),(f2640),(f2641),(f2642),(f2643),(f2644),(f2645),(f2646),(f2647),(f2648),(f2649),(f2650),(f2651),(f2652),(f2653),(f2654),(f2655),(f2656),(f2657),(f2658),(f2659),(f2660),(f2661),(f2662),(f2663),(f2664),(f2665),(f2666),(f2667),(f2668),(f2669),(f2670),(f2671),(f2672),(f2673),(f2674),(f2675),(f2676),(f2677),(f2678),(f2679),(f2680),(f2681),(f2682),(f2683),(f2684),(f2685),(f2686),(f2687),(f2688),(f2689),(f2690),(f2691),(f2692),(f2693),(f2694),(f2695),(f2696),(f2697),(f2698),(f2699),(f2700),(f2701),(f2702),(f2703),(f2704),(f2705),(f2706),(f2707),(f2708),(f2709),(f2710),(f2711),(f2712),(f2713),(f2714),(f2715),(f2716),(f2717),(f2718),(f2719),(f2720),(f2721),(f2722),(f2723),(f2724),(f2725),(f2726),(f2727),(f2728),(f2729),(f2730),(f2731),(f2732),(f2733),(f2734),(f2735),(f2736),(f2737),(f2738),(f2739),(f2740),(f2741),(f2742),(f2743),(f2744),(f2745),(f2746),(f2747),(f2748),(f2749),(f2750),(f2751),(f2752),(f2753),(f2754),(f2755),(f2756),(f2757),(f2758),(f2759),(f2760),(f2761),(f2762),(f2763),(f2764),(f2765),(f2766),(f2767),(f2768),(f2769),(f2770),(f2771),(f2772),(f2773),(f2774),(f2775),(f2776),(f2777),(f2778),(f2779),(f2780),(f2781),(f2782),(f2783),(f2784),(f2785),(f2786),(f2787),(f2788),(f2789),(f2790),(f2791),(f2792),(f2793),(f2794),(f2795),(f2796),(f2797),(f2798),(f2799),(f2800),(f2801),(f2802),(f2803),(f2804),(f2805),(f2806),(f2807),(f2808),(f2809),(f2810),(f2811),(f2812),(f2813),(f2814),(f2815),(f2816),(f2817),(f2818),(f2819),(f2820),(f2821),(f2822),(f2823),(f2824),(f2825),(f2826),(f2827),(f2828),(f2829),(f2830),(f2831),(f2832),(f2833),(f2834),(f2835),(f2836),(f2837),(f2838),(f2839),(f2840),(f2841),(f2842),(f2843),(f2844),(f2845),(f2846),(f2847),(f2848),(f2849),(f2850),(f2851),(f2852),(f2853),(f2854),(f2855),(f2856),(f2857),(f2858),(f2859),(f2860),(f2861),(f2862),(f2863),(f2864),(f2865),(f2866),(f2867),(f2868),(f2869),(f2870),(f2871),(f2872),(f2873),(f2874),(f2875),(f2876),(f2877),(f2878),(f2879),(f2880),(f2881),(f2882),(f2883),(f2884),(f2885),(f2886),(f2887),(f2888),(f2889),(f2890),(f2891),(f2892),(f2893),(f2894),(f2895),(f2896),(f2897),(f2898),(f2899),(f2900),(f2901),(f2902),(f2903),(f2904),(f2905),(f2906),(f2907),(f2908),(f2909),(f2910),(f2911),(f2912),(f2913),(f2914),(f2915),(f2916),(f2917),(f2918),(f2919),(f2920),(f2921),(f2922),(f2923),(f2924),(f2925),(f2926),(f2927),(f2928),(f2929),(f2930),(f2931),(f2932),(f2933),(f2934),(f2935),(f2936),(f2937),(f2938),(f2939),(f2940),(f2941),(f2942),(f2943),(f2944),(f2945),(f2946),(f2947),(f2948),(f2949),(f2950),(f2951),(f2952),(f2953),(f2954),(f2955),(f2956),(f2957),(f2958),(f2959),(f2960),(f2961),(f2962),(f2963),(f2964),(f2965),(f2966),(f2967),(f2968),(f2969),(f2970),(f2971),(f2972),(f2973),(f2974),(f2975),(f2976),(f2977),(f2978),(f2979),(f2980),(f2981),(f2982),(f2983),(f2984),(f2985),(f2986),(f2987),(f2988),(f2989),(f2990),(f2991),(f2992),(f2993),(f2994),(f2995),(f2996),(f2997),(f2998),(f2999),(f3000),(f3001),(f3002),(f3003),(f3004),(f3005),(f3006),(f3007),(f3008),(f3009),(f3010),(f3011),(f3012),(f3013),(f3014),(f3015),(f3016),(f3017),(f3018),(f3019),(f3020),(f3021),(f3022),(f3023),(f3024),(f3025),(f3026),(f3027),(f3028),(f3029),(f3030),(f3031),(f3032),(f3033),(f3034),(f3035),(f3036),(f3037),(f3038),(f3039),(f3040),(f3041),(f3042),(f3043),(f3044),(f3045),(f3046),(f3047),(f3048),(f3049),(f3050),(f3051),(f3052),(f3053),(f3054),(f3055),(f3056),(f3057),(f3058),(f3059),(f3060),(f3061),(f3062),(f3063),(f3064),(f3065),(f3066),(f3067),(f3068),(f3069),(f3070),(f3071),(f3072),(f3073),(f3074),(f3075),(f3076),(f3077),(f3078),(f3079),(f3080),(f3081),(f3082),(f3083),(f3084),(f3085),(f3086),(f3087),(f3088),(f3089),(f3090),(f3091),(f3092),(f3093),(f3094),(f3095),(f3096),(f3097),(f3098),(f3099),(f3100),(f3101),(f3102),(f3103),(f3104),(f3105),(f3106),(f3107),(f3108),(f3109),(f3110),(f3111),(f3112),(f3113),(f3114),(f3115),(f3116),(f3117),(f3118),(f3119),(f3120),(f3121),(f3122),(f3123),(f3124),(f3125),(f3126),(f3127),(f3128),(f3129),(f3130),(f3131),(f3132),(f3133),(f3134),(f3135),(f3136),(f3137),(f3138),(f3139),(f3140),(f3141),(f3142),(f3143),(f3144),(f3145),(f3146),(f3147),(f3148),(f3149),(f3150),(f3151),(f3152),(f3153),(f3154),(f3155),(f3156),(f3157),(f3158),(f3159),(f3160),(f3161),(f3162),(f3163),(f3164),(f3165),(f3166),(f3167),(f3168),(f3169),(f3170),(f3171),(f3172),(f3173),(f3174),(f3175),(f3176),(f3177),(f3178),(f3179),(f3180),(f3181),(f3182),(f3183),(f3184),(f3185),(f3186),(f3187),(f3188),(f3189),(f3190),(f3191),(f3192),(f3193),(f3194),(f3195),(f3196),(f3197),(f3198),(f3199),(f3200),(f3201),(f3202),(f3203),(f3204),(f3205),(f3206),(f3207),(f3208),(f3209),(f3210),(f3211),(f3212),(f3213),(f3214),(f3215),(f3216),(f3217),(f3218),(f3219),(f3220),(f3221),(f3222),(f3223),(f3224),(f3225),(f3226),(f3227),(f3228),(f3229),(f3230),(f3231),(f3232),(f3233),(f3234),(f3235),(f3236),(f3237),(f3238),(f3239),(f3240),(f3241),(f3242),(f3243),(f3244),(f3245),(f3246),(f3247),(f3248),(f3249),(f3250),(f3251),(f3252),(f3253),(f3254),(f3255),(f3256),(f3257),(f3258),(f3259),(f3260),(f3261),(f3262),(f3263),(f3264),(f3265),(f3266),(f3267),(f3268),(f3269),(f3270),(f3271),(f3272),(f3273),(f3274),(f3275),(f3276),(f3277),(f3278),(f3279),(f3280),(f3281),(f3282),(f3283),(f3284),(f3285),(f3286),(f3287),(f3288),(f3289),(f3290),(f3291),(f3292),(f3293),(f3294),(f3295),(f3296),(f3297),(f3298),(f3299),(f3300),(f3301),(f3302),(f3303),(f3304),(f3305),(f3306),(f3307),(f3308),(f3309),(f3310),(f3311),(f3312),(f3313),(f3314),(f3315),(f3316),(f3317),(f3318),(f3319),(f3320),(f3321),(f3322),(f3323),(f3324),(f3325),(f3326),(f3327),(f3328),(f3329),(f3330),(f3331),(f3332),(f3333),(f3334),(f3335),(f3336),(f3337),(f3338),(f3339),(f3340),(f3341),(f3342),(f3343),(f3344),(f3345),(f3346),(f3347),(f3348),(f3349),(f3350),(f3351),(f3352),(f3353),(f3354),(f3355),(f3356),(f3357),(f3358),(f3359),(f3360),(f3361),(f3362),(f3363),(f3364),(f3365),(f3366),(f3367),(f3368),(f3369),(f3370),(f3371),(f3372),(f3373),(f3374),(f3375),(f3376),(f3377),(f3378),(f3379),(f3380),(f3381),(f3382),(f3383),(f3384),(f3385),(f3386),(f3387),(f3388),(f3389),(f3390),(f3391),(f3392),(f3393),(f3394),(f3395),(f3396),(f3397),(f3398),(f3399),(f3400),(f3401),(f3402),(f3403),(f3404),(f3405),(f3406),(f3407),(f3408),(f3409),(f3410),(f3411),(f3412),(f3413),(f3414),(f3415),(f3416),(f3417),(f3418),(f3419),(f3420),(f3421),(f3422),(f3423),(f3424),(f3425),(f3426),(f3427),(f3428),(f3429),(f3430),(f3431),(f3432),(f3433),(f3434),(f3435),(f3436),(f3437),(f3438),(f3439),(f3440),(f3441),(f3442),(f3443),(f3444),(f3445),(f3446),(f3447),(f3448),(f3449),(f3450),(f3451),(f3452),(f3453),(f3454),(f3455),(f3456),(f3457),(f3458),(f3459),(f3460),(f3461),(f3462),(f3463),(f3464),(f3465),(f3466),(f3467),(f3468),(f3469),(f3470),(f3471),(f3472),(f3473),(f3474),(f3475),(f3476),(f3477),(f3478),(f3479),(f3480),(f3481),(f3482),(f3483),(f3484),(f3485),(f3486),(f3487),(f3488),(f3489),(f3490),(f3491),(f3492),(f3493),(f3494),(f3495),(f3496),(f3497),(f3498),(f3499),(f3500),(f3501),(f3502),(f3503),(f3504),(f3505),(f3506),(f3507),(f3508),(f3509),(f3510),(f3511),(f3512),(f3513),(f3514),(f3515),(f3516),(f3517),(f3518),(f3519),(f3520),(f3521),(f3522),(f3523),(f3524),(f3525),(f3526),(f3527),(f3528),(f3529),(f3530),(f3531),(f3532),(f3533),(f3534),(f3535),(f3536),(f3537),(f3538),(f3539),(f3540),(f3541),(f3542),(f3543),(f3544),(f3545),(f3546),(f3547),(f3548),(f3549),(f3550),(f3551),(f3552),(f3553),(f3554),(f3555),(f3556),(f3557),(f3558),(f3559),(f3560),(f3561),(f3562),(f3563),(f3564),(f3565),(f3566),(f3567),(f3568),(f3569),(f3570),(f3571),(f3572),(f3573),(f3574),(f3575),(f3576),(f3577),(f3578),(f3579),(f3580),(f3581),(f3582),(f3583),(f3584),(f3585),(f3586),(f3587),(f3588),(f3589),(f3590),(f3591),(f3592),(f3593),(f3594),(f3595),(f3596),(f3597),(f3598),(f3599),(f3600),(f3601),(f3602),(f3603),(f3604),(f3605),(f3606),(f3607),(f3608),(f3609),(f3610),(f3611),(f3612),(f3613),(f3614),(f3615),(f3616),(f3617),(f3618),(f3619),(f3620),(f3621),(f3622),(f3623),(f3624),(f3625),(f3626),(f3627),(f3628),(f3629),(f3630),(f3631),(f3632),(f3633),(f3634),(f3635),(f3636),(f3637),(f3638),(f3639),(f3640),(f3641),(f3642),(f3643),(f3644),(f3645),(f3646),(f3647),(f3648),(f3649),(f3650),(f3651),(f3652),(f3653),(f3654),(f3655),(f3656),(f3657),(f3658),(f3659),(f3660),(f3661),(f3662),(f3663),(f3664),(f3665),(f3666),(f3667),(f3668),(f3669),(f3670),(f3671),(f3672),(f3673),(f3674),(f3675),(f3676),(f3677),(f3678),(f3679),(f3680),(f3681),(f3682),(f3683),(f3684),(f3685),(f3686),(f3687),(f3688),(f3689),(f3690),(f3691),(f3692),(f3693),(f3694),(f3695),(f3696),(f3697),(f3698),(f3699),(f3700),(f3701),(f3702),(f3703),(f3704),(f3705),(f3706),(f3707),(f3708),(f3709),(f3710),(f3711),(f3712),(f3713),(f3714),(f3715),(f3716),(f3717),(f3718),(f3719),(f3720),(f3721),(f3722),(f3723),(f3724),(f3725),(f3726),(f3727),(f3728),(f3729),(f3730),(f3731),(f3732),(f3733),(f3734),(f3735),(f3736),(f3737),(f3738),(f3739),(f3740),(f3741),(f3742),(f3743),(f3744),(f3745),(f3746),(f3747),(f3748),(f3749),(f3750),(f3751),(f3752),(f3753),(f3754),(f3755),(f3756),(f3757),(f3758),(f3759),(f3760),(f3761),(f3762),(f3763),(f3764),(f3765),(f3766),(f3767),(f3768),(f3769),(f3770),(f3771),(f3772),(f3773),(f3774),(f3775),(f3776),(f3777),(f3778),(f3779),(f3780),(f3781),(f3782),(f3783),(f3784),(f3785),(f3786),(f3787),(f3788),(f3789),(f3790),(f3791),(f3792),(f3793),(f3794),(f3795),(f3796),(f3797),(f3798),(f3799),(f3800),(f3801),(f3802),(f3803),(f3804),(f3805),(f3806),(f3807),(f3808),(f3809),(f3810),(f3811),(f3812),(f3813),(f3814),(f3815),(f3816),(f3817),(f3818),(f3819),(f3820),(f3821),(f3822),(f3823),(f3824),(f3825),(f3826),(f3827),(f3828),(f3829),(f3830),(f3831),(f3832),(f3833),(f3834),(f3835),(f3836),(f3837),(f3838),(f3839),(f3840),(f3841),(f3842),(f3843),(f3844),(f3845),(f3846),(f3847),(f3848),(f3849),(f3850),(f3851),(f3852),(f3853),(f3854),(f3855),(f3856),(f3857),(f3858),(f3859),(f3860),(f3861),(f3862),(f3863),(f3864),(f3865),(f3866),(f3867),(f3868),(f3869),(f3870),(f3871),(f3872),(f3873),(f3874),(f3875),(f3876),(f3877),(f3878),(f3879),(f3880),(f3881),(f3882),(f3883),(f3884),(f3885),(f3886),(f3887),(f3888),(f3889),(f3890),(f3891),(f3892),(f3893),(f3894),(f3895),(f3896),(f3897),(f3898),(f3899),(f3900),(f3901),(f3902),(f3903),(f3904),(f3905),(f3906),(f3907),(f3908),(f3909),(f3910),(f3911),(f3912),(f3913),(f3914),(f3915),(f3916),(f3917),(f3918),(f3919),(f3920),(f3921),(f3922),(f3923),(f3924),(f3925),(f3926),(f3927),(f3928),(f3929),(f3930),(f3931),(f3932),(f3933),(f3934),(f3935),(f3936),(f3937),(f3938),(f3939),(f3940),(f3941),(f3942),(f3943),(f3944),(f3945),(f3946),(f3947),(f3948),(f3949),(f3950),(f3951),(f3952),(f3953),(f3954),(f3955),(f3956),(f3957),(f3958),(f3959),(f3960),(f3961),(f3962),(f3963),(f3964),(f3965),(f3966),(f3967),(f3968),(f3969),(f3970),(f3971),(f3972),(f3973),(f3974),(f3975),(f3976),(f3977),(f3978),(f3979),(f3980),(f3981),(f3982),(f3983),(f3984),(f3985),(f3986),(f3987),(f3988),(f3989),(f3990),(f3991),(f3992),(f3993),(f3994),(f3995),(f3996),(f3997),(f3998),(f3999),(f4000),(f4001),(f4002),(f4003),(f4004),(f4005),(f4006),(f4007),(f4008),(f4009),(f4010),(f4011),(f4012),(f4013),(f4014),(f4015),(f4016),(f4017),(f4018),(f4019),(f4020),(f4021),(f4022),(f4023),(f4024),(f4025),(f4026),(f4027),(f4028),(f4029),(f4030),(f4031),(f4032),(f4033),(f4034),(f4035),(f4036),(f4037),(f4038),(f4039),(f4040),(f4041),(f4042),(f4043),(f4044),(f4045),(f4046),(f4047),(f4048),(f4049),(f4050),(f4051),(f4052),(f4053),(f4054),(f4055),(f4056),(f4057),(f4058),(f4059),(f4060),(f4061),(f4062),(f4063),(f4064),(f4065),(f4066),(f4067),(f4068),(f4069),(f4070),(f4071),(f4072),(f4073),(f4074),(f4075),(f4076),(f4077),(f4078),(f4079),(f4080),(f4081),(f4082),(f4083),(f4084),(f4085),(f4086),(f4087),(f4088),(f4089),(f4090),(f4091),(f4092),(f4093),(f4094),(f4095),(f4096),(f4097),(f4098),(f4099),(f4100),(f4101),(f4102),(f4103),(f4104),(f4105),(f4106),(f4107),(f4108),(f4109),(f4110),(f4111),(f4112),(f4113),(f4114),(f4115),(f4116),(f4117),(f4118),(f4119),(f4120),(f4121),(f4122),(f4123),(f4124),(f4125),(f4126),(f4127),(f4128),(f4129),(f4130),(f4131),(f4132),(f4133),(f4134),(f4135),(f4136),(f4137),(f4138),(f4139),(f4140),(f4141),(f4142),(f4143),(f4144),(f4145),(f4146),(f4147),(f4148),(f4149),(f4150),(f4151),(f4152),(f4153),(f4154),(f4155),(f4156),(f4157),(f4158),(f4159),(f4160),(f4161),(f4162),(f4163),(f4164),(f4165),(f4166),(f4167),(f4168),(f4169),(f4170),(f4171),(f4172),(f4173),(f4174),(f4175),(f4176),(f4177),(f4178),(f4179),(f4180),(f4181),(f4182),(f4183),(f4184),(f4185),(f4186),(f4187),(f4188),(f4189),(f4190),(f4191),(f4192),(f4193),(f4194),(f4195),(f4196),(f4197),(f4198),(f4199),(f4200),(f4201),(f4202),(f4203),(f4204),(f4205),(f4206),(f4207),(f4208),(f4209),(f4210),(f4211),(f4212),(f4213),(f4214),(f4215),(f4216),(f4217),(f4218),(f4219),(f4220),(f4221),(f4222),(f4223),(f4224),(f4225),(f4226),(f4227),(f4228),(f4229),(f4230),(f4231),(f4232),(f4233),(f4234),(f4235),(f4236),(f4237),(f4238),(f4239),(f4240),(f4241),(f4242),(f4243),(f4244),(f4245),(f4246),(f4247),(f4248),(f4249),(f4250),(f4251),(f4252),(f4253),(f4254),(f4255),(f4256),(f4257),(f4258),(f4259),(f4260),(f4261),(f4262),(f4263),(f4264),(f4265),(f4266),(f4267),(f4268),(f4269),(f4270),(f4271),(f4272),(f4273),(f4274),(f4275),(f4276),(f4277),(f4278),(f4279),(f4280),(f4281),(f4282),(f4283),(f4284),(f4285),(f4286),(f4287),(f4288),(f4289),(f4290),(f4291),(f4292),(f4293),(f4294),(f4295),(f4296),(f4297),(f4298),(f4299),(f4300),(f4301),(f4302),(f4303),(f4304),(f4305),(f4306),(f4307),(f4308),(f4309),(f4310),(f4311),(f4312),(f4313),(f4314),(f4315),(f4316),(f4317),(f4318),(f4319),(f4320),(f4321),(f4322),(f4323),(f4324),(f4325),(f4326),(f4327),(f4328),(f4329),(f4330),(f4331),(f4332),(f4333),(f4334),(f4335),(f4336),(f4337),(f4338),(f4339),(f4340),(f4341),(f4342),(f4343),(f4344),(f4345),(f4346),(f4347),(f4348),(f4349),(f4350),(f4351),(f4352),(f4353),(f4354),(f4355),(f4356),(f4357),(f4358),(f4359),(f4360),(f4361),(f4362),(f4363),(f4364),(f4365),(f4366),(f4367),(f4368),(f4369),(f4370),(f4371),(f4372),(f4373),(f4374),(f4375),(f4376),(f4377),(f4378),(f4379),(f4380),(f4381),(f4382),(f4383),(f4384),(f4385),(f4386),(f4387),(f4388),(f4389),(f4390),(f4391),(f4392),(f4393),(f4394),(f4395),(f4396),(f4397),(f4398),(f4399),(f4400),(f4401),(f4402),(f4403),(f4404),(f4405),(f4406),(f4407),(f4408),(f4409),(f4410),(f4411),(f4412),(f4413),(f4414),(f4415),(f4416),(f4417),(f4418),(f4419),(f4420),(f4421),(f4422),(f4423),(f4424),(f4425),(f4426),(f4427),(f4428),(f4429),(f4430),(f4431),(f4432),(f4433),(f4434),(f4435),(f4436),(f4437),(f4438),(f4439),(f4440),(f4441),(f4442),(f4443),(f4444),(f4445),(f4446),(f4447),(f4448),(f4449),(f4450),(f4451),(f4452),(f4453),(f4454),(f4455),(f4456),(f4457),(f4458),(f4459),(f4460),(f4461),(f4462),(f4463),(f4464),(f4465),(f4466),(f4467),(f4468),(f4469),(f4470),(f4471),(f4472),(f4473),(f4474),(f4475),(f4476),(f4477),(f4478),(f4479),(f4480),(f4481),(f4482),(f4483),(f4484),(f4485),(f4486),(f4487),(f4488),(f4489),(f4490),(f4491),(f4492),(f4493),(f4494),(f4495),(f4496),(f4497),(f4498),(f4499),(f4500),(f4501),(f4502),(f4503),(f4504),(f4505),(f4506),(f4507),(f4508),(f4509),(f4510),(f4511),(f4512),(f4513),(f4514),(f4515),(f4516),(f4517),(f4518),(f4519),(f4520),(f4521),(f4522),(f4523),(f4524),(f4525),(f4526),(f4527),(f4528),(f4529),(f4530),(f4531),(f4532),(f4533),(f4534),(f4535),(f4536),(f4537),(f4538),(f4539),(f4540),(f4541),(f4542),(f4543),(f4544),(f4545),(f4546),(f4547),(f4548),(f4549),(f4550),(f4551),(f4552),(f4553),(f4554),(f4555),(f4556),(f4557),(f4558),(f4559),(f4560),(f4561),(f4562),(f4563),(f4564),(f4565),(f4566),(f4567),(f4568),(f4569),(f4570),(f4571),(f4572),(f4573),(f4574),(f4575),(f4576),(f4577),(f4578),(f4579),(f4580),(f4581),(f4582),(f4583),(f4584),(f4585),(f4586),(f4587),(f4588),(f4589),(f4590),(f4591),(f4592),(f4593),(f4594),(f4595),(f4596),(f4597),(f4598),(f4599),(f4600),(f4601),(f4602),(f4603),(f4604),(f4605),(f4606),(f4607),(f4608),(f4609),(f4610),(f4611),(f4612),(f4613),(f4614),(f4615),(f4616),(f4617),(f4618),(f4619),(f4620),(f4621),(f4622),(f4623),(f4624),(f4625),(f4626),(f4627),(f4628),(f4629),(f4630),(f4631),(f4632),(f4633),(f4634),(f4635),(f4636),(f4637),(f4638),(f4639),(f4640),(f4641),(f4642),(f4643),(f4644),(f4645),(f4646),(f4647),(f4648),(f4649),(f4650),(f4651),(f4652),(f4653),(f4654),(f4655),(f4656),(f4657),(f4658),(f4659),(f4660),(f4661),(f4662),(f4663),(f4664),(f4665),(f4666),(f4667),(f4668),(f4669),(f4670),(f4671),(f4672),(f4673),(f4674),(f4675),(f4676),(f4677),(f4678),(f4679),(f4680),(f4681),(f4682),(f4683),(f4684),(f4685),(f4686),(f4687),(f4688),(f4689),(f4690),(f4691),(f4692),(f4693),(f4694),(f4695),(f4696),(f4697),(f4698),(f4699),(f4700),(f4701),(f4702),(f4703),(f4704),(f4705),(f4706),(f4707),(f4708),(f4709),(f4710),(f4711),(f4712),(f4713),(f4714),(f4715),(f4716),(f4717),(f4718),(f4719),(f4720),(f4721),(f4722),(f4723),(f4724),(f4725),(f4726),(f4727),(f4728),(f4729),(f4730),(f4731),(f4732),(f4733),(f4734),(f4735),(f4736),(f4737),(f4738),(f4739),(f4740),(f4741),(f4742),(f4743),(f4744),(f4745),(f4746),(f4747),(f4748),(f4749),(f4750),(f4751),(f4752),(f4753),(f4754),(f4755),(f4756),(f4757),(f4758),(f4759),(f4760),(f4761),(f4762),(f4763),(f4764),(f4765),(f4766),(f4767),(f4768),(f4769),(f4770),(f4771),(f4772),(f4773),(f4774),(f4775),(f4776),(f4777),(f4778),(f4779),(f4780),(f4781),(f4782),(f4783),(f4784),(f4785),(f4786),(f4787),(f4788),(f4789),(f4790),(f4791),(f4792),(f4793),(f4794),(f4795),(f4796),(f4797),(f4798),(f4799),(f4800),(f4801),(f4802),(f4803),(f4804),(f4805),(f4806),(f4807),(f4808),(f4809),(f4810),(f4811),(f4812),(f4813),(f4814),(f4815),(f4816),(f4817),(f4818),(f4819),(f4820),(f4821),(f4822),(f4823),(f4824),(f4825),(f4826),(f4827),(f4828),(f4829),(f4830),(f4831),(f4832),(f4833),(f4834),(f4835),(f4836),(f4837),(f4838),(f4839),(f4840),(f4841),(f4842),(f4843),(f4844),(f4845),(f4846),(f4847),(f4848),(f4849),(f4850),(f4851),(f4852),(f4853),(f4854),(f4855),(f4856),(f4857),(f4858),(f4859),(f4860),(f4861),(f4862),(f4863),(f4864),(f4865),(f4866),(f4867),(f4868),(f4869),(f4870),(f4871),(f4872),(f4873),(f4874),(f4875),(f4876),(f4877),(f4878),(f4879),(f4880),(f4881),(f4882),(f4883),(f4884),(f4885),(f4886),(f4887),(f4888),(f4889),(f4890),(f4891),(f4892),(f4893),(f4894),(f4895),(f4896),(f4897),(f4898),(f4899),(f4900),(f4901),(f4902),(f4903),(f4904),(f4905),(f4906),(f4907),(f4908),(f4909),(f4910),(f4911),(f4912),(f4913),(f4914),(f4915),(f4916),(f4917),(f4918),(f4919),(f4920),(f4921),(f4922),(f4923),(f4924),(f4925),(f4926),(f4927),(f4928),(f4929),(f4930),(f4931),(f4932),(f4933),(f4934),(f4935),(f4936),(f4937),(f4938),(f4939),(f4940),(f4941),(f4942),(f4943),(f4944),(f4945),(f4946),(f4947),(f4948),(f4949),(f4950),(f4951),(f4952),(f4953),(f4954),(f4955),(f4956),(f4957),(f4958),(f4959),(f4960),(f4961),(f4962),(f4963),(f4964),(f4965),(f4966),(f4967),(f4968),(f4969),(f4970),(f4971),(f4972),(f4973),(f4974),(f4975),(f4976),(f4977),(f4978),(f4979),(f4980),(f4981),(f4982),(f4983),(f4984),(f4985),(f4986),(f4987),(f4988),(f4989),(f4990),(f4991),(f4992),(f4993),(f4994),(f4995),(f4996),(f4997),(f4998),(f4999),(f5000),(f5001),(f5002),(f5003),(f5004),(f5005),(f5006),(f5007),(f5008),(f5009),(f5010),(f5011),(f5012),(f5013),(f5014),(f5015),(f5016),(f5017),(f5018),(f5019),(f5020),(f5021),(f5022),(f5023),(f5024),(f5025),(f5026),(f5027),(f5028),(f5029),(f5030),(f5031),(f5032),(f5033),(f5034),(f5035),(f5036),(f5037),(f5038),(f5039),(f5040),(f5041),(f5042),(f5043),(f5044),(f5045),(f5046),(f5047),(f5048),(f5049),(f5050),(f5051),(f5052),(f5053),(f5054),(f5055),(f5056),(f5057),(f5058),(f5059),(f5060),(f5061),(f5062),(f5063),(f5064),(f5065),(f5066),(f5067),(f5068),(f5069),(f5070),(f5071),(f5072),(f5073),(f5074),(f5075),(f5076),(f5077),(f5078),(f5079),(f5080),(f5081),(f5082),(f5083),(f5084),(f5085),(f5086),(f5087),(f5088),(f5089),(f5090),(f5091),(f5092),(f5093),(f5094),(f5095),(f5096),(f5097),(f5098),(f5099),(f5100),(f5101),(f5102),(f5103),(f5104),(f5105),(f5106),(f5107),(f5108),(f5109),(f5110),(f5111),(f5112),(f5113),(f5114),(f5115),(f5116),(f5117),(f5118),(f5119),(f5120),(f5121),(f5122),(f5123),(f5124),(f5125),(f5126),(f5127),(f5128),(f5129),(f5130),(f5131),(f5132),(f5133),(f5134),(f5135),(f5136),(f5137),(f5138),(f5139),(f5140),(f5141),(f5142),(f5143),(f5144),(f5145),(f5146),(f5147),(f5148),(f5149),(f5150),(f5151),(f5152),(f5153),(f5154),(f5155),(f5156),(f5157),(f5158),(f5159),(f5160),(f5161),(f5162),(f5163),(f5164),(f5165),(f5166),(f5167),(f5168),(f5169),(f5170),(f5171),(f5172),(f5173),(f5174),(f5175),(f5176),(f5177),(f5178),(f5179),(f5180),(f5181),(f5182),(f5183),(f5184),(f5185),(f5186),(f5187),(f5188),(f5189),(f5190),(f5191),(f5192),(f5193),(f5194),(f5195),(f5196),(f5197),(f5198),(f5199),(f5200),(f5201),(f5202),(f5203),(f5204),(f5205),(f5206),(f5207),(f5208),(f5209),(f5210),(f5211),(f5212),(f5213),(f5214),(f5215),(f5216),(f5217),(f5218),(f5219),(f5220),(f5221),(f5222),(f5223),(f5224),(f5225),(f5226),(f5227),(f5228),(f5229),(f5230),(f5231),(f5232),(f5233),(f5234),(f5235),(f5236),(f5237),(f5238),(f5239),(f5240),(f5241),(f5242),(f5243),(f5244),(f5245),(f5246),(f5247),(f5248),(f5249),(f5250),(f5251),(f5252),(f5253),(f5254),(f5255),(f5256),(f5257),(f5258),(f5259),(f5260),(f5261),(f5262),(f5263),(f5264),(f5265),(f5266),(f5267),(f5268),(f5269),(f5270),(f5271),(f5272),(f5273),(f5274),(f5275),(f5276),(f5277),(f5278),(f5279),(f5280),(f5281),(f5282),(f5283),(f5284),(f5285),(f5286),(f5287),(f5288),(f5289),(f5290),(f5291),(f5292),(f5293),(f5294),(f5295),(f5296),(f5297),(f5298),(f5299),(f5300),(f5301),(f5302),(f5303),(f5304),(f5305),(f5306),(f5307),(f5308),(f5309),(f5310),(f5311),(f5312),(f5313),(f5314),(f5315),(f5316),(f5317),(f5318),(f5319),(f5320),(f5321),(f5322),(f5323),(f5324),(f5325),(f5326),(f5327),(f5328),(f5329),(f5330),(f5331),(f5332),(f5333),(f5334),(f5335),(f5336),(f5337),(f5338),(f5339),(f5340),(f5341),(f5342),(f5343),(f5344),(f5345),(f5346),(f5347),(f5348),(f5349),(f5350),(f5351),(f5352),(f5353),(f5354),(f5355),(f5356),(f5357),(f5358),(f5359),(f5360),(f5361),(f5362),(f5363),(f5364),(f5365),(f5366),(f5367),(f5368),(f5369),(f5370),(f5371),(f5372),(f5373),(f5374),(f5375),(f5376),(f5377),(f5378),(f5379),(f5380),(f5381),(f5382),(f5383),(f5384),(f5385),(f5386),(f5387),(f5388),(f5389),(f5390),(f5391),(f5392),(f5393),(f5394),(f5395),(f5396),(f5397),(f5398),(f5399),(f5400),(f5401),(f5402),(f5403),(f5404),(f5405),(f5406),(f5407),(f5408),(f5409),(f5410),(f5411),(f5412),(f5413),(f5414),(f5415),(f5416),(f5417),(f5418),(f5419),(f5420),(f5421),(f5422),(f5423),(f5424),(f5425),(f5426),(f5427),(f5428),(f5429),(f5430),(f5431),(f5432),(f5433),(f5434),(f5435),(f5436),(f5437),(f5438),(f5439),(f5440),(f5441),(f5442),(f5443),(f5444),(f5445),(f5446),(f5447),(f5448),(f5449),(f5450),(f5451),(f5452),(f5453),(f5454),(f5455),(f5456),(f5457),(f5458),(f5459),(f5460),(f5461),(f5462),(f5463),(f5464),(f5465),(f5466),(f5467),(f5468),(f5469),(f5470),(f5471),(f5472),(f5473),(f5474),(f5475),(f5476),(f5477),(f5478),(f5479),(f5480),(f5481),(f5482),(f5483),(f5484),(f5485),(f5486),(f5487),(f5488),(f5489),(f5490),(f5491),(f5492),(f5493),(f5494),(f5495),(f5496),(f5497),(f5498),(f5499),(f5500),(f5501),(f5502),(f5503),(f5504),(f5505),(f5506),(f5507),(f5508),(f5509),(f5510),(f5511),(f5512),(f5513),(f5514),(f5515),(f5516),(f5517),(f5518),(f5519),(f5520),(f5521),(f5522),(f5523),(f5524),(f5525),(f5526),(f5527),(f5528),(f5529),(f5530),(f5531),(f5532),(f5533),(f5534),(f5535),(f5536),(f5537),(f5538),(f5539),(f5540),(f5541),(f5542),(f5543),(f5544),(f5545),(f5546),(f5547),(f5548),(f5549),(f5550),(f5551),(f5552),(f5553),(f5554),(f5555),(f5556),(f5557),(f5558),(f5559),(f5560),(f5561),(f5562),(f5563),(f5564),(f5565),(f5566),(f5567),(f5568),(f5569),(f5570),(f5571),(f5572),(f5573),(f5574),(f5575),(f5576),(f5577),(f5578),(f5579),(f5580),(f5581),(f5582),(f5583),(f5584),(f5585),(f5586),(f5587),(f5588),(f5589),(f5590),(f5591),(f5592),(f5593),(f5594),(f5595),(f5596),(f5597),(f5598),(f5599),(f5600),(f5601),(f5602),(f5603),(f5604),(f5605),(f5606),(f5607),(f5608),(f5609),(f5610),(f5611),(f5612),(f5613),(f5614),(f5615),(f5616),(f5617),(f5618),(f5619),(f5620),(f5621),(f5622),(f5623),(f5624),(f5625),(f5626),(f5627),(f5628),(f5629),(f5630),(f5631),(f5632),(f5633),(f5634),(f5635),(f5636),(f5637),(f5638),(f5639),(f5640),(f5641),(f5642),(f5643),(f5644),(f5645),(f5646),(f5647),(f5648),(f5649),(f5650),(f5651),(f5652),(f5653),(f5654),(f5655),(f5656),(f5657),(f5658),(f5659),(f5660),(f5661),(f5662),(f5663),(f5664),(f5665),(f5666),(f5667),(f5668),(f5669),(f5670),(f5671),(f5672),(f5673),(f5674),(f5675),(f5676),(f5677),(f5678),(f5679),(f5680),(f5681),(f5682),(f5683),(f5684),(f5685),(f5686),(f5687),(f5688),(f5689),(f5690),(f5691),(f5692),(f5693),(f5694),(f5695),(f5696),(f5697),(f5698),(f5699),(f5700),(f5701),(f5702),(f5703),(f5704),(f5705),(f5706),(f5707),(f5708),(f5709),(f5710),(f5711),(f5712),(f5713),(f5714),(f5715),(f5716),(f5717),(f5718),(f5719),(f5720),(f5721),(f5722),(f5723),(f5724),(f5725),(f5726),(f5727),(f5728),(f5729),(f5730),(f5731),(f5732),(f5733),(f5734),(f5735),(f5736),(f5737),(f5738),(f5739),(f5740),(f5741),(f5742),(f5743),(f5744),(f5745),(f5746),(f5747),(f5748),(f5749),(f5750),(f5751),(f5752),(f5753),(f5754),(f5755),(f5756),(f5757),(f5758),(f5759),(f5760),(f5761),(f5762),(f5763),(f5764),(f5765),(f5766),(f5767),(f5768),(f5769),(f5770),(f5771),(f5772),(f5773),(f5774),(f5775),(f5776),(f5777),(f5778),(f5779),(f5780),(f5781),(f5782),(f5783),(f5784),(f5785),(f5786),(f5787),(f5788),(f5789),(f5790),(f5791),(f5792),(f5793),(f5794),(f5795),(f5796),(f5797),(f5798),(f5799),(f5800),(f5801),(f5802),(f5803),(f5804),(f5805),(f5806),(f5807),(f5808),(f5809),(f5810),(f5811),(f5812),(f5813),(f5814),(f5815),(f5816),(f5817),(f5818),(f5819),(f5820),(f5821),(f5822),(f5823),(f5824),(f5825),(f5826),(f5827),(f5828),(f5829),(f5830),(f5831),(f5832),(f5833),(f5834),(f5835),(f5836),(f5837),(f5838),(f5839),(f5840),(f5841),(f5842),(f5843),(f5844),(f5845),(f5846),(f5847),(f5848),(f5849),(f5850),(f5851),(f5852),(f5853),(f5854),(f5855),(f5856),(f5857),(f5858),(f5859),(f5860),(f5861),(f5862),(f5863),(f5864),(f5865),(f5866),(f5867),(f5868),(f5869),(f5870),(f5871),(f5872),(f5873),(f5874),(f5875),(f5876),(f5877),(f5878),(f5879),(f5880),(f5881),(f5882),(f5883),(f5884),(f5885),(f5886),(f5887),(f5888),(f5889),(f5890),(f5891),(f5892),(f5893),(f5894),(f5895),(f5896),(f5897),(f5898),(f5899),(f5900),(f5901),(f5902),(f5903),(f5904),(f5905),(f5906),(f5907),(f5908),(f5909),(f5910),(f5911),(f5912),(f5913),(f5914),(f5915),(f5916),(f5917),(f5918),(f5919),(f5920),(f5921),(f5922),(f5923),(f5924),(f5925),(f5926),(f5927),(f5928),(f5929),(f5930),(f5931),(f5932),(f5933),(f5934),(f5935),(f5936),(f5937),(f5938),(f5939),(f5940),(f5941),(f5942),(f5943),(f5944),(f5945),(f5946),(f5947),(f5948),(f5949),(f5950),(f5951),(f5952),(f5953),(f5954),(f5955),(f5956),(f5957),(f5958),(f5959),(f5960),(f5961),(f5962),(f5963),(f5964),(f5965),(f5966),(f5967),(f5968),(f5969),(f5970),(f5971),(f5972),(f5973),(f5974),(f5975),(f5976),(f5977),(f5978),(f5979),(f5980),(f5981),(f5982),(f5983),(f5984),(f5985),(f5986),(f5987),(f5988),(f5989),(f5990),(f5991),(f5992),(f5993),(f5994),(f5995),(f5996),(f5997),(f5998),(f5999),(f6000),(f6001),(f6002),(f6003),(f6004),(f6005),(f6006),(f6007),(f6008),(f6009),(f6010),(f6011),(f6012),(f6013),(f6014),(f6015),(f6016),(f6017),(f6018),(f6019),(f6020),(f6021),(f6022),(f6023),(f6024),(f6025),(f6026),(f6027),(f6028),(f6029),(f6030),(f6031),(f6032),(f6033),(f6034),(f6035),(f6036),(f6037),(f6038),(f6039),(f6040),(f6041),(f6042),(f6043),(f6044),(f6045),(f6046),(f6047),(f6048),(f6049),(f6050),(f6051),(f6052),(f6053),(f6054),(f6055),(f6056),(f6057),(f6058),(f6059),(f6060),(f6061),(f6062),(f6063),(f6064),(f6065),(f6066),(f6067),(f6068),(f6069),(f6070),(f6071),(f6072),(f6073),(f6074),(f6075),(f6076),(f6077),(f6078),(f6079),(f6080),(f6081),(f6082),(f6083),(f6084),(f6085),(f6086),(f6087),(f6088),(f6089),(f6090),(f6091),(f6092),(f6093),(f6094),(f6095),(f6096),(f6097),(f6098),(f6099),(f6100),(f6101),(f6102),(f6103),(f6104),(f6105),(f6106),(f6107),(f6108),(f6109),(f6110),(f6111),(f6112),(f6113),(f6114),(f6115),(f6116),(f6117),(f6118),(f6119),(f6120),(f6121),(f6122),(f6123),(f6124),(f6125),(f6126),(f6127),(f6128),(f6129),(f6130),(f6131),(f6132),(f6133),(f6134),(f6135),(f6136),(f6137),(f6138),(f6139),(f6140),(f6141),(f6142),(f6143),(f6144),(f6145),(f6146),(f6147),(f6148),(f6149),(f6150),(f6151),(f6152),(f6153),(f6154),(f6155),(f6156),(f6157),(f6158),(f6159),(f6160),(f6161),(f6162),(f6163),(f6164),(f6165),(f6166),(f6167),(f6168),(f6169),(f6170),(f6171),(f6172),(f6173),(f6174),(f6175),(f6176),(f6177),(f6178),(f6179),(f6180),(f6181),(f6182),(f6183),(f6184),(f6185),(f6186),(f6187),(f6188),(f6189),(f6190),(f6191),(f6192),(f6193),(f6194),(f6195),(f6196),(f6197),(f6198),(f6199),(f6200),(f6201),(f6202),(f6203),(f6204),(f6205),(f6206),(f6207),(f6208),(f6209),(f6210),(f6211),(f6212),(f6213),(f6214),(f6215),(f6216),(f6217),(f6218),(f6219),(f6220),(f6221),(f6222),(f6223),(f6224),(f6225),(f6226),(f6227),(f6228),(f6229),(f6230),(f6231),(f6232),(f6233),(f6234),(f6235),(f6236),(f6237),(f6238),(f6239),(f6240),(f6241),(f6242),(f6243),(f6244),(f6245),(f6246),(f6247),(f6248),(f6249),(f6250),(f6251),(f6252),(f6253),(f6254),(f6255),(f6256),(f6257),(f6258),(f6259),(f6260),(f6261),(f6262),(f6263),(f6264),(f6265),(f6266),(f6267),(f6268),(f6269),(f6270),(f6271),(f6272),(f6273),(f6274),(f6275),(f6276),(f6277),(f6278),(f6279),(f6280),(f6281),(f6282),(f6283),(f6284),(f6285),(f6286),(f6287),(f6288),(f6289),(f6290),(f6291),(f6292),(f6293),(f6294),(f6295),(f6296),(f6297),(f6298),(f6299),(f6300),(f6301),(f6302),(f6303),(f6304),(f6305),(f6306),(f6307),(f6308),(f6309),(f6310),(f6311),(f6312),(f6313),(f6314),(f6315),(f6316),(f6317),(f6318),(f6319),(f6320),(f6321),(f6322),(f6323),(f6324),(f6325),(f6326),(f6327),(f6328),(f6329),(f6330),(f6331),(f6332),(f6333),(f6334),(f6335),(f6336),(f6337),(f6338),(f6339),(f6340),(f6341),(f6342),(f6343),(f6344),(f6345),(f6346),(f6347),(f6348),(f6349),(f6350),(f6351),(f6352),(f6353),(f6354),(f6355),(f6356),(f6357),(f6358),(f6359),(f6360),(f6361),(f6362),(f6363),(f6364),(f6365),(f6366),(f6367),(f6368),(f6369),(f6370),(f6371),(f6372),(f6373),(f6374),(f6375),(f6376),(f6377),(f6378),(f6379),(f6380),(f6381),(f6382),(f6383),(f6384),(f6385),(f6386),(f6387),(f6388),(f6389),(f6390),(f6391),(f6392),(f6393),(f6394),(f6395),(f6396),(f6397),(f6398),(f6399),(f6400),(f6401),(f6402),(f6403),(f6404),(f6405),(f6406),(f6407),(f6408),(f6409),(f6410),(f6411),(f6412),(f6413),(f6414),(f6415),(f6416),(f6417),(f6418),(f6419),(f6420),(f6421),(f6422),(f6423),(f6424),(f6425),(f6426),(f6427),(f6428),(f6429),(f6430),(f6431),(f6432),(f6433),(f6434),(f6435),(f6436),(f6437),(f6438),(f6439),(f6440),(f6441),(f6442),(f6443),(f6444),(f6445),(f6446),(f6447),(f6448),(f6449),(f6450),(f6451),(f6452),(f6453),(f6454),(f6455),(f6456),(f6457),(f6458),(f6459),(f6460),(f6461),(f6462),(f6463),(f6464),(f6465),(f6466),(f6467),(f6468),(f6469),(f6470),(f6471),(f6472),(f6473),(f6474),(f6475),(f6476),(f6477),(f6478),(f6479),(f6480),(f6481),(f6482),(f6483),(f6484),(f6485),(f6486),(f6487),(f6488),(f6489),(f6490),(f6491),(f6492),(f6493),(f6494),(f6495),(f6496),(f6497),(f6498),(f6499),(f6500),(f6501),(f6502),(f6503),(f6504),(f6505),(f6506),(f6507),(f6508),(f6509),(f6510),(f6511),(f6512),(f6513),(f6514),(f6515),(f6516),(f6517),(f6518),(f6519),(f6520),(f6521),(f6522),(f6523),(f6524),(f6525),(f6526),(f6527),(f6528),(f6529),(f6530),(f6531),(f6532),(f6533),(f6534),(f6535),(f6536),(f6537),(f6538),(f6539),(f6540),(f6541),(f6542),(f6543),(f6544),(f6545),(f6546),(f6547),(f6548),(f6549),(f6550),(f6551),(f6552),(f6553),(f6554),(f6555),(f6556),(f6557),(f6558),(f6559),(f6560),(f6561),(f6562),(f6563),(f6564),(f6565),(f6566),(f6567),(f6568),(f6569),(f6570),(f6571),(f6572),(f6573),(f6574),(f6575),(f6576),(f6577),(f6578),(f6579),(f6580),(f6581),(f6582),(f6583),(f6584),(f6585),(f6586),(f6587),(f6588),(f6589),(f6590),(f6591),(f6592),(f6593),(f6594),(f6595),(f6596),(f6597),(f6598),(f6599),(f6600),(f6601),(f6602),(f6603),(f6604),(f6605),(f6606),(f6607),(f6608),(f6609),(f6610),(f6611),(f6612),(f6613),(f6614),(f6615),(f6616),(f6617),(f6618),(f6619),(f6620),(f6621),(f6622),(f6623),(f6624),(f6625),(f6626),(f6627),(f6628),(f6629),(f6630),(f6631),(f6632),(f6633),(f6634),(f6635),(f6636),(f6637),(f6638),(f6639),(f6640),(f6641),(f6642),(f6643),(f6644),(f6645),(f6646),(f6647),(f6648),(f6649),(f6650),(f6651),(f6652),(f6653),(f6654),(f6655),(f6656),(f6657),(f6658),(f6659),(f6660),(f6661),(f6662),(f6663),(f6664),(f6665),(f6666),(f6667),(f6668),(f6669),(f6670),(f6671),(f6672),(f6673),(f6674),(f6675),(f6676),(f6677),(f6678),(f6679),(f6680),(f6681),(f6682),(f6683),(f6684),(f6685),(f6686),(f6687),(f6688),(f6689),(f6690),(f6691),(f6692),(f6693),(f6694),(f6695),(f6696),(f6697),(f6698),(f6699),(f6700),(f6701),(f6702),(f6703),(f6704),(f6705),(f6706),(f6707),(f6708),(f6709),(f6710),(f6711),(f6712),(f6713),(f6714),(f6715),(f6716),(f6717),(f6718),(f6719),(f6720),(f6721),(f6722),(f6723),(f6724),(f6725),(f6726),(f6727),(f6728),(f6729),(f6730),(f6731),(f6732),(f6733),(f6734),(f6735),(f6736),(f6737),(f6738),(f6739),(f6740),(f6741),(f6742),(f6743),(f6744),(f6745),(f6746),(f6747),(f6748),(f6749),(f6750),(f6751),(f6752),(f6753),(f6754),(f6755),(f6756),(f6757),(f6758),(f6759),(f6760),(f6761),(f6762),(f6763),(f6764),(f6765),(f6766),(f6767),(f6768),(f6769),(f6770),(f6771),(f6772),(f6773),(f6774),(f6775),(f6776),(f6777),(f6778),(f6779),(f6780),(f6781),(f6782),(f6783),(f6784),(f6785),(f6786),(f6787),(f6788),(f6789),(f6790),(f6791),(f6792),(f6793),(f6794),(f6795),(f6796),(f6797),(f6798),(f6799),(f6800),(f6801),(f6802),(f6803),(f6804),(f6805),(f6806),(f6807),(f6808),(f6809),(f6810),(f6811),(f6812),(f6813),(f6814),(f6815),(f6816),(f6817),(f6818),(f6819),(f6820),(f6821),(f6822),(f6823),(f6824),(f6825),(f6826),(f6827),(f6828),(f6829),(f6830),(f6831),(f6832),(f6833),(f6834),(f6835),(f6836),(f6837),(f6838),(f6839),(f6840),(f6841),(f6842),(f6843),(f6844),(f6845),(f6846),(f6847),(f6848),(f6849),(f6850),(f6851),(f6852),(f6853),(f6854),(f6855),(f6856),(f6857),(f6858),(f6859),(f6860),(f6861),(f6862),(f6863),(f6864),(f6865),(f6866),(f6867),(f6868),(f6869),(f6870),(f6871),(f6872),(f6873),(f6874),(f6875),(f6876),(f6877),(f6878),(f6879),(f6880),(f6881),(f6882),(f6883),(f6884),(f6885),(f6886),(f6887),(f6888),(f6889),(f6890),(f6891),(f6892),(f6893),(f6894),(f6895),(f6896),(f6897),(f6898),(f6899),(f6900),(f6901),(f6902),(f6903),(f6904),(f6905),(f6906),(f6907),(f6908),(f6909),(f6910),(f6911),(f6912),(f6913),(f6914),(f6915),(f6916),(f6917),(f6918),(f6919),(f6920),(f6921),(f6922),(f6923),(f6924),(f6925),(f6926),(f6927),(f6928),(f6929),(f6930),(f6931),(f6932),(f6933),(f6934),(f6935),(f6936),(f6937),(f6938),(f6939),(f6940),(f6941),(f6942),(f6943),(f6944),(f6945),(f6946),(f6947),(f6948),(f6949),(f6950),(f6951),(f6952),(f6953),(f6954),(f6955),(f6956),(f6957),(f6958),(f6959),(f6960),(f6961),(f6962),(f6963),(f6964),(f6965),(f6966),(f6967),(f6968),(f6969),(f6970),(f6971),(f6972),(f6973),(f6974),(f6975),(f6976),(f6977),(f6978),(f6979),(f6980),(f6981),(f6982),(f6983),(f6984),(f6985),(f6986),(f6987),(f6988),(f6989),(f6990),(f6991),(f6992),(f6993),(f6994),(f6995),(f6996),(f6997),(f6998),(f6999),(f7000),(f7001),(f7002),(f7003),(f7004),(f7005),(f7006),(f7007),(f7008),(f7009),(f7010),(f7011),(f7012),(f7013),(f7014),(f7015),(f7016),(f7017),(f7018),(f7019),(f7020),(f7021),(f7022),(f7023),(f7024),(f7025),(f7026),(f7027),(f7028),(f7029),(f7030),(f7031),(f7032),(f7033),(f7034),(f7035),(f7036),(f7037),(f7038),(f7039),(f7040),(f7041),(f7042),(f7043),(f7044),(f7045),(f7046),(f7047),(f7048),(f7049),(f7050),(f7051),(f7052),(f7053),(f7054),(f7055),(f7056),(f7057),(f7058),(f7059),(f7060),(f7061),(f7062),(f7063),(f7064),(f7065),(f7066),(f7067),(f7068),(f7069),(f7070),(f7071),(f7072),(f7073),(f7074),(f7075),(f7076),(f7077),(f7078),(f7079),(f7080),(f7081),(f7082),(f7083),(f7084),(f7085),(f7086),(f7087),(f7088),(f7089),(f7090),(f7091),(f7092),(f7093),(f7094),(f7095),(f7096),(f7097),(f7098),(f7099),(f7100),(f7101),(f7102),(f7103),(f7104),(f7105),(f7106),(f7107),(f7108),(f7109),(f7110),(f7111),(f7112),(f7113),(f7114),(f7115),(f7116),(f7117),(f7118),(f7119),(f7120),(f7121),(f7122),(f7123),(f7124),(f7125),(f7126),(f7127),(f7128),(f7129),(f7130),(f7131),(f7132),(f7133),(f7134),(f7135),(f7136),(f7137),(f7138),(f7139),(f7140),(f7141),(f7142),(f7143),(f7144),(f7145),(f7146),(f7147),(f7148),(f7149),(f7150),(f7151),(f7152),(f7153),(f7154),(f7155),(f7156),(f7157),(f7158),(f7159),(f7160),(f7161),(f7162),(f7163),(f7164),(f7165),(f7166),(f7167),(f7168),(f7169),(f7170),(f7171),(f7172),(f7173),(f7174),(f7175),(f7176),(f7177),(f7178),(f7179),(f7180),(f7181),(f7182),(f7183),(f7184),(f7185),(f7186),(f7187),(f7188),(f7189),(f7190),(f7191),(f7192),(f7193),(f7194),(f7195),(f7196),(f7197),(f7198),(f7199),(f7200),(f7201),(f7202),(f7203),(f7204),(f7205),(f7206),(f7207),(f7208),(f7209),(f7210),(f7211),(f7212),(f7213),(f7214),(f7215),(f7216),(f7217),(f7218),(f7219),(f7220),(f7221),(f7222),(f7223),(f7224),(f7225),(f7226),(f7227),(f7228),(f7229),(f7230),(f7231),(f7232),(f7233),(f7234),(f7235),(f7236),(f7237),(f7238),(f7239),(f7240),(f7241),(f7242),(f7243),(f7244),(f7245),(f7246),(f7247),(f7248),(f7249),(f7250),(f7251),(f7252),(f7253),(f7254),(f7255),(f7256),(f7257),(f7258),(f7259),(f7260),(f7261),(f7262),(f7263),(f7264),(f7265),(f7266),(f7267),(f7268),(f7269),(f7270),(f7271),(f7272),(f7273),(f7274),(f7275),(f7276),(f7277),(f7278),(f7279),(f7280),(f7281),(f7282),(f7283),(f7284),(f7285),(f7286),(f7287),(f7288),(f7289),(f7290),(f7291),(f7292),(f7293),(f7294),(f7295),(f7296),(f7297),(f7298),(f7299),(f7300),(f7301),(f7302),(f7303),(f7304),(f7305),(f7306),(f7307),(f7308),(f7309),(f7310),(f7311),(f7312),(f7313),(f7314),(f7315),(f7316),(f7317),(f7318),(f7319),(f7320),(f7321),(f7322),(f7323),(f7324),(f7325),(f7326),(f7327),(f7328),(f7329),(f7330),(f7331),(f7332),(f7333),(f7334),(f7335),(f7336),(f7337),(f7338),(f7339),(f7340),(f7341),(f7342),(f7343),(f7344),(f7345),(f7346),(f7347),(f7348),(f7349),(f7350),(f7351),(f7352),(f7353),(f7354),(f7355),(f7356),(f7357),(f7358),(f7359),(f7360),(f7361),(f7362),(f7363),(f7364),(f7365),(f7366),(f7367),(f7368),(f7369),(f7370),(f7371),(f7372),(f7373),(f7374),(f7375),(f7376),(f7377),(f7378),(f7379),(f7380),(f7381),(f7382),(f7383),(f7384),(f7385),(f7386),(f7387),(f7388),(f7389),(f7390),(f7391),(f7392),(f7393),(f7394),(f7395),(f7396),(f7397),(f7398),(f7399),(f7400),(f7401),(f7402),(f7403),(f7404),(f7405),(f7406),(f7407),(f7408),(f7409),(f7410),(f7411),(f7412),(f7413),(f7414),(f7415),(f7416),(f7417),(f7418),(f7419),(f7420),(f7421),(f7422),(f7423),(f7424),(f7425),(f7426),(f7427),(f7428),(f7429),(f7430),(f7431),(f7432),(f7433),(f7434),(f7435),(f7436),(f7437),(f7438),(f7439),(f7440),(f7441),(f7442),(f7443),(f7444),(f7445),(f7446),(f7447),(f7448),(f7449),(f7450),(f7451),(f7452),(f7453),(f7454),(f7455),(f7456),(f7457),(f7458),(f7459),(f7460),(f7461),(f7462),(f7463),(f7464),(f7465),(f7466),(f7467),(f7468),(f7469),(f7470),(f7471),(f7472),(f7473),(f7474),(f7475),(f7476),(f7477),(f7478),(f7479),(f7480),(f7481),(f7482),(f7483),(f7484),(f7485),(f7486),(f7487),(f7488),(f7489),(f7490),(f7491),(f7492),(f7493),(f7494),(f7495),(f7496),(f7497),(f7498),(f7499),(f7500),(f7501),(f7502),(f7503),(f7504),(f7505),(f7506),(f7507),(f7508),(f7509),(f7510),(f7511),(f7512),(f7513),(f7514),(f7515),(f7516),(f7517),(f7518),(f7519),(f7520),(f7521),(f7522),(f7523),(f7524),(f7525),(f7526),(f7527),(f7528),(f7529),(f7530),(f7531),(f7532),(f7533),(f7534),(f7535),(f7536),(f7537),(f7538),(f7539),(f7540),(f7541),(f7542),(f7543),(f7544),(f7545),(f7546),(f7547),(f7548),(f7549),(f7550),(f7551),(f7552),(f7553),(f7554),(f7555),(f7556),(f7557),(f7558),(f7559),(f7560),(f7561),(f7562),(f7563),(f7564),(f7565),(f7566),(f7567),(f7568),(f7569),(f7570),(f7571),(f7572),(f7573),(f7574),(f7575),(f7576),(f7577),(f7578),(f7579),(f7580),(f7581),(f7582),(f7583),(f7584),(f7585),(f7586),(f7587),(f7588),(f7589),(f7590),(f7591),(f7592),(f7593),(f7594),(f7595),(f7596),(f7597),(f7598),(f7599),(f7600),(f7601),(f7602),(f7603),(f7604),(f7605),(f7606),(f7607),(f7608),(f7609),(f7610),(f7611),(f7612),(f7613),(f7614),(f7615),(f7616),(f7617),(f7618),(f7619),(f7620),(f7621),(f7622),(f7623),(f7624),(f7625),(f7626),(f7627),(f7628),(f7629),(f7630),(f7631),(f7632),(f7633),(f7634),(f7635),(f7636),(f7637),(f7638),(f7639),(f7640),(f7641),(f7642),(f7643),(f7644),(f7645),(f7646),(f7647),(f7648),(f7649),(f7650),(f7651),(f7652),(f7653),(f7654),(f7655),(f7656),(f7657),(f7658),(f7659),(f7660),(f7661),(f7662),(f7663),(f7664),(f7665),(f7666),(f7667),(f7668),(f7669),(f7670),(f7671),(f7672),(f7673),(f7674),(f7675),(f7676),(f7677),(f7678),(f7679),(f7680),(f7681),(f7682),(f7683),(f7684),(f7685),(f7686),(f7687),(f7688),(f7689),(f7690),(f7691),(f7692),(f7693),(f7694),(f7695),(f7696),(f7697),(f7698),(f7699),(f7700),(f7701),(f7702),(f7703),(f7704),(f7705),(f7706),(f7707),(f7708),(f7709),(f7710),(f7711),(f7712),(f7713),(f7714),(f7715),(f7716),(f7717),(f7718),(f7719),(f7720),(f7721),(f7722),(f7723),(f7724),(f7725),(f7726),(f7727),(f7728),(f7729),(f7730),(f7731),(f7732),(f7733),(f7734),(f7735),(f7736),(f7737),(f7738),(f7739),(f7740),(f7741),(f7742),(f7743),(f7744),(f7745),(f7746),(f7747),(f7748),(f7749),(f7750),(f7751),(f7752),(f7753),(f7754),(f7755),(f7756),(f7757),(f7758),(f7759),(f7760),(f7761),(f7762),(f7763),(f7764),(f7765),(f7766),(f7767),(f7768),(f7769),(f7770),(f7771),(f7772),(f7773),(f7774),(f7775),(f7776),(f7777),(f7778),(f7779),(f7780),(f7781),(f7782),(f7783),(f7784),(f7785),(f7786),(f7787),(f7788),(f7789),(f7790),(f7791),(f7792),(f7793),(f7794),(f7795),(f7796),(f7797),(f7798),(f7799),(f7800),(f7801),(f7802),(f7803),(f7804),(f7805),(f7806),(f7807),(f7808),(f7809),(f7810),(f7811),(f7812),(f7813),(f7814),(f7815),(f7816),(f7817),(f7818),(f7819),(f7820),(f7821),(f7822),(f7823),(f7824),(f7825),(f7826),(f7827),(f7828),(f7829),(f7830),(f7831),(f7832),(f7833),(f7834),(f7835),(f7836),(f7837),(f7838),(f7839),(f7840),(f7841),(f7842),(f7843),(f7844),(f7845),(f7846),(f7847),(f7848),(f7849),(f7850),(f7851),(f7852),(f7853),(f7854),(f7855),(f7856),(f7857),(f7858),(f7859),(f7860),(f7861),(f7862),(f7863),(f7864),(f7865),(f7866),(f7867),(f7868),(f7869),(f7870),(f7871),(f7872),(f7873),(f7874),(f7875),(f7876),(f7877),(f7878),(f7879),(f7880),(f7881),(f7882),(f7883),(f7884),(f7885),(f7886),(f7887),(f7888),(f7889),(f7890),(f7891),(f7892),(f7893),(f7894),(f7895),(f7896),(f7897),(f7898),(f7899),(f7900),(f7901),(f7902),(f7903),(f7904),(f7905),(f7906),(f7907),(f7908),(f7909),(f7910),(f7911),(f7912),(f7913),(f7914),(f7915),(f7916),(f7917),(f7918),(f7919),(f7920),(f7921),(f7922),(f7923),(f7924),(f7925),(f7926),(f7927),(f7928),(f7929),(f7930),(f7931),(f7932),(f7933),(f7934),(f7935),(f7936),(f7937),(f7938),(f7939),(f7940),(f7941),(f7942),(f7943),(f7944),(f7945),(f7946),(f7947),(f7948),(f7949),(f7950),(f7951),(f7952),(f7953),(f7954),(f7955),(f7956),(f7957),(f7958),(f7959),(f7960),(f7961),(f7962),(f7963),(f7964),(f7965),(f7966),(f7967),(f7968),(f7969),(f7970),(f7971),(f7972),(f7973),(f7974),(f7975),(f7976),(f7977),(f7978),(f7979),(f7980),(f7981),(f7982),(f7983),(f7984),(f7985),(f7986),(f7987),(f7988),(f7989),(f7990),(f7991),(f7992),(f7993),(f7994),(f7995),(f7996),(f7997),(f7998),(f7999),(f8000),(f8001),(f8002),(f8003),(f8004),(f8005),(f8006),(f8007),(f8008),(f8009),(f8010),(f8011),(f8012),(f8013),(f8014),(f8015),(f8016),(f8017),(f8018),(f8019),(f8020),(f8021),(f8022),(f8023),(f8024),(f8025),(f8026),(f8027),(f8028),(f8029),(f8030),(f8031),(f8032),(f8033),(f8034),(f8035),(f8036),(f8037),(f8038),(f8039),(f8040),(f8041),(f8042),(f8043),(f8044),(f8045),(f8046),(f8047),(f8048),(f8049),(f8050),(f8051),(f8052),(f8053),(f8054),(f8055),(f8056),(f8057),(f8058),(f8059),(f8060),(f8061),(f8062),(f8063),(f8064),(f8065),(f8066),(f8067),(f8068),(f8069),(f8070),(f8071),(f8072),(f8073),(f8074),(f8075),(f8076),(f8077),(f8078),(f8079),(f8080),(f8081),(f8082),(f8083),(f8084),(f8085),(f8086),(f8087),(f8088),(f8089),(f8090),(f8091),(f8092),(f8093),(f8094),(f8095),(f8096),(f8097),(f8098),(f8099),(f8100),(f8101),(f8102),(f8103),(f8104),(f8105),(f8106),(f8107),(f8108),(f8109),(f8110),(f8111),(f8112),(f8113),(f8114),(f8115),(f8116),(f8117),(f8118),(f8119),(f8120),(f8121),(f8122),(f8123),(f8124),(f8125),(f8126),(f8127),(f8128),(f8129),(f8130),(f8131),(f8132),(f8133),(f8134),(f8135),(f8136),(f8137),(f8138),(f8139),(f8140),(f8141),(f8142),(f8143),(f8144),(f8145),(f8146),(f8147),(f8148),(f8149),(f8150),(f8151),(f8152),(f8153),(f8154),(f8155),(f8156),(f8157),(f8158),(f8159),(f8160),(f8161),(f8162),(f8163),(f8164),(f8165),(f8166),(f8167),(f8168),(f8169),(f8170),(f8171),(f8172),(f8173),(f8174),(f8175),(f8176),(f8177),(f8178),(f8179),(f8180),(f8181),(f8182),(f8183),(f8184),(f8185),(f8186),(f8187),(f8188),(f8189),(f8190),(f8191),(f8192),(f8193),(f8194),(f8195),(f8196),(f8197),(f8198),(f8199),(f8200),(f8201),(f8202),(f8203),(f8204),(f8205),(f8206),(f8207),(f8208),(f8209),(f8210),(f8211),(f8212),(f8213),(f8214),(f8215),(f8216),(f8217),(f8218),(f8219),(f8220),(f8221),(f8222),(f8223),(f8224),(f8225),(f8226),(f8227),(f8228),(f8229),(f8230),(f8231),(f8232),(f8233),(f8234),(f8235),(f8236),(f8237),(f8238),(f8239),(f8240),(f8241),(f8242),(f8243),(f8244),(f8245),(f8246),(f8247),(f8248),(f8249),(f8250),(f8251),(f8252),(f8253),(f8254),(f8255),(f8256),(f8257),(f8258),(f8259),(f8260),(f8261),(f8262),(f8263),(f8264),(f8265),(f8266),(f8267),(f8268),(f8269),(f8270),(f8271),(f8272),(f8273),(f8274),(f8275),(f8276),(f8277),(f8278),(f8279),(f8280),(f8281),(f8282),(f8283),(f8284),(f8285),(f8286),(f8287),(f8288),(f8289),(f8290),(f8291),(f8292),(f8293),(f8294),(f8295),(f8296),(f8297),(f8298),(f8299),(f8300),(f8301),(f8302),(f8303),(f8304),(f8305),(f8306),(f8307),(f8308),(f8309),(f8310),(f8311),(f8312),(f8313),(f8314),(f8315),(f8316),(f8317),(f8318),(f8319),(f8320),(f8321),(f8322),(f8323),(f8324),(f8325),(f8326),(f8327),(f8328),(f8329),(f8330),(f8331),(f8332),(f8333),(f8334),(f8335),(f8336),(f8337),(f8338),(f8339),(f8340),(f8341),(f8342),(f8343),(f8344),(f8345),(f8346),(f8347),(f8348),(f8349),(f8350),(f8351),(f8352),(f8353),(f8354),(f8355),(f8356),(f8357),(f8358),(f8359),(f8360),(f8361),(f8362),(f8363),(f8364),(f8365),(f8366),(f8367),(f8368),(f8369),(f8370),(f8371),(f8372),(f8373),(f8374),(f8375),(f8376),(f8377),(f8378),(f8379),(f8380),(f8381),(f8382),(f8383),(f8384),(f8385),(f8386),(f8387),(f8388),(f8389),(f8390),(f8391),(f8392),(f8393),(f8394),(f8395),(f8396),(f8397),(f8398),(f8399),(f8400),(f8401),(f8402),(f8403),(f8404),(f8405),(f8406),(f8407),(f8408),(f8409),(f8410),(f8411),(f8412),(f8413),(f8414),(f8415),(f8416),(f8417),(f8418),(f8419),(f8420),(f8421),(f8422),(f8423),(f8424),(f8425),(f8426),(f8427),(f8428),(f8429),(f8430),(f8431),(f8432),(f8433),(f8434),(f8435),(f8436),(f8437),(f8438),(f8439),(f8440),(f8441),(f8442),(f8443),(f8444),(f8445),(f8446),(f8447),(f8448),(f8449),(f8450),(f8451),(f8452),(f8453),(f8454),(f8455),(f8456),(f8457),(f8458),(f8459),(f8460),(f8461),(f8462),(f8463),(f8464),(f8465),(f8466),(f8467),(f8468),(f8469),(f8470),(f8471),(f8472),(f8473),(f8474),(f8475),(f8476),(f8477),(f8478),(f8479),(f8480),(f8481),(f8482),(f8483),(f8484),(f8485),(f8486),(f8487),(f8488),(f8489),(f8490),(f8491),(f8492),(f8493),(f8494),(f8495),(f8496),(f8497),(f8498),(f8499),(f8500),(f8501),(f8502),(f8503),(f8504),(f8505),(f8506),(f8507),(f8508),(f8509),(f8510),(f8511),(f8512),(f8513),(f8514),(f8515),(f8516),(f8517),(f8518),(f8519),(f8520),(f8521),(f8522),(f8523),(f8524),(f8525),(f8526),(f8527),(f8528),(f8529),(f8530),(f8531),(f8532),(f8533),(f8534),(f8535),(f8536),(f8537),(f8538),(f8539),(f8540),(f8541),(f8542),(f8543),(f8544),(f8545),(f8546),(f8547),(f8548),(f8549),(f8550),(f8551),(f8552),(f8553),(f8554),(f8555),(f8556),(f8557),(f8558),(f8559),(f8560),(f8561),(f8562),(f8563),(f8564),(f8565),(f8566),(f8567),(f8568),(f8569),(f8570),(f8571),(f8572),(f8573),(f8574),(f8575),(f8576),(f8577),(f8578),(f8579),(f8580),(f8581),(f8582),(f8583),(f8584),(f8585),(f8586),(f8587),(f8588),(f8589),(f8590),(f8591),(f8592),(f8593),(f8594),(f8595),(f8596),(f8597),(f8598),(f8599),(f8600),(f8601),(f8602),(f8603),(f8604),(f8605),(f8606),(f8607),(f8608),(f8609),(f8610),(f8611),(f8612),(f8613),(f8614),(f8615),(f8616),(f8617),(f8618),(f8619),(f8620),(f8621),(f8622),(f8623),(f8624),(f8625),(f8626),(f8627),(f8628),(f8629),(f8630),(f8631),(f8632),(f8633),(f8634),(f8635),(f8636),(f8637),(f8638),(f8639),(f8640),(f8641),(f8642),(f8643),(f8644),(f8645),(f8646),(f8647),(f8648),(f8649),(f8650),(f8651),(f8652),(f8653),(f8654),(f8655),(f8656),(f8657),(f8658),(f8659),(f8660),(f8661),(f8662),(f8663),(f8664),(f8665),(f8666),(f8667),(f8668),(f8669),(f8670),(f8671),(f8672),(f8673),(f8674),(f8675),(f8676),(f8677),(f8678),(f8679),(f8680),(f8681),(f8682),(f8683),(f8684),(f8685),(f8686),(f8687),(f8688),(f8689),(f8690),(f8691),(f8692),(f8693),(f8694),(f8695),(f8696),(f8697),(f8698),(f8699),(f8700),(f8701),(f8702),(f8703),(f8704),(f8705),(f8706),(f8707),(f8708),(f8709),(f8710),(f8711),(f8712),(f8713),(f8714),(f8715),(f8716),(f8717),(f8718),(f8719),(f8720),(f8721),(f8722),(f8723),(f8724),(f8725),(f8726),(f8727),(f8728),(f8729),(f8730),(f8731),(f8732),(f8733),(f8734),(f8735),(f8736),(f8737),(f8738),(f8739),(f8740),(f8741),(f8742),(f8743),(f8744),(f8745),(f8746),(f8747),(f8748),(f8749),(f8750),(f8751),(f8752),(f8753),(f8754),(f8755),(f8756),(f8757),(f8758),(f8759),(f8760),(f8761),(f8762),(f8763),(f8764),(f8765),(f8766),(f8767),(f8768),(f8769),(f8770),(f8771),(f8772),(f8773),(f8774),(f8775),(f8776),(f8777),(f8778),(f8779),(f8780),(f8781),(f8782),(f8783),(f8784),(f8785),(f8786),(f8787),(f8788),(f8789),(f8790),(f8791),(f8792),(f8793),(f8794),(f8795),(f8796),(f8797),(f8798),(f8799),(f8800),(f8801),(f8802),(f8803),(f8804),(f8805),(f8806),(f8807),(f8808),(f8809),(f8810),(f8811),(f8812),(f8813),(f8814),(f8815),(f8816),(f8817),(f8818),(f8819),(f8820),(f8821),(f8822),(f8823),(f8824),(f8825),(f8826),(f8827),(f8828),(f8829),(f8830),(f8831),(f8832),(f8833),(f8834),(f8835),(f8836),(f8837),(f8838),(f8839),(f8840),(f8841),(f8842),(f8843),(f8844),(f8845),(f8846),(f8847),(f8848),(f8849),(f8850),(f8851),(f8852),(f8853),(f8854),(f8855),(f8856),(f8857),(f8858),(f8859),(f8860),(f8861),(f8862),(f8863),(f8864),(f8865),(f8866),(f8867),(f8868),(f8869),(f8870),(f8871),(f8872),(f8873),(f8874),(f8875),(f8876),(f8877),(f8878),(f8879),(f8880),(f8881),(f8882),(f8883),(f8884),(f8885),(f8886),(f8887),(f8888),(f8889),(f8890),(f8891),(f8892),(f8893),(f8894),(f8895),(f8896),(f8897),(f8898),(f8899),(f8900),(f8901),(f8902),(f8903),(f8904),(f8905),(f8906),(f8907),(f8908),(f8909),(f8910),(f8911),(f8912),(f8913),(f8914),(f8915),(f8916),(f8917),(f8918),(f8919),(f8920),(f8921),(f8922),(f8923),(f8924),(f8925),(f8926),(f8927),(f8928),(f8929),(f8930),(f8931),(f8932),(f8933),(f8934),(f8935),(f8936),(f8937),(f8938),(f8939),(f8940),(f8941),(f8942),(f8943),(f8944),(f8945),(f8946),(f8947),(f8948),(f8949),(f8950),(f8951),(f8952),(f8953),(f8954),(f8955),(f8956),(f8957),(f8958),(f8959),(f8960),(f8961),(f8962),(f8963),(f8964),(f8965),(f8966),(f8967),(f8968),(f8969),(f8970),(f8971),(f8972),(f8973),(f8974),(f8975),(f8976),(f8977),(f8978),(f8979),(f8980),(f8981),(f8982),(f8983),(f8984),(f8985),(f8986),(f8987),(f8988),(f8989),(f8990),(f8991),(f8992),(f8993),(f8994),(f8995),(f8996),(f8997),(f8998),(f8999),(f9000),(f9001),(f9002),(f9003),(f9004),(f9005),(f9006),(f9007),(f9008),(f9009),(f9010),(f9011),(f9012),(f9013),(f9014),(f9015),(f9016),(f9017),(f9018),(f9019),(f9020),(f9021),(f9022),(f9023),(f9024),(f9025),(f9026),(f9027),(f9028),(f9029),(f9030),(f9031),(f9032),(f9033),(f9034),(f9035),(f9036),(f9037),(f9038),(f9039),(f9040),(f9041),(f9042),(f9043),(f9044),(f9045),(f9046),(f9047),(f9048),(f9049),(f9050),(f9051),(f9052),(f9053),(f9054),(f9055),(f9056),(f9057),(f9058),(f9059),(f9060),(f9061),(f9062),(f9063),(f9064),(f9065),(f9066),(f9067),(f9068),(f9069),(f9070),(f9071),(f9072),(f9073),(f9074),(f9075),(f9076),(f9077),(f9078),(f9079),(f9080),(f9081),(f9082),(f9083),(f9084),(f9085),(f9086),(f9087),(f9088),(f9089),(f9090),(f9091),(f9092),(f9093),(f9094),(f9095),(f9096),(f9097),(f9098),(f9099),(f9100),(f9101),(f9102),(f9103),(f9104),(f9105),(f9106),(f9107),(f9108),(f9109),(f9110),(f9111),(f9112),(f9113),(f9114),(f9115),(f9116),(f9117),(f9118),(f9119),(f9120),(f9121),(f9122),(f9123),(f9124),(f9125),(f9126),(f9127),(f9128),(f9129),(f9130),(f9131),(f9132),(f9133),(f9134),(f9135),(f9136),(f9137),(f9138),(f9139),(f9140),(f9141),(f9142),(f9143),(f9144),(f9145),(f9146),(f9147),(f9148),(f9149),(f9150),(f9151),(f9152),(f9153),(f9154),(f9155),(f9156),(f9157),(f9158),(f9159),(f9160),(f9161),(f9162),(f9163),(f9164),(f9165),(f9166),(f9167),(f9168),(f9169),(f9170),(f9171),(f9172),(f9173),(f9174),(f9175),(f9176),(f9177),(f9178),(f9179),(f9180),(f9181),(f9182),(f9183),(f9184),(f9185),(f9186),(f9187),(f9188),(f9189),(f9190),(f9191),(f9192),(f9193),(f9194),(f9195),(f9196),(f9197),(f9198),(f9199),(f9200),(f9201),(f9202),(f9203),(f9204),(f9205),(f9206),(f9207),(f9208),(f9209),(f9210),(f9211),(f9212),(f9213),(f9214),(f9215),(f9216),(f9217),(f9218),(f9219),(f9220),(f9221),(f9222),(f9223),(f9224),(f9225),(f9226),(f9227),(f9228),(f9229),(f9230),(f9231),(f9232),(f9233),(f9234),(f9235),(f9236),(f9237),(f9238),(f9239),(f9240),(f9241),(f9242),(f9243),(f9244),(f9245),(f9246),(f9247),(f9248),(f9249),(f9250),(f9251),(f9252),(f9253),(f9254),(f9255),(f9256),(f9257),(f9258),(f9259),(f9260),(f9261),(f9262),(f9263),(f9264),(f9265),(f9266),(f9267),(f9268),(f9269),(f9270),(f9271),(f9272),(f9273),(f9274),(f9275),(f9276),(f9277),(f9278),(f9279),(f9280),(f9281),(f9282),(f9283),(f9284),(f9285),(f9286),(f9287),(f9288),(f9289),(f9290),(f9291),(f9292),(f9293),(f9294),(f9295),(f9296),(f9297),(f9298),(f9299),(f9300),(f9301),(f9302),(f9303),(f9304),(f9305),(f9306),(f9307),(f9308),(f9309),(f9310),(f9311),(f9312),(f9313),(f9314),(f9315),(f9316),(f9317),(f9318),(f9319),(f9320),(f9321),(f9322),(f9323),(f9324),(f9325),(f9326),(f9327),(f9328),(f9329),(f9330),(f9331),(f9332),(f9333),(f9334),(f9335),(f9336),(f9337),(f9338),(f9339),(f9340),(f9341),(f9342),(f9343),(f9344),(f9345),(f9346),(f9347),(f9348),(f9349),(f9350),(f9351),(f9352),(f9353),(f9354),(f9355),(f9356),(f9357),(f9358),(f9359),(f9360),(f9361),(f9362),(f9363),(f9364),(f9365),(f9366),(f9367),(f9368),(f9369),(f9370),(f9371),(f9372),(f9373),(f9374),(f9375),(f9376),(f9377),(f9378),(f9379),(f9380),(f9381),(f9382),(f9383),(f9384),(f9385),(f9386),(f9387),(f9388),(f9389),(f9390),(f9391),(f9392),(f9393),(f9394),(f9395),(f9396),(f9397),(f9398),(f9399),(f9400),(f9401),(f9402),(f9403),(f9404),(f9405),(f9406),(f9407),(f9408),(f9409),(f9410),(f9411),(f9412),(f9413),(f9414),(f9415),(f9416),(f9417),(f9418),(f9419),(f9420),(f9421),(f9422),(f9423),(f9424),(f9425),(f9426),(f9427),(f9428),(f9429),(f9430),(f9431),(f9432),(f9433),(f9434),(f9435),(f9436),(f9437),(f9438),(f9439),(f9440),(f9441),(f9442),(f9443),(f9444),(f9445),(f9446),(f9447),(f9448),(f9449),(f9450),(f9451),(f9452),(f9453),(f9454),(f9455),(f9456),(f9457),(f9458),(f9459),(f9460),(f9461),(f9462),(f9463),(f9464),(f9465),(f9466),(f9467),(f9468),(f9469),(f9470),(f9471),(f9472),(f9473),(f9474),(f9475),(f9476),(f9477),(f9478),(f9479),(f9480),(f9481),(f9482),(f9483),(f9484),(f9485),(f9486),(f9487),(f9488),(f9489),(f9490),(f9491),(f9492),(f9493),(f9494),(f9495),(f9496),(f9497),(f9498),(f9499),(f9500),(f9501),(f9502),(f9503),(f9504),(f9505),(f9506),(f9507),(f9508),(f9509),(f9510),(f9511),(f9512),(f9513),(f9514),(f9515),(f9516),(f9517),(f9518),(f9519),(f9520),(f9521),(f9522),(f9523),(f9524),(f9525),(f9526),(f9527),(f9528),(f9529),(f9530),(f9531),(f9532),(f9533),(f9534),(f9535),(f9536),(f9537),(f9538),(f9539),(f9540),(f9541),(f9542),(f9543),(f9544),(f9545),(f9546),(f9547),(f9548),(f9549),(f9550),(f9551),(f9552),(f9553),(f9554),(f9555),(f9556),(f9557),(f9558),(f9559),(f9560),(f9561),(f9562),(f9563),(f9564),(f9565),(f9566),(f9567),(f9568),(f9569),(f9570),(f9571),(f9572),(f9573),(f9574),(f9575),(f9576),(f9577),(f9578),(f9579),(f9580),(f9581),(f9582),(f9583),(f9584),(f9585),(f9586),(f9587),(f9588),(f9589),(f9590),(f9591),(f9592),(f9593),(f9594),(f9595),(f9596),(f9597),(f9598),(f9599),(f9600),(f9601),(f9602),(f9603),(f9604),(f9605),(f9606),(f9607),(f9608),(f9609),(f9610),(f9611),(f9612),(f9613),(f9614),(f9615),(f9616),(f9617),(f9618),(f9619),(f9620),(f9621),(f9622),(f9623),(f9624),(f9625),(f9626),(f9627),(f9628),(f9629),(f9630),(f9631),(f9632),(f9633),(f9634),(f9635),(f9636),(f9637),(f9638),(f9639),(f9640),(f9641),(f9642),(f9643),(f9644),(f9645),(f9646),(f9647),(f9648),(f9649),(f9650),(f9651),(f9652),(f9653),(f9654),(f9655),(f9656),(f9657),(f9658),(f9659),(f9660),(f9661),(f9662),(f9663),(f9664),(f9665),(f9666),(f9667),(f9668),(f9669),(f9670),(f9671),(f9672),(f9673),(f9674),(f9675),(f9676),(f9677),(f9678),(f9679),(f9680),(f9681),(f9682),(f9683),(f9684),(f9685),(f9686),(f9687),(f9688),(f9689),(f9690),(f9691),(f9692),(f9693),(f9694),(f9695),(f9696),(f9697),(f9698),(f9699),(f9700),(f9701),(f9702),(f9703),(f9704),(f9705),(f9706),(f9707),(f9708),(f9709),(f9710),(f9711),(f9712),(f9713),(f9714),(f9715),(f9716),(f9717),(f9718),(f9719),(f9720),(f9721),(f9722),(f9723),(f9724),(f9725),(f9726),(f9727),(f9728),(f9729),(f9730),(f9731),(f9732),(f9733),(f9734),(f9735),(f9736),(f9737),(f9738),(f9739),(f9740),(f9741),(f9742),(f9743),(f9744),(f9745),(f9746),(f9747),(f9748),(f9749),(f9750),(f9751),(f9752),(f9753),(f9754),(f9755),(f9756),(f9757),(f9758),(f9759),(f9760),(f9761),(f9762),(f9763),(f9764),(f9765),(f9766),(f9767),(f9768),(f9769),(f9770),(f9771),(f9772),(f9773),(f9774),(f9775),(f9776),(f9777),(f9778),(f9779),(f9780),(f9781),(f9782),(f9783),(f9784),(f9785),(f9786),(f9787),(f9788),(f9789),(f9790),(f9791),(f9792),(f9793),(f9794),(f9795),(f9796),(f9797),(f9798),(f9799),(f9800),(f9801),(f9802),(f9803),(f9804),(f9805),(f9806),(f9807),(f9808),(f9809),(f9810),(f9811),(f9812),(f9813),(f9814),(f9815),(f9816),(f9817),(f9818),(f9819),(f9820),(f9821),(f9822),(f9823),(f9824),(f9825),(f9826),(f9827),(f9828),(f9829),(f9830),(f9831),(f9832),(f9833),(f9834),(f9835),(f9836),(f9837),(f9838),(f9839),(f9840),(f9841),(f9842),(f9843),(f9844),(f9845),(f9846),(f9847),(f9848),(f9849),(f9850),(f9851),(f9852),(f9853),(f9854),(f9855),(f9856),(f9857),(f9858),(f9859),(f9860),(f9861),(f9862),(f9863),(f9864),(f9865),(f9866),(f9867),(f9868),(f9869),(f9870),(f9871),(f9872),(f9873),(f9874),(f9875),(f9876),(f9877),(f9878),(f9879),(f9880),(f9881),(f9882),(f9883),(f9884),(f9885),(f9886),(f9887),(f9888),(f9889),(f9890),(f9891),(f9892),(f9893),(f9894),(f9895),(f9896),(f9897),(f9898),(f9899),(f9900),(f9901),(f9902),(f9903),(f9904),(f9905),(f9906),(f9907),(f9908),(f9909),(f9910),(f9911),(f9912),(f9913),(f9914),(f9915),(f9916),(f9917),(f9918),(f9919),(f9920),(f9921),(f9922),(f9923),(f9924),(f9925),(f9926),(f9927),(f9928),(f9929),(f9930),(f9931),(f9932),(f9933),(f9934),(f9935),(f9936),(f9937),(f9938),(f9939),(f9940),(f9941),(f9942),(f9943),(f9944),(f9945),(f9946),(f9947),(f9948),(f9949),(f9950),(f9951),(f9952),(f9953),(f9954),(f9955),(f9956),(f9957),(f9958),(f9959),(f9960),(f9961),(f9962),(f9963),(f9964),(f9965),(f9966),(f9967),(f9968),(f9969),(f9970),(f9971),(f9972),(f9973),(f9974),(f9975),(f9976),(f9977),(f9978),(f9979),(f9980),(f9981),(f9982),(f9983),(f9984),(f9985),(f9986),(f9987),(f9988),(f9989),(f9990),(f9991),(f9992),(f9993),(f9994),(f9995),(f9996),(f9997),(f9998)} ] +Dir: 1 [ { (d0),(d1),(d2),(d3),(d4),(d5),(d6),(d7),(d8),(d9),(d10),(d11),(d12),(d13),(d14),(d15),(d16),(d17),(d18),(d19),(d20),(d21),(d22),(d23),(d24),(d25),(d26),(d27),(d28),(d29),(d30),(d31),(d32),(d33),(d34),(d35),(d36),(d37),(d38),(d39),(d40),(d41),(d42),(d43),(d44),(d45),(d46),(d47),(d48),(d49),(d50),(d51),(d52),(d53),(d54),(d55),(d56),(d57),(d58),(d59),(d60),(d61),(d62),(d63),(d64),(d65),(d66),(d67),(d68),(d69),(d70),(d71),(d72),(d73),(d74),(d75),(d76),(d77),(d78),(d79),(d80),(d81),(d82),(d83),(d84),(d85),(d86),(d87),(d88),(d89),(d90),(d91),(d92),(d93),(d94),(d95),(d96),(d97),(d98),(d99),(d100),(d101),(d102),(d103),(d104),(d105),(d106),(d107),(d108),(d109),(d110),(d111),(d112),(d113),(d114),(d115),(d116),(d117),(d118),(d119),(d120),(d121),(d122),(d123),(d124),(d125),(d126),(d127),(d128),(d129),(d130),(d131),(d132),(d133),(d134),(d135),(d136),(d137),(d138),(d139),(d140),(d141),(d142),(d143),(d144),(d145),(d146),(d147),(d148),(d149),(d150),(d151),(d152),(d153),(d154),(d155),(d156),(d157),(d158),(d159),(d160),(d161),(d162),(d163),(d164),(d165),(d166),(d167),(d168),(d169),(d170),(d171),(d172),(d173),(d174),(d175),(d176),(d177),(d178),(d179),(d180),(d181),(d182),(d183),(d184),(d185),(d186),(d187),(d188),(d189),(d190),(d191),(d192),(d193),(d194),(d195),(d196),(d197),(d198),(d199),(d200),(d201),(d202),(d203),(d204),(d205),(d206),(d207),(d208),(d209),(d210),(d211),(d212),(d213),(d214),(d215),(d216),(d217),(d218),(d219),(d220),(d221),(d222),(d223),(d224),(d225),(d226),(d227),(d228),(d229),(d230),(d231),(d232),(d233),(d234),(d235),(d236),(d237),(d238),(d239),(d240),(d241),(d242),(d243),(d244),(d245),(d246),(d247),(d248),(d249),(d250),(d251),(d252),(d253),(d254),(d255),(d256),(d257),(d258),(d259),(d260),(d261),(d262),(d263),(d264),(d265),(d266),(d267),(d268),(d269),(d270),(d271),(d272),(d273),(d274),(d275),(d276),(d277),(d278),(d279),(d280),(d281),(d282),(d283),(d284),(d285),(d286),(d287),(d288),(d289),(d290),(d291),(d292),(d293),(d294),(d295),(d296),(d297),(d298),(d299),(d300),(d301),(d302),(d303),(d304),(d305),(d306),(d307),(d308),(d309),(d310),(d311),(d312),(d313),(d314),(d315),(d316),(d317),(d318),(d319),(d320),(d321),(d322),(d323),(d324),(d325),(d326),(d327),(d328),(d329),(d330),(d331),(d332),(d333),(d334),(d335),(d336),(d337),(d338),(d339),(d340),(d341),(d342),(d343),(d344),(d345),(d346),(d347),(d348),(d349),(d350),(d351),(d352),(d353),(d354),(d355),(d356),(d357),(d358),(d359),(d360),(d361),(d362),(d363),(d364),(d365),(d366),(d367),(d368),(d369),(d370),(d371),(d372),(d373),(d374),(d375),(d376),(d377),(d378),(d379),(d380),(d381),(d382),(d383),(d384),(d385),(d386),(d387),(d388),(d389),(d390),(d391),(d392),(d393),(d394),(d395),(d396),(d397),(d398),(d399),(d400),(d401),(d402),(d403),(d404),(d405),(d406),(d407),(d408),(d409),(d410),(d411),(d412),(d413),(d414),(d415),(d416),(d417),(d418),(d419),(d420),(d421),(d422),(d423),(d424),(d425),(d426),(d427),(d428),(d429),(d430),(d431),(d432),(d433),(d434),(d435),(d436),(d437),(d438),(d439),(d440),(d441),(d442),(d443),(d444),(d445),(d446),(d447),(d448),(d449),(d450),(d451),(d452),(d453),(d454),(d455),(d456),(d457),(d458),(d459),(d460),(d461),(d462),(d463),(d464),(d465),(d466),(d467),(d468),(d469),(d470),(d471),(d472),(d473),(d474),(d475),(d476),(d477),(d478),(d479),(d480),(d481),(d482),(d483),(d484),(d485),(d486),(d487),(d488),(d489),(d490),(d491),(d492),(d493),(d494),(d495),(d496),(d497),(d498),(d499),(d500),(d501),(d502),(d503),(d504),(d505),(d506),(d507),(d508),(d509),(d510),(d511),(d512),(d513),(d514),(d515),(d516),(d517),(d518),(d519),(d520),(d521),(d522),(d523),(d524),(d525),(d526),(d527),(d528),(d529),(d530),(d531),(d532),(d533),(d534),(d535),(d536),(d537),(d538),(d539),(d540),(d541),(d542),(d543),(d544),(d545),(d546),(d547),(d548),(d549),(d550),(d551),(d552),(d553),(d554),(d555),(d556),(d557),(d558),(d559),(d560),(d561),(d562),(d563),(d564),(d565),(d566),(d567),(d568),(d569),(d570),(d571),(d572),(d573),(d574),(d575),(d576),(d577),(d578),(d579),(d580),(d581),(d582),(d583),(d584),(d585),(d586),(d587),(d588),(d589),(d590),(d591),(d592),(d593),(d594),(d595),(d596),(d597),(d598),(d599),(d600),(d601),(d602),(d603),(d604),(d605),(d606),(d607),(d608),(d609),(d610),(d611),(d612),(d613),(d614),(d615),(d616),(d617),(d618),(d619),(d620),(d621),(d622),(d623),(d624),(d625),(d626),(d627),(d628),(d629),(d630),(d631),(d632),(d633),(d634),(d635),(d636),(d637),(d638),(d639),(d640),(d641),(d642),(d643),(d644),(d645),(d646),(d647),(d648),(d649),(d650),(d651),(d652),(d653),(d654),(d655),(d656),(d657),(d658),(d659),(d660),(d661),(d662),(d663),(d664),(d665),(d666),(d667),(d668),(d669),(d670),(d671),(d672),(d673),(d674),(d675),(d676),(d677),(d678),(d679),(d680),(d681),(d682),(d683),(d684),(d685),(d686),(d687),(d688),(d689),(d690),(d691),(d692),(d693),(d694),(d695),(d696),(d697),(d698),(d699),(d700),(d701),(d702),(d703),(d704),(d705),(d706),(d707),(d708),(d709),(d710),(d711),(d712),(d713),(d714),(d715),(d716),(d717),(d718),(d719),(d720),(d721),(d722),(d723),(d724),(d725),(d726),(d727),(d728),(d729),(d730),(d731),(d732),(d733),(d734),(d735),(d736),(d737),(d738),(d739),(d740),(d741),(d742),(d743),(d744),(d745),(d746),(d747),(d748),(d749),(d750),(d751),(d752),(d753),(d754),(d755),(d756),(d757),(d758),(d759),(d760),(d761),(d762),(d763),(d764),(d765),(d766),(d767),(d768),(d769),(d770),(d771),(d772),(d773),(d774),(d775),(d776),(d777),(d778),(d779),(d780),(d781),(d782),(d783),(d784),(d785),(d786),(d787),(d788),(d789),(d790),(d791),(d792),(d793),(d794),(d795),(d796),(d797),(d798),(d799),(d800),(d801),(d802),(d803),(d804),(d805),(d806),(d807),(d808),(d809),(d810),(d811),(d812),(d813),(d814),(d815),(d816),(d817),(d818),(d819),(d820),(d821),(d822),(d823),(d824),(d825),(d826),(d827),(d828),(d829),(d830),(d831),(d832),(d833),(d834),(d835),(d836),(d837),(d838),(d839),(d840),(d841),(d842),(d843),(d844),(d845),(d846),(d847),(d848),(d849),(d850),(d851),(d852),(d853),(d854),(d855),(d856),(d857),(d858),(d859),(d860),(d861),(d862),(d863),(d864),(d865),(d866),(d867),(d868),(d869),(d870),(d871),(d872),(d873),(d874),(d875),(d876),(d877),(d878),(d879),(d880),(d881),(d882),(d883),(d884),(d885),(d886),(d887),(d888),(d889),(d890),(d891),(d892),(d893),(d894),(d895),(d896),(d897),(d898),(d899),(d900),(d901),(d902),(d903),(d904),(d905),(d906),(d907),(d908),(d909),(d910),(d911),(d912),(d913),(d914),(d915),(d916),(d917),(d918),(d919),(d920),(d921),(d922),(d923),(d924),(d925),(d926),(d927),(d928),(d929),(d930),(d931),(d932),(d933),(d934),(d935),(d936),(d937),(d938),(d939),(d940),(d941),(d942),(d943),(d944),(d945),(d946),(d947),(d948),(d949),(d950),(d951),(d952),(d953),(d954),(d955),(d956),(d957),(d958),(d959),(d960),(d961),(d962),(d963),(d964),(d965),(d966),(d967),(d968),(d969),(d970),(d971),(d972),(d973),(d974),(d975),(d976),(d977),(d978),(d979),(d980),(d981),(d982),(d983),(d984),(d985),(d986),(d987),(d988),(d989),(d990),(d991),(d992),(d993),(d994),(d995),(d996),(d997),(d998),(d999),(d1000),(d1001),(d1002),(d1003),(d1004),(d1005),(d1006),(d1007),(d1008),(d1009),(d1010),(d1011),(d1012),(d1013),(d1014),(d1015),(d1016),(d1017),(d1018),(d1019),(d1020),(d1021),(d1022),(d1023),(d1024),(d1025),(d1026),(d1027),(d1028),(d1029),(d1030),(d1031),(d1032),(d1033),(d1034),(d1035),(d1036),(d1037),(d1038),(d1039),(d1040),(d1041),(d1042),(d1043),(d1044),(d1045),(d1046),(d1047),(d1048),(d1049),(d1050),(d1051),(d1052),(d1053),(d1054),(d1055),(d1056),(d1057),(d1058),(d1059),(d1060),(d1061),(d1062),(d1063),(d1064),(d1065),(d1066),(d1067),(d1068),(d1069),(d1070),(d1071),(d1072),(d1073),(d1074),(d1075),(d1076),(d1077),(d1078),(d1079),(d1080),(d1081),(d1082),(d1083),(d1084),(d1085),(d1086),(d1087),(d1088),(d1089),(d1090),(d1091),(d1092),(d1093),(d1094),(d1095),(d1096),(d1097),(d1098),(d1099),(d1100),(d1101),(d1102),(d1103),(d1104),(d1105),(d1106),(d1107),(d1108),(d1109),(d1110),(d1111),(d1112),(d1113),(d1114),(d1115),(d1116),(d1117),(d1118),(d1119),(d1120),(d1121),(d1122),(d1123),(d1124),(d1125),(d1126),(d1127),(d1128),(d1129),(d1130),(d1131),(d1132),(d1133),(d1134),(d1135),(d1136),(d1137),(d1138),(d1139),(d1140),(d1141),(d1142),(d1143),(d1144),(d1145),(d1146),(d1147),(d1148),(d1149),(d1150),(d1151),(d1152),(d1153),(d1154),(d1155),(d1156),(d1157),(d1158),(d1159),(d1160),(d1161),(d1162),(d1163),(d1164),(d1165),(d1166),(d1167),(d1168),(d1169),(d1170),(d1171),(d1172),(d1173),(d1174),(d1175),(d1176),(d1177),(d1178),(d1179),(d1180),(d1181),(d1182),(d1183),(d1184),(d1185),(d1186),(d1187),(d1188),(d1189),(d1190),(d1191),(d1192),(d1193),(d1194),(d1195),(d1196),(d1197),(d1198),(d1199),(d1200),(d1201),(d1202),(d1203),(d1204),(d1205),(d1206),(d1207),(d1208),(d1209),(d1210),(d1211),(d1212),(d1213),(d1214),(d1215),(d1216),(d1217),(d1218),(d1219),(d1220),(d1221),(d1222),(d1223),(d1224),(d1225),(d1226),(d1227),(d1228),(d1229),(d1230),(d1231),(d1232),(d1233),(d1234),(d1235),(d1236),(d1237),(d1238),(d1239),(d1240),(d1241),(d1242),(d1243),(d1244),(d1245),(d1246),(d1247),(d1248),(d1249),(d1250),(d1251),(d1252),(d1253),(d1254),(d1255),(d1256),(d1257),(d1258),(d1259),(d1260),(d1261),(d1262),(d1263),(d1264),(d1265),(d1266),(d1267),(d1268),(d1269),(d1270),(d1271),(d1272),(d1273),(d1274),(d1275),(d1276),(d1277),(d1278),(d1279),(d1280),(d1281),(d1282),(d1283),(d1284),(d1285),(d1286),(d1287),(d1288),(d1289),(d1290),(d1291),(d1292),(d1293),(d1294),(d1295),(d1296),(d1297),(d1298),(d1299),(d1300),(d1301),(d1302),(d1303),(d1304),(d1305),(d1306),(d1307),(d1308),(d1309),(d1310),(d1311),(d1312),(d1313),(d1314),(d1315),(d1316),(d1317),(d1318),(d1319),(d1320),(d1321),(d1322),(d1323),(d1324),(d1325),(d1326),(d1327),(d1328),(d1329),(d1330),(d1331),(d1332),(d1333),(d1334),(d1335),(d1336),(d1337),(d1338),(d1339),(d1340),(d1341),(d1342),(d1343),(d1344),(d1345),(d1346),(d1347),(d1348),(d1349),(d1350),(d1351),(d1352),(d1353),(d1354),(d1355),(d1356),(d1357),(d1358),(d1359),(d1360),(d1361),(d1362),(d1363),(d1364),(d1365),(d1366),(d1367),(d1368),(d1369),(d1370),(d1371),(d1372),(d1373),(d1374),(d1375),(d1376),(d1377),(d1378),(d1379),(d1380),(d1381),(d1382),(d1383),(d1384),(d1385),(d1386),(d1387),(d1388),(d1389),(d1390),(d1391),(d1392),(d1393),(d1394),(d1395),(d1396),(d1397),(d1398),(d1399),(d1400),(d1401),(d1402),(d1403),(d1404),(d1405),(d1406),(d1407),(d1408),(d1409),(d1410),(d1411),(d1412),(d1413),(d1414),(d1415),(d1416),(d1417),(d1418),(d1419),(d1420),(d1421),(d1422),(d1423),(d1424),(d1425),(d1426),(d1427),(d1428),(d1429),(d1430),(d1431),(d1432),(d1433),(d1434),(d1435),(d1436),(d1437),(d1438),(d1439),(d1440),(d1441),(d1442),(d1443),(d1444),(d1445),(d1446),(d1447),(d1448),(d1449),(d1450),(d1451),(d1452),(d1453),(d1454),(d1455),(d1456),(d1457),(d1458),(d1459),(d1460),(d1461),(d1462),(d1463),(d1464),(d1465),(d1466),(d1467),(d1468),(d1469),(d1470),(d1471),(d1472),(d1473),(d1474),(d1475),(d1476),(d1477),(d1478),(d1479),(d1480),(d1481),(d1482),(d1483),(d1484),(d1485),(d1486),(d1487),(d1488),(d1489),(d1490),(d1491),(d1492),(d1493),(d1494),(d1495),(d1496),(d1497),(d1498),(d1499),(d1500),(d1501),(d1502),(d1503),(d1504),(d1505),(d1506),(d1507),(d1508),(d1509),(d1510),(d1511),(d1512),(d1513),(d1514),(d1515),(d1516),(d1517),(d1518),(d1519),(d1520),(d1521),(d1522),(d1523),(d1524),(d1525),(d1526),(d1527),(d1528),(d1529),(d1530),(d1531),(d1532),(d1533),(d1534),(d1535),(d1536),(d1537),(d1538),(d1539),(d1540),(d1541),(d1542),(d1543),(d1544),(d1545),(d1546),(d1547),(d1548),(d1549),(d1550),(d1551),(d1552),(d1553),(d1554),(d1555),(d1556),(d1557),(d1558),(d1559),(d1560),(d1561),(d1562),(d1563),(d1564),(d1565),(d1566),(d1567),(d1568),(d1569),(d1570),(d1571),(d1572),(d1573),(d1574),(d1575),(d1576),(d1577),(d1578),(d1579),(d1580),(d1581),(d1582),(d1583),(d1584),(d1585),(d1586),(d1587),(d1588),(d1589),(d1590),(d1591),(d1592),(d1593),(d1594),(d1595),(d1596),(d1597),(d1598),(d1599),(d1600),(d1601),(d1602),(d1603),(d1604),(d1605),(d1606),(d1607),(d1608),(d1609),(d1610),(d1611),(d1612),(d1613),(d1614),(d1615),(d1616),(d1617),(d1618),(d1619),(d1620),(d1621),(d1622),(d1623),(d1624),(d1625),(d1626),(d1627),(d1628),(d1629),(d1630),(d1631),(d1632),(d1633),(d1634),(d1635),(d1636),(d1637),(d1638),(d1639),(d1640),(d1641),(d1642),(d1643),(d1644),(d1645),(d1646),(d1647),(d1648),(d1649),(d1650),(d1651),(d1652),(d1653),(d1654),(d1655),(d1656),(d1657),(d1658),(d1659),(d1660),(d1661),(d1662),(d1663),(d1664),(d1665),(d1666),(d1667),(d1668),(d1669),(d1670),(d1671),(d1672),(d1673),(d1674),(d1675),(d1676),(d1677),(d1678),(d1679),(d1680),(d1681),(d1682),(d1683),(d1684),(d1685),(d1686),(d1687),(d1688),(d1689),(d1690),(d1691),(d1692),(d1693),(d1694),(d1695),(d1696),(d1697),(d1698),(d1699),(d1700),(d1701),(d1702),(d1703),(d1704),(d1705),(d1706),(d1707),(d1708),(d1709),(d1710),(d1711),(d1712),(d1713),(d1714),(d1715),(d1716),(d1717),(d1718),(d1719),(d1720),(d1721),(d1722),(d1723),(d1724),(d1725),(d1726),(d1727),(d1728),(d1729),(d1730),(d1731),(d1732),(d1733),(d1734),(d1735),(d1736),(d1737),(d1738),(d1739),(d1740),(d1741),(d1742),(d1743),(d1744),(d1745),(d1746),(d1747),(d1748),(d1749),(d1750),(d1751),(d1752),(d1753),(d1754),(d1755),(d1756),(d1757),(d1758),(d1759),(d1760),(d1761),(d1762),(d1763),(d1764),(d1765),(d1766),(d1767),(d1768),(d1769),(d1770),(d1771),(d1772),(d1773),(d1774),(d1775),(d1776),(d1777),(d1778),(d1779),(d1780),(d1781),(d1782),(d1783),(d1784),(d1785),(d1786),(d1787),(d1788),(d1789),(d1790),(d1791),(d1792),(d1793),(d1794),(d1795),(d1796),(d1797),(d1798),(d1799),(d1800),(d1801),(d1802),(d1803),(d1804),(d1805),(d1806),(d1807),(d1808),(d1809),(d1810),(d1811),(d1812),(d1813),(d1814),(d1815),(d1816),(d1817),(d1818),(d1819),(d1820),(d1821),(d1822),(d1823),(d1824),(d1825),(d1826),(d1827),(d1828),(d1829),(d1830),(d1831),(d1832),(d1833),(d1834),(d1835),(d1836),(d1837),(d1838),(d1839),(d1840),(d1841),(d1842),(d1843),(d1844),(d1845),(d1846),(d1847),(d1848),(d1849),(d1850),(d1851),(d1852),(d1853),(d1854),(d1855),(d1856),(d1857),(d1858),(d1859),(d1860),(d1861),(d1862),(d1863),(d1864),(d1865),(d1866),(d1867),(d1868),(d1869),(d1870),(d1871),(d1872),(d1873),(d1874),(d1875),(d1876),(d1877),(d1878),(d1879),(d1880),(d1881),(d1882),(d1883),(d1884),(d1885),(d1886),(d1887),(d1888),(d1889),(d1890),(d1891),(d1892),(d1893),(d1894),(d1895),(d1896),(d1897),(d1898),(d1899),(d1900),(d1901),(d1902),(d1903),(d1904),(d1905),(d1906),(d1907),(d1908),(d1909),(d1910),(d1911),(d1912),(d1913),(d1914),(d1915),(d1916),(d1917),(d1918),(d1919),(d1920),(d1921),(d1922),(d1923),(d1924),(d1925),(d1926),(d1927),(d1928),(d1929),(d1930),(d1931),(d1932),(d1933),(d1934),(d1935),(d1936),(d1937),(d1938),(d1939),(d1940),(d1941),(d1942),(d1943),(d1944),(d1945),(d1946),(d1947),(d1948),(d1949),(d1950),(d1951),(d1952),(d1953),(d1954),(d1955),(d1956),(d1957),(d1958),(d1959),(d1960),(d1961),(d1962),(d1963),(d1964),(d1965),(d1966),(d1967),(d1968),(d1969),(d1970),(d1971),(d1972),(d1973),(d1974),(d1975),(d1976),(d1977),(d1978),(d1979),(d1980),(d1981),(d1982),(d1983),(d1984),(d1985),(d1986),(d1987),(d1988),(d1989),(d1990),(d1991),(d1992),(d1993),(d1994),(d1995),(d1996),(d1997),(d1998),(d1999),(d2000),(d2001),(d2002),(d2003),(d2004),(d2005),(d2006),(d2007),(d2008),(d2009),(d2010),(d2011),(d2012),(d2013),(d2014),(d2015),(d2016),(d2017),(d2018),(d2019),(d2020),(d2021),(d2022),(d2023),(d2024),(d2025),(d2026),(d2027),(d2028),(d2029),(d2030),(d2031),(d2032),(d2033),(d2034),(d2035),(d2036),(d2037),(d2038),(d2039),(d2040),(d2041),(d2042),(d2043),(d2044),(d2045),(d2046),(d2047),(d2048),(d2049),(d2050),(d2051),(d2052),(d2053),(d2054),(d2055),(d2056),(d2057),(d2058),(d2059),(d2060),(d2061),(d2062),(d2063),(d2064),(d2065),(d2066),(d2067),(d2068),(d2069),(d2070),(d2071),(d2072),(d2073),(d2074),(d2075),(d2076),(d2077),(d2078),(d2079),(d2080),(d2081),(d2082),(d2083),(d2084),(d2085),(d2086),(d2087),(d2088),(d2089),(d2090),(d2091),(d2092),(d2093),(d2094),(d2095),(d2096),(d2097),(d2098),(d2099),(d2100),(d2101),(d2102),(d2103),(d2104),(d2105),(d2106),(d2107),(d2108),(d2109),(d2110),(d2111),(d2112),(d2113),(d2114),(d2115),(d2116),(d2117),(d2118),(d2119),(d2120),(d2121),(d2122),(d2123),(d2124),(d2125),(d2126),(d2127),(d2128),(d2129),(d2130),(d2131),(d2132),(d2133),(d2134),(d2135),(d2136),(d2137),(d2138),(d2139),(d2140),(d2141),(d2142),(d2143),(d2144),(d2145),(d2146),(d2147),(d2148),(d2149),(d2150),(d2151),(d2152),(d2153),(d2154),(d2155),(d2156),(d2157),(d2158),(d2159),(d2160),(d2161),(d2162),(d2163),(d2164),(d2165),(d2166),(d2167),(d2168),(d2169),(d2170),(d2171),(d2172),(d2173),(d2174),(d2175),(d2176),(d2177),(d2178),(d2179),(d2180),(d2181),(d2182),(d2183),(d2184),(d2185),(d2186),(d2187),(d2188),(d2189),(d2190),(d2191),(d2192),(d2193),(d2194),(d2195),(d2196),(d2197),(d2198),(d2199),(d2200),(d2201),(d2202),(d2203),(d2204),(d2205),(d2206),(d2207),(d2208),(d2209),(d2210),(d2211),(d2212),(d2213),(d2214),(d2215),(d2216),(d2217),(d2218),(d2219),(d2220),(d2221),(d2222),(d2223),(d2224),(d2225),(d2226),(d2227),(d2228),(d2229),(d2230),(d2231),(d2232),(d2233),(d2234),(d2235),(d2236),(d2237),(d2238),(d2239),(d2240),(d2241),(d2242),(d2243),(d2244),(d2245),(d2246),(d2247),(d2248),(d2249),(d2250),(d2251),(d2252),(d2253),(d2254),(d2255),(d2256),(d2257),(d2258),(d2259),(d2260),(d2261),(d2262),(d2263),(d2264),(d2265),(d2266),(d2267),(d2268),(d2269),(d2270),(d2271),(d2272),(d2273),(d2274),(d2275),(d2276),(d2277),(d2278),(d2279),(d2280),(d2281),(d2282),(d2283),(d2284),(d2285),(d2286),(d2287),(d2288),(d2289),(d2290),(d2291),(d2292),(d2293),(d2294),(d2295),(d2296),(d2297),(d2298),(d2299),(d2300),(d2301),(d2302),(d2303),(d2304),(d2305),(d2306),(d2307),(d2308),(d2309),(d2310),(d2311),(d2312),(d2313),(d2314),(d2315),(d2316),(d2317),(d2318),(d2319),(d2320),(d2321),(d2322),(d2323),(d2324),(d2325),(d2326),(d2327),(d2328),(d2329),(d2330),(d2331),(d2332),(d2333),(d2334),(d2335),(d2336),(d2337),(d2338),(d2339),(d2340),(d2341),(d2342),(d2343),(d2344),(d2345),(d2346),(d2347),(d2348),(d2349),(d2350),(d2351),(d2352),(d2353),(d2354),(d2355),(d2356),(d2357),(d2358),(d2359),(d2360),(d2361),(d2362),(d2363),(d2364),(d2365),(d2366),(d2367),(d2368),(d2369),(d2370),(d2371),(d2372),(d2373),(d2374),(d2375),(d2376),(d2377),(d2378),(d2379),(d2380),(d2381),(d2382),(d2383),(d2384),(d2385),(d2386),(d2387),(d2388),(d2389),(d2390),(d2391),(d2392),(d2393),(d2394),(d2395),(d2396),(d2397),(d2398),(d2399),(d2400),(d2401),(d2402),(d2403),(d2404),(d2405),(d2406),(d2407),(d2408),(d2409),(d2410),(d2411),(d2412),(d2413),(d2414),(d2415),(d2416),(d2417),(d2418),(d2419),(d2420),(d2421),(d2422),(d2423),(d2424),(d2425),(d2426),(d2427),(d2428),(d2429),(d2430),(d2431),(d2432),(d2433),(d2434),(d2435),(d2436),(d2437),(d2438),(d2439),(d2440),(d2441),(d2442),(d2443),(d2444),(d2445),(d2446),(d2447),(d2448),(d2449),(d2450),(d2451),(d2452),(d2453),(d2454),(d2455),(d2456),(d2457),(d2458),(d2459),(d2460),(d2461),(d2462),(d2463),(d2464),(d2465),(d2466),(d2467),(d2468),(d2469),(d2470),(d2471),(d2472),(d2473),(d2474),(d2475),(d2476),(d2477),(d2478),(d2479),(d2480),(d2481),(d2482),(d2483),(d2484),(d2485),(d2486),(d2487),(d2488),(d2489),(d2490),(d2491),(d2492),(d2493),(d2494),(d2495),(d2496),(d2497),(d2498),(d2499),(d2500),(d2501),(d2502),(d2503),(d2504),(d2505),(d2506),(d2507),(d2508),(d2509),(d2510),(d2511),(d2512),(d2513),(d2514),(d2515),(d2516),(d2517),(d2518),(d2519),(d2520),(d2521),(d2522),(d2523),(d2524),(d2525),(d2526),(d2527),(d2528),(d2529),(d2530),(d2531),(d2532),(d2533),(d2534),(d2535),(d2536),(d2537),(d2538),(d2539),(d2540),(d2541),(d2542),(d2543),(d2544),(d2545),(d2546),(d2547),(d2548),(d2549),(d2550),(d2551),(d2552),(d2553),(d2554),(d2555),(d2556),(d2557),(d2558),(d2559),(d2560),(d2561),(d2562),(d2563),(d2564),(d2565),(d2566),(d2567),(d2568),(d2569),(d2570),(d2571),(d2572),(d2573),(d2574),(d2575),(d2576),(d2577),(d2578),(d2579),(d2580),(d2581),(d2582),(d2583),(d2584),(d2585),(d2586),(d2587),(d2588),(d2589),(d2590),(d2591),(d2592),(d2593),(d2594),(d2595),(d2596),(d2597),(d2598),(d2599),(d2600),(d2601),(d2602),(d2603),(d2604),(d2605),(d2606),(d2607),(d2608),(d2609),(d2610),(d2611),(d2612),(d2613),(d2614),(d2615),(d2616),(d2617),(d2618),(d2619),(d2620),(d2621),(d2622),(d2623),(d2624),(d2625),(d2626),(d2627),(d2628),(d2629),(d2630),(d2631),(d2632),(d2633),(d2634),(d2635),(d2636),(d2637),(d2638),(d2639),(d2640),(d2641),(d2642),(d2643),(d2644),(d2645),(d2646),(d2647),(d2648),(d2649),(d2650),(d2651),(d2652),(d2653),(d2654),(d2655),(d2656),(d2657),(d2658),(d2659),(d2660),(d2661),(d2662),(d2663),(d2664),(d2665),(d2666),(d2667),(d2668),(d2669),(d2670),(d2671),(d2672),(d2673),(d2674),(d2675),(d2676),(d2677),(d2678),(d2679),(d2680),(d2681),(d2682),(d2683),(d2684),(d2685),(d2686),(d2687),(d2688),(d2689),(d2690),(d2691),(d2692),(d2693),(d2694),(d2695),(d2696),(d2697),(d2698),(d2699),(d2700),(d2701),(d2702),(d2703),(d2704),(d2705),(d2706),(d2707),(d2708),(d2709),(d2710),(d2711),(d2712),(d2713),(d2714),(d2715),(d2716),(d2717),(d2718),(d2719),(d2720),(d2721),(d2722),(d2723),(d2724),(d2725),(d2726),(d2727),(d2728),(d2729),(d2730),(d2731),(d2732),(d2733),(d2734),(d2735),(d2736),(d2737),(d2738),(d2739),(d2740),(d2741),(d2742),(d2743),(d2744),(d2745),(d2746),(d2747),(d2748),(d2749),(d2750),(d2751),(d2752),(d2753),(d2754),(d2755),(d2756),(d2757),(d2758),(d2759),(d2760),(d2761),(d2762),(d2763),(d2764),(d2765),(d2766),(d2767),(d2768),(d2769),(d2770),(d2771),(d2772),(d2773),(d2774),(d2775),(d2776),(d2777),(d2778),(d2779),(d2780),(d2781),(d2782),(d2783),(d2784),(d2785),(d2786),(d2787),(d2788),(d2789),(d2790),(d2791),(d2792),(d2793),(d2794),(d2795),(d2796),(d2797),(d2798),(d2799),(d2800),(d2801),(d2802),(d2803),(d2804),(d2805),(d2806),(d2807),(d2808),(d2809),(d2810),(d2811),(d2812),(d2813),(d2814),(d2815),(d2816),(d2817),(d2818),(d2819),(d2820),(d2821),(d2822),(d2823),(d2824),(d2825),(d2826),(d2827),(d2828),(d2829),(d2830),(d2831),(d2832),(d2833),(d2834),(d2835),(d2836),(d2837),(d2838),(d2839),(d2840),(d2841),(d2842),(d2843),(d2844),(d2845),(d2846),(d2847),(d2848),(d2849),(d2850),(d2851),(d2852),(d2853),(d2854),(d2855),(d2856),(d2857),(d2858),(d2859),(d2860),(d2861),(d2862),(d2863),(d2864),(d2865),(d2866),(d2867),(d2868),(d2869),(d2870),(d2871),(d2872),(d2873),(d2874),(d2875),(d2876),(d2877),(d2878),(d2879),(d2880),(d2881),(d2882),(d2883),(d2884),(d2885),(d2886),(d2887),(d2888),(d2889),(d2890),(d2891),(d2892),(d2893),(d2894),(d2895),(d2896),(d2897),(d2898),(d2899),(d2900),(d2901),(d2902),(d2903),(d2904),(d2905),(d2906),(d2907),(d2908),(d2909),(d2910),(d2911),(d2912),(d2913),(d2914),(d2915),(d2916),(d2917),(d2918),(d2919),(d2920),(d2921),(d2922),(d2923),(d2924),(d2925),(d2926),(d2927),(d2928),(d2929),(d2930),(d2931),(d2932),(d2933),(d2934),(d2935),(d2936),(d2937),(d2938),(d2939),(d2940),(d2941),(d2942),(d2943),(d2944),(d2945),(d2946),(d2947),(d2948),(d2949),(d2950),(d2951),(d2952),(d2953),(d2954),(d2955),(d2956),(d2957),(d2958),(d2959),(d2960),(d2961),(d2962),(d2963),(d2964),(d2965),(d2966),(d2967),(d2968),(d2969),(d2970),(d2971),(d2972),(d2973),(d2974),(d2975),(d2976),(d2977),(d2978),(d2979),(d2980),(d2981),(d2982),(d2983),(d2984),(d2985),(d2986),(d2987),(d2988),(d2989),(d2990),(d2991),(d2992),(d2993),(d2994),(d2995),(d2996),(d2997),(d2998),(d2999),(d3000),(d3001),(d3002),(d3003),(d3004),(d3005),(d3006),(d3007),(d3008),(d3009),(d3010),(d3011),(d3012),(d3013),(d3014),(d3015),(d3016),(d3017),(d3018),(d3019),(d3020),(d3021),(d3022),(d3023),(d3024),(d3025),(d3026),(d3027),(d3028),(d3029),(d3030),(d3031),(d3032),(d3033),(d3034),(d3035),(d3036),(d3037),(d3038),(d3039),(d3040),(d3041),(d3042),(d3043),(d3044),(d3045),(d3046),(d3047),(d3048),(d3049),(d3050),(d3051),(d3052),(d3053),(d3054),(d3055),(d3056),(d3057),(d3058),(d3059),(d3060),(d3061),(d3062),(d3063),(d3064),(d3065),(d3066),(d3067),(d3068),(d3069),(d3070),(d3071),(d3072),(d3073),(d3074),(d3075),(d3076),(d3077),(d3078),(d3079),(d3080),(d3081),(d3082),(d3083),(d3084),(d3085),(d3086),(d3087),(d3088),(d3089),(d3090),(d3091),(d3092),(d3093),(d3094),(d3095),(d3096),(d3097),(d3098),(d3099),(d3100),(d3101),(d3102),(d3103),(d3104),(d3105),(d3106),(d3107),(d3108),(d3109),(d3110),(d3111),(d3112),(d3113),(d3114),(d3115),(d3116),(d3117),(d3118),(d3119),(d3120),(d3121),(d3122),(d3123),(d3124),(d3125),(d3126),(d3127),(d3128),(d3129),(d3130),(d3131),(d3132),(d3133),(d3134),(d3135),(d3136),(d3137),(d3138),(d3139),(d3140),(d3141),(d3142),(d3143),(d3144),(d3145),(d3146),(d3147),(d3148),(d3149),(d3150),(d3151),(d3152),(d3153),(d3154),(d3155),(d3156),(d3157),(d3158),(d3159),(d3160),(d3161),(d3162),(d3163),(d3164),(d3165),(d3166),(d3167),(d3168),(d3169),(d3170),(d3171),(d3172),(d3173),(d3174),(d3175),(d3176),(d3177),(d3178),(d3179),(d3180),(d3181),(d3182),(d3183),(d3184),(d3185),(d3186),(d3187),(d3188),(d3189),(d3190),(d3191),(d3192),(d3193),(d3194),(d3195),(d3196),(d3197),(d3198),(d3199),(d3200),(d3201),(d3202),(d3203),(d3204),(d3205),(d3206),(d3207),(d3208),(d3209),(d3210),(d3211),(d3212),(d3213),(d3214),(d3215),(d3216),(d3217),(d3218),(d3219),(d3220),(d3221),(d3222),(d3223),(d3224),(d3225),(d3226),(d3227),(d3228),(d3229),(d3230),(d3231),(d3232),(d3233),(d3234),(d3235),(d3236),(d3237),(d3238),(d3239),(d3240),(d3241),(d3242),(d3243),(d3244),(d3245),(d3246),(d3247),(d3248),(d3249),(d3250),(d3251),(d3252),(d3253),(d3254),(d3255),(d3256),(d3257),(d3258),(d3259),(d3260),(d3261),(d3262),(d3263),(d3264),(d3265),(d3266),(d3267),(d3268),(d3269),(d3270),(d3271),(d3272),(d3273),(d3274),(d3275),(d3276),(d3277),(d3278),(d3279),(d3280),(d3281),(d3282),(d3283),(d3284),(d3285),(d3286),(d3287),(d3288),(d3289),(d3290),(d3291),(d3292),(d3293),(d3294),(d3295),(d3296),(d3297),(d3298),(d3299),(d3300),(d3301),(d3302),(d3303),(d3304),(d3305),(d3306),(d3307),(d3308),(d3309),(d3310),(d3311),(d3312),(d3313),(d3314),(d3315),(d3316),(d3317),(d3318),(d3319),(d3320),(d3321),(d3322),(d3323),(d3324),(d3325),(d3326),(d3327),(d3328),(d3329),(d3330),(d3331),(d3332),(d3333),(d3334),(d3335),(d3336),(d3337),(d3338),(d3339),(d3340),(d3341),(d3342),(d3343),(d3344),(d3345),(d3346),(d3347),(d3348),(d3349),(d3350),(d3351),(d3352),(d3353),(d3354),(d3355),(d3356),(d3357),(d3358),(d3359),(d3360),(d3361),(d3362),(d3363),(d3364),(d3365),(d3366),(d3367),(d3368),(d3369),(d3370),(d3371),(d3372),(d3373),(d3374),(d3375),(d3376),(d3377),(d3378),(d3379),(d3380),(d3381),(d3382),(d3383),(d3384),(d3385),(d3386),(d3387),(d3388),(d3389),(d3390),(d3391),(d3392),(d3393),(d3394),(d3395),(d3396),(d3397),(d3398),(d3399),(d3400),(d3401),(d3402),(d3403),(d3404),(d3405),(d3406),(d3407),(d3408),(d3409),(d3410),(d3411),(d3412),(d3413),(d3414),(d3415),(d3416),(d3417),(d3418),(d3419),(d3420),(d3421),(d3422),(d3423),(d3424),(d3425),(d3426),(d3427),(d3428),(d3429),(d3430),(d3431),(d3432),(d3433),(d3434),(d3435),(d3436),(d3437),(d3438),(d3439),(d3440),(d3441),(d3442),(d3443),(d3444),(d3445),(d3446),(d3447),(d3448),(d3449),(d3450),(d3451),(d3452),(d3453),(d3454),(d3455),(d3456),(d3457),(d3458),(d3459),(d3460),(d3461),(d3462),(d3463),(d3464),(d3465),(d3466),(d3467),(d3468),(d3469),(d3470),(d3471),(d3472),(d3473),(d3474),(d3475),(d3476),(d3477),(d3478),(d3479),(d3480),(d3481),(d3482),(d3483),(d3484),(d3485),(d3486),(d3487),(d3488),(d3489),(d3490),(d3491),(d3492),(d3493),(d3494),(d3495),(d3496),(d3497),(d3498),(d3499),(d3500),(d3501),(d3502),(d3503),(d3504),(d3505),(d3506),(d3507),(d3508),(d3509),(d3510),(d3511),(d3512),(d3513),(d3514),(d3515),(d3516),(d3517),(d3518),(d3519),(d3520),(d3521),(d3522),(d3523),(d3524),(d3525),(d3526),(d3527),(d3528),(d3529),(d3530),(d3531),(d3532),(d3533),(d3534),(d3535),(d3536),(d3537),(d3538),(d3539),(d3540),(d3541),(d3542),(d3543),(d3544),(d3545),(d3546),(d3547),(d3548),(d3549),(d3550),(d3551),(d3552),(d3553),(d3554),(d3555),(d3556),(d3557),(d3558),(d3559),(d3560),(d3561),(d3562),(d3563),(d3564),(d3565),(d3566),(d3567),(d3568),(d3569),(d3570),(d3571),(d3572),(d3573),(d3574),(d3575),(d3576),(d3577),(d3578),(d3579),(d3580),(d3581),(d3582),(d3583),(d3584),(d3585),(d3586),(d3587),(d3588),(d3589),(d3590),(d3591),(d3592),(d3593),(d3594),(d3595),(d3596),(d3597),(d3598),(d3599),(d3600),(d3601),(d3602),(d3603),(d3604),(d3605),(d3606),(d3607),(d3608),(d3609),(d3610),(d3611),(d3612),(d3613),(d3614),(d3615),(d3616),(d3617),(d3618),(d3619),(d3620),(d3621),(d3622),(d3623),(d3624),(d3625),(d3626),(d3627),(d3628),(d3629),(d3630),(d3631),(d3632),(d3633),(d3634),(d3635),(d3636),(d3637),(d3638),(d3639),(d3640),(d3641),(d3642),(d3643),(d3644),(d3645),(d3646),(d3647),(d3648),(d3649),(d3650),(d3651),(d3652),(d3653),(d3654),(d3655),(d3656),(d3657),(d3658),(d3659),(d3660),(d3661),(d3662),(d3663),(d3664),(d3665),(d3666),(d3667),(d3668),(d3669),(d3670),(d3671),(d3672),(d3673),(d3674),(d3675),(d3676),(d3677),(d3678),(d3679),(d3680),(d3681),(d3682),(d3683),(d3684),(d3685),(d3686),(d3687),(d3688),(d3689),(d3690),(d3691),(d3692),(d3693),(d3694),(d3695),(d3696),(d3697),(d3698),(d3699),(d3700),(d3701),(d3702),(d3703),(d3704),(d3705),(d3706),(d3707),(d3708),(d3709),(d3710),(d3711),(d3712),(d3713),(d3714),(d3715),(d3716),(d3717),(d3718),(d3719),(d3720),(d3721),(d3722),(d3723),(d3724),(d3725),(d3726),(d3727),(d3728),(d3729),(d3730),(d3731),(d3732),(d3733),(d3734),(d3735),(d3736),(d3737),(d3738),(d3739),(d3740),(d3741),(d3742),(d3743),(d3744),(d3745),(d3746),(d3747),(d3748),(d3749),(d3750),(d3751),(d3752),(d3753),(d3754),(d3755),(d3756),(d3757),(d3758),(d3759),(d3760),(d3761),(d3762),(d3763),(d3764),(d3765),(d3766),(d3767),(d3768),(d3769),(d3770),(d3771),(d3772),(d3773),(d3774),(d3775),(d3776),(d3777),(d3778),(d3779),(d3780),(d3781),(d3782),(d3783),(d3784),(d3785),(d3786),(d3787),(d3788),(d3789),(d3790),(d3791),(d3792),(d3793),(d3794),(d3795),(d3796),(d3797),(d3798),(d3799),(d3800),(d3801),(d3802),(d3803),(d3804),(d3805),(d3806),(d3807),(d3808),(d3809),(d3810),(d3811),(d3812),(d3813),(d3814),(d3815),(d3816),(d3817),(d3818),(d3819),(d3820),(d3821),(d3822),(d3823),(d3824),(d3825),(d3826),(d3827),(d3828),(d3829),(d3830),(d3831),(d3832),(d3833),(d3834),(d3835),(d3836),(d3837),(d3838),(d3839),(d3840),(d3841),(d3842),(d3843),(d3844),(d3845),(d3846),(d3847),(d3848),(d3849),(d3850),(d3851),(d3852),(d3853),(d3854),(d3855),(d3856),(d3857),(d3858),(d3859),(d3860),(d3861),(d3862),(d3863),(d3864),(d3865),(d3866),(d3867),(d3868),(d3869),(d3870),(d3871),(d3872),(d3873),(d3874),(d3875),(d3876),(d3877),(d3878),(d3879),(d3880),(d3881),(d3882),(d3883),(d3884),(d3885),(d3886),(d3887),(d3888),(d3889),(d3890),(d3891),(d3892),(d3893),(d3894),(d3895),(d3896),(d3897),(d3898),(d3899),(d3900),(d3901),(d3902),(d3903),(d3904),(d3905),(d3906),(d3907),(d3908),(d3909),(d3910),(d3911),(d3912),(d3913),(d3914),(d3915),(d3916),(d3917),(d3918),(d3919),(d3920),(d3921),(d3922),(d3923),(d3924),(d3925),(d3926),(d3927),(d3928),(d3929),(d3930),(d3931),(d3932),(d3933),(d3934),(d3935),(d3936),(d3937),(d3938),(d3939),(d3940),(d3941),(d3942),(d3943),(d3944),(d3945),(d3946),(d3947),(d3948),(d3949),(d3950),(d3951),(d3952),(d3953),(d3954),(d3955),(d3956),(d3957),(d3958),(d3959),(d3960),(d3961),(d3962),(d3963),(d3964),(d3965),(d3966),(d3967),(d3968),(d3969),(d3970),(d3971),(d3972),(d3973),(d3974),(d3975),(d3976),(d3977),(d3978),(d3979),(d3980),(d3981),(d3982),(d3983),(d3984),(d3985),(d3986),(d3987),(d3988),(d3989),(d3990),(d3991),(d3992),(d3993),(d3994),(d3995),(d3996),(d3997),(d3998),(d3999),(d4000),(d4001),(d4002),(d4003),(d4004),(d4005),(d4006),(d4007),(d4008),(d4009),(d4010),(d4011),(d4012),(d4013),(d4014),(d4015),(d4016),(d4017),(d4018),(d4019),(d4020),(d4021),(d4022),(d4023),(d4024),(d4025),(d4026),(d4027),(d4028),(d4029),(d4030),(d4031),(d4032),(d4033),(d4034),(d4035),(d4036),(d4037),(d4038),(d4039),(d4040),(d4041),(d4042),(d4043),(d4044),(d4045),(d4046),(d4047),(d4048),(d4049),(d4050),(d4051),(d4052),(d4053),(d4054),(d4055),(d4056),(d4057),(d4058),(d4059),(d4060),(d4061),(d4062),(d4063),(d4064),(d4065),(d4066),(d4067),(d4068),(d4069),(d4070),(d4071),(d4072),(d4073),(d4074),(d4075),(d4076),(d4077),(d4078),(d4079),(d4080),(d4081),(d4082),(d4083),(d4084),(d4085),(d4086),(d4087),(d4088),(d4089),(d4090),(d4091),(d4092),(d4093),(d4094),(d4095),(d4096),(d4097),(d4098),(d4099),(d4100),(d4101),(d4102),(d4103),(d4104),(d4105),(d4106),(d4107),(d4108),(d4109),(d4110),(d4111),(d4112),(d4113),(d4114),(d4115),(d4116),(d4117),(d4118),(d4119),(d4120),(d4121),(d4122),(d4123),(d4124),(d4125),(d4126),(d4127),(d4128),(d4129),(d4130),(d4131),(d4132),(d4133),(d4134),(d4135),(d4136),(d4137),(d4138),(d4139),(d4140),(d4141),(d4142),(d4143),(d4144),(d4145),(d4146),(d4147),(d4148),(d4149),(d4150),(d4151),(d4152),(d4153),(d4154),(d4155),(d4156),(d4157),(d4158),(d4159),(d4160),(d4161),(d4162),(d4163),(d4164),(d4165),(d4166),(d4167),(d4168),(d4169),(d4170),(d4171),(d4172),(d4173),(d4174),(d4175),(d4176),(d4177),(d4178),(d4179),(d4180),(d4181),(d4182),(d4183),(d4184),(d4185),(d4186),(d4187),(d4188),(d4189),(d4190),(d4191),(d4192),(d4193),(d4194),(d4195),(d4196),(d4197),(d4198),(d4199),(d4200),(d4201),(d4202),(d4203),(d4204),(d4205),(d4206),(d4207),(d4208),(d4209),(d4210),(d4211),(d4212),(d4213),(d4214),(d4215),(d4216),(d4217),(d4218),(d4219),(d4220),(d4221),(d4222),(d4223),(d4224),(d4225),(d4226),(d4227),(d4228),(d4229),(d4230),(d4231),(d4232),(d4233),(d4234),(d4235),(d4236),(d4237),(d4238),(d4239),(d4240),(d4241),(d4242),(d4243),(d4244),(d4245),(d4246),(d4247),(d4248),(d4249),(d4250),(d4251),(d4252),(d4253),(d4254),(d4255),(d4256),(d4257),(d4258),(d4259),(d4260),(d4261),(d4262),(d4263),(d4264),(d4265),(d4266),(d4267),(d4268),(d4269),(d4270),(d4271),(d4272),(d4273),(d4274),(d4275),(d4276),(d4277),(d4278),(d4279),(d4280),(d4281),(d4282),(d4283),(d4284),(d4285),(d4286),(d4287),(d4288),(d4289),(d4290),(d4291),(d4292),(d4293),(d4294),(d4295),(d4296),(d4297),(d4298),(d4299),(d4300),(d4301),(d4302),(d4303),(d4304),(d4305),(d4306),(d4307),(d4308),(d4309),(d4310),(d4311),(d4312),(d4313),(d4314),(d4315),(d4316),(d4317),(d4318),(d4319),(d4320),(d4321),(d4322),(d4323),(d4324),(d4325),(d4326),(d4327),(d4328),(d4329),(d4330),(d4331),(d4332),(d4333),(d4334),(d4335),(d4336),(d4337),(d4338),(d4339),(d4340),(d4341),(d4342),(d4343),(d4344),(d4345),(d4346),(d4347),(d4348),(d4349),(d4350),(d4351),(d4352),(d4353),(d4354),(d4355),(d4356),(d4357),(d4358),(d4359),(d4360),(d4361),(d4362),(d4363),(d4364),(d4365),(d4366),(d4367),(d4368),(d4369),(d4370),(d4371),(d4372),(d4373),(d4374),(d4375),(d4376),(d4377),(d4378),(d4379),(d4380),(d4381),(d4382),(d4383),(d4384),(d4385),(d4386),(d4387),(d4388),(d4389),(d4390),(d4391),(d4392),(d4393),(d4394),(d4395),(d4396),(d4397),(d4398),(d4399),(d4400),(d4401),(d4402),(d4403),(d4404),(d4405),(d4406),(d4407),(d4408),(d4409),(d4410),(d4411),(d4412),(d4413),(d4414),(d4415),(d4416),(d4417),(d4418),(d4419),(d4420),(d4421),(d4422),(d4423),(d4424),(d4425),(d4426),(d4427),(d4428),(d4429),(d4430),(d4431),(d4432),(d4433),(d4434),(d4435),(d4436),(d4437),(d4438),(d4439),(d4440),(d4441),(d4442),(d4443),(d4444),(d4445),(d4446),(d4447),(d4448),(d4449),(d4450),(d4451),(d4452),(d4453),(d4454),(d4455),(d4456),(d4457),(d4458),(d4459),(d4460),(d4461),(d4462),(d4463),(d4464),(d4465),(d4466),(d4467),(d4468),(d4469),(d4470),(d4471),(d4472),(d4473),(d4474),(d4475),(d4476),(d4477),(d4478),(d4479),(d4480),(d4481),(d4482),(d4483),(d4484),(d4485),(d4486),(d4487),(d4488),(d4489),(d4490),(d4491),(d4492),(d4493),(d4494),(d4495),(d4496),(d4497),(d4498),(d4499),(d4500),(d4501),(d4502),(d4503),(d4504),(d4505),(d4506),(d4507),(d4508),(d4509),(d4510),(d4511),(d4512),(d4513),(d4514),(d4515),(d4516),(d4517),(d4518),(d4519),(d4520),(d4521),(d4522),(d4523),(d4524),(d4525),(d4526),(d4527),(d4528),(d4529),(d4530),(d4531),(d4532),(d4533),(d4534),(d4535),(d4536),(d4537),(d4538),(d4539),(d4540),(d4541),(d4542),(d4543),(d4544),(d4545),(d4546),(d4547),(d4548),(d4549),(d4550),(d4551),(d4552),(d4553),(d4554),(d4555),(d4556),(d4557),(d4558),(d4559),(d4560),(d4561),(d4562),(d4563),(d4564),(d4565),(d4566),(d4567),(d4568),(d4569),(d4570),(d4571),(d4572),(d4573),(d4574),(d4575),(d4576),(d4577),(d4578),(d4579),(d4580),(d4581),(d4582),(d4583),(d4584),(d4585),(d4586),(d4587),(d4588),(d4589),(d4590),(d4591),(d4592),(d4593),(d4594),(d4595),(d4596),(d4597),(d4598),(d4599),(d4600),(d4601),(d4602),(d4603),(d4604),(d4605),(d4606),(d4607),(d4608),(d4609),(d4610),(d4611),(d4612),(d4613),(d4614),(d4615),(d4616),(d4617),(d4618),(d4619),(d4620),(d4621),(d4622),(d4623),(d4624),(d4625),(d4626),(d4627),(d4628),(d4629),(d4630),(d4631),(d4632),(d4633),(d4634),(d4635),(d4636),(d4637),(d4638),(d4639),(d4640),(d4641),(d4642),(d4643),(d4644),(d4645),(d4646),(d4647),(d4648),(d4649),(d4650),(d4651),(d4652),(d4653),(d4654),(d4655),(d4656),(d4657),(d4658),(d4659),(d4660),(d4661),(d4662),(d4663),(d4664),(d4665),(d4666),(d4667),(d4668),(d4669),(d4670),(d4671),(d4672),(d4673),(d4674),(d4675),(d4676),(d4677),(d4678),(d4679),(d4680),(d4681),(d4682),(d4683),(d4684),(d4685),(d4686),(d4687),(d4688),(d4689),(d4690),(d4691),(d4692),(d4693),(d4694),(d4695),(d4696),(d4697),(d4698),(d4699),(d4700),(d4701),(d4702),(d4703),(d4704),(d4705),(d4706),(d4707),(d4708),(d4709),(d4710),(d4711),(d4712),(d4713),(d4714),(d4715),(d4716),(d4717),(d4718),(d4719),(d4720),(d4721),(d4722),(d4723),(d4724),(d4725),(d4726),(d4727),(d4728),(d4729),(d4730),(d4731),(d4732),(d4733),(d4734),(d4735),(d4736),(d4737),(d4738),(d4739),(d4740),(d4741),(d4742),(d4743),(d4744),(d4745),(d4746),(d4747),(d4748),(d4749),(d4750),(d4751),(d4752),(d4753),(d4754),(d4755),(d4756),(d4757),(d4758),(d4759),(d4760),(d4761),(d4762),(d4763),(d4764),(d4765),(d4766),(d4767),(d4768),(d4769),(d4770),(d4771),(d4772),(d4773),(d4774),(d4775),(d4776),(d4777),(d4778),(d4779),(d4780),(d4781),(d4782),(d4783),(d4784),(d4785),(d4786),(d4787),(d4788),(d4789),(d4790),(d4791),(d4792),(d4793),(d4794),(d4795),(d4796),(d4797),(d4798),(d4799),(d4800),(d4801),(d4802),(d4803),(d4804),(d4805),(d4806),(d4807),(d4808),(d4809),(d4810),(d4811),(d4812),(d4813),(d4814),(d4815),(d4816),(d4817),(d4818),(d4819),(d4820),(d4821),(d4822),(d4823),(d4824),(d4825),(d4826),(d4827),(d4828),(d4829),(d4830),(d4831),(d4832),(d4833),(d4834),(d4835),(d4836),(d4837),(d4838),(d4839),(d4840),(d4841),(d4842),(d4843),(d4844),(d4845),(d4846),(d4847),(d4848),(d4849),(d4850),(d4851),(d4852),(d4853),(d4854),(d4855),(d4856),(d4857),(d4858),(d4859),(d4860),(d4861),(d4862),(d4863),(d4864),(d4865),(d4866),(d4867),(d4868),(d4869),(d4870),(d4871),(d4872),(d4873),(d4874),(d4875),(d4876),(d4877),(d4878),(d4879),(d4880),(d4881),(d4882),(d4883),(d4884),(d4885),(d4886),(d4887),(d4888),(d4889),(d4890),(d4891),(d4892),(d4893),(d4894),(d4895),(d4896),(d4897),(d4898),(d4899),(d4900),(d4901),(d4902),(d4903),(d4904),(d4905),(d4906),(d4907),(d4908),(d4909),(d4910),(d4911),(d4912),(d4913),(d4914),(d4915),(d4916),(d4917),(d4918),(d4919),(d4920),(d4921),(d4922),(d4923),(d4924),(d4925),(d4926),(d4927),(d4928),(d4929),(d4930),(d4931),(d4932),(d4933),(d4934),(d4935),(d4936),(d4937),(d4938),(d4939),(d4940),(d4941),(d4942),(d4943),(d4944),(d4945),(d4946),(d4947),(d4948),(d4949),(d4950),(d4951),(d4952),(d4953),(d4954),(d4955),(d4956),(d4957),(d4958),(d4959),(d4960),(d4961),(d4962),(d4963),(d4964),(d4965),(d4966),(d4967),(d4968),(d4969),(d4970),(d4971),(d4972),(d4973),(d4974),(d4975),(d4976),(d4977),(d4978),(d4979),(d4980),(d4981),(d4982),(d4983),(d4984),(d4985),(d4986),(d4987),(d4988),(d4989),(d4990),(d4991),(d4992),(d4993),(d4994),(d4995),(d4996),(d4997),(d4998),(d4999),(d5000),(d5001),(d5002),(d5003),(d5004),(d5005),(d5006),(d5007),(d5008),(d5009),(d5010),(d5011),(d5012),(d5013),(d5014),(d5015),(d5016),(d5017),(d5018),(d5019),(d5020),(d5021),(d5022),(d5023),(d5024),(d5025),(d5026),(d5027),(d5028),(d5029),(d5030),(d5031),(d5032),(d5033),(d5034),(d5035),(d5036),(d5037),(d5038),(d5039),(d5040),(d5041),(d5042),(d5043),(d5044),(d5045),(d5046),(d5047),(d5048),(d5049),(d5050),(d5051),(d5052),(d5053),(d5054),(d5055),(d5056),(d5057),(d5058),(d5059),(d5060),(d5061),(d5062),(d5063),(d5064),(d5065),(d5066),(d5067),(d5068),(d5069),(d5070),(d5071),(d5072),(d5073),(d5074),(d5075),(d5076),(d5077),(d5078),(d5079),(d5080),(d5081),(d5082),(d5083),(d5084),(d5085),(d5086),(d5087),(d5088),(d5089),(d5090),(d5091),(d5092),(d5093),(d5094),(d5095),(d5096),(d5097),(d5098),(d5099),(d5100),(d5101),(d5102),(d5103),(d5104),(d5105),(d5106),(d5107),(d5108),(d5109),(d5110),(d5111),(d5112),(d5113),(d5114),(d5115),(d5116),(d5117),(d5118),(d5119),(d5120),(d5121),(d5122),(d5123),(d5124),(d5125),(d5126),(d5127),(d5128),(d5129),(d5130),(d5131),(d5132),(d5133),(d5134),(d5135),(d5136),(d5137),(d5138),(d5139),(d5140),(d5141),(d5142),(d5143),(d5144),(d5145),(d5146),(d5147),(d5148),(d5149),(d5150),(d5151),(d5152),(d5153),(d5154),(d5155),(d5156),(d5157),(d5158),(d5159),(d5160),(d5161),(d5162),(d5163),(d5164),(d5165),(d5166),(d5167),(d5168),(d5169),(d5170),(d5171),(d5172),(d5173),(d5174),(d5175),(d5176),(d5177),(d5178),(d5179),(d5180),(d5181),(d5182),(d5183),(d5184),(d5185),(d5186),(d5187),(d5188),(d5189),(d5190),(d5191),(d5192),(d5193),(d5194),(d5195),(d5196),(d5197),(d5198),(d5199),(d5200),(d5201),(d5202),(d5203),(d5204),(d5205),(d5206),(d5207),(d5208),(d5209),(d5210),(d5211),(d5212),(d5213),(d5214),(d5215),(d5216),(d5217),(d5218),(d5219),(d5220),(d5221),(d5222),(d5223),(d5224),(d5225),(d5226),(d5227),(d5228),(d5229),(d5230),(d5231),(d5232),(d5233),(d5234),(d5235),(d5236),(d5237),(d5238),(d5239),(d5240),(d5241),(d5242),(d5243),(d5244),(d5245),(d5246),(d5247),(d5248),(d5249),(d5250),(d5251),(d5252),(d5253),(d5254),(d5255),(d5256),(d5257),(d5258),(d5259),(d5260),(d5261),(d5262),(d5263),(d5264),(d5265),(d5266),(d5267),(d5268),(d5269),(d5270),(d5271),(d5272),(d5273),(d5274),(d5275),(d5276),(d5277),(d5278),(d5279),(d5280),(d5281),(d5282),(d5283),(d5284),(d5285),(d5286),(d5287),(d5288),(d5289),(d5290),(d5291),(d5292),(d5293),(d5294),(d5295),(d5296),(d5297),(d5298),(d5299),(d5300),(d5301),(d5302),(d5303),(d5304),(d5305),(d5306),(d5307),(d5308),(d5309),(d5310),(d5311),(d5312),(d5313),(d5314),(d5315),(d5316),(d5317),(d5318),(d5319),(d5320),(d5321),(d5322),(d5323),(d5324),(d5325),(d5326),(d5327),(d5328),(d5329),(d5330),(d5331),(d5332),(d5333),(d5334),(d5335),(d5336),(d5337),(d5338),(d5339),(d5340),(d5341),(d5342),(d5343),(d5344),(d5345),(d5346),(d5347),(d5348),(d5349),(d5350),(d5351),(d5352),(d5353),(d5354),(d5355),(d5356),(d5357),(d5358),(d5359),(d5360),(d5361),(d5362),(d5363),(d5364),(d5365),(d5366),(d5367),(d5368),(d5369),(d5370),(d5371),(d5372),(d5373),(d5374),(d5375),(d5376),(d5377),(d5378),(d5379),(d5380),(d5381),(d5382),(d5383),(d5384),(d5385),(d5386),(d5387),(d5388),(d5389),(d5390),(d5391),(d5392),(d5393),(d5394),(d5395),(d5396),(d5397),(d5398),(d5399),(d5400),(d5401),(d5402),(d5403),(d5404),(d5405),(d5406),(d5407),(d5408),(d5409),(d5410),(d5411),(d5412),(d5413),(d5414),(d5415),(d5416),(d5417),(d5418),(d5419),(d5420),(d5421),(d5422),(d5423),(d5424),(d5425),(d5426),(d5427),(d5428),(d5429),(d5430),(d5431),(d5432),(d5433),(d5434),(d5435),(d5436),(d5437),(d5438),(d5439),(d5440),(d5441),(d5442),(d5443),(d5444),(d5445),(d5446),(d5447),(d5448),(d5449),(d5450),(d5451),(d5452),(d5453),(d5454),(d5455),(d5456),(d5457),(d5458),(d5459),(d5460),(d5461),(d5462),(d5463),(d5464),(d5465),(d5466),(d5467),(d5468),(d5469),(d5470),(d5471),(d5472),(d5473),(d5474),(d5475),(d5476),(d5477),(d5478),(d5479),(d5480),(d5481),(d5482),(d5483),(d5484),(d5485),(d5486),(d5487),(d5488),(d5489),(d5490),(d5491),(d5492),(d5493),(d5494),(d5495),(d5496),(d5497),(d5498),(d5499),(d5500),(d5501),(d5502),(d5503),(d5504),(d5505),(d5506),(d5507),(d5508),(d5509),(d5510),(d5511),(d5512),(d5513),(d5514),(d5515),(d5516),(d5517),(d5518),(d5519),(d5520),(d5521),(d5522),(d5523),(d5524),(d5525),(d5526),(d5527),(d5528),(d5529),(d5530),(d5531),(d5532),(d5533),(d5534),(d5535),(d5536),(d5537),(d5538),(d5539),(d5540),(d5541),(d5542),(d5543),(d5544),(d5545),(d5546),(d5547),(d5548),(d5549),(d5550),(d5551),(d5552),(d5553),(d5554),(d5555),(d5556),(d5557),(d5558),(d5559),(d5560),(d5561),(d5562),(d5563),(d5564),(d5565),(d5566),(d5567),(d5568),(d5569),(d5570),(d5571),(d5572),(d5573),(d5574),(d5575),(d5576),(d5577),(d5578),(d5579),(d5580),(d5581),(d5582),(d5583),(d5584),(d5585),(d5586),(d5587),(d5588),(d5589),(d5590),(d5591),(d5592),(d5593),(d5594),(d5595),(d5596),(d5597),(d5598),(d5599),(d5600),(d5601),(d5602),(d5603),(d5604),(d5605),(d5606),(d5607),(d5608),(d5609),(d5610),(d5611),(d5612),(d5613),(d5614),(d5615),(d5616),(d5617),(d5618),(d5619),(d5620),(d5621),(d5622),(d5623),(d5624),(d5625),(d5626),(d5627),(d5628),(d5629),(d5630),(d5631),(d5632),(d5633),(d5634),(d5635),(d5636),(d5637),(d5638),(d5639),(d5640),(d5641),(d5642),(d5643),(d5644),(d5645),(d5646),(d5647),(d5648),(d5649),(d5650),(d5651),(d5652),(d5653),(d5654),(d5655),(d5656),(d5657),(d5658),(d5659),(d5660),(d5661),(d5662),(d5663),(d5664),(d5665),(d5666),(d5667),(d5668),(d5669),(d5670),(d5671),(d5672),(d5673),(d5674),(d5675),(d5676),(d5677),(d5678),(d5679),(d5680),(d5681),(d5682),(d5683),(d5684),(d5685),(d5686),(d5687),(d5688),(d5689),(d5690),(d5691),(d5692),(d5693),(d5694),(d5695),(d5696),(d5697),(d5698),(d5699),(d5700),(d5701),(d5702),(d5703),(d5704),(d5705),(d5706),(d5707),(d5708),(d5709),(d5710),(d5711),(d5712),(d5713),(d5714),(d5715),(d5716),(d5717),(d5718),(d5719),(d5720),(d5721),(d5722),(d5723),(d5724),(d5725),(d5726),(d5727),(d5728),(d5729),(d5730),(d5731),(d5732),(d5733),(d5734),(d5735),(d5736),(d5737),(d5738),(d5739),(d5740),(d5741),(d5742),(d5743),(d5744),(d5745),(d5746),(d5747),(d5748),(d5749),(d5750),(d5751),(d5752),(d5753),(d5754),(d5755),(d5756),(d5757),(d5758),(d5759),(d5760),(d5761),(d5762),(d5763),(d5764),(d5765),(d5766),(d5767),(d5768),(d5769),(d5770),(d5771),(d5772),(d5773),(d5774),(d5775),(d5776),(d5777),(d5778),(d5779),(d5780),(d5781),(d5782),(d5783),(d5784),(d5785),(d5786),(d5787),(d5788),(d5789),(d5790),(d5791),(d5792),(d5793),(d5794),(d5795),(d5796),(d5797),(d5798),(d5799),(d5800),(d5801),(d5802),(d5803),(d5804),(d5805),(d5806),(d5807),(d5808),(d5809),(d5810),(d5811),(d5812),(d5813),(d5814),(d5815),(d5816),(d5817),(d5818),(d5819),(d5820),(d5821),(d5822),(d5823),(d5824),(d5825),(d5826),(d5827),(d5828),(d5829),(d5830),(d5831),(d5832),(d5833),(d5834),(d5835),(d5836),(d5837),(d5838),(d5839),(d5840),(d5841),(d5842),(d5843),(d5844),(d5845),(d5846),(d5847),(d5848),(d5849),(d5850),(d5851),(d5852),(d5853),(d5854),(d5855),(d5856),(d5857),(d5858),(d5859),(d5860),(d5861),(d5862),(d5863),(d5864),(d5865),(d5866),(d5867),(d5868),(d5869),(d5870),(d5871),(d5872),(d5873),(d5874),(d5875),(d5876),(d5877),(d5878),(d5879),(d5880),(d5881),(d5882),(d5883),(d5884),(d5885),(d5886),(d5887),(d5888),(d5889),(d5890),(d5891),(d5892),(d5893),(d5894),(d5895),(d5896),(d5897),(d5898),(d5899),(d5900),(d5901),(d5902),(d5903),(d5904),(d5905),(d5906),(d5907),(d5908),(d5909),(d5910),(d5911),(d5912),(d5913),(d5914),(d5915),(d5916),(d5917),(d5918),(d5919),(d5920),(d5921),(d5922),(d5923),(d5924),(d5925),(d5926),(d5927),(d5928),(d5929),(d5930),(d5931),(d5932),(d5933),(d5934),(d5935),(d5936),(d5937),(d5938),(d5939),(d5940),(d5941),(d5942),(d5943),(d5944),(d5945),(d5946),(d5947),(d5948),(d5949),(d5950),(d5951),(d5952),(d5953),(d5954),(d5955),(d5956),(d5957),(d5958),(d5959),(d5960),(d5961),(d5962),(d5963),(d5964),(d5965),(d5966),(d5967),(d5968),(d5969),(d5970),(d5971),(d5972),(d5973),(d5974),(d5975),(d5976),(d5977),(d5978),(d5979),(d5980),(d5981),(d5982),(d5983),(d5984),(d5985),(d5986),(d5987),(d5988),(d5989),(d5990),(d5991),(d5992),(d5993),(d5994),(d5995),(d5996),(d5997),(d5998),(d5999),(d6000),(d6001),(d6002),(d6003),(d6004),(d6005),(d6006),(d6007),(d6008),(d6009),(d6010),(d6011),(d6012),(d6013),(d6014),(d6015),(d6016),(d6017),(d6018),(d6019),(d6020),(d6021),(d6022),(d6023),(d6024),(d6025),(d6026),(d6027),(d6028),(d6029),(d6030),(d6031),(d6032),(d6033),(d6034),(d6035),(d6036),(d6037),(d6038),(d6039),(d6040),(d6041),(d6042),(d6043),(d6044),(d6045),(d6046),(d6047),(d6048),(d6049),(d6050),(d6051),(d6052),(d6053),(d6054),(d6055),(d6056),(d6057),(d6058),(d6059),(d6060),(d6061),(d6062),(d6063),(d6064),(d6065),(d6066),(d6067),(d6068),(d6069),(d6070),(d6071),(d6072),(d6073),(d6074),(d6075),(d6076),(d6077),(d6078),(d6079),(d6080),(d6081),(d6082),(d6083),(d6084),(d6085),(d6086),(d6087),(d6088),(d6089),(d6090),(d6091),(d6092),(d6093),(d6094),(d6095),(d6096),(d6097),(d6098),(d6099),(d6100),(d6101),(d6102),(d6103),(d6104),(d6105),(d6106),(d6107),(d6108),(d6109),(d6110),(d6111),(d6112),(d6113),(d6114),(d6115),(d6116),(d6117),(d6118),(d6119),(d6120),(d6121),(d6122),(d6123),(d6124),(d6125),(d6126),(d6127),(d6128),(d6129),(d6130),(d6131),(d6132),(d6133),(d6134),(d6135),(d6136),(d6137),(d6138),(d6139),(d6140),(d6141),(d6142),(d6143),(d6144),(d6145),(d6146),(d6147),(d6148),(d6149),(d6150),(d6151),(d6152),(d6153),(d6154),(d6155),(d6156),(d6157),(d6158),(d6159),(d6160),(d6161),(d6162),(d6163),(d6164),(d6165),(d6166),(d6167),(d6168),(d6169),(d6170),(d6171),(d6172),(d6173),(d6174),(d6175),(d6176),(d6177),(d6178),(d6179),(d6180),(d6181),(d6182),(d6183),(d6184),(d6185),(d6186),(d6187),(d6188),(d6189),(d6190),(d6191),(d6192),(d6193),(d6194),(d6195),(d6196),(d6197),(d6198),(d6199),(d6200),(d6201),(d6202),(d6203),(d6204),(d6205),(d6206),(d6207),(d6208),(d6209),(d6210),(d6211),(d6212),(d6213),(d6214),(d6215),(d6216),(d6217),(d6218),(d6219),(d6220),(d6221),(d6222),(d6223),(d6224),(d6225),(d6226),(d6227),(d6228),(d6229),(d6230),(d6231),(d6232),(d6233),(d6234),(d6235),(d6236),(d6237),(d6238),(d6239),(d6240),(d6241),(d6242),(d6243),(d6244),(d6245),(d6246),(d6247),(d6248),(d6249),(d6250),(d6251),(d6252),(d6253),(d6254),(d6255),(d6256),(d6257),(d6258),(d6259),(d6260),(d6261),(d6262),(d6263),(d6264),(d6265),(d6266),(d6267),(d6268),(d6269),(d6270),(d6271),(d6272),(d6273),(d6274),(d6275),(d6276),(d6277),(d6278),(d6279),(d6280),(d6281),(d6282),(d6283),(d6284),(d6285),(d6286),(d6287),(d6288),(d6289),(d6290),(d6291),(d6292),(d6293),(d6294),(d6295),(d6296),(d6297),(d6298),(d6299),(d6300),(d6301),(d6302),(d6303),(d6304),(d6305),(d6306),(d6307),(d6308),(d6309),(d6310),(d6311),(d6312),(d6313),(d6314),(d6315),(d6316),(d6317),(d6318),(d6319),(d6320),(d6321),(d6322),(d6323),(d6324),(d6325),(d6326),(d6327),(d6328),(d6329),(d6330),(d6331),(d6332),(d6333),(d6334),(d6335),(d6336),(d6337),(d6338),(d6339),(d6340),(d6341),(d6342),(d6343),(d6344),(d6345),(d6346),(d6347),(d6348),(d6349),(d6350),(d6351),(d6352),(d6353),(d6354),(d6355),(d6356),(d6357),(d6358),(d6359),(d6360),(d6361),(d6362),(d6363),(d6364),(d6365),(d6366),(d6367),(d6368),(d6369),(d6370),(d6371),(d6372),(d6373),(d6374),(d6375),(d6376),(d6377),(d6378),(d6379),(d6380),(d6381),(d6382),(d6383),(d6384),(d6385),(d6386),(d6387),(d6388),(d6389),(d6390),(d6391),(d6392),(d6393),(d6394),(d6395),(d6396),(d6397),(d6398),(d6399),(d6400),(d6401),(d6402),(d6403),(d6404),(d6405),(d6406),(d6407),(d6408),(d6409),(d6410),(d6411),(d6412),(d6413),(d6414),(d6415),(d6416),(d6417),(d6418),(d6419),(d6420),(d6421),(d6422),(d6423),(d6424),(d6425),(d6426),(d6427),(d6428),(d6429),(d6430),(d6431),(d6432),(d6433),(d6434),(d6435),(d6436),(d6437),(d6438),(d6439),(d6440),(d6441),(d6442),(d6443),(d6444),(d6445),(d6446),(d6447),(d6448),(d6449),(d6450),(d6451),(d6452),(d6453),(d6454),(d6455),(d6456),(d6457),(d6458),(d6459),(d6460),(d6461),(d6462),(d6463),(d6464),(d6465),(d6466),(d6467),(d6468),(d6469),(d6470),(d6471),(d6472),(d6473),(d6474),(d6475),(d6476),(d6477),(d6478),(d6479),(d6480),(d6481),(d6482),(d6483),(d6484),(d6485),(d6486),(d6487),(d6488),(d6489),(d6490),(d6491),(d6492),(d6493),(d6494),(d6495),(d6496),(d6497),(d6498),(d6499),(d6500),(d6501),(d6502),(d6503),(d6504),(d6505),(d6506),(d6507),(d6508),(d6509),(d6510),(d6511),(d6512),(d6513),(d6514),(d6515),(d6516),(d6517),(d6518),(d6519),(d6520),(d6521),(d6522),(d6523),(d6524),(d6525),(d6526),(d6527),(d6528),(d6529),(d6530),(d6531),(d6532),(d6533),(d6534),(d6535),(d6536),(d6537),(d6538),(d6539),(d6540),(d6541),(d6542),(d6543),(d6544),(d6545),(d6546),(d6547),(d6548),(d6549),(d6550),(d6551),(d6552),(d6553),(d6554),(d6555),(d6556),(d6557),(d6558),(d6559),(d6560),(d6561),(d6562),(d6563),(d6564),(d6565),(d6566),(d6567),(d6568),(d6569),(d6570),(d6571),(d6572),(d6573),(d6574),(d6575),(d6576),(d6577),(d6578),(d6579),(d6580),(d6581),(d6582),(d6583),(d6584),(d6585),(d6586),(d6587),(d6588),(d6589),(d6590),(d6591),(d6592),(d6593),(d6594),(d6595),(d6596),(d6597),(d6598),(d6599),(d6600),(d6601),(d6602),(d6603),(d6604),(d6605),(d6606),(d6607),(d6608),(d6609),(d6610),(d6611),(d6612),(d6613),(d6614),(d6615),(d6616),(d6617),(d6618),(d6619),(d6620),(d6621),(d6622),(d6623),(d6624),(d6625),(d6626),(d6627),(d6628),(d6629),(d6630),(d6631),(d6632),(d6633),(d6634),(d6635),(d6636),(d6637),(d6638),(d6639),(d6640),(d6641),(d6642),(d6643),(d6644),(d6645),(d6646),(d6647),(d6648),(d6649),(d6650),(d6651),(d6652),(d6653),(d6654),(d6655),(d6656),(d6657),(d6658),(d6659),(d6660),(d6661),(d6662),(d6663),(d6664),(d6665),(d6666),(d6667),(d6668),(d6669),(d6670),(d6671),(d6672),(d6673),(d6674),(d6675),(d6676),(d6677),(d6678),(d6679),(d6680),(d6681),(d6682),(d6683),(d6684),(d6685),(d6686),(d6687),(d6688),(d6689),(d6690),(d6691),(d6692),(d6693),(d6694),(d6695),(d6696),(d6697),(d6698),(d6699),(d6700),(d6701),(d6702),(d6703),(d6704),(d6705),(d6706),(d6707),(d6708),(d6709),(d6710),(d6711),(d6712),(d6713),(d6714),(d6715),(d6716),(d6717),(d6718),(d6719),(d6720),(d6721),(d6722),(d6723),(d6724),(d6725),(d6726),(d6727),(d6728),(d6729),(d6730),(d6731),(d6732),(d6733),(d6734),(d6735),(d6736),(d6737),(d6738),(d6739),(d6740),(d6741),(d6742),(d6743),(d6744),(d6745),(d6746),(d6747),(d6748),(d6749),(d6750),(d6751),(d6752),(d6753),(d6754),(d6755),(d6756),(d6757),(d6758),(d6759),(d6760),(d6761),(d6762),(d6763),(d6764),(d6765),(d6766),(d6767),(d6768),(d6769),(d6770),(d6771),(d6772),(d6773),(d6774),(d6775),(d6776),(d6777),(d6778),(d6779),(d6780),(d6781),(d6782),(d6783),(d6784),(d6785),(d6786),(d6787),(d6788),(d6789),(d6790),(d6791),(d6792),(d6793),(d6794),(d6795),(d6796),(d6797),(d6798),(d6799),(d6800),(d6801),(d6802),(d6803),(d6804),(d6805),(d6806),(d6807),(d6808),(d6809),(d6810),(d6811),(d6812),(d6813),(d6814),(d6815),(d6816),(d6817),(d6818),(d6819),(d6820),(d6821),(d6822),(d6823),(d6824),(d6825),(d6826),(d6827),(d6828),(d6829),(d6830),(d6831),(d6832),(d6833),(d6834),(d6835),(d6836),(d6837),(d6838),(d6839),(d6840),(d6841),(d6842),(d6843),(d6844),(d6845),(d6846),(d6847),(d6848),(d6849),(d6850),(d6851),(d6852),(d6853),(d6854),(d6855),(d6856),(d6857),(d6858),(d6859),(d6860),(d6861),(d6862),(d6863),(d6864),(d6865),(d6866),(d6867),(d6868),(d6869),(d6870),(d6871),(d6872),(d6873),(d6874),(d6875),(d6876),(d6877),(d6878),(d6879),(d6880),(d6881),(d6882),(d6883),(d6884),(d6885),(d6886),(d6887),(d6888),(d6889),(d6890),(d6891),(d6892),(d6893),(d6894),(d6895),(d6896),(d6897),(d6898),(d6899),(d6900),(d6901),(d6902),(d6903),(d6904),(d6905),(d6906),(d6907),(d6908),(d6909),(d6910),(d6911),(d6912),(d6913),(d6914),(d6915),(d6916),(d6917),(d6918),(d6919),(d6920),(d6921),(d6922),(d6923),(d6924),(d6925),(d6926),(d6927),(d6928),(d6929),(d6930),(d6931),(d6932),(d6933),(d6934),(d6935),(d6936),(d6937),(d6938),(d6939),(d6940),(d6941),(d6942),(d6943),(d6944),(d6945),(d6946),(d6947),(d6948),(d6949),(d6950),(d6951),(d6952),(d6953),(d6954),(d6955),(d6956),(d6957),(d6958),(d6959),(d6960),(d6961),(d6962),(d6963),(d6964),(d6965),(d6966),(d6967),(d6968),(d6969),(d6970),(d6971),(d6972),(d6973),(d6974),(d6975),(d6976),(d6977),(d6978),(d6979),(d6980),(d6981),(d6982),(d6983),(d6984),(d6985),(d6986),(d6987),(d6988),(d6989),(d6990),(d6991),(d6992),(d6993),(d6994),(d6995),(d6996),(d6997),(d6998),(d6999),(d7000),(d7001),(d7002),(d7003),(d7004),(d7005),(d7006),(d7007),(d7008),(d7009),(d7010),(d7011),(d7012),(d7013),(d7014),(d7015),(d7016),(d7017),(d7018),(d7019),(d7020),(d7021),(d7022),(d7023),(d7024),(d7025),(d7026),(d7027),(d7028),(d7029),(d7030),(d7031),(d7032),(d7033),(d7034),(d7035),(d7036),(d7037),(d7038),(d7039),(d7040),(d7041),(d7042),(d7043),(d7044),(d7045),(d7046),(d7047),(d7048),(d7049),(d7050),(d7051),(d7052),(d7053),(d7054),(d7055),(d7056),(d7057),(d7058),(d7059),(d7060),(d7061),(d7062),(d7063),(d7064),(d7065),(d7066),(d7067),(d7068),(d7069),(d7070),(d7071),(d7072),(d7073),(d7074),(d7075),(d7076),(d7077),(d7078),(d7079),(d7080),(d7081),(d7082),(d7083),(d7084),(d7085),(d7086),(d7087),(d7088),(d7089),(d7090),(d7091),(d7092),(d7093),(d7094),(d7095),(d7096),(d7097),(d7098),(d7099),(d7100),(d7101),(d7102),(d7103),(d7104),(d7105),(d7106),(d7107),(d7108),(d7109),(d7110),(d7111),(d7112),(d7113),(d7114),(d7115),(d7116),(d7117),(d7118),(d7119),(d7120),(d7121),(d7122),(d7123),(d7124),(d7125),(d7126),(d7127),(d7128),(d7129),(d7130),(d7131),(d7132),(d7133),(d7134),(d7135),(d7136),(d7137),(d7138),(d7139),(d7140),(d7141),(d7142),(d7143),(d7144),(d7145),(d7146),(d7147),(d7148),(d7149),(d7150),(d7151),(d7152),(d7153),(d7154),(d7155),(d7156),(d7157),(d7158),(d7159),(d7160),(d7161),(d7162),(d7163),(d7164),(d7165),(d7166),(d7167),(d7168),(d7169),(d7170),(d7171),(d7172),(d7173),(d7174),(d7175),(d7176),(d7177),(d7178),(d7179),(d7180),(d7181),(d7182),(d7183),(d7184),(d7185),(d7186),(d7187),(d7188),(d7189),(d7190),(d7191),(d7192),(d7193),(d7194),(d7195),(d7196),(d7197),(d7198),(d7199),(d7200),(d7201),(d7202),(d7203),(d7204),(d7205),(d7206),(d7207),(d7208),(d7209),(d7210),(d7211),(d7212),(d7213),(d7214),(d7215),(d7216),(d7217),(d7218),(d7219),(d7220),(d7221),(d7222),(d7223),(d7224),(d7225),(d7226),(d7227),(d7228),(d7229),(d7230),(d7231),(d7232),(d7233),(d7234),(d7235),(d7236),(d7237),(d7238),(d7239),(d7240),(d7241),(d7242),(d7243),(d7244),(d7245),(d7246),(d7247),(d7248),(d7249),(d7250),(d7251),(d7252),(d7253),(d7254),(d7255),(d7256),(d7257),(d7258),(d7259),(d7260),(d7261),(d7262),(d7263),(d7264),(d7265),(d7266),(d7267),(d7268),(d7269),(d7270),(d7271),(d7272),(d7273),(d7274),(d7275),(d7276),(d7277),(d7278),(d7279),(d7280),(d7281),(d7282),(d7283),(d7284),(d7285),(d7286),(d7287),(d7288),(d7289),(d7290),(d7291),(d7292),(d7293),(d7294),(d7295),(d7296),(d7297),(d7298),(d7299),(d7300),(d7301),(d7302),(d7303),(d7304),(d7305),(d7306),(d7307),(d7308),(d7309),(d7310),(d7311),(d7312),(d7313),(d7314),(d7315),(d7316),(d7317),(d7318),(d7319),(d7320),(d7321),(d7322),(d7323),(d7324),(d7325),(d7326),(d7327),(d7328),(d7329),(d7330),(d7331),(d7332),(d7333),(d7334),(d7335),(d7336),(d7337),(d7338),(d7339),(d7340),(d7341),(d7342),(d7343),(d7344),(d7345),(d7346),(d7347),(d7348),(d7349),(d7350),(d7351),(d7352),(d7353),(d7354),(d7355),(d7356),(d7357),(d7358),(d7359),(d7360),(d7361),(d7362),(d7363),(d7364),(d7365),(d7366),(d7367),(d7368),(d7369),(d7370),(d7371),(d7372),(d7373),(d7374),(d7375),(d7376),(d7377),(d7378),(d7379),(d7380),(d7381),(d7382),(d7383),(d7384),(d7385),(d7386),(d7387),(d7388),(d7389),(d7390),(d7391),(d7392),(d7393),(d7394),(d7395),(d7396),(d7397),(d7398),(d7399),(d7400),(d7401),(d7402),(d7403),(d7404),(d7405),(d7406),(d7407),(d7408),(d7409),(d7410),(d7411),(d7412),(d7413),(d7414),(d7415),(d7416),(d7417),(d7418),(d7419),(d7420),(d7421),(d7422),(d7423),(d7424),(d7425),(d7426),(d7427),(d7428),(d7429),(d7430),(d7431),(d7432),(d7433),(d7434),(d7435),(d7436),(d7437),(d7438),(d7439),(d7440),(d7441),(d7442),(d7443),(d7444),(d7445),(d7446),(d7447),(d7448),(d7449),(d7450),(d7451),(d7452),(d7453),(d7454),(d7455),(d7456),(d7457),(d7458),(d7459),(d7460),(d7461),(d7462),(d7463),(d7464),(d7465),(d7466),(d7467),(d7468),(d7469),(d7470),(d7471),(d7472),(d7473),(d7474),(d7475),(d7476),(d7477),(d7478),(d7479),(d7480),(d7481),(d7482),(d7483),(d7484),(d7485),(d7486),(d7487),(d7488),(d7489),(d7490),(d7491),(d7492),(d7493),(d7494),(d7495),(d7496),(d7497),(d7498),(d7499),(d7500),(d7501),(d7502),(d7503),(d7504),(d7505),(d7506),(d7507),(d7508),(d7509),(d7510),(d7511),(d7512),(d7513),(d7514),(d7515),(d7516),(d7517),(d7518),(d7519),(d7520),(d7521),(d7522),(d7523),(d7524),(d7525),(d7526),(d7527),(d7528),(d7529),(d7530),(d7531),(d7532),(d7533),(d7534),(d7535),(d7536),(d7537),(d7538),(d7539),(d7540),(d7541),(d7542),(d7543),(d7544),(d7545),(d7546),(d7547),(d7548),(d7549),(d7550),(d7551),(d7552),(d7553),(d7554),(d7555),(d7556),(d7557),(d7558),(d7559),(d7560),(d7561),(d7562),(d7563),(d7564),(d7565),(d7566),(d7567),(d7568),(d7569),(d7570),(d7571),(d7572),(d7573),(d7574),(d7575),(d7576),(d7577),(d7578),(d7579),(d7580),(d7581),(d7582),(d7583),(d7584),(d7585),(d7586),(d7587),(d7588),(d7589),(d7590),(d7591),(d7592),(d7593),(d7594),(d7595),(d7596),(d7597),(d7598),(d7599),(d7600),(d7601),(d7602),(d7603),(d7604),(d7605),(d7606),(d7607),(d7608),(d7609),(d7610),(d7611),(d7612),(d7613),(d7614),(d7615),(d7616),(d7617),(d7618),(d7619),(d7620),(d7621),(d7622),(d7623),(d7624),(d7625),(d7626),(d7627),(d7628),(d7629),(d7630),(d7631),(d7632),(d7633),(d7634),(d7635),(d7636),(d7637),(d7638),(d7639),(d7640),(d7641),(d7642),(d7643),(d7644),(d7645),(d7646),(d7647),(d7648),(d7649),(d7650),(d7651),(d7652),(d7653),(d7654),(d7655),(d7656),(d7657),(d7658),(d7659),(d7660),(d7661),(d7662),(d7663),(d7664),(d7665),(d7666),(d7667),(d7668),(d7669),(d7670),(d7671),(d7672),(d7673),(d7674),(d7675),(d7676),(d7677),(d7678),(d7679),(d7680),(d7681),(d7682),(d7683),(d7684),(d7685),(d7686),(d7687),(d7688),(d7689),(d7690),(d7691),(d7692),(d7693),(d7694),(d7695),(d7696),(d7697),(d7698),(d7699),(d7700),(d7701),(d7702),(d7703),(d7704),(d7705),(d7706),(d7707),(d7708),(d7709),(d7710),(d7711),(d7712),(d7713),(d7714),(d7715),(d7716),(d7717),(d7718),(d7719),(d7720),(d7721),(d7722),(d7723),(d7724),(d7725),(d7726),(d7727),(d7728),(d7729),(d7730),(d7731),(d7732),(d7733),(d7734),(d7735),(d7736),(d7737),(d7738),(d7739),(d7740),(d7741),(d7742),(d7743),(d7744),(d7745),(d7746),(d7747),(d7748),(d7749),(d7750),(d7751),(d7752),(d7753),(d7754),(d7755),(d7756),(d7757),(d7758),(d7759),(d7760),(d7761),(d7762),(d7763),(d7764),(d7765),(d7766),(d7767),(d7768),(d7769),(d7770),(d7771),(d7772),(d7773),(d7774),(d7775),(d7776),(d7777),(d7778),(d7779),(d7780),(d7781),(d7782),(d7783),(d7784),(d7785),(d7786),(d7787),(d7788),(d7789),(d7790),(d7791),(d7792),(d7793),(d7794),(d7795),(d7796),(d7797),(d7798),(d7799),(d7800),(d7801),(d7802),(d7803),(d7804),(d7805),(d7806),(d7807),(d7808),(d7809),(d7810),(d7811),(d7812),(d7813),(d7814),(d7815),(d7816),(d7817),(d7818),(d7819),(d7820),(d7821),(d7822),(d7823),(d7824),(d7825),(d7826),(d7827),(d7828),(d7829),(d7830),(d7831),(d7832),(d7833),(d7834),(d7835),(d7836),(d7837),(d7838),(d7839),(d7840),(d7841),(d7842),(d7843),(d7844),(d7845),(d7846),(d7847),(d7848),(d7849),(d7850),(d7851),(d7852),(d7853),(d7854),(d7855),(d7856),(d7857),(d7858),(d7859),(d7860),(d7861),(d7862),(d7863),(d7864),(d7865),(d7866),(d7867),(d7868),(d7869),(d7870),(d7871),(d7872),(d7873),(d7874),(d7875),(d7876),(d7877),(d7878),(d7879),(d7880),(d7881),(d7882),(d7883),(d7884),(d7885),(d7886),(d7887),(d7888),(d7889),(d7890),(d7891),(d7892),(d7893),(d7894),(d7895),(d7896),(d7897),(d7898),(d7899),(d7900),(d7901),(d7902),(d7903),(d7904),(d7905),(d7906),(d7907),(d7908),(d7909),(d7910),(d7911),(d7912),(d7913),(d7914),(d7915),(d7916),(d7917),(d7918),(d7919),(d7920),(d7921),(d7922),(d7923),(d7924),(d7925),(d7926),(d7927),(d7928),(d7929),(d7930),(d7931),(d7932),(d7933),(d7934),(d7935),(d7936),(d7937),(d7938),(d7939),(d7940),(d7941),(d7942),(d7943),(d7944),(d7945),(d7946),(d7947),(d7948),(d7949),(d7950),(d7951),(d7952),(d7953),(d7954),(d7955),(d7956),(d7957),(d7958),(d7959),(d7960),(d7961),(d7962),(d7963),(d7964),(d7965),(d7966),(d7967),(d7968),(d7969),(d7970),(d7971),(d7972),(d7973),(d7974),(d7975),(d7976),(d7977),(d7978),(d7979),(d7980),(d7981),(d7982),(d7983),(d7984),(d7985),(d7986),(d7987),(d7988),(d7989),(d7990),(d7991),(d7992),(d7993),(d7994),(d7995),(d7996),(d7997),(d7998),(d7999),(d8000),(d8001),(d8002),(d8003),(d8004),(d8005),(d8006),(d8007),(d8008),(d8009),(d8010),(d8011),(d8012),(d8013),(d8014),(d8015),(d8016),(d8017),(d8018),(d8019),(d8020),(d8021),(d8022),(d8023),(d8024),(d8025),(d8026),(d8027),(d8028),(d8029),(d8030),(d8031),(d8032),(d8033),(d8034),(d8035),(d8036),(d8037),(d8038),(d8039),(d8040),(d8041),(d8042),(d8043),(d8044),(d8045),(d8046),(d8047),(d8048),(d8049),(d8050),(d8051),(d8052),(d8053),(d8054),(d8055),(d8056),(d8057),(d8058),(d8059),(d8060),(d8061),(d8062),(d8063),(d8064),(d8065),(d8066),(d8067),(d8068),(d8069),(d8070),(d8071),(d8072),(d8073),(d8074),(d8075),(d8076),(d8077),(d8078),(d8079),(d8080),(d8081),(d8082),(d8083),(d8084),(d8085),(d8086),(d8087),(d8088),(d8089),(d8090),(d8091),(d8092),(d8093),(d8094),(d8095),(d8096),(d8097),(d8098),(d8099),(d8100),(d8101),(d8102),(d8103),(d8104),(d8105),(d8106),(d8107),(d8108),(d8109),(d8110),(d8111),(d8112),(d8113),(d8114),(d8115),(d8116),(d8117),(d8118),(d8119),(d8120),(d8121),(d8122),(d8123),(d8124),(d8125),(d8126),(d8127),(d8128),(d8129),(d8130),(d8131),(d8132),(d8133),(d8134),(d8135),(d8136),(d8137),(d8138),(d8139),(d8140),(d8141),(d8142),(d8143),(d8144),(d8145),(d8146),(d8147),(d8148),(d8149),(d8150),(d8151),(d8152),(d8153),(d8154),(d8155),(d8156),(d8157),(d8158),(d8159),(d8160),(d8161),(d8162),(d8163),(d8164),(d8165),(d8166),(d8167),(d8168),(d8169),(d8170),(d8171),(d8172),(d8173),(d8174),(d8175),(d8176),(d8177),(d8178),(d8179),(d8180),(d8181),(d8182),(d8183),(d8184),(d8185),(d8186),(d8187),(d8188),(d8189),(d8190),(d8191),(d8192),(d8193),(d8194),(d8195),(d8196),(d8197),(d8198),(d8199),(d8200),(d8201),(d8202),(d8203),(d8204),(d8205),(d8206),(d8207),(d8208),(d8209),(d8210),(d8211),(d8212),(d8213),(d8214),(d8215),(d8216),(d8217),(d8218),(d8219),(d8220),(d8221),(d8222),(d8223),(d8224),(d8225),(d8226),(d8227),(d8228),(d8229),(d8230),(d8231),(d8232),(d8233),(d8234),(d8235),(d8236),(d8237),(d8238),(d8239),(d8240),(d8241),(d8242),(d8243),(d8244),(d8245),(d8246),(d8247),(d8248),(d8249),(d8250),(d8251),(d8252),(d8253),(d8254),(d8255),(d8256),(d8257),(d8258),(d8259),(d8260),(d8261),(d8262),(d8263),(d8264),(d8265),(d8266),(d8267),(d8268),(d8269),(d8270),(d8271),(d8272),(d8273),(d8274),(d8275),(d8276),(d8277),(d8278),(d8279),(d8280),(d8281),(d8282),(d8283),(d8284),(d8285),(d8286),(d8287),(d8288),(d8289),(d8290),(d8291),(d8292),(d8293),(d8294),(d8295),(d8296),(d8297),(d8298),(d8299),(d8300),(d8301),(d8302),(d8303),(d8304),(d8305),(d8306),(d8307),(d8308),(d8309),(d8310),(d8311),(d8312),(d8313),(d8314),(d8315),(d8316),(d8317),(d8318),(d8319),(d8320),(d8321),(d8322),(d8323),(d8324),(d8325),(d8326),(d8327),(d8328),(d8329),(d8330),(d8331),(d8332),(d8333),(d8334),(d8335),(d8336),(d8337),(d8338),(d8339),(d8340),(d8341),(d8342),(d8343),(d8344),(d8345),(d8346),(d8347),(d8348),(d8349),(d8350),(d8351),(d8352),(d8353),(d8354),(d8355),(d8356),(d8357),(d8358),(d8359),(d8360),(d8361),(d8362),(d8363),(d8364),(d8365),(d8366),(d8367),(d8368),(d8369),(d8370),(d8371),(d8372),(d8373),(d8374),(d8375),(d8376),(d8377),(d8378),(d8379),(d8380),(d8381),(d8382),(d8383),(d8384),(d8385),(d8386),(d8387),(d8388),(d8389),(d8390),(d8391),(d8392),(d8393),(d8394),(d8395),(d8396),(d8397),(d8398),(d8399),(d8400),(d8401),(d8402),(d8403),(d8404),(d8405),(d8406),(d8407),(d8408),(d8409),(d8410),(d8411),(d8412),(d8413),(d8414),(d8415),(d8416),(d8417),(d8418),(d8419),(d8420),(d8421),(d8422),(d8423),(d8424),(d8425),(d8426),(d8427),(d8428),(d8429),(d8430),(d8431),(d8432),(d8433),(d8434),(d8435),(d8436),(d8437),(d8438),(d8439),(d8440),(d8441),(d8442),(d8443),(d8444),(d8445),(d8446),(d8447),(d8448),(d8449),(d8450),(d8451),(d8452),(d8453),(d8454),(d8455),(d8456),(d8457),(d8458),(d8459),(d8460),(d8461),(d8462),(d8463),(d8464),(d8465),(d8466),(d8467),(d8468),(d8469),(d8470),(d8471),(d8472),(d8473),(d8474),(d8475),(d8476),(d8477),(d8478),(d8479),(d8480),(d8481),(d8482),(d8483),(d8484),(d8485),(d8486),(d8487),(d8488),(d8489),(d8490),(d8491),(d8492),(d8493),(d8494),(d8495),(d8496),(d8497),(d8498),(d8499),(d8500),(d8501),(d8502),(d8503),(d8504),(d8505),(d8506),(d8507),(d8508),(d8509),(d8510),(d8511),(d8512),(d8513),(d8514),(d8515),(d8516),(d8517),(d8518),(d8519),(d8520),(d8521),(d8522),(d8523),(d8524),(d8525),(d8526),(d8527),(d8528),(d8529),(d8530),(d8531),(d8532),(d8533),(d8534),(d8535),(d8536),(d8537),(d8538),(d8539),(d8540),(d8541),(d8542),(d8543),(d8544),(d8545),(d8546),(d8547),(d8548),(d8549),(d8550),(d8551),(d8552),(d8553),(d8554),(d8555),(d8556),(d8557),(d8558),(d8559),(d8560),(d8561),(d8562),(d8563),(d8564),(d8565),(d8566),(d8567),(d8568),(d8569),(d8570),(d8571),(d8572),(d8573),(d8574),(d8575),(d8576),(d8577),(d8578),(d8579),(d8580),(d8581),(d8582),(d8583),(d8584),(d8585),(d8586),(d8587),(d8588),(d8589),(d8590),(d8591),(d8592),(d8593),(d8594),(d8595),(d8596),(d8597),(d8598),(d8599),(d8600),(d8601),(d8602),(d8603),(d8604),(d8605),(d8606),(d8607),(d8608),(d8609),(d8610),(d8611),(d8612),(d8613),(d8614),(d8615),(d8616),(d8617),(d8618),(d8619),(d8620),(d8621),(d8622),(d8623),(d8624),(d8625),(d8626),(d8627),(d8628),(d8629),(d8630),(d8631),(d8632),(d8633),(d8634),(d8635),(d8636),(d8637),(d8638),(d8639),(d8640),(d8641),(d8642),(d8643),(d8644),(d8645),(d8646),(d8647),(d8648),(d8649),(d8650),(d8651),(d8652),(d8653),(d8654),(d8655),(d8656),(d8657),(d8658),(d8659),(d8660),(d8661),(d8662),(d8663),(d8664),(d8665),(d8666),(d8667),(d8668),(d8669),(d8670),(d8671),(d8672),(d8673),(d8674),(d8675),(d8676),(d8677),(d8678),(d8679),(d8680),(d8681),(d8682),(d8683),(d8684),(d8685),(d8686),(d8687),(d8688),(d8689),(d8690),(d8691),(d8692),(d8693),(d8694),(d8695),(d8696),(d8697),(d8698),(d8699),(d8700),(d8701),(d8702),(d8703),(d8704),(d8705),(d8706),(d8707),(d8708),(d8709),(d8710),(d8711),(d8712),(d8713),(d8714),(d8715),(d8716),(d8717),(d8718),(d8719),(d8720),(d8721),(d8722),(d8723),(d8724),(d8725),(d8726),(d8727),(d8728),(d8729),(d8730),(d8731),(d8732),(d8733),(d8734),(d8735),(d8736),(d8737),(d8738),(d8739),(d8740),(d8741),(d8742),(d8743),(d8744),(d8745),(d8746),(d8747),(d8748),(d8749),(d8750),(d8751),(d8752),(d8753),(d8754),(d8755),(d8756),(d8757),(d8758),(d8759),(d8760),(d8761),(d8762),(d8763),(d8764),(d8765),(d8766),(d8767),(d8768),(d8769),(d8770),(d8771),(d8772),(d8773),(d8774),(d8775),(d8776),(d8777),(d8778),(d8779),(d8780),(d8781),(d8782),(d8783),(d8784),(d8785),(d8786),(d8787),(d8788),(d8789),(d8790),(d8791),(d8792),(d8793),(d8794),(d8795),(d8796),(d8797),(d8798),(d8799),(d8800),(d8801),(d8802),(d8803),(d8804),(d8805),(d8806),(d8807),(d8808),(d8809),(d8810),(d8811),(d8812),(d8813),(d8814),(d8815),(d8816),(d8817),(d8818),(d8819),(d8820),(d8821),(d8822),(d8823),(d8824),(d8825),(d8826),(d8827),(d8828),(d8829),(d8830),(d8831),(d8832),(d8833),(d8834),(d8835),(d8836),(d8837),(d8838),(d8839),(d8840),(d8841),(d8842),(d8843),(d8844),(d8845),(d8846),(d8847),(d8848),(d8849),(d8850),(d8851),(d8852),(d8853),(d8854),(d8855),(d8856),(d8857),(d8858),(d8859),(d8860),(d8861),(d8862),(d8863),(d8864),(d8865),(d8866),(d8867),(d8868),(d8869),(d8870),(d8871),(d8872),(d8873),(d8874),(d8875),(d8876),(d8877),(d8878),(d8879),(d8880),(d8881),(d8882),(d8883),(d8884),(d8885),(d8886),(d8887),(d8888),(d8889),(d8890),(d8891),(d8892),(d8893),(d8894),(d8895),(d8896),(d8897),(d8898),(d8899),(d8900),(d8901),(d8902),(d8903),(d8904),(d8905),(d8906),(d8907),(d8908),(d8909),(d8910),(d8911),(d8912),(d8913),(d8914),(d8915),(d8916),(d8917),(d8918),(d8919),(d8920),(d8921),(d8922),(d8923),(d8924),(d8925),(d8926),(d8927),(d8928),(d8929),(d8930),(d8931),(d8932),(d8933),(d8934),(d8935),(d8936),(d8937),(d8938),(d8939),(d8940),(d8941),(d8942),(d8943),(d8944),(d8945),(d8946),(d8947),(d8948),(d8949),(d8950),(d8951),(d8952),(d8953),(d8954),(d8955),(d8956),(d8957),(d8958),(d8959),(d8960),(d8961),(d8962),(d8963),(d8964),(d8965),(d8966),(d8967),(d8968),(d8969),(d8970),(d8971),(d8972),(d8973),(d8974),(d8975),(d8976),(d8977),(d8978),(d8979),(d8980),(d8981),(d8982),(d8983),(d8984),(d8985),(d8986),(d8987),(d8988),(d8989),(d8990),(d8991),(d8992),(d8993),(d8994),(d8995),(d8996),(d8997),(d8998),(d8999),(d9000),(d9001),(d9002),(d9003),(d9004),(d9005),(d9006),(d9007),(d9008),(d9009),(d9010),(d9011),(d9012),(d9013),(d9014),(d9015),(d9016),(d9017),(d9018),(d9019),(d9020),(d9021),(d9022),(d9023),(d9024),(d9025),(d9026),(d9027),(d9028),(d9029),(d9030),(d9031),(d9032),(d9033),(d9034),(d9035),(d9036),(d9037),(d9038),(d9039),(d9040),(d9041),(d9042),(d9043),(d9044),(d9045),(d9046),(d9047),(d9048),(d9049),(d9050),(d9051),(d9052),(d9053),(d9054),(d9055),(d9056),(d9057),(d9058),(d9059),(d9060),(d9061),(d9062),(d9063),(d9064),(d9065),(d9066),(d9067),(d9068),(d9069),(d9070),(d9071),(d9072),(d9073),(d9074),(d9075),(d9076),(d9077),(d9078),(d9079),(d9080),(d9081),(d9082),(d9083),(d9084),(d9085),(d9086),(d9087),(d9088),(d9089),(d9090),(d9091),(d9092),(d9093),(d9094),(d9095),(d9096),(d9097),(d9098),(d9099),(d9100),(d9101),(d9102),(d9103),(d9104),(d9105),(d9106),(d9107),(d9108),(d9109),(d9110),(d9111),(d9112),(d9113),(d9114),(d9115),(d9116),(d9117),(d9118),(d9119),(d9120),(d9121),(d9122),(d9123),(d9124),(d9125),(d9126),(d9127),(d9128),(d9129),(d9130),(d9131),(d9132),(d9133),(d9134),(d9135),(d9136),(d9137),(d9138),(d9139),(d9140),(d9141),(d9142),(d9143),(d9144),(d9145),(d9146),(d9147),(d9148),(d9149),(d9150),(d9151),(d9152),(d9153),(d9154),(d9155),(d9156),(d9157),(d9158),(d9159),(d9160),(d9161),(d9162),(d9163),(d9164),(d9165),(d9166),(d9167),(d9168),(d9169),(d9170),(d9171),(d9172),(d9173),(d9174),(d9175),(d9176),(d9177),(d9178),(d9179),(d9180),(d9181),(d9182),(d9183),(d9184),(d9185),(d9186),(d9187),(d9188),(d9189),(d9190),(d9191),(d9192),(d9193),(d9194),(d9195),(d9196),(d9197),(d9198),(d9199),(d9200),(d9201),(d9202),(d9203),(d9204),(d9205),(d9206),(d9207),(d9208),(d9209),(d9210),(d9211),(d9212),(d9213),(d9214),(d9215),(d9216),(d9217),(d9218),(d9219),(d9220),(d9221),(d9222),(d9223),(d9224),(d9225),(d9226),(d9227),(d9228),(d9229),(d9230),(d9231),(d9232),(d9233),(d9234),(d9235),(d9236),(d9237),(d9238),(d9239),(d9240),(d9241),(d9242),(d9243),(d9244),(d9245),(d9246),(d9247),(d9248),(d9249),(d9250),(d9251),(d9252),(d9253),(d9254),(d9255),(d9256),(d9257),(d9258),(d9259),(d9260),(d9261),(d9262),(d9263),(d9264),(d9265),(d9266),(d9267),(d9268),(d9269),(d9270),(d9271),(d9272),(d9273),(d9274),(d9275),(d9276),(d9277),(d9278),(d9279),(d9280),(d9281),(d9282),(d9283),(d9284),(d9285),(d9286),(d9287),(d9288),(d9289),(d9290),(d9291),(d9292),(d9293),(d9294),(d9295),(d9296),(d9297),(d9298),(d9299),(d9300),(d9301),(d9302),(d9303),(d9304),(d9305),(d9306),(d9307),(d9308),(d9309),(d9310),(d9311),(d9312),(d9313),(d9314),(d9315),(d9316),(d9317),(d9318),(d9319),(d9320),(d9321),(d9322),(d9323),(d9324),(d9325),(d9326),(d9327),(d9328),(d9329),(d9330),(d9331),(d9332),(d9333),(d9334),(d9335),(d9336),(d9337),(d9338),(d9339),(d9340),(d9341),(d9342),(d9343),(d9344),(d9345),(d9346),(d9347),(d9348),(d9349),(d9350),(d9351),(d9352),(d9353),(d9354),(d9355),(d9356),(d9357),(d9358),(d9359),(d9360),(d9361),(d9362),(d9363),(d9364),(d9365),(d9366),(d9367),(d9368),(d9369),(d9370),(d9371),(d9372),(d9373),(d9374),(d9375),(d9376),(d9377),(d9378),(d9379),(d9380),(d9381),(d9382),(d9383),(d9384),(d9385),(d9386),(d9387),(d9388),(d9389),(d9390),(d9391),(d9392),(d9393),(d9394),(d9395),(d9396),(d9397),(d9398),(d9399),(d9400),(d9401),(d9402),(d9403),(d9404),(d9405),(d9406),(d9407),(d9408),(d9409),(d9410),(d9411),(d9412),(d9413),(d9414),(d9415),(d9416),(d9417),(d9418),(d9419),(d9420),(d9421),(d9422),(d9423),(d9424),(d9425),(d9426),(d9427),(d9428),(d9429),(d9430),(d9431),(d9432),(d9433),(d9434),(d9435),(d9436),(d9437),(d9438),(d9439),(d9440),(d9441),(d9442),(d9443),(d9444),(d9445),(d9446),(d9447),(d9448),(d9449),(d9450),(d9451),(d9452),(d9453),(d9454),(d9455),(d9456),(d9457),(d9458),(d9459),(d9460),(d9461),(d9462),(d9463),(d9464),(d9465),(d9466),(d9467),(d9468),(d9469),(d9470),(d9471),(d9472),(d9473),(d9474),(d9475),(d9476),(d9477),(d9478),(d9479),(d9480),(d9481),(d9482),(d9483),(d9484),(d9485),(d9486),(d9487),(d9488),(d9489),(d9490),(d9491),(d9492),(d9493),(d9494),(d9495),(d9496),(d9497),(d9498),(d9499),(d9500),(d9501),(d9502),(d9503),(d9504),(d9505),(d9506),(d9507),(d9508),(d9509),(d9510),(d9511),(d9512),(d9513),(d9514),(d9515),(d9516),(d9517),(d9518),(d9519),(d9520),(d9521),(d9522),(d9523),(d9524),(d9525),(d9526),(d9527),(d9528),(d9529),(d9530),(d9531),(d9532),(d9533),(d9534),(d9535),(d9536),(d9537),(d9538),(d9539),(d9540),(d9541),(d9542),(d9543),(d9544),(d9545),(d9546),(d9547),(d9548),(d9549),(d9550),(d9551),(d9552),(d9553),(d9554),(d9555),(d9556),(d9557),(d9558),(d9559),(d9560),(d9561),(d9562),(d9563),(d9564),(d9565),(d9566),(d9567),(d9568),(d9569),(d9570),(d9571),(d9572),(d9573),(d9574),(d9575),(d9576),(d9577),(d9578),(d9579),(d9580),(d9581),(d9582),(d9583),(d9584),(d9585),(d9586),(d9587),(d9588),(d9589),(d9590),(d9591),(d9592),(d9593),(d9594),(d9595),(d9596),(d9597),(d9598),(d9599),(d9600),(d9601),(d9602),(d9603),(d9604),(d9605),(d9606),(d9607),(d9608),(d9609),(d9610),(d9611),(d9612),(d9613),(d9614),(d9615),(d9616),(d9617),(d9618),(d9619),(d9620),(d9621),(d9622),(d9623),(d9624),(d9625),(d9626),(d9627),(d9628),(d9629),(d9630),(d9631),(d9632),(d9633),(d9634),(d9635),(d9636),(d9637),(d9638),(d9639),(d9640),(d9641),(d9642),(d9643),(d9644),(d9645),(d9646),(d9647),(d9648),(d9649),(d9650),(d9651),(d9652),(d9653),(d9654),(d9655),(d9656),(d9657),(d9658),(d9659),(d9660),(d9661),(d9662),(d9663),(d9664),(d9665),(d9666),(d9667),(d9668),(d9669),(d9670),(d9671),(d9672),(d9673),(d9674),(d9675),(d9676),(d9677),(d9678),(d9679),(d9680),(d9681),(d9682),(d9683),(d9684),(d9685),(d9686),(d9687),(d9688),(d9689),(d9690),(d9691),(d9692),(d9693),(d9694),(d9695),(d9696),(d9697),(d9698),(d9699),(d9700),(d9701),(d9702),(d9703),(d9704),(d9705),(d9706),(d9707),(d9708),(d9709),(d9710),(d9711),(d9712),(d9713),(d9714),(d9715),(d9716),(d9717),(d9718),(d9719),(d9720),(d9721),(d9722),(d9723),(d9724),(d9725),(d9726),(d9727),(d9728),(d9729),(d9730),(d9731),(d9732),(d9733),(d9734),(d9735),(d9736),(d9737),(d9738),(d9739),(d9740),(d9741),(d9742),(d9743),(d9744),(d9745),(d9746),(d9747),(d9748),(d9749),(d9750),(d9751),(d9752),(d9753),(d9754),(d9755),(d9756),(d9757),(d9758),(d9759),(d9760),(d9761),(d9762),(d9763),(d9764),(d9765),(d9766),(d9767),(d9768),(d9769),(d9770),(d9771),(d9772),(d9773),(d9774),(d9775),(d9776),(d9777),(d9778),(d9779),(d9780),(d9781),(d9782),(d9783),(d9784),(d9785),(d9786),(d9787),(d9788),(d9789),(d9790),(d9791),(d9792),(d9793),(d9794),(d9795),(d9796),(d9797),(d9798),(d9799),(d9800),(d9801),(d9802),(d9803),(d9804),(d9805),(d9806),(d9807),(d9808),(d9809),(d9810),(d9811),(d9812),(d9813),(d9814),(d9815),(d9816),(d9817),(d9818),(d9819),(d9820),(d9821),(d9822),(d9823),(d9824),(d9825),(d9826),(d9827),(d9828),(d9829),(d9830),(d9831),(d9832),(d9833),(d9834),(d9835),(d9836),(d9837),(d9838),(d9839),(d9840),(d9841),(d9842),(d9843),(d9844),(d9845),(d9846),(d9847),(d9848),(d9849),(d9850),(d9851),(d9852),(d9853),(d9854),(d9855),(d9856),(d9857),(d9858),(d9859),(d9860),(d9861),(d9862),(d9863),(d9864),(d9865),(d9866),(d9867),(d9868),(d9869),(d9870),(d9871),(d9872),(d9873),(d9874),(d9875),(d9876),(d9877),(d9878),(d9879),(d9880),(d9881),(d9882),(d9883),(d9884),(d9885),(d9886),(d9887),(d9888),(d9889),(d9890),(d9891),(d9892),(d9893),(d9894),(d9895),(d9896),(d9897),(d9898),(d9899),(d9900),(d9901),(d9902),(d9903),(d9904),(d9905),(d9906),(d9907),(d9908),(d9909),(d9910),(d9911),(d9912),(d9913),(d9914),(d9915),(d9916),(d9917),(d9918),(d9919),(d9920),(d9921),(d9922),(d9923),(d9924),(d9925),(d9926),(d9927),(d9928),(d9929),(d9930),(d9931),(d9932),(d9933),(d9934),(d9935),(d9936),(d9937),(d9938),(d9939),(d9940),(d9941),(d9942),(d9943),(d9944),(d9945),(d9946),(d9947),(d9948),(d9949),(d9950),(d9951),(d9952),(d9953),(d9954),(d9955),(d9956),(d9957),(d9958),(d9959),(d9960),(d9961),(d9962),(d9963),(d9964),(d9965),(d9966),(d9967),(d9968),(d9969),(d9970),(d9971),(d9972),(d9973),(d9974),(d9975),(d9976),(d9977),(d9978),(d9979),(d9980),(d9981),(d9982),(d9983),(d9984),(d9985),(d9986),(d9987),(d9988),(d9989),(d9990),(d9991),(d9992),(d9993),(d9994),(d9995),(d9996),(d9997),(d9998)} ] +Root :1 [{(d0)}] +contents: [ [ [d0,d1],[d0,d2],[d2,d3],[d2,d4],[d4,d5],[d4,d6],[d6,d7],[d6,d8],[d8,d9],[d8,d10],[d10,d11],[d10,d12],[d12,d13],[d12,d14],[d14,d15],[d14,d16],[d16,d17],[d16,d18],[d18,d19],[d18,d20],[d20,d21],[d20,d22],[d22,d23],[d22,d24],[d24,d25],[d24,d26],[d26,d27],[d26,d28],[d28,d29],[d28,d30],[d30,d31],[d30,d32],[d32,d33],[d32,d34],[d34,d35],[d34,d36],[d36,d37],[d36,d38],[d38,d39],[d38,d40],[d40,d41],[d40,d42],[d42,d43],[d42,d44],[d44,d45],[d44,d46],[d46,d47],[d46,d48],[d48,d49],[d48,d50],[d50,d51],[d50,d52],[d52,d53],[d52,d54],[d54,d55],[d54,d56],[d56,d57],[d56,d58],[d58,d59],[d58,d60],[d60,d61],[d60,d62],[d62,d63],[d62,d64],[d64,d65],[d64,d66],[d66,d67],[d66,d68],[d68,d69],[d68,d70],[d70,d71],[d70,d72],[d72,d73],[d72,d74],[d74,d75],[d74,d76],[d76,d77],[d76,d78],[d78,d79],[d78,d80],[d80,d81],[d80,d82],[d82,d83],[d82,d84],[d84,d85],[d84,d86],[d86,d87],[d86,d88],[d88,d89],[d88,d90],[d90,d91],[d90,d92],[d92,d93],[d92,d94],[d94,d95],[d94,d96],[d96,d97],[d96,d98],[d98,d99],[d98,d100],[d100,d101],[d100,d102],[d102,d103],[d102,d104],[d104,d105],[d104,d106],[d106,d107],[d106,d108],[d108,d109],[d108,d110],[d110,d111],[d110,d112],[d112,d113],[d112,d114],[d114,d115],[d114,d116],[d116,d117],[d116,d118],[d118,d119],[d118,d120],[d120,d121],[d120,d122],[d122,d123],[d122,d124],[d124,d125],[d124,d126],[d126,d127],[d126,d128],[d128,d129],[d128,d130],[d130,d131],[d130,d132],[d132,d133],[d132,d134],[d134,d135],[d134,d136],[d136,d137],[d136,d138],[d138,d139],[d138,d140],[d140,d141],[d140,d142],[d142,d143],[d142,d144],[d144,d145],[d144,d146],[d146,d147],[d146,d148],[d148,d149],[d148,d150],[d150,d151],[d150,d152],[d152,d153],[d152,d154],[d154,d155],[d154,d156],[d156,d157],[d156,d158],[d158,d159],[d158,d160],[d160,d161],[d160,d162],[d162,d163],[d162,d164],[d164,d165],[d164,d166],[d166,d167],[d166,d168],[d168,d169],[d168,d170],[d170,d171],[d170,d172],[d172,d173],[d172,d174],[d174,d175],[d174,d176],[d176,d177],[d176,d178],[d178,d179],[d178,d180],[d180,d181],[d180,d182],[d182,d183],[d182,d184],[d184,d185],[d184,d186],[d186,d187],[d186,d188],[d188,d189],[d188,d190],[d190,d191],[d190,d192],[d192,d193],[d192,d194],[d194,d195],[d194,d196],[d196,d197],[d196,d198],[d198,d199],[d198,d200],[d200,d201],[d200,d202],[d202,d203],[d202,d204],[d204,d205],[d204,d206],[d206,d207],[d206,d208],[d208,d209],[d208,d210],[d210,d211],[d210,d212],[d212,d213],[d212,d214],[d214,d215],[d214,d216],[d216,d217],[d216,d218],[d218,d219],[d218,d220],[d220,d221],[d220,d222],[d222,d223],[d222,d224],[d224,d225],[d224,d226],[d226,d227],[d226,d228],[d228,d229],[d228,d230],[d230,d231],[d230,d232],[d232,d233],[d232,d234],[d234,d235],[d234,d236],[d236,d237],[d236,d238],[d238,d239],[d238,d240],[d240,d241],[d240,d242],[d242,d243],[d242,d244],[d244,d245],[d244,d246],[d246,d247],[d246,d248],[d248,d249],[d248,d250],[d250,d251],[d250,d252],[d252,d253],[d252,d254],[d254,d255],[d254,d256],[d256,d257],[d256,d258],[d258,d259],[d258,d260],[d260,d261],[d260,d262],[d262,d263],[d262,d264],[d264,d265],[d264,d266],[d266,d267],[d266,d268],[d268,d269],[d268,d270],[d270,d271],[d270,d272],[d272,d273],[d272,d274],[d274,d275],[d274,d276],[d276,d277],[d276,d278],[d278,d279],[d278,d280],[d280,d281],[d280,d282],[d282,d283],[d282,d284],[d284,d285],[d284,d286],[d286,d287],[d286,d288],[d288,d289],[d288,d290],[d290,d291],[d290,d292],[d292,d293],[d292,d294],[d294,d295],[d294,d296],[d296,d297],[d296,d298],[d298,d299],[d298,d300],[d300,d301],[d300,d302],[d302,d303],[d302,d304],[d304,d305],[d304,d306],[d306,d307],[d306,d308],[d308,d309],[d308,d310],[d310,d311],[d310,d312],[d312,d313],[d312,d314],[d314,d315],[d314,d316],[d316,d317],[d316,d318],[d318,d319],[d318,d320],[d320,d321],[d320,d322],[d322,d323],[d322,d324],[d324,d325],[d324,d326],[d326,d327],[d326,d328],[d328,d329],[d328,d330],[d330,d331],[d330,d332],[d332,d333],[d332,d334],[d334,d335],[d334,d336],[d336,d337],[d336,d338],[d338,d339],[d338,d340],[d340,d341],[d340,d342],[d342,d343],[d342,d344],[d344,d345],[d344,d346],[d346,d347],[d346,d348],[d348,d349],[d348,d350],[d350,d351],[d350,d352],[d352,d353],[d352,d354],[d354,d355],[d354,d356],[d356,d357],[d356,d358],[d358,d359],[d358,d360],[d360,d361],[d360,d362],[d362,d363],[d362,d364],[d364,d365],[d364,d366],[d366,d367],[d366,d368],[d368,d369],[d368,d370],[d370,d371],[d370,d372],[d372,d373],[d372,d374],[d374,d375],[d374,d376],[d376,d377],[d376,d378],[d378,d379],[d378,d380],[d380,d381],[d380,d382],[d382,d383],[d382,d384],[d384,d385],[d384,d386],[d386,d387],[d386,d388],[d388,d389],[d388,d390],[d390,d391],[d390,d392],[d392,d393],[d392,d394],[d394,d395],[d394,d396],[d396,d397],[d396,d398],[d398,d399],[d398,d400],[d400,d401],[d400,d402],[d402,d403],[d402,d404],[d404,d405],[d404,d406],[d406,d407],[d406,d408],[d408,d409],[d408,d410],[d410,d411],[d410,d412],[d412,d413],[d412,d414],[d414,d415],[d414,d416],[d416,d417],[d416,d418],[d418,d419],[d418,d420],[d420,d421],[d420,d422],[d422,d423],[d422,d424],[d424,d425],[d424,d426],[d426,d427],[d426,d428],[d428,d429],[d428,d430],[d430,d431],[d430,d432],[d432,d433],[d432,d434],[d434,d435],[d434,d436],[d436,d437],[d436,d438],[d438,d439],[d438,d440],[d440,d441],[d440,d442],[d442,d443],[d442,d444],[d444,d445],[d444,d446],[d446,d447],[d446,d448],[d448,d449],[d448,d450],[d450,d451],[d450,d452],[d452,d453],[d452,d454],[d454,d455],[d454,d456],[d456,d457],[d456,d458],[d458,d459],[d458,d460],[d460,d461],[d460,d462],[d462,d463],[d462,d464],[d464,d465],[d464,d466],[d466,d467],[d466,d468],[d468,d469],[d468,d470],[d470,d471],[d470,d472],[d472,d473],[d472,d474],[d474,d475],[d474,d476],[d476,d477],[d476,d478],[d478,d479],[d478,d480],[d480,d481],[d480,d482],[d482,d483],[d482,d484],[d484,d485],[d484,d486],[d486,d487],[d486,d488],[d488,d489],[d488,d490],[d490,d491],[d490,d492],[d492,d493],[d492,d494],[d494,d495],[d494,d496],[d496,d497],[d496,d498],[d498,d499],[d498,d500],[d500,d501],[d500,d502],[d502,d503],[d502,d504],[d504,d505],[d504,d506],[d506,d507],[d506,d508],[d508,d509],[d508,d510],[d510,d511],[d510,d512],[d512,d513],[d512,d514],[d514,d515],[d514,d516],[d516,d517],[d516,d518],[d518,d519],[d518,d520],[d520,d521],[d520,d522],[d522,d523],[d522,d524],[d524,d525],[d524,d526],[d526,d527],[d526,d528],[d528,d529],[d528,d530],[d530,d531],[d530,d532],[d532,d533],[d532,d534],[d534,d535],[d534,d536],[d536,d537],[d536,d538],[d538,d539],[d538,d540],[d540,d541],[d540,d542],[d542,d543],[d542,d544],[d544,d545],[d544,d546],[d546,d547],[d546,d548],[d548,d549],[d548,d550],[d550,d551],[d550,d552],[d552,d553],[d552,d554],[d554,d555],[d554,d556],[d556,d557],[d556,d558],[d558,d559],[d558,d560],[d560,d561],[d560,d562],[d562,d563],[d562,d564],[d564,d565],[d564,d566],[d566,d567],[d566,d568],[d568,d569],[d568,d570],[d570,d571],[d570,d572],[d572,d573],[d572,d574],[d574,d575],[d574,d576],[d576,d577],[d576,d578],[d578,d579],[d578,d580],[d580,d581],[d580,d582],[d582,d583],[d582,d584],[d584,d585],[d584,d586],[d586,d587],[d586,d588],[d588,d589],[d588,d590],[d590,d591],[d590,d592],[d592,d593],[d592,d594],[d594,d595],[d594,d596],[d596,d597],[d596,d598],[d598,d599],[d598,d600],[d600,d601],[d600,d602],[d602,d603],[d602,d604],[d604,d605],[d604,d606],[d606,d607],[d606,d608],[d608,d609],[d608,d610],[d610,d611],[d610,d612],[d612,d613],[d612,d614],[d614,d615],[d614,d616],[d616,d617],[d616,d618],[d618,d619],[d618,d620],[d620,d621],[d620,d622],[d622,d623],[d622,d624],[d624,d625],[d624,d626],[d626,d627],[d626,d628],[d628,d629],[d628,d630],[d630,d631],[d630,d632],[d632,d633],[d632,d634],[d634,d635],[d634,d636],[d636,d637],[d636,d638],[d638,d639],[d638,d640],[d640,d641],[d640,d642],[d642,d643],[d642,d644],[d644,d645],[d644,d646],[d646,d647],[d646,d648],[d648,d649],[d648,d650],[d650,d651],[d650,d652],[d652,d653],[d652,d654],[d654,d655],[d654,d656],[d656,d657],[d656,d658],[d658,d659],[d658,d660],[d660,d661],[d660,d662],[d662,d663],[d662,d664],[d664,d665],[d664,d666],[d666,d667],[d666,d668],[d668,d669],[d668,d670],[d670,d671],[d670,d672],[d672,d673],[d672,d674],[d674,d675],[d674,d676],[d676,d677],[d676,d678],[d678,d679],[d678,d680],[d680,d681],[d680,d682],[d682,d683],[d682,d684],[d684,d685],[d684,d686],[d686,d687],[d686,d688],[d688,d689],[d688,d690],[d690,d691],[d690,d692],[d692,d693],[d692,d694],[d694,d695],[d694,d696],[d696,d697],[d696,d698],[d698,d699],[d698,d700],[d700,d701],[d700,d702],[d702,d703],[d702,d704],[d704,d705],[d704,d706],[d706,d707],[d706,d708],[d708,d709],[d708,d710],[d710,d711],[d710,d712],[d712,d713],[d712,d714],[d714,d715],[d714,d716],[d716,d717],[d716,d718],[d718,d719],[d718,d720],[d720,d721],[d720,d722],[d722,d723],[d722,d724],[d724,d725],[d724,d726],[d726,d727],[d726,d728],[d728,d729],[d728,d730],[d730,d731],[d730,d732],[d732,d733],[d732,d734],[d734,d735],[d734,d736],[d736,d737],[d736,d738],[d738,d739],[d738,d740],[d740,d741],[d740,d742],[d742,d743],[d742,d744],[d744,d745],[d744,d746],[d746,d747],[d746,d748],[d748,d749],[d748,d750],[d750,d751],[d750,d752],[d752,d753],[d752,d754],[d754,d755],[d754,d756],[d756,d757],[d756,d758],[d758,d759],[d758,d760],[d760,d761],[d760,d762],[d762,d763],[d762,d764],[d764,d765],[d764,d766],[d766,d767],[d766,d768],[d768,d769],[d768,d770],[d770,d771],[d770,d772],[d772,d773],[d772,d774],[d774,d775],[d774,d776],[d776,d777],[d776,d778],[d778,d779],[d778,d780],[d780,d781],[d780,d782],[d782,d783],[d782,d784],[d784,d785],[d784,d786],[d786,d787],[d786,d788],[d788,d789],[d788,d790],[d790,d791],[d790,d792],[d792,d793],[d792,d794],[d794,d795],[d794,d796],[d796,d797],[d796,d798],[d798,d799],[d798,d800],[d800,d801],[d800,d802],[d802,d803],[d802,d804],[d804,d805],[d804,d806],[d806,d807],[d806,d808],[d808,d809],[d808,d810],[d810,d811],[d810,d812],[d812,d813],[d812,d814],[d814,d815],[d814,d816],[d816,d817],[d816,d818],[d818,d819],[d818,d820],[d820,d821],[d820,d822],[d822,d823],[d822,d824],[d824,d825],[d824,d826],[d826,d827],[d826,d828],[d828,d829],[d828,d830],[d830,d831],[d830,d832],[d832,d833],[d832,d834],[d834,d835],[d834,d836],[d836,d837],[d836,d838],[d838,d839],[d838,d840],[d840,d841],[d840,d842],[d842,d843],[d842,d844],[d844,d845],[d844,d846],[d846,d847],[d846,d848],[d848,d849],[d848,d850],[d850,d851],[d850,d852],[d852,d853],[d852,d854],[d854,d855],[d854,d856],[d856,d857],[d856,d858],[d858,d859],[d858,d860],[d860,d861],[d860,d862],[d862,d863],[d862,d864],[d864,d865],[d864,d866],[d866,d867],[d866,d868],[d868,d869],[d868,d870],[d870,d871],[d870,d872],[d872,d873],[d872,d874],[d874,d875],[d874,d876],[d876,d877],[d876,d878],[d878,d879],[d878,d880],[d880,d881],[d880,d882],[d882,d883],[d882,d884],[d884,d885],[d884,d886],[d886,d887],[d886,d888],[d888,d889],[d888,d890],[d890,d891],[d890,d892],[d892,d893],[d892,d894],[d894,d895],[d894,d896],[d896,d897],[d896,d898],[d898,d899],[d898,d900],[d900,d901],[d900,d902],[d902,d903],[d902,d904],[d904,d905],[d904,d906],[d906,d907],[d906,d908],[d908,d909],[d908,d910],[d910,d911],[d910,d912],[d912,d913],[d912,d914],[d914,d915],[d914,d916],[d916,d917],[d916,d918],[d918,d919],[d918,d920],[d920,d921],[d920,d922],[d922,d923],[d922,d924],[d924,d925],[d924,d926],[d926,d927],[d926,d928],[d928,d929],[d928,d930],[d930,d931],[d930,d932],[d932,d933],[d932,d934],[d934,d935],[d934,d936],[d936,d937],[d936,d938],[d938,d939],[d938,d940],[d940,d941],[d940,d942],[d942,d943],[d942,d944],[d944,d945],[d944,d946],[d946,d947],[d946,d948],[d948,d949],[d948,d950],[d950,d951],[d950,d952],[d952,d953],[d952,d954],[d954,d955],[d954,d956],[d956,d957],[d956,d958],[d958,d959],[d958,d960],[d960,d961],[d960,d962],[d962,d963],[d962,d964],[d964,d965],[d964,d966],[d966,d967],[d966,d968],[d968,d969],[d968,d970],[d970,d971],[d970,d972],[d972,d973],[d972,d974],[d974,d975],[d974,d976],[d976,d977],[d976,d978],[d978,d979],[d978,d980],[d980,d981],[d980,d982],[d982,d983],[d982,d984],[d984,d985],[d984,d986],[d986,d987],[d986,d988],[d988,d989],[d988,d990],[d990,d991],[d990,d992],[d992,d993],[d992,d994],[d994,d995],[d994,d996],[d996,d997],[d996,d998],[d998,d999],[d998,d1000],[d1000,d1001],[d1000,d1002],[d1002,d1003],[d1002,d1004],[d1004,d1005],[d1004,d1006],[d1006,d1007],[d1006,d1008],[d1008,d1009],[d1008,d1010],[d1010,d1011],[d1010,d1012],[d1012,d1013],[d1012,d1014],[d1014,d1015],[d1014,d1016],[d1016,d1017],[d1016,d1018],[d1018,d1019],[d1018,d1020],[d1020,d1021],[d1020,d1022],[d1022,d1023],[d1022,d1024],[d1024,d1025],[d1024,d1026],[d1026,d1027],[d1026,d1028],[d1028,d1029],[d1028,d1030],[d1030,d1031],[d1030,d1032],[d1032,d1033],[d1032,d1034],[d1034,d1035],[d1034,d1036],[d1036,d1037],[d1036,d1038],[d1038,d1039],[d1038,d1040],[d1040,d1041],[d1040,d1042],[d1042,d1043],[d1042,d1044],[d1044,d1045],[d1044,d1046],[d1046,d1047],[d1046,d1048],[d1048,d1049],[d1048,d1050],[d1050,d1051],[d1050,d1052],[d1052,d1053],[d1052,d1054],[d1054,d1055],[d1054,d1056],[d1056,d1057],[d1056,d1058],[d1058,d1059],[d1058,d1060],[d1060,d1061],[d1060,d1062],[d1062,d1063],[d1062,d1064],[d1064,d1065],[d1064,d1066],[d1066,d1067],[d1066,d1068],[d1068,d1069],[d1068,d1070],[d1070,d1071],[d1070,d1072],[d1072,d1073],[d1072,d1074],[d1074,d1075],[d1074,d1076],[d1076,d1077],[d1076,d1078],[d1078,d1079],[d1078,d1080],[d1080,d1081],[d1080,d1082],[d1082,d1083],[d1082,d1084],[d1084,d1085],[d1084,d1086],[d1086,d1087],[d1086,d1088],[d1088,d1089],[d1088,d1090],[d1090,d1091],[d1090,d1092],[d1092,d1093],[d1092,d1094],[d1094,d1095],[d1094,d1096],[d1096,d1097],[d1096,d1098],[d1098,d1099],[d1098,d1100],[d1100,d1101],[d1100,d1102],[d1102,d1103],[d1102,d1104],[d1104,d1105],[d1104,d1106],[d1106,d1107],[d1106,d1108],[d1108,d1109],[d1108,d1110],[d1110,d1111],[d1110,d1112],[d1112,d1113],[d1112,d1114],[d1114,d1115],[d1114,d1116],[d1116,d1117],[d1116,d1118],[d1118,d1119],[d1118,d1120],[d1120,d1121],[d1120,d1122],[d1122,d1123],[d1122,d1124],[d1124,d1125],[d1124,d1126],[d1126,d1127],[d1126,d1128],[d1128,d1129],[d1128,d1130],[d1130,d1131],[d1130,d1132],[d1132,d1133],[d1132,d1134],[d1134,d1135],[d1134,d1136],[d1136,d1137],[d1136,d1138],[d1138,d1139],[d1138,d1140],[d1140,d1141],[d1140,d1142],[d1142,d1143],[d1142,d1144],[d1144,d1145],[d1144,d1146],[d1146,d1147],[d1146,d1148],[d1148,d1149],[d1148,d1150],[d1150,d1151],[d1150,d1152],[d1152,d1153],[d1152,d1154],[d1154,d1155],[d1154,d1156],[d1156,d1157],[d1156,d1158],[d1158,d1159],[d1158,d1160],[d1160,d1161],[d1160,d1162],[d1162,d1163],[d1162,d1164],[d1164,d1165],[d1164,d1166],[d1166,d1167],[d1166,d1168],[d1168,d1169],[d1168,d1170],[d1170,d1171],[d1170,d1172],[d1172,d1173],[d1172,d1174],[d1174,d1175],[d1174,d1176],[d1176,d1177],[d1176,d1178],[d1178,d1179],[d1178,d1180],[d1180,d1181],[d1180,d1182],[d1182,d1183],[d1182,d1184],[d1184,d1185],[d1184,d1186],[d1186,d1187],[d1186,d1188],[d1188,d1189],[d1188,d1190],[d1190,d1191],[d1190,d1192],[d1192,d1193],[d1192,d1194],[d1194,d1195],[d1194,d1196],[d1196,d1197],[d1196,d1198],[d1198,d1199],[d1198,d1200],[d1200,d1201],[d1200,d1202],[d1202,d1203],[d1202,d1204],[d1204,d1205],[d1204,d1206],[d1206,d1207],[d1206,d1208],[d1208,d1209],[d1208,d1210],[d1210,d1211],[d1210,d1212],[d1212,d1213],[d1212,d1214],[d1214,d1215],[d1214,d1216],[d1216,d1217],[d1216,d1218],[d1218,d1219],[d1218,d1220],[d1220,d1221],[d1220,d1222],[d1222,d1223],[d1222,d1224],[d1224,d1225],[d1224,d1226],[d1226,d1227],[d1226,d1228],[d1228,d1229],[d1228,d1230],[d1230,d1231],[d1230,d1232],[d1232,d1233],[d1232,d1234],[d1234,d1235],[d1234,d1236],[d1236,d1237],[d1236,d1238],[d1238,d1239],[d1238,d1240],[d1240,d1241],[d1240,d1242],[d1242,d1243],[d1242,d1244],[d1244,d1245],[d1244,d1246],[d1246,d1247],[d1246,d1248],[d1248,d1249],[d1248,d1250],[d1250,d1251],[d1250,d1252],[d1252,d1253],[d1252,d1254],[d1254,d1255],[d1254,d1256],[d1256,d1257],[d1256,d1258],[d1258,d1259],[d1258,d1260],[d1260,d1261],[d1260,d1262],[d1262,d1263],[d1262,d1264],[d1264,d1265],[d1264,d1266],[d1266,d1267],[d1266,d1268],[d1268,d1269],[d1268,d1270],[d1270,d1271],[d1270,d1272],[d1272,d1273],[d1272,d1274],[d1274,d1275],[d1274,d1276],[d1276,d1277],[d1276,d1278],[d1278,d1279],[d1278,d1280],[d1280,d1281],[d1280,d1282],[d1282,d1283],[d1282,d1284],[d1284,d1285],[d1284,d1286],[d1286,d1287],[d1286,d1288],[d1288,d1289],[d1288,d1290],[d1290,d1291],[d1290,d1292],[d1292,d1293],[d1292,d1294],[d1294,d1295],[d1294,d1296],[d1296,d1297],[d1296,d1298],[d1298,d1299],[d1298,d1300],[d1300,d1301],[d1300,d1302],[d1302,d1303],[d1302,d1304],[d1304,d1305],[d1304,d1306],[d1306,d1307],[d1306,d1308],[d1308,d1309],[d1308,d1310],[d1310,d1311],[d1310,d1312],[d1312,d1313],[d1312,d1314],[d1314,d1315],[d1314,d1316],[d1316,d1317],[d1316,d1318],[d1318,d1319],[d1318,d1320],[d1320,d1321],[d1320,d1322],[d1322,d1323],[d1322,d1324],[d1324,d1325],[d1324,d1326],[d1326,d1327],[d1326,d1328],[d1328,d1329],[d1328,d1330],[d1330,d1331],[d1330,d1332],[d1332,d1333],[d1332,d1334],[d1334,d1335],[d1334,d1336],[d1336,d1337],[d1336,d1338],[d1338,d1339],[d1338,d1340],[d1340,d1341],[d1340,d1342],[d1342,d1343],[d1342,d1344],[d1344,d1345],[d1344,d1346],[d1346,d1347],[d1346,d1348],[d1348,d1349],[d1348,d1350],[d1350,d1351],[d1350,d1352],[d1352,d1353],[d1352,d1354],[d1354,d1355],[d1354,d1356],[d1356,d1357],[d1356,d1358],[d1358,d1359],[d1358,d1360],[d1360,d1361],[d1360,d1362],[d1362,d1363],[d1362,d1364],[d1364,d1365],[d1364,d1366],[d1366,d1367],[d1366,d1368],[d1368,d1369],[d1368,d1370],[d1370,d1371],[d1370,d1372],[d1372,d1373],[d1372,d1374],[d1374,d1375],[d1374,d1376],[d1376,d1377],[d1376,d1378],[d1378,d1379],[d1378,d1380],[d1380,d1381],[d1380,d1382],[d1382,d1383],[d1382,d1384],[d1384,d1385],[d1384,d1386],[d1386,d1387],[d1386,d1388],[d1388,d1389],[d1388,d1390],[d1390,d1391],[d1390,d1392],[d1392,d1393],[d1392,d1394],[d1394,d1395],[d1394,d1396],[d1396,d1397],[d1396,d1398],[d1398,d1399],[d1398,d1400],[d1400,d1401],[d1400,d1402],[d1402,d1403],[d1402,d1404],[d1404,d1405],[d1404,d1406],[d1406,d1407],[d1406,d1408],[d1408,d1409],[d1408,d1410],[d1410,d1411],[d1410,d1412],[d1412,d1413],[d1412,d1414],[d1414,d1415],[d1414,d1416],[d1416,d1417],[d1416,d1418],[d1418,d1419],[d1418,d1420],[d1420,d1421],[d1420,d1422],[d1422,d1423],[d1422,d1424],[d1424,d1425],[d1424,d1426],[d1426,d1427],[d1426,d1428],[d1428,d1429],[d1428,d1430],[d1430,d1431],[d1430,d1432],[d1432,d1433],[d1432,d1434],[d1434,d1435],[d1434,d1436],[d1436,d1437],[d1436,d1438],[d1438,d1439],[d1438,d1440],[d1440,d1441],[d1440,d1442],[d1442,d1443],[d1442,d1444],[d1444,d1445],[d1444,d1446],[d1446,d1447],[d1446,d1448],[d1448,d1449],[d1448,d1450],[d1450,d1451],[d1450,d1452],[d1452,d1453],[d1452,d1454],[d1454,d1455],[d1454,d1456],[d1456,d1457],[d1456,d1458],[d1458,d1459],[d1458,d1460],[d1460,d1461],[d1460,d1462],[d1462,d1463],[d1462,d1464],[d1464,d1465],[d1464,d1466],[d1466,d1467],[d1466,d1468],[d1468,d1469],[d1468,d1470],[d1470,d1471],[d1470,d1472],[d1472,d1473],[d1472,d1474],[d1474,d1475],[d1474,d1476],[d1476,d1477],[d1476,d1478],[d1478,d1479],[d1478,d1480],[d1480,d1481],[d1480,d1482],[d1482,d1483],[d1482,d1484],[d1484,d1485],[d1484,d1486],[d1486,d1487],[d1486,d1488],[d1488,d1489],[d1488,d1490],[d1490,d1491],[d1490,d1492],[d1492,d1493],[d1492,d1494],[d1494,d1495],[d1494,d1496],[d1496,d1497],[d1496,d1498],[d1498,d1499],[d1498,d1500],[d1500,d1501],[d1500,d1502],[d1502,d1503],[d1502,d1504],[d1504,d1505],[d1504,d1506],[d1506,d1507],[d1506,d1508],[d1508,d1509],[d1508,d1510],[d1510,d1511],[d1510,d1512],[d1512,d1513],[d1512,d1514],[d1514,d1515],[d1514,d1516],[d1516,d1517],[d1516,d1518],[d1518,d1519],[d1518,d1520],[d1520,d1521],[d1520,d1522],[d1522,d1523],[d1522,d1524],[d1524,d1525],[d1524,d1526],[d1526,d1527],[d1526,d1528],[d1528,d1529],[d1528,d1530],[d1530,d1531],[d1530,d1532],[d1532,d1533],[d1532,d1534],[d1534,d1535],[d1534,d1536],[d1536,d1537],[d1536,d1538],[d1538,d1539],[d1538,d1540],[d1540,d1541],[d1540,d1542],[d1542,d1543],[d1542,d1544],[d1544,d1545],[d1544,d1546],[d1546,d1547],[d1546,d1548],[d1548,d1549],[d1548,d1550],[d1550,d1551],[d1550,d1552],[d1552,d1553],[d1552,d1554],[d1554,d1555],[d1554,d1556],[d1556,d1557],[d1556,d1558],[d1558,d1559],[d1558,d1560],[d1560,d1561],[d1560,d1562],[d1562,d1563],[d1562,d1564],[d1564,d1565],[d1564,d1566],[d1566,d1567],[d1566,d1568],[d1568,d1569],[d1568,d1570],[d1570,d1571],[d1570,d1572],[d1572,d1573],[d1572,d1574],[d1574,d1575],[d1574,d1576],[d1576,d1577],[d1576,d1578],[d1578,d1579],[d1578,d1580],[d1580,d1581],[d1580,d1582],[d1582,d1583],[d1582,d1584],[d1584,d1585],[d1584,d1586],[d1586,d1587],[d1586,d1588],[d1588,d1589],[d1588,d1590],[d1590,d1591],[d1590,d1592],[d1592,d1593],[d1592,d1594],[d1594,d1595],[d1594,d1596],[d1596,d1597],[d1596,d1598],[d1598,d1599],[d1598,d1600],[d1600,d1601],[d1600,d1602],[d1602,d1603],[d1602,d1604],[d1604,d1605],[d1604,d1606],[d1606,d1607],[d1606,d1608],[d1608,d1609],[d1608,d1610],[d1610,d1611],[d1610,d1612],[d1612,d1613],[d1612,d1614],[d1614,d1615],[d1614,d1616],[d1616,d1617],[d1616,d1618],[d1618,d1619],[d1618,d1620],[d1620,d1621],[d1620,d1622],[d1622,d1623],[d1622,d1624],[d1624,d1625],[d1624,d1626],[d1626,d1627],[d1626,d1628],[d1628,d1629],[d1628,d1630],[d1630,d1631],[d1630,d1632],[d1632,d1633],[d1632,d1634],[d1634,d1635],[d1634,d1636],[d1636,d1637],[d1636,d1638],[d1638,d1639],[d1638,d1640],[d1640,d1641],[d1640,d1642],[d1642,d1643],[d1642,d1644],[d1644,d1645],[d1644,d1646],[d1646,d1647],[d1646,d1648],[d1648,d1649],[d1648,d1650],[d1650,d1651],[d1650,d1652],[d1652,d1653],[d1652,d1654],[d1654,d1655],[d1654,d1656],[d1656,d1657],[d1656,d1658],[d1658,d1659],[d1658,d1660],[d1660,d1661],[d1660,d1662],[d1662,d1663],[d1662,d1664],[d1664,d1665],[d1664,d1666],[d1666,d1667],[d1666,d1668],[d1668,d1669],[d1668,d1670],[d1670,d1671],[d1670,d1672],[d1672,d1673],[d1672,d1674],[d1674,d1675],[d1674,d1676],[d1676,d1677],[d1676,d1678],[d1678,d1679],[d1678,d1680],[d1680,d1681],[d1680,d1682],[d1682,d1683],[d1682,d1684],[d1684,d1685],[d1684,d1686],[d1686,d1687],[d1686,d1688],[d1688,d1689],[d1688,d1690],[d1690,d1691],[d1690,d1692],[d1692,d1693],[d1692,d1694],[d1694,d1695],[d1694,d1696],[d1696,d1697],[d1696,d1698],[d1698,d1699],[d1698,d1700],[d1700,d1701],[d1700,d1702],[d1702,d1703],[d1702,d1704],[d1704,d1705],[d1704,d1706],[d1706,d1707],[d1706,d1708],[d1708,d1709],[d1708,d1710],[d1710,d1711],[d1710,d1712],[d1712,d1713],[d1712,d1714],[d1714,d1715],[d1714,d1716],[d1716,d1717],[d1716,d1718],[d1718,d1719],[d1718,d1720],[d1720,d1721],[d1720,d1722],[d1722,d1723],[d1722,d1724],[d1724,d1725],[d1724,d1726],[d1726,d1727],[d1726,d1728],[d1728,d1729],[d1728,d1730],[d1730,d1731],[d1730,d1732],[d1732,d1733],[d1732,d1734],[d1734,d1735],[d1734,d1736],[d1736,d1737],[d1736,d1738],[d1738,d1739],[d1738,d1740],[d1740,d1741],[d1740,d1742],[d1742,d1743],[d1742,d1744],[d1744,d1745],[d1744,d1746],[d1746,d1747],[d1746,d1748],[d1748,d1749],[d1748,d1750],[d1750,d1751],[d1750,d1752],[d1752,d1753],[d1752,d1754],[d1754,d1755],[d1754,d1756],[d1756,d1757],[d1756,d1758],[d1758,d1759],[d1758,d1760],[d1760,d1761],[d1760,d1762],[d1762,d1763],[d1762,d1764],[d1764,d1765],[d1764,d1766],[d1766,d1767],[d1766,d1768],[d1768,d1769],[d1768,d1770],[d1770,d1771],[d1770,d1772],[d1772,d1773],[d1772,d1774],[d1774,d1775],[d1774,d1776],[d1776,d1777],[d1776,d1778],[d1778,d1779],[d1778,d1780],[d1780,d1781],[d1780,d1782],[d1782,d1783],[d1782,d1784],[d1784,d1785],[d1784,d1786],[d1786,d1787],[d1786,d1788],[d1788,d1789],[d1788,d1790],[d1790,d1791],[d1790,d1792],[d1792,d1793],[d1792,d1794],[d1794,d1795],[d1794,d1796],[d1796,d1797],[d1796,d1798],[d1798,d1799],[d1798,d1800],[d1800,d1801],[d1800,d1802],[d1802,d1803],[d1802,d1804],[d1804,d1805],[d1804,d1806],[d1806,d1807],[d1806,d1808],[d1808,d1809],[d1808,d1810],[d1810,d1811],[d1810,d1812],[d1812,d1813],[d1812,d1814],[d1814,d1815],[d1814,d1816],[d1816,d1817],[d1816,d1818],[d1818,d1819],[d1818,d1820],[d1820,d1821],[d1820,d1822],[d1822,d1823],[d1822,d1824],[d1824,d1825],[d1824,d1826],[d1826,d1827],[d1826,d1828],[d1828,d1829],[d1828,d1830],[d1830,d1831],[d1830,d1832],[d1832,d1833],[d1832,d1834],[d1834,d1835],[d1834,d1836],[d1836,d1837],[d1836,d1838],[d1838,d1839],[d1838,d1840],[d1840,d1841],[d1840,d1842],[d1842,d1843],[d1842,d1844],[d1844,d1845],[d1844,d1846],[d1846,d1847],[d1846,d1848],[d1848,d1849],[d1848,d1850],[d1850,d1851],[d1850,d1852],[d1852,d1853],[d1852,d1854],[d1854,d1855],[d1854,d1856],[d1856,d1857],[d1856,d1858],[d1858,d1859],[d1858,d1860],[d1860,d1861],[d1860,d1862],[d1862,d1863],[d1862,d1864],[d1864,d1865],[d1864,d1866],[d1866,d1867],[d1866,d1868],[d1868,d1869],[d1868,d1870],[d1870,d1871],[d1870,d1872],[d1872,d1873],[d1872,d1874],[d1874,d1875],[d1874,d1876],[d1876,d1877],[d1876,d1878],[d1878,d1879],[d1878,d1880],[d1880,d1881],[d1880,d1882],[d1882,d1883],[d1882,d1884],[d1884,d1885],[d1884,d1886],[d1886,d1887],[d1886,d1888],[d1888,d1889],[d1888,d1890],[d1890,d1891],[d1890,d1892],[d1892,d1893],[d1892,d1894],[d1894,d1895],[d1894,d1896],[d1896,d1897],[d1896,d1898],[d1898,d1899],[d1898,d1900],[d1900,d1901],[d1900,d1902],[d1902,d1903],[d1902,d1904],[d1904,d1905],[d1904,d1906],[d1906,d1907],[d1906,d1908],[d1908,d1909],[d1908,d1910],[d1910,d1911],[d1910,d1912],[d1912,d1913],[d1912,d1914],[d1914,d1915],[d1914,d1916],[d1916,d1917],[d1916,d1918],[d1918,d1919],[d1918,d1920],[d1920,d1921],[d1920,d1922],[d1922,d1923],[d1922,d1924],[d1924,d1925],[d1924,d1926],[d1926,d1927],[d1926,d1928],[d1928,d1929],[d1928,d1930],[d1930,d1931],[d1930,d1932],[d1932,d1933],[d1932,d1934],[d1934,d1935],[d1934,d1936],[d1936,d1937],[d1936,d1938],[d1938,d1939],[d1938,d1940],[d1940,d1941],[d1940,d1942],[d1942,d1943],[d1942,d1944],[d1944,d1945],[d1944,d1946],[d1946,d1947],[d1946,d1948],[d1948,d1949],[d1948,d1950],[d1950,d1951],[d1950,d1952],[d1952,d1953],[d1952,d1954],[d1954,d1955],[d1954,d1956],[d1956,d1957],[d1956,d1958],[d1958,d1959],[d1958,d1960],[d1960,d1961],[d1960,d1962],[d1962,d1963],[d1962,d1964],[d1964,d1965],[d1964,d1966],[d1966,d1967],[d1966,d1968],[d1968,d1969],[d1968,d1970],[d1970,d1971],[d1970,d1972],[d1972,d1973],[d1972,d1974],[d1974,d1975],[d1974,d1976],[d1976,d1977],[d1976,d1978],[d1978,d1979],[d1978,d1980],[d1980,d1981],[d1980,d1982],[d1982,d1983],[d1982,d1984],[d1984,d1985],[d1984,d1986],[d1986,d1987],[d1986,d1988],[d1988,d1989],[d1988,d1990],[d1990,d1991],[d1990,d1992],[d1992,d1993],[d1992,d1994],[d1994,d1995],[d1994,d1996],[d1996,d1997],[d1996,d1998],[d1998,d1999],[d1998,d2000],[d2000,d2001],[d2000,d2002],[d2002,d2003],[d2002,d2004],[d2004,d2005],[d2004,d2006],[d2006,d2007],[d2006,d2008],[d2008,d2009],[d2008,d2010],[d2010,d2011],[d2010,d2012],[d2012,d2013],[d2012,d2014],[d2014,d2015],[d2014,d2016],[d2016,d2017],[d2016,d2018],[d2018,d2019],[d2018,d2020],[d2020,d2021],[d2020,d2022],[d2022,d2023],[d2022,d2024],[d2024,d2025],[d2024,d2026],[d2026,d2027],[d2026,d2028],[d2028,d2029],[d2028,d2030],[d2030,d2031],[d2030,d2032],[d2032,d2033],[d2032,d2034],[d2034,d2035],[d2034,d2036],[d2036,d2037],[d2036,d2038],[d2038,d2039],[d2038,d2040],[d2040,d2041],[d2040,d2042],[d2042,d2043],[d2042,d2044],[d2044,d2045],[d2044,d2046],[d2046,d2047],[d2046,d2048],[d2048,d2049],[d2048,d2050],[d2050,d2051],[d2050,d2052],[d2052,d2053],[d2052,d2054],[d2054,d2055],[d2054,d2056],[d2056,d2057],[d2056,d2058],[d2058,d2059],[d2058,d2060],[d2060,d2061],[d2060,d2062],[d2062,d2063],[d2062,d2064],[d2064,d2065],[d2064,d2066],[d2066,d2067],[d2066,d2068],[d2068,d2069],[d2068,d2070],[d2070,d2071],[d2070,d2072],[d2072,d2073],[d2072,d2074],[d2074,d2075],[d2074,d2076],[d2076,d2077],[d2076,d2078],[d2078,d2079],[d2078,d2080],[d2080,d2081],[d2080,d2082],[d2082,d2083],[d2082,d2084],[d2084,d2085],[d2084,d2086],[d2086,d2087],[d2086,d2088],[d2088,d2089],[d2088,d2090],[d2090,d2091],[d2090,d2092],[d2092,d2093],[d2092,d2094],[d2094,d2095],[d2094,d2096],[d2096,d2097],[d2096,d2098],[d2098,d2099],[d2098,d2100],[d2100,d2101],[d2100,d2102],[d2102,d2103],[d2102,d2104],[d2104,d2105],[d2104,d2106],[d2106,d2107],[d2106,d2108],[d2108,d2109],[d2108,d2110],[d2110,d2111],[d2110,d2112],[d2112,d2113],[d2112,d2114],[d2114,d2115],[d2114,d2116],[d2116,d2117],[d2116,d2118],[d2118,d2119],[d2118,d2120],[d2120,d2121],[d2120,d2122],[d2122,d2123],[d2122,d2124],[d2124,d2125],[d2124,d2126],[d2126,d2127],[d2126,d2128],[d2128,d2129],[d2128,d2130],[d2130,d2131],[d2130,d2132],[d2132,d2133],[d2132,d2134],[d2134,d2135],[d2134,d2136],[d2136,d2137],[d2136,d2138],[d2138,d2139],[d2138,d2140],[d2140,d2141],[d2140,d2142],[d2142,d2143],[d2142,d2144],[d2144,d2145],[d2144,d2146],[d2146,d2147],[d2146,d2148],[d2148,d2149],[d2148,d2150],[d2150,d2151],[d2150,d2152],[d2152,d2153],[d2152,d2154],[d2154,d2155],[d2154,d2156],[d2156,d2157],[d2156,d2158],[d2158,d2159],[d2158,d2160],[d2160,d2161],[d2160,d2162],[d2162,d2163],[d2162,d2164],[d2164,d2165],[d2164,d2166],[d2166,d2167],[d2166,d2168],[d2168,d2169],[d2168,d2170],[d2170,d2171],[d2170,d2172],[d2172,d2173],[d2172,d2174],[d2174,d2175],[d2174,d2176],[d2176,d2177],[d2176,d2178],[d2178,d2179],[d2178,d2180],[d2180,d2181],[d2180,d2182],[d2182,d2183],[d2182,d2184],[d2184,d2185],[d2184,d2186],[d2186,d2187],[d2186,d2188],[d2188,d2189],[d2188,d2190],[d2190,d2191],[d2190,d2192],[d2192,d2193],[d2192,d2194],[d2194,d2195],[d2194,d2196],[d2196,d2197],[d2196,d2198],[d2198,d2199],[d2198,d2200],[d2200,d2201],[d2200,d2202],[d2202,d2203],[d2202,d2204],[d2204,d2205],[d2204,d2206],[d2206,d2207],[d2206,d2208],[d2208,d2209],[d2208,d2210],[d2210,d2211],[d2210,d2212],[d2212,d2213],[d2212,d2214],[d2214,d2215],[d2214,d2216],[d2216,d2217],[d2216,d2218],[d2218,d2219],[d2218,d2220],[d2220,d2221],[d2220,d2222],[d2222,d2223],[d2222,d2224],[d2224,d2225],[d2224,d2226],[d2226,d2227],[d2226,d2228],[d2228,d2229],[d2228,d2230],[d2230,d2231],[d2230,d2232],[d2232,d2233],[d2232,d2234],[d2234,d2235],[d2234,d2236],[d2236,d2237],[d2236,d2238],[d2238,d2239],[d2238,d2240],[d2240,d2241],[d2240,d2242],[d2242,d2243],[d2242,d2244],[d2244,d2245],[d2244,d2246],[d2246,d2247],[d2246,d2248],[d2248,d2249],[d2248,d2250],[d2250,d2251],[d2250,d2252],[d2252,d2253],[d2252,d2254],[d2254,d2255],[d2254,d2256],[d2256,d2257],[d2256,d2258],[d2258,d2259],[d2258,d2260],[d2260,d2261],[d2260,d2262],[d2262,d2263],[d2262,d2264],[d2264,d2265],[d2264,d2266],[d2266,d2267],[d2266,d2268],[d2268,d2269],[d2268,d2270],[d2270,d2271],[d2270,d2272],[d2272,d2273],[d2272,d2274],[d2274,d2275],[d2274,d2276],[d2276,d2277],[d2276,d2278],[d2278,d2279],[d2278,d2280],[d2280,d2281],[d2280,d2282],[d2282,d2283],[d2282,d2284],[d2284,d2285],[d2284,d2286],[d2286,d2287],[d2286,d2288],[d2288,d2289],[d2288,d2290],[d2290,d2291],[d2290,d2292],[d2292,d2293],[d2292,d2294],[d2294,d2295],[d2294,d2296],[d2296,d2297],[d2296,d2298],[d2298,d2299],[d2298,d2300],[d2300,d2301],[d2300,d2302],[d2302,d2303],[d2302,d2304],[d2304,d2305],[d2304,d2306],[d2306,d2307],[d2306,d2308],[d2308,d2309],[d2308,d2310],[d2310,d2311],[d2310,d2312],[d2312,d2313],[d2312,d2314],[d2314,d2315],[d2314,d2316],[d2316,d2317],[d2316,d2318],[d2318,d2319],[d2318,d2320],[d2320,d2321],[d2320,d2322],[d2322,d2323],[d2322,d2324],[d2324,d2325],[d2324,d2326],[d2326,d2327],[d2326,d2328],[d2328,d2329],[d2328,d2330],[d2330,d2331],[d2330,d2332],[d2332,d2333],[d2332,d2334],[d2334,d2335],[d2334,d2336],[d2336,d2337],[d2336,d2338],[d2338,d2339],[d2338,d2340],[d2340,d2341],[d2340,d2342],[d2342,d2343],[d2342,d2344],[d2344,d2345],[d2344,d2346],[d2346,d2347],[d2346,d2348],[d2348,d2349],[d2348,d2350],[d2350,d2351],[d2350,d2352],[d2352,d2353],[d2352,d2354],[d2354,d2355],[d2354,d2356],[d2356,d2357],[d2356,d2358],[d2358,d2359],[d2358,d2360],[d2360,d2361],[d2360,d2362],[d2362,d2363],[d2362,d2364],[d2364,d2365],[d2364,d2366],[d2366,d2367],[d2366,d2368],[d2368,d2369],[d2368,d2370],[d2370,d2371],[d2370,d2372],[d2372,d2373],[d2372,d2374],[d2374,d2375],[d2374,d2376],[d2376,d2377],[d2376,d2378],[d2378,d2379],[d2378,d2380],[d2380,d2381],[d2380,d2382],[d2382,d2383],[d2382,d2384],[d2384,d2385],[d2384,d2386],[d2386,d2387],[d2386,d2388],[d2388,d2389],[d2388,d2390],[d2390,d2391],[d2390,d2392],[d2392,d2393],[d2392,d2394],[d2394,d2395],[d2394,d2396],[d2396,d2397],[d2396,d2398],[d2398,d2399],[d2398,d2400],[d2400,d2401],[d2400,d2402],[d2402,d2403],[d2402,d2404],[d2404,d2405],[d2404,d2406],[d2406,d2407],[d2406,d2408],[d2408,d2409],[d2408,d2410],[d2410,d2411],[d2410,d2412],[d2412,d2413],[d2412,d2414],[d2414,d2415],[d2414,d2416],[d2416,d2417],[d2416,d2418],[d2418,d2419],[d2418,d2420],[d2420,d2421],[d2420,d2422],[d2422,d2423],[d2422,d2424],[d2424,d2425],[d2424,d2426],[d2426,d2427],[d2426,d2428],[d2428,d2429],[d2428,d2430],[d2430,d2431],[d2430,d2432],[d2432,d2433],[d2432,d2434],[d2434,d2435],[d2434,d2436],[d2436,d2437],[d2436,d2438],[d2438,d2439],[d2438,d2440],[d2440,d2441],[d2440,d2442],[d2442,d2443],[d2442,d2444],[d2444,d2445],[d2444,d2446],[d2446,d2447],[d2446,d2448],[d2448,d2449],[d2448,d2450],[d2450,d2451],[d2450,d2452],[d2452,d2453],[d2452,d2454],[d2454,d2455],[d2454,d2456],[d2456,d2457],[d2456,d2458],[d2458,d2459],[d2458,d2460],[d2460,d2461],[d2460,d2462],[d2462,d2463],[d2462,d2464],[d2464,d2465],[d2464,d2466],[d2466,d2467],[d2466,d2468],[d2468,d2469],[d2468,d2470],[d2470,d2471],[d2470,d2472],[d2472,d2473],[d2472,d2474],[d2474,d2475],[d2474,d2476],[d2476,d2477],[d2476,d2478],[d2478,d2479],[d2478,d2480],[d2480,d2481],[d2480,d2482],[d2482,d2483],[d2482,d2484],[d2484,d2485],[d2484,d2486],[d2486,d2487],[d2486,d2488],[d2488,d2489],[d2488,d2490],[d2490,d2491],[d2490,d2492],[d2492,d2493],[d2492,d2494],[d2494,d2495],[d2494,d2496],[d2496,d2497],[d2496,d2498],[d2498,d2499],[d2498,d2500],[d2500,d2501],[d2500,d2502],[d2502,d2503],[d2502,d2504],[d2504,d2505],[d2504,d2506],[d2506,d2507],[d2506,d2508],[d2508,d2509],[d2508,d2510],[d2510,d2511],[d2510,d2512],[d2512,d2513],[d2512,d2514],[d2514,d2515],[d2514,d2516],[d2516,d2517],[d2516,d2518],[d2518,d2519],[d2518,d2520],[d2520,d2521],[d2520,d2522],[d2522,d2523],[d2522,d2524],[d2524,d2525],[d2524,d2526],[d2526,d2527],[d2526,d2528],[d2528,d2529],[d2528,d2530],[d2530,d2531],[d2530,d2532],[d2532,d2533],[d2532,d2534],[d2534,d2535],[d2534,d2536],[d2536,d2537],[d2536,d2538],[d2538,d2539],[d2538,d2540],[d2540,d2541],[d2540,d2542],[d2542,d2543],[d2542,d2544],[d2544,d2545],[d2544,d2546],[d2546,d2547],[d2546,d2548],[d2548,d2549],[d2548,d2550],[d2550,d2551],[d2550,d2552],[d2552,d2553],[d2552,d2554],[d2554,d2555],[d2554,d2556],[d2556,d2557],[d2556,d2558],[d2558,d2559],[d2558,d2560],[d2560,d2561],[d2560,d2562],[d2562,d2563],[d2562,d2564],[d2564,d2565],[d2564,d2566],[d2566,d2567],[d2566,d2568],[d2568,d2569],[d2568,d2570],[d2570,d2571],[d2570,d2572],[d2572,d2573],[d2572,d2574],[d2574,d2575],[d2574,d2576],[d2576,d2577],[d2576,d2578],[d2578,d2579],[d2578,d2580],[d2580,d2581],[d2580,d2582],[d2582,d2583],[d2582,d2584],[d2584,d2585],[d2584,d2586],[d2586,d2587],[d2586,d2588],[d2588,d2589],[d2588,d2590],[d2590,d2591],[d2590,d2592],[d2592,d2593],[d2592,d2594],[d2594,d2595],[d2594,d2596],[d2596,d2597],[d2596,d2598],[d2598,d2599],[d2598,d2600],[d2600,d2601],[d2600,d2602],[d2602,d2603],[d2602,d2604],[d2604,d2605],[d2604,d2606],[d2606,d2607],[d2606,d2608],[d2608,d2609],[d2608,d2610],[d2610,d2611],[d2610,d2612],[d2612,d2613],[d2612,d2614],[d2614,d2615],[d2614,d2616],[d2616,d2617],[d2616,d2618],[d2618,d2619],[d2618,d2620],[d2620,d2621],[d2620,d2622],[d2622,d2623],[d2622,d2624],[d2624,d2625],[d2624,d2626],[d2626,d2627],[d2626,d2628],[d2628,d2629],[d2628,d2630],[d2630,d2631],[d2630,d2632],[d2632,d2633],[d2632,d2634],[d2634,d2635],[d2634,d2636],[d2636,d2637],[d2636,d2638],[d2638,d2639],[d2638,d2640],[d2640,d2641],[d2640,d2642],[d2642,d2643],[d2642,d2644],[d2644,d2645],[d2644,d2646],[d2646,d2647],[d2646,d2648],[d2648,d2649],[d2648,d2650],[d2650,d2651],[d2650,d2652],[d2652,d2653],[d2652,d2654],[d2654,d2655],[d2654,d2656],[d2656,d2657],[d2656,d2658],[d2658,d2659],[d2658,d2660],[d2660,d2661],[d2660,d2662],[d2662,d2663],[d2662,d2664],[d2664,d2665],[d2664,d2666],[d2666,d2667],[d2666,d2668],[d2668,d2669],[d2668,d2670],[d2670,d2671],[d2670,d2672],[d2672,d2673],[d2672,d2674],[d2674,d2675],[d2674,d2676],[d2676,d2677],[d2676,d2678],[d2678,d2679],[d2678,d2680],[d2680,d2681],[d2680,d2682],[d2682,d2683],[d2682,d2684],[d2684,d2685],[d2684,d2686],[d2686,d2687],[d2686,d2688],[d2688,d2689],[d2688,d2690],[d2690,d2691],[d2690,d2692],[d2692,d2693],[d2692,d2694],[d2694,d2695],[d2694,d2696],[d2696,d2697],[d2696,d2698],[d2698,d2699],[d2698,d2700],[d2700,d2701],[d2700,d2702],[d2702,d2703],[d2702,d2704],[d2704,d2705],[d2704,d2706],[d2706,d2707],[d2706,d2708],[d2708,d2709],[d2708,d2710],[d2710,d2711],[d2710,d2712],[d2712,d2713],[d2712,d2714],[d2714,d2715],[d2714,d2716],[d2716,d2717],[d2716,d2718],[d2718,d2719],[d2718,d2720],[d2720,d2721],[d2720,d2722],[d2722,d2723],[d2722,d2724],[d2724,d2725],[d2724,d2726],[d2726,d2727],[d2726,d2728],[d2728,d2729],[d2728,d2730],[d2730,d2731],[d2730,d2732],[d2732,d2733],[d2732,d2734],[d2734,d2735],[d2734,d2736],[d2736,d2737],[d2736,d2738],[d2738,d2739],[d2738,d2740],[d2740,d2741],[d2740,d2742],[d2742,d2743],[d2742,d2744],[d2744,d2745],[d2744,d2746],[d2746,d2747],[d2746,d2748],[d2748,d2749],[d2748,d2750],[d2750,d2751],[d2750,d2752],[d2752,d2753],[d2752,d2754],[d2754,d2755],[d2754,d2756],[d2756,d2757],[d2756,d2758],[d2758,d2759],[d2758,d2760],[d2760,d2761],[d2760,d2762],[d2762,d2763],[d2762,d2764],[d2764,d2765],[d2764,d2766],[d2766,d2767],[d2766,d2768],[d2768,d2769],[d2768,d2770],[d2770,d2771],[d2770,d2772],[d2772,d2773],[d2772,d2774],[d2774,d2775],[d2774,d2776],[d2776,d2777],[d2776,d2778],[d2778,d2779],[d2778,d2780],[d2780,d2781],[d2780,d2782],[d2782,d2783],[d2782,d2784],[d2784,d2785],[d2784,d2786],[d2786,d2787],[d2786,d2788],[d2788,d2789],[d2788,d2790],[d2790,d2791],[d2790,d2792],[d2792,d2793],[d2792,d2794],[d2794,d2795],[d2794,d2796],[d2796,d2797],[d2796,d2798],[d2798,d2799],[d2798,d2800],[d2800,d2801],[d2800,d2802],[d2802,d2803],[d2802,d2804],[d2804,d2805],[d2804,d2806],[d2806,d2807],[d2806,d2808],[d2808,d2809],[d2808,d2810],[d2810,d2811],[d2810,d2812],[d2812,d2813],[d2812,d2814],[d2814,d2815],[d2814,d2816],[d2816,d2817],[d2816,d2818],[d2818,d2819],[d2818,d2820],[d2820,d2821],[d2820,d2822],[d2822,d2823],[d2822,d2824],[d2824,d2825],[d2824,d2826],[d2826,d2827],[d2826,d2828],[d2828,d2829],[d2828,d2830],[d2830,d2831],[d2830,d2832],[d2832,d2833],[d2832,d2834],[d2834,d2835],[d2834,d2836],[d2836,d2837],[d2836,d2838],[d2838,d2839],[d2838,d2840],[d2840,d2841],[d2840,d2842],[d2842,d2843],[d2842,d2844],[d2844,d2845],[d2844,d2846],[d2846,d2847],[d2846,d2848],[d2848,d2849],[d2848,d2850],[d2850,d2851],[d2850,d2852],[d2852,d2853],[d2852,d2854],[d2854,d2855],[d2854,d2856],[d2856,d2857],[d2856,d2858],[d2858,d2859],[d2858,d2860],[d2860,d2861],[d2860,d2862],[d2862,d2863],[d2862,d2864],[d2864,d2865],[d2864,d2866],[d2866,d2867],[d2866,d2868],[d2868,d2869],[d2868,d2870],[d2870,d2871],[d2870,d2872],[d2872,d2873],[d2872,d2874],[d2874,d2875],[d2874,d2876],[d2876,d2877],[d2876,d2878],[d2878,d2879],[d2878,d2880],[d2880,d2881],[d2880,d2882],[d2882,d2883],[d2882,d2884],[d2884,d2885],[d2884,d2886],[d2886,d2887],[d2886,d2888],[d2888,d2889],[d2888,d2890],[d2890,d2891],[d2890,d2892],[d2892,d2893],[d2892,d2894],[d2894,d2895],[d2894,d2896],[d2896,d2897],[d2896,d2898],[d2898,d2899],[d2898,d2900],[d2900,d2901],[d2900,d2902],[d2902,d2903],[d2902,d2904],[d2904,d2905],[d2904,d2906],[d2906,d2907],[d2906,d2908],[d2908,d2909],[d2908,d2910],[d2910,d2911],[d2910,d2912],[d2912,d2913],[d2912,d2914],[d2914,d2915],[d2914,d2916],[d2916,d2917],[d2916,d2918],[d2918,d2919],[d2918,d2920],[d2920,d2921],[d2920,d2922],[d2922,d2923],[d2922,d2924],[d2924,d2925],[d2924,d2926],[d2926,d2927],[d2926,d2928],[d2928,d2929],[d2928,d2930],[d2930,d2931],[d2930,d2932],[d2932,d2933],[d2932,d2934],[d2934,d2935],[d2934,d2936],[d2936,d2937],[d2936,d2938],[d2938,d2939],[d2938,d2940],[d2940,d2941],[d2940,d2942],[d2942,d2943],[d2942,d2944],[d2944,d2945],[d2944,d2946],[d2946,d2947],[d2946,d2948],[d2948,d2949],[d2948,d2950],[d2950,d2951],[d2950,d2952],[d2952,d2953],[d2952,d2954],[d2954,d2955],[d2954,d2956],[d2956,d2957],[d2956,d2958],[d2958,d2959],[d2958,d2960],[d2960,d2961],[d2960,d2962],[d2962,d2963],[d2962,d2964],[d2964,d2965],[d2964,d2966],[d2966,d2967],[d2966,d2968],[d2968,d2969],[d2968,d2970],[d2970,d2971],[d2970,d2972],[d2972,d2973],[d2972,d2974],[d2974,d2975],[d2974,d2976],[d2976,d2977],[d2976,d2978],[d2978,d2979],[d2978,d2980],[d2980,d2981],[d2980,d2982],[d2982,d2983],[d2982,d2984],[d2984,d2985],[d2984,d2986],[d2986,d2987],[d2986,d2988],[d2988,d2989],[d2988,d2990],[d2990,d2991],[d2990,d2992],[d2992,d2993],[d2992,d2994],[d2994,d2995],[d2994,d2996],[d2996,d2997],[d2996,d2998],[d2998,d2999],[d2998,d3000],[d3000,d3001],[d3000,d3002],[d3002,d3003],[d3002,d3004],[d3004,d3005],[d3004,d3006],[d3006,d3007],[d3006,d3008],[d3008,d3009],[d3008,d3010],[d3010,d3011],[d3010,d3012],[d3012,d3013],[d3012,d3014],[d3014,d3015],[d3014,d3016],[d3016,d3017],[d3016,d3018],[d3018,d3019],[d3018,d3020],[d3020,d3021],[d3020,d3022],[d3022,d3023],[d3022,d3024],[d3024,d3025],[d3024,d3026],[d3026,d3027],[d3026,d3028],[d3028,d3029],[d3028,d3030],[d3030,d3031],[d3030,d3032],[d3032,d3033],[d3032,d3034],[d3034,d3035],[d3034,d3036],[d3036,d3037],[d3036,d3038],[d3038,d3039],[d3038,d3040],[d3040,d3041],[d3040,d3042],[d3042,d3043],[d3042,d3044],[d3044,d3045],[d3044,d3046],[d3046,d3047],[d3046,d3048],[d3048,d3049],[d3048,d3050],[d3050,d3051],[d3050,d3052],[d3052,d3053],[d3052,d3054],[d3054,d3055],[d3054,d3056],[d3056,d3057],[d3056,d3058],[d3058,d3059],[d3058,d3060],[d3060,d3061],[d3060,d3062],[d3062,d3063],[d3062,d3064],[d3064,d3065],[d3064,d3066],[d3066,d3067],[d3066,d3068],[d3068,d3069],[d3068,d3070],[d3070,d3071],[d3070,d3072],[d3072,d3073],[d3072,d3074],[d3074,d3075],[d3074,d3076],[d3076,d3077],[d3076,d3078],[d3078,d3079],[d3078,d3080],[d3080,d3081],[d3080,d3082],[d3082,d3083],[d3082,d3084],[d3084,d3085],[d3084,d3086],[d3086,d3087],[d3086,d3088],[d3088,d3089],[d3088,d3090],[d3090,d3091],[d3090,d3092],[d3092,d3093],[d3092,d3094],[d3094,d3095],[d3094,d3096],[d3096,d3097],[d3096,d3098],[d3098,d3099],[d3098,d3100],[d3100,d3101],[d3100,d3102],[d3102,d3103],[d3102,d3104],[d3104,d3105],[d3104,d3106],[d3106,d3107],[d3106,d3108],[d3108,d3109],[d3108,d3110],[d3110,d3111],[d3110,d3112],[d3112,d3113],[d3112,d3114],[d3114,d3115],[d3114,d3116],[d3116,d3117],[d3116,d3118],[d3118,d3119],[d3118,d3120],[d3120,d3121],[d3120,d3122],[d3122,d3123],[d3122,d3124],[d3124,d3125],[d3124,d3126],[d3126,d3127],[d3126,d3128],[d3128,d3129],[d3128,d3130],[d3130,d3131],[d3130,d3132],[d3132,d3133],[d3132,d3134],[d3134,d3135],[d3134,d3136],[d3136,d3137],[d3136,d3138],[d3138,d3139],[d3138,d3140],[d3140,d3141],[d3140,d3142],[d3142,d3143],[d3142,d3144],[d3144,d3145],[d3144,d3146],[d3146,d3147],[d3146,d3148],[d3148,d3149],[d3148,d3150],[d3150,d3151],[d3150,d3152],[d3152,d3153],[d3152,d3154],[d3154,d3155],[d3154,d3156],[d3156,d3157],[d3156,d3158],[d3158,d3159],[d3158,d3160],[d3160,d3161],[d3160,d3162],[d3162,d3163],[d3162,d3164],[d3164,d3165],[d3164,d3166],[d3166,d3167],[d3166,d3168],[d3168,d3169],[d3168,d3170],[d3170,d3171],[d3170,d3172],[d3172,d3173],[d3172,d3174],[d3174,d3175],[d3174,d3176],[d3176,d3177],[d3176,d3178],[d3178,d3179],[d3178,d3180],[d3180,d3181],[d3180,d3182],[d3182,d3183],[d3182,d3184],[d3184,d3185],[d3184,d3186],[d3186,d3187],[d3186,d3188],[d3188,d3189],[d3188,d3190],[d3190,d3191],[d3190,d3192],[d3192,d3193],[d3192,d3194],[d3194,d3195],[d3194,d3196],[d3196,d3197],[d3196,d3198],[d3198,d3199],[d3198,d3200],[d3200,d3201],[d3200,d3202],[d3202,d3203],[d3202,d3204],[d3204,d3205],[d3204,d3206],[d3206,d3207],[d3206,d3208],[d3208,d3209],[d3208,d3210],[d3210,d3211],[d3210,d3212],[d3212,d3213],[d3212,d3214],[d3214,d3215],[d3214,d3216],[d3216,d3217],[d3216,d3218],[d3218,d3219],[d3218,d3220],[d3220,d3221],[d3220,d3222],[d3222,d3223],[d3222,d3224],[d3224,d3225],[d3224,d3226],[d3226,d3227],[d3226,d3228],[d3228,d3229],[d3228,d3230],[d3230,d3231],[d3230,d3232],[d3232,d3233],[d3232,d3234],[d3234,d3235],[d3234,d3236],[d3236,d3237],[d3236,d3238],[d3238,d3239],[d3238,d3240],[d3240,d3241],[d3240,d3242],[d3242,d3243],[d3242,d3244],[d3244,d3245],[d3244,d3246],[d3246,d3247],[d3246,d3248],[d3248,d3249],[d3248,d3250],[d3250,d3251],[d3250,d3252],[d3252,d3253],[d3252,d3254],[d3254,d3255],[d3254,d3256],[d3256,d3257],[d3256,d3258],[d3258,d3259],[d3258,d3260],[d3260,d3261],[d3260,d3262],[d3262,d3263],[d3262,d3264],[d3264,d3265],[d3264,d3266],[d3266,d3267],[d3266,d3268],[d3268,d3269],[d3268,d3270],[d3270,d3271],[d3270,d3272],[d3272,d3273],[d3272,d3274],[d3274,d3275],[d3274,d3276],[d3276,d3277],[d3276,d3278],[d3278,d3279],[d3278,d3280],[d3280,d3281],[d3280,d3282],[d3282,d3283],[d3282,d3284],[d3284,d3285],[d3284,d3286],[d3286,d3287],[d3286,d3288],[d3288,d3289],[d3288,d3290],[d3290,d3291],[d3290,d3292],[d3292,d3293],[d3292,d3294],[d3294,d3295],[d3294,d3296],[d3296,d3297],[d3296,d3298],[d3298,d3299],[d3298,d3300],[d3300,d3301],[d3300,d3302],[d3302,d3303],[d3302,d3304],[d3304,d3305],[d3304,d3306],[d3306,d3307],[d3306,d3308],[d3308,d3309],[d3308,d3310],[d3310,d3311],[d3310,d3312],[d3312,d3313],[d3312,d3314],[d3314,d3315],[d3314,d3316],[d3316,d3317],[d3316,d3318],[d3318,d3319],[d3318,d3320],[d3320,d3321],[d3320,d3322],[d3322,d3323],[d3322,d3324],[d3324,d3325],[d3324,d3326],[d3326,d3327],[d3326,d3328],[d3328,d3329],[d3328,d3330],[d3330,d3331],[d3330,d3332],[d3332,d3333],[d3332,d3334],[d3334,d3335],[d3334,d3336],[d3336,d3337],[d3336,d3338],[d3338,d3339],[d3338,d3340],[d3340,d3341],[d3340,d3342],[d3342,d3343],[d3342,d3344],[d3344,d3345],[d3344,d3346],[d3346,d3347],[d3346,d3348],[d3348,d3349],[d3348,d3350],[d3350,d3351],[d3350,d3352],[d3352,d3353],[d3352,d3354],[d3354,d3355],[d3354,d3356],[d3356,d3357],[d3356,d3358],[d3358,d3359],[d3358,d3360],[d3360,d3361],[d3360,d3362],[d3362,d3363],[d3362,d3364],[d3364,d3365],[d3364,d3366],[d3366,d3367],[d3366,d3368],[d3368,d3369],[d3368,d3370],[d3370,d3371],[d3370,d3372],[d3372,d3373],[d3372,d3374],[d3374,d3375],[d3374,d3376],[d3376,d3377],[d3376,d3378],[d3378,d3379],[d3378,d3380],[d3380,d3381],[d3380,d3382],[d3382,d3383],[d3382,d3384],[d3384,d3385],[d3384,d3386],[d3386,d3387],[d3386,d3388],[d3388,d3389],[d3388,d3390],[d3390,d3391],[d3390,d3392],[d3392,d3393],[d3392,d3394],[d3394,d3395],[d3394,d3396],[d3396,d3397],[d3396,d3398],[d3398,d3399],[d3398,d3400],[d3400,d3401],[d3400,d3402],[d3402,d3403],[d3402,d3404],[d3404,d3405],[d3404,d3406],[d3406,d3407],[d3406,d3408],[d3408,d3409],[d3408,d3410],[d3410,d3411],[d3410,d3412],[d3412,d3413],[d3412,d3414],[d3414,d3415],[d3414,d3416],[d3416,d3417],[d3416,d3418],[d3418,d3419],[d3418,d3420],[d3420,d3421],[d3420,d3422],[d3422,d3423],[d3422,d3424],[d3424,d3425],[d3424,d3426],[d3426,d3427],[d3426,d3428],[d3428,d3429],[d3428,d3430],[d3430,d3431],[d3430,d3432],[d3432,d3433],[d3432,d3434],[d3434,d3435],[d3434,d3436],[d3436,d3437],[d3436,d3438],[d3438,d3439],[d3438,d3440],[d3440,d3441],[d3440,d3442],[d3442,d3443],[d3442,d3444],[d3444,d3445],[d3444,d3446],[d3446,d3447],[d3446,d3448],[d3448,d3449],[d3448,d3450],[d3450,d3451],[d3450,d3452],[d3452,d3453],[d3452,d3454],[d3454,d3455],[d3454,d3456],[d3456,d3457],[d3456,d3458],[d3458,d3459],[d3458,d3460],[d3460,d3461],[d3460,d3462],[d3462,d3463],[d3462,d3464],[d3464,d3465],[d3464,d3466],[d3466,d3467],[d3466,d3468],[d3468,d3469],[d3468,d3470],[d3470,d3471],[d3470,d3472],[d3472,d3473],[d3472,d3474],[d3474,d3475],[d3474,d3476],[d3476,d3477],[d3476,d3478],[d3478,d3479],[d3478,d3480],[d3480,d3481],[d3480,d3482],[d3482,d3483],[d3482,d3484],[d3484,d3485],[d3484,d3486],[d3486,d3487],[d3486,d3488],[d3488,d3489],[d3488,d3490],[d3490,d3491],[d3490,d3492],[d3492,d3493],[d3492,d3494],[d3494,d3495],[d3494,d3496],[d3496,d3497],[d3496,d3498],[d3498,d3499],[d3498,d3500],[d3500,d3501],[d3500,d3502],[d3502,d3503],[d3502,d3504],[d3504,d3505],[d3504,d3506],[d3506,d3507],[d3506,d3508],[d3508,d3509],[d3508,d3510],[d3510,d3511],[d3510,d3512],[d3512,d3513],[d3512,d3514],[d3514,d3515],[d3514,d3516],[d3516,d3517],[d3516,d3518],[d3518,d3519],[d3518,d3520],[d3520,d3521],[d3520,d3522],[d3522,d3523],[d3522,d3524],[d3524,d3525],[d3524,d3526],[d3526,d3527],[d3526,d3528],[d3528,d3529],[d3528,d3530],[d3530,d3531],[d3530,d3532],[d3532,d3533],[d3532,d3534],[d3534,d3535],[d3534,d3536],[d3536,d3537],[d3536,d3538],[d3538,d3539],[d3538,d3540],[d3540,d3541],[d3540,d3542],[d3542,d3543],[d3542,d3544],[d3544,d3545],[d3544,d3546],[d3546,d3547],[d3546,d3548],[d3548,d3549],[d3548,d3550],[d3550,d3551],[d3550,d3552],[d3552,d3553],[d3552,d3554],[d3554,d3555],[d3554,d3556],[d3556,d3557],[d3556,d3558],[d3558,d3559],[d3558,d3560],[d3560,d3561],[d3560,d3562],[d3562,d3563],[d3562,d3564],[d3564,d3565],[d3564,d3566],[d3566,d3567],[d3566,d3568],[d3568,d3569],[d3568,d3570],[d3570,d3571],[d3570,d3572],[d3572,d3573],[d3572,d3574],[d3574,d3575],[d3574,d3576],[d3576,d3577],[d3576,d3578],[d3578,d3579],[d3578,d3580],[d3580,d3581],[d3580,d3582],[d3582,d3583],[d3582,d3584],[d3584,d3585],[d3584,d3586],[d3586,d3587],[d3586,d3588],[d3588,d3589],[d3588,d3590],[d3590,d3591],[d3590,d3592],[d3592,d3593],[d3592,d3594],[d3594,d3595],[d3594,d3596],[d3596,d3597],[d3596,d3598],[d3598,d3599],[d3598,d3600],[d3600,d3601],[d3600,d3602],[d3602,d3603],[d3602,d3604],[d3604,d3605],[d3604,d3606],[d3606,d3607],[d3606,d3608],[d3608,d3609],[d3608,d3610],[d3610,d3611],[d3610,d3612],[d3612,d3613],[d3612,d3614],[d3614,d3615],[d3614,d3616],[d3616,d3617],[d3616,d3618],[d3618,d3619],[d3618,d3620],[d3620,d3621],[d3620,d3622],[d3622,d3623],[d3622,d3624],[d3624,d3625],[d3624,d3626],[d3626,d3627],[d3626,d3628],[d3628,d3629],[d3628,d3630],[d3630,d3631],[d3630,d3632],[d3632,d3633],[d3632,d3634],[d3634,d3635],[d3634,d3636],[d3636,d3637],[d3636,d3638],[d3638,d3639],[d3638,d3640],[d3640,d3641],[d3640,d3642],[d3642,d3643],[d3642,d3644],[d3644,d3645],[d3644,d3646],[d3646,d3647],[d3646,d3648],[d3648,d3649],[d3648,d3650],[d3650,d3651],[d3650,d3652],[d3652,d3653],[d3652,d3654],[d3654,d3655],[d3654,d3656],[d3656,d3657],[d3656,d3658],[d3658,d3659],[d3658,d3660],[d3660,d3661],[d3660,d3662],[d3662,d3663],[d3662,d3664],[d3664,d3665],[d3664,d3666],[d3666,d3667],[d3666,d3668],[d3668,d3669],[d3668,d3670],[d3670,d3671],[d3670,d3672],[d3672,d3673],[d3672,d3674],[d3674,d3675],[d3674,d3676],[d3676,d3677],[d3676,d3678],[d3678,d3679],[d3678,d3680],[d3680,d3681],[d3680,d3682],[d3682,d3683],[d3682,d3684],[d3684,d3685],[d3684,d3686],[d3686,d3687],[d3686,d3688],[d3688,d3689],[d3688,d3690],[d3690,d3691],[d3690,d3692],[d3692,d3693],[d3692,d3694],[d3694,d3695],[d3694,d3696],[d3696,d3697],[d3696,d3698],[d3698,d3699],[d3698,d3700],[d3700,d3701],[d3700,d3702],[d3702,d3703],[d3702,d3704],[d3704,d3705],[d3704,d3706],[d3706,d3707],[d3706,d3708],[d3708,d3709],[d3708,d3710],[d3710,d3711],[d3710,d3712],[d3712,d3713],[d3712,d3714],[d3714,d3715],[d3714,d3716],[d3716,d3717],[d3716,d3718],[d3718,d3719],[d3718,d3720],[d3720,d3721],[d3720,d3722],[d3722,d3723],[d3722,d3724],[d3724,d3725],[d3724,d3726],[d3726,d3727],[d3726,d3728],[d3728,d3729],[d3728,d3730],[d3730,d3731],[d3730,d3732],[d3732,d3733],[d3732,d3734],[d3734,d3735],[d3734,d3736],[d3736,d3737],[d3736,d3738],[d3738,d3739],[d3738,d3740],[d3740,d3741],[d3740,d3742],[d3742,d3743],[d3742,d3744],[d3744,d3745],[d3744,d3746],[d3746,d3747],[d3746,d3748],[d3748,d3749],[d3748,d3750],[d3750,d3751],[d3750,d3752],[d3752,d3753],[d3752,d3754],[d3754,d3755],[d3754,d3756],[d3756,d3757],[d3756,d3758],[d3758,d3759],[d3758,d3760],[d3760,d3761],[d3760,d3762],[d3762,d3763],[d3762,d3764],[d3764,d3765],[d3764,d3766],[d3766,d3767],[d3766,d3768],[d3768,d3769],[d3768,d3770],[d3770,d3771],[d3770,d3772],[d3772,d3773],[d3772,d3774],[d3774,d3775],[d3774,d3776],[d3776,d3777],[d3776,d3778],[d3778,d3779],[d3778,d3780],[d3780,d3781],[d3780,d3782],[d3782,d3783],[d3782,d3784],[d3784,d3785],[d3784,d3786],[d3786,d3787],[d3786,d3788],[d3788,d3789],[d3788,d3790],[d3790,d3791],[d3790,d3792],[d3792,d3793],[d3792,d3794],[d3794,d3795],[d3794,d3796],[d3796,d3797],[d3796,d3798],[d3798,d3799],[d3798,d3800],[d3800,d3801],[d3800,d3802],[d3802,d3803],[d3802,d3804],[d3804,d3805],[d3804,d3806],[d3806,d3807],[d3806,d3808],[d3808,d3809],[d3808,d3810],[d3810,d3811],[d3810,d3812],[d3812,d3813],[d3812,d3814],[d3814,d3815],[d3814,d3816],[d3816,d3817],[d3816,d3818],[d3818,d3819],[d3818,d3820],[d3820,d3821],[d3820,d3822],[d3822,d3823],[d3822,d3824],[d3824,d3825],[d3824,d3826],[d3826,d3827],[d3826,d3828],[d3828,d3829],[d3828,d3830],[d3830,d3831],[d3830,d3832],[d3832,d3833],[d3832,d3834],[d3834,d3835],[d3834,d3836],[d3836,d3837],[d3836,d3838],[d3838,d3839],[d3838,d3840],[d3840,d3841],[d3840,d3842],[d3842,d3843],[d3842,d3844],[d3844,d3845],[d3844,d3846],[d3846,d3847],[d3846,d3848],[d3848,d3849],[d3848,d3850],[d3850,d3851],[d3850,d3852],[d3852,d3853],[d3852,d3854],[d3854,d3855],[d3854,d3856],[d3856,d3857],[d3856,d3858],[d3858,d3859],[d3858,d3860],[d3860,d3861],[d3860,d3862],[d3862,d3863],[d3862,d3864],[d3864,d3865],[d3864,d3866],[d3866,d3867],[d3866,d3868],[d3868,d3869],[d3868,d3870],[d3870,d3871],[d3870,d3872],[d3872,d3873],[d3872,d3874],[d3874,d3875],[d3874,d3876],[d3876,d3877],[d3876,d3878],[d3878,d3879],[d3878,d3880],[d3880,d3881],[d3880,d3882],[d3882,d3883],[d3882,d3884],[d3884,d3885],[d3884,d3886],[d3886,d3887],[d3886,d3888],[d3888,d3889],[d3888,d3890],[d3890,d3891],[d3890,d3892],[d3892,d3893],[d3892,d3894],[d3894,d3895],[d3894,d3896],[d3896,d3897],[d3896,d3898],[d3898,d3899],[d3898,d3900],[d3900,d3901],[d3900,d3902],[d3902,d3903],[d3902,d3904],[d3904,d3905],[d3904,d3906],[d3906,d3907],[d3906,d3908],[d3908,d3909],[d3908,d3910],[d3910,d3911],[d3910,d3912],[d3912,d3913],[d3912,d3914],[d3914,d3915],[d3914,d3916],[d3916,d3917],[d3916,d3918],[d3918,d3919],[d3918,d3920],[d3920,d3921],[d3920,d3922],[d3922,d3923],[d3922,d3924],[d3924,d3925],[d3924,d3926],[d3926,d3927],[d3926,d3928],[d3928,d3929],[d3928,d3930],[d3930,d3931],[d3930,d3932],[d3932,d3933],[d3932,d3934],[d3934,d3935],[d3934,d3936],[d3936,d3937],[d3936,d3938],[d3938,d3939],[d3938,d3940],[d3940,d3941],[d3940,d3942],[d3942,d3943],[d3942,d3944],[d3944,d3945],[d3944,d3946],[d3946,d3947],[d3946,d3948],[d3948,d3949],[d3948,d3950],[d3950,d3951],[d3950,d3952],[d3952,d3953],[d3952,d3954],[d3954,d3955],[d3954,d3956],[d3956,d3957],[d3956,d3958],[d3958,d3959],[d3958,d3960],[d3960,d3961],[d3960,d3962],[d3962,d3963],[d3962,d3964],[d3964,d3965],[d3964,d3966],[d3966,d3967],[d3966,d3968],[d3968,d3969],[d3968,d3970],[d3970,d3971],[d3970,d3972],[d3972,d3973],[d3972,d3974],[d3974,d3975],[d3974,d3976],[d3976,d3977],[d3976,d3978],[d3978,d3979],[d3978,d3980],[d3980,d3981],[d3980,d3982],[d3982,d3983],[d3982,d3984],[d3984,d3985],[d3984,d3986],[d3986,d3987],[d3986,d3988],[d3988,d3989],[d3988,d3990],[d3990,d3991],[d3990,d3992],[d3992,d3993],[d3992,d3994],[d3994,d3995],[d3994,d3996],[d3996,d3997],[d3996,d3998],[d3998,d3999],[d3998,d4000],[d4000,d4001],[d4000,d4002],[d4002,d4003],[d4002,d4004],[d4004,d4005],[d4004,d4006],[d4006,d4007],[d4006,d4008],[d4008,d4009],[d4008,d4010],[d4010,d4011],[d4010,d4012],[d4012,d4013],[d4012,d4014],[d4014,d4015],[d4014,d4016],[d4016,d4017],[d4016,d4018],[d4018,d4019],[d4018,d4020],[d4020,d4021],[d4020,d4022],[d4022,d4023],[d4022,d4024],[d4024,d4025],[d4024,d4026],[d4026,d4027],[d4026,d4028],[d4028,d4029],[d4028,d4030],[d4030,d4031],[d4030,d4032],[d4032,d4033],[d4032,d4034],[d4034,d4035],[d4034,d4036],[d4036,d4037],[d4036,d4038],[d4038,d4039],[d4038,d4040],[d4040,d4041],[d4040,d4042],[d4042,d4043],[d4042,d4044],[d4044,d4045],[d4044,d4046],[d4046,d4047],[d4046,d4048],[d4048,d4049],[d4048,d4050],[d4050,d4051],[d4050,d4052],[d4052,d4053],[d4052,d4054],[d4054,d4055],[d4054,d4056],[d4056,d4057],[d4056,d4058],[d4058,d4059],[d4058,d4060],[d4060,d4061],[d4060,d4062],[d4062,d4063],[d4062,d4064],[d4064,d4065],[d4064,d4066],[d4066,d4067],[d4066,d4068],[d4068,d4069],[d4068,d4070],[d4070,d4071],[d4070,d4072],[d4072,d4073],[d4072,d4074],[d4074,d4075],[d4074,d4076],[d4076,d4077],[d4076,d4078],[d4078,d4079],[d4078,d4080],[d4080,d4081],[d4080,d4082],[d4082,d4083],[d4082,d4084],[d4084,d4085],[d4084,d4086],[d4086,d4087],[d4086,d4088],[d4088,d4089],[d4088,d4090],[d4090,d4091],[d4090,d4092],[d4092,d4093],[d4092,d4094],[d4094,d4095],[d4094,d4096],[d4096,d4097],[d4096,d4098],[d4098,d4099],[d4098,d4100],[d4100,d4101],[d4100,d4102],[d4102,d4103],[d4102,d4104],[d4104,d4105],[d4104,d4106],[d4106,d4107],[d4106,d4108],[d4108,d4109],[d4108,d4110],[d4110,d4111],[d4110,d4112],[d4112,d4113],[d4112,d4114],[d4114,d4115],[d4114,d4116],[d4116,d4117],[d4116,d4118],[d4118,d4119],[d4118,d4120],[d4120,d4121],[d4120,d4122],[d4122,d4123],[d4122,d4124],[d4124,d4125],[d4124,d4126],[d4126,d4127],[d4126,d4128],[d4128,d4129],[d4128,d4130],[d4130,d4131],[d4130,d4132],[d4132,d4133],[d4132,d4134],[d4134,d4135],[d4134,d4136],[d4136,d4137],[d4136,d4138],[d4138,d4139],[d4138,d4140],[d4140,d4141],[d4140,d4142],[d4142,d4143],[d4142,d4144],[d4144,d4145],[d4144,d4146],[d4146,d4147],[d4146,d4148],[d4148,d4149],[d4148,d4150],[d4150,d4151],[d4150,d4152],[d4152,d4153],[d4152,d4154],[d4154,d4155],[d4154,d4156],[d4156,d4157],[d4156,d4158],[d4158,d4159],[d4158,d4160],[d4160,d4161],[d4160,d4162],[d4162,d4163],[d4162,d4164],[d4164,d4165],[d4164,d4166],[d4166,d4167],[d4166,d4168],[d4168,d4169],[d4168,d4170],[d4170,d4171],[d4170,d4172],[d4172,d4173],[d4172,d4174],[d4174,d4175],[d4174,d4176],[d4176,d4177],[d4176,d4178],[d4178,d4179],[d4178,d4180],[d4180,d4181],[d4180,d4182],[d4182,d4183],[d4182,d4184],[d4184,d4185],[d4184,d4186],[d4186,d4187],[d4186,d4188],[d4188,d4189],[d4188,d4190],[d4190,d4191],[d4190,d4192],[d4192,d4193],[d4192,d4194],[d4194,d4195],[d4194,d4196],[d4196,d4197],[d4196,d4198],[d4198,d4199],[d4198,d4200],[d4200,d4201],[d4200,d4202],[d4202,d4203],[d4202,d4204],[d4204,d4205],[d4204,d4206],[d4206,d4207],[d4206,d4208],[d4208,d4209],[d4208,d4210],[d4210,d4211],[d4210,d4212],[d4212,d4213],[d4212,d4214],[d4214,d4215],[d4214,d4216],[d4216,d4217],[d4216,d4218],[d4218,d4219],[d4218,d4220],[d4220,d4221],[d4220,d4222],[d4222,d4223],[d4222,d4224],[d4224,d4225],[d4224,d4226],[d4226,d4227],[d4226,d4228],[d4228,d4229],[d4228,d4230],[d4230,d4231],[d4230,d4232],[d4232,d4233],[d4232,d4234],[d4234,d4235],[d4234,d4236],[d4236,d4237],[d4236,d4238],[d4238,d4239],[d4238,d4240],[d4240,d4241],[d4240,d4242],[d4242,d4243],[d4242,d4244],[d4244,d4245],[d4244,d4246],[d4246,d4247],[d4246,d4248],[d4248,d4249],[d4248,d4250],[d4250,d4251],[d4250,d4252],[d4252,d4253],[d4252,d4254],[d4254,d4255],[d4254,d4256],[d4256,d4257],[d4256,d4258],[d4258,d4259],[d4258,d4260],[d4260,d4261],[d4260,d4262],[d4262,d4263],[d4262,d4264],[d4264,d4265],[d4264,d4266],[d4266,d4267],[d4266,d4268],[d4268,d4269],[d4268,d4270],[d4270,d4271],[d4270,d4272],[d4272,d4273],[d4272,d4274],[d4274,d4275],[d4274,d4276],[d4276,d4277],[d4276,d4278],[d4278,d4279],[d4278,d4280],[d4280,d4281],[d4280,d4282],[d4282,d4283],[d4282,d4284],[d4284,d4285],[d4284,d4286],[d4286,d4287],[d4286,d4288],[d4288,d4289],[d4288,d4290],[d4290,d4291],[d4290,d4292],[d4292,d4293],[d4292,d4294],[d4294,d4295],[d4294,d4296],[d4296,d4297],[d4296,d4298],[d4298,d4299],[d4298,d4300],[d4300,d4301],[d4300,d4302],[d4302,d4303],[d4302,d4304],[d4304,d4305],[d4304,d4306],[d4306,d4307],[d4306,d4308],[d4308,d4309],[d4308,d4310],[d4310,d4311],[d4310,d4312],[d4312,d4313],[d4312,d4314],[d4314,d4315],[d4314,d4316],[d4316,d4317],[d4316,d4318],[d4318,d4319],[d4318,d4320],[d4320,d4321],[d4320,d4322],[d4322,d4323],[d4322,d4324],[d4324,d4325],[d4324,d4326],[d4326,d4327],[d4326,d4328],[d4328,d4329],[d4328,d4330],[d4330,d4331],[d4330,d4332],[d4332,d4333],[d4332,d4334],[d4334,d4335],[d4334,d4336],[d4336,d4337],[d4336,d4338],[d4338,d4339],[d4338,d4340],[d4340,d4341],[d4340,d4342],[d4342,d4343],[d4342,d4344],[d4344,d4345],[d4344,d4346],[d4346,d4347],[d4346,d4348],[d4348,d4349],[d4348,d4350],[d4350,d4351],[d4350,d4352],[d4352,d4353],[d4352,d4354],[d4354,d4355],[d4354,d4356],[d4356,d4357],[d4356,d4358],[d4358,d4359],[d4358,d4360],[d4360,d4361],[d4360,d4362],[d4362,d4363],[d4362,d4364],[d4364,d4365],[d4364,d4366],[d4366,d4367],[d4366,d4368],[d4368,d4369],[d4368,d4370],[d4370,d4371],[d4370,d4372],[d4372,d4373],[d4372,d4374],[d4374,d4375],[d4374,d4376],[d4376,d4377],[d4376,d4378],[d4378,d4379],[d4378,d4380],[d4380,d4381],[d4380,d4382],[d4382,d4383],[d4382,d4384],[d4384,d4385],[d4384,d4386],[d4386,d4387],[d4386,d4388],[d4388,d4389],[d4388,d4390],[d4390,d4391],[d4390,d4392],[d4392,d4393],[d4392,d4394],[d4394,d4395],[d4394,d4396],[d4396,d4397],[d4396,d4398],[d4398,d4399],[d4398,d4400],[d4400,d4401],[d4400,d4402],[d4402,d4403],[d4402,d4404],[d4404,d4405],[d4404,d4406],[d4406,d4407],[d4406,d4408],[d4408,d4409],[d4408,d4410],[d4410,d4411],[d4410,d4412],[d4412,d4413],[d4412,d4414],[d4414,d4415],[d4414,d4416],[d4416,d4417],[d4416,d4418],[d4418,d4419],[d4418,d4420],[d4420,d4421],[d4420,d4422],[d4422,d4423],[d4422,d4424],[d4424,d4425],[d4424,d4426],[d4426,d4427],[d4426,d4428],[d4428,d4429],[d4428,d4430],[d4430,d4431],[d4430,d4432],[d4432,d4433],[d4432,d4434],[d4434,d4435],[d4434,d4436],[d4436,d4437],[d4436,d4438],[d4438,d4439],[d4438,d4440],[d4440,d4441],[d4440,d4442],[d4442,d4443],[d4442,d4444],[d4444,d4445],[d4444,d4446],[d4446,d4447],[d4446,d4448],[d4448,d4449],[d4448,d4450],[d4450,d4451],[d4450,d4452],[d4452,d4453],[d4452,d4454],[d4454,d4455],[d4454,d4456],[d4456,d4457],[d4456,d4458],[d4458,d4459],[d4458,d4460],[d4460,d4461],[d4460,d4462],[d4462,d4463],[d4462,d4464],[d4464,d4465],[d4464,d4466],[d4466,d4467],[d4466,d4468],[d4468,d4469],[d4468,d4470],[d4470,d4471],[d4470,d4472],[d4472,d4473],[d4472,d4474],[d4474,d4475],[d4474,d4476],[d4476,d4477],[d4476,d4478],[d4478,d4479],[d4478,d4480],[d4480,d4481],[d4480,d4482],[d4482,d4483],[d4482,d4484],[d4484,d4485],[d4484,d4486],[d4486,d4487],[d4486,d4488],[d4488,d4489],[d4488,d4490],[d4490,d4491],[d4490,d4492],[d4492,d4493],[d4492,d4494],[d4494,d4495],[d4494,d4496],[d4496,d4497],[d4496,d4498],[d4498,d4499],[d4498,d4500],[d4500,d4501],[d4500,d4502],[d4502,d4503],[d4502,d4504],[d4504,d4505],[d4504,d4506],[d4506,d4507],[d4506,d4508],[d4508,d4509],[d4508,d4510],[d4510,d4511],[d4510,d4512],[d4512,d4513],[d4512,d4514],[d4514,d4515],[d4514,d4516],[d4516,d4517],[d4516,d4518],[d4518,d4519],[d4518,d4520],[d4520,d4521],[d4520,d4522],[d4522,d4523],[d4522,d4524],[d4524,d4525],[d4524,d4526],[d4526,d4527],[d4526,d4528],[d4528,d4529],[d4528,d4530],[d4530,d4531],[d4530,d4532],[d4532,d4533],[d4532,d4534],[d4534,d4535],[d4534,d4536],[d4536,d4537],[d4536,d4538],[d4538,d4539],[d4538,d4540],[d4540,d4541],[d4540,d4542],[d4542,d4543],[d4542,d4544],[d4544,d4545],[d4544,d4546],[d4546,d4547],[d4546,d4548],[d4548,d4549],[d4548,d4550],[d4550,d4551],[d4550,d4552],[d4552,d4553],[d4552,d4554],[d4554,d4555],[d4554,d4556],[d4556,d4557],[d4556,d4558],[d4558,d4559],[d4558,d4560],[d4560,d4561],[d4560,d4562],[d4562,d4563],[d4562,d4564],[d4564,d4565],[d4564,d4566],[d4566,d4567],[d4566,d4568],[d4568,d4569],[d4568,d4570],[d4570,d4571],[d4570,d4572],[d4572,d4573],[d4572,d4574],[d4574,d4575],[d4574,d4576],[d4576,d4577],[d4576,d4578],[d4578,d4579],[d4578,d4580],[d4580,d4581],[d4580,d4582],[d4582,d4583],[d4582,d4584],[d4584,d4585],[d4584,d4586],[d4586,d4587],[d4586,d4588],[d4588,d4589],[d4588,d4590],[d4590,d4591],[d4590,d4592],[d4592,d4593],[d4592,d4594],[d4594,d4595],[d4594,d4596],[d4596,d4597],[d4596,d4598],[d4598,d4599],[d4598,d4600],[d4600,d4601],[d4600,d4602],[d4602,d4603],[d4602,d4604],[d4604,d4605],[d4604,d4606],[d4606,d4607],[d4606,d4608],[d4608,d4609],[d4608,d4610],[d4610,d4611],[d4610,d4612],[d4612,d4613],[d4612,d4614],[d4614,d4615],[d4614,d4616],[d4616,d4617],[d4616,d4618],[d4618,d4619],[d4618,d4620],[d4620,d4621],[d4620,d4622],[d4622,d4623],[d4622,d4624],[d4624,d4625],[d4624,d4626],[d4626,d4627],[d4626,d4628],[d4628,d4629],[d4628,d4630],[d4630,d4631],[d4630,d4632],[d4632,d4633],[d4632,d4634],[d4634,d4635],[d4634,d4636],[d4636,d4637],[d4636,d4638],[d4638,d4639],[d4638,d4640],[d4640,d4641],[d4640,d4642],[d4642,d4643],[d4642,d4644],[d4644,d4645],[d4644,d4646],[d4646,d4647],[d4646,d4648],[d4648,d4649],[d4648,d4650],[d4650,d4651],[d4650,d4652],[d4652,d4653],[d4652,d4654],[d4654,d4655],[d4654,d4656],[d4656,d4657],[d4656,d4658],[d4658,d4659],[d4658,d4660],[d4660,d4661],[d4660,d4662],[d4662,d4663],[d4662,d4664],[d4664,d4665],[d4664,d4666],[d4666,d4667],[d4666,d4668],[d4668,d4669],[d4668,d4670],[d4670,d4671],[d4670,d4672],[d4672,d4673],[d4672,d4674],[d4674,d4675],[d4674,d4676],[d4676,d4677],[d4676,d4678],[d4678,d4679],[d4678,d4680],[d4680,d4681],[d4680,d4682],[d4682,d4683],[d4682,d4684],[d4684,d4685],[d4684,d4686],[d4686,d4687],[d4686,d4688],[d4688,d4689],[d4688,d4690],[d4690,d4691],[d4690,d4692],[d4692,d4693],[d4692,d4694],[d4694,d4695],[d4694,d4696],[d4696,d4697],[d4696,d4698],[d4698,d4699],[d4698,d4700],[d4700,d4701],[d4700,d4702],[d4702,d4703],[d4702,d4704],[d4704,d4705],[d4704,d4706],[d4706,d4707],[d4706,d4708],[d4708,d4709],[d4708,d4710],[d4710,d4711],[d4710,d4712],[d4712,d4713],[d4712,d4714],[d4714,d4715],[d4714,d4716],[d4716,d4717],[d4716,d4718],[d4718,d4719],[d4718,d4720],[d4720,d4721],[d4720,d4722],[d4722,d4723],[d4722,d4724],[d4724,d4725],[d4724,d4726],[d4726,d4727],[d4726,d4728],[d4728,d4729],[d4728,d4730],[d4730,d4731],[d4730,d4732],[d4732,d4733],[d4732,d4734],[d4734,d4735],[d4734,d4736],[d4736,d4737],[d4736,d4738],[d4738,d4739],[d4738,d4740],[d4740,d4741],[d4740,d4742],[d4742,d4743],[d4742,d4744],[d4744,d4745],[d4744,d4746],[d4746,d4747],[d4746,d4748],[d4748,d4749],[d4748,d4750],[d4750,d4751],[d4750,d4752],[d4752,d4753],[d4752,d4754],[d4754,d4755],[d4754,d4756],[d4756,d4757],[d4756,d4758],[d4758,d4759],[d4758,d4760],[d4760,d4761],[d4760,d4762],[d4762,d4763],[d4762,d4764],[d4764,d4765],[d4764,d4766],[d4766,d4767],[d4766,d4768],[d4768,d4769],[d4768,d4770],[d4770,d4771],[d4770,d4772],[d4772,d4773],[d4772,d4774],[d4774,d4775],[d4774,d4776],[d4776,d4777],[d4776,d4778],[d4778,d4779],[d4778,d4780],[d4780,d4781],[d4780,d4782],[d4782,d4783],[d4782,d4784],[d4784,d4785],[d4784,d4786],[d4786,d4787],[d4786,d4788],[d4788,d4789],[d4788,d4790],[d4790,d4791],[d4790,d4792],[d4792,d4793],[d4792,d4794],[d4794,d4795],[d4794,d4796],[d4796,d4797],[d4796,d4798],[d4798,d4799],[d4798,d4800],[d4800,d4801],[d4800,d4802],[d4802,d4803],[d4802,d4804],[d4804,d4805],[d4804,d4806],[d4806,d4807],[d4806,d4808],[d4808,d4809],[d4808,d4810],[d4810,d4811],[d4810,d4812],[d4812,d4813],[d4812,d4814],[d4814,d4815],[d4814,d4816],[d4816,d4817],[d4816,d4818],[d4818,d4819],[d4818,d4820],[d4820,d4821],[d4820,d4822],[d4822,d4823],[d4822,d4824],[d4824,d4825],[d4824,d4826],[d4826,d4827],[d4826,d4828],[d4828,d4829],[d4828,d4830],[d4830,d4831],[d4830,d4832],[d4832,d4833],[d4832,d4834],[d4834,d4835],[d4834,d4836],[d4836,d4837],[d4836,d4838],[d4838,d4839],[d4838,d4840],[d4840,d4841],[d4840,d4842],[d4842,d4843],[d4842,d4844],[d4844,d4845],[d4844,d4846],[d4846,d4847],[d4846,d4848],[d4848,d4849],[d4848,d4850],[d4850,d4851],[d4850,d4852],[d4852,d4853],[d4852,d4854],[d4854,d4855],[d4854,d4856],[d4856,d4857],[d4856,d4858],[d4858,d4859],[d4858,d4860],[d4860,d4861],[d4860,d4862],[d4862,d4863],[d4862,d4864],[d4864,d4865],[d4864,d4866],[d4866,d4867],[d4866,d4868],[d4868,d4869],[d4868,d4870],[d4870,d4871],[d4870,d4872],[d4872,d4873],[d4872,d4874],[d4874,d4875],[d4874,d4876],[d4876,d4877],[d4876,d4878],[d4878,d4879],[d4878,d4880],[d4880,d4881],[d4880,d4882],[d4882,d4883],[d4882,d4884],[d4884,d4885],[d4884,d4886],[d4886,d4887],[d4886,d4888],[d4888,d4889],[d4888,d4890],[d4890,d4891],[d4890,d4892],[d4892,d4893],[d4892,d4894],[d4894,d4895],[d4894,d4896],[d4896,d4897],[d4896,d4898],[d4898,d4899],[d4898,d4900],[d4900,d4901],[d4900,d4902],[d4902,d4903],[d4902,d4904],[d4904,d4905],[d4904,d4906],[d4906,d4907],[d4906,d4908],[d4908,d4909],[d4908,d4910],[d4910,d4911],[d4910,d4912],[d4912,d4913],[d4912,d4914],[d4914,d4915],[d4914,d4916],[d4916,d4917],[d4916,d4918],[d4918,d4919],[d4918,d4920],[d4920,d4921],[d4920,d4922],[d4922,d4923],[d4922,d4924],[d4924,d4925],[d4924,d4926],[d4926,d4927],[d4926,d4928],[d4928,d4929],[d4928,d4930],[d4930,d4931],[d4930,d4932],[d4932,d4933],[d4932,d4934],[d4934,d4935],[d4934,d4936],[d4936,d4937],[d4936,d4938],[d4938,d4939],[d4938,d4940],[d4940,d4941],[d4940,d4942],[d4942,d4943],[d4942,d4944],[d4944,d4945],[d4944,d4946],[d4946,d4947],[d4946,d4948],[d4948,d4949],[d4948,d4950],[d4950,d4951],[d4950,d4952],[d4952,d4953],[d4952,d4954],[d4954,d4955],[d4954,d4956],[d4956,d4957],[d4956,d4958],[d4958,d4959],[d4958,d4960],[d4960,d4961],[d4960,d4962],[d4962,d4963],[d4962,d4964],[d4964,d4965],[d4964,d4966],[d4966,d4967],[d4966,d4968],[d4968,d4969],[d4968,d4970],[d4970,d4971],[d4970,d4972],[d4972,d4973],[d4972,d4974],[d4974,d4975],[d4974,d4976],[d4976,d4977],[d4976,d4978],[d4978,d4979],[d4978,d4980],[d4980,d4981],[d4980,d4982],[d4982,d4983],[d4982,d4984],[d4984,d4985],[d4984,d4986],[d4986,d4987],[d4986,d4988],[d4988,d4989],[d4988,d4990],[d4990,d4991],[d4990,d4992],[d4992,d4993],[d4992,d4994],[d4994,d4995],[d4994,d4996],[d4996,d4997],[d4996,d4998],[d4998,d4999],[d4998,d5000],[d5000,d5001],[d5000,d5002],[d5002,d5003],[d5002,d5004],[d5004,d5005],[d5004,d5006],[d5006,d5007],[d5006,d5008],[d5008,d5009],[d5008,d5010],[d5010,d5011],[d5010,d5012],[d5012,d5013],[d5012,d5014],[d5014,d5015],[d5014,d5016],[d5016,d5017],[d5016,d5018],[d5018,d5019],[d5018,d5020],[d5020,d5021],[d5020,d5022],[d5022,d5023],[d5022,d5024],[d5024,d5025],[d5024,d5026],[d5026,d5027],[d5026,d5028],[d5028,d5029],[d5028,d5030],[d5030,d5031],[d5030,d5032],[d5032,d5033],[d5032,d5034],[d5034,d5035],[d5034,d5036],[d5036,d5037],[d5036,d5038],[d5038,d5039],[d5038,d5040],[d5040,d5041],[d5040,d5042],[d5042,d5043],[d5042,d5044],[d5044,d5045],[d5044,d5046],[d5046,d5047],[d5046,d5048],[d5048,d5049],[d5048,d5050],[d5050,d5051],[d5050,d5052],[d5052,d5053],[d5052,d5054],[d5054,d5055],[d5054,d5056],[d5056,d5057],[d5056,d5058],[d5058,d5059],[d5058,d5060],[d5060,d5061],[d5060,d5062],[d5062,d5063],[d5062,d5064],[d5064,d5065],[d5064,d5066],[d5066,d5067],[d5066,d5068],[d5068,d5069],[d5068,d5070],[d5070,d5071],[d5070,d5072],[d5072,d5073],[d5072,d5074],[d5074,d5075],[d5074,d5076],[d5076,d5077],[d5076,d5078],[d5078,d5079],[d5078,d5080],[d5080,d5081],[d5080,d5082],[d5082,d5083],[d5082,d5084],[d5084,d5085],[d5084,d5086],[d5086,d5087],[d5086,d5088],[d5088,d5089],[d5088,d5090],[d5090,d5091],[d5090,d5092],[d5092,d5093],[d5092,d5094],[d5094,d5095],[d5094,d5096],[d5096,d5097],[d5096,d5098],[d5098,d5099],[d5098,d5100],[d5100,d5101],[d5100,d5102],[d5102,d5103],[d5102,d5104],[d5104,d5105],[d5104,d5106],[d5106,d5107],[d5106,d5108],[d5108,d5109],[d5108,d5110],[d5110,d5111],[d5110,d5112],[d5112,d5113],[d5112,d5114],[d5114,d5115],[d5114,d5116],[d5116,d5117],[d5116,d5118],[d5118,d5119],[d5118,d5120],[d5120,d5121],[d5120,d5122],[d5122,d5123],[d5122,d5124],[d5124,d5125],[d5124,d5126],[d5126,d5127],[d5126,d5128],[d5128,d5129],[d5128,d5130],[d5130,d5131],[d5130,d5132],[d5132,d5133],[d5132,d5134],[d5134,d5135],[d5134,d5136],[d5136,d5137],[d5136,d5138],[d5138,d5139],[d5138,d5140],[d5140,d5141],[d5140,d5142],[d5142,d5143],[d5142,d5144],[d5144,d5145],[d5144,d5146],[d5146,d5147],[d5146,d5148],[d5148,d5149],[d5148,d5150],[d5150,d5151],[d5150,d5152],[d5152,d5153],[d5152,d5154],[d5154,d5155],[d5154,d5156],[d5156,d5157],[d5156,d5158],[d5158,d5159],[d5158,d5160],[d5160,d5161],[d5160,d5162],[d5162,d5163],[d5162,d5164],[d5164,d5165],[d5164,d5166],[d5166,d5167],[d5166,d5168],[d5168,d5169],[d5168,d5170],[d5170,d5171],[d5170,d5172],[d5172,d5173],[d5172,d5174],[d5174,d5175],[d5174,d5176],[d5176,d5177],[d5176,d5178],[d5178,d5179],[d5178,d5180],[d5180,d5181],[d5180,d5182],[d5182,d5183],[d5182,d5184],[d5184,d5185],[d5184,d5186],[d5186,d5187],[d5186,d5188],[d5188,d5189],[d5188,d5190],[d5190,d5191],[d5190,d5192],[d5192,d5193],[d5192,d5194],[d5194,d5195],[d5194,d5196],[d5196,d5197],[d5196,d5198],[d5198,d5199],[d5198,d5200],[d5200,d5201],[d5200,d5202],[d5202,d5203],[d5202,d5204],[d5204,d5205],[d5204,d5206],[d5206,d5207],[d5206,d5208],[d5208,d5209],[d5208,d5210],[d5210,d5211],[d5210,d5212],[d5212,d5213],[d5212,d5214],[d5214,d5215],[d5214,d5216],[d5216,d5217],[d5216,d5218],[d5218,d5219],[d5218,d5220],[d5220,d5221],[d5220,d5222],[d5222,d5223],[d5222,d5224],[d5224,d5225],[d5224,d5226],[d5226,d5227],[d5226,d5228],[d5228,d5229],[d5228,d5230],[d5230,d5231],[d5230,d5232],[d5232,d5233],[d5232,d5234],[d5234,d5235],[d5234,d5236],[d5236,d5237],[d5236,d5238],[d5238,d5239],[d5238,d5240],[d5240,d5241],[d5240,d5242],[d5242,d5243],[d5242,d5244],[d5244,d5245],[d5244,d5246],[d5246,d5247],[d5246,d5248],[d5248,d5249],[d5248,d5250],[d5250,d5251],[d5250,d5252],[d5252,d5253],[d5252,d5254],[d5254,d5255],[d5254,d5256],[d5256,d5257],[d5256,d5258],[d5258,d5259],[d5258,d5260],[d5260,d5261],[d5260,d5262],[d5262,d5263],[d5262,d5264],[d5264,d5265],[d5264,d5266],[d5266,d5267],[d5266,d5268],[d5268,d5269],[d5268,d5270],[d5270,d5271],[d5270,d5272],[d5272,d5273],[d5272,d5274],[d5274,d5275],[d5274,d5276],[d5276,d5277],[d5276,d5278],[d5278,d5279],[d5278,d5280],[d5280,d5281],[d5280,d5282],[d5282,d5283],[d5282,d5284],[d5284,d5285],[d5284,d5286],[d5286,d5287],[d5286,d5288],[d5288,d5289],[d5288,d5290],[d5290,d5291],[d5290,d5292],[d5292,d5293],[d5292,d5294],[d5294,d5295],[d5294,d5296],[d5296,d5297],[d5296,d5298],[d5298,d5299],[d5298,d5300],[d5300,d5301],[d5300,d5302],[d5302,d5303],[d5302,d5304],[d5304,d5305],[d5304,d5306],[d5306,d5307],[d5306,d5308],[d5308,d5309],[d5308,d5310],[d5310,d5311],[d5310,d5312],[d5312,d5313],[d5312,d5314],[d5314,d5315],[d5314,d5316],[d5316,d5317],[d5316,d5318],[d5318,d5319],[d5318,d5320],[d5320,d5321],[d5320,d5322],[d5322,d5323],[d5322,d5324],[d5324,d5325],[d5324,d5326],[d5326,d5327],[d5326,d5328],[d5328,d5329],[d5328,d5330],[d5330,d5331],[d5330,d5332],[d5332,d5333],[d5332,d5334],[d5334,d5335],[d5334,d5336],[d5336,d5337],[d5336,d5338],[d5338,d5339],[d5338,d5340],[d5340,d5341],[d5340,d5342],[d5342,d5343],[d5342,d5344],[d5344,d5345],[d5344,d5346],[d5346,d5347],[d5346,d5348],[d5348,d5349],[d5348,d5350],[d5350,d5351],[d5350,d5352],[d5352,d5353],[d5352,d5354],[d5354,d5355],[d5354,d5356],[d5356,d5357],[d5356,d5358],[d5358,d5359],[d5358,d5360],[d5360,d5361],[d5360,d5362],[d5362,d5363],[d5362,d5364],[d5364,d5365],[d5364,d5366],[d5366,d5367],[d5366,d5368],[d5368,d5369],[d5368,d5370],[d5370,d5371],[d5370,d5372],[d5372,d5373],[d5372,d5374],[d5374,d5375],[d5374,d5376],[d5376,d5377],[d5376,d5378],[d5378,d5379],[d5378,d5380],[d5380,d5381],[d5380,d5382],[d5382,d5383],[d5382,d5384],[d5384,d5385],[d5384,d5386],[d5386,d5387],[d5386,d5388],[d5388,d5389],[d5388,d5390],[d5390,d5391],[d5390,d5392],[d5392,d5393],[d5392,d5394],[d5394,d5395],[d5394,d5396],[d5396,d5397],[d5396,d5398],[d5398,d5399],[d5398,d5400],[d5400,d5401],[d5400,d5402],[d5402,d5403],[d5402,d5404],[d5404,d5405],[d5404,d5406],[d5406,d5407],[d5406,d5408],[d5408,d5409],[d5408,d5410],[d5410,d5411],[d5410,d5412],[d5412,d5413],[d5412,d5414],[d5414,d5415],[d5414,d5416],[d5416,d5417],[d5416,d5418],[d5418,d5419],[d5418,d5420],[d5420,d5421],[d5420,d5422],[d5422,d5423],[d5422,d5424],[d5424,d5425],[d5424,d5426],[d5426,d5427],[d5426,d5428],[d5428,d5429],[d5428,d5430],[d5430,d5431],[d5430,d5432],[d5432,d5433],[d5432,d5434],[d5434,d5435],[d5434,d5436],[d5436,d5437],[d5436,d5438],[d5438,d5439],[d5438,d5440],[d5440,d5441],[d5440,d5442],[d5442,d5443],[d5442,d5444],[d5444,d5445],[d5444,d5446],[d5446,d5447],[d5446,d5448],[d5448,d5449],[d5448,d5450],[d5450,d5451],[d5450,d5452],[d5452,d5453],[d5452,d5454],[d5454,d5455],[d5454,d5456],[d5456,d5457],[d5456,d5458],[d5458,d5459],[d5458,d5460],[d5460,d5461],[d5460,d5462],[d5462,d5463],[d5462,d5464],[d5464,d5465],[d5464,d5466],[d5466,d5467],[d5466,d5468],[d5468,d5469],[d5468,d5470],[d5470,d5471],[d5470,d5472],[d5472,d5473],[d5472,d5474],[d5474,d5475],[d5474,d5476],[d5476,d5477],[d5476,d5478],[d5478,d5479],[d5478,d5480],[d5480,d5481],[d5480,d5482],[d5482,d5483],[d5482,d5484],[d5484,d5485],[d5484,d5486],[d5486,d5487],[d5486,d5488],[d5488,d5489],[d5488,d5490],[d5490,d5491],[d5490,d5492],[d5492,d5493],[d5492,d5494],[d5494,d5495],[d5494,d5496],[d5496,d5497],[d5496,d5498],[d5498,d5499],[d5498,d5500],[d5500,d5501],[d5500,d5502],[d5502,d5503],[d5502,d5504],[d5504,d5505],[d5504,d5506],[d5506,d5507],[d5506,d5508],[d5508,d5509],[d5508,d5510],[d5510,d5511],[d5510,d5512],[d5512,d5513],[d5512,d5514],[d5514,d5515],[d5514,d5516],[d5516,d5517],[d5516,d5518],[d5518,d5519],[d5518,d5520],[d5520,d5521],[d5520,d5522],[d5522,d5523],[d5522,d5524],[d5524,d5525],[d5524,d5526],[d5526,d5527],[d5526,d5528],[d5528,d5529],[d5528,d5530],[d5530,d5531],[d5530,d5532],[d5532,d5533],[d5532,d5534],[d5534,d5535],[d5534,d5536],[d5536,d5537],[d5536,d5538],[d5538,d5539],[d5538,d5540],[d5540,d5541],[d5540,d5542],[d5542,d5543],[d5542,d5544],[d5544,d5545],[d5544,d5546],[d5546,d5547],[d5546,d5548],[d5548,d5549],[d5548,d5550],[d5550,d5551],[d5550,d5552],[d5552,d5553],[d5552,d5554],[d5554,d5555],[d5554,d5556],[d5556,d5557],[d5556,d5558],[d5558,d5559],[d5558,d5560],[d5560,d5561],[d5560,d5562],[d5562,d5563],[d5562,d5564],[d5564,d5565],[d5564,d5566],[d5566,d5567],[d5566,d5568],[d5568,d5569],[d5568,d5570],[d5570,d5571],[d5570,d5572],[d5572,d5573],[d5572,d5574],[d5574,d5575],[d5574,d5576],[d5576,d5577],[d5576,d5578],[d5578,d5579],[d5578,d5580],[d5580,d5581],[d5580,d5582],[d5582,d5583],[d5582,d5584],[d5584,d5585],[d5584,d5586],[d5586,d5587],[d5586,d5588],[d5588,d5589],[d5588,d5590],[d5590,d5591],[d5590,d5592],[d5592,d5593],[d5592,d5594],[d5594,d5595],[d5594,d5596],[d5596,d5597],[d5596,d5598],[d5598,d5599],[d5598,d5600],[d5600,d5601],[d5600,d5602],[d5602,d5603],[d5602,d5604],[d5604,d5605],[d5604,d5606],[d5606,d5607],[d5606,d5608],[d5608,d5609],[d5608,d5610],[d5610,d5611],[d5610,d5612],[d5612,d5613],[d5612,d5614],[d5614,d5615],[d5614,d5616],[d5616,d5617],[d5616,d5618],[d5618,d5619],[d5618,d5620],[d5620,d5621],[d5620,d5622],[d5622,d5623],[d5622,d5624],[d5624,d5625],[d5624,d5626],[d5626,d5627],[d5626,d5628],[d5628,d5629],[d5628,d5630],[d5630,d5631],[d5630,d5632],[d5632,d5633],[d5632,d5634],[d5634,d5635],[d5634,d5636],[d5636,d5637],[d5636,d5638],[d5638,d5639],[d5638,d5640],[d5640,d5641],[d5640,d5642],[d5642,d5643],[d5642,d5644],[d5644,d5645],[d5644,d5646],[d5646,d5647],[d5646,d5648],[d5648,d5649],[d5648,d5650],[d5650,d5651],[d5650,d5652],[d5652,d5653],[d5652,d5654],[d5654,d5655],[d5654,d5656],[d5656,d5657],[d5656,d5658],[d5658,d5659],[d5658,d5660],[d5660,d5661],[d5660,d5662],[d5662,d5663],[d5662,d5664],[d5664,d5665],[d5664,d5666],[d5666,d5667],[d5666,d5668],[d5668,d5669],[d5668,d5670],[d5670,d5671],[d5670,d5672],[d5672,d5673],[d5672,d5674],[d5674,d5675],[d5674,d5676],[d5676,d5677],[d5676,d5678],[d5678,d5679],[d5678,d5680],[d5680,d5681],[d5680,d5682],[d5682,d5683],[d5682,d5684],[d5684,d5685],[d5684,d5686],[d5686,d5687],[d5686,d5688],[d5688,d5689],[d5688,d5690],[d5690,d5691],[d5690,d5692],[d5692,d5693],[d5692,d5694],[d5694,d5695],[d5694,d5696],[d5696,d5697],[d5696,d5698],[d5698,d5699],[d5698,d5700],[d5700,d5701],[d5700,d5702],[d5702,d5703],[d5702,d5704],[d5704,d5705],[d5704,d5706],[d5706,d5707],[d5706,d5708],[d5708,d5709],[d5708,d5710],[d5710,d5711],[d5710,d5712],[d5712,d5713],[d5712,d5714],[d5714,d5715],[d5714,d5716],[d5716,d5717],[d5716,d5718],[d5718,d5719],[d5718,d5720],[d5720,d5721],[d5720,d5722],[d5722,d5723],[d5722,d5724],[d5724,d5725],[d5724,d5726],[d5726,d5727],[d5726,d5728],[d5728,d5729],[d5728,d5730],[d5730,d5731],[d5730,d5732],[d5732,d5733],[d5732,d5734],[d5734,d5735],[d5734,d5736],[d5736,d5737],[d5736,d5738],[d5738,d5739],[d5738,d5740],[d5740,d5741],[d5740,d5742],[d5742,d5743],[d5742,d5744],[d5744,d5745],[d5744,d5746],[d5746,d5747],[d5746,d5748],[d5748,d5749],[d5748,d5750],[d5750,d5751],[d5750,d5752],[d5752,d5753],[d5752,d5754],[d5754,d5755],[d5754,d5756],[d5756,d5757],[d5756,d5758],[d5758,d5759],[d5758,d5760],[d5760,d5761],[d5760,d5762],[d5762,d5763],[d5762,d5764],[d5764,d5765],[d5764,d5766],[d5766,d5767],[d5766,d5768],[d5768,d5769],[d5768,d5770],[d5770,d5771],[d5770,d5772],[d5772,d5773],[d5772,d5774],[d5774,d5775],[d5774,d5776],[d5776,d5777],[d5776,d5778],[d5778,d5779],[d5778,d5780],[d5780,d5781],[d5780,d5782],[d5782,d5783],[d5782,d5784],[d5784,d5785],[d5784,d5786],[d5786,d5787],[d5786,d5788],[d5788,d5789],[d5788,d5790],[d5790,d5791],[d5790,d5792],[d5792,d5793],[d5792,d5794],[d5794,d5795],[d5794,d5796],[d5796,d5797],[d5796,d5798],[d5798,d5799],[d5798,d5800],[d5800,d5801],[d5800,d5802],[d5802,d5803],[d5802,d5804],[d5804,d5805],[d5804,d5806],[d5806,d5807],[d5806,d5808],[d5808,d5809],[d5808,d5810],[d5810,d5811],[d5810,d5812],[d5812,d5813],[d5812,d5814],[d5814,d5815],[d5814,d5816],[d5816,d5817],[d5816,d5818],[d5818,d5819],[d5818,d5820],[d5820,d5821],[d5820,d5822],[d5822,d5823],[d5822,d5824],[d5824,d5825],[d5824,d5826],[d5826,d5827],[d5826,d5828],[d5828,d5829],[d5828,d5830],[d5830,d5831],[d5830,d5832],[d5832,d5833],[d5832,d5834],[d5834,d5835],[d5834,d5836],[d5836,d5837],[d5836,d5838],[d5838,d5839],[d5838,d5840],[d5840,d5841],[d5840,d5842],[d5842,d5843],[d5842,d5844],[d5844,d5845],[d5844,d5846],[d5846,d5847],[d5846,d5848],[d5848,d5849],[d5848,d5850],[d5850,d5851],[d5850,d5852],[d5852,d5853],[d5852,d5854],[d5854,d5855],[d5854,d5856],[d5856,d5857],[d5856,d5858],[d5858,d5859],[d5858,d5860],[d5860,d5861],[d5860,d5862],[d5862,d5863],[d5862,d5864],[d5864,d5865],[d5864,d5866],[d5866,d5867],[d5866,d5868],[d5868,d5869],[d5868,d5870],[d5870,d5871],[d5870,d5872],[d5872,d5873],[d5872,d5874],[d5874,d5875],[d5874,d5876],[d5876,d5877],[d5876,d5878],[d5878,d5879],[d5878,d5880],[d5880,d5881],[d5880,d5882],[d5882,d5883],[d5882,d5884],[d5884,d5885],[d5884,d5886],[d5886,d5887],[d5886,d5888],[d5888,d5889],[d5888,d5890],[d5890,d5891],[d5890,d5892],[d5892,d5893],[d5892,d5894],[d5894,d5895],[d5894,d5896],[d5896,d5897],[d5896,d5898],[d5898,d5899],[d5898,d5900],[d5900,d5901],[d5900,d5902],[d5902,d5903],[d5902,d5904],[d5904,d5905],[d5904,d5906],[d5906,d5907],[d5906,d5908],[d5908,d5909],[d5908,d5910],[d5910,d5911],[d5910,d5912],[d5912,d5913],[d5912,d5914],[d5914,d5915],[d5914,d5916],[d5916,d5917],[d5916,d5918],[d5918,d5919],[d5918,d5920],[d5920,d5921],[d5920,d5922],[d5922,d5923],[d5922,d5924],[d5924,d5925],[d5924,d5926],[d5926,d5927],[d5926,d5928],[d5928,d5929],[d5928,d5930],[d5930,d5931],[d5930,d5932],[d5932,d5933],[d5932,d5934],[d5934,d5935],[d5934,d5936],[d5936,d5937],[d5936,d5938],[d5938,d5939],[d5938,d5940],[d5940,d5941],[d5940,d5942],[d5942,d5943],[d5942,d5944],[d5944,d5945],[d5944,d5946],[d5946,d5947],[d5946,d5948],[d5948,d5949],[d5948,d5950],[d5950,d5951],[d5950,d5952],[d5952,d5953],[d5952,d5954],[d5954,d5955],[d5954,d5956],[d5956,d5957],[d5956,d5958],[d5958,d5959],[d5958,d5960],[d5960,d5961],[d5960,d5962],[d5962,d5963],[d5962,d5964],[d5964,d5965],[d5964,d5966],[d5966,d5967],[d5966,d5968],[d5968,d5969],[d5968,d5970],[d5970,d5971],[d5970,d5972],[d5972,d5973],[d5972,d5974],[d5974,d5975],[d5974,d5976],[d5976,d5977],[d5976,d5978],[d5978,d5979],[d5978,d5980],[d5980,d5981],[d5980,d5982],[d5982,d5983],[d5982,d5984],[d5984,d5985],[d5984,d5986],[d5986,d5987],[d5986,d5988],[d5988,d5989],[d5988,d5990],[d5990,d5991],[d5990,d5992],[d5992,d5993],[d5992,d5994],[d5994,d5995],[d5994,d5996],[d5996,d5997],[d5996,d5998],[d5998,d5999],[d5998,d6000],[d6000,d6001],[d6000,d6002],[d6002,d6003],[d6002,d6004],[d6004,d6005],[d6004,d6006],[d6006,d6007],[d6006,d6008],[d6008,d6009],[d6008,d6010],[d6010,d6011],[d6010,d6012],[d6012,d6013],[d6012,d6014],[d6014,d6015],[d6014,d6016],[d6016,d6017],[d6016,d6018],[d6018,d6019],[d6018,d6020],[d6020,d6021],[d6020,d6022],[d6022,d6023],[d6022,d6024],[d6024,d6025],[d6024,d6026],[d6026,d6027],[d6026,d6028],[d6028,d6029],[d6028,d6030],[d6030,d6031],[d6030,d6032],[d6032,d6033],[d6032,d6034],[d6034,d6035],[d6034,d6036],[d6036,d6037],[d6036,d6038],[d6038,d6039],[d6038,d6040],[d6040,d6041],[d6040,d6042],[d6042,d6043],[d6042,d6044],[d6044,d6045],[d6044,d6046],[d6046,d6047],[d6046,d6048],[d6048,d6049],[d6048,d6050],[d6050,d6051],[d6050,d6052],[d6052,d6053],[d6052,d6054],[d6054,d6055],[d6054,d6056],[d6056,d6057],[d6056,d6058],[d6058,d6059],[d6058,d6060],[d6060,d6061],[d6060,d6062],[d6062,d6063],[d6062,d6064],[d6064,d6065],[d6064,d6066],[d6066,d6067],[d6066,d6068],[d6068,d6069],[d6068,d6070],[d6070,d6071],[d6070,d6072],[d6072,d6073],[d6072,d6074],[d6074,d6075],[d6074,d6076],[d6076,d6077],[d6076,d6078],[d6078,d6079],[d6078,d6080],[d6080,d6081],[d6080,d6082],[d6082,d6083],[d6082,d6084],[d6084,d6085],[d6084,d6086],[d6086,d6087],[d6086,d6088],[d6088,d6089],[d6088,d6090],[d6090,d6091],[d6090,d6092],[d6092,d6093],[d6092,d6094],[d6094,d6095],[d6094,d6096],[d6096,d6097],[d6096,d6098],[d6098,d6099],[d6098,d6100],[d6100,d6101],[d6100,d6102],[d6102,d6103],[d6102,d6104],[d6104,d6105],[d6104,d6106],[d6106,d6107],[d6106,d6108],[d6108,d6109],[d6108,d6110],[d6110,d6111],[d6110,d6112],[d6112,d6113],[d6112,d6114],[d6114,d6115],[d6114,d6116],[d6116,d6117],[d6116,d6118],[d6118,d6119],[d6118,d6120],[d6120,d6121],[d6120,d6122],[d6122,d6123],[d6122,d6124],[d6124,d6125],[d6124,d6126],[d6126,d6127],[d6126,d6128],[d6128,d6129],[d6128,d6130],[d6130,d6131],[d6130,d6132],[d6132,d6133],[d6132,d6134],[d6134,d6135],[d6134,d6136],[d6136,d6137],[d6136,d6138],[d6138,d6139],[d6138,d6140],[d6140,d6141],[d6140,d6142],[d6142,d6143],[d6142,d6144],[d6144,d6145],[d6144,d6146],[d6146,d6147],[d6146,d6148],[d6148,d6149],[d6148,d6150],[d6150,d6151],[d6150,d6152],[d6152,d6153],[d6152,d6154],[d6154,d6155],[d6154,d6156],[d6156,d6157],[d6156,d6158],[d6158,d6159],[d6158,d6160],[d6160,d6161],[d6160,d6162],[d6162,d6163],[d6162,d6164],[d6164,d6165],[d6164,d6166],[d6166,d6167],[d6166,d6168],[d6168,d6169],[d6168,d6170],[d6170,d6171],[d6170,d6172],[d6172,d6173],[d6172,d6174],[d6174,d6175],[d6174,d6176],[d6176,d6177],[d6176,d6178],[d6178,d6179],[d6178,d6180],[d6180,d6181],[d6180,d6182],[d6182,d6183],[d6182,d6184],[d6184,d6185],[d6184,d6186],[d6186,d6187],[d6186,d6188],[d6188,d6189],[d6188,d6190],[d6190,d6191],[d6190,d6192],[d6192,d6193],[d6192,d6194],[d6194,d6195],[d6194,d6196],[d6196,d6197],[d6196,d6198],[d6198,d6199],[d6198,d6200],[d6200,d6201],[d6200,d6202],[d6202,d6203],[d6202,d6204],[d6204,d6205],[d6204,d6206],[d6206,d6207],[d6206,d6208],[d6208,d6209],[d6208,d6210],[d6210,d6211],[d6210,d6212],[d6212,d6213],[d6212,d6214],[d6214,d6215],[d6214,d6216],[d6216,d6217],[d6216,d6218],[d6218,d6219],[d6218,d6220],[d6220,d6221],[d6220,d6222],[d6222,d6223],[d6222,d6224],[d6224,d6225],[d6224,d6226],[d6226,d6227],[d6226,d6228],[d6228,d6229],[d6228,d6230],[d6230,d6231],[d6230,d6232],[d6232,d6233],[d6232,d6234],[d6234,d6235],[d6234,d6236],[d6236,d6237],[d6236,d6238],[d6238,d6239],[d6238,d6240],[d6240,d6241],[d6240,d6242],[d6242,d6243],[d6242,d6244],[d6244,d6245],[d6244,d6246],[d6246,d6247],[d6246,d6248],[d6248,d6249],[d6248,d6250],[d6250,d6251],[d6250,d6252],[d6252,d6253],[d6252,d6254],[d6254,d6255],[d6254,d6256],[d6256,d6257],[d6256,d6258],[d6258,d6259],[d6258,d6260],[d6260,d6261],[d6260,d6262],[d6262,d6263],[d6262,d6264],[d6264,d6265],[d6264,d6266],[d6266,d6267],[d6266,d6268],[d6268,d6269],[d6268,d6270],[d6270,d6271],[d6270,d6272],[d6272,d6273],[d6272,d6274],[d6274,d6275],[d6274,d6276],[d6276,d6277],[d6276,d6278],[d6278,d6279],[d6278,d6280],[d6280,d6281],[d6280,d6282],[d6282,d6283],[d6282,d6284],[d6284,d6285],[d6284,d6286],[d6286,d6287],[d6286,d6288],[d6288,d6289],[d6288,d6290],[d6290,d6291],[d6290,d6292],[d6292,d6293],[d6292,d6294],[d6294,d6295],[d6294,d6296],[d6296,d6297],[d6296,d6298],[d6298,d6299],[d6298,d6300],[d6300,d6301],[d6300,d6302],[d6302,d6303],[d6302,d6304],[d6304,d6305],[d6304,d6306],[d6306,d6307],[d6306,d6308],[d6308,d6309],[d6308,d6310],[d6310,d6311],[d6310,d6312],[d6312,d6313],[d6312,d6314],[d6314,d6315],[d6314,d6316],[d6316,d6317],[d6316,d6318],[d6318,d6319],[d6318,d6320],[d6320,d6321],[d6320,d6322],[d6322,d6323],[d6322,d6324],[d6324,d6325],[d6324,d6326],[d6326,d6327],[d6326,d6328],[d6328,d6329],[d6328,d6330],[d6330,d6331],[d6330,d6332],[d6332,d6333],[d6332,d6334],[d6334,d6335],[d6334,d6336],[d6336,d6337],[d6336,d6338],[d6338,d6339],[d6338,d6340],[d6340,d6341],[d6340,d6342],[d6342,d6343],[d6342,d6344],[d6344,d6345],[d6344,d6346],[d6346,d6347],[d6346,d6348],[d6348,d6349],[d6348,d6350],[d6350,d6351],[d6350,d6352],[d6352,d6353],[d6352,d6354],[d6354,d6355],[d6354,d6356],[d6356,d6357],[d6356,d6358],[d6358,d6359],[d6358,d6360],[d6360,d6361],[d6360,d6362],[d6362,d6363],[d6362,d6364],[d6364,d6365],[d6364,d6366],[d6366,d6367],[d6366,d6368],[d6368,d6369],[d6368,d6370],[d6370,d6371],[d6370,d6372],[d6372,d6373],[d6372,d6374],[d6374,d6375],[d6374,d6376],[d6376,d6377],[d6376,d6378],[d6378,d6379],[d6378,d6380],[d6380,d6381],[d6380,d6382],[d6382,d6383],[d6382,d6384],[d6384,d6385],[d6384,d6386],[d6386,d6387],[d6386,d6388],[d6388,d6389],[d6388,d6390],[d6390,d6391],[d6390,d6392],[d6392,d6393],[d6392,d6394],[d6394,d6395],[d6394,d6396],[d6396,d6397],[d6396,d6398],[d6398,d6399],[d6398,d6400],[d6400,d6401],[d6400,d6402],[d6402,d6403],[d6402,d6404],[d6404,d6405],[d6404,d6406],[d6406,d6407],[d6406,d6408],[d6408,d6409],[d6408,d6410],[d6410,d6411],[d6410,d6412],[d6412,d6413],[d6412,d6414],[d6414,d6415],[d6414,d6416],[d6416,d6417],[d6416,d6418],[d6418,d6419],[d6418,d6420],[d6420,d6421],[d6420,d6422],[d6422,d6423],[d6422,d6424],[d6424,d6425],[d6424,d6426],[d6426,d6427],[d6426,d6428],[d6428,d6429],[d6428,d6430],[d6430,d6431],[d6430,d6432],[d6432,d6433],[d6432,d6434],[d6434,d6435],[d6434,d6436],[d6436,d6437],[d6436,d6438],[d6438,d6439],[d6438,d6440],[d6440,d6441],[d6440,d6442],[d6442,d6443],[d6442,d6444],[d6444,d6445],[d6444,d6446],[d6446,d6447],[d6446,d6448],[d6448,d6449],[d6448,d6450],[d6450,d6451],[d6450,d6452],[d6452,d6453],[d6452,d6454],[d6454,d6455],[d6454,d6456],[d6456,d6457],[d6456,d6458],[d6458,d6459],[d6458,d6460],[d6460,d6461],[d6460,d6462],[d6462,d6463],[d6462,d6464],[d6464,d6465],[d6464,d6466],[d6466,d6467],[d6466,d6468],[d6468,d6469],[d6468,d6470],[d6470,d6471],[d6470,d6472],[d6472,d6473],[d6472,d6474],[d6474,d6475],[d6474,d6476],[d6476,d6477],[d6476,d6478],[d6478,d6479],[d6478,d6480],[d6480,d6481],[d6480,d6482],[d6482,d6483],[d6482,d6484],[d6484,d6485],[d6484,d6486],[d6486,d6487],[d6486,d6488],[d6488,d6489],[d6488,d6490],[d6490,d6491],[d6490,d6492],[d6492,d6493],[d6492,d6494],[d6494,d6495],[d6494,d6496],[d6496,d6497],[d6496,d6498],[d6498,d6499],[d6498,d6500],[d6500,d6501],[d6500,d6502],[d6502,d6503],[d6502,d6504],[d6504,d6505],[d6504,d6506],[d6506,d6507],[d6506,d6508],[d6508,d6509],[d6508,d6510],[d6510,d6511],[d6510,d6512],[d6512,d6513],[d6512,d6514],[d6514,d6515],[d6514,d6516],[d6516,d6517],[d6516,d6518],[d6518,d6519],[d6518,d6520],[d6520,d6521],[d6520,d6522],[d6522,d6523],[d6522,d6524],[d6524,d6525],[d6524,d6526],[d6526,d6527],[d6526,d6528],[d6528,d6529],[d6528,d6530],[d6530,d6531],[d6530,d6532],[d6532,d6533],[d6532,d6534],[d6534,d6535],[d6534,d6536],[d6536,d6537],[d6536,d6538],[d6538,d6539],[d6538,d6540],[d6540,d6541],[d6540,d6542],[d6542,d6543],[d6542,d6544],[d6544,d6545],[d6544,d6546],[d6546,d6547],[d6546,d6548],[d6548,d6549],[d6548,d6550],[d6550,d6551],[d6550,d6552],[d6552,d6553],[d6552,d6554],[d6554,d6555],[d6554,d6556],[d6556,d6557],[d6556,d6558],[d6558,d6559],[d6558,d6560],[d6560,d6561],[d6560,d6562],[d6562,d6563],[d6562,d6564],[d6564,d6565],[d6564,d6566],[d6566,d6567],[d6566,d6568],[d6568,d6569],[d6568,d6570],[d6570,d6571],[d6570,d6572],[d6572,d6573],[d6572,d6574],[d6574,d6575],[d6574,d6576],[d6576,d6577],[d6576,d6578],[d6578,d6579],[d6578,d6580],[d6580,d6581],[d6580,d6582],[d6582,d6583],[d6582,d6584],[d6584,d6585],[d6584,d6586],[d6586,d6587],[d6586,d6588],[d6588,d6589],[d6588,d6590],[d6590,d6591],[d6590,d6592],[d6592,d6593],[d6592,d6594],[d6594,d6595],[d6594,d6596],[d6596,d6597],[d6596,d6598],[d6598,d6599],[d6598,d6600],[d6600,d6601],[d6600,d6602],[d6602,d6603],[d6602,d6604],[d6604,d6605],[d6604,d6606],[d6606,d6607],[d6606,d6608],[d6608,d6609],[d6608,d6610],[d6610,d6611],[d6610,d6612],[d6612,d6613],[d6612,d6614],[d6614,d6615],[d6614,d6616],[d6616,d6617],[d6616,d6618],[d6618,d6619],[d6618,d6620],[d6620,d6621],[d6620,d6622],[d6622,d6623],[d6622,d6624],[d6624,d6625],[d6624,d6626],[d6626,d6627],[d6626,d6628],[d6628,d6629],[d6628,d6630],[d6630,d6631],[d6630,d6632],[d6632,d6633],[d6632,d6634],[d6634,d6635],[d6634,d6636],[d6636,d6637],[d6636,d6638],[d6638,d6639],[d6638,d6640],[d6640,d6641],[d6640,d6642],[d6642,d6643],[d6642,d6644],[d6644,d6645],[d6644,d6646],[d6646,d6647],[d6646,d6648],[d6648,d6649],[d6648,d6650],[d6650,d6651],[d6650,d6652],[d6652,d6653],[d6652,d6654],[d6654,d6655],[d6654,d6656],[d6656,d6657],[d6656,d6658],[d6658,d6659],[d6658,d6660],[d6660,d6661],[d6660,d6662],[d6662,d6663],[d6662,d6664],[d6664,d6665],[d6664,d6666],[d6666,d6667],[d6666,d6668],[d6668,d6669],[d6668,d6670],[d6670,d6671],[d6670,d6672],[d6672,d6673],[d6672,d6674],[d6674,d6675],[d6674,d6676],[d6676,d6677],[d6676,d6678],[d6678,d6679],[d6678,d6680],[d6680,d6681],[d6680,d6682],[d6682,d6683],[d6682,d6684],[d6684,d6685],[d6684,d6686],[d6686,d6687],[d6686,d6688],[d6688,d6689],[d6688,d6690],[d6690,d6691],[d6690,d6692],[d6692,d6693],[d6692,d6694],[d6694,d6695],[d6694,d6696],[d6696,d6697],[d6696,d6698],[d6698,d6699],[d6698,d6700],[d6700,d6701],[d6700,d6702],[d6702,d6703],[d6702,d6704],[d6704,d6705],[d6704,d6706],[d6706,d6707],[d6706,d6708],[d6708,d6709],[d6708,d6710],[d6710,d6711],[d6710,d6712],[d6712,d6713],[d6712,d6714],[d6714,d6715],[d6714,d6716],[d6716,d6717],[d6716,d6718],[d6718,d6719],[d6718,d6720],[d6720,d6721],[d6720,d6722],[d6722,d6723],[d6722,d6724],[d6724,d6725],[d6724,d6726],[d6726,d6727],[d6726,d6728],[d6728,d6729],[d6728,d6730],[d6730,d6731],[d6730,d6732],[d6732,d6733],[d6732,d6734],[d6734,d6735],[d6734,d6736],[d6736,d6737],[d6736,d6738],[d6738,d6739],[d6738,d6740],[d6740,d6741],[d6740,d6742],[d6742,d6743],[d6742,d6744],[d6744,d6745],[d6744,d6746],[d6746,d6747],[d6746,d6748],[d6748,d6749],[d6748,d6750],[d6750,d6751],[d6750,d6752],[d6752,d6753],[d6752,d6754],[d6754,d6755],[d6754,d6756],[d6756,d6757],[d6756,d6758],[d6758,d6759],[d6758,d6760],[d6760,d6761],[d6760,d6762],[d6762,d6763],[d6762,d6764],[d6764,d6765],[d6764,d6766],[d6766,d6767],[d6766,d6768],[d6768,d6769],[d6768,d6770],[d6770,d6771],[d6770,d6772],[d6772,d6773],[d6772,d6774],[d6774,d6775],[d6774,d6776],[d6776,d6777],[d6776,d6778],[d6778,d6779],[d6778,d6780],[d6780,d6781],[d6780,d6782],[d6782,d6783],[d6782,d6784],[d6784,d6785],[d6784,d6786],[d6786,d6787],[d6786,d6788],[d6788,d6789],[d6788,d6790],[d6790,d6791],[d6790,d6792],[d6792,d6793],[d6792,d6794],[d6794,d6795],[d6794,d6796],[d6796,d6797],[d6796,d6798],[d6798,d6799],[d6798,d6800],[d6800,d6801],[d6800,d6802],[d6802,d6803],[d6802,d6804],[d6804,d6805],[d6804,d6806],[d6806,d6807],[d6806,d6808],[d6808,d6809],[d6808,d6810],[d6810,d6811],[d6810,d6812],[d6812,d6813],[d6812,d6814],[d6814,d6815],[d6814,d6816],[d6816,d6817],[d6816,d6818],[d6818,d6819],[d6818,d6820],[d6820,d6821],[d6820,d6822],[d6822,d6823],[d6822,d6824],[d6824,d6825],[d6824,d6826],[d6826,d6827],[d6826,d6828],[d6828,d6829],[d6828,d6830],[d6830,d6831],[d6830,d6832],[d6832,d6833],[d6832,d6834],[d6834,d6835],[d6834,d6836],[d6836,d6837],[d6836,d6838],[d6838,d6839],[d6838,d6840],[d6840,d6841],[d6840,d6842],[d6842,d6843],[d6842,d6844],[d6844,d6845],[d6844,d6846],[d6846,d6847],[d6846,d6848],[d6848,d6849],[d6848,d6850],[d6850,d6851],[d6850,d6852],[d6852,d6853],[d6852,d6854],[d6854,d6855],[d6854,d6856],[d6856,d6857],[d6856,d6858],[d6858,d6859],[d6858,d6860],[d6860,d6861],[d6860,d6862],[d6862,d6863],[d6862,d6864],[d6864,d6865],[d6864,d6866],[d6866,d6867],[d6866,d6868],[d6868,d6869],[d6868,d6870],[d6870,d6871],[d6870,d6872],[d6872,d6873],[d6872,d6874],[d6874,d6875],[d6874,d6876],[d6876,d6877],[d6876,d6878],[d6878,d6879],[d6878,d6880],[d6880,d6881],[d6880,d6882],[d6882,d6883],[d6882,d6884],[d6884,d6885],[d6884,d6886],[d6886,d6887],[d6886,d6888],[d6888,d6889],[d6888,d6890],[d6890,d6891],[d6890,d6892],[d6892,d6893],[d6892,d6894],[d6894,d6895],[d6894,d6896],[d6896,d6897],[d6896,d6898],[d6898,d6899],[d6898,d6900],[d6900,d6901],[d6900,d6902],[d6902,d6903],[d6902,d6904],[d6904,d6905],[d6904,d6906],[d6906,d6907],[d6906,d6908],[d6908,d6909],[d6908,d6910],[d6910,d6911],[d6910,d6912],[d6912,d6913],[d6912,d6914],[d6914,d6915],[d6914,d6916],[d6916,d6917],[d6916,d6918],[d6918,d6919],[d6918,d6920],[d6920,d6921],[d6920,d6922],[d6922,d6923],[d6922,d6924],[d6924,d6925],[d6924,d6926],[d6926,d6927],[d6926,d6928],[d6928,d6929],[d6928,d6930],[d6930,d6931],[d6930,d6932],[d6932,d6933],[d6932,d6934],[d6934,d6935],[d6934,d6936],[d6936,d6937],[d6936,d6938],[d6938,d6939],[d6938,d6940],[d6940,d6941],[d6940,d6942],[d6942,d6943],[d6942,d6944],[d6944,d6945],[d6944,d6946],[d6946,d6947],[d6946,d6948],[d6948,d6949],[d6948,d6950],[d6950,d6951],[d6950,d6952],[d6952,d6953],[d6952,d6954],[d6954,d6955],[d6954,d6956],[d6956,d6957],[d6956,d6958],[d6958,d6959],[d6958,d6960],[d6960,d6961],[d6960,d6962],[d6962,d6963],[d6962,d6964],[d6964,d6965],[d6964,d6966],[d6966,d6967],[d6966,d6968],[d6968,d6969],[d6968,d6970],[d6970,d6971],[d6970,d6972],[d6972,d6973],[d6972,d6974],[d6974,d6975],[d6974,d6976],[d6976,d6977],[d6976,d6978],[d6978,d6979],[d6978,d6980],[d6980,d6981],[d6980,d6982],[d6982,d6983],[d6982,d6984],[d6984,d6985],[d6984,d6986],[d6986,d6987],[d6986,d6988],[d6988,d6989],[d6988,d6990],[d6990,d6991],[d6990,d6992],[d6992,d6993],[d6992,d6994],[d6994,d6995],[d6994,d6996],[d6996,d6997],[d6996,d6998],[d6998,d6999],[d6998,d7000],[d7000,d7001],[d7000,d7002],[d7002,d7003],[d7002,d7004],[d7004,d7005],[d7004,d7006],[d7006,d7007],[d7006,d7008],[d7008,d7009],[d7008,d7010],[d7010,d7011],[d7010,d7012],[d7012,d7013],[d7012,d7014],[d7014,d7015],[d7014,d7016],[d7016,d7017],[d7016,d7018],[d7018,d7019],[d7018,d7020],[d7020,d7021],[d7020,d7022],[d7022,d7023],[d7022,d7024],[d7024,d7025],[d7024,d7026],[d7026,d7027],[d7026,d7028],[d7028,d7029],[d7028,d7030],[d7030,d7031],[d7030,d7032],[d7032,d7033],[d7032,d7034],[d7034,d7035],[d7034,d7036],[d7036,d7037],[d7036,d7038],[d7038,d7039],[d7038,d7040],[d7040,d7041],[d7040,d7042],[d7042,d7043],[d7042,d7044],[d7044,d7045],[d7044,d7046],[d7046,d7047],[d7046,d7048],[d7048,d7049],[d7048,d7050],[d7050,d7051],[d7050,d7052],[d7052,d7053],[d7052,d7054],[d7054,d7055],[d7054,d7056],[d7056,d7057],[d7056,d7058],[d7058,d7059],[d7058,d7060],[d7060,d7061],[d7060,d7062],[d7062,d7063],[d7062,d7064],[d7064,d7065],[d7064,d7066],[d7066,d7067],[d7066,d7068],[d7068,d7069],[d7068,d7070],[d7070,d7071],[d7070,d7072],[d7072,d7073],[d7072,d7074],[d7074,d7075],[d7074,d7076],[d7076,d7077],[d7076,d7078],[d7078,d7079],[d7078,d7080],[d7080,d7081],[d7080,d7082],[d7082,d7083],[d7082,d7084],[d7084,d7085],[d7084,d7086],[d7086,d7087],[d7086,d7088],[d7088,d7089],[d7088,d7090],[d7090,d7091],[d7090,d7092],[d7092,d7093],[d7092,d7094],[d7094,d7095],[d7094,d7096],[d7096,d7097],[d7096,d7098],[d7098,d7099],[d7098,d7100],[d7100,d7101],[d7100,d7102],[d7102,d7103],[d7102,d7104],[d7104,d7105],[d7104,d7106],[d7106,d7107],[d7106,d7108],[d7108,d7109],[d7108,d7110],[d7110,d7111],[d7110,d7112],[d7112,d7113],[d7112,d7114],[d7114,d7115],[d7114,d7116],[d7116,d7117],[d7116,d7118],[d7118,d7119],[d7118,d7120],[d7120,d7121],[d7120,d7122],[d7122,d7123],[d7122,d7124],[d7124,d7125],[d7124,d7126],[d7126,d7127],[d7126,d7128],[d7128,d7129],[d7128,d7130],[d7130,d7131],[d7130,d7132],[d7132,d7133],[d7132,d7134],[d7134,d7135],[d7134,d7136],[d7136,d7137],[d7136,d7138],[d7138,d7139],[d7138,d7140],[d7140,d7141],[d7140,d7142],[d7142,d7143],[d7142,d7144],[d7144,d7145],[d7144,d7146],[d7146,d7147],[d7146,d7148],[d7148,d7149],[d7148,d7150],[d7150,d7151],[d7150,d7152],[d7152,d7153],[d7152,d7154],[d7154,d7155],[d7154,d7156],[d7156,d7157],[d7156,d7158],[d7158,d7159],[d7158,d7160],[d7160,d7161],[d7160,d7162],[d7162,d7163],[d7162,d7164],[d7164,d7165],[d7164,d7166],[d7166,d7167],[d7166,d7168],[d7168,d7169],[d7168,d7170],[d7170,d7171],[d7170,d7172],[d7172,d7173],[d7172,d7174],[d7174,d7175],[d7174,d7176],[d7176,d7177],[d7176,d7178],[d7178,d7179],[d7178,d7180],[d7180,d7181],[d7180,d7182],[d7182,d7183],[d7182,d7184],[d7184,d7185],[d7184,d7186],[d7186,d7187],[d7186,d7188],[d7188,d7189],[d7188,d7190],[d7190,d7191],[d7190,d7192],[d7192,d7193],[d7192,d7194],[d7194,d7195],[d7194,d7196],[d7196,d7197],[d7196,d7198],[d7198,d7199],[d7198,d7200],[d7200,d7201],[d7200,d7202],[d7202,d7203],[d7202,d7204],[d7204,d7205],[d7204,d7206],[d7206,d7207],[d7206,d7208],[d7208,d7209],[d7208,d7210],[d7210,d7211],[d7210,d7212],[d7212,d7213],[d7212,d7214],[d7214,d7215],[d7214,d7216],[d7216,d7217],[d7216,d7218],[d7218,d7219],[d7218,d7220],[d7220,d7221],[d7220,d7222],[d7222,d7223],[d7222,d7224],[d7224,d7225],[d7224,d7226],[d7226,d7227],[d7226,d7228],[d7228,d7229],[d7228,d7230],[d7230,d7231],[d7230,d7232],[d7232,d7233],[d7232,d7234],[d7234,d7235],[d7234,d7236],[d7236,d7237],[d7236,d7238],[d7238,d7239],[d7238,d7240],[d7240,d7241],[d7240,d7242],[d7242,d7243],[d7242,d7244],[d7244,d7245],[d7244,d7246],[d7246,d7247],[d7246,d7248],[d7248,d7249],[d7248,d7250],[d7250,d7251],[d7250,d7252],[d7252,d7253],[d7252,d7254],[d7254,d7255],[d7254,d7256],[d7256,d7257],[d7256,d7258],[d7258,d7259],[d7258,d7260],[d7260,d7261],[d7260,d7262],[d7262,d7263],[d7262,d7264],[d7264,d7265],[d7264,d7266],[d7266,d7267],[d7266,d7268],[d7268,d7269],[d7268,d7270],[d7270,d7271],[d7270,d7272],[d7272,d7273],[d7272,d7274],[d7274,d7275],[d7274,d7276],[d7276,d7277],[d7276,d7278],[d7278,d7279],[d7278,d7280],[d7280,d7281],[d7280,d7282],[d7282,d7283],[d7282,d7284],[d7284,d7285],[d7284,d7286],[d7286,d7287],[d7286,d7288],[d7288,d7289],[d7288,d7290],[d7290,d7291],[d7290,d7292],[d7292,d7293],[d7292,d7294],[d7294,d7295],[d7294,d7296],[d7296,d7297],[d7296,d7298],[d7298,d7299],[d7298,d7300],[d7300,d7301],[d7300,d7302],[d7302,d7303],[d7302,d7304],[d7304,d7305],[d7304,d7306],[d7306,d7307],[d7306,d7308],[d7308,d7309],[d7308,d7310],[d7310,d7311],[d7310,d7312],[d7312,d7313],[d7312,d7314],[d7314,d7315],[d7314,d7316],[d7316,d7317],[d7316,d7318],[d7318,d7319],[d7318,d7320],[d7320,d7321],[d7320,d7322],[d7322,d7323],[d7322,d7324],[d7324,d7325],[d7324,d7326],[d7326,d7327],[d7326,d7328],[d7328,d7329],[d7328,d7330],[d7330,d7331],[d7330,d7332],[d7332,d7333],[d7332,d7334],[d7334,d7335],[d7334,d7336],[d7336,d7337],[d7336,d7338],[d7338,d7339],[d7338,d7340],[d7340,d7341],[d7340,d7342],[d7342,d7343],[d7342,d7344],[d7344,d7345],[d7344,d7346],[d7346,d7347],[d7346,d7348],[d7348,d7349],[d7348,d7350],[d7350,d7351],[d7350,d7352],[d7352,d7353],[d7352,d7354],[d7354,d7355],[d7354,d7356],[d7356,d7357],[d7356,d7358],[d7358,d7359],[d7358,d7360],[d7360,d7361],[d7360,d7362],[d7362,d7363],[d7362,d7364],[d7364,d7365],[d7364,d7366],[d7366,d7367],[d7366,d7368],[d7368,d7369],[d7368,d7370],[d7370,d7371],[d7370,d7372],[d7372,d7373],[d7372,d7374],[d7374,d7375],[d7374,d7376],[d7376,d7377],[d7376,d7378],[d7378,d7379],[d7378,d7380],[d7380,d7381],[d7380,d7382],[d7382,d7383],[d7382,d7384],[d7384,d7385],[d7384,d7386],[d7386,d7387],[d7386,d7388],[d7388,d7389],[d7388,d7390],[d7390,d7391],[d7390,d7392],[d7392,d7393],[d7392,d7394],[d7394,d7395],[d7394,d7396],[d7396,d7397],[d7396,d7398],[d7398,d7399],[d7398,d7400],[d7400,d7401],[d7400,d7402],[d7402,d7403],[d7402,d7404],[d7404,d7405],[d7404,d7406],[d7406,d7407],[d7406,d7408],[d7408,d7409],[d7408,d7410],[d7410,d7411],[d7410,d7412],[d7412,d7413],[d7412,d7414],[d7414,d7415],[d7414,d7416],[d7416,d7417],[d7416,d7418],[d7418,d7419],[d7418,d7420],[d7420,d7421],[d7420,d7422],[d7422,d7423],[d7422,d7424],[d7424,d7425],[d7424,d7426],[d7426,d7427],[d7426,d7428],[d7428,d7429],[d7428,d7430],[d7430,d7431],[d7430,d7432],[d7432,d7433],[d7432,d7434],[d7434,d7435],[d7434,d7436],[d7436,d7437],[d7436,d7438],[d7438,d7439],[d7438,d7440],[d7440,d7441],[d7440,d7442],[d7442,d7443],[d7442,d7444],[d7444,d7445],[d7444,d7446],[d7446,d7447],[d7446,d7448],[d7448,d7449],[d7448,d7450],[d7450,d7451],[d7450,d7452],[d7452,d7453],[d7452,d7454],[d7454,d7455],[d7454,d7456],[d7456,d7457],[d7456,d7458],[d7458,d7459],[d7458,d7460],[d7460,d7461],[d7460,d7462],[d7462,d7463],[d7462,d7464],[d7464,d7465],[d7464,d7466],[d7466,d7467],[d7466,d7468],[d7468,d7469],[d7468,d7470],[d7470,d7471],[d7470,d7472],[d7472,d7473],[d7472,d7474],[d7474,d7475],[d7474,d7476],[d7476,d7477],[d7476,d7478],[d7478,d7479],[d7478,d7480],[d7480,d7481],[d7480,d7482],[d7482,d7483],[d7482,d7484],[d7484,d7485],[d7484,d7486],[d7486,d7487],[d7486,d7488],[d7488,d7489],[d7488,d7490],[d7490,d7491],[d7490,d7492],[d7492,d7493],[d7492,d7494],[d7494,d7495],[d7494,d7496],[d7496,d7497],[d7496,d7498],[d7498,d7499],[d7498,d7500],[d7500,d7501],[d7500,d7502],[d7502,d7503],[d7502,d7504],[d7504,d7505],[d7504,d7506],[d7506,d7507],[d7506,d7508],[d7508,d7509],[d7508,d7510],[d7510,d7511],[d7510,d7512],[d7512,d7513],[d7512,d7514],[d7514,d7515],[d7514,d7516],[d7516,d7517],[d7516,d7518],[d7518,d7519],[d7518,d7520],[d7520,d7521],[d7520,d7522],[d7522,d7523],[d7522,d7524],[d7524,d7525],[d7524,d7526],[d7526,d7527],[d7526,d7528],[d7528,d7529],[d7528,d7530],[d7530,d7531],[d7530,d7532],[d7532,d7533],[d7532,d7534],[d7534,d7535],[d7534,d7536],[d7536,d7537],[d7536,d7538],[d7538,d7539],[d7538,d7540],[d7540,d7541],[d7540,d7542],[d7542,d7543],[d7542,d7544],[d7544,d7545],[d7544,d7546],[d7546,d7547],[d7546,d7548],[d7548,d7549],[d7548,d7550],[d7550,d7551],[d7550,d7552],[d7552,d7553],[d7552,d7554],[d7554,d7555],[d7554,d7556],[d7556,d7557],[d7556,d7558],[d7558,d7559],[d7558,d7560],[d7560,d7561],[d7560,d7562],[d7562,d7563],[d7562,d7564],[d7564,d7565],[d7564,d7566],[d7566,d7567],[d7566,d7568],[d7568,d7569],[d7568,d7570],[d7570,d7571],[d7570,d7572],[d7572,d7573],[d7572,d7574],[d7574,d7575],[d7574,d7576],[d7576,d7577],[d7576,d7578],[d7578,d7579],[d7578,d7580],[d7580,d7581],[d7580,d7582],[d7582,d7583],[d7582,d7584],[d7584,d7585],[d7584,d7586],[d7586,d7587],[d7586,d7588],[d7588,d7589],[d7588,d7590],[d7590,d7591],[d7590,d7592],[d7592,d7593],[d7592,d7594],[d7594,d7595],[d7594,d7596],[d7596,d7597],[d7596,d7598],[d7598,d7599],[d7598,d7600],[d7600,d7601],[d7600,d7602],[d7602,d7603],[d7602,d7604],[d7604,d7605],[d7604,d7606],[d7606,d7607],[d7606,d7608],[d7608,d7609],[d7608,d7610],[d7610,d7611],[d7610,d7612],[d7612,d7613],[d7612,d7614],[d7614,d7615],[d7614,d7616],[d7616,d7617],[d7616,d7618],[d7618,d7619],[d7618,d7620],[d7620,d7621],[d7620,d7622],[d7622,d7623],[d7622,d7624],[d7624,d7625],[d7624,d7626],[d7626,d7627],[d7626,d7628],[d7628,d7629],[d7628,d7630],[d7630,d7631],[d7630,d7632],[d7632,d7633],[d7632,d7634],[d7634,d7635],[d7634,d7636],[d7636,d7637],[d7636,d7638],[d7638,d7639],[d7638,d7640],[d7640,d7641],[d7640,d7642],[d7642,d7643],[d7642,d7644],[d7644,d7645],[d7644,d7646],[d7646,d7647],[d7646,d7648],[d7648,d7649],[d7648,d7650],[d7650,d7651],[d7650,d7652],[d7652,d7653],[d7652,d7654],[d7654,d7655],[d7654,d7656],[d7656,d7657],[d7656,d7658],[d7658,d7659],[d7658,d7660],[d7660,d7661],[d7660,d7662],[d7662,d7663],[d7662,d7664],[d7664,d7665],[d7664,d7666],[d7666,d7667],[d7666,d7668],[d7668,d7669],[d7668,d7670],[d7670,d7671],[d7670,d7672],[d7672,d7673],[d7672,d7674],[d7674,d7675],[d7674,d7676],[d7676,d7677],[d7676,d7678],[d7678,d7679],[d7678,d7680],[d7680,d7681],[d7680,d7682],[d7682,d7683],[d7682,d7684],[d7684,d7685],[d7684,d7686],[d7686,d7687],[d7686,d7688],[d7688,d7689],[d7688,d7690],[d7690,d7691],[d7690,d7692],[d7692,d7693],[d7692,d7694],[d7694,d7695],[d7694,d7696],[d7696,d7697],[d7696,d7698],[d7698,d7699],[d7698,d7700],[d7700,d7701],[d7700,d7702],[d7702,d7703],[d7702,d7704],[d7704,d7705],[d7704,d7706],[d7706,d7707],[d7706,d7708],[d7708,d7709],[d7708,d7710],[d7710,d7711],[d7710,d7712],[d7712,d7713],[d7712,d7714],[d7714,d7715],[d7714,d7716],[d7716,d7717],[d7716,d7718],[d7718,d7719],[d7718,d7720],[d7720,d7721],[d7720,d7722],[d7722,d7723],[d7722,d7724],[d7724,d7725],[d7724,d7726],[d7726,d7727],[d7726,d7728],[d7728,d7729],[d7728,d7730],[d7730,d7731],[d7730,d7732],[d7732,d7733],[d7732,d7734],[d7734,d7735],[d7734,d7736],[d7736,d7737],[d7736,d7738],[d7738,d7739],[d7738,d7740],[d7740,d7741],[d7740,d7742],[d7742,d7743],[d7742,d7744],[d7744,d7745],[d7744,d7746],[d7746,d7747],[d7746,d7748],[d7748,d7749],[d7748,d7750],[d7750,d7751],[d7750,d7752],[d7752,d7753],[d7752,d7754],[d7754,d7755],[d7754,d7756],[d7756,d7757],[d7756,d7758],[d7758,d7759],[d7758,d7760],[d7760,d7761],[d7760,d7762],[d7762,d7763],[d7762,d7764],[d7764,d7765],[d7764,d7766],[d7766,d7767],[d7766,d7768],[d7768,d7769],[d7768,d7770],[d7770,d7771],[d7770,d7772],[d7772,d7773],[d7772,d7774],[d7774,d7775],[d7774,d7776],[d7776,d7777],[d7776,d7778],[d7778,d7779],[d7778,d7780],[d7780,d7781],[d7780,d7782],[d7782,d7783],[d7782,d7784],[d7784,d7785],[d7784,d7786],[d7786,d7787],[d7786,d7788],[d7788,d7789],[d7788,d7790],[d7790,d7791],[d7790,d7792],[d7792,d7793],[d7792,d7794],[d7794,d7795],[d7794,d7796],[d7796,d7797],[d7796,d7798],[d7798,d7799],[d7798,d7800],[d7800,d7801],[d7800,d7802],[d7802,d7803],[d7802,d7804],[d7804,d7805],[d7804,d7806],[d7806,d7807],[d7806,d7808],[d7808,d7809],[d7808,d7810],[d7810,d7811],[d7810,d7812],[d7812,d7813],[d7812,d7814],[d7814,d7815],[d7814,d7816],[d7816,d7817],[d7816,d7818],[d7818,d7819],[d7818,d7820],[d7820,d7821],[d7820,d7822],[d7822,d7823],[d7822,d7824],[d7824,d7825],[d7824,d7826],[d7826,d7827],[d7826,d7828],[d7828,d7829],[d7828,d7830],[d7830,d7831],[d7830,d7832],[d7832,d7833],[d7832,d7834],[d7834,d7835],[d7834,d7836],[d7836,d7837],[d7836,d7838],[d7838,d7839],[d7838,d7840],[d7840,d7841],[d7840,d7842],[d7842,d7843],[d7842,d7844],[d7844,d7845],[d7844,d7846],[d7846,d7847],[d7846,d7848],[d7848,d7849],[d7848,d7850],[d7850,d7851],[d7850,d7852],[d7852,d7853],[d7852,d7854],[d7854,d7855],[d7854,d7856],[d7856,d7857],[d7856,d7858],[d7858,d7859],[d7858,d7860],[d7860,d7861],[d7860,d7862],[d7862,d7863],[d7862,d7864],[d7864,d7865],[d7864,d7866],[d7866,d7867],[d7866,d7868],[d7868,d7869],[d7868,d7870],[d7870,d7871],[d7870,d7872],[d7872,d7873],[d7872,d7874],[d7874,d7875],[d7874,d7876],[d7876,d7877],[d7876,d7878],[d7878,d7879],[d7878,d7880],[d7880,d7881],[d7880,d7882],[d7882,d7883],[d7882,d7884],[d7884,d7885],[d7884,d7886],[d7886,d7887],[d7886,d7888],[d7888,d7889],[d7888,d7890],[d7890,d7891],[d7890,d7892],[d7892,d7893],[d7892,d7894],[d7894,d7895],[d7894,d7896],[d7896,d7897],[d7896,d7898],[d7898,d7899],[d7898,d7900],[d7900,d7901],[d7900,d7902],[d7902,d7903],[d7902,d7904],[d7904,d7905],[d7904,d7906],[d7906,d7907],[d7906,d7908],[d7908,d7909],[d7908,d7910],[d7910,d7911],[d7910,d7912],[d7912,d7913],[d7912,d7914],[d7914,d7915],[d7914,d7916],[d7916,d7917],[d7916,d7918],[d7918,d7919],[d7918,d7920],[d7920,d7921],[d7920,d7922],[d7922,d7923],[d7922,d7924],[d7924,d7925],[d7924,d7926],[d7926,d7927],[d7926,d7928],[d7928,d7929],[d7928,d7930],[d7930,d7931],[d7930,d7932],[d7932,d7933],[d7932,d7934],[d7934,d7935],[d7934,d7936],[d7936,d7937],[d7936,d7938],[d7938,d7939],[d7938,d7940],[d7940,d7941],[d7940,d7942],[d7942,d7943],[d7942,d7944],[d7944,d7945],[d7944,d7946],[d7946,d7947],[d7946,d7948],[d7948,d7949],[d7948,d7950],[d7950,d7951],[d7950,d7952],[d7952,d7953],[d7952,d7954],[d7954,d7955],[d7954,d7956],[d7956,d7957],[d7956,d7958],[d7958,d7959],[d7958,d7960],[d7960,d7961],[d7960,d7962],[d7962,d7963],[d7962,d7964],[d7964,d7965],[d7964,d7966],[d7966,d7967],[d7966,d7968],[d7968,d7969],[d7968,d7970],[d7970,d7971],[d7970,d7972],[d7972,d7973],[d7972,d7974],[d7974,d7975],[d7974,d7976],[d7976,d7977],[d7976,d7978],[d7978,d7979],[d7978,d7980],[d7980,d7981],[d7980,d7982],[d7982,d7983],[d7982,d7984],[d7984,d7985],[d7984,d7986],[d7986,d7987],[d7986,d7988],[d7988,d7989],[d7988,d7990],[d7990,d7991],[d7990,d7992],[d7992,d7993],[d7992,d7994],[d7994,d7995],[d7994,d7996],[d7996,d7997],[d7996,d7998],[d7998,d7999],[d7998,d8000],[d8000,d8001],[d8000,d8002],[d8002,d8003],[d8002,d8004],[d8004,d8005],[d8004,d8006],[d8006,d8007],[d8006,d8008],[d8008,d8009],[d8008,d8010],[d8010,d8011],[d8010,d8012],[d8012,d8013],[d8012,d8014],[d8014,d8015],[d8014,d8016],[d8016,d8017],[d8016,d8018],[d8018,d8019],[d8018,d8020],[d8020,d8021],[d8020,d8022],[d8022,d8023],[d8022,d8024],[d8024,d8025],[d8024,d8026],[d8026,d8027],[d8026,d8028],[d8028,d8029],[d8028,d8030],[d8030,d8031],[d8030,d8032],[d8032,d8033],[d8032,d8034],[d8034,d8035],[d8034,d8036],[d8036,d8037],[d8036,d8038],[d8038,d8039],[d8038,d8040],[d8040,d8041],[d8040,d8042],[d8042,d8043],[d8042,d8044],[d8044,d8045],[d8044,d8046],[d8046,d8047],[d8046,d8048],[d8048,d8049],[d8048,d8050],[d8050,d8051],[d8050,d8052],[d8052,d8053],[d8052,d8054],[d8054,d8055],[d8054,d8056],[d8056,d8057],[d8056,d8058],[d8058,d8059],[d8058,d8060],[d8060,d8061],[d8060,d8062],[d8062,d8063],[d8062,d8064],[d8064,d8065],[d8064,d8066],[d8066,d8067],[d8066,d8068],[d8068,d8069],[d8068,d8070],[d8070,d8071],[d8070,d8072],[d8072,d8073],[d8072,d8074],[d8074,d8075],[d8074,d8076],[d8076,d8077],[d8076,d8078],[d8078,d8079],[d8078,d8080],[d8080,d8081],[d8080,d8082],[d8082,d8083],[d8082,d8084],[d8084,d8085],[d8084,d8086],[d8086,d8087],[d8086,d8088],[d8088,d8089],[d8088,d8090],[d8090,d8091],[d8090,d8092],[d8092,d8093],[d8092,d8094],[d8094,d8095],[d8094,d8096],[d8096,d8097],[d8096,d8098],[d8098,d8099],[d8098,d8100],[d8100,d8101],[d8100,d8102],[d8102,d8103],[d8102,d8104],[d8104,d8105],[d8104,d8106],[d8106,d8107],[d8106,d8108],[d8108,d8109],[d8108,d8110],[d8110,d8111],[d8110,d8112],[d8112,d8113],[d8112,d8114],[d8114,d8115],[d8114,d8116],[d8116,d8117],[d8116,d8118],[d8118,d8119],[d8118,d8120],[d8120,d8121],[d8120,d8122],[d8122,d8123],[d8122,d8124],[d8124,d8125],[d8124,d8126],[d8126,d8127],[d8126,d8128],[d8128,d8129],[d8128,d8130],[d8130,d8131],[d8130,d8132],[d8132,d8133],[d8132,d8134],[d8134,d8135],[d8134,d8136],[d8136,d8137],[d8136,d8138],[d8138,d8139],[d8138,d8140],[d8140,d8141],[d8140,d8142],[d8142,d8143],[d8142,d8144],[d8144,d8145],[d8144,d8146],[d8146,d8147],[d8146,d8148],[d8148,d8149],[d8148,d8150],[d8150,d8151],[d8150,d8152],[d8152,d8153],[d8152,d8154],[d8154,d8155],[d8154,d8156],[d8156,d8157],[d8156,d8158],[d8158,d8159],[d8158,d8160],[d8160,d8161],[d8160,d8162],[d8162,d8163],[d8162,d8164],[d8164,d8165],[d8164,d8166],[d8166,d8167],[d8166,d8168],[d8168,d8169],[d8168,d8170],[d8170,d8171],[d8170,d8172],[d8172,d8173],[d8172,d8174],[d8174,d8175],[d8174,d8176],[d8176,d8177],[d8176,d8178],[d8178,d8179],[d8178,d8180],[d8180,d8181],[d8180,d8182],[d8182,d8183],[d8182,d8184],[d8184,d8185],[d8184,d8186],[d8186,d8187],[d8186,d8188],[d8188,d8189],[d8188,d8190],[d8190,d8191],[d8190,d8192],[d8192,d8193],[d8192,d8194],[d8194,d8195],[d8194,d8196],[d8196,d8197],[d8196,d8198],[d8198,d8199],[d8198,d8200],[d8200,d8201],[d8200,d8202],[d8202,d8203],[d8202,d8204],[d8204,d8205],[d8204,d8206],[d8206,d8207],[d8206,d8208],[d8208,d8209],[d8208,d8210],[d8210,d8211],[d8210,d8212],[d8212,d8213],[d8212,d8214],[d8214,d8215],[d8214,d8216],[d8216,d8217],[d8216,d8218],[d8218,d8219],[d8218,d8220],[d8220,d8221],[d8220,d8222],[d8222,d8223],[d8222,d8224],[d8224,d8225],[d8224,d8226],[d8226,d8227],[d8226,d8228],[d8228,d8229],[d8228,d8230],[d8230,d8231],[d8230,d8232],[d8232,d8233],[d8232,d8234],[d8234,d8235],[d8234,d8236],[d8236,d8237],[d8236,d8238],[d8238,d8239],[d8238,d8240],[d8240,d8241],[d8240,d8242],[d8242,d8243],[d8242,d8244],[d8244,d8245],[d8244,d8246],[d8246,d8247],[d8246,d8248],[d8248,d8249],[d8248,d8250],[d8250,d8251],[d8250,d8252],[d8252,d8253],[d8252,d8254],[d8254,d8255],[d8254,d8256],[d8256,d8257],[d8256,d8258],[d8258,d8259],[d8258,d8260],[d8260,d8261],[d8260,d8262],[d8262,d8263],[d8262,d8264],[d8264,d8265],[d8264,d8266],[d8266,d8267],[d8266,d8268],[d8268,d8269],[d8268,d8270],[d8270,d8271],[d8270,d8272],[d8272,d8273],[d8272,d8274],[d8274,d8275],[d8274,d8276],[d8276,d8277],[d8276,d8278],[d8278,d8279],[d8278,d8280],[d8280,d8281],[d8280,d8282],[d8282,d8283],[d8282,d8284],[d8284,d8285],[d8284,d8286],[d8286,d8287],[d8286,d8288],[d8288,d8289],[d8288,d8290],[d8290,d8291],[d8290,d8292],[d8292,d8293],[d8292,d8294],[d8294,d8295],[d8294,d8296],[d8296,d8297],[d8296,d8298],[d8298,d8299],[d8298,d8300],[d8300,d8301],[d8300,d8302],[d8302,d8303],[d8302,d8304],[d8304,d8305],[d8304,d8306],[d8306,d8307],[d8306,d8308],[d8308,d8309],[d8308,d8310],[d8310,d8311],[d8310,d8312],[d8312,d8313],[d8312,d8314],[d8314,d8315],[d8314,d8316],[d8316,d8317],[d8316,d8318],[d8318,d8319],[d8318,d8320],[d8320,d8321],[d8320,d8322],[d8322,d8323],[d8322,d8324],[d8324,d8325],[d8324,d8326],[d8326,d8327],[d8326,d8328],[d8328,d8329],[d8328,d8330],[d8330,d8331],[d8330,d8332],[d8332,d8333],[d8332,d8334],[d8334,d8335],[d8334,d8336],[d8336,d8337],[d8336,d8338],[d8338,d8339],[d8338,d8340],[d8340,d8341],[d8340,d8342],[d8342,d8343],[d8342,d8344],[d8344,d8345],[d8344,d8346],[d8346,d8347],[d8346,d8348],[d8348,d8349],[d8348,d8350],[d8350,d8351],[d8350,d8352],[d8352,d8353],[d8352,d8354],[d8354,d8355],[d8354,d8356],[d8356,d8357],[d8356,d8358],[d8358,d8359],[d8358,d8360],[d8360,d8361],[d8360,d8362],[d8362,d8363],[d8362,d8364],[d8364,d8365],[d8364,d8366],[d8366,d8367],[d8366,d8368],[d8368,d8369],[d8368,d8370],[d8370,d8371],[d8370,d8372],[d8372,d8373],[d8372,d8374],[d8374,d8375],[d8374,d8376],[d8376,d8377],[d8376,d8378],[d8378,d8379],[d8378,d8380],[d8380,d8381],[d8380,d8382],[d8382,d8383],[d8382,d8384],[d8384,d8385],[d8384,d8386],[d8386,d8387],[d8386,d8388],[d8388,d8389],[d8388,d8390],[d8390,d8391],[d8390,d8392],[d8392,d8393],[d8392,d8394],[d8394,d8395],[d8394,d8396],[d8396,d8397],[d8396,d8398],[d8398,d8399],[d8398,d8400],[d8400,d8401],[d8400,d8402],[d8402,d8403],[d8402,d8404],[d8404,d8405],[d8404,d8406],[d8406,d8407],[d8406,d8408],[d8408,d8409],[d8408,d8410],[d8410,d8411],[d8410,d8412],[d8412,d8413],[d8412,d8414],[d8414,d8415],[d8414,d8416],[d8416,d8417],[d8416,d8418],[d8418,d8419],[d8418,d8420],[d8420,d8421],[d8420,d8422],[d8422,d8423],[d8422,d8424],[d8424,d8425],[d8424,d8426],[d8426,d8427],[d8426,d8428],[d8428,d8429],[d8428,d8430],[d8430,d8431],[d8430,d8432],[d8432,d8433],[d8432,d8434],[d8434,d8435],[d8434,d8436],[d8436,d8437],[d8436,d8438],[d8438,d8439],[d8438,d8440],[d8440,d8441],[d8440,d8442],[d8442,d8443],[d8442,d8444],[d8444,d8445],[d8444,d8446],[d8446,d8447],[d8446,d8448],[d8448,d8449],[d8448,d8450],[d8450,d8451],[d8450,d8452],[d8452,d8453],[d8452,d8454],[d8454,d8455],[d8454,d8456],[d8456,d8457],[d8456,d8458],[d8458,d8459],[d8458,d8460],[d8460,d8461],[d8460,d8462],[d8462,d8463],[d8462,d8464],[d8464,d8465],[d8464,d8466],[d8466,d8467],[d8466,d8468],[d8468,d8469],[d8468,d8470],[d8470,d8471],[d8470,d8472],[d8472,d8473],[d8472,d8474],[d8474,d8475],[d8474,d8476],[d8476,d8477],[d8476,d8478],[d8478,d8479],[d8478,d8480],[d8480,d8481],[d8480,d8482],[d8482,d8483],[d8482,d8484],[d8484,d8485],[d8484,d8486],[d8486,d8487],[d8486,d8488],[d8488,d8489],[d8488,d8490],[d8490,d8491],[d8490,d8492],[d8492,d8493],[d8492,d8494],[d8494,d8495],[d8494,d8496],[d8496,d8497],[d8496,d8498],[d8498,d8499],[d8498,d8500],[d8500,d8501],[d8500,d8502],[d8502,d8503],[d8502,d8504],[d8504,d8505],[d8504,d8506],[d8506,d8507],[d8506,d8508],[d8508,d8509],[d8508,d8510],[d8510,d8511],[d8510,d8512],[d8512,d8513],[d8512,d8514],[d8514,d8515],[d8514,d8516],[d8516,d8517],[d8516,d8518],[d8518,d8519],[d8518,d8520],[d8520,d8521],[d8520,d8522],[d8522,d8523],[d8522,d8524],[d8524,d8525],[d8524,d8526],[d8526,d8527],[d8526,d8528],[d8528,d8529],[d8528,d8530],[d8530,d8531],[d8530,d8532],[d8532,d8533],[d8532,d8534],[d8534,d8535],[d8534,d8536],[d8536,d8537],[d8536,d8538],[d8538,d8539],[d8538,d8540],[d8540,d8541],[d8540,d8542],[d8542,d8543],[d8542,d8544],[d8544,d8545],[d8544,d8546],[d8546,d8547],[d8546,d8548],[d8548,d8549],[d8548,d8550],[d8550,d8551],[d8550,d8552],[d8552,d8553],[d8552,d8554],[d8554,d8555],[d8554,d8556],[d8556,d8557],[d8556,d8558],[d8558,d8559],[d8558,d8560],[d8560,d8561],[d8560,d8562],[d8562,d8563],[d8562,d8564],[d8564,d8565],[d8564,d8566],[d8566,d8567],[d8566,d8568],[d8568,d8569],[d8568,d8570],[d8570,d8571],[d8570,d8572],[d8572,d8573],[d8572,d8574],[d8574,d8575],[d8574,d8576],[d8576,d8577],[d8576,d8578],[d8578,d8579],[d8578,d8580],[d8580,d8581],[d8580,d8582],[d8582,d8583],[d8582,d8584],[d8584,d8585],[d8584,d8586],[d8586,d8587],[d8586,d8588],[d8588,d8589],[d8588,d8590],[d8590,d8591],[d8590,d8592],[d8592,d8593],[d8592,d8594],[d8594,d8595],[d8594,d8596],[d8596,d8597],[d8596,d8598],[d8598,d8599],[d8598,d8600],[d8600,d8601],[d8600,d8602],[d8602,d8603],[d8602,d8604],[d8604,d8605],[d8604,d8606],[d8606,d8607],[d8606,d8608],[d8608,d8609],[d8608,d8610],[d8610,d8611],[d8610,d8612],[d8612,d8613],[d8612,d8614],[d8614,d8615],[d8614,d8616],[d8616,d8617],[d8616,d8618],[d8618,d8619],[d8618,d8620],[d8620,d8621],[d8620,d8622],[d8622,d8623],[d8622,d8624],[d8624,d8625],[d8624,d8626],[d8626,d8627],[d8626,d8628],[d8628,d8629],[d8628,d8630],[d8630,d8631],[d8630,d8632],[d8632,d8633],[d8632,d8634],[d8634,d8635],[d8634,d8636],[d8636,d8637],[d8636,d8638],[d8638,d8639],[d8638,d8640],[d8640,d8641],[d8640,d8642],[d8642,d8643],[d8642,d8644],[d8644,d8645],[d8644,d8646],[d8646,d8647],[d8646,d8648],[d8648,d8649],[d8648,d8650],[d8650,d8651],[d8650,d8652],[d8652,d8653],[d8652,d8654],[d8654,d8655],[d8654,d8656],[d8656,d8657],[d8656,d8658],[d8658,d8659],[d8658,d8660],[d8660,d8661],[d8660,d8662],[d8662,d8663],[d8662,d8664],[d8664,d8665],[d8664,d8666],[d8666,d8667],[d8666,d8668],[d8668,d8669],[d8668,d8670],[d8670,d8671],[d8670,d8672],[d8672,d8673],[d8672,d8674],[d8674,d8675],[d8674,d8676],[d8676,d8677],[d8676,d8678],[d8678,d8679],[d8678,d8680],[d8680,d8681],[d8680,d8682],[d8682,d8683],[d8682,d8684],[d8684,d8685],[d8684,d8686],[d8686,d8687],[d8686,d8688],[d8688,d8689],[d8688,d8690],[d8690,d8691],[d8690,d8692],[d8692,d8693],[d8692,d8694],[d8694,d8695],[d8694,d8696],[d8696,d8697],[d8696,d8698],[d8698,d8699],[d8698,d8700],[d8700,d8701],[d8700,d8702],[d8702,d8703],[d8702,d8704],[d8704,d8705],[d8704,d8706],[d8706,d8707],[d8706,d8708],[d8708,d8709],[d8708,d8710],[d8710,d8711],[d8710,d8712],[d8712,d8713],[d8712,d8714],[d8714,d8715],[d8714,d8716],[d8716,d8717],[d8716,d8718],[d8718,d8719],[d8718,d8720],[d8720,d8721],[d8720,d8722],[d8722,d8723],[d8722,d8724],[d8724,d8725],[d8724,d8726],[d8726,d8727],[d8726,d8728],[d8728,d8729],[d8728,d8730],[d8730,d8731],[d8730,d8732],[d8732,d8733],[d8732,d8734],[d8734,d8735],[d8734,d8736],[d8736,d8737],[d8736,d8738],[d8738,d8739],[d8738,d8740],[d8740,d8741],[d8740,d8742],[d8742,d8743],[d8742,d8744],[d8744,d8745],[d8744,d8746],[d8746,d8747],[d8746,d8748],[d8748,d8749],[d8748,d8750],[d8750,d8751],[d8750,d8752],[d8752,d8753],[d8752,d8754],[d8754,d8755],[d8754,d8756],[d8756,d8757],[d8756,d8758],[d8758,d8759],[d8758,d8760],[d8760,d8761],[d8760,d8762],[d8762,d8763],[d8762,d8764],[d8764,d8765],[d8764,d8766],[d8766,d8767],[d8766,d8768],[d8768,d8769],[d8768,d8770],[d8770,d8771],[d8770,d8772],[d8772,d8773],[d8772,d8774],[d8774,d8775],[d8774,d8776],[d8776,d8777],[d8776,d8778],[d8778,d8779],[d8778,d8780],[d8780,d8781],[d8780,d8782],[d8782,d8783],[d8782,d8784],[d8784,d8785],[d8784,d8786],[d8786,d8787],[d8786,d8788],[d8788,d8789],[d8788,d8790],[d8790,d8791],[d8790,d8792],[d8792,d8793],[d8792,d8794],[d8794,d8795],[d8794,d8796],[d8796,d8797],[d8796,d8798],[d8798,d8799],[d8798,d8800],[d8800,d8801],[d8800,d8802],[d8802,d8803],[d8802,d8804],[d8804,d8805],[d8804,d8806],[d8806,d8807],[d8806,d8808],[d8808,d8809],[d8808,d8810],[d8810,d8811],[d8810,d8812],[d8812,d8813],[d8812,d8814],[d8814,d8815],[d8814,d8816],[d8816,d8817],[d8816,d8818],[d8818,d8819],[d8818,d8820],[d8820,d8821],[d8820,d8822],[d8822,d8823],[d8822,d8824],[d8824,d8825],[d8824,d8826],[d8826,d8827],[d8826,d8828],[d8828,d8829],[d8828,d8830],[d8830,d8831],[d8830,d8832],[d8832,d8833],[d8832,d8834],[d8834,d8835],[d8834,d8836],[d8836,d8837],[d8836,d8838],[d8838,d8839],[d8838,d8840],[d8840,d8841],[d8840,d8842],[d8842,d8843],[d8842,d8844],[d8844,d8845],[d8844,d8846],[d8846,d8847],[d8846,d8848],[d8848,d8849],[d8848,d8850],[d8850,d8851],[d8850,d8852],[d8852,d8853],[d8852,d8854],[d8854,d8855],[d8854,d8856],[d8856,d8857],[d8856,d8858],[d8858,d8859],[d8858,d8860],[d8860,d8861],[d8860,d8862],[d8862,d8863],[d8862,d8864],[d8864,d8865],[d8864,d8866],[d8866,d8867],[d8866,d8868],[d8868,d8869],[d8868,d8870],[d8870,d8871],[d8870,d8872],[d8872,d8873],[d8872,d8874],[d8874,d8875],[d8874,d8876],[d8876,d8877],[d8876,d8878],[d8878,d8879],[d8878,d8880],[d8880,d8881],[d8880,d8882],[d8882,d8883],[d8882,d8884],[d8884,d8885],[d8884,d8886],[d8886,d8887],[d8886,d8888],[d8888,d8889],[d8888,d8890],[d8890,d8891],[d8890,d8892],[d8892,d8893],[d8892,d8894],[d8894,d8895],[d8894,d8896],[d8896,d8897],[d8896,d8898],[d8898,d8899],[d8898,d8900],[d8900,d8901],[d8900,d8902],[d8902,d8903],[d8902,d8904],[d8904,d8905],[d8904,d8906],[d8906,d8907],[d8906,d8908],[d8908,d8909],[d8908,d8910],[d8910,d8911],[d8910,d8912],[d8912,d8913],[d8912,d8914],[d8914,d8915],[d8914,d8916],[d8916,d8917],[d8916,d8918],[d8918,d8919],[d8918,d8920],[d8920,d8921],[d8920,d8922],[d8922,d8923],[d8922,d8924],[d8924,d8925],[d8924,d8926],[d8926,d8927],[d8926,d8928],[d8928,d8929],[d8928,d8930],[d8930,d8931],[d8930,d8932],[d8932,d8933],[d8932,d8934],[d8934,d8935],[d8934,d8936],[d8936,d8937],[d8936,d8938],[d8938,d8939],[d8938,d8940],[d8940,d8941],[d8940,d8942],[d8942,d8943],[d8942,d8944],[d8944,d8945],[d8944,d8946],[d8946,d8947],[d8946,d8948],[d8948,d8949],[d8948,d8950],[d8950,d8951],[d8950,d8952],[d8952,d8953],[d8952,d8954],[d8954,d8955],[d8954,d8956],[d8956,d8957],[d8956,d8958],[d8958,d8959],[d8958,d8960],[d8960,d8961],[d8960,d8962],[d8962,d8963],[d8962,d8964],[d8964,d8965],[d8964,d8966],[d8966,d8967],[d8966,d8968],[d8968,d8969],[d8968,d8970],[d8970,d8971],[d8970,d8972],[d8972,d8973],[d8972,d8974],[d8974,d8975],[d8974,d8976],[d8976,d8977],[d8976,d8978],[d8978,d8979],[d8978,d8980],[d8980,d8981],[d8980,d8982],[d8982,d8983],[d8982,d8984],[d8984,d8985],[d8984,d8986],[d8986,d8987],[d8986,d8988],[d8988,d8989],[d8988,d8990],[d8990,d8991],[d8990,d8992],[d8992,d8993],[d8992,d8994],[d8994,d8995],[d8994,d8996],[d8996,d8997],[d8996,d8998],[d8998,d8999],[d8998,d9000],[d9000,d9001],[d9000,d9002],[d9002,d9003],[d9002,d9004],[d9004,d9005],[d9004,d9006],[d9006,d9007],[d9006,d9008],[d9008,d9009],[d9008,d9010],[d9010,d9011],[d9010,d9012],[d9012,d9013],[d9012,d9014],[d9014,d9015],[d9014,d9016],[d9016,d9017],[d9016,d9018],[d9018,d9019],[d9018,d9020],[d9020,d9021],[d9020,d9022],[d9022,d9023],[d9022,d9024],[d9024,d9025],[d9024,d9026],[d9026,d9027],[d9026,d9028],[d9028,d9029],[d9028,d9030],[d9030,d9031],[d9030,d9032],[d9032,d9033],[d9032,d9034],[d9034,d9035],[d9034,d9036],[d9036,d9037],[d9036,d9038],[d9038,d9039],[d9038,d9040],[d9040,d9041],[d9040,d9042],[d9042,d9043],[d9042,d9044],[d9044,d9045],[d9044,d9046],[d9046,d9047],[d9046,d9048],[d9048,d9049],[d9048,d9050],[d9050,d9051],[d9050,d9052],[d9052,d9053],[d9052,d9054],[d9054,d9055],[d9054,d9056],[d9056,d9057],[d9056,d9058],[d9058,d9059],[d9058,d9060],[d9060,d9061],[d9060,d9062],[d9062,d9063],[d9062,d9064],[d9064,d9065],[d9064,d9066],[d9066,d9067],[d9066,d9068],[d9068,d9069],[d9068,d9070],[d9070,d9071],[d9070,d9072],[d9072,d9073],[d9072,d9074],[d9074,d9075],[d9074,d9076],[d9076,d9077],[d9076,d9078],[d9078,d9079],[d9078,d9080],[d9080,d9081],[d9080,d9082],[d9082,d9083],[d9082,d9084],[d9084,d9085],[d9084,d9086],[d9086,d9087],[d9086,d9088],[d9088,d9089],[d9088,d9090],[d9090,d9091],[d9090,d9092],[d9092,d9093],[d9092,d9094],[d9094,d9095],[d9094,d9096],[d9096,d9097],[d9096,d9098],[d9098,d9099],[d9098,d9100],[d9100,d9101],[d9100,d9102],[d9102,d9103],[d9102,d9104],[d9104,d9105],[d9104,d9106],[d9106,d9107],[d9106,d9108],[d9108,d9109],[d9108,d9110],[d9110,d9111],[d9110,d9112],[d9112,d9113],[d9112,d9114],[d9114,d9115],[d9114,d9116],[d9116,d9117],[d9116,d9118],[d9118,d9119],[d9118,d9120],[d9120,d9121],[d9120,d9122],[d9122,d9123],[d9122,d9124],[d9124,d9125],[d9124,d9126],[d9126,d9127],[d9126,d9128],[d9128,d9129],[d9128,d9130],[d9130,d9131],[d9130,d9132],[d9132,d9133],[d9132,d9134],[d9134,d9135],[d9134,d9136],[d9136,d9137],[d9136,d9138],[d9138,d9139],[d9138,d9140],[d9140,d9141],[d9140,d9142],[d9142,d9143],[d9142,d9144],[d9144,d9145],[d9144,d9146],[d9146,d9147],[d9146,d9148],[d9148,d9149],[d9148,d9150],[d9150,d9151],[d9150,d9152],[d9152,d9153],[d9152,d9154],[d9154,d9155],[d9154,d9156],[d9156,d9157],[d9156,d9158],[d9158,d9159],[d9158,d9160],[d9160,d9161],[d9160,d9162],[d9162,d9163],[d9162,d9164],[d9164,d9165],[d9164,d9166],[d9166,d9167],[d9166,d9168],[d9168,d9169],[d9168,d9170],[d9170,d9171],[d9170,d9172],[d9172,d9173],[d9172,d9174],[d9174,d9175],[d9174,d9176],[d9176,d9177],[d9176,d9178],[d9178,d9179],[d9178,d9180],[d9180,d9181],[d9180,d9182],[d9182,d9183],[d9182,d9184],[d9184,d9185],[d9184,d9186],[d9186,d9187],[d9186,d9188],[d9188,d9189],[d9188,d9190],[d9190,d9191],[d9190,d9192],[d9192,d9193],[d9192,d9194],[d9194,d9195],[d9194,d9196],[d9196,d9197],[d9196,d9198],[d9198,d9199],[d9198,d9200],[d9200,d9201],[d9200,d9202],[d9202,d9203],[d9202,d9204],[d9204,d9205],[d9204,d9206],[d9206,d9207],[d9206,d9208],[d9208,d9209],[d9208,d9210],[d9210,d9211],[d9210,d9212],[d9212,d9213],[d9212,d9214],[d9214,d9215],[d9214,d9216],[d9216,d9217],[d9216,d9218],[d9218,d9219],[d9218,d9220],[d9220,d9221],[d9220,d9222],[d9222,d9223],[d9222,d9224],[d9224,d9225],[d9224,d9226],[d9226,d9227],[d9226,d9228],[d9228,d9229],[d9228,d9230],[d9230,d9231],[d9230,d9232],[d9232,d9233],[d9232,d9234],[d9234,d9235],[d9234,d9236],[d9236,d9237],[d9236,d9238],[d9238,d9239],[d9238,d9240],[d9240,d9241],[d9240,d9242],[d9242,d9243],[d9242,d9244],[d9244,d9245],[d9244,d9246],[d9246,d9247],[d9246,d9248],[d9248,d9249],[d9248,d9250],[d9250,d9251],[d9250,d9252],[d9252,d9253],[d9252,d9254],[d9254,d9255],[d9254,d9256],[d9256,d9257],[d9256,d9258],[d9258,d9259],[d9258,d9260],[d9260,d9261],[d9260,d9262],[d9262,d9263],[d9262,d9264],[d9264,d9265],[d9264,d9266],[d9266,d9267],[d9266,d9268],[d9268,d9269],[d9268,d9270],[d9270,d9271],[d9270,d9272],[d9272,d9273],[d9272,d9274],[d9274,d9275],[d9274,d9276],[d9276,d9277],[d9276,d9278],[d9278,d9279],[d9278,d9280],[d9280,d9281],[d9280,d9282],[d9282,d9283],[d9282,d9284],[d9284,d9285],[d9284,d9286],[d9286,d9287],[d9286,d9288],[d9288,d9289],[d9288,d9290],[d9290,d9291],[d9290,d9292],[d9292,d9293],[d9292,d9294],[d9294,d9295],[d9294,d9296],[d9296,d9297],[d9296,d9298],[d9298,d9299],[d9298,d9300],[d9300,d9301],[d9300,d9302],[d9302,d9303],[d9302,d9304],[d9304,d9305],[d9304,d9306],[d9306,d9307],[d9306,d9308],[d9308,d9309],[d9308,d9310],[d9310,d9311],[d9310,d9312],[d9312,d9313],[d9312,d9314],[d9314,d9315],[d9314,d9316],[d9316,d9317],[d9316,d9318],[d9318,d9319],[d9318,d9320],[d9320,d9321],[d9320,d9322],[d9322,d9323],[d9322,d9324],[d9324,d9325],[d9324,d9326],[d9326,d9327],[d9326,d9328],[d9328,d9329],[d9328,d9330],[d9330,d9331],[d9330,d9332],[d9332,d9333],[d9332,d9334],[d9334,d9335],[d9334,d9336],[d9336,d9337],[d9336,d9338],[d9338,d9339],[d9338,d9340],[d9340,d9341],[d9340,d9342],[d9342,d9343],[d9342,d9344],[d9344,d9345],[d9344,d9346],[d9346,d9347],[d9346,d9348],[d9348,d9349],[d9348,d9350],[d9350,d9351],[d9350,d9352],[d9352,d9353],[d9352,d9354],[d9354,d9355],[d9354,d9356],[d9356,d9357],[d9356,d9358],[d9358,d9359],[d9358,d9360],[d9360,d9361],[d9360,d9362],[d9362,d9363],[d9362,d9364],[d9364,d9365],[d9364,d9366],[d9366,d9367],[d9366,d9368],[d9368,d9369],[d9368,d9370],[d9370,d9371],[d9370,d9372],[d9372,d9373],[d9372,d9374],[d9374,d9375],[d9374,d9376],[d9376,d9377],[d9376,d9378],[d9378,d9379],[d9378,d9380],[d9380,d9381],[d9380,d9382],[d9382,d9383],[d9382,d9384],[d9384,d9385],[d9384,d9386],[d9386,d9387],[d9386,d9388],[d9388,d9389],[d9388,d9390],[d9390,d9391],[d9390,d9392],[d9392,d9393],[d9392,d9394],[d9394,d9395],[d9394,d9396],[d9396,d9397],[d9396,d9398],[d9398,d9399],[d9398,d9400],[d9400,d9401],[d9400,d9402],[d9402,d9403],[d9402,d9404],[d9404,d9405],[d9404,d9406],[d9406,d9407],[d9406,d9408],[d9408,d9409],[d9408,d9410],[d9410,d9411],[d9410,d9412],[d9412,d9413],[d9412,d9414],[d9414,d9415],[d9414,d9416],[d9416,d9417],[d9416,d9418],[d9418,d9419],[d9418,d9420],[d9420,d9421],[d9420,d9422],[d9422,d9423],[d9422,d9424],[d9424,d9425],[d9424,d9426],[d9426,d9427],[d9426,d9428],[d9428,d9429],[d9428,d9430],[d9430,d9431],[d9430,d9432],[d9432,d9433],[d9432,d9434],[d9434,d9435],[d9434,d9436],[d9436,d9437],[d9436,d9438],[d9438,d9439],[d9438,d9440],[d9440,d9441],[d9440,d9442],[d9442,d9443],[d9442,d9444],[d9444,d9445],[d9444,d9446],[d9446,d9447],[d9446,d9448],[d9448,d9449],[d9448,d9450],[d9450,d9451],[d9450,d9452],[d9452,d9453],[d9452,d9454],[d9454,d9455],[d9454,d9456],[d9456,d9457],[d9456,d9458],[d9458,d9459],[d9458,d9460],[d9460,d9461],[d9460,d9462],[d9462,d9463],[d9462,d9464],[d9464,d9465],[d9464,d9466],[d9466,d9467],[d9466,d9468],[d9468,d9469],[d9468,d9470],[d9470,d9471],[d9470,d9472],[d9472,d9473],[d9472,d9474],[d9474,d9475],[d9474,d9476],[d9476,d9477],[d9476,d9478],[d9478,d9479],[d9478,d9480],[d9480,d9481],[d9480,d9482],[d9482,d9483],[d9482,d9484],[d9484,d9485],[d9484,d9486],[d9486,d9487],[d9486,d9488],[d9488,d9489],[d9488,d9490],[d9490,d9491],[d9490,d9492],[d9492,d9493],[d9492,d9494],[d9494,d9495],[d9494,d9496],[d9496,d9497],[d9496,d9498],[d9498,d9499],[d9498,d9500],[d9500,d9501],[d9500,d9502],[d9502,d9503],[d9502,d9504],[d9504,d9505],[d9504,d9506],[d9506,d9507],[d9506,d9508],[d9508,d9509],[d9508,d9510],[d9510,d9511],[d9510,d9512],[d9512,d9513],[d9512,d9514],[d9514,d9515],[d9514,d9516],[d9516,d9517],[d9516,d9518],[d9518,d9519],[d9518,d9520],[d9520,d9521],[d9520,d9522],[d9522,d9523],[d9522,d9524],[d9524,d9525],[d9524,d9526],[d9526,d9527],[d9526,d9528],[d9528,d9529],[d9528,d9530],[d9530,d9531],[d9530,d9532],[d9532,d9533],[d9532,d9534],[d9534,d9535],[d9534,d9536],[d9536,d9537],[d9536,d9538],[d9538,d9539],[d9538,d9540],[d9540,d9541],[d9540,d9542],[d9542,d9543],[d9542,d9544],[d9544,d9545],[d9544,d9546],[d9546,d9547],[d9546,d9548],[d9548,d9549],[d9548,d9550],[d9550,d9551],[d9550,d9552],[d9552,d9553],[d9552,d9554],[d9554,d9555],[d9554,d9556],[d9556,d9557],[d9556,d9558],[d9558,d9559],[d9558,d9560],[d9560,d9561],[d9560,d9562],[d9562,d9563],[d9562,d9564],[d9564,d9565],[d9564,d9566],[d9566,d9567],[d9566,d9568],[d9568,d9569],[d9568,d9570],[d9570,d9571],[d9570,d9572],[d9572,d9573],[d9572,d9574],[d9574,d9575],[d9574,d9576],[d9576,d9577],[d9576,d9578],[d9578,d9579],[d9578,d9580],[d9580,d9581],[d9580,d9582],[d9582,d9583],[d9582,d9584],[d9584,d9585],[d9584,d9586],[d9586,d9587],[d9586,d9588],[d9588,d9589],[d9588,d9590],[d9590,d9591],[d9590,d9592],[d9592,d9593],[d9592,d9594],[d9594,d9595],[d9594,d9596],[d9596,d9597],[d9596,d9598],[d9598,d9599],[d9598,d9600],[d9600,d9601],[d9600,d9602],[d9602,d9603],[d9602,d9604],[d9604,d9605],[d9604,d9606],[d9606,d9607],[d9606,d9608],[d9608,d9609],[d9608,d9610],[d9610,d9611],[d9610,d9612],[d9612,d9613],[d9612,d9614],[d9614,d9615],[d9614,d9616],[d9616,d9617],[d9616,d9618],[d9618,d9619],[d9618,d9620],[d9620,d9621],[d9620,d9622],[d9622,d9623],[d9622,d9624],[d9624,d9625],[d9624,d9626],[d9626,d9627],[d9626,d9628],[d9628,d9629],[d9628,d9630],[d9630,d9631],[d9630,d9632],[d9632,d9633],[d9632,d9634],[d9634,d9635],[d9634,d9636],[d9636,d9637],[d9636,d9638],[d9638,d9639],[d9638,d9640],[d9640,d9641],[d9640,d9642],[d9642,d9643],[d9642,d9644],[d9644,d9645],[d9644,d9646],[d9646,d9647],[d9646,d9648],[d9648,d9649],[d9648,d9650],[d9650,d9651],[d9650,d9652],[d9652,d9653],[d9652,d9654],[d9654,d9655],[d9654,d9656],[d9656,d9657],[d9656,d9658],[d9658,d9659],[d9658,d9660],[d9660,d9661],[d9660,d9662],[d9662,d9663],[d9662,d9664],[d9664,d9665],[d9664,d9666],[d9666,d9667],[d9666,d9668],[d9668,d9669],[d9668,d9670],[d9670,d9671],[d9670,d9672],[d9672,d9673],[d9672,d9674],[d9674,d9675],[d9674,d9676],[d9676,d9677],[d9676,d9678],[d9678,d9679],[d9678,d9680],[d9680,d9681],[d9680,d9682],[d9682,d9683],[d9682,d9684],[d9684,d9685],[d9684,d9686],[d9686,d9687],[d9686,d9688],[d9688,d9689],[d9688,d9690],[d9690,d9691],[d9690,d9692],[d9692,d9693],[d9692,d9694],[d9694,d9695],[d9694,d9696],[d9696,d9697],[d9696,d9698],[d9698,d9699],[d9698,d9700],[d9700,d9701],[d9700,d9702],[d9702,d9703],[d9702,d9704],[d9704,d9705],[d9704,d9706],[d9706,d9707],[d9706,d9708],[d9708,d9709],[d9708,d9710],[d9710,d9711],[d9710,d9712],[d9712,d9713],[d9712,d9714],[d9714,d9715],[d9714,d9716],[d9716,d9717],[d9716,d9718],[d9718,d9719],[d9718,d9720],[d9720,d9721],[d9720,d9722],[d9722,d9723],[d9722,d9724],[d9724,d9725],[d9724,d9726],[d9726,d9727],[d9726,d9728],[d9728,d9729],[d9728,d9730],[d9730,d9731],[d9730,d9732],[d9732,d9733],[d9732,d9734],[d9734,d9735],[d9734,d9736],[d9736,d9737],[d9736,d9738],[d9738,d9739],[d9738,d9740],[d9740,d9741],[d9740,d9742],[d9742,d9743],[d9742,d9744],[d9744,d9745],[d9744,d9746],[d9746,d9747],[d9746,d9748],[d9748,d9749],[d9748,d9750],[d9750,d9751],[d9750,d9752],[d9752,d9753],[d9752,d9754],[d9754,d9755],[d9754,d9756],[d9756,d9757],[d9756,d9758],[d9758,d9759],[d9758,d9760],[d9760,d9761],[d9760,d9762],[d9762,d9763],[d9762,d9764],[d9764,d9765],[d9764,d9766],[d9766,d9767],[d9766,d9768],[d9768,d9769],[d9768,d9770],[d9770,d9771],[d9770,d9772],[d9772,d9773],[d9772,d9774],[d9774,d9775],[d9774,d9776],[d9776,d9777],[d9776,d9778],[d9778,d9779],[d9778,d9780],[d9780,d9781],[d9780,d9782],[d9782,d9783],[d9782,d9784],[d9784,d9785],[d9784,d9786],[d9786,d9787],[d9786,d9788],[d9788,d9789],[d9788,d9790],[d9790,d9791],[d9790,d9792],[d9792,d9793],[d9792,d9794],[d9794,d9795],[d9794,d9796],[d9796,d9797],[d9796,d9798],[d9798,d9799],[d9798,d9800],[d9800,d9801],[d9800,d9802],[d9802,d9803],[d9802,d9804],[d9804,d9805],[d9804,d9806],[d9806,d9807],[d9806,d9808],[d9808,d9809],[d9808,d9810],[d9810,d9811],[d9810,d9812],[d9812,d9813],[d9812,d9814],[d9814,d9815],[d9814,d9816],[d9816,d9817],[d9816,d9818],[d9818,d9819],[d9818,d9820],[d9820,d9821],[d9820,d9822],[d9822,d9823],[d9822,d9824],[d9824,d9825],[d9824,d9826],[d9826,d9827],[d9826,d9828],[d9828,d9829],[d9828,d9830],[d9830,d9831],[d9830,d9832],[d9832,d9833],[d9832,d9834],[d9834,d9835],[d9834,d9836],[d9836,d9837],[d9836,d9838],[d9838,d9839],[d9838,d9840],[d9840,d9841],[d9840,d9842],[d9842,d9843],[d9842,d9844],[d9844,d9845],[d9844,d9846],[d9846,d9847],[d9846,d9848],[d9848,d9849],[d9848,d9850],[d9850,d9851],[d9850,d9852],[d9852,d9853],[d9852,d9854],[d9854,d9855],[d9854,d9856],[d9856,d9857],[d9856,d9858],[d9858,d9859],[d9858,d9860],[d9860,d9861],[d9860,d9862],[d9862,d9863],[d9862,d9864],[d9864,d9865],[d9864,d9866],[d9866,d9867],[d9866,d9868],[d9868,d9869],[d9868,d9870],[d9870,d9871],[d9870,d9872],[d9872,d9873],[d9872,d9874],[d9874,d9875],[d9874,d9876],[d9876,d9877],[d9876,d9878],[d9878,d9879],[d9878,d9880],[d9880,d9881],[d9880,d9882],[d9882,d9883],[d9882,d9884],[d9884,d9885],[d9884,d9886],[d9886,d9887],[d9886,d9888],[d9888,d9889],[d9888,d9890],[d9890,d9891],[d9890,d9892],[d9892,d9893],[d9892,d9894],[d9894,d9895],[d9894,d9896],[d9896,d9897],[d9896,d9898],[d9898,d9899],[d9898,d9900],[d9900,d9901],[d9900,d9902],[d9902,d9903],[d9902,d9904],[d9904,d9905],[d9904,d9906],[d9906,d9907],[d9906,d9908],[d9908,d9909],[d9908,d9910],[d9910,d9911],[d9910,d9912],[d9912,d9913],[d9912,d9914],[d9914,d9915],[d9914,d9916],[d9916,d9917],[d9916,d9918],[d9918,d9919],[d9918,d9920],[d9920,d9921],[d9920,d9922],[d9922,d9923],[d9922,d9924],[d9924,d9925],[d9924,d9926],[d9926,d9927],[d9926,d9928],[d9928,d9929],[d9928,d9930],[d9930,d9931],[d9930,d9932],[d9932,d9933],[d9932,d9934],[d9934,d9935],[d9934,d9936],[d9936,d9937],[d9936,d9938],[d9938,d9939],[d9938,d9940],[d9940,d9941],[d9940,d9942],[d9942,d9943],[d9942,d9944],[d9944,d9945],[d9944,d9946],[d9946,d9947],[d9946,d9948],[d9948,d9949],[d9948,d9950],[d9950,d9951],[d9950,d9952],[d9952,d9953],[d9952,d9954],[d9954,d9955],[d9954,d9956],[d9956,d9957],[d9956,d9958],[d9958,d9959],[d9958,d9960],[d9960,d9961],[d9960,d9962],[d9962,d9963],[d9962,d9964],[d9964,d9965],[d9964,d9966],[d9966,d9967],[d9966,d9968],[d9968,d9969],[d9968,d9970],[d9970,d9971],[d9970,d9972],[d9972,d9973],[d9972,d9974],[d9974,d9975],[d9974,d9976],[d9976,d9977],[d9976,d9978],[d9978,d9979],[d9978,d9980],[d9980,d9981],[d9980,d9982],[d9982,d9983],[d9982,d9984],[d9984,d9985],[d9984,d9986],[d9986,d9987],[d9986,d9988],[d9988,d9989],[d9988,d9990],[d9990,d9991],[d9990,d9992],[d9992,d9993],[d9992,d9994],[d9994,d9995],[d9994,d9996],[d9996,d9997],[d9996,d9998],[d1,f0],[d1,f1],[d3,f2],[d3,f3],[d5,f4],[d5,f5],[d7,f6],[d7,f7],[d9,f8],[d9,f9],[d11,f10],[d11,f11],[d13,f12],[d13,f13],[d15,f14],[d15,f15],[d17,f16],[d17,f17],[d19,f18],[d19,f19],[d21,f20],[d21,f21],[d23,f22],[d23,f23],[d25,f24],[d25,f25],[d27,f26],[d27,f27],[d29,f28],[d29,f29],[d31,f30],[d31,f31],[d33,f32],[d33,f33],[d35,f34],[d35,f35],[d37,f36],[d37,f37],[d39,f38],[d39,f39],[d41,f40],[d41,f41],[d43,f42],[d43,f43],[d45,f44],[d45,f45],[d47,f46],[d47,f47],[d49,f48],[d49,f49],[d51,f50],[d51,f51],[d53,f52],[d53,f53],[d55,f54],[d55,f55],[d57,f56],[d57,f57],[d59,f58],[d59,f59],[d61,f60],[d61,f61],[d63,f62],[d63,f63],[d65,f64],[d65,f65],[d67,f66],[d67,f67],[d69,f68],[d69,f69],[d71,f70],[d71,f71],[d73,f72],[d73,f73],[d75,f74],[d75,f75],[d77,f76],[d77,f77],[d79,f78],[d79,f79],[d81,f80],[d81,f81],[d83,f82],[d83,f83],[d85,f84],[d85,f85],[d87,f86],[d87,f87],[d89,f88],[d89,f89],[d91,f90],[d91,f91],[d93,f92],[d93,f93],[d95,f94],[d95,f95],[d97,f96],[d97,f97],[d99,f98],[d99,f99],[d101,f100],[d101,f101],[d103,f102],[d103,f103],[d105,f104],[d105,f105],[d107,f106],[d107,f107],[d109,f108],[d109,f109],[d111,f110],[d111,f111],[d113,f112],[d113,f113],[d115,f114],[d115,f115],[d117,f116],[d117,f117],[d119,f118],[d119,f119],[d121,f120],[d121,f121],[d123,f122],[d123,f123],[d125,f124],[d125,f125],[d127,f126],[d127,f127],[d129,f128],[d129,f129],[d131,f130],[d131,f131],[d133,f132],[d133,f133],[d135,f134],[d135,f135],[d137,f136],[d137,f137],[d139,f138],[d139,f139],[d141,f140],[d141,f141],[d143,f142],[d143,f143],[d145,f144],[d145,f145],[d147,f146],[d147,f147],[d149,f148],[d149,f149],[d151,f150],[d151,f151],[d153,f152],[d153,f153],[d155,f154],[d155,f155],[d157,f156],[d157,f157],[d159,f158],[d159,f159],[d161,f160],[d161,f161],[d163,f162],[d163,f163],[d165,f164],[d165,f165],[d167,f166],[d167,f167],[d169,f168],[d169,f169],[d171,f170],[d171,f171],[d173,f172],[d173,f173],[d175,f174],[d175,f175],[d177,f176],[d177,f177],[d179,f178],[d179,f179],[d181,f180],[d181,f181],[d183,f182],[d183,f183],[d185,f184],[d185,f185],[d187,f186],[d187,f187],[d189,f188],[d189,f189],[d191,f190],[d191,f191],[d193,f192],[d193,f193],[d195,f194],[d195,f195],[d197,f196],[d197,f197],[d199,f198],[d199,f199],[d201,f200],[d201,f201],[d203,f202],[d203,f203],[d205,f204],[d205,f205],[d207,f206],[d207,f207],[d209,f208],[d209,f209],[d211,f210],[d211,f211],[d213,f212],[d213,f213],[d215,f214],[d215,f215],[d217,f216],[d217,f217],[d219,f218],[d219,f219],[d221,f220],[d221,f221],[d223,f222],[d223,f223],[d225,f224],[d225,f225],[d227,f226],[d227,f227],[d229,f228],[d229,f229],[d231,f230],[d231,f231],[d233,f232],[d233,f233],[d235,f234],[d235,f235],[d237,f236],[d237,f237],[d239,f238],[d239,f239],[d241,f240],[d241,f241],[d243,f242],[d243,f243],[d245,f244],[d245,f245],[d247,f246],[d247,f247],[d249,f248],[d249,f249],[d251,f250],[d251,f251],[d253,f252],[d253,f253],[d255,f254],[d255,f255],[d257,f256],[d257,f257],[d259,f258],[d259,f259],[d261,f260],[d261,f261],[d263,f262],[d263,f263],[d265,f264],[d265,f265],[d267,f266],[d267,f267],[d269,f268],[d269,f269],[d271,f270],[d271,f271],[d273,f272],[d273,f273],[d275,f274],[d275,f275],[d277,f276],[d277,f277],[d279,f278],[d279,f279],[d281,f280],[d281,f281],[d283,f282],[d283,f283],[d285,f284],[d285,f285],[d287,f286],[d287,f287],[d289,f288],[d289,f289],[d291,f290],[d291,f291],[d293,f292],[d293,f293],[d295,f294],[d295,f295],[d297,f296],[d297,f297],[d299,f298],[d299,f299],[d301,f300],[d301,f301],[d303,f302],[d303,f303],[d305,f304],[d305,f305],[d307,f306],[d307,f307],[d309,f308],[d309,f309],[d311,f310],[d311,f311],[d313,f312],[d313,f313],[d315,f314],[d315,f315],[d317,f316],[d317,f317],[d319,f318],[d319,f319],[d321,f320],[d321,f321],[d323,f322],[d323,f323],[d325,f324],[d325,f325],[d327,f326],[d327,f327],[d329,f328],[d329,f329],[d331,f330],[d331,f331],[d333,f332],[d333,f333],[d335,f334],[d335,f335],[d337,f336],[d337,f337],[d339,f338],[d339,f339],[d341,f340],[d341,f341],[d343,f342],[d343,f343],[d345,f344],[d345,f345],[d347,f346],[d347,f347],[d349,f348],[d349,f349],[d351,f350],[d351,f351],[d353,f352],[d353,f353],[d355,f354],[d355,f355],[d357,f356],[d357,f357],[d359,f358],[d359,f359],[d361,f360],[d361,f361],[d363,f362],[d363,f363],[d365,f364],[d365,f365],[d367,f366],[d367,f367],[d369,f368],[d369,f369],[d371,f370],[d371,f371],[d373,f372],[d373,f373],[d375,f374],[d375,f375],[d377,f376],[d377,f377],[d379,f378],[d379,f379],[d381,f380],[d381,f381],[d383,f382],[d383,f383],[d385,f384],[d385,f385],[d387,f386],[d387,f387],[d389,f388],[d389,f389],[d391,f390],[d391,f391],[d393,f392],[d393,f393],[d395,f394],[d395,f395],[d397,f396],[d397,f397],[d399,f398],[d399,f399],[d401,f400],[d401,f401],[d403,f402],[d403,f403],[d405,f404],[d405,f405],[d407,f406],[d407,f407],[d409,f408],[d409,f409],[d411,f410],[d411,f411],[d413,f412],[d413,f413],[d415,f414],[d415,f415],[d417,f416],[d417,f417],[d419,f418],[d419,f419],[d421,f420],[d421,f421],[d423,f422],[d423,f423],[d425,f424],[d425,f425],[d427,f426],[d427,f427],[d429,f428],[d429,f429],[d431,f430],[d431,f431],[d433,f432],[d433,f433],[d435,f434],[d435,f435],[d437,f436],[d437,f437],[d439,f438],[d439,f439],[d441,f440],[d441,f441],[d443,f442],[d443,f443],[d445,f444],[d445,f445],[d447,f446],[d447,f447],[d449,f448],[d449,f449],[d451,f450],[d451,f451],[d453,f452],[d453,f453],[d455,f454],[d455,f455],[d457,f456],[d457,f457],[d459,f458],[d459,f459],[d461,f460],[d461,f461],[d463,f462],[d463,f463],[d465,f464],[d465,f465],[d467,f466],[d467,f467],[d469,f468],[d469,f469],[d471,f470],[d471,f471],[d473,f472],[d473,f473],[d475,f474],[d475,f475],[d477,f476],[d477,f477],[d479,f478],[d479,f479],[d481,f480],[d481,f481],[d483,f482],[d483,f483],[d485,f484],[d485,f485],[d487,f486],[d487,f487],[d489,f488],[d489,f489],[d491,f490],[d491,f491],[d493,f492],[d493,f493],[d495,f494],[d495,f495],[d497,f496],[d497,f497],[d499,f498],[d499,f499],[d501,f500],[d501,f501],[d503,f502],[d503,f503],[d505,f504],[d505,f505],[d507,f506],[d507,f507],[d509,f508],[d509,f509],[d511,f510],[d511,f511],[d513,f512],[d513,f513],[d515,f514],[d515,f515],[d517,f516],[d517,f517],[d519,f518],[d519,f519],[d521,f520],[d521,f521],[d523,f522],[d523,f523],[d525,f524],[d525,f525],[d527,f526],[d527,f527],[d529,f528],[d529,f529],[d531,f530],[d531,f531],[d533,f532],[d533,f533],[d535,f534],[d535,f535],[d537,f536],[d537,f537],[d539,f538],[d539,f539],[d541,f540],[d541,f541],[d543,f542],[d543,f543],[d545,f544],[d545,f545],[d547,f546],[d547,f547],[d549,f548],[d549,f549],[d551,f550],[d551,f551],[d553,f552],[d553,f553],[d555,f554],[d555,f555],[d557,f556],[d557,f557],[d559,f558],[d559,f559],[d561,f560],[d561,f561],[d563,f562],[d563,f563],[d565,f564],[d565,f565],[d567,f566],[d567,f567],[d569,f568],[d569,f569],[d571,f570],[d571,f571],[d573,f572],[d573,f573],[d575,f574],[d575,f575],[d577,f576],[d577,f577],[d579,f578],[d579,f579],[d581,f580],[d581,f581],[d583,f582],[d583,f583],[d585,f584],[d585,f585],[d587,f586],[d587,f587],[d589,f588],[d589,f589],[d591,f590],[d591,f591],[d593,f592],[d593,f593],[d595,f594],[d595,f595],[d597,f596],[d597,f597],[d599,f598],[d599,f599],[d601,f600],[d601,f601],[d603,f602],[d603,f603],[d605,f604],[d605,f605],[d607,f606],[d607,f607],[d609,f608],[d609,f609],[d611,f610],[d611,f611],[d613,f612],[d613,f613],[d615,f614],[d615,f615],[d617,f616],[d617,f617],[d619,f618],[d619,f619],[d621,f620],[d621,f621],[d623,f622],[d623,f623],[d625,f624],[d625,f625],[d627,f626],[d627,f627],[d629,f628],[d629,f629],[d631,f630],[d631,f631],[d633,f632],[d633,f633],[d635,f634],[d635,f635],[d637,f636],[d637,f637],[d639,f638],[d639,f639],[d641,f640],[d641,f641],[d643,f642],[d643,f643],[d645,f644],[d645,f645],[d647,f646],[d647,f647],[d649,f648],[d649,f649],[d651,f650],[d651,f651],[d653,f652],[d653,f653],[d655,f654],[d655,f655],[d657,f656],[d657,f657],[d659,f658],[d659,f659],[d661,f660],[d661,f661],[d663,f662],[d663,f663],[d665,f664],[d665,f665],[d667,f666],[d667,f667],[d669,f668],[d669,f669],[d671,f670],[d671,f671],[d673,f672],[d673,f673],[d675,f674],[d675,f675],[d677,f676],[d677,f677],[d679,f678],[d679,f679],[d681,f680],[d681,f681],[d683,f682],[d683,f683],[d685,f684],[d685,f685],[d687,f686],[d687,f687],[d689,f688],[d689,f689],[d691,f690],[d691,f691],[d693,f692],[d693,f693],[d695,f694],[d695,f695],[d697,f696],[d697,f697],[d699,f698],[d699,f699],[d701,f700],[d701,f701],[d703,f702],[d703,f703],[d705,f704],[d705,f705],[d707,f706],[d707,f707],[d709,f708],[d709,f709],[d711,f710],[d711,f711],[d713,f712],[d713,f713],[d715,f714],[d715,f715],[d717,f716],[d717,f717],[d719,f718],[d719,f719],[d721,f720],[d721,f721],[d723,f722],[d723,f723],[d725,f724],[d725,f725],[d727,f726],[d727,f727],[d729,f728],[d729,f729],[d731,f730],[d731,f731],[d733,f732],[d733,f733],[d735,f734],[d735,f735],[d737,f736],[d737,f737],[d739,f738],[d739,f739],[d741,f740],[d741,f741],[d743,f742],[d743,f743],[d745,f744],[d745,f745],[d747,f746],[d747,f747],[d749,f748],[d749,f749],[d751,f750],[d751,f751],[d753,f752],[d753,f753],[d755,f754],[d755,f755],[d757,f756],[d757,f757],[d759,f758],[d759,f759],[d761,f760],[d761,f761],[d763,f762],[d763,f763],[d765,f764],[d765,f765],[d767,f766],[d767,f767],[d769,f768],[d769,f769],[d771,f770],[d771,f771],[d773,f772],[d773,f773],[d775,f774],[d775,f775],[d777,f776],[d777,f777],[d779,f778],[d779,f779],[d781,f780],[d781,f781],[d783,f782],[d783,f783],[d785,f784],[d785,f785],[d787,f786],[d787,f787],[d789,f788],[d789,f789],[d791,f790],[d791,f791],[d793,f792],[d793,f793],[d795,f794],[d795,f795],[d797,f796],[d797,f797],[d799,f798],[d799,f799],[d801,f800],[d801,f801],[d803,f802],[d803,f803],[d805,f804],[d805,f805],[d807,f806],[d807,f807],[d809,f808],[d809,f809],[d811,f810],[d811,f811],[d813,f812],[d813,f813],[d815,f814],[d815,f815],[d817,f816],[d817,f817],[d819,f818],[d819,f819],[d821,f820],[d821,f821],[d823,f822],[d823,f823],[d825,f824],[d825,f825],[d827,f826],[d827,f827],[d829,f828],[d829,f829],[d831,f830],[d831,f831],[d833,f832],[d833,f833],[d835,f834],[d835,f835],[d837,f836],[d837,f837],[d839,f838],[d839,f839],[d841,f840],[d841,f841],[d843,f842],[d843,f843],[d845,f844],[d845,f845],[d847,f846],[d847,f847],[d849,f848],[d849,f849],[d851,f850],[d851,f851],[d853,f852],[d853,f853],[d855,f854],[d855,f855],[d857,f856],[d857,f857],[d859,f858],[d859,f859],[d861,f860],[d861,f861],[d863,f862],[d863,f863],[d865,f864],[d865,f865],[d867,f866],[d867,f867],[d869,f868],[d869,f869],[d871,f870],[d871,f871],[d873,f872],[d873,f873],[d875,f874],[d875,f875],[d877,f876],[d877,f877],[d879,f878],[d879,f879],[d881,f880],[d881,f881],[d883,f882],[d883,f883],[d885,f884],[d885,f885],[d887,f886],[d887,f887],[d889,f888],[d889,f889],[d891,f890],[d891,f891],[d893,f892],[d893,f893],[d895,f894],[d895,f895],[d897,f896],[d897,f897],[d899,f898],[d899,f899],[d901,f900],[d901,f901],[d903,f902],[d903,f903],[d905,f904],[d905,f905],[d907,f906],[d907,f907],[d909,f908],[d909,f909],[d911,f910],[d911,f911],[d913,f912],[d913,f913],[d915,f914],[d915,f915],[d917,f916],[d917,f917],[d919,f918],[d919,f919],[d921,f920],[d921,f921],[d923,f922],[d923,f923],[d925,f924],[d925,f925],[d927,f926],[d927,f927],[d929,f928],[d929,f929],[d931,f930],[d931,f931],[d933,f932],[d933,f933],[d935,f934],[d935,f935],[d937,f936],[d937,f937],[d939,f938],[d939,f939],[d941,f940],[d941,f941],[d943,f942],[d943,f943],[d945,f944],[d945,f945],[d947,f946],[d947,f947],[d949,f948],[d949,f949],[d951,f950],[d951,f951],[d953,f952],[d953,f953],[d955,f954],[d955,f955],[d957,f956],[d957,f957],[d959,f958],[d959,f959],[d961,f960],[d961,f961],[d963,f962],[d963,f963],[d965,f964],[d965,f965],[d967,f966],[d967,f967],[d969,f968],[d969,f969],[d971,f970],[d971,f971],[d973,f972],[d973,f973],[d975,f974],[d975,f975],[d977,f976],[d977,f977],[d979,f978],[d979,f979],[d981,f980],[d981,f981],[d983,f982],[d983,f983],[d985,f984],[d985,f985],[d987,f986],[d987,f987],[d989,f988],[d989,f989],[d991,f990],[d991,f991],[d993,f992],[d993,f993],[d995,f994],[d995,f995],[d997,f996],[d997,f997],[d999,f998],[d999,f999],[d1001,f1000],[d1001,f1001],[d1003,f1002],[d1003,f1003],[d1005,f1004],[d1005,f1005],[d1007,f1006],[d1007,f1007],[d1009,f1008],[d1009,f1009],[d1011,f1010],[d1011,f1011],[d1013,f1012],[d1013,f1013],[d1015,f1014],[d1015,f1015],[d1017,f1016],[d1017,f1017],[d1019,f1018],[d1019,f1019],[d1021,f1020],[d1021,f1021],[d1023,f1022],[d1023,f1023],[d1025,f1024],[d1025,f1025],[d1027,f1026],[d1027,f1027],[d1029,f1028],[d1029,f1029],[d1031,f1030],[d1031,f1031],[d1033,f1032],[d1033,f1033],[d1035,f1034],[d1035,f1035],[d1037,f1036],[d1037,f1037],[d1039,f1038],[d1039,f1039],[d1041,f1040],[d1041,f1041],[d1043,f1042],[d1043,f1043],[d1045,f1044],[d1045,f1045],[d1047,f1046],[d1047,f1047],[d1049,f1048],[d1049,f1049],[d1051,f1050],[d1051,f1051],[d1053,f1052],[d1053,f1053],[d1055,f1054],[d1055,f1055],[d1057,f1056],[d1057,f1057],[d1059,f1058],[d1059,f1059],[d1061,f1060],[d1061,f1061],[d1063,f1062],[d1063,f1063],[d1065,f1064],[d1065,f1065],[d1067,f1066],[d1067,f1067],[d1069,f1068],[d1069,f1069],[d1071,f1070],[d1071,f1071],[d1073,f1072],[d1073,f1073],[d1075,f1074],[d1075,f1075],[d1077,f1076],[d1077,f1077],[d1079,f1078],[d1079,f1079],[d1081,f1080],[d1081,f1081],[d1083,f1082],[d1083,f1083],[d1085,f1084],[d1085,f1085],[d1087,f1086],[d1087,f1087],[d1089,f1088],[d1089,f1089],[d1091,f1090],[d1091,f1091],[d1093,f1092],[d1093,f1093],[d1095,f1094],[d1095,f1095],[d1097,f1096],[d1097,f1097],[d1099,f1098],[d1099,f1099],[d1101,f1100],[d1101,f1101],[d1103,f1102],[d1103,f1103],[d1105,f1104],[d1105,f1105],[d1107,f1106],[d1107,f1107],[d1109,f1108],[d1109,f1109],[d1111,f1110],[d1111,f1111],[d1113,f1112],[d1113,f1113],[d1115,f1114],[d1115,f1115],[d1117,f1116],[d1117,f1117],[d1119,f1118],[d1119,f1119],[d1121,f1120],[d1121,f1121],[d1123,f1122],[d1123,f1123],[d1125,f1124],[d1125,f1125],[d1127,f1126],[d1127,f1127],[d1129,f1128],[d1129,f1129],[d1131,f1130],[d1131,f1131],[d1133,f1132],[d1133,f1133],[d1135,f1134],[d1135,f1135],[d1137,f1136],[d1137,f1137],[d1139,f1138],[d1139,f1139],[d1141,f1140],[d1141,f1141],[d1143,f1142],[d1143,f1143],[d1145,f1144],[d1145,f1145],[d1147,f1146],[d1147,f1147],[d1149,f1148],[d1149,f1149],[d1151,f1150],[d1151,f1151],[d1153,f1152],[d1153,f1153],[d1155,f1154],[d1155,f1155],[d1157,f1156],[d1157,f1157],[d1159,f1158],[d1159,f1159],[d1161,f1160],[d1161,f1161],[d1163,f1162],[d1163,f1163],[d1165,f1164],[d1165,f1165],[d1167,f1166],[d1167,f1167],[d1169,f1168],[d1169,f1169],[d1171,f1170],[d1171,f1171],[d1173,f1172],[d1173,f1173],[d1175,f1174],[d1175,f1175],[d1177,f1176],[d1177,f1177],[d1179,f1178],[d1179,f1179],[d1181,f1180],[d1181,f1181],[d1183,f1182],[d1183,f1183],[d1185,f1184],[d1185,f1185],[d1187,f1186],[d1187,f1187],[d1189,f1188],[d1189,f1189],[d1191,f1190],[d1191,f1191],[d1193,f1192],[d1193,f1193],[d1195,f1194],[d1195,f1195],[d1197,f1196],[d1197,f1197],[d1199,f1198],[d1199,f1199],[d1201,f1200],[d1201,f1201],[d1203,f1202],[d1203,f1203],[d1205,f1204],[d1205,f1205],[d1207,f1206],[d1207,f1207],[d1209,f1208],[d1209,f1209],[d1211,f1210],[d1211,f1211],[d1213,f1212],[d1213,f1213],[d1215,f1214],[d1215,f1215],[d1217,f1216],[d1217,f1217],[d1219,f1218],[d1219,f1219],[d1221,f1220],[d1221,f1221],[d1223,f1222],[d1223,f1223],[d1225,f1224],[d1225,f1225],[d1227,f1226],[d1227,f1227],[d1229,f1228],[d1229,f1229],[d1231,f1230],[d1231,f1231],[d1233,f1232],[d1233,f1233],[d1235,f1234],[d1235,f1235],[d1237,f1236],[d1237,f1237],[d1239,f1238],[d1239,f1239],[d1241,f1240],[d1241,f1241],[d1243,f1242],[d1243,f1243],[d1245,f1244],[d1245,f1245],[d1247,f1246],[d1247,f1247],[d1249,f1248],[d1249,f1249],[d1251,f1250],[d1251,f1251],[d1253,f1252],[d1253,f1253],[d1255,f1254],[d1255,f1255],[d1257,f1256],[d1257,f1257],[d1259,f1258],[d1259,f1259],[d1261,f1260],[d1261,f1261],[d1263,f1262],[d1263,f1263],[d1265,f1264],[d1265,f1265],[d1267,f1266],[d1267,f1267],[d1269,f1268],[d1269,f1269],[d1271,f1270],[d1271,f1271],[d1273,f1272],[d1273,f1273],[d1275,f1274],[d1275,f1275],[d1277,f1276],[d1277,f1277],[d1279,f1278],[d1279,f1279],[d1281,f1280],[d1281,f1281],[d1283,f1282],[d1283,f1283],[d1285,f1284],[d1285,f1285],[d1287,f1286],[d1287,f1287],[d1289,f1288],[d1289,f1289],[d1291,f1290],[d1291,f1291],[d1293,f1292],[d1293,f1293],[d1295,f1294],[d1295,f1295],[d1297,f1296],[d1297,f1297],[d1299,f1298],[d1299,f1299],[d1301,f1300],[d1301,f1301],[d1303,f1302],[d1303,f1303],[d1305,f1304],[d1305,f1305],[d1307,f1306],[d1307,f1307],[d1309,f1308],[d1309,f1309],[d1311,f1310],[d1311,f1311],[d1313,f1312],[d1313,f1313],[d1315,f1314],[d1315,f1315],[d1317,f1316],[d1317,f1317],[d1319,f1318],[d1319,f1319],[d1321,f1320],[d1321,f1321],[d1323,f1322],[d1323,f1323],[d1325,f1324],[d1325,f1325],[d1327,f1326],[d1327,f1327],[d1329,f1328],[d1329,f1329],[d1331,f1330],[d1331,f1331],[d1333,f1332],[d1333,f1333],[d1335,f1334],[d1335,f1335],[d1337,f1336],[d1337,f1337],[d1339,f1338],[d1339,f1339],[d1341,f1340],[d1341,f1341],[d1343,f1342],[d1343,f1343],[d1345,f1344],[d1345,f1345],[d1347,f1346],[d1347,f1347],[d1349,f1348],[d1349,f1349],[d1351,f1350],[d1351,f1351],[d1353,f1352],[d1353,f1353],[d1355,f1354],[d1355,f1355],[d1357,f1356],[d1357,f1357],[d1359,f1358],[d1359,f1359],[d1361,f1360],[d1361,f1361],[d1363,f1362],[d1363,f1363],[d1365,f1364],[d1365,f1365],[d1367,f1366],[d1367,f1367],[d1369,f1368],[d1369,f1369],[d1371,f1370],[d1371,f1371],[d1373,f1372],[d1373,f1373],[d1375,f1374],[d1375,f1375],[d1377,f1376],[d1377,f1377],[d1379,f1378],[d1379,f1379],[d1381,f1380],[d1381,f1381],[d1383,f1382],[d1383,f1383],[d1385,f1384],[d1385,f1385],[d1387,f1386],[d1387,f1387],[d1389,f1388],[d1389,f1389],[d1391,f1390],[d1391,f1391],[d1393,f1392],[d1393,f1393],[d1395,f1394],[d1395,f1395],[d1397,f1396],[d1397,f1397],[d1399,f1398],[d1399,f1399],[d1401,f1400],[d1401,f1401],[d1403,f1402],[d1403,f1403],[d1405,f1404],[d1405,f1405],[d1407,f1406],[d1407,f1407],[d1409,f1408],[d1409,f1409],[d1411,f1410],[d1411,f1411],[d1413,f1412],[d1413,f1413],[d1415,f1414],[d1415,f1415],[d1417,f1416],[d1417,f1417],[d1419,f1418],[d1419,f1419],[d1421,f1420],[d1421,f1421],[d1423,f1422],[d1423,f1423],[d1425,f1424],[d1425,f1425],[d1427,f1426],[d1427,f1427],[d1429,f1428],[d1429,f1429],[d1431,f1430],[d1431,f1431],[d1433,f1432],[d1433,f1433],[d1435,f1434],[d1435,f1435],[d1437,f1436],[d1437,f1437],[d1439,f1438],[d1439,f1439],[d1441,f1440],[d1441,f1441],[d1443,f1442],[d1443,f1443],[d1445,f1444],[d1445,f1445],[d1447,f1446],[d1447,f1447],[d1449,f1448],[d1449,f1449],[d1451,f1450],[d1451,f1451],[d1453,f1452],[d1453,f1453],[d1455,f1454],[d1455,f1455],[d1457,f1456],[d1457,f1457],[d1459,f1458],[d1459,f1459],[d1461,f1460],[d1461,f1461],[d1463,f1462],[d1463,f1463],[d1465,f1464],[d1465,f1465],[d1467,f1466],[d1467,f1467],[d1469,f1468],[d1469,f1469],[d1471,f1470],[d1471,f1471],[d1473,f1472],[d1473,f1473],[d1475,f1474],[d1475,f1475],[d1477,f1476],[d1477,f1477],[d1479,f1478],[d1479,f1479],[d1481,f1480],[d1481,f1481],[d1483,f1482],[d1483,f1483],[d1485,f1484],[d1485,f1485],[d1487,f1486],[d1487,f1487],[d1489,f1488],[d1489,f1489],[d1491,f1490],[d1491,f1491],[d1493,f1492],[d1493,f1493],[d1495,f1494],[d1495,f1495],[d1497,f1496],[d1497,f1497],[d1499,f1498],[d1499,f1499],[d1501,f1500],[d1501,f1501],[d1503,f1502],[d1503,f1503],[d1505,f1504],[d1505,f1505],[d1507,f1506],[d1507,f1507],[d1509,f1508],[d1509,f1509],[d1511,f1510],[d1511,f1511],[d1513,f1512],[d1513,f1513],[d1515,f1514],[d1515,f1515],[d1517,f1516],[d1517,f1517],[d1519,f1518],[d1519,f1519],[d1521,f1520],[d1521,f1521],[d1523,f1522],[d1523,f1523],[d1525,f1524],[d1525,f1525],[d1527,f1526],[d1527,f1527],[d1529,f1528],[d1529,f1529],[d1531,f1530],[d1531,f1531],[d1533,f1532],[d1533,f1533],[d1535,f1534],[d1535,f1535],[d1537,f1536],[d1537,f1537],[d1539,f1538],[d1539,f1539],[d1541,f1540],[d1541,f1541],[d1543,f1542],[d1543,f1543],[d1545,f1544],[d1545,f1545],[d1547,f1546],[d1547,f1547],[d1549,f1548],[d1549,f1549],[d1551,f1550],[d1551,f1551],[d1553,f1552],[d1553,f1553],[d1555,f1554],[d1555,f1555],[d1557,f1556],[d1557,f1557],[d1559,f1558],[d1559,f1559],[d1561,f1560],[d1561,f1561],[d1563,f1562],[d1563,f1563],[d1565,f1564],[d1565,f1565],[d1567,f1566],[d1567,f1567],[d1569,f1568],[d1569,f1569],[d1571,f1570],[d1571,f1571],[d1573,f1572],[d1573,f1573],[d1575,f1574],[d1575,f1575],[d1577,f1576],[d1577,f1577],[d1579,f1578],[d1579,f1579],[d1581,f1580],[d1581,f1581],[d1583,f1582],[d1583,f1583],[d1585,f1584],[d1585,f1585],[d1587,f1586],[d1587,f1587],[d1589,f1588],[d1589,f1589],[d1591,f1590],[d1591,f1591],[d1593,f1592],[d1593,f1593],[d1595,f1594],[d1595,f1595],[d1597,f1596],[d1597,f1597],[d1599,f1598],[d1599,f1599],[d1601,f1600],[d1601,f1601],[d1603,f1602],[d1603,f1603],[d1605,f1604],[d1605,f1605],[d1607,f1606],[d1607,f1607],[d1609,f1608],[d1609,f1609],[d1611,f1610],[d1611,f1611],[d1613,f1612],[d1613,f1613],[d1615,f1614],[d1615,f1615],[d1617,f1616],[d1617,f1617],[d1619,f1618],[d1619,f1619],[d1621,f1620],[d1621,f1621],[d1623,f1622],[d1623,f1623],[d1625,f1624],[d1625,f1625],[d1627,f1626],[d1627,f1627],[d1629,f1628],[d1629,f1629],[d1631,f1630],[d1631,f1631],[d1633,f1632],[d1633,f1633],[d1635,f1634],[d1635,f1635],[d1637,f1636],[d1637,f1637],[d1639,f1638],[d1639,f1639],[d1641,f1640],[d1641,f1641],[d1643,f1642],[d1643,f1643],[d1645,f1644],[d1645,f1645],[d1647,f1646],[d1647,f1647],[d1649,f1648],[d1649,f1649],[d1651,f1650],[d1651,f1651],[d1653,f1652],[d1653,f1653],[d1655,f1654],[d1655,f1655],[d1657,f1656],[d1657,f1657],[d1659,f1658],[d1659,f1659],[d1661,f1660],[d1661,f1661],[d1663,f1662],[d1663,f1663],[d1665,f1664],[d1665,f1665],[d1667,f1666],[d1667,f1667],[d1669,f1668],[d1669,f1669],[d1671,f1670],[d1671,f1671],[d1673,f1672],[d1673,f1673],[d1675,f1674],[d1675,f1675],[d1677,f1676],[d1677,f1677],[d1679,f1678],[d1679,f1679],[d1681,f1680],[d1681,f1681],[d1683,f1682],[d1683,f1683],[d1685,f1684],[d1685,f1685],[d1687,f1686],[d1687,f1687],[d1689,f1688],[d1689,f1689],[d1691,f1690],[d1691,f1691],[d1693,f1692],[d1693,f1693],[d1695,f1694],[d1695,f1695],[d1697,f1696],[d1697,f1697],[d1699,f1698],[d1699,f1699],[d1701,f1700],[d1701,f1701],[d1703,f1702],[d1703,f1703],[d1705,f1704],[d1705,f1705],[d1707,f1706],[d1707,f1707],[d1709,f1708],[d1709,f1709],[d1711,f1710],[d1711,f1711],[d1713,f1712],[d1713,f1713],[d1715,f1714],[d1715,f1715],[d1717,f1716],[d1717,f1717],[d1719,f1718],[d1719,f1719],[d1721,f1720],[d1721,f1721],[d1723,f1722],[d1723,f1723],[d1725,f1724],[d1725,f1725],[d1727,f1726],[d1727,f1727],[d1729,f1728],[d1729,f1729],[d1731,f1730],[d1731,f1731],[d1733,f1732],[d1733,f1733],[d1735,f1734],[d1735,f1735],[d1737,f1736],[d1737,f1737],[d1739,f1738],[d1739,f1739],[d1741,f1740],[d1741,f1741],[d1743,f1742],[d1743,f1743],[d1745,f1744],[d1745,f1745],[d1747,f1746],[d1747,f1747],[d1749,f1748],[d1749,f1749],[d1751,f1750],[d1751,f1751],[d1753,f1752],[d1753,f1753],[d1755,f1754],[d1755,f1755],[d1757,f1756],[d1757,f1757],[d1759,f1758],[d1759,f1759],[d1761,f1760],[d1761,f1761],[d1763,f1762],[d1763,f1763],[d1765,f1764],[d1765,f1765],[d1767,f1766],[d1767,f1767],[d1769,f1768],[d1769,f1769],[d1771,f1770],[d1771,f1771],[d1773,f1772],[d1773,f1773],[d1775,f1774],[d1775,f1775],[d1777,f1776],[d1777,f1777],[d1779,f1778],[d1779,f1779],[d1781,f1780],[d1781,f1781],[d1783,f1782],[d1783,f1783],[d1785,f1784],[d1785,f1785],[d1787,f1786],[d1787,f1787],[d1789,f1788],[d1789,f1789],[d1791,f1790],[d1791,f1791],[d1793,f1792],[d1793,f1793],[d1795,f1794],[d1795,f1795],[d1797,f1796],[d1797,f1797],[d1799,f1798],[d1799,f1799],[d1801,f1800],[d1801,f1801],[d1803,f1802],[d1803,f1803],[d1805,f1804],[d1805,f1805],[d1807,f1806],[d1807,f1807],[d1809,f1808],[d1809,f1809],[d1811,f1810],[d1811,f1811],[d1813,f1812],[d1813,f1813],[d1815,f1814],[d1815,f1815],[d1817,f1816],[d1817,f1817],[d1819,f1818],[d1819,f1819],[d1821,f1820],[d1821,f1821],[d1823,f1822],[d1823,f1823],[d1825,f1824],[d1825,f1825],[d1827,f1826],[d1827,f1827],[d1829,f1828],[d1829,f1829],[d1831,f1830],[d1831,f1831],[d1833,f1832],[d1833,f1833],[d1835,f1834],[d1835,f1835],[d1837,f1836],[d1837,f1837],[d1839,f1838],[d1839,f1839],[d1841,f1840],[d1841,f1841],[d1843,f1842],[d1843,f1843],[d1845,f1844],[d1845,f1845],[d1847,f1846],[d1847,f1847],[d1849,f1848],[d1849,f1849],[d1851,f1850],[d1851,f1851],[d1853,f1852],[d1853,f1853],[d1855,f1854],[d1855,f1855],[d1857,f1856],[d1857,f1857],[d1859,f1858],[d1859,f1859],[d1861,f1860],[d1861,f1861],[d1863,f1862],[d1863,f1863],[d1865,f1864],[d1865,f1865],[d1867,f1866],[d1867,f1867],[d1869,f1868],[d1869,f1869],[d1871,f1870],[d1871,f1871],[d1873,f1872],[d1873,f1873],[d1875,f1874],[d1875,f1875],[d1877,f1876],[d1877,f1877],[d1879,f1878],[d1879,f1879],[d1881,f1880],[d1881,f1881],[d1883,f1882],[d1883,f1883],[d1885,f1884],[d1885,f1885],[d1887,f1886],[d1887,f1887],[d1889,f1888],[d1889,f1889],[d1891,f1890],[d1891,f1891],[d1893,f1892],[d1893,f1893],[d1895,f1894],[d1895,f1895],[d1897,f1896],[d1897,f1897],[d1899,f1898],[d1899,f1899],[d1901,f1900],[d1901,f1901],[d1903,f1902],[d1903,f1903],[d1905,f1904],[d1905,f1905],[d1907,f1906],[d1907,f1907],[d1909,f1908],[d1909,f1909],[d1911,f1910],[d1911,f1911],[d1913,f1912],[d1913,f1913],[d1915,f1914],[d1915,f1915],[d1917,f1916],[d1917,f1917],[d1919,f1918],[d1919,f1919],[d1921,f1920],[d1921,f1921],[d1923,f1922],[d1923,f1923],[d1925,f1924],[d1925,f1925],[d1927,f1926],[d1927,f1927],[d1929,f1928],[d1929,f1929],[d1931,f1930],[d1931,f1931],[d1933,f1932],[d1933,f1933],[d1935,f1934],[d1935,f1935],[d1937,f1936],[d1937,f1937],[d1939,f1938],[d1939,f1939],[d1941,f1940],[d1941,f1941],[d1943,f1942],[d1943,f1943],[d1945,f1944],[d1945,f1945],[d1947,f1946],[d1947,f1947],[d1949,f1948],[d1949,f1949],[d1951,f1950],[d1951,f1951],[d1953,f1952],[d1953,f1953],[d1955,f1954],[d1955,f1955],[d1957,f1956],[d1957,f1957],[d1959,f1958],[d1959,f1959],[d1961,f1960],[d1961,f1961],[d1963,f1962],[d1963,f1963],[d1965,f1964],[d1965,f1965],[d1967,f1966],[d1967,f1967],[d1969,f1968],[d1969,f1969],[d1971,f1970],[d1971,f1971],[d1973,f1972],[d1973,f1973],[d1975,f1974],[d1975,f1975],[d1977,f1976],[d1977,f1977],[d1979,f1978],[d1979,f1979],[d1981,f1980],[d1981,f1981],[d1983,f1982],[d1983,f1983],[d1985,f1984],[d1985,f1985],[d1987,f1986],[d1987,f1987],[d1989,f1988],[d1989,f1989],[d1991,f1990],[d1991,f1991],[d1993,f1992],[d1993,f1993],[d1995,f1994],[d1995,f1995],[d1997,f1996],[d1997,f1997],[d1999,f1998],[d1999,f1999],[d2001,f2000],[d2001,f2001],[d2003,f2002],[d2003,f2003],[d2005,f2004],[d2005,f2005],[d2007,f2006],[d2007,f2007],[d2009,f2008],[d2009,f2009],[d2011,f2010],[d2011,f2011],[d2013,f2012],[d2013,f2013],[d2015,f2014],[d2015,f2015],[d2017,f2016],[d2017,f2017],[d2019,f2018],[d2019,f2019],[d2021,f2020],[d2021,f2021],[d2023,f2022],[d2023,f2023],[d2025,f2024],[d2025,f2025],[d2027,f2026],[d2027,f2027],[d2029,f2028],[d2029,f2029],[d2031,f2030],[d2031,f2031],[d2033,f2032],[d2033,f2033],[d2035,f2034],[d2035,f2035],[d2037,f2036],[d2037,f2037],[d2039,f2038],[d2039,f2039],[d2041,f2040],[d2041,f2041],[d2043,f2042],[d2043,f2043],[d2045,f2044],[d2045,f2045],[d2047,f2046],[d2047,f2047],[d2049,f2048],[d2049,f2049],[d2051,f2050],[d2051,f2051],[d2053,f2052],[d2053,f2053],[d2055,f2054],[d2055,f2055],[d2057,f2056],[d2057,f2057],[d2059,f2058],[d2059,f2059],[d2061,f2060],[d2061,f2061],[d2063,f2062],[d2063,f2063],[d2065,f2064],[d2065,f2065],[d2067,f2066],[d2067,f2067],[d2069,f2068],[d2069,f2069],[d2071,f2070],[d2071,f2071],[d2073,f2072],[d2073,f2073],[d2075,f2074],[d2075,f2075],[d2077,f2076],[d2077,f2077],[d2079,f2078],[d2079,f2079],[d2081,f2080],[d2081,f2081],[d2083,f2082],[d2083,f2083],[d2085,f2084],[d2085,f2085],[d2087,f2086],[d2087,f2087],[d2089,f2088],[d2089,f2089],[d2091,f2090],[d2091,f2091],[d2093,f2092],[d2093,f2093],[d2095,f2094],[d2095,f2095],[d2097,f2096],[d2097,f2097],[d2099,f2098],[d2099,f2099],[d2101,f2100],[d2101,f2101],[d2103,f2102],[d2103,f2103],[d2105,f2104],[d2105,f2105],[d2107,f2106],[d2107,f2107],[d2109,f2108],[d2109,f2109],[d2111,f2110],[d2111,f2111],[d2113,f2112],[d2113,f2113],[d2115,f2114],[d2115,f2115],[d2117,f2116],[d2117,f2117],[d2119,f2118],[d2119,f2119],[d2121,f2120],[d2121,f2121],[d2123,f2122],[d2123,f2123],[d2125,f2124],[d2125,f2125],[d2127,f2126],[d2127,f2127],[d2129,f2128],[d2129,f2129],[d2131,f2130],[d2131,f2131],[d2133,f2132],[d2133,f2133],[d2135,f2134],[d2135,f2135],[d2137,f2136],[d2137,f2137],[d2139,f2138],[d2139,f2139],[d2141,f2140],[d2141,f2141],[d2143,f2142],[d2143,f2143],[d2145,f2144],[d2145,f2145],[d2147,f2146],[d2147,f2147],[d2149,f2148],[d2149,f2149],[d2151,f2150],[d2151,f2151],[d2153,f2152],[d2153,f2153],[d2155,f2154],[d2155,f2155],[d2157,f2156],[d2157,f2157],[d2159,f2158],[d2159,f2159],[d2161,f2160],[d2161,f2161],[d2163,f2162],[d2163,f2163],[d2165,f2164],[d2165,f2165],[d2167,f2166],[d2167,f2167],[d2169,f2168],[d2169,f2169],[d2171,f2170],[d2171,f2171],[d2173,f2172],[d2173,f2173],[d2175,f2174],[d2175,f2175],[d2177,f2176],[d2177,f2177],[d2179,f2178],[d2179,f2179],[d2181,f2180],[d2181,f2181],[d2183,f2182],[d2183,f2183],[d2185,f2184],[d2185,f2185],[d2187,f2186],[d2187,f2187],[d2189,f2188],[d2189,f2189],[d2191,f2190],[d2191,f2191],[d2193,f2192],[d2193,f2193],[d2195,f2194],[d2195,f2195],[d2197,f2196],[d2197,f2197],[d2199,f2198],[d2199,f2199],[d2201,f2200],[d2201,f2201],[d2203,f2202],[d2203,f2203],[d2205,f2204],[d2205,f2205],[d2207,f2206],[d2207,f2207],[d2209,f2208],[d2209,f2209],[d2211,f2210],[d2211,f2211],[d2213,f2212],[d2213,f2213],[d2215,f2214],[d2215,f2215],[d2217,f2216],[d2217,f2217],[d2219,f2218],[d2219,f2219],[d2221,f2220],[d2221,f2221],[d2223,f2222],[d2223,f2223],[d2225,f2224],[d2225,f2225],[d2227,f2226],[d2227,f2227],[d2229,f2228],[d2229,f2229],[d2231,f2230],[d2231,f2231],[d2233,f2232],[d2233,f2233],[d2235,f2234],[d2235,f2235],[d2237,f2236],[d2237,f2237],[d2239,f2238],[d2239,f2239],[d2241,f2240],[d2241,f2241],[d2243,f2242],[d2243,f2243],[d2245,f2244],[d2245,f2245],[d2247,f2246],[d2247,f2247],[d2249,f2248],[d2249,f2249],[d2251,f2250],[d2251,f2251],[d2253,f2252],[d2253,f2253],[d2255,f2254],[d2255,f2255],[d2257,f2256],[d2257,f2257],[d2259,f2258],[d2259,f2259],[d2261,f2260],[d2261,f2261],[d2263,f2262],[d2263,f2263],[d2265,f2264],[d2265,f2265],[d2267,f2266],[d2267,f2267],[d2269,f2268],[d2269,f2269],[d2271,f2270],[d2271,f2271],[d2273,f2272],[d2273,f2273],[d2275,f2274],[d2275,f2275],[d2277,f2276],[d2277,f2277],[d2279,f2278],[d2279,f2279],[d2281,f2280],[d2281,f2281],[d2283,f2282],[d2283,f2283],[d2285,f2284],[d2285,f2285],[d2287,f2286],[d2287,f2287],[d2289,f2288],[d2289,f2289],[d2291,f2290],[d2291,f2291],[d2293,f2292],[d2293,f2293],[d2295,f2294],[d2295,f2295],[d2297,f2296],[d2297,f2297],[d2299,f2298],[d2299,f2299],[d2301,f2300],[d2301,f2301],[d2303,f2302],[d2303,f2303],[d2305,f2304],[d2305,f2305],[d2307,f2306],[d2307,f2307],[d2309,f2308],[d2309,f2309],[d2311,f2310],[d2311,f2311],[d2313,f2312],[d2313,f2313],[d2315,f2314],[d2315,f2315],[d2317,f2316],[d2317,f2317],[d2319,f2318],[d2319,f2319],[d2321,f2320],[d2321,f2321],[d2323,f2322],[d2323,f2323],[d2325,f2324],[d2325,f2325],[d2327,f2326],[d2327,f2327],[d2329,f2328],[d2329,f2329],[d2331,f2330],[d2331,f2331],[d2333,f2332],[d2333,f2333],[d2335,f2334],[d2335,f2335],[d2337,f2336],[d2337,f2337],[d2339,f2338],[d2339,f2339],[d2341,f2340],[d2341,f2341],[d2343,f2342],[d2343,f2343],[d2345,f2344],[d2345,f2345],[d2347,f2346],[d2347,f2347],[d2349,f2348],[d2349,f2349],[d2351,f2350],[d2351,f2351],[d2353,f2352],[d2353,f2353],[d2355,f2354],[d2355,f2355],[d2357,f2356],[d2357,f2357],[d2359,f2358],[d2359,f2359],[d2361,f2360],[d2361,f2361],[d2363,f2362],[d2363,f2363],[d2365,f2364],[d2365,f2365],[d2367,f2366],[d2367,f2367],[d2369,f2368],[d2369,f2369],[d2371,f2370],[d2371,f2371],[d2373,f2372],[d2373,f2373],[d2375,f2374],[d2375,f2375],[d2377,f2376],[d2377,f2377],[d2379,f2378],[d2379,f2379],[d2381,f2380],[d2381,f2381],[d2383,f2382],[d2383,f2383],[d2385,f2384],[d2385,f2385],[d2387,f2386],[d2387,f2387],[d2389,f2388],[d2389,f2389],[d2391,f2390],[d2391,f2391],[d2393,f2392],[d2393,f2393],[d2395,f2394],[d2395,f2395],[d2397,f2396],[d2397,f2397],[d2399,f2398],[d2399,f2399],[d2401,f2400],[d2401,f2401],[d2403,f2402],[d2403,f2403],[d2405,f2404],[d2405,f2405],[d2407,f2406],[d2407,f2407],[d2409,f2408],[d2409,f2409],[d2411,f2410],[d2411,f2411],[d2413,f2412],[d2413,f2413],[d2415,f2414],[d2415,f2415],[d2417,f2416],[d2417,f2417],[d2419,f2418],[d2419,f2419],[d2421,f2420],[d2421,f2421],[d2423,f2422],[d2423,f2423],[d2425,f2424],[d2425,f2425],[d2427,f2426],[d2427,f2427],[d2429,f2428],[d2429,f2429],[d2431,f2430],[d2431,f2431],[d2433,f2432],[d2433,f2433],[d2435,f2434],[d2435,f2435],[d2437,f2436],[d2437,f2437],[d2439,f2438],[d2439,f2439],[d2441,f2440],[d2441,f2441],[d2443,f2442],[d2443,f2443],[d2445,f2444],[d2445,f2445],[d2447,f2446],[d2447,f2447],[d2449,f2448],[d2449,f2449],[d2451,f2450],[d2451,f2451],[d2453,f2452],[d2453,f2453],[d2455,f2454],[d2455,f2455],[d2457,f2456],[d2457,f2457],[d2459,f2458],[d2459,f2459],[d2461,f2460],[d2461,f2461],[d2463,f2462],[d2463,f2463],[d2465,f2464],[d2465,f2465],[d2467,f2466],[d2467,f2467],[d2469,f2468],[d2469,f2469],[d2471,f2470],[d2471,f2471],[d2473,f2472],[d2473,f2473],[d2475,f2474],[d2475,f2475],[d2477,f2476],[d2477,f2477],[d2479,f2478],[d2479,f2479],[d2481,f2480],[d2481,f2481],[d2483,f2482],[d2483,f2483],[d2485,f2484],[d2485,f2485],[d2487,f2486],[d2487,f2487],[d2489,f2488],[d2489,f2489],[d2491,f2490],[d2491,f2491],[d2493,f2492],[d2493,f2493],[d2495,f2494],[d2495,f2495],[d2497,f2496],[d2497,f2497],[d2499,f2498],[d2499,f2499],[d2501,f2500],[d2501,f2501],[d2503,f2502],[d2503,f2503],[d2505,f2504],[d2505,f2505],[d2507,f2506],[d2507,f2507],[d2509,f2508],[d2509,f2509],[d2511,f2510],[d2511,f2511],[d2513,f2512],[d2513,f2513],[d2515,f2514],[d2515,f2515],[d2517,f2516],[d2517,f2517],[d2519,f2518],[d2519,f2519],[d2521,f2520],[d2521,f2521],[d2523,f2522],[d2523,f2523],[d2525,f2524],[d2525,f2525],[d2527,f2526],[d2527,f2527],[d2529,f2528],[d2529,f2529],[d2531,f2530],[d2531,f2531],[d2533,f2532],[d2533,f2533],[d2535,f2534],[d2535,f2535],[d2537,f2536],[d2537,f2537],[d2539,f2538],[d2539,f2539],[d2541,f2540],[d2541,f2541],[d2543,f2542],[d2543,f2543],[d2545,f2544],[d2545,f2545],[d2547,f2546],[d2547,f2547],[d2549,f2548],[d2549,f2549],[d2551,f2550],[d2551,f2551],[d2553,f2552],[d2553,f2553],[d2555,f2554],[d2555,f2555],[d2557,f2556],[d2557,f2557],[d2559,f2558],[d2559,f2559],[d2561,f2560],[d2561,f2561],[d2563,f2562],[d2563,f2563],[d2565,f2564],[d2565,f2565],[d2567,f2566],[d2567,f2567],[d2569,f2568],[d2569,f2569],[d2571,f2570],[d2571,f2571],[d2573,f2572],[d2573,f2573],[d2575,f2574],[d2575,f2575],[d2577,f2576],[d2577,f2577],[d2579,f2578],[d2579,f2579],[d2581,f2580],[d2581,f2581],[d2583,f2582],[d2583,f2583],[d2585,f2584],[d2585,f2585],[d2587,f2586],[d2587,f2587],[d2589,f2588],[d2589,f2589],[d2591,f2590],[d2591,f2591],[d2593,f2592],[d2593,f2593],[d2595,f2594],[d2595,f2595],[d2597,f2596],[d2597,f2597],[d2599,f2598],[d2599,f2599],[d2601,f2600],[d2601,f2601],[d2603,f2602],[d2603,f2603],[d2605,f2604],[d2605,f2605],[d2607,f2606],[d2607,f2607],[d2609,f2608],[d2609,f2609],[d2611,f2610],[d2611,f2611],[d2613,f2612],[d2613,f2613],[d2615,f2614],[d2615,f2615],[d2617,f2616],[d2617,f2617],[d2619,f2618],[d2619,f2619],[d2621,f2620],[d2621,f2621],[d2623,f2622],[d2623,f2623],[d2625,f2624],[d2625,f2625],[d2627,f2626],[d2627,f2627],[d2629,f2628],[d2629,f2629],[d2631,f2630],[d2631,f2631],[d2633,f2632],[d2633,f2633],[d2635,f2634],[d2635,f2635],[d2637,f2636],[d2637,f2637],[d2639,f2638],[d2639,f2639],[d2641,f2640],[d2641,f2641],[d2643,f2642],[d2643,f2643],[d2645,f2644],[d2645,f2645],[d2647,f2646],[d2647,f2647],[d2649,f2648],[d2649,f2649],[d2651,f2650],[d2651,f2651],[d2653,f2652],[d2653,f2653],[d2655,f2654],[d2655,f2655],[d2657,f2656],[d2657,f2657],[d2659,f2658],[d2659,f2659],[d2661,f2660],[d2661,f2661],[d2663,f2662],[d2663,f2663],[d2665,f2664],[d2665,f2665],[d2667,f2666],[d2667,f2667],[d2669,f2668],[d2669,f2669],[d2671,f2670],[d2671,f2671],[d2673,f2672],[d2673,f2673],[d2675,f2674],[d2675,f2675],[d2677,f2676],[d2677,f2677],[d2679,f2678],[d2679,f2679],[d2681,f2680],[d2681,f2681],[d2683,f2682],[d2683,f2683],[d2685,f2684],[d2685,f2685],[d2687,f2686],[d2687,f2687],[d2689,f2688],[d2689,f2689],[d2691,f2690],[d2691,f2691],[d2693,f2692],[d2693,f2693],[d2695,f2694],[d2695,f2695],[d2697,f2696],[d2697,f2697],[d2699,f2698],[d2699,f2699],[d2701,f2700],[d2701,f2701],[d2703,f2702],[d2703,f2703],[d2705,f2704],[d2705,f2705],[d2707,f2706],[d2707,f2707],[d2709,f2708],[d2709,f2709],[d2711,f2710],[d2711,f2711],[d2713,f2712],[d2713,f2713],[d2715,f2714],[d2715,f2715],[d2717,f2716],[d2717,f2717],[d2719,f2718],[d2719,f2719],[d2721,f2720],[d2721,f2721],[d2723,f2722],[d2723,f2723],[d2725,f2724],[d2725,f2725],[d2727,f2726],[d2727,f2727],[d2729,f2728],[d2729,f2729],[d2731,f2730],[d2731,f2731],[d2733,f2732],[d2733,f2733],[d2735,f2734],[d2735,f2735],[d2737,f2736],[d2737,f2737],[d2739,f2738],[d2739,f2739],[d2741,f2740],[d2741,f2741],[d2743,f2742],[d2743,f2743],[d2745,f2744],[d2745,f2745],[d2747,f2746],[d2747,f2747],[d2749,f2748],[d2749,f2749],[d2751,f2750],[d2751,f2751],[d2753,f2752],[d2753,f2753],[d2755,f2754],[d2755,f2755],[d2757,f2756],[d2757,f2757],[d2759,f2758],[d2759,f2759],[d2761,f2760],[d2761,f2761],[d2763,f2762],[d2763,f2763],[d2765,f2764],[d2765,f2765],[d2767,f2766],[d2767,f2767],[d2769,f2768],[d2769,f2769],[d2771,f2770],[d2771,f2771],[d2773,f2772],[d2773,f2773],[d2775,f2774],[d2775,f2775],[d2777,f2776],[d2777,f2777],[d2779,f2778],[d2779,f2779],[d2781,f2780],[d2781,f2781],[d2783,f2782],[d2783,f2783],[d2785,f2784],[d2785,f2785],[d2787,f2786],[d2787,f2787],[d2789,f2788],[d2789,f2789],[d2791,f2790],[d2791,f2791],[d2793,f2792],[d2793,f2793],[d2795,f2794],[d2795,f2795],[d2797,f2796],[d2797,f2797],[d2799,f2798],[d2799,f2799],[d2801,f2800],[d2801,f2801],[d2803,f2802],[d2803,f2803],[d2805,f2804],[d2805,f2805],[d2807,f2806],[d2807,f2807],[d2809,f2808],[d2809,f2809],[d2811,f2810],[d2811,f2811],[d2813,f2812],[d2813,f2813],[d2815,f2814],[d2815,f2815],[d2817,f2816],[d2817,f2817],[d2819,f2818],[d2819,f2819],[d2821,f2820],[d2821,f2821],[d2823,f2822],[d2823,f2823],[d2825,f2824],[d2825,f2825],[d2827,f2826],[d2827,f2827],[d2829,f2828],[d2829,f2829],[d2831,f2830],[d2831,f2831],[d2833,f2832],[d2833,f2833],[d2835,f2834],[d2835,f2835],[d2837,f2836],[d2837,f2837],[d2839,f2838],[d2839,f2839],[d2841,f2840],[d2841,f2841],[d2843,f2842],[d2843,f2843],[d2845,f2844],[d2845,f2845],[d2847,f2846],[d2847,f2847],[d2849,f2848],[d2849,f2849],[d2851,f2850],[d2851,f2851],[d2853,f2852],[d2853,f2853],[d2855,f2854],[d2855,f2855],[d2857,f2856],[d2857,f2857],[d2859,f2858],[d2859,f2859],[d2861,f2860],[d2861,f2861],[d2863,f2862],[d2863,f2863],[d2865,f2864],[d2865,f2865],[d2867,f2866],[d2867,f2867],[d2869,f2868],[d2869,f2869],[d2871,f2870],[d2871,f2871],[d2873,f2872],[d2873,f2873],[d2875,f2874],[d2875,f2875],[d2877,f2876],[d2877,f2877],[d2879,f2878],[d2879,f2879],[d2881,f2880],[d2881,f2881],[d2883,f2882],[d2883,f2883],[d2885,f2884],[d2885,f2885],[d2887,f2886],[d2887,f2887],[d2889,f2888],[d2889,f2889],[d2891,f2890],[d2891,f2891],[d2893,f2892],[d2893,f2893],[d2895,f2894],[d2895,f2895],[d2897,f2896],[d2897,f2897],[d2899,f2898],[d2899,f2899],[d2901,f2900],[d2901,f2901],[d2903,f2902],[d2903,f2903],[d2905,f2904],[d2905,f2905],[d2907,f2906],[d2907,f2907],[d2909,f2908],[d2909,f2909],[d2911,f2910],[d2911,f2911],[d2913,f2912],[d2913,f2913],[d2915,f2914],[d2915,f2915],[d2917,f2916],[d2917,f2917],[d2919,f2918],[d2919,f2919],[d2921,f2920],[d2921,f2921],[d2923,f2922],[d2923,f2923],[d2925,f2924],[d2925,f2925],[d2927,f2926],[d2927,f2927],[d2929,f2928],[d2929,f2929],[d2931,f2930],[d2931,f2931],[d2933,f2932],[d2933,f2933],[d2935,f2934],[d2935,f2935],[d2937,f2936],[d2937,f2937],[d2939,f2938],[d2939,f2939],[d2941,f2940],[d2941,f2941],[d2943,f2942],[d2943,f2943],[d2945,f2944],[d2945,f2945],[d2947,f2946],[d2947,f2947],[d2949,f2948],[d2949,f2949],[d2951,f2950],[d2951,f2951],[d2953,f2952],[d2953,f2953],[d2955,f2954],[d2955,f2955],[d2957,f2956],[d2957,f2957],[d2959,f2958],[d2959,f2959],[d2961,f2960],[d2961,f2961],[d2963,f2962],[d2963,f2963],[d2965,f2964],[d2965,f2965],[d2967,f2966],[d2967,f2967],[d2969,f2968],[d2969,f2969],[d2971,f2970],[d2971,f2971],[d2973,f2972],[d2973,f2973],[d2975,f2974],[d2975,f2975],[d2977,f2976],[d2977,f2977],[d2979,f2978],[d2979,f2979],[d2981,f2980],[d2981,f2981],[d2983,f2982],[d2983,f2983],[d2985,f2984],[d2985,f2985],[d2987,f2986],[d2987,f2987],[d2989,f2988],[d2989,f2989],[d2991,f2990],[d2991,f2991],[d2993,f2992],[d2993,f2993],[d2995,f2994],[d2995,f2995],[d2997,f2996],[d2997,f2997],[d2999,f2998],[d2999,f2999],[d3001,f3000],[d3001,f3001],[d3003,f3002],[d3003,f3003],[d3005,f3004],[d3005,f3005],[d3007,f3006],[d3007,f3007],[d3009,f3008],[d3009,f3009],[d3011,f3010],[d3011,f3011],[d3013,f3012],[d3013,f3013],[d3015,f3014],[d3015,f3015],[d3017,f3016],[d3017,f3017],[d3019,f3018],[d3019,f3019],[d3021,f3020],[d3021,f3021],[d3023,f3022],[d3023,f3023],[d3025,f3024],[d3025,f3025],[d3027,f3026],[d3027,f3027],[d3029,f3028],[d3029,f3029],[d3031,f3030],[d3031,f3031],[d3033,f3032],[d3033,f3033],[d3035,f3034],[d3035,f3035],[d3037,f3036],[d3037,f3037],[d3039,f3038],[d3039,f3039],[d3041,f3040],[d3041,f3041],[d3043,f3042],[d3043,f3043],[d3045,f3044],[d3045,f3045],[d3047,f3046],[d3047,f3047],[d3049,f3048],[d3049,f3049],[d3051,f3050],[d3051,f3051],[d3053,f3052],[d3053,f3053],[d3055,f3054],[d3055,f3055],[d3057,f3056],[d3057,f3057],[d3059,f3058],[d3059,f3059],[d3061,f3060],[d3061,f3061],[d3063,f3062],[d3063,f3063],[d3065,f3064],[d3065,f3065],[d3067,f3066],[d3067,f3067],[d3069,f3068],[d3069,f3069],[d3071,f3070],[d3071,f3071],[d3073,f3072],[d3073,f3073],[d3075,f3074],[d3075,f3075],[d3077,f3076],[d3077,f3077],[d3079,f3078],[d3079,f3079],[d3081,f3080],[d3081,f3081],[d3083,f3082],[d3083,f3083],[d3085,f3084],[d3085,f3085],[d3087,f3086],[d3087,f3087],[d3089,f3088],[d3089,f3089],[d3091,f3090],[d3091,f3091],[d3093,f3092],[d3093,f3093],[d3095,f3094],[d3095,f3095],[d3097,f3096],[d3097,f3097],[d3099,f3098],[d3099,f3099],[d3101,f3100],[d3101,f3101],[d3103,f3102],[d3103,f3103],[d3105,f3104],[d3105,f3105],[d3107,f3106],[d3107,f3107],[d3109,f3108],[d3109,f3109],[d3111,f3110],[d3111,f3111],[d3113,f3112],[d3113,f3113],[d3115,f3114],[d3115,f3115],[d3117,f3116],[d3117,f3117],[d3119,f3118],[d3119,f3119],[d3121,f3120],[d3121,f3121],[d3123,f3122],[d3123,f3123],[d3125,f3124],[d3125,f3125],[d3127,f3126],[d3127,f3127],[d3129,f3128],[d3129,f3129],[d3131,f3130],[d3131,f3131],[d3133,f3132],[d3133,f3133],[d3135,f3134],[d3135,f3135],[d3137,f3136],[d3137,f3137],[d3139,f3138],[d3139,f3139],[d3141,f3140],[d3141,f3141],[d3143,f3142],[d3143,f3143],[d3145,f3144],[d3145,f3145],[d3147,f3146],[d3147,f3147],[d3149,f3148],[d3149,f3149],[d3151,f3150],[d3151,f3151],[d3153,f3152],[d3153,f3153],[d3155,f3154],[d3155,f3155],[d3157,f3156],[d3157,f3157],[d3159,f3158],[d3159,f3159],[d3161,f3160],[d3161,f3161],[d3163,f3162],[d3163,f3163],[d3165,f3164],[d3165,f3165],[d3167,f3166],[d3167,f3167],[d3169,f3168],[d3169,f3169],[d3171,f3170],[d3171,f3171],[d3173,f3172],[d3173,f3173],[d3175,f3174],[d3175,f3175],[d3177,f3176],[d3177,f3177],[d3179,f3178],[d3179,f3179],[d3181,f3180],[d3181,f3181],[d3183,f3182],[d3183,f3183],[d3185,f3184],[d3185,f3185],[d3187,f3186],[d3187,f3187],[d3189,f3188],[d3189,f3189],[d3191,f3190],[d3191,f3191],[d3193,f3192],[d3193,f3193],[d3195,f3194],[d3195,f3195],[d3197,f3196],[d3197,f3197],[d3199,f3198],[d3199,f3199],[d3201,f3200],[d3201,f3201],[d3203,f3202],[d3203,f3203],[d3205,f3204],[d3205,f3205],[d3207,f3206],[d3207,f3207],[d3209,f3208],[d3209,f3209],[d3211,f3210],[d3211,f3211],[d3213,f3212],[d3213,f3213],[d3215,f3214],[d3215,f3215],[d3217,f3216],[d3217,f3217],[d3219,f3218],[d3219,f3219],[d3221,f3220],[d3221,f3221],[d3223,f3222],[d3223,f3223],[d3225,f3224],[d3225,f3225],[d3227,f3226],[d3227,f3227],[d3229,f3228],[d3229,f3229],[d3231,f3230],[d3231,f3231],[d3233,f3232],[d3233,f3233],[d3235,f3234],[d3235,f3235],[d3237,f3236],[d3237,f3237],[d3239,f3238],[d3239,f3239],[d3241,f3240],[d3241,f3241],[d3243,f3242],[d3243,f3243],[d3245,f3244],[d3245,f3245],[d3247,f3246],[d3247,f3247],[d3249,f3248],[d3249,f3249],[d3251,f3250],[d3251,f3251],[d3253,f3252],[d3253,f3253],[d3255,f3254],[d3255,f3255],[d3257,f3256],[d3257,f3257],[d3259,f3258],[d3259,f3259],[d3261,f3260],[d3261,f3261],[d3263,f3262],[d3263,f3263],[d3265,f3264],[d3265,f3265],[d3267,f3266],[d3267,f3267],[d3269,f3268],[d3269,f3269],[d3271,f3270],[d3271,f3271],[d3273,f3272],[d3273,f3273],[d3275,f3274],[d3275,f3275],[d3277,f3276],[d3277,f3277],[d3279,f3278],[d3279,f3279],[d3281,f3280],[d3281,f3281],[d3283,f3282],[d3283,f3283],[d3285,f3284],[d3285,f3285],[d3287,f3286],[d3287,f3287],[d3289,f3288],[d3289,f3289],[d3291,f3290],[d3291,f3291],[d3293,f3292],[d3293,f3293],[d3295,f3294],[d3295,f3295],[d3297,f3296],[d3297,f3297],[d3299,f3298],[d3299,f3299],[d3301,f3300],[d3301,f3301],[d3303,f3302],[d3303,f3303],[d3305,f3304],[d3305,f3305],[d3307,f3306],[d3307,f3307],[d3309,f3308],[d3309,f3309],[d3311,f3310],[d3311,f3311],[d3313,f3312],[d3313,f3313],[d3315,f3314],[d3315,f3315],[d3317,f3316],[d3317,f3317],[d3319,f3318],[d3319,f3319],[d3321,f3320],[d3321,f3321],[d3323,f3322],[d3323,f3323],[d3325,f3324],[d3325,f3325],[d3327,f3326],[d3327,f3327],[d3329,f3328],[d3329,f3329],[d3331,f3330],[d3331,f3331],[d3333,f3332],[d3333,f3333],[d3335,f3334],[d3335,f3335],[d3337,f3336],[d3337,f3337],[d3339,f3338],[d3339,f3339],[d3341,f3340],[d3341,f3341],[d3343,f3342],[d3343,f3343],[d3345,f3344],[d3345,f3345],[d3347,f3346],[d3347,f3347],[d3349,f3348],[d3349,f3349],[d3351,f3350],[d3351,f3351],[d3353,f3352],[d3353,f3353],[d3355,f3354],[d3355,f3355],[d3357,f3356],[d3357,f3357],[d3359,f3358],[d3359,f3359],[d3361,f3360],[d3361,f3361],[d3363,f3362],[d3363,f3363],[d3365,f3364],[d3365,f3365],[d3367,f3366],[d3367,f3367],[d3369,f3368],[d3369,f3369],[d3371,f3370],[d3371,f3371],[d3373,f3372],[d3373,f3373],[d3375,f3374],[d3375,f3375],[d3377,f3376],[d3377,f3377],[d3379,f3378],[d3379,f3379],[d3381,f3380],[d3381,f3381],[d3383,f3382],[d3383,f3383],[d3385,f3384],[d3385,f3385],[d3387,f3386],[d3387,f3387],[d3389,f3388],[d3389,f3389],[d3391,f3390],[d3391,f3391],[d3393,f3392],[d3393,f3393],[d3395,f3394],[d3395,f3395],[d3397,f3396],[d3397,f3397],[d3399,f3398],[d3399,f3399],[d3401,f3400],[d3401,f3401],[d3403,f3402],[d3403,f3403],[d3405,f3404],[d3405,f3405],[d3407,f3406],[d3407,f3407],[d3409,f3408],[d3409,f3409],[d3411,f3410],[d3411,f3411],[d3413,f3412],[d3413,f3413],[d3415,f3414],[d3415,f3415],[d3417,f3416],[d3417,f3417],[d3419,f3418],[d3419,f3419],[d3421,f3420],[d3421,f3421],[d3423,f3422],[d3423,f3423],[d3425,f3424],[d3425,f3425],[d3427,f3426],[d3427,f3427],[d3429,f3428],[d3429,f3429],[d3431,f3430],[d3431,f3431],[d3433,f3432],[d3433,f3433],[d3435,f3434],[d3435,f3435],[d3437,f3436],[d3437,f3437],[d3439,f3438],[d3439,f3439],[d3441,f3440],[d3441,f3441],[d3443,f3442],[d3443,f3443],[d3445,f3444],[d3445,f3445],[d3447,f3446],[d3447,f3447],[d3449,f3448],[d3449,f3449],[d3451,f3450],[d3451,f3451],[d3453,f3452],[d3453,f3453],[d3455,f3454],[d3455,f3455],[d3457,f3456],[d3457,f3457],[d3459,f3458],[d3459,f3459],[d3461,f3460],[d3461,f3461],[d3463,f3462],[d3463,f3463],[d3465,f3464],[d3465,f3465],[d3467,f3466],[d3467,f3467],[d3469,f3468],[d3469,f3469],[d3471,f3470],[d3471,f3471],[d3473,f3472],[d3473,f3473],[d3475,f3474],[d3475,f3475],[d3477,f3476],[d3477,f3477],[d3479,f3478],[d3479,f3479],[d3481,f3480],[d3481,f3481],[d3483,f3482],[d3483,f3483],[d3485,f3484],[d3485,f3485],[d3487,f3486],[d3487,f3487],[d3489,f3488],[d3489,f3489],[d3491,f3490],[d3491,f3491],[d3493,f3492],[d3493,f3493],[d3495,f3494],[d3495,f3495],[d3497,f3496],[d3497,f3497],[d3499,f3498],[d3499,f3499],[d3501,f3500],[d3501,f3501],[d3503,f3502],[d3503,f3503],[d3505,f3504],[d3505,f3505],[d3507,f3506],[d3507,f3507],[d3509,f3508],[d3509,f3509],[d3511,f3510],[d3511,f3511],[d3513,f3512],[d3513,f3513],[d3515,f3514],[d3515,f3515],[d3517,f3516],[d3517,f3517],[d3519,f3518],[d3519,f3519],[d3521,f3520],[d3521,f3521],[d3523,f3522],[d3523,f3523],[d3525,f3524],[d3525,f3525],[d3527,f3526],[d3527,f3527],[d3529,f3528],[d3529,f3529],[d3531,f3530],[d3531,f3531],[d3533,f3532],[d3533,f3533],[d3535,f3534],[d3535,f3535],[d3537,f3536],[d3537,f3537],[d3539,f3538],[d3539,f3539],[d3541,f3540],[d3541,f3541],[d3543,f3542],[d3543,f3543],[d3545,f3544],[d3545,f3545],[d3547,f3546],[d3547,f3547],[d3549,f3548],[d3549,f3549],[d3551,f3550],[d3551,f3551],[d3553,f3552],[d3553,f3553],[d3555,f3554],[d3555,f3555],[d3557,f3556],[d3557,f3557],[d3559,f3558],[d3559,f3559],[d3561,f3560],[d3561,f3561],[d3563,f3562],[d3563,f3563],[d3565,f3564],[d3565,f3565],[d3567,f3566],[d3567,f3567],[d3569,f3568],[d3569,f3569],[d3571,f3570],[d3571,f3571],[d3573,f3572],[d3573,f3573],[d3575,f3574],[d3575,f3575],[d3577,f3576],[d3577,f3577],[d3579,f3578],[d3579,f3579],[d3581,f3580],[d3581,f3581],[d3583,f3582],[d3583,f3583],[d3585,f3584],[d3585,f3585],[d3587,f3586],[d3587,f3587],[d3589,f3588],[d3589,f3589],[d3591,f3590],[d3591,f3591],[d3593,f3592],[d3593,f3593],[d3595,f3594],[d3595,f3595],[d3597,f3596],[d3597,f3597],[d3599,f3598],[d3599,f3599],[d3601,f3600],[d3601,f3601],[d3603,f3602],[d3603,f3603],[d3605,f3604],[d3605,f3605],[d3607,f3606],[d3607,f3607],[d3609,f3608],[d3609,f3609],[d3611,f3610],[d3611,f3611],[d3613,f3612],[d3613,f3613],[d3615,f3614],[d3615,f3615],[d3617,f3616],[d3617,f3617],[d3619,f3618],[d3619,f3619],[d3621,f3620],[d3621,f3621],[d3623,f3622],[d3623,f3623],[d3625,f3624],[d3625,f3625],[d3627,f3626],[d3627,f3627],[d3629,f3628],[d3629,f3629],[d3631,f3630],[d3631,f3631],[d3633,f3632],[d3633,f3633],[d3635,f3634],[d3635,f3635],[d3637,f3636],[d3637,f3637],[d3639,f3638],[d3639,f3639],[d3641,f3640],[d3641,f3641],[d3643,f3642],[d3643,f3643],[d3645,f3644],[d3645,f3645],[d3647,f3646],[d3647,f3647],[d3649,f3648],[d3649,f3649],[d3651,f3650],[d3651,f3651],[d3653,f3652],[d3653,f3653],[d3655,f3654],[d3655,f3655],[d3657,f3656],[d3657,f3657],[d3659,f3658],[d3659,f3659],[d3661,f3660],[d3661,f3661],[d3663,f3662],[d3663,f3663],[d3665,f3664],[d3665,f3665],[d3667,f3666],[d3667,f3667],[d3669,f3668],[d3669,f3669],[d3671,f3670],[d3671,f3671],[d3673,f3672],[d3673,f3673],[d3675,f3674],[d3675,f3675],[d3677,f3676],[d3677,f3677],[d3679,f3678],[d3679,f3679],[d3681,f3680],[d3681,f3681],[d3683,f3682],[d3683,f3683],[d3685,f3684],[d3685,f3685],[d3687,f3686],[d3687,f3687],[d3689,f3688],[d3689,f3689],[d3691,f3690],[d3691,f3691],[d3693,f3692],[d3693,f3693],[d3695,f3694],[d3695,f3695],[d3697,f3696],[d3697,f3697],[d3699,f3698],[d3699,f3699],[d3701,f3700],[d3701,f3701],[d3703,f3702],[d3703,f3703],[d3705,f3704],[d3705,f3705],[d3707,f3706],[d3707,f3707],[d3709,f3708],[d3709,f3709],[d3711,f3710],[d3711,f3711],[d3713,f3712],[d3713,f3713],[d3715,f3714],[d3715,f3715],[d3717,f3716],[d3717,f3717],[d3719,f3718],[d3719,f3719],[d3721,f3720],[d3721,f3721],[d3723,f3722],[d3723,f3723],[d3725,f3724],[d3725,f3725],[d3727,f3726],[d3727,f3727],[d3729,f3728],[d3729,f3729],[d3731,f3730],[d3731,f3731],[d3733,f3732],[d3733,f3733],[d3735,f3734],[d3735,f3735],[d3737,f3736],[d3737,f3737],[d3739,f3738],[d3739,f3739],[d3741,f3740],[d3741,f3741],[d3743,f3742],[d3743,f3743],[d3745,f3744],[d3745,f3745],[d3747,f3746],[d3747,f3747],[d3749,f3748],[d3749,f3749],[d3751,f3750],[d3751,f3751],[d3753,f3752],[d3753,f3753],[d3755,f3754],[d3755,f3755],[d3757,f3756],[d3757,f3757],[d3759,f3758],[d3759,f3759],[d3761,f3760],[d3761,f3761],[d3763,f3762],[d3763,f3763],[d3765,f3764],[d3765,f3765],[d3767,f3766],[d3767,f3767],[d3769,f3768],[d3769,f3769],[d3771,f3770],[d3771,f3771],[d3773,f3772],[d3773,f3773],[d3775,f3774],[d3775,f3775],[d3777,f3776],[d3777,f3777],[d3779,f3778],[d3779,f3779],[d3781,f3780],[d3781,f3781],[d3783,f3782],[d3783,f3783],[d3785,f3784],[d3785,f3785],[d3787,f3786],[d3787,f3787],[d3789,f3788],[d3789,f3789],[d3791,f3790],[d3791,f3791],[d3793,f3792],[d3793,f3793],[d3795,f3794],[d3795,f3795],[d3797,f3796],[d3797,f3797],[d3799,f3798],[d3799,f3799],[d3801,f3800],[d3801,f3801],[d3803,f3802],[d3803,f3803],[d3805,f3804],[d3805,f3805],[d3807,f3806],[d3807,f3807],[d3809,f3808],[d3809,f3809],[d3811,f3810],[d3811,f3811],[d3813,f3812],[d3813,f3813],[d3815,f3814],[d3815,f3815],[d3817,f3816],[d3817,f3817],[d3819,f3818],[d3819,f3819],[d3821,f3820],[d3821,f3821],[d3823,f3822],[d3823,f3823],[d3825,f3824],[d3825,f3825],[d3827,f3826],[d3827,f3827],[d3829,f3828],[d3829,f3829],[d3831,f3830],[d3831,f3831],[d3833,f3832],[d3833,f3833],[d3835,f3834],[d3835,f3835],[d3837,f3836],[d3837,f3837],[d3839,f3838],[d3839,f3839],[d3841,f3840],[d3841,f3841],[d3843,f3842],[d3843,f3843],[d3845,f3844],[d3845,f3845],[d3847,f3846],[d3847,f3847],[d3849,f3848],[d3849,f3849],[d3851,f3850],[d3851,f3851],[d3853,f3852],[d3853,f3853],[d3855,f3854],[d3855,f3855],[d3857,f3856],[d3857,f3857],[d3859,f3858],[d3859,f3859],[d3861,f3860],[d3861,f3861],[d3863,f3862],[d3863,f3863],[d3865,f3864],[d3865,f3865],[d3867,f3866],[d3867,f3867],[d3869,f3868],[d3869,f3869],[d3871,f3870],[d3871,f3871],[d3873,f3872],[d3873,f3873],[d3875,f3874],[d3875,f3875],[d3877,f3876],[d3877,f3877],[d3879,f3878],[d3879,f3879],[d3881,f3880],[d3881,f3881],[d3883,f3882],[d3883,f3883],[d3885,f3884],[d3885,f3885],[d3887,f3886],[d3887,f3887],[d3889,f3888],[d3889,f3889],[d3891,f3890],[d3891,f3891],[d3893,f3892],[d3893,f3893],[d3895,f3894],[d3895,f3895],[d3897,f3896],[d3897,f3897],[d3899,f3898],[d3899,f3899],[d3901,f3900],[d3901,f3901],[d3903,f3902],[d3903,f3903],[d3905,f3904],[d3905,f3905],[d3907,f3906],[d3907,f3907],[d3909,f3908],[d3909,f3909],[d3911,f3910],[d3911,f3911],[d3913,f3912],[d3913,f3913],[d3915,f3914],[d3915,f3915],[d3917,f3916],[d3917,f3917],[d3919,f3918],[d3919,f3919],[d3921,f3920],[d3921,f3921],[d3923,f3922],[d3923,f3923],[d3925,f3924],[d3925,f3925],[d3927,f3926],[d3927,f3927],[d3929,f3928],[d3929,f3929],[d3931,f3930],[d3931,f3931],[d3933,f3932],[d3933,f3933],[d3935,f3934],[d3935,f3935],[d3937,f3936],[d3937,f3937],[d3939,f3938],[d3939,f3939],[d3941,f3940],[d3941,f3941],[d3943,f3942],[d3943,f3943],[d3945,f3944],[d3945,f3945],[d3947,f3946],[d3947,f3947],[d3949,f3948],[d3949,f3949],[d3951,f3950],[d3951,f3951],[d3953,f3952],[d3953,f3953],[d3955,f3954],[d3955,f3955],[d3957,f3956],[d3957,f3957],[d3959,f3958],[d3959,f3959],[d3961,f3960],[d3961,f3961],[d3963,f3962],[d3963,f3963],[d3965,f3964],[d3965,f3965],[d3967,f3966],[d3967,f3967],[d3969,f3968],[d3969,f3969],[d3971,f3970],[d3971,f3971],[d3973,f3972],[d3973,f3973],[d3975,f3974],[d3975,f3975],[d3977,f3976],[d3977,f3977],[d3979,f3978],[d3979,f3979],[d3981,f3980],[d3981,f3981],[d3983,f3982],[d3983,f3983],[d3985,f3984],[d3985,f3985],[d3987,f3986],[d3987,f3987],[d3989,f3988],[d3989,f3989],[d3991,f3990],[d3991,f3991],[d3993,f3992],[d3993,f3993],[d3995,f3994],[d3995,f3995],[d3997,f3996],[d3997,f3997],[d3999,f3998],[d3999,f3999],[d4001,f4000],[d4001,f4001],[d4003,f4002],[d4003,f4003],[d4005,f4004],[d4005,f4005],[d4007,f4006],[d4007,f4007],[d4009,f4008],[d4009,f4009],[d4011,f4010],[d4011,f4011],[d4013,f4012],[d4013,f4013],[d4015,f4014],[d4015,f4015],[d4017,f4016],[d4017,f4017],[d4019,f4018],[d4019,f4019],[d4021,f4020],[d4021,f4021],[d4023,f4022],[d4023,f4023],[d4025,f4024],[d4025,f4025],[d4027,f4026],[d4027,f4027],[d4029,f4028],[d4029,f4029],[d4031,f4030],[d4031,f4031],[d4033,f4032],[d4033,f4033],[d4035,f4034],[d4035,f4035],[d4037,f4036],[d4037,f4037],[d4039,f4038],[d4039,f4039],[d4041,f4040],[d4041,f4041],[d4043,f4042],[d4043,f4043],[d4045,f4044],[d4045,f4045],[d4047,f4046],[d4047,f4047],[d4049,f4048],[d4049,f4049],[d4051,f4050],[d4051,f4051],[d4053,f4052],[d4053,f4053],[d4055,f4054],[d4055,f4055],[d4057,f4056],[d4057,f4057],[d4059,f4058],[d4059,f4059],[d4061,f4060],[d4061,f4061],[d4063,f4062],[d4063,f4063],[d4065,f4064],[d4065,f4065],[d4067,f4066],[d4067,f4067],[d4069,f4068],[d4069,f4069],[d4071,f4070],[d4071,f4071],[d4073,f4072],[d4073,f4073],[d4075,f4074],[d4075,f4075],[d4077,f4076],[d4077,f4077],[d4079,f4078],[d4079,f4079],[d4081,f4080],[d4081,f4081],[d4083,f4082],[d4083,f4083],[d4085,f4084],[d4085,f4085],[d4087,f4086],[d4087,f4087],[d4089,f4088],[d4089,f4089],[d4091,f4090],[d4091,f4091],[d4093,f4092],[d4093,f4093],[d4095,f4094],[d4095,f4095],[d4097,f4096],[d4097,f4097],[d4099,f4098],[d4099,f4099],[d4101,f4100],[d4101,f4101],[d4103,f4102],[d4103,f4103],[d4105,f4104],[d4105,f4105],[d4107,f4106],[d4107,f4107],[d4109,f4108],[d4109,f4109],[d4111,f4110],[d4111,f4111],[d4113,f4112],[d4113,f4113],[d4115,f4114],[d4115,f4115],[d4117,f4116],[d4117,f4117],[d4119,f4118],[d4119,f4119],[d4121,f4120],[d4121,f4121],[d4123,f4122],[d4123,f4123],[d4125,f4124],[d4125,f4125],[d4127,f4126],[d4127,f4127],[d4129,f4128],[d4129,f4129],[d4131,f4130],[d4131,f4131],[d4133,f4132],[d4133,f4133],[d4135,f4134],[d4135,f4135],[d4137,f4136],[d4137,f4137],[d4139,f4138],[d4139,f4139],[d4141,f4140],[d4141,f4141],[d4143,f4142],[d4143,f4143],[d4145,f4144],[d4145,f4145],[d4147,f4146],[d4147,f4147],[d4149,f4148],[d4149,f4149],[d4151,f4150],[d4151,f4151],[d4153,f4152],[d4153,f4153],[d4155,f4154],[d4155,f4155],[d4157,f4156],[d4157,f4157],[d4159,f4158],[d4159,f4159],[d4161,f4160],[d4161,f4161],[d4163,f4162],[d4163,f4163],[d4165,f4164],[d4165,f4165],[d4167,f4166],[d4167,f4167],[d4169,f4168],[d4169,f4169],[d4171,f4170],[d4171,f4171],[d4173,f4172],[d4173,f4173],[d4175,f4174],[d4175,f4175],[d4177,f4176],[d4177,f4177],[d4179,f4178],[d4179,f4179],[d4181,f4180],[d4181,f4181],[d4183,f4182],[d4183,f4183],[d4185,f4184],[d4185,f4185],[d4187,f4186],[d4187,f4187],[d4189,f4188],[d4189,f4189],[d4191,f4190],[d4191,f4191],[d4193,f4192],[d4193,f4193],[d4195,f4194],[d4195,f4195],[d4197,f4196],[d4197,f4197],[d4199,f4198],[d4199,f4199],[d4201,f4200],[d4201,f4201],[d4203,f4202],[d4203,f4203],[d4205,f4204],[d4205,f4205],[d4207,f4206],[d4207,f4207],[d4209,f4208],[d4209,f4209],[d4211,f4210],[d4211,f4211],[d4213,f4212],[d4213,f4213],[d4215,f4214],[d4215,f4215],[d4217,f4216],[d4217,f4217],[d4219,f4218],[d4219,f4219],[d4221,f4220],[d4221,f4221],[d4223,f4222],[d4223,f4223],[d4225,f4224],[d4225,f4225],[d4227,f4226],[d4227,f4227],[d4229,f4228],[d4229,f4229],[d4231,f4230],[d4231,f4231],[d4233,f4232],[d4233,f4233],[d4235,f4234],[d4235,f4235],[d4237,f4236],[d4237,f4237],[d4239,f4238],[d4239,f4239],[d4241,f4240],[d4241,f4241],[d4243,f4242],[d4243,f4243],[d4245,f4244],[d4245,f4245],[d4247,f4246],[d4247,f4247],[d4249,f4248],[d4249,f4249],[d4251,f4250],[d4251,f4251],[d4253,f4252],[d4253,f4253],[d4255,f4254],[d4255,f4255],[d4257,f4256],[d4257,f4257],[d4259,f4258],[d4259,f4259],[d4261,f4260],[d4261,f4261],[d4263,f4262],[d4263,f4263],[d4265,f4264],[d4265,f4265],[d4267,f4266],[d4267,f4267],[d4269,f4268],[d4269,f4269],[d4271,f4270],[d4271,f4271],[d4273,f4272],[d4273,f4273],[d4275,f4274],[d4275,f4275],[d4277,f4276],[d4277,f4277],[d4279,f4278],[d4279,f4279],[d4281,f4280],[d4281,f4281],[d4283,f4282],[d4283,f4283],[d4285,f4284],[d4285,f4285],[d4287,f4286],[d4287,f4287],[d4289,f4288],[d4289,f4289],[d4291,f4290],[d4291,f4291],[d4293,f4292],[d4293,f4293],[d4295,f4294],[d4295,f4295],[d4297,f4296],[d4297,f4297],[d4299,f4298],[d4299,f4299],[d4301,f4300],[d4301,f4301],[d4303,f4302],[d4303,f4303],[d4305,f4304],[d4305,f4305],[d4307,f4306],[d4307,f4307],[d4309,f4308],[d4309,f4309],[d4311,f4310],[d4311,f4311],[d4313,f4312],[d4313,f4313],[d4315,f4314],[d4315,f4315],[d4317,f4316],[d4317,f4317],[d4319,f4318],[d4319,f4319],[d4321,f4320],[d4321,f4321],[d4323,f4322],[d4323,f4323],[d4325,f4324],[d4325,f4325],[d4327,f4326],[d4327,f4327],[d4329,f4328],[d4329,f4329],[d4331,f4330],[d4331,f4331],[d4333,f4332],[d4333,f4333],[d4335,f4334],[d4335,f4335],[d4337,f4336],[d4337,f4337],[d4339,f4338],[d4339,f4339],[d4341,f4340],[d4341,f4341],[d4343,f4342],[d4343,f4343],[d4345,f4344],[d4345,f4345],[d4347,f4346],[d4347,f4347],[d4349,f4348],[d4349,f4349],[d4351,f4350],[d4351,f4351],[d4353,f4352],[d4353,f4353],[d4355,f4354],[d4355,f4355],[d4357,f4356],[d4357,f4357],[d4359,f4358],[d4359,f4359],[d4361,f4360],[d4361,f4361],[d4363,f4362],[d4363,f4363],[d4365,f4364],[d4365,f4365],[d4367,f4366],[d4367,f4367],[d4369,f4368],[d4369,f4369],[d4371,f4370],[d4371,f4371],[d4373,f4372],[d4373,f4373],[d4375,f4374],[d4375,f4375],[d4377,f4376],[d4377,f4377],[d4379,f4378],[d4379,f4379],[d4381,f4380],[d4381,f4381],[d4383,f4382],[d4383,f4383],[d4385,f4384],[d4385,f4385],[d4387,f4386],[d4387,f4387],[d4389,f4388],[d4389,f4389],[d4391,f4390],[d4391,f4391],[d4393,f4392],[d4393,f4393],[d4395,f4394],[d4395,f4395],[d4397,f4396],[d4397,f4397],[d4399,f4398],[d4399,f4399],[d4401,f4400],[d4401,f4401],[d4403,f4402],[d4403,f4403],[d4405,f4404],[d4405,f4405],[d4407,f4406],[d4407,f4407],[d4409,f4408],[d4409,f4409],[d4411,f4410],[d4411,f4411],[d4413,f4412],[d4413,f4413],[d4415,f4414],[d4415,f4415],[d4417,f4416],[d4417,f4417],[d4419,f4418],[d4419,f4419],[d4421,f4420],[d4421,f4421],[d4423,f4422],[d4423,f4423],[d4425,f4424],[d4425,f4425],[d4427,f4426],[d4427,f4427],[d4429,f4428],[d4429,f4429],[d4431,f4430],[d4431,f4431],[d4433,f4432],[d4433,f4433],[d4435,f4434],[d4435,f4435],[d4437,f4436],[d4437,f4437],[d4439,f4438],[d4439,f4439],[d4441,f4440],[d4441,f4441],[d4443,f4442],[d4443,f4443],[d4445,f4444],[d4445,f4445],[d4447,f4446],[d4447,f4447],[d4449,f4448],[d4449,f4449],[d4451,f4450],[d4451,f4451],[d4453,f4452],[d4453,f4453],[d4455,f4454],[d4455,f4455],[d4457,f4456],[d4457,f4457],[d4459,f4458],[d4459,f4459],[d4461,f4460],[d4461,f4461],[d4463,f4462],[d4463,f4463],[d4465,f4464],[d4465,f4465],[d4467,f4466],[d4467,f4467],[d4469,f4468],[d4469,f4469],[d4471,f4470],[d4471,f4471],[d4473,f4472],[d4473,f4473],[d4475,f4474],[d4475,f4475],[d4477,f4476],[d4477,f4477],[d4479,f4478],[d4479,f4479],[d4481,f4480],[d4481,f4481],[d4483,f4482],[d4483,f4483],[d4485,f4484],[d4485,f4485],[d4487,f4486],[d4487,f4487],[d4489,f4488],[d4489,f4489],[d4491,f4490],[d4491,f4491],[d4493,f4492],[d4493,f4493],[d4495,f4494],[d4495,f4495],[d4497,f4496],[d4497,f4497],[d4499,f4498],[d4499,f4499],[d4501,f4500],[d4501,f4501],[d4503,f4502],[d4503,f4503],[d4505,f4504],[d4505,f4505],[d4507,f4506],[d4507,f4507],[d4509,f4508],[d4509,f4509],[d4511,f4510],[d4511,f4511],[d4513,f4512],[d4513,f4513],[d4515,f4514],[d4515,f4515],[d4517,f4516],[d4517,f4517],[d4519,f4518],[d4519,f4519],[d4521,f4520],[d4521,f4521],[d4523,f4522],[d4523,f4523],[d4525,f4524],[d4525,f4525],[d4527,f4526],[d4527,f4527],[d4529,f4528],[d4529,f4529],[d4531,f4530],[d4531,f4531],[d4533,f4532],[d4533,f4533],[d4535,f4534],[d4535,f4535],[d4537,f4536],[d4537,f4537],[d4539,f4538],[d4539,f4539],[d4541,f4540],[d4541,f4541],[d4543,f4542],[d4543,f4543],[d4545,f4544],[d4545,f4545],[d4547,f4546],[d4547,f4547],[d4549,f4548],[d4549,f4549],[d4551,f4550],[d4551,f4551],[d4553,f4552],[d4553,f4553],[d4555,f4554],[d4555,f4555],[d4557,f4556],[d4557,f4557],[d4559,f4558],[d4559,f4559],[d4561,f4560],[d4561,f4561],[d4563,f4562],[d4563,f4563],[d4565,f4564],[d4565,f4565],[d4567,f4566],[d4567,f4567],[d4569,f4568],[d4569,f4569],[d4571,f4570],[d4571,f4571],[d4573,f4572],[d4573,f4573],[d4575,f4574],[d4575,f4575],[d4577,f4576],[d4577,f4577],[d4579,f4578],[d4579,f4579],[d4581,f4580],[d4581,f4581],[d4583,f4582],[d4583,f4583],[d4585,f4584],[d4585,f4585],[d4587,f4586],[d4587,f4587],[d4589,f4588],[d4589,f4589],[d4591,f4590],[d4591,f4591],[d4593,f4592],[d4593,f4593],[d4595,f4594],[d4595,f4595],[d4597,f4596],[d4597,f4597],[d4599,f4598],[d4599,f4599],[d4601,f4600],[d4601,f4601],[d4603,f4602],[d4603,f4603],[d4605,f4604],[d4605,f4605],[d4607,f4606],[d4607,f4607],[d4609,f4608],[d4609,f4609],[d4611,f4610],[d4611,f4611],[d4613,f4612],[d4613,f4613],[d4615,f4614],[d4615,f4615],[d4617,f4616],[d4617,f4617],[d4619,f4618],[d4619,f4619],[d4621,f4620],[d4621,f4621],[d4623,f4622],[d4623,f4623],[d4625,f4624],[d4625,f4625],[d4627,f4626],[d4627,f4627],[d4629,f4628],[d4629,f4629],[d4631,f4630],[d4631,f4631],[d4633,f4632],[d4633,f4633],[d4635,f4634],[d4635,f4635],[d4637,f4636],[d4637,f4637],[d4639,f4638],[d4639,f4639],[d4641,f4640],[d4641,f4641],[d4643,f4642],[d4643,f4643],[d4645,f4644],[d4645,f4645],[d4647,f4646],[d4647,f4647],[d4649,f4648],[d4649,f4649],[d4651,f4650],[d4651,f4651],[d4653,f4652],[d4653,f4653],[d4655,f4654],[d4655,f4655],[d4657,f4656],[d4657,f4657],[d4659,f4658],[d4659,f4659],[d4661,f4660],[d4661,f4661],[d4663,f4662],[d4663,f4663],[d4665,f4664],[d4665,f4665],[d4667,f4666],[d4667,f4667],[d4669,f4668],[d4669,f4669],[d4671,f4670],[d4671,f4671],[d4673,f4672],[d4673,f4673],[d4675,f4674],[d4675,f4675],[d4677,f4676],[d4677,f4677],[d4679,f4678],[d4679,f4679],[d4681,f4680],[d4681,f4681],[d4683,f4682],[d4683,f4683],[d4685,f4684],[d4685,f4685],[d4687,f4686],[d4687,f4687],[d4689,f4688],[d4689,f4689],[d4691,f4690],[d4691,f4691],[d4693,f4692],[d4693,f4693],[d4695,f4694],[d4695,f4695],[d4697,f4696],[d4697,f4697],[d4699,f4698],[d4699,f4699],[d4701,f4700],[d4701,f4701],[d4703,f4702],[d4703,f4703],[d4705,f4704],[d4705,f4705],[d4707,f4706],[d4707,f4707],[d4709,f4708],[d4709,f4709],[d4711,f4710],[d4711,f4711],[d4713,f4712],[d4713,f4713],[d4715,f4714],[d4715,f4715],[d4717,f4716],[d4717,f4717],[d4719,f4718],[d4719,f4719],[d4721,f4720],[d4721,f4721],[d4723,f4722],[d4723,f4723],[d4725,f4724],[d4725,f4725],[d4727,f4726],[d4727,f4727],[d4729,f4728],[d4729,f4729],[d4731,f4730],[d4731,f4731],[d4733,f4732],[d4733,f4733],[d4735,f4734],[d4735,f4735],[d4737,f4736],[d4737,f4737],[d4739,f4738],[d4739,f4739],[d4741,f4740],[d4741,f4741],[d4743,f4742],[d4743,f4743],[d4745,f4744],[d4745,f4745],[d4747,f4746],[d4747,f4747],[d4749,f4748],[d4749,f4749],[d4751,f4750],[d4751,f4751],[d4753,f4752],[d4753,f4753],[d4755,f4754],[d4755,f4755],[d4757,f4756],[d4757,f4757],[d4759,f4758],[d4759,f4759],[d4761,f4760],[d4761,f4761],[d4763,f4762],[d4763,f4763],[d4765,f4764],[d4765,f4765],[d4767,f4766],[d4767,f4767],[d4769,f4768],[d4769,f4769],[d4771,f4770],[d4771,f4771],[d4773,f4772],[d4773,f4773],[d4775,f4774],[d4775,f4775],[d4777,f4776],[d4777,f4777],[d4779,f4778],[d4779,f4779],[d4781,f4780],[d4781,f4781],[d4783,f4782],[d4783,f4783],[d4785,f4784],[d4785,f4785],[d4787,f4786],[d4787,f4787],[d4789,f4788],[d4789,f4789],[d4791,f4790],[d4791,f4791],[d4793,f4792],[d4793,f4793],[d4795,f4794],[d4795,f4795],[d4797,f4796],[d4797,f4797],[d4799,f4798],[d4799,f4799],[d4801,f4800],[d4801,f4801],[d4803,f4802],[d4803,f4803],[d4805,f4804],[d4805,f4805],[d4807,f4806],[d4807,f4807],[d4809,f4808],[d4809,f4809],[d4811,f4810],[d4811,f4811],[d4813,f4812],[d4813,f4813],[d4815,f4814],[d4815,f4815],[d4817,f4816],[d4817,f4817],[d4819,f4818],[d4819,f4819],[d4821,f4820],[d4821,f4821],[d4823,f4822],[d4823,f4823],[d4825,f4824],[d4825,f4825],[d4827,f4826],[d4827,f4827],[d4829,f4828],[d4829,f4829],[d4831,f4830],[d4831,f4831],[d4833,f4832],[d4833,f4833],[d4835,f4834],[d4835,f4835],[d4837,f4836],[d4837,f4837],[d4839,f4838],[d4839,f4839],[d4841,f4840],[d4841,f4841],[d4843,f4842],[d4843,f4843],[d4845,f4844],[d4845,f4845],[d4847,f4846],[d4847,f4847],[d4849,f4848],[d4849,f4849],[d4851,f4850],[d4851,f4851],[d4853,f4852],[d4853,f4853],[d4855,f4854],[d4855,f4855],[d4857,f4856],[d4857,f4857],[d4859,f4858],[d4859,f4859],[d4861,f4860],[d4861,f4861],[d4863,f4862],[d4863,f4863],[d4865,f4864],[d4865,f4865],[d4867,f4866],[d4867,f4867],[d4869,f4868],[d4869,f4869],[d4871,f4870],[d4871,f4871],[d4873,f4872],[d4873,f4873],[d4875,f4874],[d4875,f4875],[d4877,f4876],[d4877,f4877],[d4879,f4878],[d4879,f4879],[d4881,f4880],[d4881,f4881],[d4883,f4882],[d4883,f4883],[d4885,f4884],[d4885,f4885],[d4887,f4886],[d4887,f4887],[d4889,f4888],[d4889,f4889],[d4891,f4890],[d4891,f4891],[d4893,f4892],[d4893,f4893],[d4895,f4894],[d4895,f4895],[d4897,f4896],[d4897,f4897],[d4899,f4898],[d4899,f4899],[d4901,f4900],[d4901,f4901],[d4903,f4902],[d4903,f4903],[d4905,f4904],[d4905,f4905],[d4907,f4906],[d4907,f4907],[d4909,f4908],[d4909,f4909],[d4911,f4910],[d4911,f4911],[d4913,f4912],[d4913,f4913],[d4915,f4914],[d4915,f4915],[d4917,f4916],[d4917,f4917],[d4919,f4918],[d4919,f4919],[d4921,f4920],[d4921,f4921],[d4923,f4922],[d4923,f4923],[d4925,f4924],[d4925,f4925],[d4927,f4926],[d4927,f4927],[d4929,f4928],[d4929,f4929],[d4931,f4930],[d4931,f4931],[d4933,f4932],[d4933,f4933],[d4935,f4934],[d4935,f4935],[d4937,f4936],[d4937,f4937],[d4939,f4938],[d4939,f4939],[d4941,f4940],[d4941,f4941],[d4943,f4942],[d4943,f4943],[d4945,f4944],[d4945,f4945],[d4947,f4946],[d4947,f4947],[d4949,f4948],[d4949,f4949],[d4951,f4950],[d4951,f4951],[d4953,f4952],[d4953,f4953],[d4955,f4954],[d4955,f4955],[d4957,f4956],[d4957,f4957],[d4959,f4958],[d4959,f4959],[d4961,f4960],[d4961,f4961],[d4963,f4962],[d4963,f4963],[d4965,f4964],[d4965,f4965],[d4967,f4966],[d4967,f4967],[d4969,f4968],[d4969,f4969],[d4971,f4970],[d4971,f4971],[d4973,f4972],[d4973,f4973],[d4975,f4974],[d4975,f4975],[d4977,f4976],[d4977,f4977],[d4979,f4978],[d4979,f4979],[d4981,f4980],[d4981,f4981],[d4983,f4982],[d4983,f4983],[d4985,f4984],[d4985,f4985],[d4987,f4986],[d4987,f4987],[d4989,f4988],[d4989,f4989],[d4991,f4990],[d4991,f4991],[d4993,f4992],[d4993,f4993],[d4995,f4994],[d4995,f4995],[d4997,f4996],[d4997,f4997],[d4999,f4998],[d4999,f4999],[d5001,f5000],[d5001,f5001],[d5003,f5002],[d5003,f5003],[d5005,f5004],[d5005,f5005],[d5007,f5006],[d5007,f5007],[d5009,f5008],[d5009,f5009],[d5011,f5010],[d5011,f5011],[d5013,f5012],[d5013,f5013],[d5015,f5014],[d5015,f5015],[d5017,f5016],[d5017,f5017],[d5019,f5018],[d5019,f5019],[d5021,f5020],[d5021,f5021],[d5023,f5022],[d5023,f5023],[d5025,f5024],[d5025,f5025],[d5027,f5026],[d5027,f5027],[d5029,f5028],[d5029,f5029],[d5031,f5030],[d5031,f5031],[d5033,f5032],[d5033,f5033],[d5035,f5034],[d5035,f5035],[d5037,f5036],[d5037,f5037],[d5039,f5038],[d5039,f5039],[d5041,f5040],[d5041,f5041],[d5043,f5042],[d5043,f5043],[d5045,f5044],[d5045,f5045],[d5047,f5046],[d5047,f5047],[d5049,f5048],[d5049,f5049],[d5051,f5050],[d5051,f5051],[d5053,f5052],[d5053,f5053],[d5055,f5054],[d5055,f5055],[d5057,f5056],[d5057,f5057],[d5059,f5058],[d5059,f5059],[d5061,f5060],[d5061,f5061],[d5063,f5062],[d5063,f5063],[d5065,f5064],[d5065,f5065],[d5067,f5066],[d5067,f5067],[d5069,f5068],[d5069,f5069],[d5071,f5070],[d5071,f5071],[d5073,f5072],[d5073,f5073],[d5075,f5074],[d5075,f5075],[d5077,f5076],[d5077,f5077],[d5079,f5078],[d5079,f5079],[d5081,f5080],[d5081,f5081],[d5083,f5082],[d5083,f5083],[d5085,f5084],[d5085,f5085],[d5087,f5086],[d5087,f5087],[d5089,f5088],[d5089,f5089],[d5091,f5090],[d5091,f5091],[d5093,f5092],[d5093,f5093],[d5095,f5094],[d5095,f5095],[d5097,f5096],[d5097,f5097],[d5099,f5098],[d5099,f5099],[d5101,f5100],[d5101,f5101],[d5103,f5102],[d5103,f5103],[d5105,f5104],[d5105,f5105],[d5107,f5106],[d5107,f5107],[d5109,f5108],[d5109,f5109],[d5111,f5110],[d5111,f5111],[d5113,f5112],[d5113,f5113],[d5115,f5114],[d5115,f5115],[d5117,f5116],[d5117,f5117],[d5119,f5118],[d5119,f5119],[d5121,f5120],[d5121,f5121],[d5123,f5122],[d5123,f5123],[d5125,f5124],[d5125,f5125],[d5127,f5126],[d5127,f5127],[d5129,f5128],[d5129,f5129],[d5131,f5130],[d5131,f5131],[d5133,f5132],[d5133,f5133],[d5135,f5134],[d5135,f5135],[d5137,f5136],[d5137,f5137],[d5139,f5138],[d5139,f5139],[d5141,f5140],[d5141,f5141],[d5143,f5142],[d5143,f5143],[d5145,f5144],[d5145,f5145],[d5147,f5146],[d5147,f5147],[d5149,f5148],[d5149,f5149],[d5151,f5150],[d5151,f5151],[d5153,f5152],[d5153,f5153],[d5155,f5154],[d5155,f5155],[d5157,f5156],[d5157,f5157],[d5159,f5158],[d5159,f5159],[d5161,f5160],[d5161,f5161],[d5163,f5162],[d5163,f5163],[d5165,f5164],[d5165,f5165],[d5167,f5166],[d5167,f5167],[d5169,f5168],[d5169,f5169],[d5171,f5170],[d5171,f5171],[d5173,f5172],[d5173,f5173],[d5175,f5174],[d5175,f5175],[d5177,f5176],[d5177,f5177],[d5179,f5178],[d5179,f5179],[d5181,f5180],[d5181,f5181],[d5183,f5182],[d5183,f5183],[d5185,f5184],[d5185,f5185],[d5187,f5186],[d5187,f5187],[d5189,f5188],[d5189,f5189],[d5191,f5190],[d5191,f5191],[d5193,f5192],[d5193,f5193],[d5195,f5194],[d5195,f5195],[d5197,f5196],[d5197,f5197],[d5199,f5198],[d5199,f5199],[d5201,f5200],[d5201,f5201],[d5203,f5202],[d5203,f5203],[d5205,f5204],[d5205,f5205],[d5207,f5206],[d5207,f5207],[d5209,f5208],[d5209,f5209],[d5211,f5210],[d5211,f5211],[d5213,f5212],[d5213,f5213],[d5215,f5214],[d5215,f5215],[d5217,f5216],[d5217,f5217],[d5219,f5218],[d5219,f5219],[d5221,f5220],[d5221,f5221],[d5223,f5222],[d5223,f5223],[d5225,f5224],[d5225,f5225],[d5227,f5226],[d5227,f5227],[d5229,f5228],[d5229,f5229],[d5231,f5230],[d5231,f5231],[d5233,f5232],[d5233,f5233],[d5235,f5234],[d5235,f5235],[d5237,f5236],[d5237,f5237],[d5239,f5238],[d5239,f5239],[d5241,f5240],[d5241,f5241],[d5243,f5242],[d5243,f5243],[d5245,f5244],[d5245,f5245],[d5247,f5246],[d5247,f5247],[d5249,f5248],[d5249,f5249],[d5251,f5250],[d5251,f5251],[d5253,f5252],[d5253,f5253],[d5255,f5254],[d5255,f5255],[d5257,f5256],[d5257,f5257],[d5259,f5258],[d5259,f5259],[d5261,f5260],[d5261,f5261],[d5263,f5262],[d5263,f5263],[d5265,f5264],[d5265,f5265],[d5267,f5266],[d5267,f5267],[d5269,f5268],[d5269,f5269],[d5271,f5270],[d5271,f5271],[d5273,f5272],[d5273,f5273],[d5275,f5274],[d5275,f5275],[d5277,f5276],[d5277,f5277],[d5279,f5278],[d5279,f5279],[d5281,f5280],[d5281,f5281],[d5283,f5282],[d5283,f5283],[d5285,f5284],[d5285,f5285],[d5287,f5286],[d5287,f5287],[d5289,f5288],[d5289,f5289],[d5291,f5290],[d5291,f5291],[d5293,f5292],[d5293,f5293],[d5295,f5294],[d5295,f5295],[d5297,f5296],[d5297,f5297],[d5299,f5298],[d5299,f5299],[d5301,f5300],[d5301,f5301],[d5303,f5302],[d5303,f5303],[d5305,f5304],[d5305,f5305],[d5307,f5306],[d5307,f5307],[d5309,f5308],[d5309,f5309],[d5311,f5310],[d5311,f5311],[d5313,f5312],[d5313,f5313],[d5315,f5314],[d5315,f5315],[d5317,f5316],[d5317,f5317],[d5319,f5318],[d5319,f5319],[d5321,f5320],[d5321,f5321],[d5323,f5322],[d5323,f5323],[d5325,f5324],[d5325,f5325],[d5327,f5326],[d5327,f5327],[d5329,f5328],[d5329,f5329],[d5331,f5330],[d5331,f5331],[d5333,f5332],[d5333,f5333],[d5335,f5334],[d5335,f5335],[d5337,f5336],[d5337,f5337],[d5339,f5338],[d5339,f5339],[d5341,f5340],[d5341,f5341],[d5343,f5342],[d5343,f5343],[d5345,f5344],[d5345,f5345],[d5347,f5346],[d5347,f5347],[d5349,f5348],[d5349,f5349],[d5351,f5350],[d5351,f5351],[d5353,f5352],[d5353,f5353],[d5355,f5354],[d5355,f5355],[d5357,f5356],[d5357,f5357],[d5359,f5358],[d5359,f5359],[d5361,f5360],[d5361,f5361],[d5363,f5362],[d5363,f5363],[d5365,f5364],[d5365,f5365],[d5367,f5366],[d5367,f5367],[d5369,f5368],[d5369,f5369],[d5371,f5370],[d5371,f5371],[d5373,f5372],[d5373,f5373],[d5375,f5374],[d5375,f5375],[d5377,f5376],[d5377,f5377],[d5379,f5378],[d5379,f5379],[d5381,f5380],[d5381,f5381],[d5383,f5382],[d5383,f5383],[d5385,f5384],[d5385,f5385],[d5387,f5386],[d5387,f5387],[d5389,f5388],[d5389,f5389],[d5391,f5390],[d5391,f5391],[d5393,f5392],[d5393,f5393],[d5395,f5394],[d5395,f5395],[d5397,f5396],[d5397,f5397],[d5399,f5398],[d5399,f5399],[d5401,f5400],[d5401,f5401],[d5403,f5402],[d5403,f5403],[d5405,f5404],[d5405,f5405],[d5407,f5406],[d5407,f5407],[d5409,f5408],[d5409,f5409],[d5411,f5410],[d5411,f5411],[d5413,f5412],[d5413,f5413],[d5415,f5414],[d5415,f5415],[d5417,f5416],[d5417,f5417],[d5419,f5418],[d5419,f5419],[d5421,f5420],[d5421,f5421],[d5423,f5422],[d5423,f5423],[d5425,f5424],[d5425,f5425],[d5427,f5426],[d5427,f5427],[d5429,f5428],[d5429,f5429],[d5431,f5430],[d5431,f5431],[d5433,f5432],[d5433,f5433],[d5435,f5434],[d5435,f5435],[d5437,f5436],[d5437,f5437],[d5439,f5438],[d5439,f5439],[d5441,f5440],[d5441,f5441],[d5443,f5442],[d5443,f5443],[d5445,f5444],[d5445,f5445],[d5447,f5446],[d5447,f5447],[d5449,f5448],[d5449,f5449],[d5451,f5450],[d5451,f5451],[d5453,f5452],[d5453,f5453],[d5455,f5454],[d5455,f5455],[d5457,f5456],[d5457,f5457],[d5459,f5458],[d5459,f5459],[d5461,f5460],[d5461,f5461],[d5463,f5462],[d5463,f5463],[d5465,f5464],[d5465,f5465],[d5467,f5466],[d5467,f5467],[d5469,f5468],[d5469,f5469],[d5471,f5470],[d5471,f5471],[d5473,f5472],[d5473,f5473],[d5475,f5474],[d5475,f5475],[d5477,f5476],[d5477,f5477],[d5479,f5478],[d5479,f5479],[d5481,f5480],[d5481,f5481],[d5483,f5482],[d5483,f5483],[d5485,f5484],[d5485,f5485],[d5487,f5486],[d5487,f5487],[d5489,f5488],[d5489,f5489],[d5491,f5490],[d5491,f5491],[d5493,f5492],[d5493,f5493],[d5495,f5494],[d5495,f5495],[d5497,f5496],[d5497,f5497],[d5499,f5498],[d5499,f5499],[d5501,f5500],[d5501,f5501],[d5503,f5502],[d5503,f5503],[d5505,f5504],[d5505,f5505],[d5507,f5506],[d5507,f5507],[d5509,f5508],[d5509,f5509],[d5511,f5510],[d5511,f5511],[d5513,f5512],[d5513,f5513],[d5515,f5514],[d5515,f5515],[d5517,f5516],[d5517,f5517],[d5519,f5518],[d5519,f5519],[d5521,f5520],[d5521,f5521],[d5523,f5522],[d5523,f5523],[d5525,f5524],[d5525,f5525],[d5527,f5526],[d5527,f5527],[d5529,f5528],[d5529,f5529],[d5531,f5530],[d5531,f5531],[d5533,f5532],[d5533,f5533],[d5535,f5534],[d5535,f5535],[d5537,f5536],[d5537,f5537],[d5539,f5538],[d5539,f5539],[d5541,f5540],[d5541,f5541],[d5543,f5542],[d5543,f5543],[d5545,f5544],[d5545,f5545],[d5547,f5546],[d5547,f5547],[d5549,f5548],[d5549,f5549],[d5551,f5550],[d5551,f5551],[d5553,f5552],[d5553,f5553],[d5555,f5554],[d5555,f5555],[d5557,f5556],[d5557,f5557],[d5559,f5558],[d5559,f5559],[d5561,f5560],[d5561,f5561],[d5563,f5562],[d5563,f5563],[d5565,f5564],[d5565,f5565],[d5567,f5566],[d5567,f5567],[d5569,f5568],[d5569,f5569],[d5571,f5570],[d5571,f5571],[d5573,f5572],[d5573,f5573],[d5575,f5574],[d5575,f5575],[d5577,f5576],[d5577,f5577],[d5579,f5578],[d5579,f5579],[d5581,f5580],[d5581,f5581],[d5583,f5582],[d5583,f5583],[d5585,f5584],[d5585,f5585],[d5587,f5586],[d5587,f5587],[d5589,f5588],[d5589,f5589],[d5591,f5590],[d5591,f5591],[d5593,f5592],[d5593,f5593],[d5595,f5594],[d5595,f5595],[d5597,f5596],[d5597,f5597],[d5599,f5598],[d5599,f5599],[d5601,f5600],[d5601,f5601],[d5603,f5602],[d5603,f5603],[d5605,f5604],[d5605,f5605],[d5607,f5606],[d5607,f5607],[d5609,f5608],[d5609,f5609],[d5611,f5610],[d5611,f5611],[d5613,f5612],[d5613,f5613],[d5615,f5614],[d5615,f5615],[d5617,f5616],[d5617,f5617],[d5619,f5618],[d5619,f5619],[d5621,f5620],[d5621,f5621],[d5623,f5622],[d5623,f5623],[d5625,f5624],[d5625,f5625],[d5627,f5626],[d5627,f5627],[d5629,f5628],[d5629,f5629],[d5631,f5630],[d5631,f5631],[d5633,f5632],[d5633,f5633],[d5635,f5634],[d5635,f5635],[d5637,f5636],[d5637,f5637],[d5639,f5638],[d5639,f5639],[d5641,f5640],[d5641,f5641],[d5643,f5642],[d5643,f5643],[d5645,f5644],[d5645,f5645],[d5647,f5646],[d5647,f5647],[d5649,f5648],[d5649,f5649],[d5651,f5650],[d5651,f5651],[d5653,f5652],[d5653,f5653],[d5655,f5654],[d5655,f5655],[d5657,f5656],[d5657,f5657],[d5659,f5658],[d5659,f5659],[d5661,f5660],[d5661,f5661],[d5663,f5662],[d5663,f5663],[d5665,f5664],[d5665,f5665],[d5667,f5666],[d5667,f5667],[d5669,f5668],[d5669,f5669],[d5671,f5670],[d5671,f5671],[d5673,f5672],[d5673,f5673],[d5675,f5674],[d5675,f5675],[d5677,f5676],[d5677,f5677],[d5679,f5678],[d5679,f5679],[d5681,f5680],[d5681,f5681],[d5683,f5682],[d5683,f5683],[d5685,f5684],[d5685,f5685],[d5687,f5686],[d5687,f5687],[d5689,f5688],[d5689,f5689],[d5691,f5690],[d5691,f5691],[d5693,f5692],[d5693,f5693],[d5695,f5694],[d5695,f5695],[d5697,f5696],[d5697,f5697],[d5699,f5698],[d5699,f5699],[d5701,f5700],[d5701,f5701],[d5703,f5702],[d5703,f5703],[d5705,f5704],[d5705,f5705],[d5707,f5706],[d5707,f5707],[d5709,f5708],[d5709,f5709],[d5711,f5710],[d5711,f5711],[d5713,f5712],[d5713,f5713],[d5715,f5714],[d5715,f5715],[d5717,f5716],[d5717,f5717],[d5719,f5718],[d5719,f5719],[d5721,f5720],[d5721,f5721],[d5723,f5722],[d5723,f5723],[d5725,f5724],[d5725,f5725],[d5727,f5726],[d5727,f5727],[d5729,f5728],[d5729,f5729],[d5731,f5730],[d5731,f5731],[d5733,f5732],[d5733,f5733],[d5735,f5734],[d5735,f5735],[d5737,f5736],[d5737,f5737],[d5739,f5738],[d5739,f5739],[d5741,f5740],[d5741,f5741],[d5743,f5742],[d5743,f5743],[d5745,f5744],[d5745,f5745],[d5747,f5746],[d5747,f5747],[d5749,f5748],[d5749,f5749],[d5751,f5750],[d5751,f5751],[d5753,f5752],[d5753,f5753],[d5755,f5754],[d5755,f5755],[d5757,f5756],[d5757,f5757],[d5759,f5758],[d5759,f5759],[d5761,f5760],[d5761,f5761],[d5763,f5762],[d5763,f5763],[d5765,f5764],[d5765,f5765],[d5767,f5766],[d5767,f5767],[d5769,f5768],[d5769,f5769],[d5771,f5770],[d5771,f5771],[d5773,f5772],[d5773,f5773],[d5775,f5774],[d5775,f5775],[d5777,f5776],[d5777,f5777],[d5779,f5778],[d5779,f5779],[d5781,f5780],[d5781,f5781],[d5783,f5782],[d5783,f5783],[d5785,f5784],[d5785,f5785],[d5787,f5786],[d5787,f5787],[d5789,f5788],[d5789,f5789],[d5791,f5790],[d5791,f5791],[d5793,f5792],[d5793,f5793],[d5795,f5794],[d5795,f5795],[d5797,f5796],[d5797,f5797],[d5799,f5798],[d5799,f5799],[d5801,f5800],[d5801,f5801],[d5803,f5802],[d5803,f5803],[d5805,f5804],[d5805,f5805],[d5807,f5806],[d5807,f5807],[d5809,f5808],[d5809,f5809],[d5811,f5810],[d5811,f5811],[d5813,f5812],[d5813,f5813],[d5815,f5814],[d5815,f5815],[d5817,f5816],[d5817,f5817],[d5819,f5818],[d5819,f5819],[d5821,f5820],[d5821,f5821],[d5823,f5822],[d5823,f5823],[d5825,f5824],[d5825,f5825],[d5827,f5826],[d5827,f5827],[d5829,f5828],[d5829,f5829],[d5831,f5830],[d5831,f5831],[d5833,f5832],[d5833,f5833],[d5835,f5834],[d5835,f5835],[d5837,f5836],[d5837,f5837],[d5839,f5838],[d5839,f5839],[d5841,f5840],[d5841,f5841],[d5843,f5842],[d5843,f5843],[d5845,f5844],[d5845,f5845],[d5847,f5846],[d5847,f5847],[d5849,f5848],[d5849,f5849],[d5851,f5850],[d5851,f5851],[d5853,f5852],[d5853,f5853],[d5855,f5854],[d5855,f5855],[d5857,f5856],[d5857,f5857],[d5859,f5858],[d5859,f5859],[d5861,f5860],[d5861,f5861],[d5863,f5862],[d5863,f5863],[d5865,f5864],[d5865,f5865],[d5867,f5866],[d5867,f5867],[d5869,f5868],[d5869,f5869],[d5871,f5870],[d5871,f5871],[d5873,f5872],[d5873,f5873],[d5875,f5874],[d5875,f5875],[d5877,f5876],[d5877,f5877],[d5879,f5878],[d5879,f5879],[d5881,f5880],[d5881,f5881],[d5883,f5882],[d5883,f5883],[d5885,f5884],[d5885,f5885],[d5887,f5886],[d5887,f5887],[d5889,f5888],[d5889,f5889],[d5891,f5890],[d5891,f5891],[d5893,f5892],[d5893,f5893],[d5895,f5894],[d5895,f5895],[d5897,f5896],[d5897,f5897],[d5899,f5898],[d5899,f5899],[d5901,f5900],[d5901,f5901],[d5903,f5902],[d5903,f5903],[d5905,f5904],[d5905,f5905],[d5907,f5906],[d5907,f5907],[d5909,f5908],[d5909,f5909],[d5911,f5910],[d5911,f5911],[d5913,f5912],[d5913,f5913],[d5915,f5914],[d5915,f5915],[d5917,f5916],[d5917,f5917],[d5919,f5918],[d5919,f5919],[d5921,f5920],[d5921,f5921],[d5923,f5922],[d5923,f5923],[d5925,f5924],[d5925,f5925],[d5927,f5926],[d5927,f5927],[d5929,f5928],[d5929,f5929],[d5931,f5930],[d5931,f5931],[d5933,f5932],[d5933,f5933],[d5935,f5934],[d5935,f5935],[d5937,f5936],[d5937,f5937],[d5939,f5938],[d5939,f5939],[d5941,f5940],[d5941,f5941],[d5943,f5942],[d5943,f5943],[d5945,f5944],[d5945,f5945],[d5947,f5946],[d5947,f5947],[d5949,f5948],[d5949,f5949],[d5951,f5950],[d5951,f5951],[d5953,f5952],[d5953,f5953],[d5955,f5954],[d5955,f5955],[d5957,f5956],[d5957,f5957],[d5959,f5958],[d5959,f5959],[d5961,f5960],[d5961,f5961],[d5963,f5962],[d5963,f5963],[d5965,f5964],[d5965,f5965],[d5967,f5966],[d5967,f5967],[d5969,f5968],[d5969,f5969],[d5971,f5970],[d5971,f5971],[d5973,f5972],[d5973,f5973],[d5975,f5974],[d5975,f5975],[d5977,f5976],[d5977,f5977],[d5979,f5978],[d5979,f5979],[d5981,f5980],[d5981,f5981],[d5983,f5982],[d5983,f5983],[d5985,f5984],[d5985,f5985],[d5987,f5986],[d5987,f5987],[d5989,f5988],[d5989,f5989],[d5991,f5990],[d5991,f5991],[d5993,f5992],[d5993,f5993],[d5995,f5994],[d5995,f5995],[d5997,f5996],[d5997,f5997],[d5999,f5998],[d5999,f5999],[d6001,f6000],[d6001,f6001],[d6003,f6002],[d6003,f6003],[d6005,f6004],[d6005,f6005],[d6007,f6006],[d6007,f6007],[d6009,f6008],[d6009,f6009],[d6011,f6010],[d6011,f6011],[d6013,f6012],[d6013,f6013],[d6015,f6014],[d6015,f6015],[d6017,f6016],[d6017,f6017],[d6019,f6018],[d6019,f6019],[d6021,f6020],[d6021,f6021],[d6023,f6022],[d6023,f6023],[d6025,f6024],[d6025,f6025],[d6027,f6026],[d6027,f6027],[d6029,f6028],[d6029,f6029],[d6031,f6030],[d6031,f6031],[d6033,f6032],[d6033,f6033],[d6035,f6034],[d6035,f6035],[d6037,f6036],[d6037,f6037],[d6039,f6038],[d6039,f6039],[d6041,f6040],[d6041,f6041],[d6043,f6042],[d6043,f6043],[d6045,f6044],[d6045,f6045],[d6047,f6046],[d6047,f6047],[d6049,f6048],[d6049,f6049],[d6051,f6050],[d6051,f6051],[d6053,f6052],[d6053,f6053],[d6055,f6054],[d6055,f6055],[d6057,f6056],[d6057,f6057],[d6059,f6058],[d6059,f6059],[d6061,f6060],[d6061,f6061],[d6063,f6062],[d6063,f6063],[d6065,f6064],[d6065,f6065],[d6067,f6066],[d6067,f6067],[d6069,f6068],[d6069,f6069],[d6071,f6070],[d6071,f6071],[d6073,f6072],[d6073,f6073],[d6075,f6074],[d6075,f6075],[d6077,f6076],[d6077,f6077],[d6079,f6078],[d6079,f6079],[d6081,f6080],[d6081,f6081],[d6083,f6082],[d6083,f6083],[d6085,f6084],[d6085,f6085],[d6087,f6086],[d6087,f6087],[d6089,f6088],[d6089,f6089],[d6091,f6090],[d6091,f6091],[d6093,f6092],[d6093,f6093],[d6095,f6094],[d6095,f6095],[d6097,f6096],[d6097,f6097],[d6099,f6098],[d6099,f6099],[d6101,f6100],[d6101,f6101],[d6103,f6102],[d6103,f6103],[d6105,f6104],[d6105,f6105],[d6107,f6106],[d6107,f6107],[d6109,f6108],[d6109,f6109],[d6111,f6110],[d6111,f6111],[d6113,f6112],[d6113,f6113],[d6115,f6114],[d6115,f6115],[d6117,f6116],[d6117,f6117],[d6119,f6118],[d6119,f6119],[d6121,f6120],[d6121,f6121],[d6123,f6122],[d6123,f6123],[d6125,f6124],[d6125,f6125],[d6127,f6126],[d6127,f6127],[d6129,f6128],[d6129,f6129],[d6131,f6130],[d6131,f6131],[d6133,f6132],[d6133,f6133],[d6135,f6134],[d6135,f6135],[d6137,f6136],[d6137,f6137],[d6139,f6138],[d6139,f6139],[d6141,f6140],[d6141,f6141],[d6143,f6142],[d6143,f6143],[d6145,f6144],[d6145,f6145],[d6147,f6146],[d6147,f6147],[d6149,f6148],[d6149,f6149],[d6151,f6150],[d6151,f6151],[d6153,f6152],[d6153,f6153],[d6155,f6154],[d6155,f6155],[d6157,f6156],[d6157,f6157],[d6159,f6158],[d6159,f6159],[d6161,f6160],[d6161,f6161],[d6163,f6162],[d6163,f6163],[d6165,f6164],[d6165,f6165],[d6167,f6166],[d6167,f6167],[d6169,f6168],[d6169,f6169],[d6171,f6170],[d6171,f6171],[d6173,f6172],[d6173,f6173],[d6175,f6174],[d6175,f6175],[d6177,f6176],[d6177,f6177],[d6179,f6178],[d6179,f6179],[d6181,f6180],[d6181,f6181],[d6183,f6182],[d6183,f6183],[d6185,f6184],[d6185,f6185],[d6187,f6186],[d6187,f6187],[d6189,f6188],[d6189,f6189],[d6191,f6190],[d6191,f6191],[d6193,f6192],[d6193,f6193],[d6195,f6194],[d6195,f6195],[d6197,f6196],[d6197,f6197],[d6199,f6198],[d6199,f6199],[d6201,f6200],[d6201,f6201],[d6203,f6202],[d6203,f6203],[d6205,f6204],[d6205,f6205],[d6207,f6206],[d6207,f6207],[d6209,f6208],[d6209,f6209],[d6211,f6210],[d6211,f6211],[d6213,f6212],[d6213,f6213],[d6215,f6214],[d6215,f6215],[d6217,f6216],[d6217,f6217],[d6219,f6218],[d6219,f6219],[d6221,f6220],[d6221,f6221],[d6223,f6222],[d6223,f6223],[d6225,f6224],[d6225,f6225],[d6227,f6226],[d6227,f6227],[d6229,f6228],[d6229,f6229],[d6231,f6230],[d6231,f6231],[d6233,f6232],[d6233,f6233],[d6235,f6234],[d6235,f6235],[d6237,f6236],[d6237,f6237],[d6239,f6238],[d6239,f6239],[d6241,f6240],[d6241,f6241],[d6243,f6242],[d6243,f6243],[d6245,f6244],[d6245,f6245],[d6247,f6246],[d6247,f6247],[d6249,f6248],[d6249,f6249],[d6251,f6250],[d6251,f6251],[d6253,f6252],[d6253,f6253],[d6255,f6254],[d6255,f6255],[d6257,f6256],[d6257,f6257],[d6259,f6258],[d6259,f6259],[d6261,f6260],[d6261,f6261],[d6263,f6262],[d6263,f6263],[d6265,f6264],[d6265,f6265],[d6267,f6266],[d6267,f6267],[d6269,f6268],[d6269,f6269],[d6271,f6270],[d6271,f6271],[d6273,f6272],[d6273,f6273],[d6275,f6274],[d6275,f6275],[d6277,f6276],[d6277,f6277],[d6279,f6278],[d6279,f6279],[d6281,f6280],[d6281,f6281],[d6283,f6282],[d6283,f6283],[d6285,f6284],[d6285,f6285],[d6287,f6286],[d6287,f6287],[d6289,f6288],[d6289,f6289],[d6291,f6290],[d6291,f6291],[d6293,f6292],[d6293,f6293],[d6295,f6294],[d6295,f6295],[d6297,f6296],[d6297,f6297],[d6299,f6298],[d6299,f6299],[d6301,f6300],[d6301,f6301],[d6303,f6302],[d6303,f6303],[d6305,f6304],[d6305,f6305],[d6307,f6306],[d6307,f6307],[d6309,f6308],[d6309,f6309],[d6311,f6310],[d6311,f6311],[d6313,f6312],[d6313,f6313],[d6315,f6314],[d6315,f6315],[d6317,f6316],[d6317,f6317],[d6319,f6318],[d6319,f6319],[d6321,f6320],[d6321,f6321],[d6323,f6322],[d6323,f6323],[d6325,f6324],[d6325,f6325],[d6327,f6326],[d6327,f6327],[d6329,f6328],[d6329,f6329],[d6331,f6330],[d6331,f6331],[d6333,f6332],[d6333,f6333],[d6335,f6334],[d6335,f6335],[d6337,f6336],[d6337,f6337],[d6339,f6338],[d6339,f6339],[d6341,f6340],[d6341,f6341],[d6343,f6342],[d6343,f6343],[d6345,f6344],[d6345,f6345],[d6347,f6346],[d6347,f6347],[d6349,f6348],[d6349,f6349],[d6351,f6350],[d6351,f6351],[d6353,f6352],[d6353,f6353],[d6355,f6354],[d6355,f6355],[d6357,f6356],[d6357,f6357],[d6359,f6358],[d6359,f6359],[d6361,f6360],[d6361,f6361],[d6363,f6362],[d6363,f6363],[d6365,f6364],[d6365,f6365],[d6367,f6366],[d6367,f6367],[d6369,f6368],[d6369,f6369],[d6371,f6370],[d6371,f6371],[d6373,f6372],[d6373,f6373],[d6375,f6374],[d6375,f6375],[d6377,f6376],[d6377,f6377],[d6379,f6378],[d6379,f6379],[d6381,f6380],[d6381,f6381],[d6383,f6382],[d6383,f6383],[d6385,f6384],[d6385,f6385],[d6387,f6386],[d6387,f6387],[d6389,f6388],[d6389,f6389],[d6391,f6390],[d6391,f6391],[d6393,f6392],[d6393,f6393],[d6395,f6394],[d6395,f6395],[d6397,f6396],[d6397,f6397],[d6399,f6398],[d6399,f6399],[d6401,f6400],[d6401,f6401],[d6403,f6402],[d6403,f6403],[d6405,f6404],[d6405,f6405],[d6407,f6406],[d6407,f6407],[d6409,f6408],[d6409,f6409],[d6411,f6410],[d6411,f6411],[d6413,f6412],[d6413,f6413],[d6415,f6414],[d6415,f6415],[d6417,f6416],[d6417,f6417],[d6419,f6418],[d6419,f6419],[d6421,f6420],[d6421,f6421],[d6423,f6422],[d6423,f6423],[d6425,f6424],[d6425,f6425],[d6427,f6426],[d6427,f6427],[d6429,f6428],[d6429,f6429],[d6431,f6430],[d6431,f6431],[d6433,f6432],[d6433,f6433],[d6435,f6434],[d6435,f6435],[d6437,f6436],[d6437,f6437],[d6439,f6438],[d6439,f6439],[d6441,f6440],[d6441,f6441],[d6443,f6442],[d6443,f6443],[d6445,f6444],[d6445,f6445],[d6447,f6446],[d6447,f6447],[d6449,f6448],[d6449,f6449],[d6451,f6450],[d6451,f6451],[d6453,f6452],[d6453,f6453],[d6455,f6454],[d6455,f6455],[d6457,f6456],[d6457,f6457],[d6459,f6458],[d6459,f6459],[d6461,f6460],[d6461,f6461],[d6463,f6462],[d6463,f6463],[d6465,f6464],[d6465,f6465],[d6467,f6466],[d6467,f6467],[d6469,f6468],[d6469,f6469],[d6471,f6470],[d6471,f6471],[d6473,f6472],[d6473,f6473],[d6475,f6474],[d6475,f6475],[d6477,f6476],[d6477,f6477],[d6479,f6478],[d6479,f6479],[d6481,f6480],[d6481,f6481],[d6483,f6482],[d6483,f6483],[d6485,f6484],[d6485,f6485],[d6487,f6486],[d6487,f6487],[d6489,f6488],[d6489,f6489],[d6491,f6490],[d6491,f6491],[d6493,f6492],[d6493,f6493],[d6495,f6494],[d6495,f6495],[d6497,f6496],[d6497,f6497],[d6499,f6498],[d6499,f6499],[d6501,f6500],[d6501,f6501],[d6503,f6502],[d6503,f6503],[d6505,f6504],[d6505,f6505],[d6507,f6506],[d6507,f6507],[d6509,f6508],[d6509,f6509],[d6511,f6510],[d6511,f6511],[d6513,f6512],[d6513,f6513],[d6515,f6514],[d6515,f6515],[d6517,f6516],[d6517,f6517],[d6519,f6518],[d6519,f6519],[d6521,f6520],[d6521,f6521],[d6523,f6522],[d6523,f6523],[d6525,f6524],[d6525,f6525],[d6527,f6526],[d6527,f6527],[d6529,f6528],[d6529,f6529],[d6531,f6530],[d6531,f6531],[d6533,f6532],[d6533,f6533],[d6535,f6534],[d6535,f6535],[d6537,f6536],[d6537,f6537],[d6539,f6538],[d6539,f6539],[d6541,f6540],[d6541,f6541],[d6543,f6542],[d6543,f6543],[d6545,f6544],[d6545,f6545],[d6547,f6546],[d6547,f6547],[d6549,f6548],[d6549,f6549],[d6551,f6550],[d6551,f6551],[d6553,f6552],[d6553,f6553],[d6555,f6554],[d6555,f6555],[d6557,f6556],[d6557,f6557],[d6559,f6558],[d6559,f6559],[d6561,f6560],[d6561,f6561],[d6563,f6562],[d6563,f6563],[d6565,f6564],[d6565,f6565],[d6567,f6566],[d6567,f6567],[d6569,f6568],[d6569,f6569],[d6571,f6570],[d6571,f6571],[d6573,f6572],[d6573,f6573],[d6575,f6574],[d6575,f6575],[d6577,f6576],[d6577,f6577],[d6579,f6578],[d6579,f6579],[d6581,f6580],[d6581,f6581],[d6583,f6582],[d6583,f6583],[d6585,f6584],[d6585,f6585],[d6587,f6586],[d6587,f6587],[d6589,f6588],[d6589,f6589],[d6591,f6590],[d6591,f6591],[d6593,f6592],[d6593,f6593],[d6595,f6594],[d6595,f6595],[d6597,f6596],[d6597,f6597],[d6599,f6598],[d6599,f6599],[d6601,f6600],[d6601,f6601],[d6603,f6602],[d6603,f6603],[d6605,f6604],[d6605,f6605],[d6607,f6606],[d6607,f6607],[d6609,f6608],[d6609,f6609],[d6611,f6610],[d6611,f6611],[d6613,f6612],[d6613,f6613],[d6615,f6614],[d6615,f6615],[d6617,f6616],[d6617,f6617],[d6619,f6618],[d6619,f6619],[d6621,f6620],[d6621,f6621],[d6623,f6622],[d6623,f6623],[d6625,f6624],[d6625,f6625],[d6627,f6626],[d6627,f6627],[d6629,f6628],[d6629,f6629],[d6631,f6630],[d6631,f6631],[d6633,f6632],[d6633,f6633],[d6635,f6634],[d6635,f6635],[d6637,f6636],[d6637,f6637],[d6639,f6638],[d6639,f6639],[d6641,f6640],[d6641,f6641],[d6643,f6642],[d6643,f6643],[d6645,f6644],[d6645,f6645],[d6647,f6646],[d6647,f6647],[d6649,f6648],[d6649,f6649],[d6651,f6650],[d6651,f6651],[d6653,f6652],[d6653,f6653],[d6655,f6654],[d6655,f6655],[d6657,f6656],[d6657,f6657],[d6659,f6658],[d6659,f6659],[d6661,f6660],[d6661,f6661],[d6663,f6662],[d6663,f6663],[d6665,f6664],[d6665,f6665],[d6667,f6666],[d6667,f6667],[d6669,f6668],[d6669,f6669],[d6671,f6670],[d6671,f6671],[d6673,f6672],[d6673,f6673],[d6675,f6674],[d6675,f6675],[d6677,f6676],[d6677,f6677],[d6679,f6678],[d6679,f6679],[d6681,f6680],[d6681,f6681],[d6683,f6682],[d6683,f6683],[d6685,f6684],[d6685,f6685],[d6687,f6686],[d6687,f6687],[d6689,f6688],[d6689,f6689],[d6691,f6690],[d6691,f6691],[d6693,f6692],[d6693,f6693],[d6695,f6694],[d6695,f6695],[d6697,f6696],[d6697,f6697],[d6699,f6698],[d6699,f6699],[d6701,f6700],[d6701,f6701],[d6703,f6702],[d6703,f6703],[d6705,f6704],[d6705,f6705],[d6707,f6706],[d6707,f6707],[d6709,f6708],[d6709,f6709],[d6711,f6710],[d6711,f6711],[d6713,f6712],[d6713,f6713],[d6715,f6714],[d6715,f6715],[d6717,f6716],[d6717,f6717],[d6719,f6718],[d6719,f6719],[d6721,f6720],[d6721,f6721],[d6723,f6722],[d6723,f6723],[d6725,f6724],[d6725,f6725],[d6727,f6726],[d6727,f6727],[d6729,f6728],[d6729,f6729],[d6731,f6730],[d6731,f6731],[d6733,f6732],[d6733,f6733],[d6735,f6734],[d6735,f6735],[d6737,f6736],[d6737,f6737],[d6739,f6738],[d6739,f6739],[d6741,f6740],[d6741,f6741],[d6743,f6742],[d6743,f6743],[d6745,f6744],[d6745,f6745],[d6747,f6746],[d6747,f6747],[d6749,f6748],[d6749,f6749],[d6751,f6750],[d6751,f6751],[d6753,f6752],[d6753,f6753],[d6755,f6754],[d6755,f6755],[d6757,f6756],[d6757,f6757],[d6759,f6758],[d6759,f6759],[d6761,f6760],[d6761,f6761],[d6763,f6762],[d6763,f6763],[d6765,f6764],[d6765,f6765],[d6767,f6766],[d6767,f6767],[d6769,f6768],[d6769,f6769],[d6771,f6770],[d6771,f6771],[d6773,f6772],[d6773,f6773],[d6775,f6774],[d6775,f6775],[d6777,f6776],[d6777,f6777],[d6779,f6778],[d6779,f6779],[d6781,f6780],[d6781,f6781],[d6783,f6782],[d6783,f6783],[d6785,f6784],[d6785,f6785],[d6787,f6786],[d6787,f6787],[d6789,f6788],[d6789,f6789],[d6791,f6790],[d6791,f6791],[d6793,f6792],[d6793,f6793],[d6795,f6794],[d6795,f6795],[d6797,f6796],[d6797,f6797],[d6799,f6798],[d6799,f6799],[d6801,f6800],[d6801,f6801],[d6803,f6802],[d6803,f6803],[d6805,f6804],[d6805,f6805],[d6807,f6806],[d6807,f6807],[d6809,f6808],[d6809,f6809],[d6811,f6810],[d6811,f6811],[d6813,f6812],[d6813,f6813],[d6815,f6814],[d6815,f6815],[d6817,f6816],[d6817,f6817],[d6819,f6818],[d6819,f6819],[d6821,f6820],[d6821,f6821],[d6823,f6822],[d6823,f6823],[d6825,f6824],[d6825,f6825],[d6827,f6826],[d6827,f6827],[d6829,f6828],[d6829,f6829],[d6831,f6830],[d6831,f6831],[d6833,f6832],[d6833,f6833],[d6835,f6834],[d6835,f6835],[d6837,f6836],[d6837,f6837],[d6839,f6838],[d6839,f6839],[d6841,f6840],[d6841,f6841],[d6843,f6842],[d6843,f6843],[d6845,f6844],[d6845,f6845],[d6847,f6846],[d6847,f6847],[d6849,f6848],[d6849,f6849],[d6851,f6850],[d6851,f6851],[d6853,f6852],[d6853,f6853],[d6855,f6854],[d6855,f6855],[d6857,f6856],[d6857,f6857],[d6859,f6858],[d6859,f6859],[d6861,f6860],[d6861,f6861],[d6863,f6862],[d6863,f6863],[d6865,f6864],[d6865,f6865],[d6867,f6866],[d6867,f6867],[d6869,f6868],[d6869,f6869],[d6871,f6870],[d6871,f6871],[d6873,f6872],[d6873,f6873],[d6875,f6874],[d6875,f6875],[d6877,f6876],[d6877,f6877],[d6879,f6878],[d6879,f6879],[d6881,f6880],[d6881,f6881],[d6883,f6882],[d6883,f6883],[d6885,f6884],[d6885,f6885],[d6887,f6886],[d6887,f6887],[d6889,f6888],[d6889,f6889],[d6891,f6890],[d6891,f6891],[d6893,f6892],[d6893,f6893],[d6895,f6894],[d6895,f6895],[d6897,f6896],[d6897,f6897],[d6899,f6898],[d6899,f6899],[d6901,f6900],[d6901,f6901],[d6903,f6902],[d6903,f6903],[d6905,f6904],[d6905,f6905],[d6907,f6906],[d6907,f6907],[d6909,f6908],[d6909,f6909],[d6911,f6910],[d6911,f6911],[d6913,f6912],[d6913,f6913],[d6915,f6914],[d6915,f6915],[d6917,f6916],[d6917,f6917],[d6919,f6918],[d6919,f6919],[d6921,f6920],[d6921,f6921],[d6923,f6922],[d6923,f6923],[d6925,f6924],[d6925,f6925],[d6927,f6926],[d6927,f6927],[d6929,f6928],[d6929,f6929],[d6931,f6930],[d6931,f6931],[d6933,f6932],[d6933,f6933],[d6935,f6934],[d6935,f6935],[d6937,f6936],[d6937,f6937],[d6939,f6938],[d6939,f6939],[d6941,f6940],[d6941,f6941],[d6943,f6942],[d6943,f6943],[d6945,f6944],[d6945,f6945],[d6947,f6946],[d6947,f6947],[d6949,f6948],[d6949,f6949],[d6951,f6950],[d6951,f6951],[d6953,f6952],[d6953,f6953],[d6955,f6954],[d6955,f6955],[d6957,f6956],[d6957,f6957],[d6959,f6958],[d6959,f6959],[d6961,f6960],[d6961,f6961],[d6963,f6962],[d6963,f6963],[d6965,f6964],[d6965,f6965],[d6967,f6966],[d6967,f6967],[d6969,f6968],[d6969,f6969],[d6971,f6970],[d6971,f6971],[d6973,f6972],[d6973,f6973],[d6975,f6974],[d6975,f6975],[d6977,f6976],[d6977,f6977],[d6979,f6978],[d6979,f6979],[d6981,f6980],[d6981,f6981],[d6983,f6982],[d6983,f6983],[d6985,f6984],[d6985,f6985],[d6987,f6986],[d6987,f6987],[d6989,f6988],[d6989,f6989],[d6991,f6990],[d6991,f6991],[d6993,f6992],[d6993,f6993],[d6995,f6994],[d6995,f6995],[d6997,f6996],[d6997,f6997],[d6999,f6998],[d6999,f6999],[d7001,f7000],[d7001,f7001],[d7003,f7002],[d7003,f7003],[d7005,f7004],[d7005,f7005],[d7007,f7006],[d7007,f7007],[d7009,f7008],[d7009,f7009],[d7011,f7010],[d7011,f7011],[d7013,f7012],[d7013,f7013],[d7015,f7014],[d7015,f7015],[d7017,f7016],[d7017,f7017],[d7019,f7018],[d7019,f7019],[d7021,f7020],[d7021,f7021],[d7023,f7022],[d7023,f7023],[d7025,f7024],[d7025,f7025],[d7027,f7026],[d7027,f7027],[d7029,f7028],[d7029,f7029],[d7031,f7030],[d7031,f7031],[d7033,f7032],[d7033,f7033],[d7035,f7034],[d7035,f7035],[d7037,f7036],[d7037,f7037],[d7039,f7038],[d7039,f7039],[d7041,f7040],[d7041,f7041],[d7043,f7042],[d7043,f7043],[d7045,f7044],[d7045,f7045],[d7047,f7046],[d7047,f7047],[d7049,f7048],[d7049,f7049],[d7051,f7050],[d7051,f7051],[d7053,f7052],[d7053,f7053],[d7055,f7054],[d7055,f7055],[d7057,f7056],[d7057,f7057],[d7059,f7058],[d7059,f7059],[d7061,f7060],[d7061,f7061],[d7063,f7062],[d7063,f7063],[d7065,f7064],[d7065,f7065],[d7067,f7066],[d7067,f7067],[d7069,f7068],[d7069,f7069],[d7071,f7070],[d7071,f7071],[d7073,f7072],[d7073,f7073],[d7075,f7074],[d7075,f7075],[d7077,f7076],[d7077,f7077],[d7079,f7078],[d7079,f7079],[d7081,f7080],[d7081,f7081],[d7083,f7082],[d7083,f7083],[d7085,f7084],[d7085,f7085],[d7087,f7086],[d7087,f7087],[d7089,f7088],[d7089,f7089],[d7091,f7090],[d7091,f7091],[d7093,f7092],[d7093,f7093],[d7095,f7094],[d7095,f7095],[d7097,f7096],[d7097,f7097],[d7099,f7098],[d7099,f7099],[d7101,f7100],[d7101,f7101],[d7103,f7102],[d7103,f7103],[d7105,f7104],[d7105,f7105],[d7107,f7106],[d7107,f7107],[d7109,f7108],[d7109,f7109],[d7111,f7110],[d7111,f7111],[d7113,f7112],[d7113,f7113],[d7115,f7114],[d7115,f7115],[d7117,f7116],[d7117,f7117],[d7119,f7118],[d7119,f7119],[d7121,f7120],[d7121,f7121],[d7123,f7122],[d7123,f7123],[d7125,f7124],[d7125,f7125],[d7127,f7126],[d7127,f7127],[d7129,f7128],[d7129,f7129],[d7131,f7130],[d7131,f7131],[d7133,f7132],[d7133,f7133],[d7135,f7134],[d7135,f7135],[d7137,f7136],[d7137,f7137],[d7139,f7138],[d7139,f7139],[d7141,f7140],[d7141,f7141],[d7143,f7142],[d7143,f7143],[d7145,f7144],[d7145,f7145],[d7147,f7146],[d7147,f7147],[d7149,f7148],[d7149,f7149],[d7151,f7150],[d7151,f7151],[d7153,f7152],[d7153,f7153],[d7155,f7154],[d7155,f7155],[d7157,f7156],[d7157,f7157],[d7159,f7158],[d7159,f7159],[d7161,f7160],[d7161,f7161],[d7163,f7162],[d7163,f7163],[d7165,f7164],[d7165,f7165],[d7167,f7166],[d7167,f7167],[d7169,f7168],[d7169,f7169],[d7171,f7170],[d7171,f7171],[d7173,f7172],[d7173,f7173],[d7175,f7174],[d7175,f7175],[d7177,f7176],[d7177,f7177],[d7179,f7178],[d7179,f7179],[d7181,f7180],[d7181,f7181],[d7183,f7182],[d7183,f7183],[d7185,f7184],[d7185,f7185],[d7187,f7186],[d7187,f7187],[d7189,f7188],[d7189,f7189],[d7191,f7190],[d7191,f7191],[d7193,f7192],[d7193,f7193],[d7195,f7194],[d7195,f7195],[d7197,f7196],[d7197,f7197],[d7199,f7198],[d7199,f7199],[d7201,f7200],[d7201,f7201],[d7203,f7202],[d7203,f7203],[d7205,f7204],[d7205,f7205],[d7207,f7206],[d7207,f7207],[d7209,f7208],[d7209,f7209],[d7211,f7210],[d7211,f7211],[d7213,f7212],[d7213,f7213],[d7215,f7214],[d7215,f7215],[d7217,f7216],[d7217,f7217],[d7219,f7218],[d7219,f7219],[d7221,f7220],[d7221,f7221],[d7223,f7222],[d7223,f7223],[d7225,f7224],[d7225,f7225],[d7227,f7226],[d7227,f7227],[d7229,f7228],[d7229,f7229],[d7231,f7230],[d7231,f7231],[d7233,f7232],[d7233,f7233],[d7235,f7234],[d7235,f7235],[d7237,f7236],[d7237,f7237],[d7239,f7238],[d7239,f7239],[d7241,f7240],[d7241,f7241],[d7243,f7242],[d7243,f7243],[d7245,f7244],[d7245,f7245],[d7247,f7246],[d7247,f7247],[d7249,f7248],[d7249,f7249],[d7251,f7250],[d7251,f7251],[d7253,f7252],[d7253,f7253],[d7255,f7254],[d7255,f7255],[d7257,f7256],[d7257,f7257],[d7259,f7258],[d7259,f7259],[d7261,f7260],[d7261,f7261],[d7263,f7262],[d7263,f7263],[d7265,f7264],[d7265,f7265],[d7267,f7266],[d7267,f7267],[d7269,f7268],[d7269,f7269],[d7271,f7270],[d7271,f7271],[d7273,f7272],[d7273,f7273],[d7275,f7274],[d7275,f7275],[d7277,f7276],[d7277,f7277],[d7279,f7278],[d7279,f7279],[d7281,f7280],[d7281,f7281],[d7283,f7282],[d7283,f7283],[d7285,f7284],[d7285,f7285],[d7287,f7286],[d7287,f7287],[d7289,f7288],[d7289,f7289],[d7291,f7290],[d7291,f7291],[d7293,f7292],[d7293,f7293],[d7295,f7294],[d7295,f7295],[d7297,f7296],[d7297,f7297],[d7299,f7298],[d7299,f7299],[d7301,f7300],[d7301,f7301],[d7303,f7302],[d7303,f7303],[d7305,f7304],[d7305,f7305],[d7307,f7306],[d7307,f7307],[d7309,f7308],[d7309,f7309],[d7311,f7310],[d7311,f7311],[d7313,f7312],[d7313,f7313],[d7315,f7314],[d7315,f7315],[d7317,f7316],[d7317,f7317],[d7319,f7318],[d7319,f7319],[d7321,f7320],[d7321,f7321],[d7323,f7322],[d7323,f7323],[d7325,f7324],[d7325,f7325],[d7327,f7326],[d7327,f7327],[d7329,f7328],[d7329,f7329],[d7331,f7330],[d7331,f7331],[d7333,f7332],[d7333,f7333],[d7335,f7334],[d7335,f7335],[d7337,f7336],[d7337,f7337],[d7339,f7338],[d7339,f7339],[d7341,f7340],[d7341,f7341],[d7343,f7342],[d7343,f7343],[d7345,f7344],[d7345,f7345],[d7347,f7346],[d7347,f7347],[d7349,f7348],[d7349,f7349],[d7351,f7350],[d7351,f7351],[d7353,f7352],[d7353,f7353],[d7355,f7354],[d7355,f7355],[d7357,f7356],[d7357,f7357],[d7359,f7358],[d7359,f7359],[d7361,f7360],[d7361,f7361],[d7363,f7362],[d7363,f7363],[d7365,f7364],[d7365,f7365],[d7367,f7366],[d7367,f7367],[d7369,f7368],[d7369,f7369],[d7371,f7370],[d7371,f7371],[d7373,f7372],[d7373,f7373],[d7375,f7374],[d7375,f7375],[d7377,f7376],[d7377,f7377],[d7379,f7378],[d7379,f7379],[d7381,f7380],[d7381,f7381],[d7383,f7382],[d7383,f7383],[d7385,f7384],[d7385,f7385],[d7387,f7386],[d7387,f7387],[d7389,f7388],[d7389,f7389],[d7391,f7390],[d7391,f7391],[d7393,f7392],[d7393,f7393],[d7395,f7394],[d7395,f7395],[d7397,f7396],[d7397,f7397],[d7399,f7398],[d7399,f7399],[d7401,f7400],[d7401,f7401],[d7403,f7402],[d7403,f7403],[d7405,f7404],[d7405,f7405],[d7407,f7406],[d7407,f7407],[d7409,f7408],[d7409,f7409],[d7411,f7410],[d7411,f7411],[d7413,f7412],[d7413,f7413],[d7415,f7414],[d7415,f7415],[d7417,f7416],[d7417,f7417],[d7419,f7418],[d7419,f7419],[d7421,f7420],[d7421,f7421],[d7423,f7422],[d7423,f7423],[d7425,f7424],[d7425,f7425],[d7427,f7426],[d7427,f7427],[d7429,f7428],[d7429,f7429],[d7431,f7430],[d7431,f7431],[d7433,f7432],[d7433,f7433],[d7435,f7434],[d7435,f7435],[d7437,f7436],[d7437,f7437],[d7439,f7438],[d7439,f7439],[d7441,f7440],[d7441,f7441],[d7443,f7442],[d7443,f7443],[d7445,f7444],[d7445,f7445],[d7447,f7446],[d7447,f7447],[d7449,f7448],[d7449,f7449],[d7451,f7450],[d7451,f7451],[d7453,f7452],[d7453,f7453],[d7455,f7454],[d7455,f7455],[d7457,f7456],[d7457,f7457],[d7459,f7458],[d7459,f7459],[d7461,f7460],[d7461,f7461],[d7463,f7462],[d7463,f7463],[d7465,f7464],[d7465,f7465],[d7467,f7466],[d7467,f7467],[d7469,f7468],[d7469,f7469],[d7471,f7470],[d7471,f7471],[d7473,f7472],[d7473,f7473],[d7475,f7474],[d7475,f7475],[d7477,f7476],[d7477,f7477],[d7479,f7478],[d7479,f7479],[d7481,f7480],[d7481,f7481],[d7483,f7482],[d7483,f7483],[d7485,f7484],[d7485,f7485],[d7487,f7486],[d7487,f7487],[d7489,f7488],[d7489,f7489],[d7491,f7490],[d7491,f7491],[d7493,f7492],[d7493,f7493],[d7495,f7494],[d7495,f7495],[d7497,f7496],[d7497,f7497],[d7499,f7498],[d7499,f7499],[d7501,f7500],[d7501,f7501],[d7503,f7502],[d7503,f7503],[d7505,f7504],[d7505,f7505],[d7507,f7506],[d7507,f7507],[d7509,f7508],[d7509,f7509],[d7511,f7510],[d7511,f7511],[d7513,f7512],[d7513,f7513],[d7515,f7514],[d7515,f7515],[d7517,f7516],[d7517,f7517],[d7519,f7518],[d7519,f7519],[d7521,f7520],[d7521,f7521],[d7523,f7522],[d7523,f7523],[d7525,f7524],[d7525,f7525],[d7527,f7526],[d7527,f7527],[d7529,f7528],[d7529,f7529],[d7531,f7530],[d7531,f7531],[d7533,f7532],[d7533,f7533],[d7535,f7534],[d7535,f7535],[d7537,f7536],[d7537,f7537],[d7539,f7538],[d7539,f7539],[d7541,f7540],[d7541,f7541],[d7543,f7542],[d7543,f7543],[d7545,f7544],[d7545,f7545],[d7547,f7546],[d7547,f7547],[d7549,f7548],[d7549,f7549],[d7551,f7550],[d7551,f7551],[d7553,f7552],[d7553,f7553],[d7555,f7554],[d7555,f7555],[d7557,f7556],[d7557,f7557],[d7559,f7558],[d7559,f7559],[d7561,f7560],[d7561,f7561],[d7563,f7562],[d7563,f7563],[d7565,f7564],[d7565,f7565],[d7567,f7566],[d7567,f7567],[d7569,f7568],[d7569,f7569],[d7571,f7570],[d7571,f7571],[d7573,f7572],[d7573,f7573],[d7575,f7574],[d7575,f7575],[d7577,f7576],[d7577,f7577],[d7579,f7578],[d7579,f7579],[d7581,f7580],[d7581,f7581],[d7583,f7582],[d7583,f7583],[d7585,f7584],[d7585,f7585],[d7587,f7586],[d7587,f7587],[d7589,f7588],[d7589,f7589],[d7591,f7590],[d7591,f7591],[d7593,f7592],[d7593,f7593],[d7595,f7594],[d7595,f7595],[d7597,f7596],[d7597,f7597],[d7599,f7598],[d7599,f7599],[d7601,f7600],[d7601,f7601],[d7603,f7602],[d7603,f7603],[d7605,f7604],[d7605,f7605],[d7607,f7606],[d7607,f7607],[d7609,f7608],[d7609,f7609],[d7611,f7610],[d7611,f7611],[d7613,f7612],[d7613,f7613],[d7615,f7614],[d7615,f7615],[d7617,f7616],[d7617,f7617],[d7619,f7618],[d7619,f7619],[d7621,f7620],[d7621,f7621],[d7623,f7622],[d7623,f7623],[d7625,f7624],[d7625,f7625],[d7627,f7626],[d7627,f7627],[d7629,f7628],[d7629,f7629],[d7631,f7630],[d7631,f7631],[d7633,f7632],[d7633,f7633],[d7635,f7634],[d7635,f7635],[d7637,f7636],[d7637,f7637],[d7639,f7638],[d7639,f7639],[d7641,f7640],[d7641,f7641],[d7643,f7642],[d7643,f7643],[d7645,f7644],[d7645,f7645],[d7647,f7646],[d7647,f7647],[d7649,f7648],[d7649,f7649],[d7651,f7650],[d7651,f7651],[d7653,f7652],[d7653,f7653],[d7655,f7654],[d7655,f7655],[d7657,f7656],[d7657,f7657],[d7659,f7658],[d7659,f7659],[d7661,f7660],[d7661,f7661],[d7663,f7662],[d7663,f7663],[d7665,f7664],[d7665,f7665],[d7667,f7666],[d7667,f7667],[d7669,f7668],[d7669,f7669],[d7671,f7670],[d7671,f7671],[d7673,f7672],[d7673,f7673],[d7675,f7674],[d7675,f7675],[d7677,f7676],[d7677,f7677],[d7679,f7678],[d7679,f7679],[d7681,f7680],[d7681,f7681],[d7683,f7682],[d7683,f7683],[d7685,f7684],[d7685,f7685],[d7687,f7686],[d7687,f7687],[d7689,f7688],[d7689,f7689],[d7691,f7690],[d7691,f7691],[d7693,f7692],[d7693,f7693],[d7695,f7694],[d7695,f7695],[d7697,f7696],[d7697,f7697],[d7699,f7698],[d7699,f7699],[d7701,f7700],[d7701,f7701],[d7703,f7702],[d7703,f7703],[d7705,f7704],[d7705,f7705],[d7707,f7706],[d7707,f7707],[d7709,f7708],[d7709,f7709],[d7711,f7710],[d7711,f7711],[d7713,f7712],[d7713,f7713],[d7715,f7714],[d7715,f7715],[d7717,f7716],[d7717,f7717],[d7719,f7718],[d7719,f7719],[d7721,f7720],[d7721,f7721],[d7723,f7722],[d7723,f7723],[d7725,f7724],[d7725,f7725],[d7727,f7726],[d7727,f7727],[d7729,f7728],[d7729,f7729],[d7731,f7730],[d7731,f7731],[d7733,f7732],[d7733,f7733],[d7735,f7734],[d7735,f7735],[d7737,f7736],[d7737,f7737],[d7739,f7738],[d7739,f7739],[d7741,f7740],[d7741,f7741],[d7743,f7742],[d7743,f7743],[d7745,f7744],[d7745,f7745],[d7747,f7746],[d7747,f7747],[d7749,f7748],[d7749,f7749],[d7751,f7750],[d7751,f7751],[d7753,f7752],[d7753,f7753],[d7755,f7754],[d7755,f7755],[d7757,f7756],[d7757,f7757],[d7759,f7758],[d7759,f7759],[d7761,f7760],[d7761,f7761],[d7763,f7762],[d7763,f7763],[d7765,f7764],[d7765,f7765],[d7767,f7766],[d7767,f7767],[d7769,f7768],[d7769,f7769],[d7771,f7770],[d7771,f7771],[d7773,f7772],[d7773,f7773],[d7775,f7774],[d7775,f7775],[d7777,f7776],[d7777,f7777],[d7779,f7778],[d7779,f7779],[d7781,f7780],[d7781,f7781],[d7783,f7782],[d7783,f7783],[d7785,f7784],[d7785,f7785],[d7787,f7786],[d7787,f7787],[d7789,f7788],[d7789,f7789],[d7791,f7790],[d7791,f7791],[d7793,f7792],[d7793,f7793],[d7795,f7794],[d7795,f7795],[d7797,f7796],[d7797,f7797],[d7799,f7798],[d7799,f7799],[d7801,f7800],[d7801,f7801],[d7803,f7802],[d7803,f7803],[d7805,f7804],[d7805,f7805],[d7807,f7806],[d7807,f7807],[d7809,f7808],[d7809,f7809],[d7811,f7810],[d7811,f7811],[d7813,f7812],[d7813,f7813],[d7815,f7814],[d7815,f7815],[d7817,f7816],[d7817,f7817],[d7819,f7818],[d7819,f7819],[d7821,f7820],[d7821,f7821],[d7823,f7822],[d7823,f7823],[d7825,f7824],[d7825,f7825],[d7827,f7826],[d7827,f7827],[d7829,f7828],[d7829,f7829],[d7831,f7830],[d7831,f7831],[d7833,f7832],[d7833,f7833],[d7835,f7834],[d7835,f7835],[d7837,f7836],[d7837,f7837],[d7839,f7838],[d7839,f7839],[d7841,f7840],[d7841,f7841],[d7843,f7842],[d7843,f7843],[d7845,f7844],[d7845,f7845],[d7847,f7846],[d7847,f7847],[d7849,f7848],[d7849,f7849],[d7851,f7850],[d7851,f7851],[d7853,f7852],[d7853,f7853],[d7855,f7854],[d7855,f7855],[d7857,f7856],[d7857,f7857],[d7859,f7858],[d7859,f7859],[d7861,f7860],[d7861,f7861],[d7863,f7862],[d7863,f7863],[d7865,f7864],[d7865,f7865],[d7867,f7866],[d7867,f7867],[d7869,f7868],[d7869,f7869],[d7871,f7870],[d7871,f7871],[d7873,f7872],[d7873,f7873],[d7875,f7874],[d7875,f7875],[d7877,f7876],[d7877,f7877],[d7879,f7878],[d7879,f7879],[d7881,f7880],[d7881,f7881],[d7883,f7882],[d7883,f7883],[d7885,f7884],[d7885,f7885],[d7887,f7886],[d7887,f7887],[d7889,f7888],[d7889,f7889],[d7891,f7890],[d7891,f7891],[d7893,f7892],[d7893,f7893],[d7895,f7894],[d7895,f7895],[d7897,f7896],[d7897,f7897],[d7899,f7898],[d7899,f7899],[d7901,f7900],[d7901,f7901],[d7903,f7902],[d7903,f7903],[d7905,f7904],[d7905,f7905],[d7907,f7906],[d7907,f7907],[d7909,f7908],[d7909,f7909],[d7911,f7910],[d7911,f7911],[d7913,f7912],[d7913,f7913],[d7915,f7914],[d7915,f7915],[d7917,f7916],[d7917,f7917],[d7919,f7918],[d7919,f7919],[d7921,f7920],[d7921,f7921],[d7923,f7922],[d7923,f7923],[d7925,f7924],[d7925,f7925],[d7927,f7926],[d7927,f7927],[d7929,f7928],[d7929,f7929],[d7931,f7930],[d7931,f7931],[d7933,f7932],[d7933,f7933],[d7935,f7934],[d7935,f7935],[d7937,f7936],[d7937,f7937],[d7939,f7938],[d7939,f7939],[d7941,f7940],[d7941,f7941],[d7943,f7942],[d7943,f7943],[d7945,f7944],[d7945,f7945],[d7947,f7946],[d7947,f7947],[d7949,f7948],[d7949,f7949],[d7951,f7950],[d7951,f7951],[d7953,f7952],[d7953,f7953],[d7955,f7954],[d7955,f7955],[d7957,f7956],[d7957,f7957],[d7959,f7958],[d7959,f7959],[d7961,f7960],[d7961,f7961],[d7963,f7962],[d7963,f7963],[d7965,f7964],[d7965,f7965],[d7967,f7966],[d7967,f7967],[d7969,f7968],[d7969,f7969],[d7971,f7970],[d7971,f7971],[d7973,f7972],[d7973,f7973],[d7975,f7974],[d7975,f7975],[d7977,f7976],[d7977,f7977],[d7979,f7978],[d7979,f7979],[d7981,f7980],[d7981,f7981],[d7983,f7982],[d7983,f7983],[d7985,f7984],[d7985,f7985],[d7987,f7986],[d7987,f7987],[d7989,f7988],[d7989,f7989],[d7991,f7990],[d7991,f7991],[d7993,f7992],[d7993,f7993],[d7995,f7994],[d7995,f7995],[d7997,f7996],[d7997,f7997],[d7999,f7998],[d7999,f7999],[d8001,f8000],[d8001,f8001],[d8003,f8002],[d8003,f8003],[d8005,f8004],[d8005,f8005],[d8007,f8006],[d8007,f8007],[d8009,f8008],[d8009,f8009],[d8011,f8010],[d8011,f8011],[d8013,f8012],[d8013,f8013],[d8015,f8014],[d8015,f8015],[d8017,f8016],[d8017,f8017],[d8019,f8018],[d8019,f8019],[d8021,f8020],[d8021,f8021],[d8023,f8022],[d8023,f8023],[d8025,f8024],[d8025,f8025],[d8027,f8026],[d8027,f8027],[d8029,f8028],[d8029,f8029],[d8031,f8030],[d8031,f8031],[d8033,f8032],[d8033,f8033],[d8035,f8034],[d8035,f8035],[d8037,f8036],[d8037,f8037],[d8039,f8038],[d8039,f8039],[d8041,f8040],[d8041,f8041],[d8043,f8042],[d8043,f8043],[d8045,f8044],[d8045,f8045],[d8047,f8046],[d8047,f8047],[d8049,f8048],[d8049,f8049],[d8051,f8050],[d8051,f8051],[d8053,f8052],[d8053,f8053],[d8055,f8054],[d8055,f8055],[d8057,f8056],[d8057,f8057],[d8059,f8058],[d8059,f8059],[d8061,f8060],[d8061,f8061],[d8063,f8062],[d8063,f8063],[d8065,f8064],[d8065,f8065],[d8067,f8066],[d8067,f8067],[d8069,f8068],[d8069,f8069],[d8071,f8070],[d8071,f8071],[d8073,f8072],[d8073,f8073],[d8075,f8074],[d8075,f8075],[d8077,f8076],[d8077,f8077],[d8079,f8078],[d8079,f8079],[d8081,f8080],[d8081,f8081],[d8083,f8082],[d8083,f8083],[d8085,f8084],[d8085,f8085],[d8087,f8086],[d8087,f8087],[d8089,f8088],[d8089,f8089],[d8091,f8090],[d8091,f8091],[d8093,f8092],[d8093,f8093],[d8095,f8094],[d8095,f8095],[d8097,f8096],[d8097,f8097],[d8099,f8098],[d8099,f8099],[d8101,f8100],[d8101,f8101],[d8103,f8102],[d8103,f8103],[d8105,f8104],[d8105,f8105],[d8107,f8106],[d8107,f8107],[d8109,f8108],[d8109,f8109],[d8111,f8110],[d8111,f8111],[d8113,f8112],[d8113,f8113],[d8115,f8114],[d8115,f8115],[d8117,f8116],[d8117,f8117],[d8119,f8118],[d8119,f8119],[d8121,f8120],[d8121,f8121],[d8123,f8122],[d8123,f8123],[d8125,f8124],[d8125,f8125],[d8127,f8126],[d8127,f8127],[d8129,f8128],[d8129,f8129],[d8131,f8130],[d8131,f8131],[d8133,f8132],[d8133,f8133],[d8135,f8134],[d8135,f8135],[d8137,f8136],[d8137,f8137],[d8139,f8138],[d8139,f8139],[d8141,f8140],[d8141,f8141],[d8143,f8142],[d8143,f8143],[d8145,f8144],[d8145,f8145],[d8147,f8146],[d8147,f8147],[d8149,f8148],[d8149,f8149],[d8151,f8150],[d8151,f8151],[d8153,f8152],[d8153,f8153],[d8155,f8154],[d8155,f8155],[d8157,f8156],[d8157,f8157],[d8159,f8158],[d8159,f8159],[d8161,f8160],[d8161,f8161],[d8163,f8162],[d8163,f8163],[d8165,f8164],[d8165,f8165],[d8167,f8166],[d8167,f8167],[d8169,f8168],[d8169,f8169],[d8171,f8170],[d8171,f8171],[d8173,f8172],[d8173,f8173],[d8175,f8174],[d8175,f8175],[d8177,f8176],[d8177,f8177],[d8179,f8178],[d8179,f8179],[d8181,f8180],[d8181,f8181],[d8183,f8182],[d8183,f8183],[d8185,f8184],[d8185,f8185],[d8187,f8186],[d8187,f8187],[d8189,f8188],[d8189,f8189],[d8191,f8190],[d8191,f8191],[d8193,f8192],[d8193,f8193],[d8195,f8194],[d8195,f8195],[d8197,f8196],[d8197,f8197],[d8199,f8198],[d8199,f8199],[d8201,f8200],[d8201,f8201],[d8203,f8202],[d8203,f8203],[d8205,f8204],[d8205,f8205],[d8207,f8206],[d8207,f8207],[d8209,f8208],[d8209,f8209],[d8211,f8210],[d8211,f8211],[d8213,f8212],[d8213,f8213],[d8215,f8214],[d8215,f8215],[d8217,f8216],[d8217,f8217],[d8219,f8218],[d8219,f8219],[d8221,f8220],[d8221,f8221],[d8223,f8222],[d8223,f8223],[d8225,f8224],[d8225,f8225],[d8227,f8226],[d8227,f8227],[d8229,f8228],[d8229,f8229],[d8231,f8230],[d8231,f8231],[d8233,f8232],[d8233,f8233],[d8235,f8234],[d8235,f8235],[d8237,f8236],[d8237,f8237],[d8239,f8238],[d8239,f8239],[d8241,f8240],[d8241,f8241],[d8243,f8242],[d8243,f8243],[d8245,f8244],[d8245,f8245],[d8247,f8246],[d8247,f8247],[d8249,f8248],[d8249,f8249],[d8251,f8250],[d8251,f8251],[d8253,f8252],[d8253,f8253],[d8255,f8254],[d8255,f8255],[d8257,f8256],[d8257,f8257],[d8259,f8258],[d8259,f8259],[d8261,f8260],[d8261,f8261],[d8263,f8262],[d8263,f8263],[d8265,f8264],[d8265,f8265],[d8267,f8266],[d8267,f8267],[d8269,f8268],[d8269,f8269],[d8271,f8270],[d8271,f8271],[d8273,f8272],[d8273,f8273],[d8275,f8274],[d8275,f8275],[d8277,f8276],[d8277,f8277],[d8279,f8278],[d8279,f8279],[d8281,f8280],[d8281,f8281],[d8283,f8282],[d8283,f8283],[d8285,f8284],[d8285,f8285],[d8287,f8286],[d8287,f8287],[d8289,f8288],[d8289,f8289],[d8291,f8290],[d8291,f8291],[d8293,f8292],[d8293,f8293],[d8295,f8294],[d8295,f8295],[d8297,f8296],[d8297,f8297],[d8299,f8298],[d8299,f8299],[d8301,f8300],[d8301,f8301],[d8303,f8302],[d8303,f8303],[d8305,f8304],[d8305,f8305],[d8307,f8306],[d8307,f8307],[d8309,f8308],[d8309,f8309],[d8311,f8310],[d8311,f8311],[d8313,f8312],[d8313,f8313],[d8315,f8314],[d8315,f8315],[d8317,f8316],[d8317,f8317],[d8319,f8318],[d8319,f8319],[d8321,f8320],[d8321,f8321],[d8323,f8322],[d8323,f8323],[d8325,f8324],[d8325,f8325],[d8327,f8326],[d8327,f8327],[d8329,f8328],[d8329,f8329],[d8331,f8330],[d8331,f8331],[d8333,f8332],[d8333,f8333],[d8335,f8334],[d8335,f8335],[d8337,f8336],[d8337,f8337],[d8339,f8338],[d8339,f8339],[d8341,f8340],[d8341,f8341],[d8343,f8342],[d8343,f8343],[d8345,f8344],[d8345,f8345],[d8347,f8346],[d8347,f8347],[d8349,f8348],[d8349,f8349],[d8351,f8350],[d8351,f8351],[d8353,f8352],[d8353,f8353],[d8355,f8354],[d8355,f8355],[d8357,f8356],[d8357,f8357],[d8359,f8358],[d8359,f8359],[d8361,f8360],[d8361,f8361],[d8363,f8362],[d8363,f8363],[d8365,f8364],[d8365,f8365],[d8367,f8366],[d8367,f8367],[d8369,f8368],[d8369,f8369],[d8371,f8370],[d8371,f8371],[d8373,f8372],[d8373,f8373],[d8375,f8374],[d8375,f8375],[d8377,f8376],[d8377,f8377],[d8379,f8378],[d8379,f8379],[d8381,f8380],[d8381,f8381],[d8383,f8382],[d8383,f8383],[d8385,f8384],[d8385,f8385],[d8387,f8386],[d8387,f8387],[d8389,f8388],[d8389,f8389],[d8391,f8390],[d8391,f8391],[d8393,f8392],[d8393,f8393],[d8395,f8394],[d8395,f8395],[d8397,f8396],[d8397,f8397],[d8399,f8398],[d8399,f8399],[d8401,f8400],[d8401,f8401],[d8403,f8402],[d8403,f8403],[d8405,f8404],[d8405,f8405],[d8407,f8406],[d8407,f8407],[d8409,f8408],[d8409,f8409],[d8411,f8410],[d8411,f8411],[d8413,f8412],[d8413,f8413],[d8415,f8414],[d8415,f8415],[d8417,f8416],[d8417,f8417],[d8419,f8418],[d8419,f8419],[d8421,f8420],[d8421,f8421],[d8423,f8422],[d8423,f8423],[d8425,f8424],[d8425,f8425],[d8427,f8426],[d8427,f8427],[d8429,f8428],[d8429,f8429],[d8431,f8430],[d8431,f8431],[d8433,f8432],[d8433,f8433],[d8435,f8434],[d8435,f8435],[d8437,f8436],[d8437,f8437],[d8439,f8438],[d8439,f8439],[d8441,f8440],[d8441,f8441],[d8443,f8442],[d8443,f8443],[d8445,f8444],[d8445,f8445],[d8447,f8446],[d8447,f8447],[d8449,f8448],[d8449,f8449],[d8451,f8450],[d8451,f8451],[d8453,f8452],[d8453,f8453],[d8455,f8454],[d8455,f8455],[d8457,f8456],[d8457,f8457],[d8459,f8458],[d8459,f8459],[d8461,f8460],[d8461,f8461],[d8463,f8462],[d8463,f8463],[d8465,f8464],[d8465,f8465],[d8467,f8466],[d8467,f8467],[d8469,f8468],[d8469,f8469],[d8471,f8470],[d8471,f8471],[d8473,f8472],[d8473,f8473],[d8475,f8474],[d8475,f8475],[d8477,f8476],[d8477,f8477],[d8479,f8478],[d8479,f8479],[d8481,f8480],[d8481,f8481],[d8483,f8482],[d8483,f8483],[d8485,f8484],[d8485,f8485],[d8487,f8486],[d8487,f8487],[d8489,f8488],[d8489,f8489],[d8491,f8490],[d8491,f8491],[d8493,f8492],[d8493,f8493],[d8495,f8494],[d8495,f8495],[d8497,f8496],[d8497,f8497],[d8499,f8498],[d8499,f8499],[d8501,f8500],[d8501,f8501],[d8503,f8502],[d8503,f8503],[d8505,f8504],[d8505,f8505],[d8507,f8506],[d8507,f8507],[d8509,f8508],[d8509,f8509],[d8511,f8510],[d8511,f8511],[d8513,f8512],[d8513,f8513],[d8515,f8514],[d8515,f8515],[d8517,f8516],[d8517,f8517],[d8519,f8518],[d8519,f8519],[d8521,f8520],[d8521,f8521],[d8523,f8522],[d8523,f8523],[d8525,f8524],[d8525,f8525],[d8527,f8526],[d8527,f8527],[d8529,f8528],[d8529,f8529],[d8531,f8530],[d8531,f8531],[d8533,f8532],[d8533,f8533],[d8535,f8534],[d8535,f8535],[d8537,f8536],[d8537,f8537],[d8539,f8538],[d8539,f8539],[d8541,f8540],[d8541,f8541],[d8543,f8542],[d8543,f8543],[d8545,f8544],[d8545,f8545],[d8547,f8546],[d8547,f8547],[d8549,f8548],[d8549,f8549],[d8551,f8550],[d8551,f8551],[d8553,f8552],[d8553,f8553],[d8555,f8554],[d8555,f8555],[d8557,f8556],[d8557,f8557],[d8559,f8558],[d8559,f8559],[d8561,f8560],[d8561,f8561],[d8563,f8562],[d8563,f8563],[d8565,f8564],[d8565,f8565],[d8567,f8566],[d8567,f8567],[d8569,f8568],[d8569,f8569],[d8571,f8570],[d8571,f8571],[d8573,f8572],[d8573,f8573],[d8575,f8574],[d8575,f8575],[d8577,f8576],[d8577,f8577],[d8579,f8578],[d8579,f8579],[d8581,f8580],[d8581,f8581],[d8583,f8582],[d8583,f8583],[d8585,f8584],[d8585,f8585],[d8587,f8586],[d8587,f8587],[d8589,f8588],[d8589,f8589],[d8591,f8590],[d8591,f8591],[d8593,f8592],[d8593,f8593],[d8595,f8594],[d8595,f8595],[d8597,f8596],[d8597,f8597],[d8599,f8598],[d8599,f8599],[d8601,f8600],[d8601,f8601],[d8603,f8602],[d8603,f8603],[d8605,f8604],[d8605,f8605],[d8607,f8606],[d8607,f8607],[d8609,f8608],[d8609,f8609],[d8611,f8610],[d8611,f8611],[d8613,f8612],[d8613,f8613],[d8615,f8614],[d8615,f8615],[d8617,f8616],[d8617,f8617],[d8619,f8618],[d8619,f8619],[d8621,f8620],[d8621,f8621],[d8623,f8622],[d8623,f8623],[d8625,f8624],[d8625,f8625],[d8627,f8626],[d8627,f8627],[d8629,f8628],[d8629,f8629],[d8631,f8630],[d8631,f8631],[d8633,f8632],[d8633,f8633],[d8635,f8634],[d8635,f8635],[d8637,f8636],[d8637,f8637],[d8639,f8638],[d8639,f8639],[d8641,f8640],[d8641,f8641],[d8643,f8642],[d8643,f8643],[d8645,f8644],[d8645,f8645],[d8647,f8646],[d8647,f8647],[d8649,f8648],[d8649,f8649],[d8651,f8650],[d8651,f8651],[d8653,f8652],[d8653,f8653],[d8655,f8654],[d8655,f8655],[d8657,f8656],[d8657,f8657],[d8659,f8658],[d8659,f8659],[d8661,f8660],[d8661,f8661],[d8663,f8662],[d8663,f8663],[d8665,f8664],[d8665,f8665],[d8667,f8666],[d8667,f8667],[d8669,f8668],[d8669,f8669],[d8671,f8670],[d8671,f8671],[d8673,f8672],[d8673,f8673],[d8675,f8674],[d8675,f8675],[d8677,f8676],[d8677,f8677],[d8679,f8678],[d8679,f8679],[d8681,f8680],[d8681,f8681],[d8683,f8682],[d8683,f8683],[d8685,f8684],[d8685,f8685],[d8687,f8686],[d8687,f8687],[d8689,f8688],[d8689,f8689],[d8691,f8690],[d8691,f8691],[d8693,f8692],[d8693,f8693],[d8695,f8694],[d8695,f8695],[d8697,f8696],[d8697,f8697],[d8699,f8698],[d8699,f8699],[d8701,f8700],[d8701,f8701],[d8703,f8702],[d8703,f8703],[d8705,f8704],[d8705,f8705],[d8707,f8706],[d8707,f8707],[d8709,f8708],[d8709,f8709],[d8711,f8710],[d8711,f8711],[d8713,f8712],[d8713,f8713],[d8715,f8714],[d8715,f8715],[d8717,f8716],[d8717,f8717],[d8719,f8718],[d8719,f8719],[d8721,f8720],[d8721,f8721],[d8723,f8722],[d8723,f8723],[d8725,f8724],[d8725,f8725],[d8727,f8726],[d8727,f8727],[d8729,f8728],[d8729,f8729],[d8731,f8730],[d8731,f8731],[d8733,f8732],[d8733,f8733],[d8735,f8734],[d8735,f8735],[d8737,f8736],[d8737,f8737],[d8739,f8738],[d8739,f8739],[d8741,f8740],[d8741,f8741],[d8743,f8742],[d8743,f8743],[d8745,f8744],[d8745,f8745],[d8747,f8746],[d8747,f8747],[d8749,f8748],[d8749,f8749],[d8751,f8750],[d8751,f8751],[d8753,f8752],[d8753,f8753],[d8755,f8754],[d8755,f8755],[d8757,f8756],[d8757,f8757],[d8759,f8758],[d8759,f8759],[d8761,f8760],[d8761,f8761],[d8763,f8762],[d8763,f8763],[d8765,f8764],[d8765,f8765],[d8767,f8766],[d8767,f8767],[d8769,f8768],[d8769,f8769],[d8771,f8770],[d8771,f8771],[d8773,f8772],[d8773,f8773],[d8775,f8774],[d8775,f8775],[d8777,f8776],[d8777,f8777],[d8779,f8778],[d8779,f8779],[d8781,f8780],[d8781,f8781],[d8783,f8782],[d8783,f8783],[d8785,f8784],[d8785,f8785],[d8787,f8786],[d8787,f8787],[d8789,f8788],[d8789,f8789],[d8791,f8790],[d8791,f8791],[d8793,f8792],[d8793,f8793],[d8795,f8794],[d8795,f8795],[d8797,f8796],[d8797,f8797],[d8799,f8798],[d8799,f8799],[d8801,f8800],[d8801,f8801],[d8803,f8802],[d8803,f8803],[d8805,f8804],[d8805,f8805],[d8807,f8806],[d8807,f8807],[d8809,f8808],[d8809,f8809],[d8811,f8810],[d8811,f8811],[d8813,f8812],[d8813,f8813],[d8815,f8814],[d8815,f8815],[d8817,f8816],[d8817,f8817],[d8819,f8818],[d8819,f8819],[d8821,f8820],[d8821,f8821],[d8823,f8822],[d8823,f8823],[d8825,f8824],[d8825,f8825],[d8827,f8826],[d8827,f8827],[d8829,f8828],[d8829,f8829],[d8831,f8830],[d8831,f8831],[d8833,f8832],[d8833,f8833],[d8835,f8834],[d8835,f8835],[d8837,f8836],[d8837,f8837],[d8839,f8838],[d8839,f8839],[d8841,f8840],[d8841,f8841],[d8843,f8842],[d8843,f8843],[d8845,f8844],[d8845,f8845],[d8847,f8846],[d8847,f8847],[d8849,f8848],[d8849,f8849],[d8851,f8850],[d8851,f8851],[d8853,f8852],[d8853,f8853],[d8855,f8854],[d8855,f8855],[d8857,f8856],[d8857,f8857],[d8859,f8858],[d8859,f8859],[d8861,f8860],[d8861,f8861],[d8863,f8862],[d8863,f8863],[d8865,f8864],[d8865,f8865],[d8867,f8866],[d8867,f8867],[d8869,f8868],[d8869,f8869],[d8871,f8870],[d8871,f8871],[d8873,f8872],[d8873,f8873],[d8875,f8874],[d8875,f8875],[d8877,f8876],[d8877,f8877],[d8879,f8878],[d8879,f8879],[d8881,f8880],[d8881,f8881],[d8883,f8882],[d8883,f8883],[d8885,f8884],[d8885,f8885],[d8887,f8886],[d8887,f8887],[d8889,f8888],[d8889,f8889],[d8891,f8890],[d8891,f8891],[d8893,f8892],[d8893,f8893],[d8895,f8894],[d8895,f8895],[d8897,f8896],[d8897,f8897],[d8899,f8898],[d8899,f8899],[d8901,f8900],[d8901,f8901],[d8903,f8902],[d8903,f8903],[d8905,f8904],[d8905,f8905],[d8907,f8906],[d8907,f8907],[d8909,f8908],[d8909,f8909],[d8911,f8910],[d8911,f8911],[d8913,f8912],[d8913,f8913],[d8915,f8914],[d8915,f8915],[d8917,f8916],[d8917,f8917],[d8919,f8918],[d8919,f8919],[d8921,f8920],[d8921,f8921],[d8923,f8922],[d8923,f8923],[d8925,f8924],[d8925,f8925],[d8927,f8926],[d8927,f8927],[d8929,f8928],[d8929,f8929],[d8931,f8930],[d8931,f8931],[d8933,f8932],[d8933,f8933],[d8935,f8934],[d8935,f8935],[d8937,f8936],[d8937,f8937],[d8939,f8938],[d8939,f8939],[d8941,f8940],[d8941,f8941],[d8943,f8942],[d8943,f8943],[d8945,f8944],[d8945,f8945],[d8947,f8946],[d8947,f8947],[d8949,f8948],[d8949,f8949],[d8951,f8950],[d8951,f8951],[d8953,f8952],[d8953,f8953],[d8955,f8954],[d8955,f8955],[d8957,f8956],[d8957,f8957],[d8959,f8958],[d8959,f8959],[d8961,f8960],[d8961,f8961],[d8963,f8962],[d8963,f8963],[d8965,f8964],[d8965,f8965],[d8967,f8966],[d8967,f8967],[d8969,f8968],[d8969,f8969],[d8971,f8970],[d8971,f8971],[d8973,f8972],[d8973,f8973],[d8975,f8974],[d8975,f8975],[d8977,f8976],[d8977,f8977],[d8979,f8978],[d8979,f8979],[d8981,f8980],[d8981,f8981],[d8983,f8982],[d8983,f8983],[d8985,f8984],[d8985,f8985],[d8987,f8986],[d8987,f8987],[d8989,f8988],[d8989,f8989],[d8991,f8990],[d8991,f8991],[d8993,f8992],[d8993,f8993],[d8995,f8994],[d8995,f8995],[d8997,f8996],[d8997,f8997],[d8999,f8998],[d8999,f8999],[d9001,f9000],[d9001,f9001],[d9003,f9002],[d9003,f9003],[d9005,f9004],[d9005,f9005],[d9007,f9006],[d9007,f9007],[d9009,f9008],[d9009,f9009],[d9011,f9010],[d9011,f9011],[d9013,f9012],[d9013,f9013],[d9015,f9014],[d9015,f9015],[d9017,f9016],[d9017,f9017],[d9019,f9018],[d9019,f9019],[d9021,f9020],[d9021,f9021],[d9023,f9022],[d9023,f9023],[d9025,f9024],[d9025,f9025],[d9027,f9026],[d9027,f9027],[d9029,f9028],[d9029,f9029],[d9031,f9030],[d9031,f9031],[d9033,f9032],[d9033,f9033],[d9035,f9034],[d9035,f9035],[d9037,f9036],[d9037,f9037],[d9039,f9038],[d9039,f9039],[d9041,f9040],[d9041,f9041],[d9043,f9042],[d9043,f9043],[d9045,f9044],[d9045,f9045],[d9047,f9046],[d9047,f9047],[d9049,f9048],[d9049,f9049],[d9051,f9050],[d9051,f9051],[d9053,f9052],[d9053,f9053],[d9055,f9054],[d9055,f9055],[d9057,f9056],[d9057,f9057],[d9059,f9058],[d9059,f9059],[d9061,f9060],[d9061,f9061],[d9063,f9062],[d9063,f9063],[d9065,f9064],[d9065,f9065],[d9067,f9066],[d9067,f9067],[d9069,f9068],[d9069,f9069],[d9071,f9070],[d9071,f9071],[d9073,f9072],[d9073,f9073],[d9075,f9074],[d9075,f9075],[d9077,f9076],[d9077,f9077],[d9079,f9078],[d9079,f9079],[d9081,f9080],[d9081,f9081],[d9083,f9082],[d9083,f9083],[d9085,f9084],[d9085,f9085],[d9087,f9086],[d9087,f9087],[d9089,f9088],[d9089,f9089],[d9091,f9090],[d9091,f9091],[d9093,f9092],[d9093,f9093],[d9095,f9094],[d9095,f9095],[d9097,f9096],[d9097,f9097],[d9099,f9098],[d9099,f9099],[d9101,f9100],[d9101,f9101],[d9103,f9102],[d9103,f9103],[d9105,f9104],[d9105,f9105],[d9107,f9106],[d9107,f9107],[d9109,f9108],[d9109,f9109],[d9111,f9110],[d9111,f9111],[d9113,f9112],[d9113,f9113],[d9115,f9114],[d9115,f9115],[d9117,f9116],[d9117,f9117],[d9119,f9118],[d9119,f9119],[d9121,f9120],[d9121,f9121],[d9123,f9122],[d9123,f9123],[d9125,f9124],[d9125,f9125],[d9127,f9126],[d9127,f9127],[d9129,f9128],[d9129,f9129],[d9131,f9130],[d9131,f9131],[d9133,f9132],[d9133,f9133],[d9135,f9134],[d9135,f9135],[d9137,f9136],[d9137,f9137],[d9139,f9138],[d9139,f9139],[d9141,f9140],[d9141,f9141],[d9143,f9142],[d9143,f9143],[d9145,f9144],[d9145,f9145],[d9147,f9146],[d9147,f9147],[d9149,f9148],[d9149,f9149],[d9151,f9150],[d9151,f9151],[d9153,f9152],[d9153,f9153],[d9155,f9154],[d9155,f9155],[d9157,f9156],[d9157,f9157],[d9159,f9158],[d9159,f9159],[d9161,f9160],[d9161,f9161],[d9163,f9162],[d9163,f9163],[d9165,f9164],[d9165,f9165],[d9167,f9166],[d9167,f9167],[d9169,f9168],[d9169,f9169],[d9171,f9170],[d9171,f9171],[d9173,f9172],[d9173,f9173],[d9175,f9174],[d9175,f9175],[d9177,f9176],[d9177,f9177],[d9179,f9178],[d9179,f9179],[d9181,f9180],[d9181,f9181],[d9183,f9182],[d9183,f9183],[d9185,f9184],[d9185,f9185],[d9187,f9186],[d9187,f9187],[d9189,f9188],[d9189,f9189],[d9191,f9190],[d9191,f9191],[d9193,f9192],[d9193,f9193],[d9195,f9194],[d9195,f9195],[d9197,f9196],[d9197,f9197],[d9199,f9198],[d9199,f9199],[d9201,f9200],[d9201,f9201],[d9203,f9202],[d9203,f9203],[d9205,f9204],[d9205,f9205],[d9207,f9206],[d9207,f9207],[d9209,f9208],[d9209,f9209],[d9211,f9210],[d9211,f9211],[d9213,f9212],[d9213,f9213],[d9215,f9214],[d9215,f9215],[d9217,f9216],[d9217,f9217],[d9219,f9218],[d9219,f9219],[d9221,f9220],[d9221,f9221],[d9223,f9222],[d9223,f9223],[d9225,f9224],[d9225,f9225],[d9227,f9226],[d9227,f9227],[d9229,f9228],[d9229,f9229],[d9231,f9230],[d9231,f9231],[d9233,f9232],[d9233,f9233],[d9235,f9234],[d9235,f9235],[d9237,f9236],[d9237,f9237],[d9239,f9238],[d9239,f9239],[d9241,f9240],[d9241,f9241],[d9243,f9242],[d9243,f9243],[d9245,f9244],[d9245,f9245],[d9247,f9246],[d9247,f9247],[d9249,f9248],[d9249,f9249],[d9251,f9250],[d9251,f9251],[d9253,f9252],[d9253,f9253],[d9255,f9254],[d9255,f9255],[d9257,f9256],[d9257,f9257],[d9259,f9258],[d9259,f9259],[d9261,f9260],[d9261,f9261],[d9263,f9262],[d9263,f9263],[d9265,f9264],[d9265,f9265],[d9267,f9266],[d9267,f9267],[d9269,f9268],[d9269,f9269],[d9271,f9270],[d9271,f9271],[d9273,f9272],[d9273,f9273],[d9275,f9274],[d9275,f9275],[d9277,f9276],[d9277,f9277],[d9279,f9278],[d9279,f9279],[d9281,f9280],[d9281,f9281],[d9283,f9282],[d9283,f9283],[d9285,f9284],[d9285,f9285],[d9287,f9286],[d9287,f9287],[d9289,f9288],[d9289,f9289],[d9291,f9290],[d9291,f9291],[d9293,f9292],[d9293,f9293],[d9295,f9294],[d9295,f9295],[d9297,f9296],[d9297,f9297],[d9299,f9298],[d9299,f9299],[d9301,f9300],[d9301,f9301],[d9303,f9302],[d9303,f9303],[d9305,f9304],[d9305,f9305],[d9307,f9306],[d9307,f9307],[d9309,f9308],[d9309,f9309],[d9311,f9310],[d9311,f9311],[d9313,f9312],[d9313,f9313],[d9315,f9314],[d9315,f9315],[d9317,f9316],[d9317,f9317],[d9319,f9318],[d9319,f9319],[d9321,f9320],[d9321,f9321],[d9323,f9322],[d9323,f9323],[d9325,f9324],[d9325,f9325],[d9327,f9326],[d9327,f9327],[d9329,f9328],[d9329,f9329],[d9331,f9330],[d9331,f9331],[d9333,f9332],[d9333,f9333],[d9335,f9334],[d9335,f9335],[d9337,f9336],[d9337,f9337],[d9339,f9338],[d9339,f9339],[d9341,f9340],[d9341,f9341],[d9343,f9342],[d9343,f9343],[d9345,f9344],[d9345,f9345],[d9347,f9346],[d9347,f9347],[d9349,f9348],[d9349,f9349],[d9351,f9350],[d9351,f9351],[d9353,f9352],[d9353,f9353],[d9355,f9354],[d9355,f9355],[d9357,f9356],[d9357,f9357],[d9359,f9358],[d9359,f9359],[d9361,f9360],[d9361,f9361],[d9363,f9362],[d9363,f9363],[d9365,f9364],[d9365,f9365],[d9367,f9366],[d9367,f9367],[d9369,f9368],[d9369,f9369],[d9371,f9370],[d9371,f9371],[d9373,f9372],[d9373,f9373],[d9375,f9374],[d9375,f9375],[d9377,f9376],[d9377,f9377],[d9379,f9378],[d9379,f9379],[d9381,f9380],[d9381,f9381],[d9383,f9382],[d9383,f9383],[d9385,f9384],[d9385,f9385],[d9387,f9386],[d9387,f9387],[d9389,f9388],[d9389,f9389],[d9391,f9390],[d9391,f9391],[d9393,f9392],[d9393,f9393],[d9395,f9394],[d9395,f9395],[d9397,f9396],[d9397,f9397],[d9399,f9398],[d9399,f9399],[d9401,f9400],[d9401,f9401],[d9403,f9402],[d9403,f9403],[d9405,f9404],[d9405,f9405],[d9407,f9406],[d9407,f9407],[d9409,f9408],[d9409,f9409],[d9411,f9410],[d9411,f9411],[d9413,f9412],[d9413,f9413],[d9415,f9414],[d9415,f9415],[d9417,f9416],[d9417,f9417],[d9419,f9418],[d9419,f9419],[d9421,f9420],[d9421,f9421],[d9423,f9422],[d9423,f9423],[d9425,f9424],[d9425,f9425],[d9427,f9426],[d9427,f9427],[d9429,f9428],[d9429,f9429],[d9431,f9430],[d9431,f9431],[d9433,f9432],[d9433,f9433],[d9435,f9434],[d9435,f9435],[d9437,f9436],[d9437,f9437],[d9439,f9438],[d9439,f9439],[d9441,f9440],[d9441,f9441],[d9443,f9442],[d9443,f9443],[d9445,f9444],[d9445,f9445],[d9447,f9446],[d9447,f9447],[d9449,f9448],[d9449,f9449],[d9451,f9450],[d9451,f9451],[d9453,f9452],[d9453,f9453],[d9455,f9454],[d9455,f9455],[d9457,f9456],[d9457,f9457],[d9459,f9458],[d9459,f9459],[d9461,f9460],[d9461,f9461],[d9463,f9462],[d9463,f9463],[d9465,f9464],[d9465,f9465],[d9467,f9466],[d9467,f9467],[d9469,f9468],[d9469,f9469],[d9471,f9470],[d9471,f9471],[d9473,f9472],[d9473,f9473],[d9475,f9474],[d9475,f9475],[d9477,f9476],[d9477,f9477],[d9479,f9478],[d9479,f9479],[d9481,f9480],[d9481,f9481],[d9483,f9482],[d9483,f9483],[d9485,f9484],[d9485,f9485],[d9487,f9486],[d9487,f9487],[d9489,f9488],[d9489,f9489],[d9491,f9490],[d9491,f9491],[d9493,f9492],[d9493,f9493],[d9495,f9494],[d9495,f9495],[d9497,f9496],[d9497,f9497],[d9499,f9498],[d9499,f9499],[d9501,f9500],[d9501,f9501],[d9503,f9502],[d9503,f9503],[d9505,f9504],[d9505,f9505],[d9507,f9506],[d9507,f9507],[d9509,f9508],[d9509,f9509],[d9511,f9510],[d9511,f9511],[d9513,f9512],[d9513,f9513],[d9515,f9514],[d9515,f9515],[d9517,f9516],[d9517,f9517],[d9519,f9518],[d9519,f9519],[d9521,f9520],[d9521,f9521],[d9523,f9522],[d9523,f9523],[d9525,f9524],[d9525,f9525],[d9527,f9526],[d9527,f9527],[d9529,f9528],[d9529,f9529],[d9531,f9530],[d9531,f9531],[d9533,f9532],[d9533,f9533],[d9535,f9534],[d9535,f9535],[d9537,f9536],[d9537,f9537],[d9539,f9538],[d9539,f9539],[d9541,f9540],[d9541,f9541],[d9543,f9542],[d9543,f9543],[d9545,f9544],[d9545,f9545],[d9547,f9546],[d9547,f9547],[d9549,f9548],[d9549,f9549],[d9551,f9550],[d9551,f9551],[d9553,f9552],[d9553,f9553],[d9555,f9554],[d9555,f9555],[d9557,f9556],[d9557,f9557],[d9559,f9558],[d9559,f9559],[d9561,f9560],[d9561,f9561],[d9563,f9562],[d9563,f9563],[d9565,f9564],[d9565,f9565],[d9567,f9566],[d9567,f9567],[d9569,f9568],[d9569,f9569],[d9571,f9570],[d9571,f9571],[d9573,f9572],[d9573,f9573],[d9575,f9574],[d9575,f9575],[d9577,f9576],[d9577,f9577],[d9579,f9578],[d9579,f9579],[d9581,f9580],[d9581,f9581],[d9583,f9582],[d9583,f9583],[d9585,f9584],[d9585,f9585],[d9587,f9586],[d9587,f9587],[d9589,f9588],[d9589,f9589],[d9591,f9590],[d9591,f9591],[d9593,f9592],[d9593,f9593],[d9595,f9594],[d9595,f9595],[d9597,f9596],[d9597,f9597],[d9599,f9598],[d9599,f9599],[d9601,f9600],[d9601,f9601],[d9603,f9602],[d9603,f9603],[d9605,f9604],[d9605,f9605],[d9607,f9606],[d9607,f9607],[d9609,f9608],[d9609,f9609],[d9611,f9610],[d9611,f9611],[d9613,f9612],[d9613,f9613],[d9615,f9614],[d9615,f9615],[d9617,f9616],[d9617,f9617],[d9619,f9618],[d9619,f9619],[d9621,f9620],[d9621,f9621],[d9623,f9622],[d9623,f9623],[d9625,f9624],[d9625,f9625],[d9627,f9626],[d9627,f9627],[d9629,f9628],[d9629,f9629],[d9631,f9630],[d9631,f9631],[d9633,f9632],[d9633,f9633],[d9635,f9634],[d9635,f9635],[d9637,f9636],[d9637,f9637],[d9639,f9638],[d9639,f9639],[d9641,f9640],[d9641,f9641],[d9643,f9642],[d9643,f9643],[d9645,f9644],[d9645,f9645],[d9647,f9646],[d9647,f9647],[d9649,f9648],[d9649,f9649],[d9651,f9650],[d9651,f9651],[d9653,f9652],[d9653,f9653],[d9655,f9654],[d9655,f9655],[d9657,f9656],[d9657,f9657],[d9659,f9658],[d9659,f9659],[d9661,f9660],[d9661,f9661],[d9663,f9662],[d9663,f9663],[d9665,f9664],[d9665,f9665],[d9667,f9666],[d9667,f9667],[d9669,f9668],[d9669,f9669],[d9671,f9670],[d9671,f9671],[d9673,f9672],[d9673,f9673],[d9675,f9674],[d9675,f9675],[d9677,f9676],[d9677,f9677],[d9679,f9678],[d9679,f9679],[d9681,f9680],[d9681,f9681],[d9683,f9682],[d9683,f9683],[d9685,f9684],[d9685,f9685],[d9687,f9686],[d9687,f9687],[d9689,f9688],[d9689,f9689],[d9691,f9690],[d9691,f9691],[d9693,f9692],[d9693,f9693],[d9695,f9694],[d9695,f9695],[d9697,f9696],[d9697,f9697],[d9699,f9698],[d9699,f9699],[d9701,f9700],[d9701,f9701],[d9703,f9702],[d9703,f9703],[d9705,f9704],[d9705,f9705],[d9707,f9706],[d9707,f9707],[d9709,f9708],[d9709,f9709],[d9711,f9710],[d9711,f9711],[d9713,f9712],[d9713,f9713],[d9715,f9714],[d9715,f9715],[d9717,f9716],[d9717,f9717],[d9719,f9718],[d9719,f9719],[d9721,f9720],[d9721,f9721],[d9723,f9722],[d9723,f9723],[d9725,f9724],[d9725,f9725],[d9727,f9726],[d9727,f9727],[d9729,f9728],[d9729,f9729],[d9731,f9730],[d9731,f9731],[d9733,f9732],[d9733,f9733],[d9735,f9734],[d9735,f9735],[d9737,f9736],[d9737,f9737],[d9739,f9738],[d9739,f9739],[d9741,f9740],[d9741,f9741],[d9743,f9742],[d9743,f9743],[d9745,f9744],[d9745,f9745],[d9747,f9746],[d9747,f9747],[d9749,f9748],[d9749,f9749],[d9751,f9750],[d9751,f9751],[d9753,f9752],[d9753,f9753],[d9755,f9754],[d9755,f9755],[d9757,f9756],[d9757,f9757],[d9759,f9758],[d9759,f9759],[d9761,f9760],[d9761,f9761],[d9763,f9762],[d9763,f9763],[d9765,f9764],[d9765,f9765],[d9767,f9766],[d9767,f9767],[d9769,f9768],[d9769,f9769],[d9771,f9770],[d9771,f9771],[d9773,f9772],[d9773,f9773],[d9775,f9774],[d9775,f9775],[d9777,f9776],[d9777,f9777],[d9779,f9778],[d9779,f9779],[d9781,f9780],[d9781,f9781],[d9783,f9782],[d9783,f9783],[d9785,f9784],[d9785,f9785],[d9787,f9786],[d9787,f9787],[d9789,f9788],[d9789,f9789],[d9791,f9790],[d9791,f9791],[d9793,f9792],[d9793,f9793],[d9795,f9794],[d9795,f9795],[d9797,f9796],[d9797,f9797],[d9799,f9798],[d9799,f9799],[d9801,f9800],[d9801,f9801],[d9803,f9802],[d9803,f9803],[d9805,f9804],[d9805,f9805],[d9807,f9806],[d9807,f9807],[d9809,f9808],[d9809,f9809],[d9811,f9810],[d9811,f9811],[d9813,f9812],[d9813,f9813],[d9815,f9814],[d9815,f9815],[d9817,f9816],[d9817,f9817],[d9819,f9818],[d9819,f9819],[d9821,f9820],[d9821,f9821],[d9823,f9822],[d9823,f9823],[d9825,f9824],[d9825,f9825],[d9827,f9826],[d9827,f9827],[d9829,f9828],[d9829,f9829],[d9831,f9830],[d9831,f9831],[d9833,f9832],[d9833,f9833],[d9835,f9834],[d9835,f9835],[d9837,f9836],[d9837,f9837],[d9839,f9838],[d9839,f9839],[d9841,f9840],[d9841,f9841],[d9843,f9842],[d9843,f9843],[d9845,f9844],[d9845,f9845],[d9847,f9846],[d9847,f9847],[d9849,f9848],[d9849,f9849],[d9851,f9850],[d9851,f9851],[d9853,f9852],[d9853,f9853],[d9855,f9854],[d9855,f9855],[d9857,f9856],[d9857,f9857],[d9859,f9858],[d9859,f9859],[d9861,f9860],[d9861,f9861],[d9863,f9862],[d9863,f9863],[d9865,f9864],[d9865,f9865],[d9867,f9866],[d9867,f9867],[d9869,f9868],[d9869,f9869],[d9871,f9870],[d9871,f9871],[d9873,f9872],[d9873,f9873],[d9875,f9874],[d9875,f9875],[d9877,f9876],[d9877,f9877],[d9879,f9878],[d9879,f9879],[d9881,f9880],[d9881,f9881],[d9883,f9882],[d9883,f9883],[d9885,f9884],[d9885,f9885],[d9887,f9886],[d9887,f9887],[d9889,f9888],[d9889,f9889],[d9891,f9890],[d9891,f9891],[d9893,f9892],[d9893,f9893],[d9895,f9894],[d9895,f9895],[d9897,f9896],[d9897,f9897],[d9899,f9898],[d9899,f9899],[d9901,f9900],[d9901,f9901],[d9903,f9902],[d9903,f9903],[d9905,f9904],[d9905,f9905],[d9907,f9906],[d9907,f9907],[d9909,f9908],[d9909,f9909],[d9911,f9910],[d9911,f9911],[d9913,f9912],[d9913,f9913],[d9915,f9914],[d9915,f9915],[d9917,f9916],[d9917,f9917],[d9919,f9918],[d9919,f9919],[d9921,f9920],[d9921,f9921],[d9923,f9922],[d9923,f9923],[d9925,f9924],[d9925,f9925],[d9927,f9926],[d9927,f9927],[d9929,f9928],[d9929,f9929],[d9931,f9930],[d9931,f9931],[d9933,f9932],[d9933,f9933],[d9935,f9934],[d9935,f9935],[d9937,f9936],[d9937,f9937],[d9939,f9938],[d9939,f9939],[d9941,f9940],[d9941,f9941],[d9943,f9942],[d9943,f9943],[d9945,f9944],[d9945,f9945],[d9947,f9946],[d9947,f9947],[d9949,f9948],[d9949,f9949],[d9951,f9950],[d9951,f9951],[d9953,f9952],[d9953,f9953],[d9955,f9954],[d9955,f9955],[d9957,f9956],[d9957,f9957],[d9959,f9958],[d9959,f9959],[d9961,f9960],[d9961,f9961],[d9963,f9962],[d9963,f9963],[d9965,f9964],[d9965,f9965],[d9967,f9966],[d9967,f9967],[d9969,f9968],[d9969,f9969],[d9971,f9970],[d9971,f9971],[d9973,f9972],[d9973,f9973],[d9975,f9974],[d9975,f9975],[d9977,f9976],[d9977,f9977],[d9979,f9978],[d9979,f9979],[d9981,f9980],[d9981,f9981],[d9983,f9982],[d9983,f9983],[d9985,f9984],[d9985,f9985],[d9987,f9986],[d9987,f9987],[d9989,f9988],[d9989,f9989],[d9991,f9990],[d9991,f9991],[d9993,f9992],[d9993,f9993],[d9995,f9994],[d9995,f9995],[d9997,f9996],[d9997,f9997],[d9998,f9998] ] ] + + +contents in Dir -> (Dir + File) +all d:Dir | not (d in d.^contents) +Root in Dir +(File + Dir) in Root.*contents \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/List.kodkod b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/List.kodkod new file mode 100644 index 00000000..3303616e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/List.kodkod @@ -0,0 +1,30 @@ +[Thing0, Thing1, Thing2, List0, List1, List2] + +Thing: [[[Thing2]]] +List:[[[List0], [List1]]] +EmptyList:[[[List0]]] +NonEmptyList:[[[List1], [List2]]] +car:[[[List1, Thing2], [List2, Thing2]]] +cdr:[[[List1, List0], [List2, List1]]] +equivTo:[[[List0, List0], [List1, List1], [List2, List2]]] +prefixes:[[[List0, List0], [List0, List2], [List1, List0], [List1, List1], [List2, List0], [List2, List1], [List2, List2]]] + +List = (EmptyList + NonEmptyList) +no (EmptyList & NonEmptyList) +equivTo in (List -> List) +prefixes in (List -> List) + +function[car: NonEmptyList -> one Thing] +function[cdr: NonEmptyList -> one List] + +Thing in (List . car) + +all L: List | some (EmptyList & (L . *cdr)) +all a: List, b: List | a in (b.equivTo) <=> ((a . car) = (b . car) && (b . cdr) in ((a . cdr) . equivTo)) + +(List -> EmptyList) in prefixes + +--all a: NonEmptyList, b: NonEmptyList | a in (b . prefixes) <=> ((a . car) = (b . car) && (a . cdr) in ((b . cdr) . prefixes)) + +--some a: NonEmptyList, b: NonEmptyList | !(a = b) && b in (a . prefixes) + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/PigeonHole b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/PigeonHole new file mode 100644 index 00000000..2866c5a1 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/PigeonHole @@ -0,0 +1,17 @@ +{Pigeon0, Pigeon1, Pigeon2, Pigeon3, Hole0, Hole1, Hole2, Hole3} + +Pigeon: [[[Pigeon0], [Pigeon1], [Pigeon2], [Pigeon3]]] +Hole: [[[Hole0], [Hole1], [Hole2], [Hole3]]] +hole: [[], [[Pigeon0, Hole0], [Pigeon0, Hole1], [Pigeon0, Hole2], [Pigeon0, Hole3], [Pigeon1, Hole0], [Pigeon1, Hole1], [Pigeon1, Hole2], [Pigeon1, Hole3], [Pigeon2, Hole0], [Pigeon2, Hole1], [Pigeon2, Hole2], [Pigeon2, Hole3], [Pigeon3, Hole0], [Pigeon3, Hole1], [Pigeon3, Hole2], [Pigeon3, Hole3]]] + +function[hole: Pigeon -> one Hole] + +-- all p1, p2: Pigeon , h1, h2: Hole | !(p1 = p2) => not (p1.hole = p2.hole) + +-- all disj p1, p2, x1: Pigeon | not (p1.hole = p2.hole) + +-- all disj p1, p2: Pigeon, disj h1, h2: Hole | not (p1.hole = p2.hole) + +-- all disj x1, x2: Pigeon, disj h1, h2: Hole | not (x1.hole = x2.hole) + +no disj p1, p2: Pigeon | p1.hole = p2.hole diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/PigeonHole3 b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/PigeonHole3 new file mode 100644 index 00000000..2866c5a1 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/PigeonHole3 @@ -0,0 +1,17 @@ +{Pigeon0, Pigeon1, Pigeon2, Pigeon3, Hole0, Hole1, Hole2, Hole3} + +Pigeon: [[[Pigeon0], [Pigeon1], [Pigeon2], [Pigeon3]]] +Hole: [[[Hole0], [Hole1], [Hole2], [Hole3]]] +hole: [[], [[Pigeon0, Hole0], [Pigeon0, Hole1], [Pigeon0, Hole2], [Pigeon0, Hole3], [Pigeon1, Hole0], [Pigeon1, Hole1], [Pigeon1, Hole2], [Pigeon1, Hole3], [Pigeon2, Hole0], [Pigeon2, Hole1], [Pigeon2, Hole2], [Pigeon2, Hole3], [Pigeon3, Hole0], [Pigeon3, Hole1], [Pigeon3, Hole2], [Pigeon3, Hole3]]] + +function[hole: Pigeon -> one Hole] + +-- all p1, p2: Pigeon , h1, h2: Hole | !(p1 = p2) => not (p1.hole = p2.hole) + +-- all disj p1, p2, x1: Pigeon | not (p1.hole = p2.hole) + +-- all disj p1, p2: Pigeon, disj h1, h2: Hole | not (p1.hole = p2.hole) + +-- all disj x1, x2: Pigeon, disj h1, h2: Hole | not (x1.hole = x2.hole) + +no disj p1, p2: Pigeon | p1.hole = p2.hole diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/RingElection.kodkod b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/RingElection.kodkod new file mode 100644 index 00000000..6baab683 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/RingElection.kodkod @@ -0,0 +1,101 @@ +[Process0, Process1, Process2, Time0, Time1, Time2, Time3] + +Process: [[], [[Process0], [Process1], [Process3]]] +succ: [[], [[Process0, Process0], [Process0, Process1], [Process0, Process2], [Process1, Process0], [Process1, Process1], [Process1, Process2], [Process2, Process0], [Process2, Process1], [Process2, Process2]]] +toSend: [[], [[Process0, Process0, Time0], [Process0, Process0, Time1], [Process0, Process0, Time2], [Process0, Process0, Time3], [Process0, Process1, Time0], [Process0, Process1, Time1], [Process0, Process1, Time2], [Process0, Process1, Time3], [Process0, Process2, Time0], [Process0, Process2, Time1], [Process0, Process2, Time2], [Process0, Process2, Time3], [Process1, Process0, Time0], [Process1, Process0, Time1], [Process1, Process0, Time2], [Process1, Process0, Time3], [Process1, Process1, Time0], [Process1, Process1, Time1], [Process1, Process1, Time2], [Process1, Process1, Time3], [Process1, Process2, Time0], [Process1, Process2, Time1], [Process1, Process2, Time2], [Process1, Process2, Time3], [Process2, Process0, Time0], [Process2, Process0, Time1], [Process2, Process0, Time2], [Process2, Process0, Time3], [Process2, Process1, Time0], [Process2, Process1, Time1], [Process2, Process1, Time2], [Process2, Process1, Time3], [Process2, Process2, Time0], [Process2, Process2, Time1], [Process2, Process2, Time2], [Process2, Process2, Time3]]] +elected: [[], [[Process0, Time0], [Process0, Time1], [Process0, Time2], [Process0, Time3], [Process1, Time0], [Process1, Time1], [Process1, Time2], [Process1, Time3], [Process2, Time0], [Process2, Time1], [Process2, Time2], [Process2, Time3]]] +pord: [[], [[Process0, Process0], [Process0, Process1], [Process0, Process2], [Process1, Process0], [Process1, Process1], [Process1, Process2], [Process2, Process0], [Process2, Process1], [Process2, Process2]]] +pfirst: [[], [[Process0], [Process1], [Process2]]] +plast: [[], [[Process0], [Process1], [Process2]]] +Time: [[], [[Time0], [Time1], [Time2], [Time3]]] +tord: [[], [[Time0, Time0], [Time0, Time1], [Time0, Time2], [Time0, Time3], [Time1, Time0], [Time1, Time1], [Time1, Time2], [Time1, Time3], [Time2, Time0], [Time2, Time1], [Time2, Time2], [Time2, Time3], [Time3, Time0], [Time3, Time1], [Time3, Time2], [Time3, Time3]]] +tfirst: [[], [[Time0], [Time1], [Time2], [Time3]]] +tlast: [[], [[Time0], [Time1], [Time2], [Time3]]] +next: [[], []] + +/** +open util/ordering[Time] as TO +open util/ordering[Process] as PO +**/ +ord[tord, Time, tfirst, tlast] && +ord[pord, Process, pfirst, plast] && +/** +sig Time {} +sig Process { + succ: Process, + toSend: Process -> Time, + elected: set Time + } +**/ +function[succ: Process -> one Process] +elected in (Process -> Time) + +/** +fact ring {all p: Process | Process in p.^succ} +**/ +all p: Process | Process in (p . ^succ) + +/** +fact defineElected { + no elected.first + all t: Time-first | elected.t = {p: Process | p in p.toSend.t - p.toSend.(t.prev)} + } +**/ +no (elected . tfirst) +all t: Time - tfirst | elected.t = {p: Process | p in p.toSend.t - p.toSend.(t.~tord)} +/** + +pred init [t: Time] { + all p: Process | p.toSend.t = p + } + +pred step [t, t': Time, p: Process] { + let from = p.toSend, to = p.succ.toSend | + some id: from.t { + from.t' = from.t - id + to.t' = to.t + (id - p.succ.prevs) + } + } + +pred skip [t, t': Time, p: Process] { + p.toSend.t = p.toSend.t' + } + +fact traces { + init [first] + all t: Time-last | + let t' = t.next | + all p: Process | + step [t, t', p] or step [t, t', succ.p] or skip [t, t', p] + } +**/ +all p: Process | p.toSend.tfirst = p +all t: Time - tlast | all p: Process | + (some id: (p . toSend) . t | + ((p . toSend) . (t . tord)) = (((p . toSend) . t) - id) && + (((p . succ) . toSend) . (t . tord)) = ((((p . succ) . toSend) . t) + (id - + ((p . succ) . ^~pord)))) || + (some id: ((succ . p) . toSend) . t | + (((succ . p) . toSend) . (t . tord)) = ((((succ . p) . toSend) . t) - id) + && + ((((succ . p) . succ) . toSend) . (t . tord)) = (((((succ . p) . succ) . + toSend) . t) + (id - (((succ . p) . succ) . ^~pord)))) || + ((p . toSend) . t) = ((p . toSend) . (t . tord)) + +/** +pred show { some elected } +**/ +some elected + +/** + all t: Time-tlast | + let t' = t.next | + all p: Process | t'.toSend = p.toSend.t.k +**/ + +/** +*****check AtMostOneElected for 3 Process, 4 Time***** +---INSTANCE--- +relations: {Process=[[Process0], [Process1], [Process2]], succ=[[Process0, Process1], [Process1, Process2], [Process2, Process0]], toSend=[[Process0, Process0, Time0], [Process0, Process0, Time1], [Process0, Process0, Time2], [Process0, Process0, Time3], [Process0, Process2, Time1], [Process1, Process1, Time0], [Process1, Process1, Time1], [Process1, Process1, Time2], [Process1, Process1, Time3], [Process1, Process2, Time2], [Process2, Process2, Time0], [Process2, Process2, Time3]], elected=[[Process2, Time3]], pord=[[Process0, Process1], [Process1, Process2]], pfirst=[[Process0]], plast=[[Process2]], Time=[[Time0], [Time1], [Time2], [Time3]], tord=[[Time0, Time1], [Time1, Time2], [Time2, Time3]], tfirst=[[Time0]], tlast=[[Time3]]} +ints: [] +**/ \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/ToyFilesystem.kodkod b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/ToyFilesystem.kodkod new file mode 100644 index 00000000..af620315 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/ToyFilesystem.kodkod @@ -0,0 +1,11 @@ +{d0, d1, f0, f1, f2} + +Root: [{(d0)}] +Dir: [ {(d0), (d1)}] +File: [{(f0), (f1), (f2)}] +contents : [[[d0, d1], [d0, f2], [d1, f0], [d1, f1]]] + +contents in Dir -> (Dir + File) +all d: Dir | !(d in d.^contents) +Root in Dir +(File + Dir) in Root.*contents diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/isFunction b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/isFunction new file mode 100644 index 00000000..15e31973 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/isFunction @@ -0,0 +1,12 @@ +{Domain0, Domain1, Domain2, Domain3, Range0, Range1, Range2, Range3} + +Domain: [[[Domain0], [Domain1], [Domain2], [Domain3]]] +Range: [[[Range0], [Range1], [Range2], [Range3]]] +func: [ [[Domain0, Range3], [Domain1, Range2], [Domain2, Range1], [Domain3, Range0]] ] + +-func: [ {} , {[Domain0, Range0], [Domain0, Range1], [Domain0, Range2], [Domain0, Range2], [Domain0, Range3], [Domain1, Range0], [Domain1, Range1], [Domain1, Range2], [Domain1, Range3], [Domain2, Range0], [Domain2, Range1], [Domain2, Range2], [Domain2, Range3], [Domain3, Range0], [Domain3, Range1], [Domain3, Range2], [Domain3, Range3]}] + +--function[hole: Domain -> one Range] + +all disj a1, a2 :Domain | a1.func != a2.func +all a: Domain | one a.func diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/isfunction.als b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/isfunction.als new file mode 100644 index 00000000..2fc1dbde --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/isfunction.als @@ -0,0 +1,15 @@ +model test/crocopat + +sig Domain { + function: set Range, +} + +sig Range {} + +pred isFunction { + all disj a1, a2 :Domain | a1.function != a2.function + all d : Domain | one d.function + all r : Range | one r.~function +} + +run isFunction for exactly 4 Domain, exactly 4 Range diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/myaddressbook.als b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/myaddressbook.als new file mode 100644 index 00000000..dbd0b11c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/myaddressbook.als @@ -0,0 +1,40 @@ +model appendixA/addressBook2 + +sig Addr, Name { } + +sig Book { + addr: Name -> (Name + Addr) + } + +/* + +---------------- +x: m e + +---------------- +r: A m -> n B +all a: A | n a.r +all b: B | m r.b + +---------------- +r: A -> (B m -> n C) +all a: A | a.r in B m -> n C + +---------------- +r: (A m -> n B) -> C +all c: C | r.c in A m -> n B +---------------- + +*/ + +--addr: Book -> (Name lone -> Addr) +pred show1 { + all b: Book | b.addr in Name lone -> Addr +} + +//r: (A m -> n B) -> C +pred show2 { + all b: Book | b.addr in Name lone -> Addr +} + +run show1 for 3 diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/pigeonhole.als b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/pigeonhole.als new file mode 100644 index 00000000..95fec987 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/pigeonhole.als @@ -0,0 +1,16 @@ +sig Pigeon { hole: Hole } + +sig Hole {} + +fact {no disj p1, p2: Pigeon | p1.hole = p2.hole} + +pred aPigeonPerHole() { + // holes are not shared + -- all p1, p2: Pigeon | p1 != p2 implies p1.hole != p2.hole + -- all p1, p2: Pigeon, h1, h2: Hole | p1 != p2 => p1.hole != p2.hole + -- no disj p1, p2: Pigeon | p1.hole = p2.hole + + +} + +run aPigeonPerHole for exactly 4 Pigeon, exactly 4 Hole diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/tougnut.als b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/tougnut.als new file mode 100644 index 00000000..1ab02e61 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/kodkod/tougnut.als @@ -0,0 +1,20 @@ +model internal/tougnut + +open util/ordering[Cell] + +sig Cell { covered: Cell -> Cell -> Cell } + +pred covering() { + // opposite corners not on the board + let board = Cell->Cell - (first->first + last->last) | covered in board->board + + // covering relation is symmetric + all x,y: Cell | y.(x.covered)->x->y in covered + + // each pair of cells on the board should be covered + // by a domino, which also covers ONE of its neighbors + all x,y: Cell | one y.(x.covered) && y.(x.covered) in (prev[x]+next[x])->y + x->(prev[y] + next[y]) + +} + +run covering for 10 diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/out/Generics1.ecore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/out/Generics1.ecore new file mode 100644 index 00000000..b6eb4c81 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/out/Generics1.ecore @@ -0,0 +1,132 @@ + + + +
+
+
+ + +
+ + +
+ + +
+ + +
+ + + +
+
+
+ + +
+
+
+ + + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/out/My.ecore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/out/My.ecore new file mode 100644 index 00000000..8200983d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/out/My.ecore @@ -0,0 +1,30 @@ + + + +
+ + +
+ + +
+ + +
+ + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/out/bookstore.ecore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/out/bookstore.ecore new file mode 100644 index 00000000..93dc47a1 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/out/bookstore.ecore @@ -0,0 +1,38 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/out/test1.ecore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/out/test1.ecore new file mode 100644 index 00000000..368df068 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/out/test1.ecore @@ -0,0 +1,94 @@ + + + +
+ + +
+ + +
+ + +
+ + + +
+ + + + + + + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/src/test/resources/out/yunus.ecore b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/out/yunus.ecore new file mode 100644 index 00000000..3593acb9 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/src/test/resources/out/yunus.ecore @@ -0,0 +1,103 @@ + + + +
+ + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/target/classes/AlloyInEcore.stg b/Source/eu.modelwriter.core.alloyinecore/target/classes/AlloyInEcore.stg new file mode 100644 index 00000000..0ebcf640 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/classes/AlloyInEcore.stg @@ -0,0 +1,147 @@ +model(options, modelName) ::= +<< +<\n><\u007B> + +<\u007D><\n> +model ;<\n><\n> +>> + +load(name, namespace) ::= +<< +import : ; +>> + +package(visibility, name, prefix, namespace, subElement) ::= +<< +package : = <\n><\u007B>; + +<\u007D><\n> +>> + +enum(visibility, name, typeParameter, instanceName, isSerializable, subElement)::= +<< +enum <\u003C><\u003E><\n><\u007B>; + +<\u007D><\n> +>> + +enumLiteral(name, enumValue, subElement) ::= +<< +literal = <\n><\u007B>; + +<\u007D><\n> +>> + +datatype(visibility, isPrimitive, nullable, name, typeParameter, instanceName, isSerializable, subElement)::= +<< +primitive nullable datatype <\u003C><\u003E><(instanceName:singleQuote()):semicolon():ls()><\n><\u007B>; + +<\u007D><\n> +>> + +class(visibility, isAbstract, name, typeParameter, superClass, instanceName, isInterface, subElement) ::= +<< +interfaceabstract class<\u003C><\u003E> extends <\n><\u007B>; + +<\u007D><\n> +>> + +attr(visibility, isStatic, model,ghost, transient, volatile, nullable, readonly, name, defaultValue, type, multiplicity, qualifier, subElement)::= +<< +static model ghost transient volatile nullable readonly attribute<\n><\u007B>; + +<\u007D><\n> +>> + +ref(visibility, isStatic, model,ghost, transient, volatile, nullable, readonly, name, opposite, defaultValue, type, multiplicity, qualifier, subElement)::= +<< +static model ghost transient volatile nullable readonly property<\n><\u007B>; + +<\u007D><\n> +>> + +op(visibility, isStatic, nullable, name, typeParameter, params, throws, type, multiplicity, qualifier, subElement) ::= +<< +static nullable operation <\u003C><\u003E>() throws <\n><\u007B>; + +<\u007D><\n> +>> + +opParameter(nullable, name, type, multiplicity, qualifier, subElement) ::= +<< +nullable +>> + +anno(name, detail, subElement)::= +<< +annotation; +( + +); +<\u007B> + +<\u007D><\n> +>> + +edetail(name, val)::= +<< + = +>> + +inv(isCallable, name, message, formula)::= +<< +callable invariant; +>> + +precondition(name, message, formula)::= +<< +requires; +>> + +postcondition(name, message, formula)::= +<< +ensures; +>> + +body(name, expression)::= +<< +body; +>> + +derivation(name, expression) ::= +<< +derivation; +>> + +initial(name, expression) ::= +<< +initial; +>> + +referenceKey(referredKeys) ::= +<< +key ; +>> + +typeParameter(name, eBound) ::= +<< + extends +>> + +genericType(classifier, typeParameter, typeArgument, upperBound, lowerBound) ::= +<< +?<\u003C><\u003E> extends super +>> + +ds(x) ::= " " +ls(x) ::= "<\ >" +rs(x) ::= " " +throw(x)::=" throws " +parenthesis(x) ::= "()" +sharp(x) ::= "#" +equals(x) ::= "= " +bracket(x) ::= "[]" +semicolon(x) ::=": " +curlyBracket(x) ::="<\u007B> <\u007D>" +singleQuote(x)::="''" +doubleQuote(x)::="\"\"" \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/classes/Ecore.recore b/Source/eu.modelwriter.core.alloyinecore/target/classes/Ecore.recore new file mode 100644 index 00000000..bc1149ad --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/classes/Ecore.recore @@ -0,0 +1,443 @@ +package ecore : ecore = 'http://www.eclipse.org/emf/2002/Ecore' +{ + class EAttribute extends EStructuralFeature + { + attribute iD : EBoolean[?]; + transient volatile readonly property eAttributeType : EDataType { derived }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ConsistentTransient' + ); + } + class EAnnotation extends EModelElement + { + attribute source : EString[?]; + property details : EStringToStringMapEntry[*] { ordered !resolve composes }; + transient property eModelElement#eAnnotations : EModelElement[?] { !resolve }; + property contents : EObject[*] { ordered !resolve composes }; + property references : EObject[*] { ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedSourceURI' + ); + } + class EClass extends EClassifier + { + attribute abstract : EBoolean[?]; + attribute interface : EBoolean[?]; + operation isSuperTypeOf(someClass : EClass[?]) : EBoolean[?]; + operation getFeatureCount() : EInt[?]; + operation getEStructuralFeature(featureID : EInt[?]) : EStructuralFeature[?]; + operation getFeatureID(feature : EStructuralFeature[?]) : EInt[?]; + operation getEStructuralFeature(featureName : EString[?]) : EStructuralFeature[?]; + operation getOperationCount() : EInt[?]; + operation getEOperation(operationID : EInt[?]) : EOperation[?]; + operation getOperationID(operation : EOperation[?]) : EInt[?]; + operation getOverride(operation : EOperation[?]) : EOperation[?]; + operation getFeatureType(feature : EStructuralFeature[?]) : EGenericType[?]; + property eSuperTypes : EClass[*] { ordered unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + property eOperations#eContainingClass : EOperation[*] { ordered !resolve composes }; + transient volatile readonly property eAllAttributes : EAttribute[*] { ordered derived }; + transient volatile readonly property eAllReferences : EReference[*] { ordered derived }; + transient volatile readonly property eReferences : EReference[*] { ordered derived }; + transient volatile readonly property eAttributes : EAttribute[*] { ordered derived }; + transient volatile readonly property eAllContainments : EReference[*] { ordered derived }; + transient volatile readonly property eAllOperations : EOperation[*] { ordered derived }; + transient volatile readonly property eAllStructuralFeatures : EStructuralFeature[*] { ordered derived }; + transient volatile readonly property eAllSuperTypes : EClass[*] { ordered derived }; + transient volatile readonly property eIDAttribute : EAttribute[?] { derived !resolve }; + property eStructuralFeatures#eContainingClass : EStructuralFeature[*] { ordered !resolve composes }; + property eGenericSuperTypes : EGenericType[*] { ordered unsettable !resolve composes } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + transient volatile readonly property eAllGenericSuperTypes : EGenericType[*] { ordered derived }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'InterfaceIsAbstract AtMostOneID UniqueFeatureNames UniqueOperationSignatures NoCircularSuperTypes WellFormedMapEntryClass ConsistentSuperTypes DisjointFeatureAndOperationSignatures' + ); + } + abstract class EClassifier extends ENamedElement + { + volatile attribute instanceClassName : EString[?] { unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + transient volatile readonly attribute instanceClass : EJavaClass[?] { derived }; + transient volatile readonly attribute defaultValue : EJavaObject[?] { derived }; + volatile attribute instanceTypeName : EString[?] { unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + operation isInstance(object : EJavaObject[?]) : EBoolean[?]; + operation getClassifierID() : EInt[?]; + transient readonly property ePackage#eClassifiers : EPackage[?]; + property eTypeParameters : ETypeParameter[*] { ordered composes }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedInstanceTypeName UniqueTypeParameterNames' + ); + } + class EDataType extends EClassifier + { + attribute serializable : EBoolean[?] = 'true'; + } + class EEnum extends EDataType + { + operation getEEnumLiteral(name : EString[?]) : EEnumLiteral[?]; + operation getEEnumLiteral(value : EInt[?]) : EEnumLiteral[?]; + operation getEEnumLiteralByLiteral(literal : EString[?]) : EEnumLiteral[?]; + property eLiterals#eEnum : EEnumLiteral[*] { ordered !resolve composes }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'UniqueEnumeratorNames UniqueEnumeratorLiterals' + ); + } + class EEnumLiteral extends ENamedElement + { + attribute value : EInt[?]; + transient attribute instance : EEnumerator[?]; + attribute literal : EString[?]; + transient readonly property eEnum#eLiterals : EEnum[?] { !resolve }; + } + class EFactory extends EModelElement + { + operation create(eClass : EClass[?]) : EObject[?]; + operation createFromString(eDataType : EDataType[?], literalValue : EString[?]) : EJavaObject[?]; + operation convertToString(eDataType : EDataType[?], instanceValue : EJavaObject[?]) : EString[?]; + transient property ePackage#eFactoryInstance : EPackage { !resolve }; + } + abstract class EModelElement + { + operation getEAnnotation(source : EString[?]) : EAnnotation[?]; + property eAnnotations#eModelElement : EAnnotation[*] { ordered !resolve composes }; + } + abstract class ENamedElement extends EModelElement + { + attribute name : EString[?]; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedName' + ); + } + class EObject + { + operation eClass() : EClass[?]; + operation eIsProxy() : EBoolean[?]; + operation eResource() : EResource[?]; + operation eContainer() : EObject[?]; + operation eContainingFeature() : EStructuralFeature[?]; + operation eContainmentFeature() : EReference[?]; + operation eContents() : EEList[?]; + operation eAllContents() : ETreeIterator[?]; + operation eCrossReferences() : EEList[?]; + operation eGet(feature : EStructuralFeature[?]) : EJavaObject[?]; + operation eGet(feature : EStructuralFeature[?], resolve : EBoolean[?]) : EJavaObject[?]; + operation eSet(feature : EStructuralFeature[?], newValue : EJavaObject[?]); + operation eIsSet(feature : EStructuralFeature[?]) : EBoolean[?]; + operation eUnset(feature : EStructuralFeature[?]); + operation eInvoke(operation : EOperation[?], arguments : EEList[?]) : EJavaObject[?] throws EInvocationTargetException; + } + class EOperation extends ETypedElement + { + operation getOperationID() : EInt[?]; + operation isOverrideOf(someOperation : EOperation[?]) : EBoolean[?]; + transient readonly property eContainingClass#eOperations : EClass[?] { !resolve }; + property eTypeParameters : ETypeParameter[*] { ordered composes }; + property eParameters#eOperation : EParameter[*] { ordered !resolve composes }; + property eExceptions : EClassifier[*] { ordered unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + property eGenericExceptions : EGenericType[*] { ordered unsettable !resolve composes } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'UniqueParameterNames UniqueTypeParameterNames NoRepeatingVoid' + ); + } + class EPackage extends ENamedElement + { + attribute nsURI : EString[?]; + attribute nsPrefix : EString[?]; + operation getEClassifier(name : EString[?]) : EClassifier[?]; + transient property eFactoryInstance#ePackage : EFactory { !resolve }; + property eClassifiers#ePackage : EClassifier[*] { ordered composes }; + property eSubpackages#eSuperPackage : EPackage[*] { ordered composes }; + transient readonly property eSuperPackage#eSubpackages : EPackage[?]; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedNsURI WellFormedNsPrefix UniqueSubpackageNames UniqueClassifierNames UniqueNsURIs' + ); + } + class EParameter extends ETypedElement + { + transient readonly property eOperation#eParameters : EOperation[?] { !resolve }; + } + class EReference extends EStructuralFeature + { + attribute containment : EBoolean[?]; + transient volatile readonly attribute container : EBoolean[?] { derived }; + attribute resolveProxies : EBoolean[?] = 'true'; + property eOpposite : EReference[?]; + transient volatile readonly property eReferenceType : EClass { derived }; + property eKeys : EAttribute[*] { ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ConsistentOpposite SingleContainer ConsistentKeys ConsistentUnique ConsistentContainer' + ); + } + abstract class EStructuralFeature extends ETypedElement + { + attribute changeable : EBoolean[?] = 'true'; + attribute volatile : EBoolean[?]; + attribute transient : EBoolean[?]; + attribute defaultValueLiteral : EString[?]; + transient volatile readonly attribute defaultValue : EJavaObject[?] { derived }; + attribute unsettable : EBoolean[?]; + attribute derived : EBoolean[?]; + operation getFeatureID() : EInt[?]; + operation getContainerClass() : EJavaClass[?]; + transient readonly property eContainingClass#eStructuralFeatures : EClass[?] { !resolve }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ValidDefaultValueLiteral' + ); + } + abstract class ETypedElement extends ENamedElement + { + attribute ordered : EBoolean[?] = 'true'; + attribute unique : EBoolean[?] = 'true'; + attribute lowerBound : EInt[?]; + attribute upperBound : EInt[?] = '1'; + transient volatile readonly attribute many : EBoolean[?] { derived }; + transient volatile readonly attribute required : EBoolean[?] { derived }; + volatile property eType : EClassifier[?] { unsettable } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + volatile property eGenericType : EGenericType[?] { unsettable !resolve composes } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ValidLowerBound ValidUpperBound ConsistentBounds ValidType' + ); + } + datatype EBigDecimal : 'java.math.BigDecimal' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#decimal' + ); + } + datatype EBigInteger : 'java.math.BigInteger' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#integer' + ); + } + datatype EBoolean : 'boolean' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#boolean' + ); + } + datatype EBooleanObject : 'java.lang.Boolean' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EBoolean', + 'name' = 'EBoolean:Object' + ); + } + datatype EByte : 'byte' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#byte' + ); + } + datatype EByteArray : 'byte[]' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#hexBinary' + ); + } + datatype EByteObject : 'java.lang.Byte' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EByte', + 'name' = 'EByte:Object' + ); + } + datatype EChar : 'char'; + datatype ECharacterObject : 'java.lang.Character' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EChar', + 'name' = 'EChar:Object' + ); + } + datatype EDate : 'java.util.Date'; + datatype EDiagnosticChain : 'org.eclipse.emf.common.util.DiagnosticChain' { !serializable }; + datatype EDouble : 'double' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#double' + ); + } + datatype EDoubleObject : 'java.lang.Double' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EDouble', + 'name' = 'EDouble:Object' + ); + } + datatype EEList : 'org.eclipse.emf.common.util.EList' { !serializable }; + datatype EEnumerator : 'org.eclipse.emf.common.util.Enumerator' { !serializable }; + datatype EFeatureMap : 'org.eclipse.emf.ecore.util.FeatureMap' { !serializable }; + datatype EFeatureMapEntry : 'org.eclipse.emf.ecore.util.FeatureMap$Entry' { !serializable }; + datatype EFloat : 'float' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#float' + ); + } + datatype EFloatObject : 'java.lang.Float' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EFloat', + 'name' = 'EFloat:Object' + ); + } + datatype EInt : 'int' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#int' + ); + } + datatype EIntegerObject : 'java.lang.Integer' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EInt', + 'name' = 'EInt:Object' + ); + } + datatype EJavaClass : 'java.lang.Class'; + datatype EJavaObject : 'java.lang.Object'; + datatype ELong : 'long' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#long' + ); + } + datatype ELongObject : 'java.lang.Long' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'ELong', + 'name' = 'ELong:Object' + ); + } + datatype EMap : 'java.util.Map' { !serializable }; + datatype EResource : 'org.eclipse.emf.ecore.resource.Resource' { !serializable }; + datatype EResourceSet : 'org.eclipse.emf.ecore.resource.ResourceSet' { !serializable }; + datatype EShort : 'short' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#short' + ); + } + datatype EShortObject : 'java.lang.Short' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EShort', + 'name' = 'EShort:Object' + ); + } + datatype EString : 'java.lang.String' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#string' + ); + } + class EStringToStringMapEntry : 'java.util.Map$Entry' + { + attribute key : EString[?]; + attribute value : EString[?]; + } + datatype ETreeIterator : 'org.eclipse.emf.common.util.TreeIterator' { !serializable }; + class EGenericType + { + operation isInstance(object : EJavaObject[?]) : EBoolean[?]; + property eUpperBound : EGenericType[?] { !resolve composes }; + property eTypeArguments : EGenericType[*] { ordered !resolve composes }; + transient readonly property eRawType : EClassifier { derived }; + property eLowerBound : EGenericType[?] { !resolve composes }; + property eTypeParameter : ETypeParameter[?] { !resolve }; + property eClassifier : EClassifier[?]; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ConsistentType ConsistentBounds ConsistentArguments' + ); + } + class ETypeParameter extends ENamedElement + { + property eBounds : EGenericType[*] { ordered !resolve composes }; + } + datatype EInvocationTargetException : 'java.lang.reflect.InvocationTargetException' { !serializable }; +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/classes/META-INF/MANIFEST.MF b/Source/eu.modelwriter.core.alloyinecore/target/classes/META-INF/MANIFEST.MF new file mode 100644 index 00000000..f45bdc8a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/classes/META-INF/MANIFEST.MF @@ -0,0 +1,7 @@ +Manifest-Version: 1.0 +Class-Path: antlr-4.6-complete.jar kodkod.jar guava-21.0.jar org.sat4j + .core-2.3.1.jar org.eclipse.emf.common_2.12.0.v20160420-0247.jar org. + eclipse.emf.ecore.xmi_2.12.0.v20160420-0247.jar org.eclipse.emf.ecore + _2.12.0.v20160420-0247.jar +Main-Class: eu.modelwriter.core.alloyinecore.AlloyInECoreFrontEnd_Test + diff --git a/Source/eu.modelwriter.core.alloyinecore/target/maven-status/maven-compiler-plugin/compile/default-cli/createdFiles.lst b/Source/eu.modelwriter.core.alloyinecore/target/maven-status/maven-compiler-plugin/compile/default-cli/createdFiles.lst new file mode 100644 index 00000000..e69de29b diff --git a/Source/eu.modelwriter.core.alloyinecore/target/maven-status/maven-compiler-plugin/compile/default-cli/inputFiles.lst b/Source/eu.modelwriter.core.alloyinecore/target/maven-status/maven-compiler-plugin/compile/default-cli/inputFiles.lst new file mode 100644 index 00000000..f1663067 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/maven-status/maven-compiler-plugin/compile/default-cli/inputFiles.lst @@ -0,0 +1,20 @@ +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/translator/KodkodTranslator.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreBaseListener.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/AlloyInECoreFrontEnd_Test.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/UnderlineErrorListener.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AnnotationSources.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/playground/GuavaTester_MultiSet.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreParser.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreBaseVisitor.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/playground/GuavaTester_Table.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/playground/GuavaTester_MultiMap1.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/playground/Test.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/Module.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/playground/GuavaTester_MultiMap.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreLexer.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/WarningRecognitionException.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreListener.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/KodKodFrontEnd_Test.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/Utilities.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/Console.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreVisitor.java diff --git a/Source/eu.modelwriter.core.alloyinecore/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/Source/eu.modelwriter.core.alloyinecore/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst new file mode 100644 index 00000000..e69de29b diff --git a/Source/eu.modelwriter.core.alloyinecore/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/Source/eu.modelwriter.core.alloyinecore/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst new file mode 100644 index 00000000..f1663067 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -0,0 +1,20 @@ +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/translator/KodkodTranslator.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreBaseListener.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/AlloyInECoreFrontEnd_Test.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/UnderlineErrorListener.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AnnotationSources.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/playground/GuavaTester_MultiSet.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreParser.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreBaseVisitor.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/playground/GuavaTester_Table.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/playground/GuavaTester_MultiMap1.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/playground/Test.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/Module.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/playground/GuavaTester_MultiMap.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreLexer.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/WarningRecognitionException.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreListener.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/KodKodFrontEnd_Test.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/Utilities.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/Console.java +/home/ferhat/IdeaProjects/eu.modelwriter.core.alloyinecore/src/main/java/eu/modelwriter/core/alloyinecore/recognizer/AlloyInEcoreVisitor.java diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/AttrTest.recore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/AttrTest.recore new file mode 100644 index 00000000..2cb68cb9 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/AttrTest.recore @@ -0,0 +1,41 @@ +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package TestPackage : tp = 'www.testpackage.org' +{ + private class TestClass extends SuperClass, UberClass : 'TCname' + { + private static model transient volatile nullable readonly attribute testAttr : Ecore::EDate[?] = '2017-01-01' { !unique derived unsettable ordered id } + { + derivation : ~testAttr; + } + model nullable attribute testStringAttr : String[?] = '' { ordered }; + ghost attribute testRealAttr : Real[?] = '0.0' { ordered }; + transient volatile attribute testBooleanAttr : Boolean[?] = 'false' { ordered }; + private transient attribute testIntAttr : Integer[?] = '1' { ordered }; + attribute testAttr1 : Integer[1] = '1' { ordered }; + attribute testAttr2 : Integer[+] = '1' { ordered }; + attribute testAttr3 : Integer[*] = '1' { ordered }; + attribute testAttr4 : Integer[2..5] = '1' { ordered }; + attribute testAttr5 : Integer[?] = '1' { ordered }; + attribute testUnlimitedNaturalAttr : UnlimitedNatural[?] = '1' { ordered }; + } + interface TestInterface extends SuperClass : 'TIname'; + enum TestEnum : 'TEname' { !serializable }; + primitive datatype TestDataType : 'TDTname' { !serializable }; + abstract class SuperClass; + abstract class UberClass; + package SubPackage : sp = 'www.sub.testpackage.org' + { + class SubTestClass + { + attribute testIntAttr : Integer[?] = '0' { ordered }; + attribute testStringAttr : String[?] = '' { ordered }; + attribute testRealAttr : Real[?] = '0' { ordered }; + transient volatile attribute testBooleanAttr : Boolean[?] = 'false' { ordered }; + transient attribute testAttr : Ecore::EDate[?] = '2016-09-09' { ordered }; + } + interface SubTestInterface; + enum SubTestEnum; + datatype SubTestDataType : 'STDTname'; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Ecore.ecore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Ecore.ecore new file mode 100644 index 00000000..15a3569f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Ecore.ecore @@ -0,0 +1,526 @@ + + + + +
+ + + + + + +
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + +
+
+ + + + + + +
+ + + + + + + +
+
+ + + + + + + + + + +
+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + +
+
+ + + + +
+
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+
+ + + + +
+ + + + +
+ + + + +
+
+ + + + + +
+
+ + + + + + +
+ + + + +
+
+ + + + + + + + + + +
+ + + + +
+
+ + + + +
+ + + + +
+
+ + + + + + + + +
+ + + + +
+
+ + + + + + + + + + +
+ + + + +
+
+ + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Ecore.recore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Ecore.recore new file mode 100644 index 00000000..1ef27747 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Ecore.recore @@ -0,0 +1,443 @@ +package ecore : ecore = 'http://www.eclipse.org/emf/2002/Ecore' +{ + class EAttribute extends EStructuralFeature + { + attribute iD : EBoolean[?] { ordered }; + transient volatile readonly property eAttributeType : EDataType[1] { derived ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ConsistentTransient' + ); + } + class EAnnotation extends EModelElement + { + attribute source : EString[?] { ordered }; + property details : EStringToStringMapEntry[*] { ordered !resolve composes }; + transient property eModelElement#eAnnotations : EModelElement[?] { ordered !resolve }; + property contents : EObject[*] { ordered !resolve composes }; + property references : EObject[*] { ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedSourceURI' + ); + } + class EClass extends EClassifier + { + attribute abstract : EBoolean[?] { ordered }; + attribute interface : EBoolean[?] { ordered }; + operation isSuperTypeOf(someClass : EClass[?] { ordered }) : EBoolean[?] { ordered }; + operation getFeatureCount() : EInt[?] { ordered }; + operation getEStructuralFeature(featureID : EInt[?] { ordered }) : EStructuralFeature[?] { ordered }; + operation getFeatureID(feature : EStructuralFeature[?] { ordered }) : EInt[?] { ordered }; + operation getEStructuralFeature(featureName : EString[?] { ordered }) : EStructuralFeature[?] { ordered }; + operation getOperationCount() : EInt[?] { ordered }; + operation getEOperation(operationID : EInt[?] { ordered }) : EOperation[?] { ordered }; + operation getOperationID(operation : EOperation[?] { ordered }) : EInt[?] { ordered }; + operation getOverride(operation : EOperation[?] { ordered }) : EOperation[?] { ordered }; + operation getFeatureType(feature : EStructuralFeature[?] { ordered }) : EGenericType[?] { ordered }; + property eSuperTypes : EClass[*] { unsettable ordered } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + property eOperations#eContainingClass : EOperation[*] { ordered !resolve composes }; + transient volatile readonly property eAllAttributes : EAttribute[*] { derived ordered }; + transient volatile readonly property eAllReferences : EReference[*] { derived ordered }; + transient volatile readonly property eReferences : EReference[*] { derived ordered }; + transient volatile readonly property eAttributes : EAttribute[*] { derived ordered }; + transient volatile readonly property eAllContainments : EReference[*] { derived ordered }; + transient volatile readonly property eAllOperations : EOperation[*] { derived ordered }; + transient volatile readonly property eAllStructuralFeatures : EStructuralFeature[*] { derived ordered }; + transient volatile readonly property eAllSuperTypes : EClass[*] { derived ordered }; + transient volatile readonly property eIDAttribute : EAttribute[?] { derived ordered !resolve }; + property eStructuralFeatures#eContainingClass : EStructuralFeature[*] { ordered !resolve composes }; + property eGenericSuperTypes : EGenericType[*] { unsettable ordered !resolve composes } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + transient volatile readonly property eAllGenericSuperTypes : EGenericType[*] { derived ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'InterfaceIsAbstract AtMostOneID UniqueFeatureNames UniqueOperationSignatures NoCircularSuperTypes WellFormedMapEntryClass ConsistentSuperTypes DisjointFeatureAndOperationSignatures' + ); + } + abstract class EClassifier extends ENamedElement + { + volatile attribute instanceClassName : EString[?] { unsettable ordered } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + transient volatile readonly attribute instanceClass : EJavaClass[?] { derived ordered }; + transient volatile readonly attribute defaultValue : EJavaObject[?] { derived ordered }; + volatile attribute instanceTypeName : EString[?] { unsettable ordered } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + operation isInstance(object : EJavaObject[?] { ordered }) : EBoolean[?] { ordered }; + operation getClassifierID() : EInt[?] { ordered }; + transient readonly property ePackage#eClassifiers : EPackage[?] { ordered }; + property eTypeParameters : ETypeParameter[*] { ordered composes }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedInstanceTypeName UniqueTypeParameterNames' + ); + } + class EDataType extends EClassifier + { + attribute serializable : EBoolean[?] = 'true' { ordered }; + } + class EEnum extends EDataType + { + operation getEEnumLiteral(name : EString[?] { ordered }) : EEnumLiteral[?] { ordered }; + operation getEEnumLiteral(value : EInt[?] { ordered }) : EEnumLiteral[?] { ordered }; + operation getEEnumLiteralByLiteral(literal : EString[?] { ordered }) : EEnumLiteral[?] { ordered }; + property eLiterals#eEnum : EEnumLiteral[*] { ordered !resolve composes }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'UniqueEnumeratorNames UniqueEnumeratorLiterals' + ); + } + class EEnumLiteral extends ENamedElement + { + attribute value : EInt[?] { ordered }; + transient attribute instance : EEnumerator[?] { ordered }; + attribute literal : EString[?] { ordered }; + transient readonly property eEnum#eLiterals : EEnum[?] { ordered !resolve }; + } + class EFactory extends EModelElement + { + operation create(eClass : EClass[?] { ordered }) : EObject[?] { ordered }; + operation createFromString(eDataType : EDataType[?] { ordered }, literalValue : EString[?] { ordered }) : EJavaObject[?] { ordered }; + operation convertToString(eDataType : EDataType[?] { ordered }, instanceValue : EJavaObject[?] { ordered }) : EString[?] { ordered }; + transient property ePackage#eFactoryInstance : EPackage[1] { ordered !resolve }; + } + abstract class EModelElement + { + operation getEAnnotation(source : EString[?] { ordered }) : EAnnotation[?] { ordered }; + property eAnnotations#eModelElement : EAnnotation[*] { ordered !resolve composes }; + } + abstract class ENamedElement extends EModelElement + { + attribute name : EString[?] { ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedName' + ); + } + class EObject + { + operation eClass() : EClass[?] { ordered }; + operation eIsProxy() : EBoolean[?] { ordered }; + operation eResource() : EResource[?] { ordered }; + operation eContainer() : EObject[?] { ordered }; + operation eContainingFeature() : EStructuralFeature[?] { ordered }; + operation eContainmentFeature() : EReference[?] { ordered }; + operation eContents() : EEList[?] { ordered }; + operation eAllContents() : ETreeIterator[?] { ordered }; + operation eCrossReferences() : EEList[?] { ordered }; + operation eGet(feature : EStructuralFeature[?] { ordered }) : EJavaObject[?] { ordered }; + operation eGet(feature : EStructuralFeature[?] { ordered }, resolve : EBoolean[?] { ordered }) : EJavaObject[?] { ordered }; + operation eSet(feature : EStructuralFeature[?] { ordered }, newValue : EJavaObject[?] { ordered }) { ordered }; + operation eIsSet(feature : EStructuralFeature[?] { ordered }) : EBoolean[?] { ordered }; + operation eUnset(feature : EStructuralFeature[?] { ordered }) { ordered }; + operation eInvoke(operation : EOperation[?] { ordered }, arguments : EEList[?] { ordered }) : EJavaObject[?] throws EInvocationTargetException { ordered }; + } + class EOperation extends ETypedElement + { + operation getOperationID() : EInt[?] { ordered }; + operation isOverrideOf(someOperation : EOperation[?] { ordered }) : EBoolean[?] { ordered }; + transient readonly property eContainingClass#eOperations : EClass[?] { ordered !resolve }; + property eTypeParameters : ETypeParameter[*] { ordered composes }; + property eParameters#eOperation : EParameter[*] { ordered !resolve composes }; + property eExceptions : EClassifier[*] { unsettable ordered } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + property eGenericExceptions : EGenericType[*] { unsettable ordered !resolve composes } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'UniqueParameterNames UniqueTypeParameterNames NoRepeatingVoid' + ); + } + class EPackage extends ENamedElement + { + attribute nsURI : EString[?] { ordered }; + attribute nsPrefix : EString[?] { ordered }; + operation getEClassifier(name : EString[?] { ordered }) : EClassifier[?] { ordered }; + transient property eFactoryInstance#ePackage : EFactory[1] { ordered !resolve }; + property eClassifiers#ePackage : EClassifier[*] { ordered composes }; + property eSubpackages#eSuperPackage : EPackage[*] { ordered composes }; + transient readonly property eSuperPackage#eSubpackages : EPackage[?] { ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'WellFormedNsURI WellFormedNsPrefix UniqueSubpackageNames UniqueClassifierNames UniqueNsURIs' + ); + } + class EParameter extends ETypedElement + { + transient readonly property eOperation#eParameters : EOperation[?] { ordered !resolve }; + } + class EReference extends EStructuralFeature + { + attribute containment : EBoolean[?] { ordered }; + transient volatile readonly attribute container : EBoolean[?] { derived ordered }; + attribute resolveProxies : EBoolean[?] = 'true' { ordered }; + property eOpposite : EReference[?] { ordered }; + transient volatile readonly property eReferenceType : EClass[1] { derived ordered }; + property eKeys : EAttribute[*] { ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ConsistentOpposite SingleContainer ConsistentKeys ConsistentUnique ConsistentContainer' + ); + } + abstract class EStructuralFeature extends ETypedElement + { + attribute changeable : EBoolean[?] = 'true' { ordered }; + attribute volatile : EBoolean[?] { ordered }; + attribute transient : EBoolean[?] { ordered }; + attribute defaultValueLiteral : EString[?] { ordered }; + transient volatile readonly attribute defaultValue : EJavaObject[?] { derived ordered }; + attribute unsettable : EBoolean[?] { ordered }; + attribute derived : EBoolean[?] { ordered }; + operation getFeatureID() : EInt[?] { ordered }; + operation getContainerClass() : EJavaClass[?] { ordered }; + transient readonly property eContainingClass#eStructuralFeatures : EClass[?] { ordered !resolve }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ValidDefaultValueLiteral' + ); + } + abstract class ETypedElement extends ENamedElement + { + attribute ordered : EBoolean[?] = 'true' { ordered }; + attribute unique : EBoolean[?] = 'true' { ordered }; + attribute lowerBound : EInt[?] { ordered }; + attribute upperBound : EInt[?] = '1' { ordered }; + transient volatile readonly attribute many : EBoolean[?] { derived ordered }; + transient volatile readonly attribute required : EBoolean[?] { derived ordered }; + volatile property eType : EClassifier[?] { unsettable ordered } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + volatile property eGenericType : EGenericType[?] { unsettable ordered !resolve composes } + { + annotation 'http://www.eclipse.org/emf/2002/GenModel' + ( + 'suppressedIsSetVisibility' = 'true', + 'suppressedUnsetVisibility' = 'true' + ); + } + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ValidLowerBound ValidUpperBound ConsistentBounds ValidType' + ); + } + datatype EBigDecimal : 'java.math.BigDecimal' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#decimal' + ); + } + datatype EBigInteger : 'java.math.BigInteger' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#integer' + ); + } + datatype EBoolean : 'boolean' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#boolean' + ); + } + datatype EBooleanObject : 'java.lang.Boolean' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EBoolean', + 'name' = 'EBoolean:Object' + ); + } + datatype EByte : 'byte' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#byte' + ); + } + datatype EByteArray : 'byte[]' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#hexBinary' + ); + } + datatype EByteObject : 'java.lang.Byte' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EByte', + 'name' = 'EByte:Object' + ); + } + datatype EChar : 'char'; + datatype ECharacterObject : 'java.lang.Character' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EChar', + 'name' = 'EChar:Object' + ); + } + datatype EDate : 'java.util.Date'; + datatype EDiagnosticChain : 'org.eclipse.emf.common.util.DiagnosticChain' { !serializable }; + datatype EDouble : 'double' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#double' + ); + } + datatype EDoubleObject : 'java.lang.Double' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EDouble', + 'name' = 'EDouble:Object' + ); + } + datatype EEList : 'org.eclipse.emf.common.util.EList' { !serializable }; + datatype EEnumerator : 'org.eclipse.emf.common.util.Enumerator' { !serializable }; + datatype EFeatureMap : 'org.eclipse.emf.ecore.util.FeatureMap' { !serializable }; + datatype EFeatureMapEntry : 'org.eclipse.emf.ecore.util.FeatureMap$Entry' { !serializable }; + datatype EFloat : 'float' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#float' + ); + } + datatype EFloatObject : 'java.lang.Float' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EFloat', + 'name' = 'EFloat:Object' + ); + } + datatype EInt : 'int' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#int' + ); + } + datatype EIntegerObject : 'java.lang.Integer' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EInt', + 'name' = 'EInt:Object' + ); + } + datatype EJavaClass : 'java.lang.Class'; + datatype EJavaObject : 'java.lang.Object'; + datatype ELong : 'long' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#long' + ); + } + datatype ELongObject : 'java.lang.Long' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'ELong', + 'name' = 'ELong:Object' + ); + } + datatype EMap : 'java.util.Map' { !serializable }; + datatype EResource : 'org.eclipse.emf.ecore.resource.Resource' { !serializable }; + datatype EResourceSet : 'org.eclipse.emf.ecore.resource.ResourceSet' { !serializable }; + datatype EShort : 'short' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#short' + ); + } + datatype EShortObject : 'java.lang.Short' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'EShort', + 'name' = 'EShort:Object' + ); + } + datatype EString : 'java.lang.String' + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'baseType' = 'http://www.w3.org/2001/XMLSchema#string' + ); + } + class EStringToStringMapEntry : 'java.util.Map$Entry' + { + attribute key : EString[?] { ordered }; + attribute value : EString[?] { ordered }; + } + datatype ETreeIterator : 'org.eclipse.emf.common.util.TreeIterator' { !serializable }; + class EGenericType + { + operation isInstance(object : EJavaObject[?] { ordered }) : EBoolean[?] { ordered }; + property eUpperBound : EGenericType[?] { ordered !resolve composes }; + property eTypeArguments : EGenericType[*] { ordered !resolve composes }; + transient readonly property eRawType : EClassifier[1] { derived ordered }; + property eLowerBound : EGenericType[?] { ordered !resolve composes }; + property eTypeParameter : ETypeParameter[?] { ordered !resolve }; + property eClassifier : EClassifier[?] { ordered }; + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'constraints' = 'ConsistentType ConsistentBounds ConsistentArguments' + ); + } + class ETypeParameter extends ENamedElement + { + property eBounds : EGenericType[*] { ordered !resolve composes }; + } + datatype EInvocationTargetException : 'java.lang.reflect.InvocationTargetException' { !serializable }; +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Erroneous.kodkod b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Erroneous.kodkod new file mode 100644 index 00000000..2be8b6e8 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Erroneous.kodkod @@ -0,0 +1,15 @@ +universe {d0, d1, d2, d3, f0, f0, f1, f2, f3,} + +relations { + File : [ {(f0), (f1), (f2)} ] + Dir : [ {(d0), (d1), (d2)} ] + Root: [{(d0)}] + Root: [{(d0)}] + contents:[{[d0, d1], [d0, f0], [kk, f0], [d0, f1], [d0, f2]}, {[d0, d1], [d0, f0], [d0, f1], [d0, f2], [d1, d2]}] +} + +contents in Dir lone -> some (Dir + File) +all d:Dir | not (x in d.^contents) +Root in Dir +all d: dir | not (x in d.^contents) +(File + Dir) in Root.*contents \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Filesystem.kodkod b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Filesystem.kodkod new file mode 100644 index 00000000..dcc9c70f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Filesystem.kodkod @@ -0,0 +1,13 @@ +universe {d0, d1, d2, d3, f0, f1, f2, f3} + +relations { + File : [ {(f0), (f1), (f2)} ] + Dir : [ {(d0), (d1), (d2)} ] + Root: [{(d0)}] + contents: [{[d0, d1], [d0, f0], [d0, f1], [d0, f2]}, {[d0, d1], [d0, f0], [d0, f1], [d0, f2], [d1, d2]}] +} + +contents in Dir lone -> some (Dir + File) +all d:Dir | not (d in d.^contents) +Root in Dir +(File + Dir) in Root.*contents \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Generics1.recore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Generics1.recore new file mode 100644 index 00000000..7c9ae017 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Generics1.recore @@ -0,0 +1,72 @@ +import My : 'My.ecore'; +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; +import Instance : 'Instance.requirements'; + +package generics : gns = 'eu.modelwriter.generics' +{ + abstract class List + { + --invariant test: all c: Canvas | lone c; + invariant test: ~Canvas = *Iterator; + operation add(element : E); + operation iterator() : Iterator[?]; + invariant quantifier: all d:List | not (d in d.^contents); + } + invariant test1: contents in Dir -> (Dir + File); + interface Iterator + { + invariant test2: (File + Dir) in Root.*contents; + operation next() : E[?] throws MyException; + operation hasNext() : Boolean; + } + class ArrayList extends List; + class Car; + abstract class Person { attribute name: String [1]; } + class Owner + { + property cars : ArrayList[?]; + property owner : V[1..*]; + } + abstract class Shape; + class Canvas + { + operation draw(shapes : List, x: Integer, y: Integer) : Boolean[?]; + operation create(name : String); + operation create(arg : ArrayList[?]) + { + requires : one ArrayList; + body; + } + property ref : List[?]; + property heyRef: sub::Hey; + property noWay: sub::subsub::CantTouchThis; + property b : My::A[2..5|?]; + attribute c: String; + attribute d: V[*|?]; + annotation; + annotation 'modelwriter/Ferhat' ('key' = , 'key' = 'value', =) + { + reference Library::books; + class AnnotationClass extends Person , Car; + property mehmet: type[+|1]; + reference Instance::B; + reference Instance::@requirements.0::@parts.1; + reference Instance::@requirements.0::@parts.0; + reference Instance::@relationships.0; + } + } + class MyException; + enum BookCategory + { + literal Mystery = 0; + literal ScienceFiction = 1; + literal Biography = 2; + } + package sub : s = 'subsubsub' + { + public class Hey; + package subsub : s2 = 'wow such sub'{ + class CantTouchThis; + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Java.g4 b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Java.g4 new file mode 100644 index 00000000..2d804a4a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Java.g4 @@ -0,0 +1,1016 @@ +/* + [The "BSD licence"] + Copyright (c) 2013 Terence Parr, Sam Harwell + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** A Java 1.7 grammar for ANTLR v4 derived from ANTLR v3 Java grammar. + * Uses ANTLR v4's left-recursive expression notation. + * It parses ECJ, Netbeans, JDK etc... + * + * Sam Harwell cleaned this up significantly and updated to 1.7! + * + * You can test with + * + * $ antlr4 Java.g4 + * $ javac *.java + * $ grun Java compilationUnit *.java + */ +grammar Java; + +// starting point for parsing a java file +compilationUnit + : packageDeclaration? importDeclaration* typeDeclaration* EOF + ; + +packageDeclaration + : annotation* 'package' qualifiedName ';' + ; + +importDeclaration + : 'import' 'static'? qualifiedName ('.' '*')? ';' + ; + +typeDeclaration + : classOrInterfaceModifier* classDeclaration + | classOrInterfaceModifier* enumDeclaration + | classOrInterfaceModifier* interfaceDeclaration + | classOrInterfaceModifier* annotationTypeDeclaration + | ';' + ; + +modifier + : classOrInterfaceModifier + | ( 'native' + | 'synchronized' + | 'transient' + | 'volatile' + ) + ; + +classOrInterfaceModifier + : annotation // class or interface + | ( 'public' // class or interface + | 'protected' // class or interface + | 'private' // class or interface + | 'static' // class or interface + | 'abstract' // class or interface + | 'final' // class only -- does not apply to interfaces + | 'strictfp' // class or interface + ) + ; + +variableModifier + : 'final' + | annotation + ; + +classDeclaration + : 'class' Identifier typeParameters? + ('extends' typeType)? + ('implements' typeList)? + classBody + ; + +typeParameters + : '<' typeParameter (',' typeParameter)* '>' + ; + +typeParameter + : Identifier ('extends' typeBound)? + ; + +typeBound + : typeType ('&' typeType)* + ; + +enumDeclaration + : ENUM Identifier ('implements' typeList)? + '{' enumConstants? ','? enumBodyDeclarations? '}' + ; + +enumConstants + : enumConstant (',' enumConstant)* + ; + +enumConstant + : annotation* Identifier arguments? classBody? + ; + +enumBodyDeclarations + : ';' classBodyDeclaration* + ; + +interfaceDeclaration + : 'interface' Identifier typeParameters? ('extends' typeList)? interfaceBody + ; + +typeList + : typeType (',' typeType)* + ; + +classBody + : '{' classBodyDeclaration* '}' + ; + +interfaceBody + : '{' interfaceBodyDeclaration* '}' + ; + +classBodyDeclaration + : ';' + | 'static'? block + | modifier* memberDeclaration + ; + +memberDeclaration + : methodDeclaration + | genericMethodDeclaration + | fieldDeclaration + | constructorDeclaration + | genericConstructorDeclaration + | interfaceDeclaration + | annotationTypeDeclaration + | classDeclaration + | enumDeclaration + ; + +/* We use rule this even for void methods which cannot have [] after parameters. + This simplifies grammar and we can consider void to be a type, which + renders the [] matching as a context-sensitive issue or a semantic check + for invalid return type after parsing. + */ +methodDeclaration + : (typeType|'void') Identifier formalParameters ('[' ']')* + ('throws' qualifiedNameList)? + ( methodBody + | ';' + ) + ; + +genericMethodDeclaration + : typeParameters methodDeclaration + ; + +constructorDeclaration + : Identifier formalParameters ('throws' qualifiedNameList)? + constructorBody + ; + +genericConstructorDeclaration + : typeParameters constructorDeclaration + ; + +fieldDeclaration + : typeType variableDeclarators ';' + ; + +interfaceBodyDeclaration + : modifier* interfaceMemberDeclaration + | ';' + ; + +interfaceMemberDeclaration + : constDeclaration + | interfaceMethodDeclaration + | genericInterfaceMethodDeclaration + | interfaceDeclaration + | annotationTypeDeclaration + | classDeclaration + | enumDeclaration + ; + +constDeclaration + : typeType constantDeclarator (',' constantDeclarator)* ';' + ; + +constantDeclarator + : Identifier ('[' ']')* '=' variableInitializer + ; + +// see matching of [] comment in methodDeclaratorRest +interfaceMethodDeclaration + : (typeType|'void') Identifier formalParameters ('[' ']')* + ('throws' qualifiedNameList)? + ';' + ; + +genericInterfaceMethodDeclaration + : typeParameters interfaceMethodDeclaration + ; + +variableDeclarators + : variableDeclarator (',' variableDeclarator)* + ; + +variableDeclarator + : variableDeclaratorId ('=' variableInitializer)? + ; + +variableDeclaratorId + : Identifier ('[' ']')* + ; + +variableInitializer + : arrayInitializer + | expression + ; + +arrayInitializer + : '{' (variableInitializer (',' variableInitializer)* (',')? )? '}' + ; + +enumConstantName + : Identifier + ; + +typeType + : classOrInterfaceType ('[' ']')* + | primitiveType ('[' ']')* + ; + +classOrInterfaceType + : Identifier typeArguments? ('.' Identifier typeArguments? )* + ; + +primitiveType + : 'boolean' + | 'char' + | 'byte' + | 'short' + | 'int' + | 'long' + | 'float' + | 'double' + ; + +typeArguments + : '<' typeArgument (',' typeArgument)* '>' + ; + +typeArgument + : typeType + | '?' (('extends' | 'super') typeType)? + ; + +qualifiedNameList + : qualifiedName (',' qualifiedName)* + ; + +formalParameters + : '(' formalParameterList? ')' + ; + +formalParameterList + : formalParameter (',' formalParameter)* (',' lastFormalParameter)? + | lastFormalParameter + ; + +formalParameter + : variableModifier* typeType variableDeclaratorId + ; + +lastFormalParameter + : variableModifier* typeType '...' variableDeclaratorId + ; + +methodBody + : block + ; + +constructorBody + : block + ; + +qualifiedName + : Identifier ('.' Identifier)* + ; + +literal + : IntegerLiteral + | FloatingPointLiteral + | CharacterLiteral + | StringLiteral + | BooleanLiteral + | 'null' + ; + +// ANNOTATIONS + +annotation + : '@' annotationName ( '(' ( elementValuePairs | elementValue )? ')' )? + ; + +annotationName : qualifiedName ; + +elementValuePairs + : elementValuePair (',' elementValuePair)* + ; + +elementValuePair + : Identifier '=' elementValue + ; + +elementValue + : expression + | annotation + | elementValueArrayInitializer + ; + +elementValueArrayInitializer + : '{' (elementValue (',' elementValue)*)? (',')? '}' + ; + +annotationTypeDeclaration + : '@' 'interface' Identifier annotationTypeBody + ; + +annotationTypeBody + : '{' (annotationTypeElementDeclaration)* '}' + ; + +annotationTypeElementDeclaration + : modifier* annotationTypeElementRest + | ';' // this is not allowed by the grammar, but apparently allowed by the actual compiler + ; + +annotationTypeElementRest + : typeType annotationMethodOrConstantRest ';' + | classDeclaration ';'? + | interfaceDeclaration ';'? + | enumDeclaration ';'? + | annotationTypeDeclaration ';'? + ; + +annotationMethodOrConstantRest + : annotationMethodRest + | annotationConstantRest + ; + +annotationMethodRest + : Identifier '(' ')' defaultValue? + ; + +annotationConstantRest + : variableDeclarators + ; + +defaultValue + : 'default' elementValue + ; + +// STATEMENTS / BLOCKS + +block + : '{' blockStatement* '}' + ; + +blockStatement + : localVariableDeclarationStatement + | statement + | typeDeclaration + ; + +localVariableDeclarationStatement + : localVariableDeclaration ';' + ; + +localVariableDeclaration + : variableModifier* typeType variableDeclarators + ; + +statement + : block + | ASSERT expression (':' expression)? ';' + | 'if' parExpression statement ('else' statement)? + | 'for' '(' forControl ')' statement + | 'while' parExpression statement + | 'do' statement 'while' parExpression ';' + | 'try' block (catchClause+ finallyBlock? | finallyBlock) + | 'try' resourceSpecification block catchClause* finallyBlock? + | 'switch' parExpression '{' switchBlockStatementGroup* switchLabel* '}' + | 'synchronized' parExpression block + | 'return' expression? ';' + | 'throw' expression ';' + | 'break' Identifier? ';' + | 'continue' Identifier? ';' + | ';' + | statementExpression ';' + | Identifier ':' statement + ; + +catchClause + : 'catch' '(' variableModifier* catchType Identifier ')' block + ; + +catchType + : qualifiedName ('|' qualifiedName)* + ; + +finallyBlock + : 'finally' block + ; + +resourceSpecification + : '(' resources ';'? ')' + ; + +resources + : resource (';' resource)* + ; + +resource + : variableModifier* classOrInterfaceType variableDeclaratorId '=' expression + ; + +/** Matches cases then statements, both of which are mandatory. + * To handle empty cases at the end, we add switchLabel* to statement. + */ +switchBlockStatementGroup + : switchLabel+ blockStatement+ + ; + +switchLabel + : 'case' constantExpression ':' + | 'case' enumConstantName ':' + | 'default' ':' + ; + +forControl + : enhancedForControl + | forInit? ';' expression? ';' forUpdate? + ; + +forInit + : localVariableDeclaration + | expressionList + ; + +enhancedForControl + : variableModifier* typeType variableDeclaratorId ':' expression + ; + +forUpdate + : expressionList + ; + +// EXPRESSIONS + +parExpression + : '(' expression ')' + ; + +expressionList + : expression (',' expression)* + ; + +statementExpression + : expression + ; + +constantExpression + : expression + ; + +expression + : primary + | expression '.' Identifier + | expression '.' 'this' + | expression '.' 'new' nonWildcardTypeArguments? innerCreator + | expression '.' 'super' superSuffix + | expression '.' explicitGenericInvocation + | expression '[' expression ']' + | expression '(' expressionList? ')' + | 'new' creator + | '(' typeType ')' expression + | expression ('++' | '--') + | ('+'|'-'|'++'|'--') expression + | ('~'|'!') expression + | expression ('*'|'/'|'%') expression + | expression ('+'|'-') expression + | expression ('<' '<' | '>' '>' '>' | '>' '>') expression + | expression ('<=' | '>=' | '>' | '<') expression + | expression 'instanceof' typeType + | expression ('==' | '!=') expression + | expression '&' expression + | expression '^' expression + | expression '|' expression + | expression '&&' expression + | expression '||' expression + | expression '?' expression ':' expression + | expression + ( '=' + | '+=' + | '-=' + | '*=' + | '/=' + | '&=' + | '|=' + | '^=' + | '>>=' + | '>>>=' + | '<<=' + | '%=' + ) + expression + ; + +primary + : '(' expression ')' + | 'this' + | 'super' + | literal + | Identifier + | typeType '.' 'class' + | 'void' '.' 'class' + | nonWildcardTypeArguments (explicitGenericInvocationSuffix | 'this' arguments) + ; + +creator + : nonWildcardTypeArguments createdName classCreatorRest + | createdName (arrayCreatorRest | classCreatorRest) + ; + +createdName + : Identifier typeArgumentsOrDiamond? ('.' Identifier typeArgumentsOrDiamond?)* + | primitiveType + ; + +innerCreator + : Identifier nonWildcardTypeArgumentsOrDiamond? classCreatorRest + ; + +arrayCreatorRest + : '[' + ( ']' ('[' ']')* arrayInitializer + | expression ']' ('[' expression ']')* ('[' ']')* + ) + ; + +classCreatorRest + : arguments classBody? + ; + +explicitGenericInvocation + : nonWildcardTypeArguments explicitGenericInvocationSuffix + ; + +nonWildcardTypeArguments + : '<' typeList '>' + ; + +typeArgumentsOrDiamond + : '<' '>' + | typeArguments + ; + +nonWildcardTypeArgumentsOrDiamond + : '<' '>' + | nonWildcardTypeArguments + ; + +superSuffix + : arguments + | '.' Identifier arguments? + ; + +explicitGenericInvocationSuffix + : 'super' superSuffix + | Identifier arguments + ; + +arguments + : '(' expressionList? ')' + ; + +// LEXER + +// §3.9 Keywords + +ABSTRACT : 'abstract'; +ASSERT : 'assert'; +BOOLEAN : 'boolean'; +BREAK : 'break'; +BYTE : 'byte'; +CASE : 'case'; +CATCH : 'catch'; +CHAR : 'char'; +CLASS : 'class'; +CONST : 'const'; +CONTINUE : 'continue'; +DEFAULT : 'default'; +DO : 'do'; +DOUBLE : 'double'; +ELSE : 'else'; +ENUM : 'enum'; +EXTENDS : 'extends'; +FINAL : 'final'; +FINALLY : 'finally'; +FLOAT : 'float'; +FOR : 'for'; +IF : 'if'; +GOTO : 'goto'; +IMPLEMENTS : 'implements'; +IMPORT : 'import'; +INSTANCEOF : 'instanceof'; +INT : 'int'; +INTERFACE : 'interface'; +LONG : 'long'; +NATIVE : 'native'; +NEW : 'new'; +PACKAGE : 'package'; +PRIVATE : 'private'; +PROTECTED : 'protected'; +PUBLIC : 'public'; +RETURN : 'return'; +SHORT : 'short'; +STATIC : 'static'; +STRICTFP : 'strictfp'; +SUPER : 'super'; +SWITCH : 'switch'; +SYNCHRONIZED : 'synchronized'; +THIS : 'this'; +THROW : 'throw'; +THROWS : 'throws'; +TRANSIENT : 'transient'; +TRY : 'try'; +VOID : 'void'; +VOLATILE : 'volatile'; +WHILE : 'while'; + +// §3.10.1 Integer Literals + +IntegerLiteral + : DecimalIntegerLiteral + | HexIntegerLiteral + | OctalIntegerLiteral + | BinaryIntegerLiteral + ; + +fragment +DecimalIntegerLiteral + : DecimalNumeral IntegerTypeSuffix? + ; + +fragment +HexIntegerLiteral + : HexNumeral IntegerTypeSuffix? + ; + +fragment +OctalIntegerLiteral + : OctalNumeral IntegerTypeSuffix? + ; + +fragment +BinaryIntegerLiteral + : BinaryNumeral IntegerTypeSuffix? + ; + +fragment +IntegerTypeSuffix + : [lL] + ; + +fragment +DecimalNumeral + : '0' + | NonZeroDigit (Digits? | Underscores Digits) + ; + +fragment +Digits + : Digit (DigitOrUnderscore* Digit)? + ; + +fragment +Digit + : '0' + | NonZeroDigit + ; + +fragment +NonZeroDigit + : [1-9] + ; + +fragment +DigitOrUnderscore + : Digit + | '_' + ; + +fragment +Underscores + : '_'+ + ; + +fragment +HexNumeral + : '0' [xX] HexDigits + ; + +fragment +HexDigits + : HexDigit (HexDigitOrUnderscore* HexDigit)? + ; + +fragment +HexDigit + : [0-9a-fA-F] + ; + +fragment +HexDigitOrUnderscore + : HexDigit + | '_' + ; + +fragment +OctalNumeral + : '0' Underscores? OctalDigits + ; + +fragment +OctalDigits + : OctalDigit (OctalDigitOrUnderscore* OctalDigit)? + ; + +fragment +OctalDigit + : [0-7] + ; + +fragment +OctalDigitOrUnderscore + : OctalDigit + | '_' + ; + +fragment +BinaryNumeral + : '0' [bB] BinaryDigits + ; + +fragment +BinaryDigits + : BinaryDigit (BinaryDigitOrUnderscore* BinaryDigit)? + ; + +fragment +BinaryDigit + : [01] + ; + +fragment +BinaryDigitOrUnderscore + : BinaryDigit + | '_' + ; + +// §3.10.2 Floating-Point Literals + +FloatingPointLiteral + : DecimalFloatingPointLiteral + | HexadecimalFloatingPointLiteral + ; + +fragment +DecimalFloatingPointLiteral + : Digits '.' Digits? ExponentPart? FloatTypeSuffix? + | '.' Digits ExponentPart? FloatTypeSuffix? + | Digits ExponentPart FloatTypeSuffix? + | Digits FloatTypeSuffix + ; + +fragment +ExponentPart + : ExponentIndicator SignedInteger + ; + +fragment +ExponentIndicator + : [eE] + ; + +fragment +SignedInteger + : Sign? Digits + ; + +fragment +Sign + : [+-] + ; + +fragment +FloatTypeSuffix + : [fFdD] + ; + +fragment +HexadecimalFloatingPointLiteral + : HexSignificand BinaryExponent FloatTypeSuffix? + ; + +fragment +HexSignificand + : HexNumeral '.'? + | '0' [xX] HexDigits? '.' HexDigits + ; + +fragment +BinaryExponent + : BinaryExponentIndicator SignedInteger + ; + +fragment +BinaryExponentIndicator + : [pP] + ; + +// §3.10.3 Boolean Literals + +BooleanLiteral + : 'true' + | 'false' + ; + +// §3.10.4 Character Literals + +CharacterLiteral + : '\'' SingleCharacter '\'' + | '\'' EscapeSequence '\'' + ; + +fragment +SingleCharacter + : ~['\\] + ; + +// §3.10.5 String Literals + +StringLiteral + : '"' StringCharacters? '"' + ; + +fragment +StringCharacters + : StringCharacter+ + ; + +fragment +StringCharacter + : ~["\\] + | EscapeSequence + ; + +// §3.10.6 Escape Sequences for Character and String Literals + +fragment +EscapeSequence + : '\\' [btnfr"'\\] + | OctalEscape + | UnicodeEscape + ; + +fragment +OctalEscape + : '\\' OctalDigit + | '\\' OctalDigit OctalDigit + | '\\' ZeroToThree OctalDigit OctalDigit + ; + +fragment +UnicodeEscape + : '\\' 'u' HexDigit HexDigit HexDigit HexDigit + ; + +fragment +ZeroToThree + : [0-3] + ; + +// §3.10.7 The Null Literal + +NullLiteral + : 'null' + ; + +// §3.11 Separators + +LPAREN : '('; +RPAREN : ')'; +LBRACE : '{'; +RBRACE : '}'; +LBRACK : '['; +RBRACK : ']'; +SEMI : ';'; +COMMA : ','; +DOT : '.'; + +// §3.12 Operators + +ASSIGN : '='; +GT : '>'; +LT : '<'; +BANG : '!'; +TILDE : '~'; +QUESTION : '?'; +COLON : ':'; +EQUAL : '=='; +LE : '<='; +GE : '>='; +NOTEQUAL : '!='; +AND : '&&'; +OR : '||'; +INC : '++'; +DEC : '--'; +ADD : '+'; +SUB : '-'; +MUL : '*'; +DIV : '/'; +BITAND : '&'; +BITOR : '|'; +CARET : '^'; +MOD : '%'; + +ADD_ASSIGN : '+='; +SUB_ASSIGN : '-='; +MUL_ASSIGN : '*='; +DIV_ASSIGN : '/='; +AND_ASSIGN : '&='; +OR_ASSIGN : '|='; +XOR_ASSIGN : '^='; +MOD_ASSIGN : '%='; +LSHIFT_ASSIGN : '<<='; +RSHIFT_ASSIGN : '>>='; +URSHIFT_ASSIGN : '>>>='; + +// §3.8 Identifiers (must appear after all keywords in the grammar) + +Identifier + : JavaLetter JavaLetterOrDigit* + ; + +fragment +JavaLetter + : [a-zA-Z$_] // these are the "java letters" below 0x7F + | // covers all characters above 0x7F which are not a surrogate + ~[\u0000-\u007F\uD800-\uDBFF] + | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF + [\uD800-\uDBFF] [\uDC00-\uDFFF] + ; + +fragment +JavaLetterOrDigit + : [a-zA-Z0-9$_] // these are the "java letters or digits" below 0x7F + | // covers all characters above 0x7F which are not a surrogate + ~[\u0000-\u007F\uD800-\uDBFF] + | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF + [\uD800-\uDBFF] [\uDC00-\uDFFF] + ; + +// +// Additional symbols not defined in the lexical specification +// + +AT : '@'; +ELLIPSIS : '...'; + +// +// Whitespace and comments +// + +WS : [ \t\r\n\u000C]+ -> skip + ; + +COMMENT + : '/*' .*? '*/' -> channel(HIDDEN) + ; + +LINE_COMMENT + : '//' ~[\r\n]* -> channel(HIDDEN) + ; diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/JavaParser2.g4 b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/JavaParser2.g4 new file mode 100644 index 00000000..85de3603 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/JavaParser2.g4 @@ -0,0 +1,1063 @@ +parser grammar JavaParser2; + +options { + tokenVocab = JavaLexer; +} + +packageName + : Identifier (DOT Identifier)* + ; + +typeName + : Identifier + | packageOrTypeName DOT Identifier + ; + +packageOrTypeName + : Identifier (DOT Identifier)* + ; + +expressionName + : Identifier + | ambiguousName DOT Identifier + ; + +methodName + : Identifier + ; + +ambiguousName + : Identifier (DOT Identifier)* + ; + +simpleTypeName + : Identifier + ; + +typeParameterModifier + : annotation + ; + +literal + : IntegerLiteral + | FloatingPointLiteral + | BooleanLiteral + | CharacterLiteral + | StringLiteral + | NullLiteral + ; + +type + : primitiveType + | referenceType + ; + +primitiveType + : (annotation)* numericType + | (annotation)* BOOLEAN + ; + +numericType + : integralType + | floatingPointType + ; + +integralType + : BYTE + | SHORT + | INT + | LONG + | CHAR + ; + +floatingPointType + : FLOAT + | DOUBLE + ; + +referenceType + : classOrInterfaceType + | typeVariable + | arrayType + ; + +classOrInterfaceType + : classType + | interfaceType + ; + +classType + : (annotation)* Identifier (typeArguments)? + | classType DOT (annotation)* Identifier (typeArguments)? + ; + +interfaceType + : classType + ; + +typeVariable + : (annotation)* Identifier + ; + +arrayType + : primitiveType dims + | classOrInterfaceType dims + | typeVariable dims + ; + +dims + : (annotation)* L_BRACKET R_BRACKET ((annotation)* L_BRACKET R_BRACKET)* + ; + +typeParameter + : (typeParameterModifier)* Identifier (typeBound)? + ; + +typeBound + : EXTENDS typeVariable + | EXTENDS classOrInterfaceType (additionalBound)* + ; + +additionalBound + : B_AND interfaceType + ; + +typeArguments + : LT typeArgumentList GT + ; + +typeArgumentList + : typeArgument (COMMA typeArgument)* + ; + +typeArgument + : referenceType + | wildcard + ; + +wildcard + : (annotation)* QUES (wildcardBounds)? + ; + +wildcardBounds + : EXTENDS referenceType + | SUPER referenceType + ; + +compilationUnit + : (packageDeclaration)? (importDeclaration)* (typeDeclaration)* + ; + +packageDeclaration + : (packageModifier)* PACKAGE Identifier (DOT Identifier)* SEMI + ; + +packageModifier + : annotation + ; + +importDeclaration + : singleTypeImportDeclaration + | typeImportOnDemandDeclaration + | singleStaticImportDeclaration + | staticImportOnDemandDeclaration + ; + +singleTypeImportDeclaration + : IMPORT typeName SEMI + ; + +typeImportOnDemandDeclaration + : IMPORT packageOrTypeName DOT MULT SEMI + ; + +singleStaticImportDeclaration + : IMPORT STATIC typeName DOT Identifier SEMI + ; + +staticImportOnDemandDeclaration + : IMPORT STATIC typeName DOT MULT SEMI + ; + +typeDeclaration + : classDeclaration + | interfaceDeclaration + | SEMI + ; + +classDeclaration + : normalClassDeclaration + | enumDeclaration + ; + +normalClassDeclaration + : (classModifier)* CLASS Identifier (typeParameters)? (superclass)? (superinterfaces)? classBody + ; + +classModifier + : annotation + | PUBLIC + | PROTECTED + | PRIVATE + | ABSTRACT + | STATIC + | FINAL + | STRICTFP + ; + +typeParameters + : LT typeParameterList GT + ; + +typeParameterList + : typeParameter (COMMA typeParameter)* + ; + +superclass + : EXTENDS classType + ; + +superinterfaces + : IMPLEMENTS interfaceTypeList + ; + +interfaceTypeList + : interfaceType (COMMA interfaceType)* + ; + +classBody + : L_CURLY (classBodyDeclaration)* R_CURLY + ; + +classBodyDeclaration + : classMemberDeclaration + | instanceInitializer + | staticInitializer + | constructorDeclaration + ; + +classMemberDeclaration + : fieldDeclaration + | methodDeclaration + | classDeclaration + | interfaceDeclaration + | SEMI + ; + +fieldDeclaration + : (fieldModifier)* unannType variableDeclaratorList SEMI + ; + +fieldModifier + : annotation + | PUBLIC + | PROTECTED + | PRIVATE + | STATIC + | FINAL + | TRANSIENT + | VOLATILE + ; + +variableDeclaratorList + : variableDeclarator (COMMA variableDeclarator)* + ; + +variableDeclarator + : variableDeclaratorId (ASSIGN variableInitializer)? + ; + +variableDeclaratorId + : Identifier (dims)? + ; + +variableInitializer + : expression + | arrayInitializer + ; + +unannType + : unannPrimitiveType + | unannReferenceType + ; + +unannPrimitiveType + : numericType + | BOOLEAN + ; + +unannReferenceType + : unannClassOrInterfaceType + | unannTypeVariable + | unannArrayType + ; + +unannClassOrInterfaceType + : unannClassType + | unannInterfaceType + ; + +unannClassType + : Identifier (typeArguments)? + | unannClassType DOT (annotation)* Identifier (typeArguments)? + ; + +unannInterfaceType + : unannClassType + ; + +unannTypeVariable + : Identifier + ; + +unannArrayType + : unannPrimitiveType dims + | unannClassOrInterfaceType dims + | unannTypeVariable dims + ; + +methodDeclaration + : (methodModifier)* methodHeader methodBody + ; + +methodModifier + : annotation + | PUBLIC + | PROTECTED + | PRIVATE + | ABSTRACT + | STATIC + | FINAL + | SYNCHRONIZED + | NATIVE + | STRICTFP + ; + +methodHeader + : result methodDeclarator (thro)? + | typeParameters (annotation)* result methodDeclarator (thro)? + ; + +result + : unannType + | VOID + ; + +methodDeclarator + : Identifier L_PARENS (formalParameterList)? R_PARENS (dims)? + ; + +formalParameterList + : formalParameters COMMA lastFormalParameter + | lastFormalParameter + ; + +formalParameters + : formalParameter (COMMA formalParameter)* + | receiverParameter (COMMA formalParameter)* + ; + +formalParameter + : (variableModifier)* unannType variableDeclaratorId + ; + +variableModifier + : annotation + | FINAL + ; + +lastFormalParameter + : (variableModifier)* unannType (annotation)* ELLIPSES variableDeclaratorId + | formalParameter + ; + +receiverParameter + : (annotation)* unannType (Identifier DOT)? THIS + ; + +thro + : THROWS exceptionTypeList + ; + +exceptionTypeList + : exceptionType (COMMA exceptionType)* + ; + +exceptionType + : classType + | typeVariable + ; + +methodBody + : block + | SEMI + ; + +instanceInitializer + : block + ; + +staticInitializer + : STATIC block + ; + +constructorDeclaration + : (constructorModifier)* constructorDeclarator (thro)? constructorBody + ; + +constructorModifier + : annotation + | PUBLIC + | PROTECTED + | PRIVATE + ; + +constructorDeclarator + : (typeParameters)? simpleTypeName L_PARENS (formalParameterList)? R_PARENS + ; + +constructorBody + : L_CURLY (explicitConstructorInvocation)? (blockStatements)? R_CURLY + ; + +explicitConstructorInvocation + : (typeArguments)? THIS L_PARENS (argumentList)? R_PARENS SEMI + | (typeArguments)? SUPER L_PARENS (argumentList)? R_PARENS SEMI + | expressionName DOT (typeArguments)? SUPER L_PARENS (argumentList)? R_PARENS SEMI + | primary DOT (typeArguments)? SUPER L_PARENS (argumentList)? R_PARENS SEMI + ; + +enumDeclaration + : (classModifier)* ENUM Identifier (superinterfaces)? enumBody + ; + +enumBody + : L_CURLY (enumConstantList)? (COMMA)? (enumBodyDeclarations)? R_CURLY + ; + +enumConstantList + : enumConstant (COMMA enumConstant)* + ; + +enumConstant + : (enumConstantModifier)* Identifier (L_PARENS (argumentList)? R_PARENS)? (classBody)? + ; + +enumConstantModifier + : annotation + ; + +enumBodyDeclarations + : SEMI (classBodyDeclaration)* + ; + +interfaceDeclaration + : normalInterfaceDeclaration + | annotationTypeDeclaration + ; + +normalInterfaceDeclaration + : (interfaceModifier)* INTERFACE Identifier (typeParameters)? (extendsInterfaces)? interfaceBody + ; + +interfaceModifier + : annotation + | PUBLIC + | PROTECTED + | PRIVATE + | ABSTRACT + | STATIC + | STRICTFP + ; + +extendsInterfaces + : EXTENDS interfaceTypeList + ; + +interfaceBody + : L_CURLY (interfaceMemberDeclaration)* R_CURLY + ; + +interfaceMemberDeclaration + : constantDeclaration + | interfaceMethodDeclaration + | classDeclaration + | interfaceDeclaration + | SEMI + ; + +constantDeclaration + : (constantModifier)* unannType variableDeclaratorList SEMI + ; + +constantModifier + : annotation + | PUBLIC + | STATIC + | FINAL + ; + +interfaceMethodDeclaration + : (interfaceMethodModifier)* methodHeader methodBody + ; + +interfaceMethodModifier + : annotation + | PUBLIC + | ABSTRACT + | DEFAULT + | STATIC + | STRICTFP + ; + +annotationTypeDeclaration + : (interfaceModifier)* AT INTERFACE Identifier annotationTypeBody + ; + +annotationTypeBody + : L_CURLY (annotationTypeMemberDeclaration)* R_CURLY + ; + +annotationTypeMemberDeclaration + : annotationTypeElementDeclaration + | constantDeclaration + | classDeclaration + | interfaceDeclaration + | SEMI + ; + +annotationTypeElementDeclaration + : (annotationTypeElementModifier)* unannType Identifier L_PARENS R_PARENS (dims)? (defaultValue)? SEMI + ; + +annotationTypeElementModifier + : annotation + | PUBLIC + | ABSTRACT + ; + +defaultValue + : DEFAULT elementValue + ; + +annotation + : normalAnnotation + | markerAnnotation + | singleElementAnnotation + ; + +normalAnnotation + : AT typeName L_PARENS (elementValuePairList)? R_PARENS + ; + +elementValuePairList + : elementValuePair (COMMA elementValuePair)* + ; + +elementValuePair + : Identifier ASSIGN elementValue + ; + +elementValue + : conditionalExpression + | elementValueArrayInitializer + | annotation + ; + +elementValueArrayInitializer + : L_CURLY (elementValueList)? (COMMA)? R_CURLY + ; + +elementValueList + : elementValue (COMMA elementValue)* + ; + +markerAnnotation + : AT typeName + ; + +singleElementAnnotation + : AT typeName L_PARENS elementValue R_PARENS + ; + +arrayInitializer + : L_CURLY (variableInitializerList)? (COMMA)? R_CURLY + ; + +variableInitializerList + : variableInitializer (COMMA variableInitializer)* + ; + +block + : L_CURLY (blockStatements)? R_CURLY + ; + +blockStatements + : blockStatement (blockStatement)* + ; + +blockStatement + : localVariableDeclarationStatement + | classDeclaration + | statement + ; + +localVariableDeclarationStatement + : localVariableDeclaration SEMI + ; + +localVariableDeclaration + : (variableModifier)* unannType variableDeclaratorList + ; + +statement + : statementWithoutTrailingSubstatement + | labeledStatement + | ifThenStatement + | ifThenElseStatement + | whileStatement + | forStatement + ; + +statementNoShortIf + : statementWithoutTrailingSubstatement + | labeledStatementNoShortIf + | ifThenElseStatementNoShortIf + | whileStatementNoShortIf + | forStatementNoShortIf + ; + +statementWithoutTrailingSubstatement + : block + | emptyStatement + | expressionStatement + | assertStatement + | switchStatement + | doStatement + | breakStatement + | continueStatement + | returnStatement + | synchronizedStatement + | throwStatement + | tryStatement + ; + +emptyStatement + : SEMI + ; + +labeledStatement + : Identifier COLON statement + ; + +labeledStatementNoShortIf + : Identifier COLON statementNoShortIf + ; + +expressionStatement + : statementExpression SEMI + ; + +statementExpression + : assignment + | preIncrementExpression + | preDecrementExpression + | postfixExpression INCREMENT + | postfixExpression DECREMENT + | methodInvocation + | classInstanceCreationExpression + ; + +ifThenStatement + : IF L_PARENS expression R_PARENS statement + ; + +ifThenElseStatement + : IF L_PARENS expression R_PARENS statementNoShortIf ELSE statement + ; + +ifThenElseStatementNoShortIf + : IF L_PARENS expression R_PARENS statementNoShortIf ELSE statementNoShortIf + ; + +assertStatement + : ASSERT expression SEMI + | ASSERT expression COLON expression SEMI + ; + +switchStatement + : SWITCH L_PARENS expression R_PARENS switchBlock + ; + +switchBlock + : L_CURLY (switchBlockStatementGroup)* (switchLabel)* R_CURLY + ; + +switchBlockStatementGroup + : switchLabels blockStatements + ; + +switchLabels + : switchLabel (switchLabel)* + ; + +switchLabel + : CASE constantExpression COLON + | CASE enumConstantName COLON + | DEFAULT COLON + ; + +enumConstantName + : Identifier + ; + +whileStatement + : WHILE L_PARENS expression R_PARENS statement + ; + +whileStatementNoShortIf + : WHILE L_PARENS expression R_PARENS statementNoShortIf + ; + +doStatement + : DO statement WHILE L_PARENS expression R_PARENS SEMI + ; + +forStatement + : basicForStatement + | enhancedForStatement + ; + +forStatementNoShortIf + : basicForStatementNoShortIf + | enhancedForStatementNoShortIf + ; + +basicForStatement + : FOR L_PARENS (forInit)? SEMI (expression)? SEMI (forUpdate)? R_PARENS statement + ; + +basicForStatementNoShortIf + : FOR L_PARENS (forInit)? SEMI (expression)? SEMI (forUpdate)? R_PARENS statementNoShortIf + ; + +forInit + : statementExpressionList + | localVariableDeclaration + ; + +forUpdate + : statementExpressionList + ; + +statementExpressionList + : statementExpression (COMMA statementExpression)* + ; + +enhancedForStatement + : FOR L_PARENS (variableModifier)* unannType variableDeclaratorId COLON expression R_PARENS statement + ; + +enhancedForStatementNoShortIf + : FOR L_PARENS (variableModifier)* unannType variableDeclaratorId COLON expression R_PARENS statementNoShortIf + ; + +breakStatement + : BREAK (Identifier)? SEMI + ; + +continueStatement + : CONTINUE (Identifier)? SEMI + ; + +returnStatement + : RETURN (expression)? SEMI + ; + +throwStatement + : THROW expression SEMI + ; + +synchronizedStatement + : SYNCHRONIZED L_PARENS expression R_PARENS block + ; + +tryStatement + : TRY block catches + | TRY block (catches)? finall + | tryWithResourcesStatement + ; + +catches + : catchClause (catchClause)* + ; + +catchClause + : CATCH L_PARENS catchFormalParameter R_PARENS block + ; + +catchFormalParameter + : (variableModifier)* catchType variableDeclaratorId + ; + +catchType + : unannClassType (B_OR classType)* + ; + +finall + : FINALLY block + ; + +tryWithResourcesStatement + : TRY resourceSpecification block (catches)? (finall)? + ; + +resourceSpecification + : L_PARENS resourceList (SEMI)? R_PARENS + ; + +resourceList + : resource (SEMI resource)* + ; + +resource + : (variableModifier)* unannType variableDeclaratorId ASSIGN expression + ; + +primary + : primaryNoNewArray + | arrayCreationExpression + ; + +primaryNoNewArray + : literal + | typeName (L_BRACKET R_BRACKET)* DOT CLASS + | VOID DOT CLASS + | THIS + | typeName DOT THIS + | L_PARENS expression R_PARENS + | classInstanceCreationExpression + | fieldAccess + | arrayAccess + | methodInvocation + | methodReference + ; + +classInstanceCreationExpression + : NEW (typeArguments)? (annotation)* Identifier (typeArgumentsOrDiamond)? L_PARENS (argumentList)? R_PARENS (classBody)? + | expressionName DOT NEW (typeArguments)? (annotation)* Identifier (typeArgumentsOrDiamond)? L_PARENS (argumentList)? R_PARENS (classBody)? + | primary DOT NEW (typeArguments)? (annotation)* Identifier (typeArgumentsOrDiamond)? L_PARENS (argumentList)? R_PARENS (classBody)? + ; + +typeArgumentsOrDiamond + : typeArguments + | DIAMOND + ; + +fieldAccess + : primary DOT Identifier + | SUPER DOT Identifier + | typeName DOT SUPER DOT Identifier + ; + +arrayAccess + : expressionName L_BRACKET expression R_BRACKET + | primaryNoNewArray L_BRACKET expression R_BRACKET + ; + +methodInvocation + : methodName L_PARENS (argumentList)? R_PARENS + | typeName DOT (typeArguments)? Identifier L_PARENS (argumentList)? R_PARENS + | expressionName DOT (typeArguments)? Identifier L_PARENS (argumentList)? R_PARENS + | primary DOT (typeArguments)? Identifier L_PARENS (argumentList)? R_PARENS + | SUPER DOT (typeArguments)? Identifier L_PARENS (argumentList)? R_PARENS + | typeName DOT SUPER DOT (typeArguments)? Identifier L_PARENS (argumentList)? R_PARENS + ; + +argumentList + : expression (COMMA expression)* + ; + +methodReference + : expressionName METHOD_REF (typeArguments)? Identifier + | referenceType METHOD_REF (typeArguments)? Identifier + | primary METHOD_REF (typeArguments)? Identifier + | SUPER METHOD_REF (typeArguments)? Identifier + | typeName DOT SUPER METHOD_REF (typeArguments)? Identifier + | classType METHOD_REF (typeArguments)? NEW + | arrayType METHOD_REF NEW + ; + +arrayCreationExpression + : NEW primitiveType dimExprs (dims)? + | NEW classOrInterfaceType dimExprs (dims)? + | NEW primitiveType dims arrayInitializer + | NEW classOrInterfaceType dims arrayInitializer + ; + +dimExprs + : dimExpr (dimExpr)* + ; + +dimExpr + : (annotation)* L_BRACKET expression R_BRACKET + ; + +constantExpression + : expression + ; + +expression + : lambdaExpression + | assignmentExpression + ; + +lambdaExpression + : lambdaParameters ARROW lambdaBody + ; + +lambdaParameters + : Identifier + | L_PARENS (formalParameterList)? R_PARENS + | L_PARENS inferredFormalParameterList R_PARENS + ; + +inferredFormalParameterList + : Identifier (COMMA Identifier)* + ; + +lambdaBody + : expression + | block + ; + +assignmentExpression + : conditionalExpression + | assignment + ; + +assignment + : leftHandSide assignmentOperator expression + ; + +leftHandSide + : expressionName + | fieldAccess + | arrayAccess + ; + +assignmentOperator + : ASSIGN + | MULT_ASSIGN + | DIV_ASSIGN + | MOD_ASSIGN + | PLUS_ASSIGN + | MINUS_ASSIGN + | L_SHIFT_ASSIGN + | R_SHIFT_ASSIGN + | UR_SHIFT_ASSIGN + | AND_ASSIGN + | XOR_ASSIGN + | OR_ASSIGN + ; + +conditionalExpression + : conditionalOrExpression + | conditionalOrExpression QUES expression COLON conditionalExpression + ; + +conditionalOrExpression + : conditionalAndExpression + | conditionalOrExpression L_OR conditionalAndExpression + ; + +conditionalAndExpression + : inclusiveOrExpression + | conditionalAndExpression L_AND inclusiveOrExpression + ; + +inclusiveOrExpression + : exclusiveOrExpression + | inclusiveOrExpression B_OR exclusiveOrExpression + ; + +exclusiveOrExpression + : andExpression + | exclusiveOrExpression XOR andExpression + ; + +andExpression + : equalityExpression + | andExpression B_AND equalityExpression + ; + +equalityExpression + : relationalExpression + | equalityExpression EQ relationalExpression + | equalityExpression NEQ relationalExpression + ; + +relationalExpression + : shiftExpression + | relationalExpression LT shiftExpression + | relationalExpression GT shiftExpression + | relationalExpression LE shiftExpression + | relationalExpression GE shiftExpression + | relationalExpression INSTANCEOF referenceType + ; + +shiftExpression + : additiveExpression + | shiftExpression L_SHIFT additiveExpression + | shiftExpression GT GT additiveExpression + | shiftExpression GT GT GT additiveExpression + ; + +additiveExpression + : multiplicativeExpression + | additiveExpression PLUS multiplicativeExpression + | additiveExpression MINUS multiplicativeExpression + ; + +multiplicativeExpression + : unaryExpression + | multiplicativeExpression MULT unaryExpression + | multiplicativeExpression DIV unaryExpression + | multiplicativeExpression MOD unaryExpression + ; + +unaryExpression + : preIncrementExpression + | preDecrementExpression + | PLUS unaryExpression + | MINUS unaryExpression + | unaryExpressionNotPlusMinus + ; + +preIncrementExpression + : INCREMENT unaryExpression + ; + +preDecrementExpression + : DECREMENT unaryExpression + ; + +unaryExpressionNotPlusMinus + : postfixExpression + | TILD unaryExpression + | BANG unaryExpression + | castExpression + ; + +postfixExpression + : primary + | expressionName + | postfixExpression INCREMENT + | postfixExpression DECREMENT + ; + +castExpression + : L_PARENS primitiveType R_PARENS unaryExpression + | L_PARENS referenceType (additionalBound)* R_PARENS unaryExpressionNotPlusMinus + | L_PARENS referenceType (additionalBound)* R_PARENS lambdaExpression + ; \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/My.recore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/My.recore new file mode 100644 index 00000000..15914ec5 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/My.recore @@ -0,0 +1,28 @@ +import Instance : 'Instance.requirements'; +import Requirements : 'Requirements.ecore'; +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package BookStorePackage : bookStore = 'http:///com.ibm.dynamic.example.bookstore.ecore' +{ + class A + { + attribute owner : String[+] { !unique }; + operation method() : String; + property ref2 : BookStorePackage::pack::B; + } + package pack : p = 'bla bla' + { + class B + { + attribute instance : Requirements::Priority[?]; + annotation 'ferhat' + { + reference BookStorePackage::A::owner; + reference Instance::B; + reference Instance::@requirements.0::@parts.1; + reference Instance::@requirements.0::@parts.0; + reference Instance::@relationships.0; + } + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/OperationTest.recore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/OperationTest.recore new file mode 100644 index 00000000..a769d8fc --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/OperationTest.recore @@ -0,0 +1,39 @@ +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package TestPackage : tp = 'www.testpackage.org' +{ + private class TestClass extends SuperClass, UberClass : 'TCname' + { + private static operation testOp(nullable testParam : Boolean[?] { ordered }, testParam2 : Ecore.EChar[+] { ordered }) : String[?] throws SubTestInterface, SubTestClass { !unique ordered } + { + requires testPre ("Hey!") : lone testOp; + body testPre : testOp; + ensures testPost ("Hey!") : one testOp; + } + operation testOp1() : TestDataType[?] { ordered }; + operation testOp2() : TestDataType[1] { ordered }; + operation testOp3() : TestDataType[*] { ordered }; + operation testOp4() : TestDataType[+] { ordered }; + operation testOp5() : TestDataType[3..6] { ordered }; + operation testVoidOp() { ordered } + { + requires : lone testOp; + body testBody : testOp; + body testBody2 : testOp; + ensures testPost ("Hey!") : one testOp; + ensures testPost2 ("Hey!") : one testOp; + } + } + interface TestInterface extends SuperClass : 'TIname'; + enum TestEnum : 'TEname' { serializable }; + primitive datatype TestDataType : 'TDTname' { serializable }; + abstract class SuperClass; + abstract class UberClass; + package SubPackage : sp = 'www.sub.testpackage.org' + { + class SubTestClass; + interface SubTestInterface; + enum SubTestEnum; + datatype SubTestDataType : 'STDTname'; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Templates.ecore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Templates.ecore new file mode 100644 index 00000000..20cad202 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Templates.ecore @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + +
+
+ + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Templates.recore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Templates.recore new file mode 100644 index 00000000..6641628c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Templates.recore @@ -0,0 +1,98 @@ +model ferhat; + +import ecore : 'http://www.eclipse.org/emf/2002/Ecore'; +import tepe : + 'http://www.eclipse.org/emf/2002/Tepe'; + +package generics : gns = 'eu.modelwriter.generics' +{ + public package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' + { + public class Library + { + nullable attribute name : String; + property books#library : Book[*|1] { composes }; + property loans : Loan[*|?] { composes }; + nullable property members#library : Member[*] { composes }; + annotation 'modelwriter/Ferhat' ('key' = , 'key' = 'value', =) + { + reference Library::books; + class AnnotationClass; + property mehmet: type; + } + annotation ; + annotation ; + } + public class Book + { + operation isAvailable() : Boolean[?]; + attribute name : String[1]; + attribute copies : Integer[1]; + property library#books : Library[?]; + volatile property loans : Loan[*|1] { derived }; + } + public class Member + { + model nullable attribute name : String[1]; + property library#members : Library[?]; + volatile property loans : Loan[*|1] { derived }; /*{derivation : library.loans->select;}*/ + volatile property books : Book[*|1] { !unique derived}; /*{derivation : loans->collect;}*/ + } + class Loan + { + property book : Book[1]; + property member : Member[1] = 'Ferhat Erata'; + annotation + { + reference tutorial::Organization::Librarian::orgOpp; + } + nullable attribute date : ecore::EDate[?]; + } + protected package enterprise : ent = 'http://www.eclipse.org/mdt/ocl/oclinecore/enterprise' + { + public interface Employee { + attribute name : String[1] = 'Ferhat Erata'; + model attribute copies : Integer[1]; + } + datatype JavaPackage : 'java.lang.Package' { !serializable }; + enum Type { serializable } + { + type1 = 2; + literal type2; + } + } + /*invariant inv_name ("this rule is violated.") : all x: Employee | lone x.model ;*/ + annotation 'test'; + annotation ; + } + + package Iterator : itr = 'iterator'; + class Iterator; + abstract class List + { + operation add(); + operation add(element : E[1]); + operation iterator() : Iterator[?]; + } + class Iterator + { + operation next() : E[?] throws MyException ; + operation hasNext() : Boolean[1]; + } + class ArrayList extends List; + class test; + abstract class Person; + class Owner + { + property cars : ArrayList[?]; + property attr1: K; + } + interface Shape; + class Canvas + { + operation draw(shapes : List[1]) : Boolean[?]; + operation create(name : String[1]); + operation create(name: String, arg : ArrayList[?]); + } + class MyException; +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Test.g4 b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Test.g4 new file mode 100644 index 00000000..4b29bcea --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Test.g4 @@ -0,0 +1,17 @@ +grammar Test; + +model: formula* ; + +formula: + left=expression 'in' right=expression #in + | left=formula 'and' right=formula #and + ; + +expression: + left=expression '+' right=expression #union + | variable #var + ; + +variable: IDENTIFIER; + +IDENTIFIER : [a-zA-Z]; diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Test.recore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Test.recore new file mode 100644 index 00000000..92658d61 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Test.recore @@ -0,0 +1,95 @@ +import FordOtosan: 'FordOtosan.ecore'; +import extlibrary: 'extlibrary.ecore'; +import Ecore: 'http://www.eclipse.org/emf/2002/Ecore'; + +package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' +{ + public class Library + { + attribute name : String[1] + { + annotation; + derivation : library.loans->select; + annotation 'sadasdas'; + } + property books#library : Book[*] { resolve composes } + { + annotation; + annotation 'sadasdas'; + derivation : library.loans->select; + } + static property loans : Loan[*] { resolve composes }; + property members#library : Member[*] { resolve composes }; + } + class Book + { + attribute name : String[1]; + attribute copies : UnlimitedNatural[1]; + operation isAvailable(param1 : Boolean[?] { ordered }, param2 : Book[?] { ordered }) : Boolean[?] + { + body; + ensures sup ("this is a precondition") : ; + } + property library#books : Library[?] { resolve }; + volatile property loans : Loan[*] { derived resolve } {derivation : library.loans->select;} + invariant importantConstraint ("multi + lined + message") : ; + } + class Member + { + attribute name : String[1]; + operation tespOP() { ordered }; + property library#members : Library[?] { resolve }; + volatile property loans : Loan[*] { derived resolve } {derivation : library.loans->select;} + volatile property books : Book[*] { !unique derived resolve } {initial : loans->collect;} + } + class Loan + { + attribute date : Ecore::EDate[?]; + property book : tutorial::Organization::SubOrg1::sb1C[1] { resolve }; + property member : Member[1] { resolve }; + annotation + { + reference tutorial::Organization::Librarian::orgOpp; + } + } + package Organization : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization' + { + enum Type { !serializable } + { + literal asd = 0; + } + datatype JavaPackage : 'java.lang.Package' { !serializable }; + class Librarian extends extlibrary::Employee + { + operation orgOpp() : Ecore::ELong[?] { ordered }; + property workOn : tutorial::Organization::SubOrg2::sb2C[?] { ordered resolve }; + } + class Ref extends tutorial::Library + { + property RefOutsideEcore : extlibrary::Item[?] { ordered resolve }; + } + package SubOrg1 : sb = 'suborg1' + { + class sb1C; + } + package SubOrg2 : sb2 = 'SubOrg2' + { + class sb2C; + } + annotation 'extAnno' + { + reference extlibrary::Item; + reference extlibrary::Item::publicationDate; + reference FordOtosan::Container::vehicle; + reference FordOtosan::Vehicle::ElectricalPowerSupplySystem::ElectricalPowerSupplySystem::electricalPowerSupplySystemPart; + } + } + annotation 'http://www.eclipse.org/emf/2002/Ecore' + ( + 'invocationDelegates' = 'http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot', + 'settingDelegates' = 'http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot', + 'validationDelegates' = 'http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot' + ); +} diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Tutorial.ecore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Tutorial.ecore new file mode 100644 index 00000000..c9aa0207 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/Tutorial.ecore @@ -0,0 +1,76 @@ + + + +
+ + +
+
+
+ + + + + + + + + +
+ + +
+ + + +
+ + + + + + + +
+ + + + + +
+ + +
+
+ + + + + +
+ + + + +
+ + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/extlibrary.ecore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/extlibrary.ecore new file mode 100644 index 00000000..1a6e74b5 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/extlibrary.ecore @@ -0,0 +1,129 @@ + + + +
+ + +
+ + + +
+ + + +
+ + + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/package.recore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/package.recore new file mode 100644 index 00000000..b95110f5 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/package.recore @@ -0,0 +1,36 @@ +import ecore : 'http://www.eclipse.org/emf/2002/Ecore' ; + +protected package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' +{ + public class Library + { + attribute name : String[1]; + property books#library : Book[*|1] { composes }; + property loans : Loan[*|1] { composes }; + property members#library : Member[*|1] { composes }; + } + public abstract class Employee { + attribute name : String[1]; + model attribute copies : Integer[1]; + } + package Enterprise0 : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/enterprise' + { + private class Car { + nullable readonly attribute name : String[1] {ordered}; + attribute copies : Integer[1]; + } + } + public package Enterprise1 : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/enterprise' + {} + package Organization1 : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization' + { + abstract interface Librarian extends Employee + { + + } + package Level2'' : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization/Level2' {} + package Level2 : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization/Level3' {} + } + package Enterprise2 : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/enterprise' + {} +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/simple.recore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/simple.recore new file mode 100644 index 00000000..7a656224 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/simple.recore @@ -0,0 +1,50 @@ +import ecore : 'http://www.eclipse.org/emf/2002/Ecore' ; + +package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' +{ + public class Library + { + attribute name : String[1]; + property books#library : Book[*|1] { composes }; + property loans : Loan[*|1] { composes }; + property members#library : Member[*|1] { composes }; + } + public class Book + { + operation isAvailable() : Boolean[?]; + attribute name : String[1]; + attribute copies : Integer[1]; + property library#books : Library[?]; + volatile property loans : Loan[*|1] { derived }; + } + public class Member + { + model attribute name : String[1]; + property library#members : Library[?]; + volatile property loans : Loan[*|1] { derived }; + volatile property books : Book[*|1] { !unique derived}; + } + class Loan + { + property book : Book[1]; + property member : Member[1]; + attribute date : ecore::EDate[?]; + } + package Organization : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization' + { + abstract class Librarian extends Employee + { + property workOn : tutorial::Library[1]; + } + abstract class Employee extends tutorial::Library + { + property RefOutsideEcore : extlib::Item[+]; + } + datatype JavaPackage : 'java.lang.Package' { !serializable }; + enum Type { serializable } + { + type1 = 2; + literal type2; + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/test.recore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/test.recore new file mode 100644 index 00000000..c5bfb61e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/test.recore @@ -0,0 +1,85 @@ +import FordOtosan: 'FordOtosan.ecore'; +import extlibrary: 'extlibrary.ecore'; +import Ecore: 'http://www.eclipse.org/emf/2002/Ecore'; + +package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' +{ + public class Library + { + attribute name : String[1] + { + annotation; + } + property books#library : Book[*] { resolve composes } + { + annotation 'sadasdas'; + } + static property loans : Loan[*] { resolve composes }; + property members#library : Member[*] { resolve composes }; + } + class Book + { + attribute name : String[1]; + attribute copies : UnlimitedNatural[1]; + operation isAvailable(param1 : Boolean[?] { ordered }, param2 : Book[?] { ordered }) : Boolean[?] + { + body; + ensures sup ("this is a precondition") : ; + } + property library#books : Library[?] { resolve }; + volatile property loans : Loan[*] { derived resolve } {derivation : library.loans->select;} + invariant importantConstraint ("multi + lined + message") : ; + } + class Member + { + attribute name : String[1]; + operation tespOP() { ordered }; + property library#members : Library[?] { resolve }; + volatile property loans : Loan[*] { derived resolve } {derivation : library.loans->select;} + volatile property books : Book[*] { !unique derived resolve } {derivation : loans->collect;} + } + class Loan + { + attribute date : Ecore.EDate[?]; + property book : tutorial.Organization.SubOrg1.sb1C[1] { resolve }; + property member : Member[1] { resolve }; + annotation + { + reference tutorial.Organization.Librarian->orgOpp; + } + } + package Organization : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization' + { + enum Type { serializable } + { + literal asd = 0; + } + datatype JavaPackage : 'java.lang.Package' { serializable }; + class Librarian extends extlibrary.Employee + { + operation orgOpp() : Ecore.ELong[?] { ordered }; + property workOn : tutorial.Organization.SubOrg2.sb2C[?] { ordered resolve }; + + class Ref extends Library + { + property RefOutsideEcore : extlibrary.Item[?] { ordered resolve }; + } + package SubOrg1 : sb = 'suborg1' + { + class sb1C; + } + package SubOrg2 : sb2 = 'SubOrg2' + { + class sb2C; + } + annotation 'extAnno' + { + reference extlibrary.Item; + reference extlibrary.Item.publicationDate; + reference FordOtosan.Container.vehicle; + reference FordOtosan.Vehicle.ElectricalPowerSupplySystem.ElectricalPowerSupplySystem.electricalPowerSupplySystemPart; + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/test1.g4 b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/test1.g4 new file mode 100644 index 00000000..61e0cc7f --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/test1.g4 @@ -0,0 +1,12 @@ +grammar test1; + +example: + left=integer '*' right=integer #integerExample + | left=string '+' right=string #stringExample + ; + +integer: IDENTIFIER; +string: INTEGER; + +STRING: [a-zA-Z]; +INTEGER: [a-zA-Z]; \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/test1.recore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/test1.recore new file mode 100644 index 00000000..159b7fb8 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/test1.recore @@ -0,0 +1,78 @@ +import extlibrary : 'MF4SEA_ML/extlibrary.ecore'; +import extlibrary : 'extlibrary.ecore'; +import Ecore : 'http://www.eclipse.org/emf/2002/Ecore'; + +package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' +{ + public abstract class Library + { + attribute name : String; + property books#library : Book[*] { composes } + { + annotation 'sadasdas'; + } + static property loans : Loan[*] { composes }; + property members#library : Member[*] { composes }; + } + class Book + { + attribute name : String; + attribute copies : UnlimitedNatural; + operation isAvailable(param1 : Boolean[?], param2 : Book[?]) : Boolean[?] + { + body; + ensures sup ("this is a precondition"); + } + property library#books : Library[?]; + volatile property loans : Loan[*] { derived }; + invariant importantConstraint ("asdasd"); + } + class Member + { + attribute name : String; + operation tespOP(); + property library#members : Library[?]; + volatile property loans : Loan[*] { derived }; + volatile property books : Book[*] { !unique derived }; + } + class Loan + { + attribute date : Ecore::EDate[?]; + property book : tutorial::Organization::SubOrg1::sb1C; + property member : Member; + annotation + { + reference tutorial::Organization::Librarian::orgOpp; + } + } + package Organization : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization' + { + enum Type { !serializable } + { + literal asd = 0; + } + datatype JavaPackage : 'java.lang.Package' { !serializable }; + class Librarian extends extlibrary::Employee + { + operation orgOpp() : Ecore::ELong[?]; + property workOn : tutorial::Organization::SubOrg2::sb2C[?]; + } + class Ref extends tutorial::Library + { + property RefOutsideEcore : extlibrary::Item[?]; + } + package SubOrg1 : sb = 'suborg1' + { + class sb1C; + } + package SubOrg2 : sb2 = 'SubOrg2' + { + class sb2C; + } + annotation 'extAnno' + { + reference extlibrary::Item; + reference extlibrary::Item::publicationDate; + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/test2.g4 b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/test2.g4 new file mode 100644 index 00000000..da72925d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/test2.g4 @@ -0,0 +1,14 @@ +grammar test2; + +example: + left=example '*' right=example #integerExample + | left=inner '+' right=inner #stringExample + ; + +inner: integer | string; + +integer: INTEGER; +string: STRING; + +STRING: [a-zA-Z]; +INTEGER: [a-zA-Z]; \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/tutorial.recore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/tutorial.recore new file mode 100644 index 00000000..cd6c744a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/tutorial.recore @@ -0,0 +1,44 @@ +import ecore : 'http://www.eclipse.org/emf/2002/Ecore' ; + +package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' +{ + class Library + { + attribute name : String[1]; + property books#library : Book[*|1] { composes }; + property loans : Loan[*|1] { composes }; + property members#library : Member[*|1] { composes }; + } + class Book + { + operation isAvailable() : Boolean[?]; + attribute name : String[1]; + attribute copies : Integer[1]; + property library#books : Library[?]; + property loans : Loan[*|1] { derived }; + } + class Member extends Employee + { + attribute name : String[1]; + property library#members : Library[?]; + volatile property loans : Loan[*|1] { derived }; + volatile property books : Book[*|1] { !unique derived }; + } + class Loan + { + property book : Book[1]; + property member : Member[1]; + attribute date : Book[?]; + } + package Organization : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization' + { + abstract class Librarian extends Employee + { + property workOn : tutorial.Library[1]; + } + abstract class Employee + { + property books : tutorial.Book[+]; + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/tutorialExtended.recore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/tutorialExtended.recore new file mode 100644 index 00000000..7ef63d6d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/tutorialExtended.recore @@ -0,0 +1,110 @@ +import ecore : 'http://www.eclipse.org/emf/2002/Ecore' ; import extlib : 'extlibrary.ecore#/' ; + +package tutorial : tut = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial' +{ + package Organization : org = 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial/organization' + { + abstract class Librarian extends Employee + { + property workOn : tutorial::Library[1]; + } + abstract class Employee extends tutorial::Library + { + property RefOutsideEcore : extlib::Item[+]; + } + datatype JavaPackage : 'java.lang.Package' { serializable }; + enum Type + { + annotation 'MODELWRITER' + ( + 'constraint' = 'formula...', + 'constraints' = ' ' + ); + literal type1; + literal type2; + } + } + abstract class Library { interface } + { + attribute name : String[1] { id }; + property books#library : Book[*] { composes }; + property loans : Loan[*] { composes }; + property members#library : Member[*] { composes }; + } + class Book + { + annotation 'MODELWRITER' + ( + 'constraint' = 'formula...', + 'constraints' = '' + ) + { + annotation 'MODELWRITERs' + ( + 'constraint' = 'formula. -> ..', + 'constraints' = 'formula...' + ) + { + property books : Book[*] { composes }; + attribute name : String[1] { id }; + enum Test { serializable } + { + literal entry1; + } + operation isAvailable() : Boolean[?] + { + annotation 'modelwriter.eu' + ( + 'constraint' = 'formula...' + ); + body: expr; + } + datatype JavaPackage : 'java.lang.Package' { serializable }; + reference extlib::Book; + reference extlib::BookOnTape::author; + reference extlib::Addressable; + } + reference extlib::Book; + reference extlib::BookOnTape::author; + reference extlib::Addressable; + } + annotation; + operation isAvailable() : Boolean[?] + { + precondition:; + precondition test:; + body test: expr; + body: expr; + } + attribute name : String[1]; + attribute copies : Integer[1]; + property library#books : Library[?]; + property loans : Loan[*] { derived volatile } + { + initial: A.r; + } + invariant SufficientCopies: all x: A | one x.r; + } + class Member + { + attribute name : String[1]; + property library#members : Library[?]; + property loans : Loan[*] { derived volatile } + { + initial: x.r; + derivation: x.r; + } + property books : Book[*] { !unique derived volatile } + { + initial: x.r; + } + invariant AtMostTwoLoans: all x: A | one x.r; + invariant UniqueLoans: all x: A | one x.r; + } + class Loan + { + property book : Book[1]; + property member : Member[1]; + attribute date : ecore::EDate[?]; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/yunus.recore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/yunus.recore new file mode 100644 index 00000000..6a06d6e1 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/AlloyInECore/yunus.recore @@ -0,0 +1,108 @@ +model asd; + +import asdasd : 'http://www.eclipse.org/emf/2002/Ecore'; + +package extlibrary : extlib = 'http:///org/eclipse/emf/examples/library/extlibrary.ecore/1.0.0' +{ + public class Book extends CirculatingItem + { + private attribute title : asdasd::EString[?]; + public attribute pages : asdasd::EInt[?] = '100'; + attribute category : BookCategory[?] { unsettable }; + property author#books : Writer; + } + class Library extends Addressable + { + private attribute name : asdasd::EString[?]; + transient volatle attribute people : asdasd::EFeatureMapEntry[*] { ordered } + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'kind' = 'group' + ); + } + transient volatile property writers : Writer[*] { ordered derived !resolve composes } + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'group' = '#people' + ); + } + transient volatile property employees : Employee[*] { ordered derived !resolve composes } + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'group' = '#people' + ); + } + transient volatile property borrowers : Borrower[*] { ordered derived !resolve composes } + { + annotation 'http:///org/eclipse/emf/ecore/util/ExtendedMetaData' + ( + 'group' = '#people' + ); + } + property stock : Item[*] { !resolve composes }; + transient property books : Book[*] { derived }; + property branches#parentBranch : Library[*] { ordered composes }; + property parentBranch#branches : Library[?]; + } + class Writer extends Person + { + transient volatile attribute name : asdasd::EString[?]; + property books#author : Book[*] { ordered }; + } + enum BookCategory + { + literal Mystery = 0; + literal ScienceFiction = 1; + literal Biography = 2; + } + abstract class Item + { + attribute publicationDate : asdasd::EDate[?]; + } + interface Lendable + { + attribute copies : asdasd::EInt; + property borrowers#borrowed : Borrower[*]; + } + abstract class CirculatingItem extends Item, Lendable; + abstract class Periodical extends Item + { + attribute title : asdasd::EString[?]; + attribute issuesPerYear : asdasd::EInt; + } + abstract class AudioVisualItem extends CirculatingItem + { + attribute title : asdasd::EString[?]; + attribute minutesLength : asdasd::EInt; + attribute damaged : asdasd::EBoolean[?]; + } + class BookOnTape extends AudioVisualItem + { + property reader : Person[?]; + property author : Writer[?]; + } + class VideoCassette extends AudioVisualItem + { + property cast : Person[*] { ordered }; + } + class Borrower extends Person + { + property borrowed#borrowers : Lendable[*] { ordered }; + } + class Person extends Addressable + { + attribute firstName : asdasd::EString; + attribute lastName : asdasd::EString; + } + class Employee extends Person + { + property manager : Employee[?]; + } + interface Addressable + { + attribute address : asdasd::EString[?]; + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/GenericTypeAnalysis.g4 b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/GenericTypeAnalysis.g4 new file mode 100644 index 00000000..69d9c806 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/GenericTypeAnalysis.g4 @@ -0,0 +1,84 @@ +grammar GenericTypeAnalysis; + +classifierTemplateSignature: + '<' ownedTypeParameters+= classifierTypeParameter (',' ownedTypeParameters+= classifierTypeParameter)* '>' +; + +classifierTypeParameter: + name= unrestrictedName ('extends' ownedEBounds+= classifierGenericBoundType ('&' ownedEBounds+= classifierGenericBoundType)*)? +; + +classifierGenericBoundType: + // classifierref, generictypeclassref, not primitive, not typeparameterref, not wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. + // wildcardref's extend should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, not wildcardref. + ownedPathName= pathName ('<' ownedETypeArguments= templateBinding '>')? +; + +operationTemplateSignature: + '<' ownedTypeParameters+= operationTypeParameter (',' ownedTypeParameters+= operationTypeParameter)* '>' +; + +operationTypeParameter: + name= unrestrictedName ('extends' ownedEBounds+= operationGenericBoundType ('&' ownedEBounds+= operationGenericBoundType)*)? +; + +operationGenericBoundType: + // classifierref, generictypeclassref, not primitive, , not wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. + // wildcardref's extend should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, not wildcardref. + ownedPathName= pathName ('<' ownedETypeArguments= templateBinding '>')? +; + + + +classSuperTypeRef: + // should be: + // classifierref, generictypeclassref, not primitive, not typeparameterref, not wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. +; + + +attributeTypeRef: + // should be: + // enumRef, datatypeRef, not classref, generictypeclassref, primitive, typeparameterref, not wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. +; + +referenceTypeRef: + // should be: + // not enumRef, not datatypeRef, classref, generictypeclassref, not primitive, typeparameterref, not wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. +; + +operationReturnTypeRef: + // should be: + // classifierref, generictypeclassref, primitive, typeparameterref, not wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. +; + +operationParameterTypeRef: + // should be: + // classifierref, generictypeclassref, primitive, typeparameterref, not wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. +; + +operationExceptionTypeRef: + // should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, not wildcardref. + // genericTypeClassref's templateBinding should be: + // classifierref, generictypeclassref, not primitive, typeparameterref, wildcardref. +; \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/Types/Filesystem.kodkod b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/Types/Filesystem.kodkod new file mode 100644 index 00000000..52ea874e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/Types/Filesystem.kodkod @@ -0,0 +1,14 @@ +universe {d0, d1, d2, d3, f0, f1, f2, f3} + +relations { + File : [ {(f0), (f1), (f2)} ] + Dir : [ {(d0), (d1), (d2)} ] + Root: Dir [{(d0)}] + contents: Dir -> File [{[d0, d1], [d0, f0], [d0, f1], [d0, f2]}, {[d0, d1], [d0, f0], [d0, f1], [d0, f2], [d1, d2]}] +} + +contents in Dir -> (Dir + File) +all d:Dir | not (d in d.^contents) +Root in Dir +(File + Dir) in Root.*contents + diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/Types/TypeDefinitions.kodkod b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/Types/TypeDefinitions.kodkod new file mode 100644 index 00000000..e295b878 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/Types/TypeDefinitions.kodkod @@ -0,0 +1,24 @@ +universe {d0, d1, d2, d3, f0, f1, f2, f3} + +relations { +File 1: [ {(f0), (f1), (f2), (f3)} ] +Dir 1 : [ {(d0), (d1), (d2)} ] +Root 1 : Dir [{(d0)}] --type checking : arity check must be performed +contents 2: Dir -> File.r3 [[[d0, d1], [d0, d2], [d0, f0], [d0, f1], [d0, f2] ]] --type checking : arity check must be performed +A: Root [[(a0), (a1)]] +B: [[(b1), (b2)]] +C: [[(c1), (c2)]] +r0: A one -> one B [[[d0, d1], [d0, d2], [d0, f0], [d0, f1], [d0, f2] ]] --bounds are now irrelavant +r1: A -> (B one -> C) [[[a0, b1, c1], [a0, b2, c2], [a0, b0, c1], [a0, b1, c2], [a0, b2, c1]]] --if it is defined as exact bounds, it may be checked! +r2: (A -> B) -> C [[[a0, b1, c1], [a0, b2, c2], [a0, b0, c1], [a0, b1, c2], [a0, b2, c1]]] +r3: (A -> B -> C) [[[a0, b1, c1], [a0, b2, c2], [a0, b0, c1], [a0, b1, c2], [a0, b2, c1]]] +r4: (A -> B) lone -> C [[]] --if type is defined and but not bounds, LB is set to empty set, but upper bound is set to the cartesian product defined +r5: A -> B -> C [[[d0, d1], [d0, d2], [d0, f0], [d0, f1], [d0, f2] ]] --type checking error, arity does not conform to bounds. +r6: (Alias -> Addr) + (Group -> (Addr + Alias + Group)) [[]] --type checking error, undefined relations + +} + +contents in Dir -> (Dir + File) +all d:Dir | not (d in d.^contents) +Root in Dir +(File + Dir) in Root.*contents diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/Types/program.als b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/Types/program.als new file mode 100644 index 00000000..a6d8cda6 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/Types/program.als @@ -0,0 +1,109 @@ +model appendixA/addressBook2 + +sig Addr, Name { } + +sig Book { + addr: Name -> (Name + Addr) + } + +/* + +---------------- +x: m e + +---------------- +r: A m -> n B +all a: A | n a.r +all b: B | m r.b + +---------------- +r: A -> (B m -> n C) +all a: A | a.r in B m -> n C + +---------------- +r: (A m -> n B) -> C +all c: C | r.c in A m -> n B +---------------- + +*/ + +--addr: Book -> (Name lone -> Addr) +pred show1 { + all b: Book | b.addr in Name lone -> Addr +} + +//r: (A m -> n B) -> C +pred show2 { + all b: Book | b.addr in Name lone -> Addr +} + +run show1 for 3 + +/* +A +B:A +C:A +D:A + +no (B & C) +no (B + C) & D +*/ + +/* +A +B +rel: A -> one B +--> +all a: A | one a.rel && a.rel in B +*/ + +/* +A +B +rel: A -> set B + +all a: A | one a.rel && a.rel in B +--> +all a: A | a.rel in B +rel.univ in A +*/ + +/* +A +B +C +rel: A -> B -> C +--> +all a: A | a.rel in B -> C +rel.univ.univ in A +*/ + +/* +A +B +C +D +rel: A -> B -> C -> D +--> +all a: A | a.rel in B -> C -> D +rel.univ.univ.univ in A +*/ + +/* +A +B +C +rel: A -> (B lone -> one C) +--> +all a: A | a.rel in B -> C && + (all b: B | one b.(a.rel) && b.(a.rel) in C) && + (all c: C | lone (a.rel).c && (a.rel).c in B) + +rel.univ.univ in A + +*/ + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/java/Java.g4 b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/java/Java.g4 new file mode 100644 index 00000000..2d804a4a --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/java/Java.g4 @@ -0,0 +1,1016 @@ +/* + [The "BSD licence"] + Copyright (c) 2013 Terence Parr, Sam Harwell + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** A Java 1.7 grammar for ANTLR v4 derived from ANTLR v3 Java grammar. + * Uses ANTLR v4's left-recursive expression notation. + * It parses ECJ, Netbeans, JDK etc... + * + * Sam Harwell cleaned this up significantly and updated to 1.7! + * + * You can test with + * + * $ antlr4 Java.g4 + * $ javac *.java + * $ grun Java compilationUnit *.java + */ +grammar Java; + +// starting point for parsing a java file +compilationUnit + : packageDeclaration? importDeclaration* typeDeclaration* EOF + ; + +packageDeclaration + : annotation* 'package' qualifiedName ';' + ; + +importDeclaration + : 'import' 'static'? qualifiedName ('.' '*')? ';' + ; + +typeDeclaration + : classOrInterfaceModifier* classDeclaration + | classOrInterfaceModifier* enumDeclaration + | classOrInterfaceModifier* interfaceDeclaration + | classOrInterfaceModifier* annotationTypeDeclaration + | ';' + ; + +modifier + : classOrInterfaceModifier + | ( 'native' + | 'synchronized' + | 'transient' + | 'volatile' + ) + ; + +classOrInterfaceModifier + : annotation // class or interface + | ( 'public' // class or interface + | 'protected' // class or interface + | 'private' // class or interface + | 'static' // class or interface + | 'abstract' // class or interface + | 'final' // class only -- does not apply to interfaces + | 'strictfp' // class or interface + ) + ; + +variableModifier + : 'final' + | annotation + ; + +classDeclaration + : 'class' Identifier typeParameters? + ('extends' typeType)? + ('implements' typeList)? + classBody + ; + +typeParameters + : '<' typeParameter (',' typeParameter)* '>' + ; + +typeParameter + : Identifier ('extends' typeBound)? + ; + +typeBound + : typeType ('&' typeType)* + ; + +enumDeclaration + : ENUM Identifier ('implements' typeList)? + '{' enumConstants? ','? enumBodyDeclarations? '}' + ; + +enumConstants + : enumConstant (',' enumConstant)* + ; + +enumConstant + : annotation* Identifier arguments? classBody? + ; + +enumBodyDeclarations + : ';' classBodyDeclaration* + ; + +interfaceDeclaration + : 'interface' Identifier typeParameters? ('extends' typeList)? interfaceBody + ; + +typeList + : typeType (',' typeType)* + ; + +classBody + : '{' classBodyDeclaration* '}' + ; + +interfaceBody + : '{' interfaceBodyDeclaration* '}' + ; + +classBodyDeclaration + : ';' + | 'static'? block + | modifier* memberDeclaration + ; + +memberDeclaration + : methodDeclaration + | genericMethodDeclaration + | fieldDeclaration + | constructorDeclaration + | genericConstructorDeclaration + | interfaceDeclaration + | annotationTypeDeclaration + | classDeclaration + | enumDeclaration + ; + +/* We use rule this even for void methods which cannot have [] after parameters. + This simplifies grammar and we can consider void to be a type, which + renders the [] matching as a context-sensitive issue or a semantic check + for invalid return type after parsing. + */ +methodDeclaration + : (typeType|'void') Identifier formalParameters ('[' ']')* + ('throws' qualifiedNameList)? + ( methodBody + | ';' + ) + ; + +genericMethodDeclaration + : typeParameters methodDeclaration + ; + +constructorDeclaration + : Identifier formalParameters ('throws' qualifiedNameList)? + constructorBody + ; + +genericConstructorDeclaration + : typeParameters constructorDeclaration + ; + +fieldDeclaration + : typeType variableDeclarators ';' + ; + +interfaceBodyDeclaration + : modifier* interfaceMemberDeclaration + | ';' + ; + +interfaceMemberDeclaration + : constDeclaration + | interfaceMethodDeclaration + | genericInterfaceMethodDeclaration + | interfaceDeclaration + | annotationTypeDeclaration + | classDeclaration + | enumDeclaration + ; + +constDeclaration + : typeType constantDeclarator (',' constantDeclarator)* ';' + ; + +constantDeclarator + : Identifier ('[' ']')* '=' variableInitializer + ; + +// see matching of [] comment in methodDeclaratorRest +interfaceMethodDeclaration + : (typeType|'void') Identifier formalParameters ('[' ']')* + ('throws' qualifiedNameList)? + ';' + ; + +genericInterfaceMethodDeclaration + : typeParameters interfaceMethodDeclaration + ; + +variableDeclarators + : variableDeclarator (',' variableDeclarator)* + ; + +variableDeclarator + : variableDeclaratorId ('=' variableInitializer)? + ; + +variableDeclaratorId + : Identifier ('[' ']')* + ; + +variableInitializer + : arrayInitializer + | expression + ; + +arrayInitializer + : '{' (variableInitializer (',' variableInitializer)* (',')? )? '}' + ; + +enumConstantName + : Identifier + ; + +typeType + : classOrInterfaceType ('[' ']')* + | primitiveType ('[' ']')* + ; + +classOrInterfaceType + : Identifier typeArguments? ('.' Identifier typeArguments? )* + ; + +primitiveType + : 'boolean' + | 'char' + | 'byte' + | 'short' + | 'int' + | 'long' + | 'float' + | 'double' + ; + +typeArguments + : '<' typeArgument (',' typeArgument)* '>' + ; + +typeArgument + : typeType + | '?' (('extends' | 'super') typeType)? + ; + +qualifiedNameList + : qualifiedName (',' qualifiedName)* + ; + +formalParameters + : '(' formalParameterList? ')' + ; + +formalParameterList + : formalParameter (',' formalParameter)* (',' lastFormalParameter)? + | lastFormalParameter + ; + +formalParameter + : variableModifier* typeType variableDeclaratorId + ; + +lastFormalParameter + : variableModifier* typeType '...' variableDeclaratorId + ; + +methodBody + : block + ; + +constructorBody + : block + ; + +qualifiedName + : Identifier ('.' Identifier)* + ; + +literal + : IntegerLiteral + | FloatingPointLiteral + | CharacterLiteral + | StringLiteral + | BooleanLiteral + | 'null' + ; + +// ANNOTATIONS + +annotation + : '@' annotationName ( '(' ( elementValuePairs | elementValue )? ')' )? + ; + +annotationName : qualifiedName ; + +elementValuePairs + : elementValuePair (',' elementValuePair)* + ; + +elementValuePair + : Identifier '=' elementValue + ; + +elementValue + : expression + | annotation + | elementValueArrayInitializer + ; + +elementValueArrayInitializer + : '{' (elementValue (',' elementValue)*)? (',')? '}' + ; + +annotationTypeDeclaration + : '@' 'interface' Identifier annotationTypeBody + ; + +annotationTypeBody + : '{' (annotationTypeElementDeclaration)* '}' + ; + +annotationTypeElementDeclaration + : modifier* annotationTypeElementRest + | ';' // this is not allowed by the grammar, but apparently allowed by the actual compiler + ; + +annotationTypeElementRest + : typeType annotationMethodOrConstantRest ';' + | classDeclaration ';'? + | interfaceDeclaration ';'? + | enumDeclaration ';'? + | annotationTypeDeclaration ';'? + ; + +annotationMethodOrConstantRest + : annotationMethodRest + | annotationConstantRest + ; + +annotationMethodRest + : Identifier '(' ')' defaultValue? + ; + +annotationConstantRest + : variableDeclarators + ; + +defaultValue + : 'default' elementValue + ; + +// STATEMENTS / BLOCKS + +block + : '{' blockStatement* '}' + ; + +blockStatement + : localVariableDeclarationStatement + | statement + | typeDeclaration + ; + +localVariableDeclarationStatement + : localVariableDeclaration ';' + ; + +localVariableDeclaration + : variableModifier* typeType variableDeclarators + ; + +statement + : block + | ASSERT expression (':' expression)? ';' + | 'if' parExpression statement ('else' statement)? + | 'for' '(' forControl ')' statement + | 'while' parExpression statement + | 'do' statement 'while' parExpression ';' + | 'try' block (catchClause+ finallyBlock? | finallyBlock) + | 'try' resourceSpecification block catchClause* finallyBlock? + | 'switch' parExpression '{' switchBlockStatementGroup* switchLabel* '}' + | 'synchronized' parExpression block + | 'return' expression? ';' + | 'throw' expression ';' + | 'break' Identifier? ';' + | 'continue' Identifier? ';' + | ';' + | statementExpression ';' + | Identifier ':' statement + ; + +catchClause + : 'catch' '(' variableModifier* catchType Identifier ')' block + ; + +catchType + : qualifiedName ('|' qualifiedName)* + ; + +finallyBlock + : 'finally' block + ; + +resourceSpecification + : '(' resources ';'? ')' + ; + +resources + : resource (';' resource)* + ; + +resource + : variableModifier* classOrInterfaceType variableDeclaratorId '=' expression + ; + +/** Matches cases then statements, both of which are mandatory. + * To handle empty cases at the end, we add switchLabel* to statement. + */ +switchBlockStatementGroup + : switchLabel+ blockStatement+ + ; + +switchLabel + : 'case' constantExpression ':' + | 'case' enumConstantName ':' + | 'default' ':' + ; + +forControl + : enhancedForControl + | forInit? ';' expression? ';' forUpdate? + ; + +forInit + : localVariableDeclaration + | expressionList + ; + +enhancedForControl + : variableModifier* typeType variableDeclaratorId ':' expression + ; + +forUpdate + : expressionList + ; + +// EXPRESSIONS + +parExpression + : '(' expression ')' + ; + +expressionList + : expression (',' expression)* + ; + +statementExpression + : expression + ; + +constantExpression + : expression + ; + +expression + : primary + | expression '.' Identifier + | expression '.' 'this' + | expression '.' 'new' nonWildcardTypeArguments? innerCreator + | expression '.' 'super' superSuffix + | expression '.' explicitGenericInvocation + | expression '[' expression ']' + | expression '(' expressionList? ')' + | 'new' creator + | '(' typeType ')' expression + | expression ('++' | '--') + | ('+'|'-'|'++'|'--') expression + | ('~'|'!') expression + | expression ('*'|'/'|'%') expression + | expression ('+'|'-') expression + | expression ('<' '<' | '>' '>' '>' | '>' '>') expression + | expression ('<=' | '>=' | '>' | '<') expression + | expression 'instanceof' typeType + | expression ('==' | '!=') expression + | expression '&' expression + | expression '^' expression + | expression '|' expression + | expression '&&' expression + | expression '||' expression + | expression '?' expression ':' expression + | expression + ( '=' + | '+=' + | '-=' + | '*=' + | '/=' + | '&=' + | '|=' + | '^=' + | '>>=' + | '>>>=' + | '<<=' + | '%=' + ) + expression + ; + +primary + : '(' expression ')' + | 'this' + | 'super' + | literal + | Identifier + | typeType '.' 'class' + | 'void' '.' 'class' + | nonWildcardTypeArguments (explicitGenericInvocationSuffix | 'this' arguments) + ; + +creator + : nonWildcardTypeArguments createdName classCreatorRest + | createdName (arrayCreatorRest | classCreatorRest) + ; + +createdName + : Identifier typeArgumentsOrDiamond? ('.' Identifier typeArgumentsOrDiamond?)* + | primitiveType + ; + +innerCreator + : Identifier nonWildcardTypeArgumentsOrDiamond? classCreatorRest + ; + +arrayCreatorRest + : '[' + ( ']' ('[' ']')* arrayInitializer + | expression ']' ('[' expression ']')* ('[' ']')* + ) + ; + +classCreatorRest + : arguments classBody? + ; + +explicitGenericInvocation + : nonWildcardTypeArguments explicitGenericInvocationSuffix + ; + +nonWildcardTypeArguments + : '<' typeList '>' + ; + +typeArgumentsOrDiamond + : '<' '>' + | typeArguments + ; + +nonWildcardTypeArgumentsOrDiamond + : '<' '>' + | nonWildcardTypeArguments + ; + +superSuffix + : arguments + | '.' Identifier arguments? + ; + +explicitGenericInvocationSuffix + : 'super' superSuffix + | Identifier arguments + ; + +arguments + : '(' expressionList? ')' + ; + +// LEXER + +// §3.9 Keywords + +ABSTRACT : 'abstract'; +ASSERT : 'assert'; +BOOLEAN : 'boolean'; +BREAK : 'break'; +BYTE : 'byte'; +CASE : 'case'; +CATCH : 'catch'; +CHAR : 'char'; +CLASS : 'class'; +CONST : 'const'; +CONTINUE : 'continue'; +DEFAULT : 'default'; +DO : 'do'; +DOUBLE : 'double'; +ELSE : 'else'; +ENUM : 'enum'; +EXTENDS : 'extends'; +FINAL : 'final'; +FINALLY : 'finally'; +FLOAT : 'float'; +FOR : 'for'; +IF : 'if'; +GOTO : 'goto'; +IMPLEMENTS : 'implements'; +IMPORT : 'import'; +INSTANCEOF : 'instanceof'; +INT : 'int'; +INTERFACE : 'interface'; +LONG : 'long'; +NATIVE : 'native'; +NEW : 'new'; +PACKAGE : 'package'; +PRIVATE : 'private'; +PROTECTED : 'protected'; +PUBLIC : 'public'; +RETURN : 'return'; +SHORT : 'short'; +STATIC : 'static'; +STRICTFP : 'strictfp'; +SUPER : 'super'; +SWITCH : 'switch'; +SYNCHRONIZED : 'synchronized'; +THIS : 'this'; +THROW : 'throw'; +THROWS : 'throws'; +TRANSIENT : 'transient'; +TRY : 'try'; +VOID : 'void'; +VOLATILE : 'volatile'; +WHILE : 'while'; + +// §3.10.1 Integer Literals + +IntegerLiteral + : DecimalIntegerLiteral + | HexIntegerLiteral + | OctalIntegerLiteral + | BinaryIntegerLiteral + ; + +fragment +DecimalIntegerLiteral + : DecimalNumeral IntegerTypeSuffix? + ; + +fragment +HexIntegerLiteral + : HexNumeral IntegerTypeSuffix? + ; + +fragment +OctalIntegerLiteral + : OctalNumeral IntegerTypeSuffix? + ; + +fragment +BinaryIntegerLiteral + : BinaryNumeral IntegerTypeSuffix? + ; + +fragment +IntegerTypeSuffix + : [lL] + ; + +fragment +DecimalNumeral + : '0' + | NonZeroDigit (Digits? | Underscores Digits) + ; + +fragment +Digits + : Digit (DigitOrUnderscore* Digit)? + ; + +fragment +Digit + : '0' + | NonZeroDigit + ; + +fragment +NonZeroDigit + : [1-9] + ; + +fragment +DigitOrUnderscore + : Digit + | '_' + ; + +fragment +Underscores + : '_'+ + ; + +fragment +HexNumeral + : '0' [xX] HexDigits + ; + +fragment +HexDigits + : HexDigit (HexDigitOrUnderscore* HexDigit)? + ; + +fragment +HexDigit + : [0-9a-fA-F] + ; + +fragment +HexDigitOrUnderscore + : HexDigit + | '_' + ; + +fragment +OctalNumeral + : '0' Underscores? OctalDigits + ; + +fragment +OctalDigits + : OctalDigit (OctalDigitOrUnderscore* OctalDigit)? + ; + +fragment +OctalDigit + : [0-7] + ; + +fragment +OctalDigitOrUnderscore + : OctalDigit + | '_' + ; + +fragment +BinaryNumeral + : '0' [bB] BinaryDigits + ; + +fragment +BinaryDigits + : BinaryDigit (BinaryDigitOrUnderscore* BinaryDigit)? + ; + +fragment +BinaryDigit + : [01] + ; + +fragment +BinaryDigitOrUnderscore + : BinaryDigit + | '_' + ; + +// §3.10.2 Floating-Point Literals + +FloatingPointLiteral + : DecimalFloatingPointLiteral + | HexadecimalFloatingPointLiteral + ; + +fragment +DecimalFloatingPointLiteral + : Digits '.' Digits? ExponentPart? FloatTypeSuffix? + | '.' Digits ExponentPart? FloatTypeSuffix? + | Digits ExponentPart FloatTypeSuffix? + | Digits FloatTypeSuffix + ; + +fragment +ExponentPart + : ExponentIndicator SignedInteger + ; + +fragment +ExponentIndicator + : [eE] + ; + +fragment +SignedInteger + : Sign? Digits + ; + +fragment +Sign + : [+-] + ; + +fragment +FloatTypeSuffix + : [fFdD] + ; + +fragment +HexadecimalFloatingPointLiteral + : HexSignificand BinaryExponent FloatTypeSuffix? + ; + +fragment +HexSignificand + : HexNumeral '.'? + | '0' [xX] HexDigits? '.' HexDigits + ; + +fragment +BinaryExponent + : BinaryExponentIndicator SignedInteger + ; + +fragment +BinaryExponentIndicator + : [pP] + ; + +// §3.10.3 Boolean Literals + +BooleanLiteral + : 'true' + | 'false' + ; + +// §3.10.4 Character Literals + +CharacterLiteral + : '\'' SingleCharacter '\'' + | '\'' EscapeSequence '\'' + ; + +fragment +SingleCharacter + : ~['\\] + ; + +// §3.10.5 String Literals + +StringLiteral + : '"' StringCharacters? '"' + ; + +fragment +StringCharacters + : StringCharacter+ + ; + +fragment +StringCharacter + : ~["\\] + | EscapeSequence + ; + +// §3.10.6 Escape Sequences for Character and String Literals + +fragment +EscapeSequence + : '\\' [btnfr"'\\] + | OctalEscape + | UnicodeEscape + ; + +fragment +OctalEscape + : '\\' OctalDigit + | '\\' OctalDigit OctalDigit + | '\\' ZeroToThree OctalDigit OctalDigit + ; + +fragment +UnicodeEscape + : '\\' 'u' HexDigit HexDigit HexDigit HexDigit + ; + +fragment +ZeroToThree + : [0-3] + ; + +// §3.10.7 The Null Literal + +NullLiteral + : 'null' + ; + +// §3.11 Separators + +LPAREN : '('; +RPAREN : ')'; +LBRACE : '{'; +RBRACE : '}'; +LBRACK : '['; +RBRACK : ']'; +SEMI : ';'; +COMMA : ','; +DOT : '.'; + +// §3.12 Operators + +ASSIGN : '='; +GT : '>'; +LT : '<'; +BANG : '!'; +TILDE : '~'; +QUESTION : '?'; +COLON : ':'; +EQUAL : '=='; +LE : '<='; +GE : '>='; +NOTEQUAL : '!='; +AND : '&&'; +OR : '||'; +INC : '++'; +DEC : '--'; +ADD : '+'; +SUB : '-'; +MUL : '*'; +DIV : '/'; +BITAND : '&'; +BITOR : '|'; +CARET : '^'; +MOD : '%'; + +ADD_ASSIGN : '+='; +SUB_ASSIGN : '-='; +MUL_ASSIGN : '*='; +DIV_ASSIGN : '/='; +AND_ASSIGN : '&='; +OR_ASSIGN : '|='; +XOR_ASSIGN : '^='; +MOD_ASSIGN : '%='; +LSHIFT_ASSIGN : '<<='; +RSHIFT_ASSIGN : '>>='; +URSHIFT_ASSIGN : '>>>='; + +// §3.8 Identifiers (must appear after all keywords in the grammar) + +Identifier + : JavaLetter JavaLetterOrDigit* + ; + +fragment +JavaLetter + : [a-zA-Z$_] // these are the "java letters" below 0x7F + | // covers all characters above 0x7F which are not a surrogate + ~[\u0000-\u007F\uD800-\uDBFF] + | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF + [\uD800-\uDBFF] [\uDC00-\uDFFF] + ; + +fragment +JavaLetterOrDigit + : [a-zA-Z0-9$_] // these are the "java letters or digits" below 0x7F + | // covers all characters above 0x7F which are not a surrogate + ~[\u0000-\u007F\uD800-\uDBFF] + | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF + [\uD800-\uDBFF] [\uDC00-\uDFFF] + ; + +// +// Additional symbols not defined in the lexical specification +// + +AT : '@'; +ELLIPSIS : '...'; + +// +// Whitespace and comments +// + +WS : [ \t\r\n\u000C]+ -> skip + ; + +COMMENT + : '/*' .*? '*/' -> channel(HIDDEN) + ; + +LINE_COMMENT + : '//' ~[\r\n]* -> channel(HIDDEN) + ; diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/java/Java8.g4 b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/java/Java8.g4 new file mode 100644 index 00000000..f63f01a5 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/java/Java8.g4 @@ -0,0 +1,1779 @@ +/* + * [The "BSD license"] + * Copyright (c) 2014 Terence Parr + * Copyright (c) 2014 Sam Harwell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * A Java 8 grammar for ANTLR 4 derived from the Java Language Specification + * chapter 19. + * + * NOTE: This grammar results in a generated parser that is much slower + * than the Java 7 grammar in the grammars-v4/java directory. This + * one is, however, extremely close to the spec. + * + * You can test with + * + * $ antlr4 Java8.g4 + * $ javac *.java + * $ grun Java8 compilationUnit *.java + * + * Or, +~/antlr/code/grammars-v4/java8 $ java Test . +/Users/parrt/antlr/code/grammars-v4/java8/./Java8BaseListener.java +/Users/parrt/antlr/code/grammars-v4/java8/./Java8Lexer.java +/Users/parrt/antlr/code/grammars-v4/java8/./Java8Listener.java +/Users/parrt/antlr/code/grammars-v4/java8/./Java8Parser.java +/Users/parrt/antlr/code/grammars-v4/java8/./Test.java +Total lexer+parser time 30844ms. + */ +grammar Java8; + +/* + * Productions from §3 (Lexical Structure) + */ + +literal + : IntegerLiteral + | FloatingPointLiteral + | BooleanLiteral + | CharacterLiteral + | StringLiteral + | NullLiteral + ; + +/* + * Productions from §4 (Types, Values, and Variables) + */ + +type + : primitiveType + | referenceType + ; + +primitiveType + : annotation* numericType + | annotation* 'boolean' + ; + +numericType + : integralType + | floatingPointType + ; + +integralType + : 'byte' + | 'short' + | 'int' + | 'long' + | 'char' + ; + +floatingPointType + : 'float' + | 'double' + ; + +referenceType + : classOrInterfaceType + | typeVariable + | arrayType + ; + +classOrInterfaceType + : ( classType_lfno_classOrInterfaceType + | interfaceType_lfno_classOrInterfaceType + ) + ( classType_lf_classOrInterfaceType + | interfaceType_lf_classOrInterfaceType + )* + ; + +classType + : annotation* Identifier typeArguments? + | classOrInterfaceType '.' annotation* Identifier typeArguments? + ; + +classType_lf_classOrInterfaceType + : '.' annotation* Identifier typeArguments? + ; + +classType_lfno_classOrInterfaceType + : annotation* Identifier typeArguments? + ; + +interfaceType + : classType + ; + +interfaceType_lf_classOrInterfaceType + : classType_lf_classOrInterfaceType + ; + +interfaceType_lfno_classOrInterfaceType + : classType_lfno_classOrInterfaceType + ; + +typeVariable + : annotation* Identifier + ; + +arrayType + : primitiveType dims + | classOrInterfaceType dims + | typeVariable dims + ; + +dims + : annotation* '[' ']' (annotation* '[' ']')* + ; + +typeParameter + : typeParameterModifier* Identifier typeBound? + ; + +typeParameterModifier + : annotation + ; + +typeBound + : 'extends' typeVariable + | 'extends' classOrInterfaceType additionalBound* + ; + +additionalBound + : '&' interfaceType + ; + +typeArguments + : '<' typeArgumentList '>' + ; + +typeArgumentList + : typeArgument (',' typeArgument)* + ; + +typeArgument + : referenceType + | wildcard + ; + +wildcard + : annotation* '?' wildcardBounds? + ; + +wildcardBounds + : 'extends' referenceType + | 'super' referenceType + ; + +/* + * Productions from §6 (Names) + */ + +packageName + : Identifier + | packageName '.' Identifier + ; + +typeName + : Identifier + | packageOrTypeName '.' Identifier + ; + +packageOrTypeName + : Identifier + | packageOrTypeName '.' Identifier + ; + +expressionName + : Identifier + | ambiguousName '.' Identifier + ; + +methodName + : Identifier + ; + +ambiguousName + : Identifier + | ambiguousName '.' Identifier + ; + +/* + * Productions from §7 (Packages) + */ + +compilationUnit + : packageDeclaration? importDeclaration* typeDeclaration* EOF + ; + +packageDeclaration + : packageModifier* 'package' Identifier ('.' Identifier)* ';' + ; + +packageModifier + : annotation + ; + +importDeclaration + : singleTypeImportDeclaration + | typeImportOnDemandDeclaration + | singleStaticImportDeclaration + | staticImportOnDemandDeclaration + ; + +singleTypeImportDeclaration + : 'import' typeName ';' + ; + +typeImportOnDemandDeclaration + : 'import' packageOrTypeName '.' '*' ';' + ; + +singleStaticImportDeclaration + : 'import' 'static' typeName '.' Identifier ';' + ; + +staticImportOnDemandDeclaration + : 'import' 'static' typeName '.' '*' ';' + ; + +typeDeclaration + : classDeclaration + | interfaceDeclaration + | ';' + ; + +/* + * Productions from §8 (Classes) + */ + +classDeclaration + : normalClassDeclaration + | enumDeclaration + ; + +normalClassDeclaration + : classModifier* 'class' Identifier typeParameters? superclass? superinterfaces? classBody + ; + +classModifier + : annotation + | 'public' + | 'protected' + | 'private' + | 'abstract' + | 'static' + | 'final' + | 'strictfp' + ; + +typeParameters + : '<' typeParameterList '>' + ; + +typeParameterList + : typeParameter (',' typeParameter)* + ; + +superclass + : 'extends' classType + ; + +superinterfaces + : 'implements' interfaceTypeList + ; + +interfaceTypeList + : interfaceType (',' interfaceType)* + ; + +classBody + : '{' classBodyDeclaration* '}' + ; + +classBodyDeclaration + : classMemberDeclaration + | instanceInitializer + | staticInitializer + | constructorDeclaration + ; + +classMemberDeclaration + : fieldDeclaration + | methodDeclaration + | classDeclaration + | interfaceDeclaration + | ';' + ; + +fieldDeclaration + : fieldModifier* unannType variableDeclaratorList ';' + ; + +fieldModifier + : annotation + | 'public' + | 'protected' + | 'private' + | 'static' + | 'final' + | 'transient' + | 'volatile' + ; + +variableDeclaratorList + : variableDeclarator (',' variableDeclarator)* + ; + +variableDeclarator + : variableDeclaratorId ('=' variableInitializer)? + ; + +variableDeclaratorId + : Identifier dims? + ; + +variableInitializer + : expression + | arrayInitializer + ; + +unannType + : unannPrimitiveType + | unannReferenceType + ; + +unannPrimitiveType + : numericType + | 'boolean' + ; + +unannReferenceType + : unannClassOrInterfaceType + | unannTypeVariable + | unannArrayType + ; + +unannClassOrInterfaceType + : ( unannClassType_lfno_unannClassOrInterfaceType + | unannInterfaceType_lfno_unannClassOrInterfaceType + ) + ( unannClassType_lf_unannClassOrInterfaceType + | unannInterfaceType_lf_unannClassOrInterfaceType + )* + ; + +unannClassType + : Identifier typeArguments? + | unannClassOrInterfaceType '.' annotation* Identifier typeArguments? + ; + +unannClassType_lf_unannClassOrInterfaceType + : '.' annotation* Identifier typeArguments? + ; + +unannClassType_lfno_unannClassOrInterfaceType + : Identifier typeArguments? + ; + +unannInterfaceType + : unannClassType + ; + +unannInterfaceType_lf_unannClassOrInterfaceType + : unannClassType_lf_unannClassOrInterfaceType + ; + +unannInterfaceType_lfno_unannClassOrInterfaceType + : unannClassType_lfno_unannClassOrInterfaceType + ; + +unannTypeVariable + : Identifier + ; + +unannArrayType + : unannPrimitiveType dims + | unannClassOrInterfaceType dims + | unannTypeVariable dims + ; + +methodDeclaration + : methodModifier* methodHeader methodBody + ; + +methodModifier + : annotation + | 'public' + | 'protected' + | 'private' + | 'abstract' + | 'static' + | 'final' + | 'synchronized' + | 'native' + | 'strictfp' + ; + +methodHeader + : result methodDeclarator throws_? + | typeParameters annotation* result methodDeclarator throws_? + ; + +result + : unannType + | 'void' + ; + +methodDeclarator + : Identifier '(' formalParameterList? ')' dims? + ; + +formalParameterList + : formalParameters ',' lastFormalParameter + | lastFormalParameter + ; + +formalParameters + : formalParameter (',' formalParameter)* + | receiverParameter (',' formalParameter)* + ; + +formalParameter + : variableModifier* unannType variableDeclaratorId + ; + +variableModifier + : annotation + | 'final' + ; + +lastFormalParameter + : variableModifier* unannType annotation* '...' variableDeclaratorId + | formalParameter + ; + +receiverParameter + : annotation* unannType (Identifier '.')? 'this' + ; + +throws_ + : 'throws' exceptionTypeList + ; + +exceptionTypeList + : exceptionType (',' exceptionType)* + ; + +exceptionType + : classType + | typeVariable + ; + +methodBody + : block + | ';' + ; + +instanceInitializer + : block + ; + +staticInitializer + : 'static' block + ; + +constructorDeclaration + : constructorModifier* constructorDeclarator throws_? constructorBody + ; + +constructorModifier + : annotation + | 'public' + | 'protected' + | 'private' + ; + +constructorDeclarator + : typeParameters? simpleTypeName '(' formalParameterList? ')' + ; + +simpleTypeName + : Identifier + ; + +constructorBody + : '{' explicitConstructorInvocation? blockStatements? '}' + ; + +explicitConstructorInvocation + : typeArguments? 'this' '(' argumentList? ')' ';' + | typeArguments? 'super' '(' argumentList? ')' ';' + | expressionName '.' typeArguments? 'super' '(' argumentList? ')' ';' + | primary '.' typeArguments? 'super' '(' argumentList? ')' ';' + ; + +enumDeclaration + : classModifier* 'enum' Identifier superinterfaces? enumBody + ; + +enumBody + : '{' enumConstantList? ','? enumBodyDeclarations? '}' + ; + +enumConstantList + : enumConstant (',' enumConstant)* + ; + +enumConstant + : enumConstantModifier* Identifier ('(' argumentList? ')')? classBody? + ; + +enumConstantModifier + : annotation + ; + +enumBodyDeclarations + : ';' classBodyDeclaration* + ; + +/* + * Productions from §9 (Interfaces) + */ + +interfaceDeclaration + : normalInterfaceDeclaration + | annotationTypeDeclaration + ; + +normalInterfaceDeclaration + : interfaceModifier* 'interface' Identifier typeParameters? extendsInterfaces? interfaceBody + ; + +interfaceModifier + : annotation + | 'public' + | 'protected' + | 'private' + | 'abstract' + | 'static' + | 'strictfp' + ; + +extendsInterfaces + : 'extends' interfaceTypeList + ; + +interfaceBody + : '{' interfaceMemberDeclaration* '}' + ; + +interfaceMemberDeclaration + : constantDeclaration + | interfaceMethodDeclaration + | classDeclaration + | interfaceDeclaration + | ';' + ; + +constantDeclaration + : constantModifier* unannType variableDeclaratorList ';' + ; + +constantModifier + : annotation + | 'public' + | 'static' + | 'final' + ; + +interfaceMethodDeclaration + : interfaceMethodModifier* methodHeader methodBody + ; + +interfaceMethodModifier + : annotation + | 'public' + | 'abstract' + | 'default' + | 'static' + | 'strictfp' + ; + +annotationTypeDeclaration + : interfaceModifier* '@' 'interface' Identifier annotationTypeBody + ; + +annotationTypeBody + : '{' annotationTypeMemberDeclaration* '}' + ; + +annotationTypeMemberDeclaration + : annotationTypeElementDeclaration + | constantDeclaration + | classDeclaration + | interfaceDeclaration + | ';' + ; + +annotationTypeElementDeclaration + : annotationTypeElementModifier* unannType Identifier '(' ')' dims? defaultValue? ';' + ; + +annotationTypeElementModifier + : annotation + | 'public' + | 'abstract' + ; + +defaultValue + : 'default' elementValue + ; + +annotation + : normalAnnotation + | markerAnnotation + | singleElementAnnotation + ; + +normalAnnotation + : '@' typeName '(' elementValuePairList? ')' + ; + +elementValuePairList + : elementValuePair (',' elementValuePair)* + ; + +elementValuePair + : Identifier '=' elementValue + ; + +elementValue + : conditionalExpression + | elementValueArrayInitializer + | annotation + ; + +elementValueArrayInitializer + : '{' elementValueList? ','? '}' + ; + +elementValueList + : elementValue (',' elementValue)* + ; + +markerAnnotation + : '@' typeName + ; + +singleElementAnnotation + : '@' typeName '(' elementValue ')' + ; + +/* + * Productions from §10 (Arrays) + */ + +arrayInitializer + : '{' variableInitializerList? ','? '}' + ; + +variableInitializerList + : variableInitializer (',' variableInitializer)* + ; + +/* + * Productions from §14 (Blocks and Statements) + */ + +block + : '{' blockStatements? '}' + ; + +blockStatements + : blockStatement blockStatement* + ; + +blockStatement + : localVariableDeclarationStatement + | classDeclaration + | statement + ; + +localVariableDeclarationStatement + : localVariableDeclaration ';' + ; + +localVariableDeclaration + : variableModifier* unannType variableDeclaratorList + ; + +statement + : statementWithoutTrailingSubstatement + | labeledStatement + | ifThenStatement + | ifThenElseStatement + | whileStatement + | forStatement + ; + +statementNoShortIf + : statementWithoutTrailingSubstatement + | labeledStatementNoShortIf + | ifThenElseStatementNoShortIf + | whileStatementNoShortIf + | forStatementNoShortIf + ; + +statementWithoutTrailingSubstatement + : block + | emptyStatement + | expressionStatement + | assertStatement + | switchStatement + | doStatement + | breakStatement + | continueStatement + | returnStatement + | synchronizedStatement + | throwStatement + | tryStatement + ; + +emptyStatement + : ';' + ; + +labeledStatement + : Identifier ':' statement + ; + +labeledStatementNoShortIf + : Identifier ':' statementNoShortIf + ; + +expressionStatement + : statementExpression ';' + ; + +statementExpression + : assignment + | preIncrementExpression + | preDecrementExpression + | postIncrementExpression + | postDecrementExpression + | methodInvocation + | classInstanceCreationExpression + ; + +ifThenStatement + : 'if' '(' expression ')' statement + ; + +ifThenElseStatement + : 'if' '(' expression ')' statementNoShortIf 'else' statement + ; + +ifThenElseStatementNoShortIf + : 'if' '(' expression ')' statementNoShortIf 'else' statementNoShortIf + ; + +assertStatement + : 'assert' expression ';' + | 'assert' expression ':' expression ';' + ; + +switchStatement + : 'switch' '(' expression ')' switchBlock + ; + +switchBlock + : '{' switchBlockStatementGroup* switchLabel* '}' + ; + +switchBlockStatementGroup + : switchLabels blockStatements + ; + +switchLabels + : switchLabel switchLabel* + ; + +switchLabel + : 'case' constantExpression ':' + | 'case' enumConstantName ':' + | 'default' ':' + ; + +enumConstantName + : Identifier + ; + +whileStatement + : 'while' '(' expression ')' statement + ; + +whileStatementNoShortIf + : 'while' '(' expression ')' statementNoShortIf + ; + +doStatement + : 'do' statement 'while' '(' expression ')' ';' + ; + +forStatement + : basicForStatement + | enhancedForStatement + ; + +forStatementNoShortIf + : basicForStatementNoShortIf + | enhancedForStatementNoShortIf + ; + +basicForStatement + : 'for' '(' forInit? ';' expression? ';' forUpdate? ')' statement + ; + +basicForStatementNoShortIf + : 'for' '(' forInit? ';' expression? ';' forUpdate? ')' statementNoShortIf + ; + +forInit + : statementExpressionList + | localVariableDeclaration + ; + +forUpdate + : statementExpressionList + ; + +statementExpressionList + : statementExpression (',' statementExpression)* + ; + +enhancedForStatement + : 'for' '(' variableModifier* unannType variableDeclaratorId ':' expression ')' statement + ; + +enhancedForStatementNoShortIf + : 'for' '(' variableModifier* unannType variableDeclaratorId ':' expression ')' statementNoShortIf + ; + +breakStatement + : 'break' Identifier? ';' + ; + +continueStatement + : 'continue' Identifier? ';' + ; + +returnStatement + : 'return' expression? ';' + ; + +throwStatement + : 'throw' expression ';' + ; + +synchronizedStatement + : 'synchronized' '(' expression ')' block + ; + +tryStatement + : 'try' block catches + | 'try' block catches? finally_ + | tryWithResourcesStatement + ; + +catches + : catchClause catchClause* + ; + +catchClause + : 'catch' '(' catchFormalParameter ')' block + ; + +catchFormalParameter + : variableModifier* catchType variableDeclaratorId + ; + +catchType + : unannClassType ('|' classType)* + ; + +finally_ + : 'finally' block + ; + +tryWithResourcesStatement + : 'try' resourceSpecification block catches? finally_? + ; + +resourceSpecification + : '(' resourceList ';'? ')' + ; + +resourceList + : resource (';' resource)* + ; + +resource + : variableModifier* unannType variableDeclaratorId '=' expression + ; + +/* + * Productions from §15 (Expressions) + */ + +primary + : ( primaryNoNewArray_lfno_primary + | arrayCreationExpression + ) + ( primaryNoNewArray_lf_primary + )* + ; + +primaryNoNewArray + : literal + | typeName ('[' ']')* '.' 'class' + | 'void' '.' 'class' + | 'this' + | typeName '.' 'this' + | '(' expression ')' + | classInstanceCreationExpression + | fieldAccess + | arrayAccess + | methodInvocation + | methodReference + ; + +primaryNoNewArray_lf_arrayAccess + : + ; + +primaryNoNewArray_lfno_arrayAccess + : literal + | typeName ('[' ']')* '.' 'class' + | 'void' '.' 'class' + | 'this' + | typeName '.' 'this' + | '(' expression ')' + | classInstanceCreationExpression + | fieldAccess + | methodInvocation + | methodReference + ; + +primaryNoNewArray_lf_primary + : classInstanceCreationExpression_lf_primary + | fieldAccess_lf_primary + | arrayAccess_lf_primary + | methodInvocation_lf_primary + | methodReference_lf_primary + ; + +primaryNoNewArray_lf_primary_lf_arrayAccess_lf_primary + : + ; + +primaryNoNewArray_lf_primary_lfno_arrayAccess_lf_primary + : classInstanceCreationExpression_lf_primary + | fieldAccess_lf_primary + | methodInvocation_lf_primary + | methodReference_lf_primary + ; + +primaryNoNewArray_lfno_primary + : literal + | typeName ('[' ']')* '.' 'class' + | unannPrimitiveType ('[' ']')* '.' 'class' + | 'void' '.' 'class' + | 'this' + | typeName '.' 'this' + | '(' expression ')' + | classInstanceCreationExpression_lfno_primary + | fieldAccess_lfno_primary + | arrayAccess_lfno_primary + | methodInvocation_lfno_primary + | methodReference_lfno_primary + ; + +primaryNoNewArray_lfno_primary_lf_arrayAccess_lfno_primary + : + ; + +primaryNoNewArray_lfno_primary_lfno_arrayAccess_lfno_primary + : literal + | typeName ('[' ']')* '.' 'class' + | unannPrimitiveType ('[' ']')* '.' 'class' + | 'void' '.' 'class' + | 'this' + | typeName '.' 'this' + | '(' expression ')' + | classInstanceCreationExpression_lfno_primary + | fieldAccess_lfno_primary + | methodInvocation_lfno_primary + | methodReference_lfno_primary + ; + +classInstanceCreationExpression + : 'new' typeArguments? annotation* Identifier ('.' annotation* Identifier)* typeArgumentsOrDiamond? '(' argumentList? ')' classBody? + | expressionName '.' 'new' typeArguments? annotation* Identifier typeArgumentsOrDiamond? '(' argumentList? ')' classBody? + | primary '.' 'new' typeArguments? annotation* Identifier typeArgumentsOrDiamond? '(' argumentList? ')' classBody? + ; + +classInstanceCreationExpression_lf_primary + : '.' 'new' typeArguments? annotation* Identifier typeArgumentsOrDiamond? '(' argumentList? ')' classBody? + ; + +classInstanceCreationExpression_lfno_primary + : 'new' typeArguments? annotation* Identifier ('.' annotation* Identifier)* typeArgumentsOrDiamond? '(' argumentList? ')' classBody? + | expressionName '.' 'new' typeArguments? annotation* Identifier typeArgumentsOrDiamond? '(' argumentList? ')' classBody? + ; + +typeArgumentsOrDiamond + : typeArguments + | '<' '>' + ; + +fieldAccess + : primary '.' Identifier + | 'super' '.' Identifier + | typeName '.' 'super' '.' Identifier + ; + +fieldAccess_lf_primary + : '.' Identifier + ; + +fieldAccess_lfno_primary + : 'super' '.' Identifier + | typeName '.' 'super' '.' Identifier + ; + +arrayAccess + : ( expressionName '[' expression ']' + | primaryNoNewArray_lfno_arrayAccess '[' expression ']' + ) + ( primaryNoNewArray_lf_arrayAccess '[' expression ']' + )* + ; + +arrayAccess_lf_primary + : ( primaryNoNewArray_lf_primary_lfno_arrayAccess_lf_primary '[' expression ']' + ) + ( primaryNoNewArray_lf_primary_lf_arrayAccess_lf_primary '[' expression ']' + )* + ; + +arrayAccess_lfno_primary + : ( expressionName '[' expression ']' + | primaryNoNewArray_lfno_primary_lfno_arrayAccess_lfno_primary '[' expression ']' + ) + ( primaryNoNewArray_lfno_primary_lf_arrayAccess_lfno_primary '[' expression ']' + )* + ; + +methodInvocation + : methodName '(' argumentList? ')' + | typeName '.' typeArguments? Identifier '(' argumentList? ')' + | expressionName '.' typeArguments? Identifier '(' argumentList? ')' + | primary '.' typeArguments? Identifier '(' argumentList? ')' + | 'super' '.' typeArguments? Identifier '(' argumentList? ')' + | typeName '.' 'super' '.' typeArguments? Identifier '(' argumentList? ')' + ; + +methodInvocation_lf_primary + : '.' typeArguments? Identifier '(' argumentList? ')' + ; + +methodInvocation_lfno_primary + : methodName '(' argumentList? ')' + | typeName '.' typeArguments? Identifier '(' argumentList? ')' + | expressionName '.' typeArguments? Identifier '(' argumentList? ')' + | 'super' '.' typeArguments? Identifier '(' argumentList? ')' + | typeName '.' 'super' '.' typeArguments? Identifier '(' argumentList? ')' + ; + +argumentList + : expression (',' expression)* + ; + +methodReference + : expressionName '::' typeArguments? Identifier + | referenceType '::' typeArguments? Identifier + | primary '::' typeArguments? Identifier + | 'super' '::' typeArguments? Identifier + | typeName '.' 'super' '::' typeArguments? Identifier + | classType '::' typeArguments? 'new' + | arrayType '::' 'new' + ; + +methodReference_lf_primary + : '::' typeArguments? Identifier + ; + +methodReference_lfno_primary + : expressionName '::' typeArguments? Identifier + | referenceType '::' typeArguments? Identifier + | 'super' '::' typeArguments? Identifier + | typeName '.' 'super' '::' typeArguments? Identifier + | classType '::' typeArguments? 'new' + | arrayType '::' 'new' + ; + +arrayCreationExpression + : 'new' primitiveType dimExprs dims? + | 'new' classOrInterfaceType dimExprs dims? + | 'new' primitiveType dims arrayInitializer + | 'new' classOrInterfaceType dims arrayInitializer + ; + +dimExprs + : dimExpr dimExpr* + ; + +dimExpr + : annotation* '[' expression ']' + ; + +constantExpression + : expression + ; + +expression + : lambdaExpression + | assignmentExpression + ; + +lambdaExpression + : lambdaParameters '->' lambdaBody + ; + +lambdaParameters + : Identifier + | '(' formalParameterList? ')' + | '(' inferredFormalParameterList ')' + ; + +inferredFormalParameterList + : Identifier (',' Identifier)* + ; + +lambdaBody + : expression + | block + ; + +assignmentExpression + : conditionalExpression + | assignment + ; + +assignment + : leftHandSide assignmentOperator expression + ; + +leftHandSide + : expressionName + | fieldAccess + | arrayAccess + ; + +assignmentOperator + : '=' + | '*=' + | '/=' + | '%=' + | '+=' + | '-=' + | '<<=' + | '>>=' + | '>>>=' + | '&=' + | '^=' + | '|=' + ; + +conditionalExpression + : conditionalOrExpression + | conditionalOrExpression '?' expression ':' conditionalExpression + ; + +conditionalOrExpression + : conditionalAndExpression + | conditionalOrExpression '||' conditionalAndExpression + ; + +conditionalAndExpression + : inclusiveOrExpression + | conditionalAndExpression '&&' inclusiveOrExpression + ; + +inclusiveOrExpression + : exclusiveOrExpression + | inclusiveOrExpression '|' exclusiveOrExpression + ; + +exclusiveOrExpression + : andExpression + | exclusiveOrExpression '^' andExpression + ; + +andExpression + : equalityExpression + | andExpression '&' equalityExpression + ; + +equalityExpression + : relationalExpression + | equalityExpression '==' relationalExpression + | equalityExpression '!=' relationalExpression + ; + +relationalExpression + : shiftExpression + | relationalExpression '<' shiftExpression + | relationalExpression '>' shiftExpression + | relationalExpression '<=' shiftExpression + | relationalExpression '>=' shiftExpression + | relationalExpression 'instanceof' referenceType + ; + +shiftExpression + : additiveExpression + | shiftExpression '<' '<' additiveExpression + | shiftExpression '>' '>' additiveExpression + | shiftExpression '>' '>' '>' additiveExpression + ; + +additiveExpression + : multiplicativeExpression + | additiveExpression '+' multiplicativeExpression + | additiveExpression '-' multiplicativeExpression + ; + +multiplicativeExpression + : unaryExpression + | multiplicativeExpression '*' unaryExpression + | multiplicativeExpression '/' unaryExpression + | multiplicativeExpression '%' unaryExpression + ; + +unaryExpression + : preIncrementExpression + | preDecrementExpression + | '+' unaryExpression + | '-' unaryExpression + | unaryExpressionNotPlusMinus + ; + +preIncrementExpression + : '++' unaryExpression + ; + +preDecrementExpression + : '--' unaryExpression + ; + +unaryExpressionNotPlusMinus + : postfixExpression + | '~' unaryExpression + | '!' unaryExpression + | castExpression + ; + +postfixExpression + : ( primary + | expressionName + ) + ( postIncrementExpression_lf_postfixExpression + | postDecrementExpression_lf_postfixExpression + )* + ; + +postIncrementExpression + : postfixExpression '++' + ; + +postIncrementExpression_lf_postfixExpression + : '++' + ; + +postDecrementExpression + : postfixExpression '--' + ; + +postDecrementExpression_lf_postfixExpression + : '--' + ; + +castExpression + : '(' primitiveType ')' unaryExpression + | '(' referenceType additionalBound* ')' unaryExpressionNotPlusMinus + | '(' referenceType additionalBound* ')' lambdaExpression + ; + +// LEXER + +// §3.9 Keywords + +ABSTRACT : 'abstract'; +ASSERT : 'assert'; +BOOLEAN : 'boolean'; +BREAK : 'break'; +BYTE : 'byte'; +CASE : 'case'; +CATCH : 'catch'; +CHAR : 'char'; +CLASS : 'class'; +CONST : 'const'; +CONTINUE : 'continue'; +DEFAULT : 'default'; +DO : 'do'; +DOUBLE : 'double'; +ELSE : 'else'; +ENUM : 'enum'; +EXTENDS : 'extends'; +FINAL : 'final'; +FINALLY : 'finally'; +FLOAT : 'float'; +FOR : 'for'; +IF : 'if'; +GOTO : 'goto'; +IMPLEMENTS : 'implements'; +IMPORT : 'import'; +INSTANCEOF : 'instanceof'; +INT : 'int'; +INTERFACE : 'interface'; +LONG : 'long'; +NATIVE : 'native'; +NEW : 'new'; +PACKAGE : 'package'; +PRIVATE : 'private'; +PROTECTED : 'protected'; +PUBLIC : 'public'; +RETURN : 'return'; +SHORT : 'short'; +STATIC : 'static'; +STRICTFP : 'strictfp'; +SUPER : 'super'; +SWITCH : 'switch'; +SYNCHRONIZED : 'synchronized'; +THIS : 'this'; +THROW : 'throw'; +THROWS : 'throws'; +TRANSIENT : 'transient'; +TRY : 'try'; +VOID : 'void'; +VOLATILE : 'volatile'; +WHILE : 'while'; + +// §3.10.1 Integer Literals + +IntegerLiteral + : DecimalIntegerLiteral + | HexIntegerLiteral + | OctalIntegerLiteral + | BinaryIntegerLiteral + ; + +fragment +DecimalIntegerLiteral + : DecimalNumeral IntegerTypeSuffix? + ; + +fragment +HexIntegerLiteral + : HexNumeral IntegerTypeSuffix? + ; + +fragment +OctalIntegerLiteral + : OctalNumeral IntegerTypeSuffix? + ; + +fragment +BinaryIntegerLiteral + : BinaryNumeral IntegerTypeSuffix? + ; + +fragment +IntegerTypeSuffix + : [lL] + ; + +fragment +DecimalNumeral + : '0' + | NonZeroDigit (Digits? | Underscores Digits) + ; + +fragment +Digits + : Digit (DigitsAndUnderscores? Digit)? + ; + +fragment +Digit + : '0' + | NonZeroDigit + ; + +fragment +NonZeroDigit + : [1-9] + ; + +fragment +DigitsAndUnderscores + : DigitOrUnderscore+ + ; + +fragment +DigitOrUnderscore + : Digit + | '_' + ; + +fragment +Underscores + : '_'+ + ; + +fragment +HexNumeral + : '0' [xX] HexDigits + ; + +fragment +HexDigits + : HexDigit (HexDigitsAndUnderscores? HexDigit)? + ; + +fragment +HexDigit + : [0-9a-fA-F] + ; + +fragment +HexDigitsAndUnderscores + : HexDigitOrUnderscore+ + ; + +fragment +HexDigitOrUnderscore + : HexDigit + | '_' + ; + +fragment +OctalNumeral + : '0' Underscores? OctalDigits + ; + +fragment +OctalDigits + : OctalDigit (OctalDigitsAndUnderscores? OctalDigit)? + ; + +fragment +OctalDigit + : [0-7] + ; + +fragment +OctalDigitsAndUnderscores + : OctalDigitOrUnderscore+ + ; + +fragment +OctalDigitOrUnderscore + : OctalDigit + | '_' + ; + +fragment +BinaryNumeral + : '0' [bB] BinaryDigits + ; + +fragment +BinaryDigits + : BinaryDigit (BinaryDigitsAndUnderscores? BinaryDigit)? + ; + +fragment +BinaryDigit + : [01] + ; + +fragment +BinaryDigitsAndUnderscores + : BinaryDigitOrUnderscore+ + ; + +fragment +BinaryDigitOrUnderscore + : BinaryDigit + | '_' + ; + +// §3.10.2 Floating-Point Literals + +FloatingPointLiteral + : DecimalFloatingPointLiteral + | HexadecimalFloatingPointLiteral + ; + +fragment +DecimalFloatingPointLiteral + : Digits '.' Digits? ExponentPart? FloatTypeSuffix? + | '.' Digits ExponentPart? FloatTypeSuffix? + | Digits ExponentPart FloatTypeSuffix? + | Digits FloatTypeSuffix + ; + +fragment +ExponentPart + : ExponentIndicator SignedInteger + ; + +fragment +ExponentIndicator + : [eE] + ; + +fragment +SignedInteger + : Sign? Digits + ; + +fragment +Sign + : [+-] + ; + +fragment +FloatTypeSuffix + : [fFdD] + ; + +fragment +HexadecimalFloatingPointLiteral + : HexSignificand BinaryExponent FloatTypeSuffix? + ; + +fragment +HexSignificand + : HexNumeral '.'? + | '0' [xX] HexDigits? '.' HexDigits + ; + +fragment +BinaryExponent + : BinaryExponentIndicator SignedInteger + ; + +fragment +BinaryExponentIndicator + : [pP] + ; + +// §3.10.3 Boolean Literals + +BooleanLiteral + : 'true' + | 'false' + ; + +// §3.10.4 Character Literals + +CharacterLiteral + : '\'' SingleCharacter '\'' + | '\'' EscapeSequence '\'' + ; + +fragment +SingleCharacter + : ~['\\] + ; + +// §3.10.5 String Literals + +StringLiteral + : '"' StringCharacters? '"' + ; + +fragment +StringCharacters + : StringCharacter+ + ; + +fragment +StringCharacter + : ~["\\] + | EscapeSequence + ; + +// §3.10.6 Escape Sequences for Character and String Literals + +fragment +EscapeSequence + : '\\' [btnfr"'\\] + | OctalEscape + | UnicodeEscape // This is not in the spec but prevents having to preprocess the input + ; + +fragment +OctalEscape + : '\\' OctalDigit + | '\\' OctalDigit OctalDigit + | '\\' ZeroToThree OctalDigit OctalDigit + ; + +fragment +ZeroToThree + : [0-3] + ; + +// This is not in the spec but prevents having to preprocess the input +fragment +UnicodeEscape + : '\\' 'u' HexDigit HexDigit HexDigit HexDigit + ; + +// §3.10.7 The Null Literal + +NullLiteral + : 'null' + ; + +// §3.11 Separators + +LPAREN : '('; +RPAREN : ')'; +LBRACE : '{'; +RBRACE : '}'; +LBRACK : '['; +RBRACK : ']'; +SEMI : ';'; +COMMA : ','; +DOT : '.'; + +// §3.12 Operators + +ASSIGN : '='; +GT : '>'; +LT : '<'; +BANG : '!'; +TILDE : '~'; +QUESTION : '?'; +COLON : ':'; +EQUAL : '=='; +LE : '<='; +GE : '>='; +NOTEQUAL : '!='; +AND : '&&'; +OR : '||'; +INC : '++'; +DEC : '--'; +ADD : '+'; +SUB : '-'; +MUL : '*'; +DIV : '/'; +BITAND : '&'; +BITOR : '|'; +CARET : '^'; +MOD : '%'; +ARROW : '->'; +COLONCOLON : '::'; + +ADD_ASSIGN : '+='; +SUB_ASSIGN : '-='; +MUL_ASSIGN : '*='; +DIV_ASSIGN : '/='; +AND_ASSIGN : '&='; +OR_ASSIGN : '|='; +XOR_ASSIGN : '^='; +MOD_ASSIGN : '%='; +LSHIFT_ASSIGN : '<<='; +RSHIFT_ASSIGN : '>>='; +URSHIFT_ASSIGN : '>>>='; + +// §3.8 Identifiers (must appear after all keywords in the grammar) + +Identifier + : JavaLetter JavaLetterOrDigit* + ; + +fragment +JavaLetter + : [a-zA-Z$_] // these are the "java letters" below 0x7F + | // covers all characters above 0x7F which are not a surrogate + ~[\u0000-\u007F\uD800-\uDBFF] + {Character.isJavaIdentifierStart(_input.LA(-1))}? + | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF + [\uD800-\uDBFF] [\uDC00-\uDFFF] + {Character.isJavaIdentifierStart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}? + ; + +fragment +JavaLetterOrDigit + : [a-zA-Z0-9$_] // these are the "java letters or digits" below 0x7F + | // covers all characters above 0x7F which are not a surrogate + ~[\u0000-\u007F\uD800-\uDBFF] + {Character.isJavaIdentifierPart(_input.LA(-1))}? + | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF + [\uD800-\uDBFF] [\uDC00-\uDFFF] + {Character.isJavaIdentifierPart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}? + ; + +// +// Additional symbols not defined in the lexical specification +// + +AT : '@'; +ELLIPSIS : '...'; + +// +// Whitespace and comments +// + +WS : [ \t\r\n\u000C]+ -> skip + ; + +COMMENT + : '/*' .*? '*/' -> skip + ; + +LINE_COMMENT + : '//' ~[\r\n]* -> skip + ; diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/Arithmetic b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/Arithmetic new file mode 100644 index 00000000..5a6b661c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/Arithmetic @@ -0,0 +1,61 @@ +a00: [[], [[a]]] +a01: [[], [[a]]] +a02: [[], [[a]]] +a03: [[], [[a]]] +a04: [[], [[a]]] +a05: [[], [[a]]] +a06: [[], [[a]]] +a07: [[], [[a]]] +a10: [[], [[a]]] +a11: [[], [[a]]] +a12: [[], [[a]]] +a13: [[], [[a]]] +a14: [[], [[a]]] +a15: [[], [[a]]] +a16: [[], [[a]]] +a17: [[], [[a]]] +a20: [[], [[a]]] +a21: [[], [[a]]] +a22: [[], [[a]]] +a23: [[], [[a]]] +a24: [[], [[a]]] +a25: [[], [[a]]] +a26: [[], [[a]]] +a27: [[], [[a]]] +x0: [[], [[0], [1], [2], [3], [4], [5], [6], [7]]] +x1: [[], [[0], [1], [2], [3], [4], [5], [6], [7]]] +x2: [[], [[0], [1], [2], [3], [4], [5], [6], [7]]] +x3: [[], [[0], [1], [2], [3], [4], [5], [6], [7]]] +x4: [[], [[0], [1], [2], [3], [4], [5], [6], [7]]] +x5: [[], [[0], [1], [2], [3], [4], [5], [6], [7]]] +x6: [[], [[0], [1], [2], [3], [4], [5], [6], [7]]] +x7: [[], [[0], [1], [2], [3], [4], [5], [6], [7]]] +( + ( + ( + ( + ( + ( + ( + ((true && one x0) && one x1) && + one x2 + ) && one x3 + ) && one x4 + ) && one x5 + ) && one x6 + ) && one x7 + ) && + ( + ( + ( + (true && ( + ( + ( + ((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0)) + ) + + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0))) + ) <= 7 + ) + ) && (((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))) <= 7)) && (((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))) <= 7)) && ((((((((((((((((((((((((((((((((((((((((((((((((((((((((true && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a01 then sum(y1) else 0)) + (if some a02 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a11 then sum(y1) else 0)) + (if some a12 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a21 then sum(y1) else 0)) + (if some a22 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a01 then sum(y1) else 0)) + (if some a03 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a11 then sum(y1) else 0)) + (if some a13 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a21 then sum(y1) else 0)) + (if some a23 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a01 then sum(y1) else 0)) + (if some a04 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a11 then sum(y1) else 0)) + (if some a14 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a21 then sum(y1) else 0)) + (if some a24 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a01 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a11 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a21 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a01 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a11 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a21 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a01 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a11 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a21 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a03 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a13 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a23 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a04 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a14 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a24 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a04 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a14 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a24 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a00 then sum(y0) else 0) + (if some a06 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a10 then sum(y0) else 0) + (if some a16 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a20 then sum(y0) else 0) + (if some a26 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a03 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a13 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a23 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a04 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a14 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a24 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a02 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a12 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a22 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a04 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a14 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a24 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a01 then sum(y0) else 0) + (if some a06 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a11 then sum(y0) else 0) + (if some a16 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a21 then sum(y0) else 0) + (if some a26 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a04 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a14 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a24 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a03 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a13 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a23 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a02 then sum(y0) else 0) + (if some a06 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a12 then sum(y0) else 0) + (if some a16 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a22 then sum(y0) else 0) + (if some a26 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a03 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a05 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a13 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a15 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a23 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a25 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a03 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a13 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a23 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a03 then sum(y0) else 0) + (if some a04 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a13 then sum(y0) else 0) + (if some a14 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a23 then sum(y0) else 0) + (if some a24 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a03 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a13 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a23 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a03 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a13 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a23 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a03 then sum(y0) else 0) + (if some a06 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a13 then sum(y0) else 0) + (if some a16 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a23 then sum(y0) else 0) + (if some a26 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a04 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a06 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a14 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a16 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a24 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a26 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a04 then sum(y0) else 0) + (if some a05 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a14 then sum(y0) else 0) + (if some a15 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a24 then sum(y0) else 0) + (if some a25 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a04 then sum(y0) else 0) + (if some a06 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a14 then sum(y0) else 0) + (if some a16 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a24 then sum(y0) else 0) + (if some a26 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))) && (all [y0: one ints, y1: one ints, y2: one ints] | !(((true && ((((if some a05 then sum(y0) else 0) + (if some a06 then sum(y1) else 0)) + (if some a07 then sum(y2) else 0)) = ((((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) + ((if some a02 then sum(x2) else 0) + (if some a03 then sum(x3) else 0))) + (((if some a04 then sum(x4) else 0) + (if some a05 then sum(x5) else 0)) + ((if some a06 then sum(x6) else 0) + (if some a07 then sum(x7) else 0)))))) && ((((if some a15 then sum(y0) else 0) + (if some a16 then sum(y1) else 0)) + (if some a17 then sum(y2) else 0)) = ((((if some a10 then sum(x0) else 0) + (if some a11 then sum(x1) else 0)) + ((if some a12 then sum(x2) else 0) + (if some a13 then sum(x3) else 0))) + (((if some a14 then sum(x4) else 0) + (if some a15 then sum(x5) else 0)) + ((if some a16 then sum(x6) else 0) + (if some a17 then sum(x7) else 0)))))) && ((((if some a25 then sum(y0) else 0) + (if some a26 then sum(y1) else 0)) + (if some a27 then sum(y2) else 0)) = ((((if some a20 then sum(x0) else 0) + (if some a21 then sum(x1) else 0)) + ((if some a22 then sum(x2) else 0) + (if some a23 then sum(x3) else 0))) + (((if some a24 then sum(x4) else 0) + (if some a25 then sum(x5) else 0)) + ((if some a26 then sum(x6) else 0) + (if some a27 then sum(x7) else 0)))))))))) diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/DiffEg b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/DiffEg new file mode 100644 index 00000000..c544d1ec --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/DiffEg @@ -0,0 +1,14 @@ +{Subject0, Subject1, Resource0, Resource1, Action0, Action1, Conflicted0, Conflicted1, Request0, Request1} + +Subject: [{}, {(Subject0), (Subject1)}] +Resource: [{}, {(Resource0), (Resource1)}] +Action: [{}, {(Action0), (Action1)}] +Conflicted: [{}, {(Conflicted0), (Conflicted1)}] +Request: [{}, {(Request0), (Request1)}] +s: [{}, {(Request0, Subject0), (Request0, Subject1), (Request1, Subject0), (Request1, Subject1)}] +r: [{}, {(Request0, Resource0), (Request0, Resource1), (Request1, Resource0), (Request1, Resource1)}] +a: [{}, {(Request0, Action0), (Request0, Action1), (Request1, Action0), (Request1, Action1)}] +s: [{}, {(Conflicted0, Subject0), (Conflicted0, Subject1), (Conflicted1, Subject0), (Conflicted1, Subject1)}] +r: [{}, {(Conflicted0, Resource0), (Conflicted0, Resource1), (Conflicted1, Resource0), (Conflicted1, Resource1)}] + +some req: one Request | all conf: one Conflicted | !(req.s in conf.s && req.r in conf.r) \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/DiffEg.kodkod b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/DiffEg.kodkod new file mode 100644 index 00000000..c544d1ec --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/DiffEg.kodkod @@ -0,0 +1,14 @@ +{Subject0, Subject1, Resource0, Resource1, Action0, Action1, Conflicted0, Conflicted1, Request0, Request1} + +Subject: [{}, {(Subject0), (Subject1)}] +Resource: [{}, {(Resource0), (Resource1)}] +Action: [{}, {(Action0), (Action1)}] +Conflicted: [{}, {(Conflicted0), (Conflicted1)}] +Request: [{}, {(Request0), (Request1)}] +s: [{}, {(Request0, Subject0), (Request0, Subject1), (Request1, Subject0), (Request1, Subject1)}] +r: [{}, {(Request0, Resource0), (Request0, Resource1), (Request1, Resource0), (Request1, Resource1)}] +a: [{}, {(Request0, Action0), (Request0, Action1), (Request1, Action0), (Request1, Action1)}] +s: [{}, {(Conflicted0, Subject0), (Conflicted0, Subject1), (Conflicted1, Subject0), (Conflicted1, Subject1)}] +r: [{}, {(Conflicted0, Resource0), (Conflicted0, Resource1), (Conflicted1, Resource0), (Conflicted1, Resource1)}] + +some req: one Request | all conf: one Conflicted | !(req.s in conf.s && req.r in conf.r) \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/FileSystem1.api b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/FileSystem1.api new file mode 100644 index 00000000..df871688 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/FileSystem1.api @@ -0,0 +1,54 @@ +relations: { + Object = [[Object0], [Object1], [Object2]] + Root=[[Object0]] + Cur=[] + File=[] + Dir=[[Object0], [Object1], [Object2]] + Name=[[Name0], [Name1], [Name2]] + DirEntry=[[DirEntry0], [DirEntry1], [DirEntry2]] + entries=[[Object0, DirEntry0], [Object0, DirEntry1], [Object2, DirEntry2]] + parent=[[Object1, Object2], [Object2, Object0]] + name=[[DirEntry0, Name2], [DirEntry1, Name1], [DirEntry2, Name0]], + contents=[[DirEntry0, Object2], [DirEntry1, Object2], [DirEntry2, Object1]], + $o=[[Object2]] +} + +( + ( + ( + ( + ( + ( + ( + ((Object = (File + Dir)) && no (File & Dir)) && + ( + ((Root in Dir) && (Cur in Dir)) && + no (Root & Cur) + ) + ) && (entries in (Dir -> DirEntry)) + ) && FUNCTION(parent, Dir ->lone Dir) + ) && FUNCTION(name, DirEntry ->one Name) + ) && FUNCTION(contents, DirEntry ->one Object) + ) && + ( + ( + ( + ( + (all this: one File | (some d: one Dir | (this in ((d . entries) . contents)))) && + (all this: one Dir | + ( + ( + ( + ((this . parent) = ((this . ~contents) . ~entries)) && + (all [e1: one (this . entries), e2: one (this . entries)] | (((e1 . name) = (e2 . name)) => (e1 = e2))) + ) && !(this in (this . ^parent)) + ) && (!(this = Root) => (Root in (this . ^parent))) + ) + ) + ) && no (Root . parent) + ) && (all this: one DirEntry | one (this . ~entries)) + ) && (all d: one (Dir - Root) | one (d . parent)) + ) + ) && !(all o: one Dir | lone (o . ~contents)) +) + diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/FileSystem1.kodkod b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/FileSystem1.kodkod new file mode 100644 index 00000000..df871688 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/FileSystem1.kodkod @@ -0,0 +1,54 @@ +relations: { + Object = [[Object0], [Object1], [Object2]] + Root=[[Object0]] + Cur=[] + File=[] + Dir=[[Object0], [Object1], [Object2]] + Name=[[Name0], [Name1], [Name2]] + DirEntry=[[DirEntry0], [DirEntry1], [DirEntry2]] + entries=[[Object0, DirEntry0], [Object0, DirEntry1], [Object2, DirEntry2]] + parent=[[Object1, Object2], [Object2, Object0]] + name=[[DirEntry0, Name2], [DirEntry1, Name1], [DirEntry2, Name0]], + contents=[[DirEntry0, Object2], [DirEntry1, Object2], [DirEntry2, Object1]], + $o=[[Object2]] +} + +( + ( + ( + ( + ( + ( + ( + ((Object = (File + Dir)) && no (File & Dir)) && + ( + ((Root in Dir) && (Cur in Dir)) && + no (Root & Cur) + ) + ) && (entries in (Dir -> DirEntry)) + ) && FUNCTION(parent, Dir ->lone Dir) + ) && FUNCTION(name, DirEntry ->one Name) + ) && FUNCTION(contents, DirEntry ->one Object) + ) && + ( + ( + ( + ( + (all this: one File | (some d: one Dir | (this in ((d . entries) . contents)))) && + (all this: one Dir | + ( + ( + ( + ((this . parent) = ((this . ~contents) . ~entries)) && + (all [e1: one (this . entries), e2: one (this . entries)] | (((e1 . name) = (e2 . name)) => (e1 = e2))) + ) && !(this in (this . ^parent)) + ) && (!(this = Root) => (Root in (this . ^parent))) + ) + ) + ) && no (Root . parent) + ) && (all this: one DirEntry | one (this . ~entries)) + ) && (all d: one (Dir - Root) | one (d . parent)) + ) + ) && !(all o: one Dir | lone (o . ~contents)) +) + diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/FileSystemKodKod1 b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/FileSystemKodKod1 new file mode 100644 index 00000000..e102c86e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/FileSystemKodKod1 @@ -0,0 +1,12 @@ +{d0, d1, d2, d3, f0, f1, f2} + +File: 1 [ {(f0), (f1), (f2)} ] +Dir: 1 [ {(d0), (d1), (d2)} ] +Root :1 [{(d0)}] +contents: [[[d0, d1], [d0, d2], [d1, f0], [d2, d3], [d3, f1], [d3, f2] ]] + +contents in Dir -> (Dir + File) +all d:Dir | not (d in d.^contents) +Root in Dir +(File + Dir) in Root.*contents + diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/FileSystemKodKod2 b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/FileSystemKodKod2 new file mode 100644 index 00000000..dd856fb1 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/FileSystemKodKod2 @@ -0,0 +1,12 @@ +{d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, f0, f1, f2, f3, f4, f5, f6, f7, f8, f9} + +File: 1 [ {(f0), (f1), (f2), (f3), (f4), (f5), (f6), (f7), (f8), (f9)} ] +Dir: 1 [ {(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7), (d8), (d9), (d10)} ] +Root :1 [{(d0)}] +contents: [[[d0, d1], [d0, d2], [d1, f0], [d1, d4], [d2, d3], [d2, d5], [d2, d6], [d3, f1], [d3, f2], [d4, f3], [d4, f4], [d5, f5], [d5, f6], [d6, f7], [d6, d7], [d7, f8], [d7, d8], [d8, f9], [d8, d9], [d8, d10] ]] + +contents in Dir -> (Dir + File) +all d:Dir | not (d in d.^contents) +Root in Dir +(File + Dir) in Root.*contents + diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/Filesystem-ex.kodkod b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/Filesystem-ex.kodkod new file mode 100644 index 00000000..00aee0d0 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/Filesystem-ex.kodkod @@ -0,0 +1,39 @@ +{l0, l1, l2, t0, t1, t2, a, 0, 1, 2, 3, 4, 5, 6, 7, ferhat} + +List: [{}, {(l0),(l1),(l2)}] +Nil :1 [{}, {(l0),(l1),(l2)}] +Cons: [{}, {(l0),(l1),(l2)}] +Thing :1 [{}, {(t0),(t1),(t2)}] +car :2 [{}, {(l0, t0), (l0, t1), (l0, t2), (l1, t0), (l1, t1), (l1, t2), (l2, t0), (l2, t1), (l2, t2)}] +cdr :2 [{}, {(l0, l0), (l0, l1), (l0, l2), (l1, l0), (l1, l1), (l1, l2), (l2, l0), (l2, l1), (l2, l2)}] +equivTo :2 [{}, {(l0, l0), (l0, l1), (l0, l2), (l1, l0), (l1, l1), (l1, l2), (l2, l0), (l2, l1), (l2, l2)}] +prefixes :2 [{}, {(l0, l0), (l0, l1), (l0, l2), (l1, l0), (l1, l1), (l1, l2), (l2, l0), (l2, l1), (l2, l2)}] + +List = Cons + Nil +no Cons & Nil + +car in Cons -> Thing +all a: Cons { + one a.car + one a.cdr +} + +cdr in Cons -> List + +all a: List | some e: some Nil | e in a.^cdr +equivTo in List -> List +all a, b: List | (a in b.equivTo) iff (a.car = b.car and a.cdr.equivTo = b.cdr.equivTo) +prefixes in List -> List +all e: Nil, a: List | e in a.prefixes +all e: Nil, a: Cons | not (a in e.prefixes) +all a, b: Cons | (a in b.prefixes) iff (a.car = b.car and a.cdr in b.cdr.prefixes) + +function[car: List -> one Thing] +/* +true && ((if some a00 then sum(x0) else 0) + (if some a01 then sum(x1) else 0)) <= - 7 + +let parent = mother + father { + no m: Man | some m.wife and m.wife in m.*parent.mother + no w: Woman | some w.husband and w.husband in w.*parent.father +} +*/ diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/Filesystem.als b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/Filesystem.als new file mode 100644 index 00000000..80dc9379 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/Filesystem.als @@ -0,0 +1,59 @@ +model examples/systems/file_system + +/* + * Model of a generic file system. + */ + +abstract sig Object {} + +sig Name {} + +sig File extends Object {} { some d: Dir | this in d.entries.contents } + +sig Dir extends Object { + entries: set DirEntry, + parent: lone Dir +} { + parent = this.~@contents.~@entries + all e1, e2 : entries | e1.name = e2.name => e1 = e2 + this !in this.^@parent + this != Root => Root in this.^@parent +} + +one sig Root extends Dir {} { no parent } + +lone sig Cur extends Dir {} + +sig DirEntry { + name: Name, + contents: Object +} { + one this.~entries +} + + +/** + * all directories besides root have one parent + */ +pred OneParent_buggyVersion { + all d: Dir - Root | one d.parent +} + +/** + * all directories besides root have one parent + */ +pred OneParent_correctVersion { + all d: Dir - Root | (one d.parent && one contents.d) +} + +/** + * Only files may be linked (that is, have more than one entry) + * That is, all directories are the contents of at most one directory entry + */ +pred NoDirAliases { + all o: Dir | lone o.~contents +} + +check { OneParent_buggyVersion => NoDirAliases } for 5 expect 1 + +check { OneParent_correctVersion => NoDirAliases } for 5 expect 0 diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/Filesystem.kodkod b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/Filesystem.kodkod new file mode 100644 index 00000000..52ea874e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/Filesystem.kodkod @@ -0,0 +1,14 @@ +universe {d0, d1, d2, d3, f0, f1, f2, f3} + +relations { + File : [ {(f0), (f1), (f2)} ] + Dir : [ {(d0), (d1), (d2)} ] + Root: Dir [{(d0)}] + contents: Dir -> File [{[d0, d1], [d0, f0], [d0, f1], [d0, f2]}, {[d0, d1], [d0, f0], [d0, f1], [d0, f2], [d1, d2]}] +} + +contents in Dir -> (Dir + File) +all d:Dir | not (d in d.^contents) +Root in Dir +(File + Dir) in Root.*contents + diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/Filesystem_wrong.kodkod b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/Filesystem_wrong.kodkod new file mode 100644 index 00000000..5057b0ea --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/Filesystem_wrong.kodkod @@ -0,0 +1,11 @@ +{d0, d1, f0, f1, f2} + +File: 1 [ {(d0), (d1)}, {(d1)} ] +Dir: 1 [ {} , {(d0), (d1)} ] +Root :1 [{(d0)}, {(d0)}] +contents: 2 [ {(d0, d1)}, {(d0, d0), (d0,d1)} ] + +contents in Dir -> (Dir + s File) +all d:Dir | not (d in d.^contents) +Root in Dir +(File + Dir) in Root.*contents diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/Hotel.kodkod b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/Hotel.kodkod new file mode 100644 index 00000000..aab0014d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/Hotel.kodkod @@ -0,0 +1,111 @@ +[Time0, Time1, Event0, Event1, Room0, Room1, Card0, Card1, Key0, Key1, Guest0, Guest1] + +Time: [[], [[Time0], [Time1]]] +Event: [[], [[Event0], [Event1]]] +Room: [[], [[Room0], [Room1]]] +Card: [[], [[Card0], [Card1]]] +Key: [[], [[Key0], [Key1]]] +Guest: [[], [[Guest0], [Guest1]]] +first: [[], [[Time0], [Time1]]] +last: [[], [[Time0], [Time1]]] +next: [[], [[Time0, Time0], [Time0, Time1], [Time1, Time0], [Time1, Time1]]] +pre: [[], [[Event0, Time0], [Event0, Time1], [Event1, Time0], [Event1, Time1]]] +post: [[], [[Event0, Time0], [Event0, Time1], [Event1, Time0], [Event1, Time1]]] +HotelEvent: [[], [[Event0], [Event1]]] +RoomCardEvent: [[], [[Event0], [Event1]]] +Enter: [[], [[Event0], [Event1]]] +NormalEnter: [[], [[Event0], [Event1]]] +RecodeEnter: [[], [[Event0], [Event1]]] +Checkin: [[], [[Event0], [Event1]]] +Checkout: [[], [[Event0], [Event1]]] +k1: [[], [[Card0, Key0], [Card0, Key1], [Card1, Key0], [Card1, Key1]]] +k2: [[], [[Card0, Key0], [Card0, Key1], [Card1, Key0], [Card1, Key1]]] +key: [[], [[Room0, Key0, Time0], [Room0, Key0, Time1], [Room0, Key1, Time0], [Room0, Key1, Time1], [Room1, Key0, Time0], [Room1, Key0, Time1], [Room1, Key1, Time0], [Room1, Key1, Time1]]] +prev: [[], [[Room0, Key0, Time0], [Room0, Key0, Time1], [Room0, Key1, Time0], [Room0, Key1, Time1], [Room1, Key0, Time0], [Room1, Key0, Time1], [Room1, Key1, Time0], [Room1, Key1, Time1]]] +occ: [[], [[Room0, Guest0, Time0], [Room0, Guest0, Time1], [Room0, Guest1, Time0], [Room0, Guest1, Time1], [Room1, Guest0, Time0], [Room1, Guest0, Time1], [Room1, Guest1, Time0], [Room1, Guest1, Time1]]] +holds: [[], [[Guest0, Card0, Time0], [Guest0, Card0, Time1], [Guest0, Card1, Time0], [Guest0, Card1, Time1], [Guest1, Card0, Time0], [Guest1, Card0, Time1], [Guest1, Card1, Time0], [Guest1, Card1, Time1]]] +guest: [[], [[Event0, Guest0], [Event0, Guest1], [Event1, Guest0], [Event1, Guest1]]] +room: [[], [[Event0, Room0], [Event0, Room1], [Event1, Room0], [Event1, Room1]]] +card: [[], [[Event0, Card0], [Event0, Card1], [Event1, Card0], [Event1, Card1]]] + + +ord[next, Time, first, last] +function[pre: Event -> one Time] +function[post: Event -> one Time] + +all t: Time - last | one {e: Event | e.pre = t && e.post = t.next} + +function[k1: Card -> one Key] +function[k2: Card -> one Key] + +key in (Room -> Key -> Time) +prev in (Room -> Key -> Time) +occ in (Room -> Guest -> Time) + +all r: Room, t: Time | one r . key . t +all r: Room, t: Time | lone r . prev . t + +holds in Guest -> Card -> Time + +prev.first = key.first +key.first in Room -> Key +all k: Key | lone key.first.k +no holds.first +no occ.first +HotelEvent = Event +HotelEvent = (RoomCardEvent + Checkout) +no (RoomCardEvent & Checkout) + +function[guest: HotelEvent -> one Guest] + +RoomCardEvent in HotelEvent +RoomCardEvent = (Checkin + Enter) + +no (Checkin & Enter) + +function[room: RoomCardEvent -> one Room] +function[card: RoomCardEvent -> one Card] + +Checkin in RoomCardEvent +all c: Checkin | no c.room.occ.c.pre +all c: Checkin | c.card.k1 = c.room.prev.c.pre +all c: Checkin | (holds . (c . post)) = ((holds . (c . pre)) + ((c . guest) -> (c . card))) +all c: Checkin | (prev . (c . post)) = ((prev . (c . pre)) ++ ((c . room) -> ((c . card) . k2))) +all c: Checkin | (occ . (c . post)) = ((occ . (c . pre)) + ((c . room) -> (c . guest))) +all c: Checkin | (key . (c . pre)) = (key . (c . post)) + +Enter in RoomCardEvent +Enter = (NormalEnter + RecodeEnter) +no (NormalEnter & RecodeEnter) +all e: Enter | e.card in (((e . guest) . holds) . (e . pre)) + +NormalEnter in Enter && (all n: NormalEnter | ((n . card) . k2) = (((n . room) . key) . (n . pre))) +all n: NormalEnter | (prev . (n . pre)) = (prev . (n . post)) +all n: NormalEnter | (holds . (n . pre)) = (holds . (n . post)) +all n: NormalEnter | (occ . (n . pre)) = (occ . (n . post)) +all n: NormalEnter | (key . (n . pre)) = (key . (n . post)) + +RecodeEnter in Enter +all n: RecodeEnter | ((n . card) . k1) = (((n . room) . key) . (n . pre)) +all n: RecodeEnter | (key . (n . post)) = ((key . (n . pre)) ++ ((n . room) -> ((n . card) . k2))) +all n: RecodeEnter | (prev . (n . pre)) = (prev . (n . post)) +all n: RecodeEnter | (holds . (n . pre)) = (holds . (n . post)) +all n: RecodeEnter | (occ . (n . pre)) = (occ . (n . post)) + +Checkout in HotelEvent +all n: Checkout | some ((occ . (n . pre)) . (n . guest)) +all n: Checkout | (occ . (n . post)) = ((occ . (n . pre)) - (Room -> (n . guest))) +all n: Checkout | (prev . (n . pre)) = (prev . (n . post)) +all n: Checkout | (holds . (n . pre)) = (holds . (n . post)) +all n: Checkout | (key . (n . pre)) = (key . (n . post)) + +all e1: Checkin, e2: Checkin | !(e1 = e2) => !(((e1 . card) . k2) = ((e2 . card) . k2)) + +all e: Checkin | !(((e . card) . k2) in ((Room . key) . first)) + +all c: Checkin - (pre . last) | some e: Enter | (e . pre) = (c . post) && (e . room) = (c . room) && (e . guest) = (c . guest) + +!(all e: Enter | some ((e.room) . (occ.(e.pre))) => (e . guest) in ((e . room) . (occ . (e . pre)))) + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/KodKodTestFile.kodkod b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/KodKodTestFile.kodkod new file mode 100644 index 00000000..e65db0b4 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/KodKodTestFile.kodkod @@ -0,0 +1,12 @@ +{d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31, d32, d33, d34, d35, d36, d37, d38, d39, d40, d41, d42, d43, d44, d45, d46, d47, d48, d49, d50, d51, d52, d53, d54, d55, d56, d57, d58, d59, d60, d61, d62, d63, d64, d65, d66, d67, d68, d69, d70, d71, d72, d73, d74, d75, d76, d77, d78, d79, d80, d81, d82, d83, d84, d85, d86, d87, d88, d89, d90, d91, d92, d93, d94, d95, d96, d97, d98, d99, d100, d101, d102, d103, d104, d105, d106, d107, d108, d109, d110, d111, d112, d113, d114, d115, d116, d117, d118, d119, d120, d121, d122, d123, d124, d125, d126, d127, d128, d129, d130, d131, d132, d133, d134, d135, d136, d137, d138, d139, d140, d141, d142, d143, d144, d145, d146, d147, d148, d149, d150, d151, d152, d153, d154, d155, d156, d157, d158, d159, d160, d161, d162, d163, d164, d165, d166, d167, d168, d169, d170, d171, d172, d173, d174, d175, d176, d177, d178, d179, d180, d181, d182, d183, d184, d185, d186, d187, d188, d189, d190, d191, d192, d193, d194, d195, d196, d197, d198, d199, d200, d201, d202, d203, d204, d205, d206, d207, d208, d209, d210, d211, d212, d213, d214, d215, d216, d217, d218, d219, d220, d221, d222, d223, d224, d225, d226, d227, d228, d229, d230, d231, d232, d233, d234, d235, d236, d237, d238, d239, d240, d241, d242, d243, d244, d245, d246, d247, d248, d249, d250, d251, d252, d253, d254, d255, d256, d257, d258, d259, d260, d261, d262, d263, d264, d265, d266, d267, d268, d269, d270, d271, d272, d273, d274, d275, d276, d277, d278, d279, d280, d281, d282, d283, d284, d285, d286, d287, d288, d289, d290, d291, d292, d293, d294, d295, d296, d297, d298, d299, d300, d301, d302, d303, d304, d305, d306, d307, d308, d309, d310, d311, d312, d313, d314, d315, d316, d317, d318, d319, d320, d321, d322, d323, d324, d325, d326, d327, d328, d329, d330, d331, d332, d333, d334, d335, d336, d337, d338, d339, d340, d341, d342, d343, d344, d345, d346, d347, d348, d349, d350, d351, d352, d353, d354, d355, d356, d357, d358, d359, d360, d361, d362, d363, d364, d365, d366, d367, d368, d369, d370, d371, d372, d373, d374, d375, d376, d377, d378, d379, d380, d381, d382, d383, d384, d385, d386, d387, d388, d389, d390, d391, d392, d393, d394, d395, d396, d397, d398, d399, d400, d401, d402, d403, d404, d405, d406, d407, d408, d409, d410, d411, d412, d413, d414, d415, d416, d417, d418, d419, d420, d421, d422, d423, d424, d425, d426, d427, d428, d429, d430, d431, d432, d433, d434, d435, d436, d437, d438, d439, d440, d441, d442, d443, d444, d445, d446, d447, d448, d449, d450, d451, d452, d453, d454, d455, d456, d457, d458, d459, d460, d461, d462, d463, d464, d465, d466, d467, d468, d469, d470, d471, d472, d473, d474, d475, d476, d477, d478, d479, d480, d481, d482, d483, d484, d485, d486, d487, d488, d489, d490, d491, d492, d493, d494, d495, d496, d497, d498, d499, d500, d501, d502, d503, d504, d505, d506, d507, d508, d509, d510, d511, d512, d513, d514, d515, d516, d517, d518, d519, d520, d521, d522, d523, d524, d525, d526, d527, d528, d529, d530, d531, d532, d533, d534, d535, d536, d537, d538, d539, d540, d541, d542, d543, d544, d545, d546, d547, d548, d549, d550, d551, d552, d553, d554, d555, d556, d557, d558, d559, d560, d561, d562, d563, d564, d565, d566, d567, d568, d569, d570, d571, d572, d573, d574, d575, d576, d577, d578, d579, d580, d581, d582, d583, d584, d585, d586, d587, d588, d589, d590, d591, d592, d593, d594, d595, d596, d597, d598, d599, d600, d601, d602, d603, d604, d605, d606, d607, d608, d609, d610, d611, d612, d613, d614, d615, d616, d617, d618, d619, d620, d621, d622, d623, d624, d625, d626, d627, d628, d629, d630, d631, d632, d633, d634, d635, d636, d637, d638, d639, d640, d641, d642, d643, d644, d645, d646, d647, d648, d649, d650, d651, d652, d653, d654, d655, d656, d657, d658, d659, d660, d661, d662, d663, d664, d665, d666, d667, d668, d669, d670, d671, d672, d673, d674, d675, d676, d677, d678, d679, d680, d681, d682, d683, d684, d685, d686, d687, d688, d689, d690, d691, d692, d693, d694, d695, d696, d697, d698, d699, d700, d701, d702, d703, d704, d705, d706, d707, d708, d709, d710, d711, d712, d713, d714, d715, d716, d717, d718, d719, d720, d721, d722, d723, d724, d725, d726, d727, d728, d729, d730, d731, d732, d733, d734, d735, d736, d737, d738, d739, d740, d741, d742, d743, d744, d745, d746, d747, d748, d749, d750, d751, d752, d753, d754, d755, d756, d757, d758, d759, d760, d761, d762, d763, d764, d765, d766, d767, d768, d769, d770, d771, d772, d773, d774, d775, d776, d777, d778, d779, d780, d781, d782, d783, d784, d785, d786, d787, d788, d789, d790, d791, d792, d793, d794, d795, d796, d797, d798, d799, d800, d801, d802, d803, d804, d805, d806, d807, d808, d809, d810, d811, d812, d813, d814, d815, d816, d817, d818, d819, d820, d821, d822, d823, d824, d825, d826, d827, d828, d829, d830, d831, d832, d833, d834, d835, d836, d837, d838, d839, d840, d841, d842, d843, d844, d845, d846, d847, d848, d849, d850, d851, d852, d853, d854, d855, d856, d857, d858, d859, d860, d861, d862, d863, d864, d865, d866, d867, d868, d869, d870, d871, d872, d873, d874, d875, d876, d877, d878, d879, d880, d881, d882, d883, d884, d885, d886, d887, d888, d889, d890, d891, d892, d893, d894, d895, d896, d897, d898, d899, d900, d901, d902, d903, d904, d905, d906, d907, d908, d909, d910, d911, d912, d913, d914, d915, d916, d917, d918, d919, d920, d921, d922, d923, d924, d925, d926, d927, d928, d929, d930, d931, d932, d933, d934, d935, d936, d937, d938, d939, d940, d941, d942, d943, d944, d945, d946, d947, d948, d949, d950, d951, d952, d953, d954, d955, d956, d957, d958, d959, d960, d961, d962, d963, d964, d965, d966, d967, d968, d969, d970, d971, d972, d973, d974, d975, d976, d977, d978, d979, d980, d981, d982, d983, d984, d985, d986, d987, d988, d989, d990, d991, d992, d993, d994, d995, d996, d997, d998, d999, d1000, d1001, d1002, d1003, d1004, d1005, d1006, d1007, d1008, d1009, d1010, d1011, d1012, d1013, d1014, d1015, d1016, d1017, d1018, d1019, d1020, d1021, d1022, d1023, d1024, d1025, d1026, d1027, d1028, d1029, d1030, d1031, d1032, d1033, d1034, d1035, d1036, d1037, d1038, d1039, d1040, d1041, d1042, d1043, d1044, d1045, d1046, d1047, d1048, d1049, d1050, d1051, d1052, d1053, d1054, d1055, d1056, d1057, d1058, d1059, d1060, d1061, d1062, d1063, d1064, d1065, d1066, d1067, d1068, d1069, d1070, d1071, d1072, d1073, d1074, d1075, d1076, d1077, d1078, d1079, d1080, d1081, d1082, d1083, d1084, d1085, d1086, d1087, d1088, d1089, d1090, d1091, d1092, d1093, d1094, d1095, d1096, d1097, d1098, d1099, d1100, d1101, d1102, d1103, d1104, d1105, d1106, d1107, d1108, d1109, d1110, d1111, d1112, d1113, d1114, d1115, d1116, d1117, d1118, d1119, d1120, d1121, d1122, d1123, d1124, d1125, d1126, d1127, d1128, d1129, d1130, d1131, d1132, d1133, d1134, d1135, d1136, d1137, d1138, d1139, d1140, d1141, d1142, d1143, d1144, d1145, d1146, d1147, d1148, d1149, d1150, d1151, d1152, d1153, d1154, d1155, d1156, d1157, d1158, d1159, d1160, d1161, d1162, d1163, d1164, d1165, d1166, d1167, d1168, d1169, d1170, d1171, d1172, d1173, d1174, d1175, d1176, d1177, d1178, d1179, d1180, d1181, d1182, d1183, d1184, d1185, d1186, d1187, d1188, d1189, d1190, d1191, d1192, d1193, d1194, d1195, d1196, d1197, d1198, d1199, d1200, d1201, d1202, d1203, d1204, d1205, d1206, d1207, d1208, d1209, d1210, d1211, d1212, d1213, d1214, d1215, d1216, d1217, d1218, d1219, d1220, d1221, d1222, d1223, d1224, d1225, d1226, d1227, d1228, d1229, d1230, d1231, d1232, d1233, d1234, d1235, d1236, d1237, d1238, d1239, d1240, d1241, d1242, d1243, d1244, d1245, d1246, d1247, d1248, d1249, d1250, d1251, d1252, d1253, d1254, d1255, d1256, d1257, d1258, d1259, d1260, d1261, d1262, d1263, d1264, d1265, d1266, d1267, d1268, d1269, d1270, d1271, d1272, d1273, d1274, d1275, d1276, d1277, d1278, d1279, d1280, d1281, d1282, d1283, d1284, d1285, d1286, d1287, d1288, d1289, d1290, d1291, d1292, d1293, d1294, d1295, d1296, d1297, d1298, d1299, d1300, d1301, d1302, d1303, d1304, d1305, d1306, d1307, d1308, d1309, d1310, d1311, d1312, d1313, d1314, d1315, d1316, d1317, d1318, d1319, d1320, d1321, d1322, d1323, d1324, d1325, d1326, d1327, d1328, d1329, d1330, d1331, d1332, d1333, d1334, d1335, d1336, d1337, d1338, d1339, d1340, d1341, d1342, d1343, d1344, d1345, d1346, d1347, d1348, d1349, d1350, d1351, d1352, d1353, d1354, d1355, d1356, d1357, d1358, d1359, d1360, d1361, d1362, d1363, d1364, d1365, d1366, d1367, d1368, d1369, d1370, d1371, d1372, d1373, d1374, d1375, d1376, d1377, d1378, d1379, d1380, d1381, d1382, d1383, d1384, d1385, d1386, d1387, d1388, d1389, d1390, d1391, d1392, d1393, d1394, d1395, d1396, d1397, d1398, d1399, d1400, d1401, d1402, d1403, d1404, d1405, d1406, d1407, d1408, d1409, d1410, d1411, d1412, d1413, d1414, d1415, d1416, d1417, d1418, d1419, d1420, d1421, d1422, d1423, d1424, d1425, d1426, d1427, d1428, d1429, d1430, d1431, d1432, d1433, d1434, d1435, d1436, d1437, d1438, d1439, d1440, d1441, d1442, d1443, d1444, d1445, d1446, d1447, d1448, d1449, d1450, d1451, d1452, d1453, d1454, d1455, d1456, d1457, d1458, d1459, d1460, d1461, d1462, d1463, d1464, d1465, d1466, d1467, d1468, d1469, d1470, d1471, d1472, d1473, d1474, d1475, d1476, d1477, d1478, d1479, d1480, d1481, d1482, d1483, d1484, d1485, d1486, d1487, d1488, d1489, d1490, d1491, d1492, d1493, d1494, d1495, d1496, d1497, d1498, d1499, d1500, d1501, d1502, d1503, d1504, d1505, d1506, d1507, d1508, d1509, d1510, d1511, d1512, d1513, d1514, d1515, d1516, d1517, d1518, d1519, d1520, d1521, d1522, d1523, d1524, d1525, d1526, d1527, d1528, d1529, d1530, d1531, d1532, d1533, d1534, d1535, d1536, d1537, d1538, d1539, d1540, d1541, d1542, d1543, d1544, d1545, d1546, d1547, d1548, d1549, d1550, d1551, d1552, d1553, d1554, d1555, d1556, d1557, d1558, d1559, d1560, d1561, d1562, d1563, d1564, d1565, d1566, d1567, d1568, d1569, d1570, d1571, d1572, d1573, d1574, d1575, d1576, d1577, d1578, d1579, d1580, d1581, d1582, d1583, d1584, d1585, d1586, d1587, d1588, d1589, d1590, d1591, d1592, d1593, d1594, d1595, d1596, d1597, d1598, d1599, d1600, d1601, d1602, d1603, d1604, d1605, d1606, d1607, d1608, d1609, d1610, d1611, d1612, d1613, d1614, d1615, d1616, d1617, d1618, d1619, d1620, d1621, d1622, d1623, d1624, d1625, d1626, d1627, d1628, d1629, d1630, d1631, d1632, d1633, d1634, d1635, d1636, d1637, d1638, d1639, d1640, d1641, d1642, d1643, d1644, d1645, d1646, d1647, d1648, d1649, d1650, d1651, d1652, d1653, d1654, d1655, d1656, d1657, d1658, d1659, d1660, d1661, d1662, d1663, d1664, d1665, d1666, d1667, d1668, d1669, d1670, d1671, d1672, d1673, d1674, d1675, d1676, d1677, d1678, d1679, d1680, d1681, d1682, d1683, d1684, d1685, d1686, d1687, d1688, d1689, d1690, d1691, d1692, d1693, d1694, d1695, d1696, d1697, d1698, d1699, d1700, d1701, d1702, d1703, d1704, d1705, d1706, d1707, d1708, d1709, d1710, d1711, d1712, d1713, d1714, d1715, d1716, d1717, d1718, d1719, d1720, d1721, d1722, d1723, d1724, d1725, d1726, d1727, d1728, d1729, d1730, d1731, d1732, d1733, d1734, d1735, d1736, d1737, d1738, d1739, d1740, d1741, d1742, d1743, d1744, d1745, d1746, d1747, d1748, d1749, d1750, d1751, d1752, d1753, d1754, d1755, d1756, d1757, d1758, d1759, d1760, d1761, d1762, d1763, d1764, d1765, d1766, d1767, d1768, d1769, d1770, d1771, d1772, d1773, d1774, d1775, d1776, d1777, d1778, d1779, d1780, d1781, d1782, d1783, d1784, d1785, d1786, d1787, d1788, d1789, d1790, d1791, d1792, d1793, d1794, d1795, d1796, d1797, d1798, d1799, d1800, d1801, d1802, d1803, d1804, d1805, d1806, d1807, d1808, d1809, d1810, d1811, d1812, d1813, d1814, d1815, d1816, d1817, d1818, d1819, d1820, d1821, d1822, d1823, d1824, d1825, d1826, d1827, d1828, d1829, d1830, d1831, d1832, d1833, d1834, d1835, d1836, d1837, d1838, d1839, d1840, d1841, d1842, d1843, d1844, d1845, d1846, d1847, d1848, d1849, d1850, d1851, d1852, d1853, d1854, d1855, d1856, d1857, d1858, d1859, d1860, d1861, d1862, d1863, d1864, d1865, d1866, d1867, d1868, d1869, d1870, d1871, d1872, d1873, d1874, d1875, d1876, d1877, d1878, d1879, d1880, d1881, d1882, d1883, d1884, d1885, d1886, d1887, d1888, d1889, d1890, d1891, d1892, d1893, d1894, d1895, d1896, d1897, d1898, d1899, d1900, d1901, d1902, d1903, d1904, d1905, d1906, d1907, d1908, d1909, d1910, d1911, d1912, d1913, d1914, d1915, d1916, d1917, d1918, d1919, d1920, d1921, d1922, d1923, d1924, d1925, d1926, d1927, d1928, d1929, d1930, d1931, d1932, d1933, d1934, d1935, d1936, d1937, d1938, d1939, d1940, d1941, d1942, d1943, d1944, d1945, d1946, d1947, d1948, d1949, d1950, d1951, d1952, d1953, d1954, d1955, d1956, d1957, d1958, d1959, d1960, d1961, d1962, d1963, d1964, d1965, d1966, d1967, d1968, d1969, d1970, d1971, d1972, d1973, d1974, d1975, d1976, d1977, d1978, d1979, d1980, d1981, d1982, d1983, d1984, d1985, d1986, d1987, d1988, d1989, d1990, d1991, d1992, d1993, d1994, d1995, d1996, d1997, d1998, d1999, d2000, d2001, d2002, d2003, d2004, d2005, d2006, d2007, d2008, d2009, d2010, d2011, d2012, d2013, d2014, d2015, d2016, d2017, d2018, d2019, d2020, d2021, d2022, d2023, d2024, d2025, d2026, d2027, d2028, d2029, d2030, d2031, d2032, d2033, d2034, d2035, d2036, d2037, d2038, d2039, d2040, d2041, d2042, d2043, d2044, d2045, d2046, d2047, d2048, d2049, d2050, d2051, d2052, d2053, d2054, d2055, d2056, d2057, d2058, d2059, d2060, d2061, d2062, d2063, d2064, d2065, d2066, d2067, d2068, d2069, d2070, d2071, d2072, d2073, d2074, d2075, d2076, d2077, d2078, d2079, d2080, d2081, d2082, d2083, d2084, d2085, d2086, d2087, d2088, d2089, d2090, d2091, d2092, d2093, d2094, d2095, d2096, d2097, d2098, d2099, d2100, d2101, d2102, d2103, d2104, d2105, d2106, d2107, d2108, d2109, d2110, d2111, d2112, d2113, d2114, d2115, d2116, d2117, d2118, d2119, d2120, d2121, d2122, d2123, d2124, d2125, d2126, d2127, d2128, d2129, d2130, d2131, d2132, d2133, d2134, d2135, d2136, d2137, d2138, d2139, d2140, d2141, d2142, d2143, d2144, d2145, d2146, d2147, d2148, d2149, d2150, d2151, d2152, d2153, d2154, d2155, d2156, d2157, d2158, d2159, d2160, d2161, d2162, d2163, d2164, d2165, d2166, d2167, d2168, d2169, d2170, d2171, d2172, d2173, d2174, d2175, d2176, d2177, d2178, d2179, d2180, d2181, d2182, d2183, d2184, d2185, d2186, d2187, d2188, d2189, d2190, d2191, d2192, d2193, d2194, d2195, d2196, d2197, d2198, d2199, d2200, d2201, d2202, d2203, d2204, d2205, d2206, d2207, d2208, d2209, d2210, d2211, d2212, d2213, d2214, d2215, d2216, d2217, d2218, d2219, d2220, d2221, d2222, d2223, d2224, d2225, d2226, d2227, d2228, d2229, d2230, d2231, d2232, d2233, d2234, d2235, d2236, d2237, d2238, d2239, d2240, d2241, d2242, d2243, d2244, d2245, d2246, d2247, d2248, d2249, d2250, d2251, d2252, d2253, d2254, d2255, d2256, d2257, d2258, d2259, d2260, d2261, d2262, d2263, d2264, d2265, d2266, d2267, d2268, d2269, d2270, d2271, d2272, d2273, d2274, d2275, d2276, d2277, d2278, d2279, d2280, d2281, d2282, d2283, d2284, d2285, d2286, d2287, d2288, d2289, d2290, d2291, d2292, d2293, d2294, d2295, d2296, d2297, d2298, d2299, d2300, d2301, d2302, d2303, d2304, d2305, d2306, d2307, d2308, d2309, d2310, d2311, d2312, d2313, d2314, d2315, d2316, d2317, d2318, d2319, d2320, d2321, d2322, d2323, d2324, d2325, d2326, d2327, d2328, d2329, d2330, d2331, d2332, d2333, d2334, d2335, d2336, d2337, d2338, d2339, d2340, d2341, d2342, d2343, d2344, d2345, d2346, d2347, d2348, d2349, d2350, d2351, d2352, d2353, d2354, d2355, d2356, d2357, d2358, d2359, d2360, d2361, d2362, d2363, d2364, d2365, d2366, d2367, d2368, d2369, d2370, d2371, d2372, d2373, d2374, d2375, d2376, d2377, d2378, d2379, d2380, d2381, d2382, d2383, d2384, d2385, d2386, d2387, d2388, d2389, d2390, d2391, d2392, d2393, d2394, d2395, d2396, d2397, d2398, d2399, d2400, d2401, d2402, d2403, d2404, d2405, d2406, d2407, d2408, d2409, d2410, d2411, d2412, d2413, d2414, d2415, d2416, d2417, d2418, d2419, d2420, d2421, d2422, d2423, d2424, d2425, d2426, d2427, d2428, d2429, d2430, d2431, d2432, d2433, d2434, d2435, d2436, d2437, d2438, d2439, d2440, d2441, d2442, d2443, d2444, d2445, d2446, d2447, d2448, d2449, d2450, d2451, d2452, d2453, d2454, d2455, d2456, d2457, d2458, d2459, d2460, d2461, d2462, d2463, d2464, d2465, d2466, d2467, d2468, d2469, d2470, d2471, d2472, d2473, d2474, d2475, d2476, d2477, d2478, d2479, d2480, d2481, d2482, d2483, d2484, d2485, d2486, d2487, d2488, d2489, d2490, d2491, d2492, d2493, d2494, d2495, d2496, d2497, d2498, d2499, d2500, d2501, d2502, d2503, d2504, d2505, d2506, d2507, d2508, d2509, d2510, d2511, d2512, d2513, d2514, d2515, d2516, d2517, d2518, d2519, d2520, d2521, d2522, d2523, d2524, d2525, d2526, d2527, d2528, d2529, d2530, d2531, d2532, d2533, d2534, d2535, d2536, d2537, d2538, d2539, d2540, d2541, d2542, d2543, d2544, d2545, d2546, d2547, d2548, d2549, d2550, d2551, d2552, d2553, d2554, d2555, d2556, d2557, d2558, d2559, d2560, d2561, d2562, d2563, d2564, d2565, d2566, d2567, d2568, d2569, d2570, d2571, d2572, d2573, d2574, d2575, d2576, d2577, d2578, d2579, d2580, d2581, d2582, d2583, d2584, d2585, d2586, d2587, d2588, d2589, d2590, d2591, d2592, d2593, d2594, d2595, d2596, d2597, d2598, d2599, d2600, d2601, d2602, d2603, d2604, d2605, d2606, d2607, d2608, d2609, d2610, d2611, d2612, d2613, d2614, d2615, d2616, d2617, d2618, d2619, d2620, d2621, d2622, d2623, d2624, d2625, d2626, d2627, d2628, d2629, d2630, d2631, d2632, d2633, d2634, d2635, d2636, d2637, d2638, d2639, d2640, d2641, d2642, d2643, d2644, d2645, d2646, d2647, d2648, d2649, d2650, d2651, d2652, d2653, d2654, d2655, d2656, d2657, d2658, d2659, d2660, d2661, d2662, d2663, d2664, d2665, d2666, d2667, d2668, d2669, d2670, d2671, d2672, d2673, d2674, d2675, d2676, d2677, d2678, d2679, d2680, d2681, d2682, d2683, d2684, d2685, d2686, d2687, d2688, d2689, d2690, d2691, d2692, d2693, d2694, d2695, d2696, d2697, d2698, d2699, d2700, d2701, d2702, d2703, d2704, d2705, d2706, d2707, d2708, d2709, d2710, d2711, d2712, d2713, d2714, d2715, d2716, d2717, d2718, d2719, d2720, d2721, d2722, d2723, d2724, d2725, d2726, d2727, d2728, d2729, d2730, d2731, d2732, d2733, d2734, d2735, d2736, d2737, d2738, d2739, d2740, d2741, d2742, d2743, d2744, d2745, d2746, d2747, d2748, d2749, d2750, d2751, d2752, d2753, d2754, d2755, d2756, d2757, d2758, d2759, d2760, d2761, d2762, d2763, d2764, d2765, d2766, d2767, d2768, d2769, d2770, d2771, d2772, d2773, d2774, d2775, d2776, d2777, d2778, d2779, d2780, d2781, d2782, d2783, d2784, d2785, d2786, d2787, d2788, d2789, d2790, d2791, d2792, d2793, d2794, d2795, d2796, d2797, d2798, d2799, d2800, d2801, d2802, d2803, d2804, d2805, d2806, d2807, d2808, d2809, d2810, d2811, d2812, d2813, d2814, d2815, d2816, d2817, d2818, d2819, d2820, d2821, d2822, d2823, d2824, d2825, d2826, d2827, d2828, d2829, d2830, d2831, d2832, d2833, d2834, d2835, d2836, d2837, d2838, d2839, d2840, d2841, d2842, d2843, d2844, d2845, d2846, d2847, d2848, d2849, d2850, d2851, d2852, d2853, d2854, d2855, d2856, d2857, d2858, d2859, d2860, d2861, d2862, d2863, d2864, d2865, d2866, d2867, d2868, d2869, d2870, d2871, d2872, d2873, d2874, d2875, d2876, d2877, d2878, d2879, d2880, d2881, d2882, d2883, d2884, d2885, d2886, d2887, d2888, d2889, d2890, d2891, d2892, d2893, d2894, d2895, d2896, d2897, d2898, d2899, d2900, d2901, d2902, d2903, d2904, d2905, d2906, d2907, d2908, d2909, d2910, d2911, d2912, d2913, d2914, d2915, d2916, d2917, d2918, d2919, d2920, d2921, d2922, d2923, d2924, d2925, d2926, d2927, d2928, d2929, d2930, d2931, d2932, d2933, d2934, d2935, d2936, d2937, d2938, d2939, d2940, d2941, d2942, d2943, d2944, d2945, d2946, d2947, d2948, d2949, d2950, d2951, d2952, d2953, d2954, d2955, d2956, d2957, d2958, d2959, d2960, d2961, d2962, d2963, d2964, d2965, d2966, d2967, d2968, d2969, d2970, d2971, d2972, d2973, d2974, d2975, d2976, d2977, d2978, d2979, d2980, d2981, d2982, d2983, d2984, d2985, d2986, d2987, d2988, d2989, d2990, d2991, d2992, d2993, d2994, d2995, d2996, d2997, d2998, d2999, d3000, d3001, d3002, d3003, d3004, d3005, d3006, d3007, d3008, d3009, d3010, d3011, d3012, d3013, d3014, d3015, d3016, d3017, d3018, d3019, d3020, d3021, d3022, d3023, d3024, d3025, d3026, d3027, d3028, d3029, d3030, d3031, d3032, d3033, d3034, d3035, d3036, d3037, d3038, d3039, d3040, d3041, d3042, d3043, d3044, d3045, d3046, d3047, d3048, d3049, d3050, d3051, d3052, d3053, d3054, d3055, d3056, d3057, d3058, d3059, d3060, d3061, d3062, d3063, d3064, d3065, d3066, d3067, d3068, d3069, d3070, d3071, d3072, d3073, d3074, d3075, d3076, d3077, d3078, d3079, d3080, d3081, d3082, d3083, d3084, d3085, d3086, d3087, d3088, d3089, d3090, d3091, d3092, d3093, d3094, d3095, d3096, d3097, d3098, d3099, d3100, d3101, d3102, d3103, d3104, d3105, d3106, d3107, d3108, d3109, d3110, d3111, d3112, d3113, d3114, d3115, d3116, d3117, d3118, d3119, d3120, d3121, d3122, d3123, d3124, d3125, d3126, d3127, d3128, d3129, d3130, d3131, d3132, d3133, d3134, d3135, d3136, d3137, d3138, d3139, d3140, d3141, d3142, d3143, d3144, d3145, d3146, d3147, d3148, d3149, d3150, d3151, d3152, d3153, d3154, d3155, d3156, d3157, d3158, d3159, d3160, d3161, d3162, d3163, d3164, d3165, d3166, d3167, d3168, d3169, d3170, d3171, d3172, d3173, d3174, d3175, d3176, d3177, d3178, d3179, d3180, d3181, d3182, d3183, d3184, d3185, d3186, d3187, d3188, d3189, d3190, d3191, d3192, d3193, d3194, d3195, d3196, d3197, d3198, d3199, d3200, d3201, d3202, d3203, d3204, d3205, d3206, d3207, d3208, d3209, d3210, d3211, d3212, d3213, d3214, d3215, d3216, d3217, d3218, d3219, d3220, d3221, d3222, d3223, d3224, d3225, d3226, d3227, d3228, d3229, d3230, d3231, d3232, d3233, d3234, d3235, d3236, d3237, d3238, d3239, d3240, d3241, d3242, d3243, d3244, d3245, d3246, d3247, d3248, d3249, d3250, d3251, d3252, d3253, d3254, d3255, d3256, d3257, d3258, d3259, d3260, d3261, d3262, d3263, d3264, d3265, d3266, d3267, d3268, d3269, d3270, d3271, d3272, d3273, d3274, d3275, d3276, d3277, d3278, d3279, d3280, d3281, d3282, d3283, d3284, d3285, d3286, d3287, d3288, d3289, d3290, d3291, d3292, d3293, d3294, d3295, d3296, d3297, d3298, d3299, d3300, d3301, d3302, d3303, d3304, d3305, d3306, d3307, d3308, d3309, d3310, d3311, d3312, d3313, d3314, d3315, d3316, d3317, d3318, d3319, d3320, d3321, d3322, d3323, d3324, d3325, d3326, d3327, d3328, d3329, d3330, d3331, d3332, d3333, d3334, d3335, d3336, d3337, d3338, d3339, d3340, d3341, d3342, d3343, d3344, d3345, d3346, d3347, d3348, d3349, d3350, d3351, d3352, d3353, d3354, d3355, d3356, d3357, d3358, d3359, d3360, d3361, d3362, d3363, d3364, d3365, d3366, d3367, d3368, d3369, d3370, d3371, d3372, d3373, d3374, d3375, d3376, d3377, d3378, d3379, d3380, d3381, d3382, d3383, d3384, d3385, d3386, d3387, d3388, d3389, d3390, d3391, d3392, d3393, d3394, d3395, d3396, d3397, d3398, d3399, d3400, d3401, d3402, d3403, d3404, d3405, d3406, d3407, d3408, d3409, d3410, d3411, d3412, d3413, d3414, d3415, d3416, d3417, d3418, d3419, d3420, d3421, d3422, d3423, d3424, d3425, d3426, d3427, d3428, d3429, d3430, d3431, d3432, d3433, d3434, d3435, d3436, d3437, d3438, d3439, d3440, d3441, d3442, d3443, d3444, d3445, d3446, d3447, d3448, d3449, d3450, d3451, d3452, d3453, d3454, d3455, d3456, d3457, d3458, d3459, d3460, d3461, d3462, d3463, d3464, d3465, d3466, d3467, d3468, d3469, d3470, d3471, d3472, d3473, d3474, d3475, d3476, d3477, d3478, d3479, d3480, d3481, d3482, d3483, d3484, d3485, d3486, d3487, d3488, d3489, d3490, d3491, d3492, d3493, d3494, d3495, d3496, d3497, d3498, d3499, d3500, d3501, d3502, d3503, d3504, d3505, d3506, d3507, d3508, d3509, d3510, d3511, d3512, d3513, d3514, d3515, d3516, d3517, d3518, d3519, d3520, d3521, d3522, d3523, d3524, d3525, d3526, d3527, d3528, d3529, d3530, d3531, d3532, d3533, d3534, d3535, d3536, d3537, d3538, d3539, d3540, d3541, d3542, d3543, d3544, d3545, d3546, d3547, d3548, d3549, d3550, d3551, d3552, d3553, d3554, d3555, d3556, d3557, d3558, d3559, d3560, d3561, d3562, d3563, d3564, d3565, d3566, d3567, d3568, d3569, d3570, d3571, d3572, d3573, d3574, d3575, d3576, d3577, d3578, d3579, d3580, d3581, d3582, d3583, d3584, d3585, d3586, d3587, d3588, d3589, d3590, d3591, d3592, d3593, d3594, d3595, d3596, d3597, d3598, d3599, d3600, d3601, d3602, d3603, d3604, d3605, d3606, d3607, d3608, d3609, d3610, d3611, d3612, d3613, d3614, d3615, d3616, d3617, d3618, d3619, d3620, d3621, d3622, d3623, d3624, d3625, d3626, d3627, d3628, d3629, d3630, d3631, d3632, d3633, d3634, d3635, d3636, d3637, d3638, d3639, d3640, d3641, d3642, d3643, d3644, d3645, d3646, d3647, d3648, d3649, d3650, d3651, d3652, d3653, d3654, d3655, d3656, d3657, d3658, d3659, d3660, d3661, d3662, d3663, d3664, d3665, d3666, d3667, d3668, d3669, d3670, d3671, d3672, d3673, d3674, d3675, d3676, d3677, d3678, d3679, d3680, d3681, d3682, d3683, d3684, d3685, d3686, d3687, d3688, d3689, d3690, d3691, d3692, d3693, d3694, d3695, d3696, d3697, d3698, d3699, d3700, d3701, d3702, d3703, d3704, d3705, d3706, d3707, d3708, d3709, d3710, d3711, d3712, d3713, d3714, d3715, d3716, d3717, d3718, d3719, d3720, d3721, d3722, d3723, d3724, d3725, d3726, d3727, d3728, d3729, d3730, d3731, d3732, d3733, d3734, d3735, d3736, d3737, d3738, d3739, d3740, d3741, d3742, d3743, d3744, d3745, d3746, d3747, d3748, d3749, d3750, d3751, d3752, d3753, d3754, d3755, d3756, d3757, d3758, d3759, d3760, d3761, d3762, d3763, d3764, d3765, d3766, d3767, d3768, d3769, d3770, d3771, d3772, d3773, d3774, d3775, d3776, d3777, d3778, d3779, d3780, d3781, d3782, d3783, d3784, d3785, d3786, d3787, d3788, d3789, d3790, d3791, d3792, d3793, d3794, d3795, d3796, d3797, d3798, d3799, d3800, d3801, d3802, d3803, d3804, d3805, d3806, d3807, d3808, d3809, d3810, d3811, d3812, d3813, d3814, d3815, d3816, d3817, d3818, d3819, d3820, d3821, d3822, d3823, d3824, d3825, d3826, d3827, d3828, d3829, d3830, d3831, d3832, d3833, d3834, d3835, d3836, d3837, d3838, d3839, d3840, d3841, d3842, d3843, d3844, d3845, d3846, d3847, d3848, d3849, d3850, d3851, d3852, d3853, d3854, d3855, d3856, d3857, d3858, d3859, d3860, d3861, d3862, d3863, d3864, d3865, d3866, d3867, d3868, d3869, d3870, d3871, d3872, d3873, d3874, d3875, d3876, d3877, d3878, d3879, d3880, d3881, d3882, d3883, d3884, d3885, d3886, d3887, d3888, d3889, d3890, d3891, d3892, d3893, d3894, d3895, d3896, d3897, d3898, d3899, d3900, d3901, d3902, d3903, d3904, d3905, d3906, d3907, d3908, d3909, d3910, d3911, d3912, d3913, d3914, d3915, d3916, d3917, d3918, d3919, d3920, d3921, d3922, d3923, d3924, d3925, d3926, d3927, d3928, d3929, d3930, d3931, d3932, d3933, d3934, d3935, d3936, d3937, d3938, d3939, d3940, d3941, d3942, d3943, d3944, d3945, d3946, d3947, d3948, d3949, d3950, d3951, d3952, d3953, d3954, d3955, d3956, d3957, d3958, d3959, d3960, d3961, d3962, d3963, d3964, d3965, d3966, d3967, d3968, d3969, d3970, d3971, d3972, d3973, d3974, d3975, d3976, d3977, d3978, d3979, d3980, d3981, d3982, d3983, d3984, d3985, d3986, d3987, d3988, d3989, d3990, d3991, d3992, d3993, d3994, d3995, d3996, d3997, d3998, d3999, d4000, d4001, d4002, d4003, d4004, d4005, d4006, d4007, d4008, d4009, d4010, d4011, d4012, d4013, d4014, d4015, d4016, d4017, d4018, d4019, d4020, d4021, d4022, d4023, d4024, d4025, d4026, d4027, d4028, d4029, d4030, d4031, d4032, d4033, d4034, d4035, d4036, d4037, d4038, d4039, d4040, d4041, d4042, d4043, d4044, d4045, d4046, d4047, d4048, d4049, d4050, d4051, d4052, d4053, d4054, d4055, d4056, d4057, d4058, d4059, d4060, d4061, d4062, d4063, d4064, d4065, d4066, d4067, d4068, d4069, d4070, d4071, d4072, d4073, d4074, d4075, d4076, d4077, d4078, d4079, d4080, d4081, d4082, d4083, d4084, d4085, d4086, d4087, d4088, d4089, d4090, d4091, d4092, d4093, d4094, d4095, d4096, d4097, d4098, d4099, d4100, d4101, d4102, d4103, d4104, d4105, d4106, d4107, d4108, d4109, d4110, d4111, d4112, d4113, d4114, d4115, d4116, d4117, d4118, d4119, d4120, d4121, d4122, d4123, d4124, d4125, d4126, d4127, d4128, d4129, d4130, d4131, d4132, d4133, d4134, d4135, d4136, d4137, d4138, d4139, d4140, d4141, d4142, d4143, d4144, d4145, d4146, d4147, d4148, d4149, d4150, d4151, d4152, d4153, d4154, d4155, d4156, d4157, d4158, d4159, d4160, d4161, d4162, d4163, d4164, d4165, d4166, d4167, d4168, d4169, d4170, d4171, d4172, d4173, d4174, d4175, d4176, d4177, d4178, d4179, d4180, d4181, d4182, d4183, d4184, d4185, d4186, d4187, d4188, d4189, d4190, d4191, d4192, d4193, d4194, d4195, d4196, d4197, d4198, d4199, d4200, d4201, d4202, d4203, d4204, d4205, d4206, d4207, d4208, d4209, d4210, d4211, d4212, d4213, d4214, d4215, d4216, d4217, d4218, d4219, d4220, d4221, d4222, d4223, d4224, d4225, d4226, d4227, d4228, d4229, d4230, d4231, d4232, d4233, d4234, d4235, d4236, d4237, d4238, d4239, d4240, d4241, d4242, d4243, d4244, d4245, d4246, d4247, d4248, d4249, d4250, d4251, d4252, d4253, d4254, d4255, d4256, d4257, d4258, d4259, d4260, d4261, d4262, d4263, d4264, d4265, d4266, d4267, d4268, d4269, d4270, d4271, d4272, d4273, d4274, d4275, d4276, d4277, d4278, d4279, d4280, d4281, d4282, d4283, d4284, d4285, d4286, d4287, d4288, d4289, d4290, d4291, d4292, d4293, d4294, d4295, d4296, d4297, d4298, d4299, d4300, d4301, d4302, d4303, d4304, d4305, d4306, d4307, d4308, d4309, d4310, d4311, d4312, d4313, d4314, d4315, d4316, d4317, d4318, d4319, d4320, d4321, d4322, d4323, d4324, d4325, d4326, d4327, d4328, d4329, d4330, d4331, d4332, d4333, d4334, d4335, d4336, d4337, d4338, d4339, d4340, d4341, d4342, d4343, d4344, d4345, d4346, d4347, d4348, d4349, d4350, d4351, d4352, d4353, d4354, d4355, d4356, d4357, d4358, d4359, d4360, d4361, d4362, d4363, d4364, d4365, d4366, d4367, d4368, d4369, d4370, d4371, d4372, d4373, d4374, d4375, d4376, d4377, d4378, d4379, d4380, d4381, d4382, d4383, d4384, d4385, d4386, d4387, d4388, d4389, d4390, d4391, d4392, d4393, d4394, d4395, d4396, d4397, d4398, d4399, d4400, d4401, d4402, d4403, d4404, d4405, d4406, d4407, d4408, d4409, d4410, d4411, d4412, d4413, d4414, d4415, d4416, d4417, d4418, d4419, d4420, d4421, d4422, d4423, d4424, d4425, d4426, d4427, d4428, d4429, d4430, d4431, d4432, d4433, d4434, d4435, d4436, d4437, d4438, d4439, d4440, d4441, d4442, d4443, d4444, d4445, d4446, d4447, d4448, d4449, d4450, d4451, d4452, d4453, d4454, d4455, d4456, d4457, d4458, d4459, d4460, d4461, d4462, d4463, d4464, d4465, d4466, d4467, d4468, d4469, d4470, d4471, d4472, d4473, d4474, d4475, d4476, d4477, d4478, d4479, d4480, d4481, d4482, d4483, d4484, d4485, d4486, d4487, d4488, d4489, d4490, d4491, d4492, d4493, d4494, d4495, d4496, d4497, d4498, d4499, d4500, d4501, d4502, d4503, d4504, d4505, d4506, d4507, d4508, d4509, d4510, d4511, d4512, d4513, d4514, d4515, d4516, d4517, d4518, d4519, d4520, d4521, d4522, d4523, d4524, d4525, d4526, d4527, d4528, d4529, d4530, d4531, d4532, d4533, d4534, d4535, d4536, d4537, d4538, d4539, d4540, d4541, d4542, d4543, d4544, d4545, d4546, d4547, d4548, d4549, d4550, d4551, d4552, d4553, d4554, d4555, d4556, d4557, d4558, d4559, d4560, d4561, d4562, d4563, d4564, d4565, d4566, d4567, d4568, d4569, d4570, d4571, d4572, d4573, d4574, d4575, d4576, d4577, d4578, d4579, d4580, d4581, d4582, d4583, d4584, d4585, d4586, d4587, d4588, d4589, d4590, d4591, d4592, d4593, d4594, d4595, d4596, d4597, d4598, d4599, d4600, d4601, d4602, d4603, d4604, d4605, d4606, d4607, d4608, d4609, d4610, d4611, d4612, d4613, d4614, d4615, d4616, d4617, d4618, d4619, d4620, d4621, d4622, d4623, d4624, d4625, d4626, d4627, d4628, d4629, d4630, d4631, d4632, d4633, d4634, d4635, d4636, d4637, d4638, d4639, d4640, d4641, d4642, d4643, d4644, d4645, d4646, d4647, d4648, d4649, d4650, d4651, d4652, d4653, d4654, d4655, d4656, d4657, d4658, d4659, d4660, d4661, d4662, d4663, d4664, d4665, d4666, d4667, d4668, d4669, d4670, d4671, d4672, d4673, d4674, d4675, d4676, d4677, d4678, d4679, d4680, d4681, d4682, d4683, d4684, d4685, d4686, d4687, d4688, d4689, d4690, d4691, d4692, d4693, d4694, d4695, d4696, d4697, d4698, d4699, d4700, d4701, d4702, d4703, d4704, d4705, d4706, d4707, d4708, d4709, d4710, d4711, d4712, d4713, d4714, d4715, d4716, d4717, d4718, d4719, d4720, d4721, d4722, d4723, d4724, d4725, d4726, d4727, d4728, d4729, d4730, d4731, d4732, d4733, d4734, d4735, d4736, d4737, d4738, d4739, d4740, d4741, d4742, d4743, d4744, d4745, d4746, d4747, d4748, d4749, d4750, d4751, d4752, d4753, d4754, d4755, d4756, d4757, d4758, d4759, d4760, d4761, d4762, d4763, d4764, d4765, d4766, d4767, d4768, d4769, d4770, d4771, d4772, d4773, d4774, d4775, d4776, d4777, d4778, d4779, d4780, d4781, d4782, d4783, d4784, d4785, d4786, d4787, d4788, d4789, d4790, d4791, d4792, d4793, d4794, d4795, d4796, d4797, d4798, d4799, d4800, d4801, d4802, d4803, d4804, d4805, d4806, d4807, d4808, d4809, d4810, d4811, d4812, d4813, d4814, d4815, d4816, d4817, d4818, d4819, d4820, d4821, d4822, d4823, d4824, d4825, d4826, d4827, d4828, d4829, d4830, d4831, d4832, d4833, d4834, d4835, d4836, d4837, d4838, d4839, d4840, d4841, d4842, d4843, d4844, d4845, d4846, d4847, d4848, d4849, d4850, d4851, d4852, d4853, d4854, d4855, d4856, d4857, d4858, d4859, d4860, d4861, d4862, d4863, d4864, d4865, d4866, d4867, d4868, d4869, d4870, d4871, d4872, d4873, d4874, d4875, d4876, d4877, d4878, d4879, d4880, d4881, d4882, d4883, d4884, d4885, d4886, d4887, d4888, d4889, d4890, d4891, d4892, d4893, d4894, d4895, d4896, d4897, d4898, d4899, d4900, d4901, d4902, d4903, d4904, d4905, d4906, d4907, d4908, d4909, d4910, d4911, d4912, d4913, d4914, d4915, d4916, d4917, d4918, d4919, d4920, d4921, d4922, d4923, d4924, d4925, d4926, d4927, d4928, d4929, d4930, d4931, d4932, d4933, d4934, d4935, d4936, d4937, d4938, d4939, d4940, d4941, d4942, d4943, d4944, d4945, d4946, d4947, d4948, d4949, d4950, d4951, d4952, d4953, d4954, d4955, d4956, d4957, d4958, d4959, d4960, d4961, d4962, d4963, d4964, d4965, d4966, d4967, d4968, d4969, d4970, d4971, d4972, d4973, d4974, d4975, d4976, d4977, d4978, d4979, d4980, d4981, d4982, d4983, d4984, d4985, d4986, d4987, d4988, d4989, d4990, d4991, d4992, d4993, d4994, d4995, d4996, d4997, d4998, d4999, d5000, d5001, d5002, d5003, d5004, d5005, d5006, d5007, d5008, d5009, d5010, d5011, d5012, d5013, d5014, d5015, d5016, d5017, d5018, d5019, d5020, d5021, d5022, d5023, d5024, d5025, d5026, d5027, d5028, d5029, d5030, d5031, d5032, d5033, d5034, d5035, d5036, d5037, d5038, d5039, d5040, d5041, d5042, d5043, d5044, d5045, d5046, d5047, d5048, d5049, d5050, d5051, d5052, d5053, d5054, d5055, d5056, d5057, d5058, d5059, d5060, d5061, d5062, d5063, d5064, d5065, d5066, d5067, d5068, d5069, d5070, d5071, d5072, d5073, d5074, d5075, d5076, d5077, d5078, d5079, d5080, d5081, d5082, d5083, d5084, d5085, d5086, d5087, d5088, d5089, d5090, d5091, d5092, d5093, d5094, d5095, d5096, d5097, d5098, d5099, d5100, d5101, d5102, d5103, d5104, d5105, d5106, d5107, d5108, d5109, d5110, d5111, d5112, d5113, d5114, d5115, d5116, d5117, d5118, d5119, d5120, d5121, d5122, d5123, d5124, d5125, d5126, d5127, d5128, d5129, d5130, d5131, d5132, d5133, d5134, d5135, d5136, d5137, d5138, d5139, d5140, d5141, d5142, d5143, d5144, d5145, d5146, d5147, d5148, d5149, d5150, d5151, d5152, d5153, d5154, d5155, d5156, d5157, d5158, d5159, d5160, d5161, d5162, d5163, d5164, d5165, d5166, d5167, d5168, d5169, d5170, d5171, d5172, d5173, d5174, d5175, d5176, d5177, d5178, d5179, d5180, d5181, d5182, d5183, d5184, d5185, d5186, d5187, d5188, d5189, d5190, d5191, d5192, d5193, d5194, d5195, d5196, d5197, d5198, d5199, d5200, d5201, d5202, d5203, d5204, d5205, d5206, d5207, d5208, d5209, d5210, d5211, d5212, d5213, d5214, d5215, d5216, d5217, d5218, d5219, d5220, d5221, d5222, d5223, d5224, d5225, d5226, d5227, d5228, d5229, d5230, d5231, d5232, d5233, d5234, d5235, d5236, d5237, d5238, d5239, d5240, d5241, d5242, d5243, d5244, d5245, d5246, d5247, d5248, d5249, d5250, d5251, d5252, d5253, d5254, d5255, d5256, d5257, d5258, d5259, d5260, d5261, d5262, d5263, d5264, d5265, d5266, d5267, d5268, d5269, d5270, d5271, d5272, d5273, d5274, d5275, d5276, d5277, d5278, d5279, d5280, d5281, d5282, d5283, d5284, d5285, d5286, d5287, d5288, d5289, d5290, d5291, d5292, d5293, d5294, d5295, d5296, d5297, d5298, d5299, d5300, d5301, d5302, d5303, d5304, d5305, d5306, d5307, d5308, d5309, d5310, d5311, d5312, d5313, d5314, d5315, d5316, d5317, d5318, d5319, d5320, d5321, d5322, d5323, d5324, d5325, d5326, d5327, d5328, d5329, d5330, d5331, d5332, d5333, d5334, d5335, d5336, d5337, d5338, d5339, d5340, d5341, d5342, d5343, d5344, d5345, d5346, d5347, d5348, d5349, d5350, d5351, d5352, d5353, d5354, d5355, d5356, d5357, d5358, d5359, d5360, d5361, d5362, d5363, d5364, d5365, d5366, d5367, d5368, d5369, d5370, d5371, d5372, d5373, d5374, d5375, d5376, d5377, d5378, d5379, d5380, d5381, d5382, d5383, d5384, d5385, d5386, d5387, d5388, d5389, d5390, d5391, d5392, d5393, d5394, d5395, d5396, d5397, d5398, d5399, d5400, d5401, d5402, d5403, d5404, d5405, d5406, d5407, d5408, d5409, d5410, d5411, d5412, d5413, d5414, d5415, d5416, d5417, d5418, d5419, d5420, d5421, d5422, d5423, d5424, d5425, d5426, d5427, d5428, d5429, d5430, d5431, d5432, d5433, d5434, d5435, d5436, d5437, d5438, d5439, d5440, d5441, d5442, d5443, d5444, d5445, d5446, d5447, d5448, d5449, d5450, d5451, d5452, d5453, d5454, d5455, d5456, d5457, d5458, d5459, d5460, d5461, d5462, d5463, d5464, d5465, d5466, d5467, d5468, d5469, d5470, d5471, d5472, d5473, d5474, d5475, d5476, d5477, d5478, d5479, d5480, d5481, d5482, d5483, d5484, d5485, d5486, d5487, d5488, d5489, d5490, d5491, d5492, d5493, d5494, d5495, d5496, d5497, d5498, d5499, d5500, d5501, d5502, d5503, d5504, d5505, d5506, d5507, d5508, d5509, d5510, d5511, d5512, d5513, d5514, d5515, d5516, d5517, d5518, d5519, d5520, d5521, d5522, d5523, d5524, d5525, d5526, d5527, d5528, d5529, d5530, d5531, d5532, d5533, d5534, d5535, d5536, d5537, d5538, d5539, d5540, d5541, d5542, d5543, d5544, d5545, d5546, d5547, d5548, d5549, d5550, d5551, d5552, d5553, d5554, d5555, d5556, d5557, d5558, d5559, d5560, d5561, d5562, d5563, d5564, d5565, d5566, d5567, d5568, d5569, d5570, d5571, d5572, d5573, d5574, d5575, d5576, d5577, d5578, d5579, d5580, d5581, d5582, d5583, d5584, d5585, d5586, d5587, d5588, d5589, d5590, d5591, d5592, d5593, d5594, d5595, d5596, d5597, d5598, d5599, d5600, d5601, d5602, d5603, d5604, d5605, d5606, d5607, d5608, d5609, d5610, d5611, d5612, d5613, d5614, d5615, d5616, d5617, d5618, d5619, d5620, d5621, d5622, d5623, d5624, d5625, d5626, d5627, d5628, d5629, d5630, d5631, d5632, d5633, d5634, d5635, d5636, d5637, d5638, d5639, d5640, d5641, d5642, d5643, d5644, d5645, d5646, d5647, d5648, d5649, d5650, d5651, d5652, d5653, d5654, d5655, d5656, d5657, d5658, d5659, d5660, d5661, d5662, d5663, d5664, d5665, d5666, d5667, d5668, d5669, d5670, d5671, d5672, d5673, d5674, d5675, d5676, d5677, d5678, d5679, d5680, d5681, d5682, d5683, d5684, d5685, d5686, d5687, d5688, d5689, d5690, d5691, d5692, d5693, d5694, d5695, d5696, d5697, d5698, d5699, d5700, d5701, d5702, d5703, d5704, d5705, d5706, d5707, d5708, d5709, d5710, d5711, d5712, d5713, d5714, d5715, d5716, d5717, d5718, d5719, d5720, d5721, d5722, d5723, d5724, d5725, d5726, d5727, d5728, d5729, d5730, d5731, d5732, d5733, d5734, d5735, d5736, d5737, d5738, d5739, d5740, d5741, d5742, d5743, d5744, d5745, d5746, d5747, d5748, d5749, d5750, d5751, d5752, d5753, d5754, d5755, d5756, d5757, d5758, d5759, d5760, d5761, d5762, d5763, d5764, d5765, d5766, d5767, d5768, d5769, d5770, d5771, d5772, d5773, d5774, d5775, d5776, d5777, d5778, d5779, d5780, d5781, d5782, d5783, d5784, d5785, d5786, d5787, d5788, d5789, d5790, d5791, d5792, d5793, d5794, d5795, d5796, d5797, d5798, d5799, d5800, d5801, d5802, d5803, d5804, d5805, d5806, d5807, d5808, d5809, d5810, d5811, d5812, d5813, d5814, d5815, d5816, d5817, d5818, d5819, d5820, d5821, d5822, d5823, d5824, d5825, d5826, d5827, d5828, d5829, d5830, d5831, d5832, d5833, d5834, d5835, d5836, d5837, d5838, d5839, d5840, d5841, d5842, d5843, d5844, d5845, d5846, d5847, d5848, d5849, d5850, d5851, d5852, d5853, d5854, d5855, d5856, d5857, d5858, d5859, d5860, d5861, d5862, d5863, d5864, d5865, d5866, d5867, d5868, d5869, d5870, d5871, d5872, d5873, d5874, d5875, d5876, d5877, d5878, d5879, d5880, d5881, d5882, d5883, d5884, d5885, d5886, d5887, d5888, d5889, d5890, d5891, d5892, d5893, d5894, d5895, d5896, d5897, d5898, d5899, d5900, d5901, d5902, d5903, d5904, d5905, d5906, d5907, d5908, d5909, d5910, d5911, d5912, d5913, d5914, d5915, d5916, d5917, d5918, d5919, d5920, d5921, d5922, d5923, d5924, d5925, d5926, d5927, d5928, d5929, d5930, d5931, d5932, d5933, d5934, d5935, d5936, d5937, d5938, d5939, d5940, d5941, d5942, d5943, d5944, d5945, d5946, d5947, d5948, d5949, d5950, d5951, d5952, d5953, d5954, d5955, d5956, d5957, d5958, d5959, d5960, d5961, d5962, d5963, d5964, d5965, d5966, d5967, d5968, d5969, d5970, d5971, d5972, d5973, d5974, d5975, d5976, d5977, d5978, d5979, d5980, d5981, d5982, d5983, d5984, d5985, d5986, d5987, d5988, d5989, d5990, d5991, d5992, d5993, d5994, d5995, d5996, d5997, d5998, d5999, d6000, d6001, d6002, d6003, d6004, d6005, d6006, d6007, d6008, d6009, d6010, d6011, d6012, d6013, d6014, d6015, d6016, d6017, d6018, d6019, d6020, d6021, d6022, d6023, d6024, d6025, d6026, d6027, d6028, d6029, d6030, d6031, d6032, d6033, d6034, d6035, d6036, d6037, d6038, d6039, d6040, d6041, d6042, d6043, d6044, d6045, d6046, d6047, d6048, d6049, d6050, d6051, d6052, d6053, d6054, d6055, d6056, d6057, d6058, d6059, d6060, d6061, d6062, d6063, d6064, d6065, d6066, d6067, d6068, d6069, d6070, d6071, d6072, d6073, d6074, d6075, d6076, d6077, d6078, d6079, d6080, d6081, d6082, d6083, d6084, d6085, d6086, d6087, d6088, d6089, d6090, d6091, d6092, d6093, d6094, d6095, d6096, d6097, d6098, d6099, d6100, d6101, d6102, d6103, d6104, d6105, d6106, d6107, d6108, d6109, d6110, d6111, d6112, d6113, d6114, d6115, d6116, d6117, d6118, d6119, d6120, d6121, d6122, d6123, d6124, d6125, d6126, d6127, d6128, d6129, d6130, d6131, d6132, d6133, d6134, d6135, d6136, d6137, d6138, d6139, d6140, d6141, d6142, d6143, d6144, d6145, d6146, d6147, d6148, d6149, d6150, d6151, d6152, d6153, d6154, d6155, d6156, d6157, d6158, d6159, d6160, d6161, d6162, d6163, d6164, d6165, d6166, d6167, d6168, d6169, d6170, d6171, d6172, d6173, d6174, d6175, d6176, d6177, d6178, d6179, d6180, d6181, d6182, d6183, d6184, d6185, d6186, d6187, d6188, d6189, d6190, d6191, d6192, d6193, d6194, d6195, d6196, d6197, d6198, d6199, d6200, d6201, d6202, d6203, d6204, d6205, d6206, d6207, d6208, d6209, d6210, d6211, d6212, d6213, d6214, d6215, d6216, d6217, d6218, d6219, d6220, d6221, d6222, d6223, d6224, d6225, d6226, d6227, d6228, d6229, d6230, d6231, d6232, d6233, d6234, d6235, d6236, d6237, d6238, d6239, d6240, d6241, d6242, d6243, d6244, d6245, d6246, d6247, d6248, d6249, d6250, d6251, d6252, d6253, d6254, d6255, d6256, d6257, d6258, d6259, d6260, d6261, d6262, d6263, d6264, d6265, d6266, d6267, d6268, d6269, d6270, d6271, d6272, d6273, d6274, d6275, d6276, d6277, d6278, d6279, d6280, d6281, d6282, d6283, d6284, d6285, d6286, d6287, d6288, d6289, d6290, d6291, d6292, d6293, d6294, d6295, d6296, d6297, d6298, d6299, d6300, d6301, d6302, d6303, d6304, d6305, d6306, d6307, d6308, d6309, d6310, d6311, d6312, d6313, d6314, d6315, d6316, d6317, d6318, d6319, d6320, d6321, d6322, d6323, d6324, d6325, d6326, d6327, d6328, d6329, d6330, d6331, d6332, d6333, d6334, d6335, d6336, d6337, d6338, d6339, d6340, d6341, d6342, d6343, d6344, d6345, d6346, d6347, d6348, d6349, d6350, d6351, d6352, d6353, d6354, d6355, d6356, d6357, d6358, d6359, d6360, d6361, d6362, d6363, d6364, d6365, d6366, d6367, d6368, d6369, d6370, d6371, d6372, d6373, d6374, d6375, d6376, d6377, d6378, d6379, d6380, d6381, d6382, d6383, d6384, d6385, d6386, d6387, d6388, d6389, d6390, d6391, d6392, d6393, d6394, d6395, d6396, d6397, d6398, d6399, d6400, d6401, d6402, d6403, d6404, d6405, d6406, d6407, d6408, d6409, d6410, d6411, d6412, d6413, d6414, d6415, d6416, d6417, d6418, d6419, d6420, d6421, d6422, d6423, d6424, d6425, d6426, d6427, d6428, d6429, d6430, d6431, d6432, d6433, d6434, d6435, d6436, d6437, d6438, d6439, d6440, d6441, d6442, d6443, d6444, d6445, d6446, d6447, d6448, d6449, d6450, d6451, d6452, d6453, d6454, d6455, d6456, d6457, d6458, d6459, d6460, d6461, d6462, d6463, d6464, d6465, d6466, d6467, d6468, d6469, d6470, d6471, d6472, d6473, d6474, d6475, d6476, d6477, d6478, d6479, d6480, d6481, d6482, d6483, d6484, d6485, d6486, d6487, d6488, d6489, d6490, d6491, d6492, d6493, d6494, d6495, d6496, d6497, d6498, d6499, d6500, d6501, d6502, d6503, d6504, d6505, d6506, d6507, d6508, d6509, d6510, d6511, d6512, d6513, d6514, d6515, d6516, d6517, d6518, d6519, d6520, d6521, d6522, d6523, d6524, d6525, d6526, d6527, d6528, d6529, d6530, d6531, d6532, d6533, d6534, d6535, d6536, d6537, d6538, d6539, d6540, d6541, d6542, d6543, d6544, d6545, d6546, d6547, d6548, d6549, d6550, d6551, d6552, d6553, d6554, d6555, d6556, d6557, d6558, d6559, d6560, d6561, d6562, d6563, d6564, d6565, d6566, d6567, d6568, d6569, d6570, d6571, d6572, d6573, d6574, d6575, d6576, d6577, d6578, d6579, d6580, d6581, d6582, d6583, d6584, d6585, d6586, d6587, d6588, d6589, d6590, d6591, d6592, d6593, d6594, d6595, d6596, d6597, d6598, d6599, d6600, d6601, d6602, d6603, d6604, d6605, d6606, d6607, d6608, d6609, d6610, d6611, d6612, d6613, d6614, d6615, d6616, d6617, d6618, d6619, d6620, d6621, d6622, d6623, d6624, d6625, d6626, d6627, d6628, d6629, d6630, d6631, d6632, d6633, d6634, d6635, d6636, d6637, d6638, d6639, d6640, d6641, d6642, d6643, d6644, d6645, d6646, d6647, d6648, d6649, d6650, d6651, d6652, d6653, d6654, d6655, d6656, d6657, d6658, d6659, d6660, d6661, d6662, d6663, d6664, d6665, d6666, d6667, d6668, d6669, d6670, d6671, d6672, d6673, d6674, d6675, d6676, d6677, d6678, d6679, d6680, d6681, d6682, d6683, d6684, d6685, d6686, d6687, d6688, d6689, d6690, d6691, d6692, d6693, d6694, d6695, d6696, d6697, d6698, d6699, d6700, d6701, d6702, d6703, d6704, d6705, d6706, d6707, d6708, d6709, d6710, d6711, d6712, d6713, d6714, d6715, d6716, d6717, d6718, d6719, d6720, d6721, d6722, d6723, d6724, d6725, d6726, d6727, d6728, d6729, d6730, d6731, d6732, d6733, d6734, d6735, d6736, d6737, d6738, d6739, d6740, d6741, d6742, d6743, d6744, d6745, d6746, d6747, d6748, d6749, d6750, d6751, d6752, d6753, d6754, d6755, d6756, d6757, d6758, d6759, d6760, d6761, d6762, d6763, d6764, d6765, d6766, d6767, d6768, d6769, d6770, d6771, d6772, d6773, d6774, d6775, d6776, d6777, d6778, d6779, d6780, d6781, d6782, d6783, d6784, d6785, d6786, d6787, d6788, d6789, d6790, d6791, d6792, d6793, d6794, d6795, d6796, d6797, d6798, d6799, d6800, d6801, d6802, d6803, d6804, d6805, d6806, d6807, d6808, d6809, d6810, d6811, d6812, d6813, d6814, d6815, d6816, d6817, d6818, d6819, d6820, d6821, d6822, d6823, d6824, d6825, d6826, d6827, d6828, d6829, d6830, d6831, d6832, d6833, d6834, d6835, d6836, d6837, d6838, d6839, d6840, d6841, d6842, d6843, d6844, d6845, d6846, d6847, d6848, d6849, d6850, d6851, d6852, d6853, d6854, d6855, d6856, d6857, d6858, d6859, d6860, d6861, d6862, d6863, d6864, d6865, d6866, d6867, d6868, d6869, d6870, d6871, d6872, d6873, d6874, d6875, d6876, d6877, d6878, d6879, d6880, d6881, d6882, d6883, d6884, d6885, d6886, d6887, d6888, d6889, d6890, d6891, d6892, d6893, d6894, d6895, d6896, d6897, d6898, d6899, d6900, d6901, d6902, d6903, d6904, d6905, d6906, d6907, d6908, d6909, d6910, d6911, d6912, d6913, d6914, d6915, d6916, d6917, d6918, d6919, d6920, d6921, d6922, d6923, d6924, d6925, d6926, d6927, d6928, d6929, d6930, d6931, d6932, d6933, d6934, d6935, d6936, d6937, d6938, d6939, d6940, d6941, d6942, d6943, d6944, d6945, d6946, d6947, d6948, d6949, d6950, d6951, d6952, d6953, d6954, d6955, d6956, d6957, d6958, d6959, d6960, d6961, d6962, d6963, d6964, d6965, d6966, d6967, d6968, d6969, d6970, d6971, d6972, d6973, d6974, d6975, d6976, d6977, d6978, d6979, d6980, d6981, d6982, d6983, d6984, d6985, d6986, d6987, d6988, d6989, d6990, d6991, d6992, d6993, d6994, d6995, d6996, d6997, d6998, d6999, d7000, d7001, d7002, d7003, d7004, d7005, d7006, d7007, d7008, d7009, d7010, d7011, d7012, d7013, d7014, d7015, d7016, d7017, d7018, d7019, d7020, d7021, d7022, d7023, d7024, d7025, d7026, d7027, d7028, d7029, d7030, d7031, d7032, d7033, d7034, d7035, d7036, d7037, d7038, d7039, d7040, d7041, d7042, d7043, d7044, d7045, d7046, d7047, d7048, d7049, d7050, d7051, d7052, d7053, d7054, d7055, d7056, d7057, d7058, d7059, d7060, d7061, d7062, d7063, d7064, d7065, d7066, d7067, d7068, d7069, d7070, d7071, d7072, d7073, d7074, d7075, d7076, d7077, d7078, d7079, d7080, d7081, d7082, d7083, d7084, d7085, d7086, d7087, d7088, d7089, d7090, d7091, d7092, d7093, d7094, d7095, d7096, d7097, d7098, d7099, d7100, d7101, d7102, d7103, d7104, d7105, d7106, d7107, d7108, d7109, d7110, d7111, d7112, d7113, d7114, d7115, d7116, d7117, d7118, d7119, d7120, d7121, d7122, d7123, d7124, d7125, d7126, d7127, d7128, d7129, d7130, d7131, d7132, d7133, d7134, d7135, d7136, d7137, d7138, d7139, d7140, d7141, d7142, d7143, d7144, d7145, d7146, d7147, d7148, d7149, d7150, d7151, d7152, d7153, d7154, d7155, d7156, d7157, d7158, d7159, d7160, d7161, d7162, d7163, d7164, d7165, d7166, d7167, d7168, d7169, d7170, d7171, d7172, d7173, d7174, d7175, d7176, d7177, d7178, d7179, d7180, d7181, d7182, d7183, d7184, d7185, d7186, d7187, d7188, d7189, d7190, d7191, d7192, d7193, d7194, d7195, d7196, d7197, d7198, d7199, d7200, d7201, d7202, d7203, d7204, d7205, d7206, d7207, d7208, d7209, d7210, d7211, d7212, d7213, d7214, d7215, d7216, d7217, d7218, d7219, d7220, d7221, d7222, d7223, d7224, d7225, d7226, d7227, d7228, d7229, d7230, d7231, d7232, d7233, d7234, d7235, d7236, d7237, d7238, d7239, d7240, d7241, d7242, d7243, d7244, d7245, d7246, d7247, d7248, d7249, d7250, d7251, d7252, d7253, d7254, d7255, d7256, d7257, d7258, d7259, d7260, d7261, d7262, d7263, d7264, d7265, d7266, d7267, d7268, d7269, d7270, d7271, d7272, d7273, d7274, d7275, d7276, d7277, d7278, d7279, d7280, d7281, d7282, d7283, d7284, d7285, d7286, d7287, d7288, d7289, d7290, d7291, d7292, d7293, d7294, d7295, d7296, d7297, d7298, d7299, d7300, d7301, d7302, d7303, d7304, d7305, d7306, d7307, d7308, d7309, d7310, d7311, d7312, d7313, d7314, d7315, d7316, d7317, d7318, d7319, d7320, d7321, d7322, d7323, d7324, d7325, d7326, d7327, d7328, d7329, d7330, d7331, d7332, d7333, d7334, d7335, d7336, d7337, d7338, d7339, d7340, d7341, d7342, d7343, d7344, d7345, d7346, d7347, d7348, d7349, d7350, d7351, d7352, d7353, d7354, d7355, d7356, d7357, d7358, d7359, d7360, d7361, d7362, d7363, d7364, d7365, d7366, d7367, d7368, d7369, d7370, d7371, d7372, d7373, d7374, d7375, d7376, d7377, d7378, d7379, d7380, d7381, d7382, d7383, d7384, d7385, d7386, d7387, d7388, d7389, d7390, d7391, d7392, d7393, d7394, d7395, d7396, d7397, d7398, d7399, d7400, d7401, d7402, d7403, d7404, d7405, d7406, d7407, d7408, d7409, d7410, d7411, d7412, d7413, d7414, d7415, d7416, d7417, d7418, d7419, d7420, d7421, d7422, d7423, d7424, d7425, d7426, d7427, d7428, d7429, d7430, d7431, d7432, d7433, d7434, d7435, d7436, d7437, d7438, d7439, d7440, d7441, d7442, d7443, d7444, d7445, d7446, d7447, d7448, d7449, d7450, d7451, d7452, d7453, d7454, d7455, d7456, d7457, d7458, d7459, d7460, d7461, d7462, d7463, d7464, d7465, d7466, d7467, d7468, d7469, d7470, d7471, d7472, d7473, d7474, d7475, d7476, d7477, d7478, d7479, d7480, d7481, d7482, d7483, d7484, d7485, d7486, d7487, d7488, d7489, d7490, d7491, d7492, d7493, d7494, d7495, d7496, d7497, d7498, d7499, d7500, d7501, d7502, d7503, d7504, d7505, d7506, d7507, d7508, d7509, d7510, d7511, d7512, d7513, d7514, d7515, d7516, d7517, d7518, d7519, d7520, d7521, d7522, d7523, d7524, d7525, d7526, d7527, d7528, d7529, d7530, d7531, d7532, d7533, d7534, d7535, d7536, d7537, d7538, d7539, d7540, d7541, d7542, d7543, d7544, d7545, d7546, d7547, d7548, d7549, d7550, d7551, d7552, d7553, d7554, d7555, d7556, d7557, d7558, d7559, d7560, d7561, d7562, d7563, d7564, d7565, d7566, d7567, d7568, d7569, d7570, d7571, d7572, d7573, d7574, d7575, d7576, d7577, d7578, d7579, d7580, d7581, d7582, d7583, d7584, d7585, d7586, d7587, d7588, d7589, d7590, d7591, d7592, d7593, d7594, d7595, d7596, d7597, d7598, d7599, d7600, d7601, d7602, d7603, d7604, d7605, d7606, d7607, d7608, d7609, d7610, d7611, d7612, d7613, d7614, d7615, d7616, d7617, d7618, d7619, d7620, d7621, d7622, d7623, d7624, d7625, d7626, d7627, d7628, d7629, d7630, d7631, d7632, d7633, d7634, d7635, d7636, d7637, d7638, d7639, d7640, d7641, d7642, d7643, d7644, d7645, d7646, d7647, d7648, d7649, d7650, d7651, d7652, d7653, d7654, d7655, d7656, d7657, d7658, d7659, d7660, d7661, d7662, d7663, d7664, d7665, d7666, d7667, d7668, d7669, d7670, d7671, d7672, d7673, d7674, d7675, d7676, d7677, d7678, d7679, d7680, d7681, d7682, d7683, d7684, d7685, d7686, d7687, d7688, d7689, d7690, d7691, d7692, d7693, d7694, d7695, d7696, d7697, d7698, d7699, d7700, d7701, d7702, d7703, d7704, d7705, d7706, d7707, d7708, d7709, d7710, d7711, d7712, d7713, d7714, d7715, d7716, d7717, d7718, d7719, d7720, d7721, d7722, d7723, d7724, d7725, d7726, d7727, d7728, d7729, d7730, d7731, d7732, d7733, d7734, d7735, d7736, d7737, d7738, d7739, d7740, d7741, d7742, d7743, d7744, d7745, d7746, d7747, d7748, d7749, d7750, d7751, d7752, d7753, d7754, d7755, d7756, d7757, d7758, d7759, d7760, d7761, d7762, d7763, d7764, d7765, d7766, d7767, d7768, d7769, d7770, d7771, d7772, d7773, d7774, d7775, d7776, d7777, d7778, d7779, d7780, d7781, d7782, d7783, d7784, d7785, d7786, d7787, d7788, d7789, d7790, d7791, d7792, d7793, d7794, d7795, d7796, d7797, d7798, d7799, d7800, d7801, d7802, d7803, d7804, d7805, d7806, d7807, d7808, d7809, d7810, d7811, d7812, d7813, d7814, d7815, d7816, d7817, d7818, d7819, d7820, d7821, d7822, d7823, d7824, d7825, d7826, d7827, d7828, d7829, d7830, d7831, d7832, d7833, d7834, d7835, d7836, d7837, d7838, d7839, d7840, d7841, d7842, d7843, d7844, d7845, d7846, d7847, d7848, d7849, d7850, d7851, d7852, d7853, d7854, d7855, d7856, d7857, d7858, d7859, d7860, d7861, d7862, d7863, d7864, d7865, d7866, d7867, d7868, d7869, d7870, d7871, d7872, d7873, d7874, d7875, d7876, d7877, d7878, d7879, d7880, d7881, d7882, d7883, d7884, d7885, d7886, d7887, d7888, d7889, d7890, d7891, d7892, d7893, d7894, d7895, d7896, d7897, d7898, d7899, d7900, d7901, d7902, d7903, d7904, d7905, d7906, d7907, d7908, d7909, d7910, d7911, d7912, d7913, d7914, d7915, d7916, d7917, d7918, d7919, d7920, d7921, d7922, d7923, d7924, d7925, d7926, d7927, d7928, d7929, d7930, d7931, d7932, d7933, d7934, d7935, d7936, d7937, d7938, d7939, d7940, d7941, d7942, d7943, d7944, d7945, d7946, d7947, d7948, d7949, d7950, d7951, d7952, d7953, d7954, d7955, d7956, d7957, d7958, d7959, d7960, d7961, d7962, d7963, d7964, d7965, d7966, d7967, d7968, d7969, d7970, d7971, d7972, d7973, d7974, d7975, d7976, d7977, d7978, d7979, d7980, d7981, d7982, d7983, d7984, d7985, d7986, d7987, d7988, d7989, d7990, d7991, d7992, d7993, d7994, d7995, d7996, d7997, d7998, d7999, d8000, d8001, d8002, d8003, d8004, d8005, d8006, d8007, d8008, d8009, d8010, d8011, d8012, d8013, d8014, d8015, d8016, d8017, d8018, d8019, d8020, d8021, d8022, d8023, d8024, d8025, d8026, d8027, d8028, d8029, d8030, d8031, d8032, d8033, d8034, d8035, d8036, d8037, d8038, d8039, d8040, d8041, d8042, d8043, d8044, d8045, d8046, d8047, d8048, d8049, d8050, d8051, d8052, d8053, d8054, d8055, d8056, d8057, d8058, d8059, d8060, d8061, d8062, d8063, d8064, d8065, d8066, d8067, d8068, d8069, d8070, d8071, d8072, d8073, d8074, d8075, d8076, d8077, d8078, d8079, d8080, d8081, d8082, d8083, d8084, d8085, d8086, d8087, d8088, d8089, d8090, d8091, d8092, d8093, d8094, d8095, d8096, d8097, d8098, d8099, d8100, d8101, d8102, d8103, d8104, d8105, d8106, d8107, d8108, d8109, d8110, d8111, d8112, d8113, d8114, d8115, d8116, d8117, d8118, d8119, d8120, d8121, d8122, d8123, d8124, d8125, d8126, d8127, d8128, d8129, d8130, d8131, d8132, d8133, d8134, d8135, d8136, d8137, d8138, d8139, d8140, d8141, d8142, d8143, d8144, d8145, d8146, d8147, d8148, d8149, d8150, d8151, d8152, d8153, d8154, d8155, d8156, d8157, d8158, d8159, d8160, d8161, d8162, d8163, d8164, d8165, d8166, d8167, d8168, d8169, d8170, d8171, d8172, d8173, d8174, d8175, d8176, d8177, d8178, d8179, d8180, d8181, d8182, d8183, d8184, d8185, d8186, d8187, d8188, d8189, d8190, d8191, d8192, d8193, d8194, d8195, d8196, d8197, d8198, d8199, d8200, d8201, d8202, d8203, d8204, d8205, d8206, d8207, d8208, d8209, d8210, d8211, d8212, d8213, d8214, d8215, d8216, d8217, d8218, d8219, d8220, d8221, d8222, d8223, d8224, d8225, d8226, d8227, d8228, d8229, d8230, d8231, d8232, d8233, d8234, d8235, d8236, d8237, d8238, d8239, d8240, d8241, d8242, d8243, d8244, d8245, d8246, d8247, d8248, d8249, d8250, d8251, d8252, d8253, d8254, d8255, d8256, d8257, d8258, d8259, d8260, d8261, d8262, d8263, d8264, d8265, d8266, d8267, d8268, d8269, d8270, d8271, d8272, d8273, d8274, d8275, d8276, d8277, d8278, d8279, d8280, d8281, d8282, d8283, d8284, d8285, d8286, d8287, d8288, d8289, d8290, d8291, d8292, d8293, d8294, d8295, d8296, d8297, d8298, d8299, d8300, d8301, d8302, d8303, d8304, d8305, d8306, d8307, d8308, d8309, d8310, d8311, d8312, d8313, d8314, d8315, d8316, d8317, d8318, d8319, d8320, d8321, d8322, d8323, d8324, d8325, d8326, d8327, d8328, d8329, d8330, d8331, d8332, d8333, d8334, d8335, d8336, d8337, d8338, d8339, d8340, d8341, d8342, d8343, d8344, d8345, d8346, d8347, d8348, d8349, d8350, d8351, d8352, d8353, d8354, d8355, d8356, d8357, d8358, d8359, d8360, d8361, d8362, d8363, d8364, d8365, d8366, d8367, d8368, d8369, d8370, d8371, d8372, d8373, d8374, d8375, d8376, d8377, d8378, d8379, d8380, d8381, d8382, d8383, d8384, d8385, d8386, d8387, d8388, d8389, d8390, d8391, d8392, d8393, d8394, d8395, d8396, d8397, d8398, d8399, d8400, d8401, d8402, d8403, d8404, d8405, d8406, d8407, d8408, d8409, d8410, d8411, d8412, d8413, d8414, d8415, d8416, d8417, d8418, d8419, d8420, d8421, d8422, d8423, d8424, d8425, d8426, d8427, d8428, d8429, d8430, d8431, d8432, d8433, d8434, d8435, d8436, d8437, d8438, d8439, d8440, d8441, d8442, d8443, d8444, d8445, d8446, d8447, d8448, d8449, d8450, d8451, d8452, d8453, d8454, d8455, d8456, d8457, d8458, d8459, d8460, d8461, d8462, d8463, d8464, d8465, d8466, d8467, d8468, d8469, d8470, d8471, d8472, d8473, d8474, d8475, d8476, d8477, d8478, d8479, d8480, d8481, d8482, d8483, d8484, d8485, d8486, d8487, d8488, d8489, d8490, d8491, d8492, d8493, d8494, d8495, d8496, d8497, d8498, d8499, d8500, d8501, d8502, d8503, d8504, d8505, d8506, d8507, d8508, d8509, d8510, d8511, d8512, d8513, d8514, d8515, d8516, d8517, d8518, d8519, d8520, d8521, d8522, d8523, d8524, d8525, d8526, d8527, d8528, d8529, d8530, d8531, d8532, d8533, d8534, d8535, d8536, d8537, d8538, d8539, d8540, d8541, d8542, d8543, d8544, d8545, d8546, d8547, d8548, d8549, d8550, d8551, d8552, d8553, d8554, d8555, d8556, d8557, d8558, d8559, d8560, d8561, d8562, d8563, d8564, d8565, d8566, d8567, d8568, d8569, d8570, d8571, d8572, d8573, d8574, d8575, d8576, d8577, d8578, d8579, d8580, d8581, d8582, d8583, d8584, d8585, d8586, d8587, d8588, d8589, d8590, d8591, d8592, d8593, d8594, d8595, d8596, d8597, d8598, d8599, d8600, d8601, d8602, d8603, d8604, d8605, d8606, d8607, d8608, d8609, d8610, d8611, d8612, d8613, d8614, d8615, d8616, d8617, d8618, d8619, d8620, d8621, d8622, d8623, d8624, d8625, d8626, d8627, d8628, d8629, d8630, d8631, d8632, d8633, d8634, d8635, d8636, d8637, d8638, d8639, d8640, d8641, d8642, d8643, d8644, d8645, d8646, d8647, d8648, d8649, d8650, d8651, d8652, d8653, d8654, d8655, d8656, d8657, d8658, d8659, d8660, d8661, d8662, d8663, d8664, d8665, d8666, d8667, d8668, d8669, d8670, d8671, d8672, d8673, d8674, d8675, d8676, d8677, d8678, d8679, d8680, d8681, d8682, d8683, d8684, d8685, d8686, d8687, d8688, d8689, d8690, d8691, d8692, d8693, d8694, d8695, d8696, d8697, d8698, d8699, d8700, d8701, d8702, d8703, d8704, d8705, d8706, d8707, d8708, d8709, d8710, d8711, d8712, d8713, d8714, d8715, d8716, d8717, d8718, d8719, d8720, d8721, d8722, d8723, d8724, d8725, d8726, d8727, d8728, d8729, d8730, d8731, d8732, d8733, d8734, d8735, d8736, d8737, d8738, d8739, d8740, d8741, d8742, d8743, d8744, d8745, d8746, d8747, d8748, d8749, d8750, d8751, d8752, d8753, d8754, d8755, d8756, d8757, d8758, d8759, d8760, d8761, d8762, d8763, d8764, d8765, d8766, d8767, d8768, d8769, d8770, d8771, d8772, d8773, d8774, d8775, d8776, d8777, d8778, d8779, d8780, d8781, d8782, d8783, d8784, d8785, d8786, d8787, d8788, d8789, d8790, d8791, d8792, d8793, d8794, d8795, d8796, d8797, d8798, d8799, d8800, d8801, d8802, d8803, d8804, d8805, d8806, d8807, d8808, d8809, d8810, d8811, d8812, d8813, d8814, d8815, d8816, d8817, d8818, d8819, d8820, d8821, d8822, d8823, d8824, d8825, d8826, d8827, d8828, d8829, d8830, d8831, d8832, d8833, d8834, d8835, d8836, d8837, d8838, d8839, d8840, d8841, d8842, d8843, d8844, d8845, d8846, d8847, d8848, d8849, d8850, d8851, d8852, d8853, d8854, d8855, d8856, d8857, d8858, d8859, d8860, d8861, d8862, d8863, d8864, d8865, d8866, d8867, d8868, d8869, d8870, d8871, d8872, d8873, d8874, d8875, d8876, d8877, d8878, d8879, d8880, d8881, d8882, d8883, d8884, d8885, d8886, d8887, d8888, d8889, d8890, d8891, d8892, d8893, d8894, d8895, d8896, d8897, d8898, d8899, d8900, d8901, d8902, d8903, d8904, d8905, d8906, d8907, d8908, d8909, d8910, d8911, d8912, d8913, d8914, d8915, d8916, d8917, d8918, d8919, d8920, d8921, d8922, d8923, d8924, d8925, d8926, d8927, d8928, d8929, d8930, d8931, d8932, d8933, d8934, d8935, d8936, d8937, d8938, d8939, d8940, d8941, d8942, d8943, d8944, d8945, d8946, d8947, d8948, d8949, d8950, d8951, d8952, d8953, d8954, d8955, d8956, d8957, d8958, d8959, d8960, d8961, d8962, d8963, d8964, d8965, d8966, d8967, d8968, d8969, d8970, d8971, d8972, d8973, d8974, d8975, d8976, d8977, d8978, d8979, d8980, d8981, d8982, d8983, d8984, d8985, d8986, d8987, d8988, d8989, d8990, d8991, d8992, d8993, d8994, d8995, d8996, d8997, d8998, d8999, d9000, d9001, d9002, d9003, d9004, d9005, d9006, d9007, d9008, d9009, d9010, d9011, d9012, d9013, d9014, d9015, d9016, d9017, d9018, d9019, d9020, d9021, d9022, d9023, d9024, d9025, d9026, d9027, d9028, d9029, d9030, d9031, d9032, d9033, d9034, d9035, d9036, d9037, d9038, d9039, d9040, d9041, d9042, d9043, d9044, d9045, d9046, d9047, d9048, d9049, d9050, d9051, d9052, d9053, d9054, d9055, d9056, d9057, d9058, d9059, d9060, d9061, d9062, d9063, d9064, d9065, d9066, d9067, d9068, d9069, d9070, d9071, d9072, d9073, d9074, d9075, d9076, d9077, d9078, d9079, d9080, d9081, d9082, d9083, d9084, d9085, d9086, d9087, d9088, d9089, d9090, d9091, d9092, d9093, d9094, d9095, d9096, d9097, d9098, d9099, d9100, d9101, d9102, d9103, d9104, d9105, d9106, d9107, d9108, d9109, d9110, d9111, d9112, d9113, d9114, d9115, d9116, d9117, d9118, d9119, d9120, d9121, d9122, d9123, d9124, d9125, d9126, d9127, d9128, d9129, d9130, d9131, d9132, d9133, d9134, d9135, d9136, d9137, d9138, d9139, d9140, d9141, d9142, d9143, d9144, d9145, d9146, d9147, d9148, d9149, d9150, d9151, d9152, d9153, d9154, d9155, d9156, d9157, d9158, d9159, d9160, d9161, d9162, d9163, d9164, d9165, d9166, d9167, d9168, d9169, d9170, d9171, d9172, d9173, d9174, d9175, d9176, d9177, d9178, d9179, d9180, d9181, d9182, d9183, d9184, d9185, d9186, d9187, d9188, d9189, d9190, d9191, d9192, d9193, d9194, d9195, d9196, d9197, d9198, d9199, d9200, d9201, d9202, d9203, d9204, d9205, d9206, d9207, d9208, d9209, d9210, d9211, d9212, d9213, d9214, d9215, d9216, d9217, d9218, d9219, d9220, d9221, d9222, d9223, d9224, d9225, d9226, d9227, d9228, d9229, d9230, d9231, d9232, d9233, d9234, d9235, d9236, d9237, d9238, d9239, d9240, d9241, d9242, d9243, d9244, d9245, d9246, d9247, d9248, d9249, d9250, d9251, d9252, d9253, d9254, d9255, d9256, d9257, d9258, d9259, d9260, d9261, d9262, d9263, d9264, d9265, d9266, d9267, d9268, d9269, d9270, d9271, d9272, d9273, d9274, d9275, d9276, d9277, d9278, d9279, d9280, d9281, d9282, d9283, d9284, d9285, d9286, d9287, d9288, d9289, d9290, d9291, d9292, d9293, d9294, d9295, d9296, d9297, d9298, d9299, d9300, d9301, d9302, d9303, d9304, d9305, d9306, d9307, d9308, d9309, d9310, d9311, d9312, d9313, d9314, d9315, d9316, d9317, d9318, d9319, d9320, d9321, d9322, d9323, d9324, d9325, d9326, d9327, d9328, d9329, d9330, d9331, d9332, d9333, d9334, d9335, d9336, d9337, d9338, d9339, d9340, d9341, d9342, d9343, d9344, d9345, d9346, d9347, d9348, d9349, d9350, d9351, d9352, d9353, d9354, d9355, d9356, d9357, d9358, d9359, d9360, d9361, d9362, d9363, d9364, d9365, d9366, d9367, d9368, d9369, d9370, d9371, d9372, d9373, d9374, d9375, d9376, d9377, d9378, d9379, d9380, d9381, d9382, d9383, d9384, d9385, d9386, d9387, d9388, d9389, d9390, d9391, d9392, d9393, d9394, d9395, d9396, d9397, d9398, d9399, d9400, d9401, d9402, d9403, d9404, d9405, d9406, d9407, d9408, d9409, d9410, d9411, d9412, d9413, d9414, d9415, d9416, d9417, d9418, d9419, d9420, d9421, d9422, d9423, d9424, d9425, d9426, d9427, d9428, d9429, d9430, d9431, d9432, d9433, d9434, d9435, d9436, d9437, d9438, d9439, d9440, d9441, d9442, d9443, d9444, d9445, d9446, d9447, d9448, d9449, d9450, d9451, d9452, d9453, d9454, d9455, d9456, d9457, d9458, d9459, d9460, d9461, d9462, d9463, d9464, d9465, d9466, d9467, d9468, d9469, d9470, d9471, d9472, d9473, d9474, d9475, d9476, d9477, d9478, d9479, d9480, d9481, d9482, d9483, d9484, d9485, d9486, d9487, d9488, d9489, d9490, d9491, d9492, d9493, d9494, d9495, d9496, d9497, d9498, d9499, d9500, d9501, d9502, d9503, d9504, d9505, d9506, d9507, d9508, d9509, d9510, d9511, d9512, d9513, d9514, d9515, d9516, d9517, d9518, d9519, d9520, d9521, d9522, d9523, d9524, d9525, d9526, d9527, d9528, d9529, d9530, d9531, d9532, d9533, d9534, d9535, d9536, d9537, d9538, d9539, d9540, d9541, d9542, d9543, d9544, d9545, d9546, d9547, d9548, d9549, d9550, d9551, d9552, d9553, d9554, d9555, d9556, d9557, d9558, d9559, d9560, d9561, d9562, d9563, d9564, d9565, d9566, d9567, d9568, d9569, d9570, d9571, d9572, d9573, d9574, d9575, d9576, d9577, d9578, d9579, d9580, d9581, d9582, d9583, d9584, d9585, d9586, d9587, d9588, d9589, d9590, d9591, d9592, d9593, d9594, d9595, d9596, d9597, d9598, d9599, d9600, d9601, d9602, d9603, d9604, d9605, d9606, d9607, d9608, d9609, d9610, d9611, d9612, d9613, d9614, d9615, d9616, d9617, d9618, d9619, d9620, d9621, d9622, d9623, d9624, d9625, d9626, d9627, d9628, d9629, d9630, d9631, d9632, d9633, d9634, d9635, d9636, d9637, d9638, d9639, d9640, d9641, d9642, d9643, d9644, d9645, d9646, d9647, d9648, d9649, d9650, d9651, d9652, d9653, d9654, d9655, d9656, d9657, d9658, d9659, d9660, d9661, d9662, d9663, d9664, d9665, d9666, d9667, d9668, d9669, d9670, d9671, d9672, d9673, d9674, d9675, d9676, d9677, d9678, d9679, d9680, d9681, d9682, d9683, d9684, d9685, d9686, d9687, d9688, d9689, d9690, d9691, d9692, d9693, d9694, d9695, d9696, d9697, d9698, d9699, d9700, d9701, d9702, d9703, d9704, d9705, d9706, d9707, d9708, d9709, d9710, d9711, d9712, d9713, d9714, d9715, d9716, d9717, d9718, d9719, d9720, d9721, d9722, d9723, d9724, d9725, d9726, d9727, d9728, d9729, d9730, d9731, d9732, d9733, d9734, d9735, d9736, d9737, d9738, d9739, d9740, d9741, d9742, d9743, d9744, d9745, d9746, d9747, d9748, d9749, d9750, d9751, d9752, d9753, d9754, d9755, d9756, d9757, d9758, d9759, d9760, d9761, d9762, d9763, d9764, d9765, d9766, d9767, d9768, d9769, d9770, d9771, d9772, d9773, d9774, d9775, d9776, d9777, d9778, d9779, d9780, d9781, d9782, d9783, d9784, d9785, d9786, d9787, d9788, d9789, d9790, d9791, d9792, d9793, d9794, d9795, d9796, d9797, d9798, d9799, d9800, d9801, d9802, d9803, d9804, d9805, d9806, d9807, d9808, d9809, d9810, d9811, d9812, d9813, d9814, d9815, d9816, d9817, d9818, d9819, d9820, d9821, d9822, d9823, d9824, d9825, d9826, d9827, d9828, d9829, d9830, d9831, d9832, d9833, d9834, d9835, d9836, d9837, d9838, d9839, d9840, d9841, d9842, d9843, d9844, d9845, d9846, d9847, d9848, d9849, d9850, d9851, d9852, d9853, d9854, d9855, d9856, d9857, d9858, d9859, d9860, d9861, d9862, d9863, d9864, d9865, d9866, d9867, d9868, d9869, d9870, d9871, d9872, d9873, d9874, d9875, d9876, d9877, d9878, d9879, d9880, d9881, d9882, d9883, d9884, d9885, d9886, d9887, d9888, d9889, d9890, d9891, d9892, d9893, d9894, d9895, d9896, d9897, d9898, d9899, d9900, d9901, d9902, d9903, d9904, d9905, d9906, d9907, d9908, d9909, d9910, d9911, d9912, d9913, d9914, d9915, d9916, d9917, d9918, d9919, d9920, d9921, d9922, d9923, d9924, d9925, d9926, d9927, d9928, d9929, d9930, d9931, d9932, d9933, d9934, d9935, d9936, d9937, d9938, d9939, d9940, d9941, d9942, d9943, d9944, d9945, d9946, d9947, d9948, d9949, d9950, d9951, d9952, d9953, d9954, d9955, d9956, d9957, d9958, d9959, d9960, d9961, d9962, d9963, d9964, d9965, d9966, d9967, d9968, d9969, d9970, d9971, d9972, d9973, d9974, d9975, d9976, d9977, d9978, d9979, d9980, d9981, d9982, d9983, d9984, d9985, d9986, d9987, d9988, d9989, d9990, d9991, d9992, d9993, d9994, d9995, d9996, d9997, d9998, f0,f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18,f19,f20,f21,f22,f23,f24,f25,f26,f27,f28,f29,f30,f31,f32,f33,f34,f35,f36,f37,f38,f39,f40,f41,f42,f43,f44,f45,f46,f47,f48,f49,f50,f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f62,f63,f64,f65,f66,f67,f68,f69,f70,f71,f72,f73,f74,f75,f76,f77,f78,f79,f80,f81,f82,f83,f84,f85,f86,f87,f88,f89,f90,f91,f92,f93,f94,f95,f96,f97,f98,f99,f100,f101,f102,f103,f104,f105,f106,f107,f108,f109,f110,f111,f112,f113,f114,f115,f116,f117,f118,f119,f120,f121,f122,f123,f124,f125,f126,f127,f128,f129,f130,f131,f132,f133,f134,f135,f136,f137,f138,f139,f140,f141,f142,f143,f144,f145,f146,f147,f148,f149,f150,f151,f152,f153,f154,f155,f156,f157,f158,f159,f160,f161,f162,f163,f164,f165,f166,f167,f168,f169,f170,f171,f172,f173,f174,f175,f176,f177,f178,f179,f180,f181,f182,f183,f184,f185,f186,f187,f188,f189,f190,f191,f192,f193,f194,f195,f196,f197,f198,f199,f200,f201,f202,f203,f204,f205,f206,f207,f208,f209,f210,f211,f212,f213,f214,f215,f216,f217,f218,f219,f220,f221,f222,f223,f224,f225,f226,f227,f228,f229,f230,f231,f232,f233,f234,f235,f236,f237,f238,f239,f240,f241,f242,f243,f244,f245,f246,f247,f248,f249,f250,f251,f252,f253,f254,f255,f256,f257,f258,f259,f260,f261,f262,f263,f264,f265,f266,f267,f268,f269,f270,f271,f272,f273,f274,f275,f276,f277,f278,f279,f280,f281,f282,f283,f284,f285,f286,f287,f288,f289,f290,f291,f292,f293,f294,f295,f296,f297,f298,f299,f300,f301,f302,f303,f304,f305,f306,f307,f308,f309,f310,f311,f312,f313,f314,f315,f316,f317,f318,f319,f320,f321,f322,f323,f324,f325,f326,f327,f328,f329,f330,f331,f332,f333,f334,f335,f336,f337,f338,f339,f340,f341,f342,f343,f344,f345,f346,f347,f348,f349,f350,f351,f352,f353,f354,f355,f356,f357,f358,f359,f360,f361,f362,f363,f364,f365,f366,f367,f368,f369,f370,f371,f372,f373,f374,f375,f376,f377,f378,f379,f380,f381,f382,f383,f384,f385,f386,f387,f388,f389,f390,f391,f392,f393,f394,f395,f396,f397,f398,f399,f400,f401,f402,f403,f404,f405,f406,f407,f408,f409,f410,f411,f412,f413,f414,f415,f416,f417,f418,f419,f420,f421,f422,f423,f424,f425,f426,f427,f428,f429,f430,f431,f432,f433,f434,f435,f436,f437,f438,f439,f440,f441,f442,f443,f444,f445,f446,f447,f448,f449,f450,f451,f452,f453,f454,f455,f456,f457,f458,f459,f460,f461,f462,f463,f464,f465,f466,f467,f468,f469,f470,f471,f472,f473,f474,f475,f476,f477,f478,f479,f480,f481,f482,f483,f484,f485,f486,f487,f488,f489,f490,f491,f492,f493,f494,f495,f496,f497,f498,f499,f500,f501,f502,f503,f504,f505,f506,f507,f508,f509,f510,f511,f512,f513,f514,f515,f516,f517,f518,f519,f520,f521,f522,f523,f524,f525,f526,f527,f528,f529,f530,f531,f532,f533,f534,f535,f536,f537,f538,f539,f540,f541,f542,f543,f544,f545,f546,f547,f548,f549,f550,f551,f552,f553,f554,f555,f556,f557,f558,f559,f560,f561,f562,f563,f564,f565,f566,f567,f568,f569,f570,f571,f572,f573,f574,f575,f576,f577,f578,f579,f580,f581,f582,f583,f584,f585,f586,f587,f588,f589,f590,f591,f592,f593,f594,f595,f596,f597,f598,f599,f600,f601,f602,f603,f604,f605,f606,f607,f608,f609,f610,f611,f612,f613,f614,f615,f616,f617,f618,f619,f620,f621,f622,f623,f624,f625,f626,f627,f628,f629,f630,f631,f632,f633,f634,f635,f636,f637,f638,f639,f640,f641,f642,f643,f644,f645,f646,f647,f648,f649,f650,f651,f652,f653,f654,f655,f656,f657,f658,f659,f660,f661,f662,f663,f664,f665,f666,f667,f668,f669,f670,f671,f672,f673,f674,f675,f676,f677,f678,f679,f680,f681,f682,f683,f684,f685,f686,f687,f688,f689,f690,f691,f692,f693,f694,f695,f696,f697,f698,f699,f700,f701,f702,f703,f704,f705,f706,f707,f708,f709,f710,f711,f712,f713,f714,f715,f716,f717,f718,f719,f720,f721,f722,f723,f724,f725,f726,f727,f728,f729,f730,f731,f732,f733,f734,f735,f736,f737,f738,f739,f740,f741,f742,f743,f744,f745,f746,f747,f748,f749,f750,f751,f752,f753,f754,f755,f756,f757,f758,f759,f760,f761,f762,f763,f764,f765,f766,f767,f768,f769,f770,f771,f772,f773,f774,f775,f776,f777,f778,f779,f780,f781,f782,f783,f784,f785,f786,f787,f788,f789,f790,f791,f792,f793,f794,f795,f796,f797,f798,f799,f800,f801,f802,f803,f804,f805,f806,f807,f808,f809,f810,f811,f812,f813,f814,f815,f816,f817,f818,f819,f820,f821,f822,f823,f824,f825,f826,f827,f828,f829,f830,f831,f832,f833,f834,f835,f836,f837,f838,f839,f840,f841,f842,f843,f844,f845,f846,f847,f848,f849,f850,f851,f852,f853,f854,f855,f856,f857,f858,f859,f860,f861,f862,f863,f864,f865,f866,f867,f868,f869,f870,f871,f872,f873,f874,f875,f876,f877,f878,f879,f880,f881,f882,f883,f884,f885,f886,f887,f888,f889,f890,f891,f892,f893,f894,f895,f896,f897,f898,f899,f900,f901,f902,f903,f904,f905,f906,f907,f908,f909,f910,f911,f912,f913,f914,f915,f916,f917,f918,f919,f920,f921,f922,f923,f924,f925,f926,f927,f928,f929,f930,f931,f932,f933,f934,f935,f936,f937,f938,f939,f940,f941,f942,f943,f944,f945,f946,f947,f948,f949,f950,f951,f952,f953,f954,f955,f956,f957,f958,f959,f960,f961,f962,f963,f964,f965,f966,f967,f968,f969,f970,f971,f972,f973,f974,f975,f976,f977,f978,f979,f980,f981,f982,f983,f984,f985,f986,f987,f988,f989,f990,f991,f992,f993,f994,f995,f996,f997,f998,f999,f1000,f1001,f1002,f1003,f1004,f1005,f1006,f1007,f1008,f1009,f1010,f1011,f1012,f1013,f1014,f1015,f1016,f1017,f1018,f1019,f1020,f1021,f1022,f1023,f1024,f1025,f1026,f1027,f1028,f1029,f1030,f1031,f1032,f1033,f1034,f1035,f1036,f1037,f1038,f1039,f1040,f1041,f1042,f1043,f1044,f1045,f1046,f1047,f1048,f1049,f1050,f1051,f1052,f1053,f1054,f1055,f1056,f1057,f1058,f1059,f1060,f1061,f1062,f1063,f1064,f1065,f1066,f1067,f1068,f1069,f1070,f1071,f1072,f1073,f1074,f1075,f1076,f1077,f1078,f1079,f1080,f1081,f1082,f1083,f1084,f1085,f1086,f1087,f1088,f1089,f1090,f1091,f1092,f1093,f1094,f1095,f1096,f1097,f1098,f1099,f1100,f1101,f1102,f1103,f1104,f1105,f1106,f1107,f1108,f1109,f1110,f1111,f1112,f1113,f1114,f1115,f1116,f1117,f1118,f1119,f1120,f1121,f1122,f1123,f1124,f1125,f1126,f1127,f1128,f1129,f1130,f1131,f1132,f1133,f1134,f1135,f1136,f1137,f1138,f1139,f1140,f1141,f1142,f1143,f1144,f1145,f1146,f1147,f1148,f1149,f1150,f1151,f1152,f1153,f1154,f1155,f1156,f1157,f1158,f1159,f1160,f1161,f1162,f1163,f1164,f1165,f1166,f1167,f1168,f1169,f1170,f1171,f1172,f1173,f1174,f1175,f1176,f1177,f1178,f1179,f1180,f1181,f1182,f1183,f1184,f1185,f1186,f1187,f1188,f1189,f1190,f1191,f1192,f1193,f1194,f1195,f1196,f1197,f1198,f1199,f1200,f1201,f1202,f1203,f1204,f1205,f1206,f1207,f1208,f1209,f1210,f1211,f1212,f1213,f1214,f1215,f1216,f1217,f1218,f1219,f1220,f1221,f1222,f1223,f1224,f1225,f1226,f1227,f1228,f1229,f1230,f1231,f1232,f1233,f1234,f1235,f1236,f1237,f1238,f1239,f1240,f1241,f1242,f1243,f1244,f1245,f1246,f1247,f1248,f1249,f1250,f1251,f1252,f1253,f1254,f1255,f1256,f1257,f1258,f1259,f1260,f1261,f1262,f1263,f1264,f1265,f1266,f1267,f1268,f1269,f1270,f1271,f1272,f1273,f1274,f1275,f1276,f1277,f1278,f1279,f1280,f1281,f1282,f1283,f1284,f1285,f1286,f1287,f1288,f1289,f1290,f1291,f1292,f1293,f1294,f1295,f1296,f1297,f1298,f1299,f1300,f1301,f1302,f1303,f1304,f1305,f1306,f1307,f1308,f1309,f1310,f1311,f1312,f1313,f1314,f1315,f1316,f1317,f1318,f1319,f1320,f1321,f1322,f1323,f1324,f1325,f1326,f1327,f1328,f1329,f1330,f1331,f1332,f1333,f1334,f1335,f1336,f1337,f1338,f1339,f1340,f1341,f1342,f1343,f1344,f1345,f1346,f1347,f1348,f1349,f1350,f1351,f1352,f1353,f1354,f1355,f1356,f1357,f1358,f1359,f1360,f1361,f1362,f1363,f1364,f1365,f1366,f1367,f1368,f1369,f1370,f1371,f1372,f1373,f1374,f1375,f1376,f1377,f1378,f1379,f1380,f1381,f1382,f1383,f1384,f1385,f1386,f1387,f1388,f1389,f1390,f1391,f1392,f1393,f1394,f1395,f1396,f1397,f1398,f1399,f1400,f1401,f1402,f1403,f1404,f1405,f1406,f1407,f1408,f1409,f1410,f1411,f1412,f1413,f1414,f1415,f1416,f1417,f1418,f1419,f1420,f1421,f1422,f1423,f1424,f1425,f1426,f1427,f1428,f1429,f1430,f1431,f1432,f1433,f1434,f1435,f1436,f1437,f1438,f1439,f1440,f1441,f1442,f1443,f1444,f1445,f1446,f1447,f1448,f1449,f1450,f1451,f1452,f1453,f1454,f1455,f1456,f1457,f1458,f1459,f1460,f1461,f1462,f1463,f1464,f1465,f1466,f1467,f1468,f1469,f1470,f1471,f1472,f1473,f1474,f1475,f1476,f1477,f1478,f1479,f1480,f1481,f1482,f1483,f1484,f1485,f1486,f1487,f1488,f1489,f1490,f1491,f1492,f1493,f1494,f1495,f1496,f1497,f1498,f1499,f1500,f1501,f1502,f1503,f1504,f1505,f1506,f1507,f1508,f1509,f1510,f1511,f1512,f1513,f1514,f1515,f1516,f1517,f1518,f1519,f1520,f1521,f1522,f1523,f1524,f1525,f1526,f1527,f1528,f1529,f1530,f1531,f1532,f1533,f1534,f1535,f1536,f1537,f1538,f1539,f1540,f1541,f1542,f1543,f1544,f1545,f1546,f1547,f1548,f1549,f1550,f1551,f1552,f1553,f1554,f1555,f1556,f1557,f1558,f1559,f1560,f1561,f1562,f1563,f1564,f1565,f1566,f1567,f1568,f1569,f1570,f1571,f1572,f1573,f1574,f1575,f1576,f1577,f1578,f1579,f1580,f1581,f1582,f1583,f1584,f1585,f1586,f1587,f1588,f1589,f1590,f1591,f1592,f1593,f1594,f1595,f1596,f1597,f1598,f1599,f1600,f1601,f1602,f1603,f1604,f1605,f1606,f1607,f1608,f1609,f1610,f1611,f1612,f1613,f1614,f1615,f1616,f1617,f1618,f1619,f1620,f1621,f1622,f1623,f1624,f1625,f1626,f1627,f1628,f1629,f1630,f1631,f1632,f1633,f1634,f1635,f1636,f1637,f1638,f1639,f1640,f1641,f1642,f1643,f1644,f1645,f1646,f1647,f1648,f1649,f1650,f1651,f1652,f1653,f1654,f1655,f1656,f1657,f1658,f1659,f1660,f1661,f1662,f1663,f1664,f1665,f1666,f1667,f1668,f1669,f1670,f1671,f1672,f1673,f1674,f1675,f1676,f1677,f1678,f1679,f1680,f1681,f1682,f1683,f1684,f1685,f1686,f1687,f1688,f1689,f1690,f1691,f1692,f1693,f1694,f1695,f1696,f1697,f1698,f1699,f1700,f1701,f1702,f1703,f1704,f1705,f1706,f1707,f1708,f1709,f1710,f1711,f1712,f1713,f1714,f1715,f1716,f1717,f1718,f1719,f1720,f1721,f1722,f1723,f1724,f1725,f1726,f1727,f1728,f1729,f1730,f1731,f1732,f1733,f1734,f1735,f1736,f1737,f1738,f1739,f1740,f1741,f1742,f1743,f1744,f1745,f1746,f1747,f1748,f1749,f1750,f1751,f1752,f1753,f1754,f1755,f1756,f1757,f1758,f1759,f1760,f1761,f1762,f1763,f1764,f1765,f1766,f1767,f1768,f1769,f1770,f1771,f1772,f1773,f1774,f1775,f1776,f1777,f1778,f1779,f1780,f1781,f1782,f1783,f1784,f1785,f1786,f1787,f1788,f1789,f1790,f1791,f1792,f1793,f1794,f1795,f1796,f1797,f1798,f1799,f1800,f1801,f1802,f1803,f1804,f1805,f1806,f1807,f1808,f1809,f1810,f1811,f1812,f1813,f1814,f1815,f1816,f1817,f1818,f1819,f1820,f1821,f1822,f1823,f1824,f1825,f1826,f1827,f1828,f1829,f1830,f1831,f1832,f1833,f1834,f1835,f1836,f1837,f1838,f1839,f1840,f1841,f1842,f1843,f1844,f1845,f1846,f1847,f1848,f1849,f1850,f1851,f1852,f1853,f1854,f1855,f1856,f1857,f1858,f1859,f1860,f1861,f1862,f1863,f1864,f1865,f1866,f1867,f1868,f1869,f1870,f1871,f1872,f1873,f1874,f1875,f1876,f1877,f1878,f1879,f1880,f1881,f1882,f1883,f1884,f1885,f1886,f1887,f1888,f1889,f1890,f1891,f1892,f1893,f1894,f1895,f1896,f1897,f1898,f1899,f1900,f1901,f1902,f1903,f1904,f1905,f1906,f1907,f1908,f1909,f1910,f1911,f1912,f1913,f1914,f1915,f1916,f1917,f1918,f1919,f1920,f1921,f1922,f1923,f1924,f1925,f1926,f1927,f1928,f1929,f1930,f1931,f1932,f1933,f1934,f1935,f1936,f1937,f1938,f1939,f1940,f1941,f1942,f1943,f1944,f1945,f1946,f1947,f1948,f1949,f1950,f1951,f1952,f1953,f1954,f1955,f1956,f1957,f1958,f1959,f1960,f1961,f1962,f1963,f1964,f1965,f1966,f1967,f1968,f1969,f1970,f1971,f1972,f1973,f1974,f1975,f1976,f1977,f1978,f1979,f1980,f1981,f1982,f1983,f1984,f1985,f1986,f1987,f1988,f1989,f1990,f1991,f1992,f1993,f1994,f1995,f1996,f1997,f1998,f1999,f2000,f2001,f2002,f2003,f2004,f2005,f2006,f2007,f2008,f2009,f2010,f2011,f2012,f2013,f2014,f2015,f2016,f2017,f2018,f2019,f2020,f2021,f2022,f2023,f2024,f2025,f2026,f2027,f2028,f2029,f2030,f2031,f2032,f2033,f2034,f2035,f2036,f2037,f2038,f2039,f2040,f2041,f2042,f2043,f2044,f2045,f2046,f2047,f2048,f2049,f2050,f2051,f2052,f2053,f2054,f2055,f2056,f2057,f2058,f2059,f2060,f2061,f2062,f2063,f2064,f2065,f2066,f2067,f2068,f2069,f2070,f2071,f2072,f2073,f2074,f2075,f2076,f2077,f2078,f2079,f2080,f2081,f2082,f2083,f2084,f2085,f2086,f2087,f2088,f2089,f2090,f2091,f2092,f2093,f2094,f2095,f2096,f2097,f2098,f2099,f2100,f2101,f2102,f2103,f2104,f2105,f2106,f2107,f2108,f2109,f2110,f2111,f2112,f2113,f2114,f2115,f2116,f2117,f2118,f2119,f2120,f2121,f2122,f2123,f2124,f2125,f2126,f2127,f2128,f2129,f2130,f2131,f2132,f2133,f2134,f2135,f2136,f2137,f2138,f2139,f2140,f2141,f2142,f2143,f2144,f2145,f2146,f2147,f2148,f2149,f2150,f2151,f2152,f2153,f2154,f2155,f2156,f2157,f2158,f2159,f2160,f2161,f2162,f2163,f2164,f2165,f2166,f2167,f2168,f2169,f2170,f2171,f2172,f2173,f2174,f2175,f2176,f2177,f2178,f2179,f2180,f2181,f2182,f2183,f2184,f2185,f2186,f2187,f2188,f2189,f2190,f2191,f2192,f2193,f2194,f2195,f2196,f2197,f2198,f2199,f2200,f2201,f2202,f2203,f2204,f2205,f2206,f2207,f2208,f2209,f2210,f2211,f2212,f2213,f2214,f2215,f2216,f2217,f2218,f2219,f2220,f2221,f2222,f2223,f2224,f2225,f2226,f2227,f2228,f2229,f2230,f2231,f2232,f2233,f2234,f2235,f2236,f2237,f2238,f2239,f2240,f2241,f2242,f2243,f2244,f2245,f2246,f2247,f2248,f2249,f2250,f2251,f2252,f2253,f2254,f2255,f2256,f2257,f2258,f2259,f2260,f2261,f2262,f2263,f2264,f2265,f2266,f2267,f2268,f2269,f2270,f2271,f2272,f2273,f2274,f2275,f2276,f2277,f2278,f2279,f2280,f2281,f2282,f2283,f2284,f2285,f2286,f2287,f2288,f2289,f2290,f2291,f2292,f2293,f2294,f2295,f2296,f2297,f2298,f2299,f2300,f2301,f2302,f2303,f2304,f2305,f2306,f2307,f2308,f2309,f2310,f2311,f2312,f2313,f2314,f2315,f2316,f2317,f2318,f2319,f2320,f2321,f2322,f2323,f2324,f2325,f2326,f2327,f2328,f2329,f2330,f2331,f2332,f2333,f2334,f2335,f2336,f2337,f2338,f2339,f2340,f2341,f2342,f2343,f2344,f2345,f2346,f2347,f2348,f2349,f2350,f2351,f2352,f2353,f2354,f2355,f2356,f2357,f2358,f2359,f2360,f2361,f2362,f2363,f2364,f2365,f2366,f2367,f2368,f2369,f2370,f2371,f2372,f2373,f2374,f2375,f2376,f2377,f2378,f2379,f2380,f2381,f2382,f2383,f2384,f2385,f2386,f2387,f2388,f2389,f2390,f2391,f2392,f2393,f2394,f2395,f2396,f2397,f2398,f2399,f2400,f2401,f2402,f2403,f2404,f2405,f2406,f2407,f2408,f2409,f2410,f2411,f2412,f2413,f2414,f2415,f2416,f2417,f2418,f2419,f2420,f2421,f2422,f2423,f2424,f2425,f2426,f2427,f2428,f2429,f2430,f2431,f2432,f2433,f2434,f2435,f2436,f2437,f2438,f2439,f2440,f2441,f2442,f2443,f2444,f2445,f2446,f2447,f2448,f2449,f2450,f2451,f2452,f2453,f2454,f2455,f2456,f2457,f2458,f2459,f2460,f2461,f2462,f2463,f2464,f2465,f2466,f2467,f2468,f2469,f2470,f2471,f2472,f2473,f2474,f2475,f2476,f2477,f2478,f2479,f2480,f2481,f2482,f2483,f2484,f2485,f2486,f2487,f2488,f2489,f2490,f2491,f2492,f2493,f2494,f2495,f2496,f2497,f2498,f2499,f2500,f2501,f2502,f2503,f2504,f2505,f2506,f2507,f2508,f2509,f2510,f2511,f2512,f2513,f2514,f2515,f2516,f2517,f2518,f2519,f2520,f2521,f2522,f2523,f2524,f2525,f2526,f2527,f2528,f2529,f2530,f2531,f2532,f2533,f2534,f2535,f2536,f2537,f2538,f2539,f2540,f2541,f2542,f2543,f2544,f2545,f2546,f2547,f2548,f2549,f2550,f2551,f2552,f2553,f2554,f2555,f2556,f2557,f2558,f2559,f2560,f2561,f2562,f2563,f2564,f2565,f2566,f2567,f2568,f2569,f2570,f2571,f2572,f2573,f2574,f2575,f2576,f2577,f2578,f2579,f2580,f2581,f2582,f2583,f2584,f2585,f2586,f2587,f2588,f2589,f2590,f2591,f2592,f2593,f2594,f2595,f2596,f2597,f2598,f2599,f2600,f2601,f2602,f2603,f2604,f2605,f2606,f2607,f2608,f2609,f2610,f2611,f2612,f2613,f2614,f2615,f2616,f2617,f2618,f2619,f2620,f2621,f2622,f2623,f2624,f2625,f2626,f2627,f2628,f2629,f2630,f2631,f2632,f2633,f2634,f2635,f2636,f2637,f2638,f2639,f2640,f2641,f2642,f2643,f2644,f2645,f2646,f2647,f2648,f2649,f2650,f2651,f2652,f2653,f2654,f2655,f2656,f2657,f2658,f2659,f2660,f2661,f2662,f2663,f2664,f2665,f2666,f2667,f2668,f2669,f2670,f2671,f2672,f2673,f2674,f2675,f2676,f2677,f2678,f2679,f2680,f2681,f2682,f2683,f2684,f2685,f2686,f2687,f2688,f2689,f2690,f2691,f2692,f2693,f2694,f2695,f2696,f2697,f2698,f2699,f2700,f2701,f2702,f2703,f2704,f2705,f2706,f2707,f2708,f2709,f2710,f2711,f2712,f2713,f2714,f2715,f2716,f2717,f2718,f2719,f2720,f2721,f2722,f2723,f2724,f2725,f2726,f2727,f2728,f2729,f2730,f2731,f2732,f2733,f2734,f2735,f2736,f2737,f2738,f2739,f2740,f2741,f2742,f2743,f2744,f2745,f2746,f2747,f2748,f2749,f2750,f2751,f2752,f2753,f2754,f2755,f2756,f2757,f2758,f2759,f2760,f2761,f2762,f2763,f2764,f2765,f2766,f2767,f2768,f2769,f2770,f2771,f2772,f2773,f2774,f2775,f2776,f2777,f2778,f2779,f2780,f2781,f2782,f2783,f2784,f2785,f2786,f2787,f2788,f2789,f2790,f2791,f2792,f2793,f2794,f2795,f2796,f2797,f2798,f2799,f2800,f2801,f2802,f2803,f2804,f2805,f2806,f2807,f2808,f2809,f2810,f2811,f2812,f2813,f2814,f2815,f2816,f2817,f2818,f2819,f2820,f2821,f2822,f2823,f2824,f2825,f2826,f2827,f2828,f2829,f2830,f2831,f2832,f2833,f2834,f2835,f2836,f2837,f2838,f2839,f2840,f2841,f2842,f2843,f2844,f2845,f2846,f2847,f2848,f2849,f2850,f2851,f2852,f2853,f2854,f2855,f2856,f2857,f2858,f2859,f2860,f2861,f2862,f2863,f2864,f2865,f2866,f2867,f2868,f2869,f2870,f2871,f2872,f2873,f2874,f2875,f2876,f2877,f2878,f2879,f2880,f2881,f2882,f2883,f2884,f2885,f2886,f2887,f2888,f2889,f2890,f2891,f2892,f2893,f2894,f2895,f2896,f2897,f2898,f2899,f2900,f2901,f2902,f2903,f2904,f2905,f2906,f2907,f2908,f2909,f2910,f2911,f2912,f2913,f2914,f2915,f2916,f2917,f2918,f2919,f2920,f2921,f2922,f2923,f2924,f2925,f2926,f2927,f2928,f2929,f2930,f2931,f2932,f2933,f2934,f2935,f2936,f2937,f2938,f2939,f2940,f2941,f2942,f2943,f2944,f2945,f2946,f2947,f2948,f2949,f2950,f2951,f2952,f2953,f2954,f2955,f2956,f2957,f2958,f2959,f2960,f2961,f2962,f2963,f2964,f2965,f2966,f2967,f2968,f2969,f2970,f2971,f2972,f2973,f2974,f2975,f2976,f2977,f2978,f2979,f2980,f2981,f2982,f2983,f2984,f2985,f2986,f2987,f2988,f2989,f2990,f2991,f2992,f2993,f2994,f2995,f2996,f2997,f2998,f2999,f3000,f3001,f3002,f3003,f3004,f3005,f3006,f3007,f3008,f3009,f3010,f3011,f3012,f3013,f3014,f3015,f3016,f3017,f3018,f3019,f3020,f3021,f3022,f3023,f3024,f3025,f3026,f3027,f3028,f3029,f3030,f3031,f3032,f3033,f3034,f3035,f3036,f3037,f3038,f3039,f3040,f3041,f3042,f3043,f3044,f3045,f3046,f3047,f3048,f3049,f3050,f3051,f3052,f3053,f3054,f3055,f3056,f3057,f3058,f3059,f3060,f3061,f3062,f3063,f3064,f3065,f3066,f3067,f3068,f3069,f3070,f3071,f3072,f3073,f3074,f3075,f3076,f3077,f3078,f3079,f3080,f3081,f3082,f3083,f3084,f3085,f3086,f3087,f3088,f3089,f3090,f3091,f3092,f3093,f3094,f3095,f3096,f3097,f3098,f3099,f3100,f3101,f3102,f3103,f3104,f3105,f3106,f3107,f3108,f3109,f3110,f3111,f3112,f3113,f3114,f3115,f3116,f3117,f3118,f3119,f3120,f3121,f3122,f3123,f3124,f3125,f3126,f3127,f3128,f3129,f3130,f3131,f3132,f3133,f3134,f3135,f3136,f3137,f3138,f3139,f3140,f3141,f3142,f3143,f3144,f3145,f3146,f3147,f3148,f3149,f3150,f3151,f3152,f3153,f3154,f3155,f3156,f3157,f3158,f3159,f3160,f3161,f3162,f3163,f3164,f3165,f3166,f3167,f3168,f3169,f3170,f3171,f3172,f3173,f3174,f3175,f3176,f3177,f3178,f3179,f3180,f3181,f3182,f3183,f3184,f3185,f3186,f3187,f3188,f3189,f3190,f3191,f3192,f3193,f3194,f3195,f3196,f3197,f3198,f3199,f3200,f3201,f3202,f3203,f3204,f3205,f3206,f3207,f3208,f3209,f3210,f3211,f3212,f3213,f3214,f3215,f3216,f3217,f3218,f3219,f3220,f3221,f3222,f3223,f3224,f3225,f3226,f3227,f3228,f3229,f3230,f3231,f3232,f3233,f3234,f3235,f3236,f3237,f3238,f3239,f3240,f3241,f3242,f3243,f3244,f3245,f3246,f3247,f3248,f3249,f3250,f3251,f3252,f3253,f3254,f3255,f3256,f3257,f3258,f3259,f3260,f3261,f3262,f3263,f3264,f3265,f3266,f3267,f3268,f3269,f3270,f3271,f3272,f3273,f3274,f3275,f3276,f3277,f3278,f3279,f3280,f3281,f3282,f3283,f3284,f3285,f3286,f3287,f3288,f3289,f3290,f3291,f3292,f3293,f3294,f3295,f3296,f3297,f3298,f3299,f3300,f3301,f3302,f3303,f3304,f3305,f3306,f3307,f3308,f3309,f3310,f3311,f3312,f3313,f3314,f3315,f3316,f3317,f3318,f3319,f3320,f3321,f3322,f3323,f3324,f3325,f3326,f3327,f3328,f3329,f3330,f3331,f3332,f3333,f3334,f3335,f3336,f3337,f3338,f3339,f3340,f3341,f3342,f3343,f3344,f3345,f3346,f3347,f3348,f3349,f3350,f3351,f3352,f3353,f3354,f3355,f3356,f3357,f3358,f3359,f3360,f3361,f3362,f3363,f3364,f3365,f3366,f3367,f3368,f3369,f3370,f3371,f3372,f3373,f3374,f3375,f3376,f3377,f3378,f3379,f3380,f3381,f3382,f3383,f3384,f3385,f3386,f3387,f3388,f3389,f3390,f3391,f3392,f3393,f3394,f3395,f3396,f3397,f3398,f3399,f3400,f3401,f3402,f3403,f3404,f3405,f3406,f3407,f3408,f3409,f3410,f3411,f3412,f3413,f3414,f3415,f3416,f3417,f3418,f3419,f3420,f3421,f3422,f3423,f3424,f3425,f3426,f3427,f3428,f3429,f3430,f3431,f3432,f3433,f3434,f3435,f3436,f3437,f3438,f3439,f3440,f3441,f3442,f3443,f3444,f3445,f3446,f3447,f3448,f3449,f3450,f3451,f3452,f3453,f3454,f3455,f3456,f3457,f3458,f3459,f3460,f3461,f3462,f3463,f3464,f3465,f3466,f3467,f3468,f3469,f3470,f3471,f3472,f3473,f3474,f3475,f3476,f3477,f3478,f3479,f3480,f3481,f3482,f3483,f3484,f3485,f3486,f3487,f3488,f3489,f3490,f3491,f3492,f3493,f3494,f3495,f3496,f3497,f3498,f3499,f3500,f3501,f3502,f3503,f3504,f3505,f3506,f3507,f3508,f3509,f3510,f3511,f3512,f3513,f3514,f3515,f3516,f3517,f3518,f3519,f3520,f3521,f3522,f3523,f3524,f3525,f3526,f3527,f3528,f3529,f3530,f3531,f3532,f3533,f3534,f3535,f3536,f3537,f3538,f3539,f3540,f3541,f3542,f3543,f3544,f3545,f3546,f3547,f3548,f3549,f3550,f3551,f3552,f3553,f3554,f3555,f3556,f3557,f3558,f3559,f3560,f3561,f3562,f3563,f3564,f3565,f3566,f3567,f3568,f3569,f3570,f3571,f3572,f3573,f3574,f3575,f3576,f3577,f3578,f3579,f3580,f3581,f3582,f3583,f3584,f3585,f3586,f3587,f3588,f3589,f3590,f3591,f3592,f3593,f3594,f3595,f3596,f3597,f3598,f3599,f3600,f3601,f3602,f3603,f3604,f3605,f3606,f3607,f3608,f3609,f3610,f3611,f3612,f3613,f3614,f3615,f3616,f3617,f3618,f3619,f3620,f3621,f3622,f3623,f3624,f3625,f3626,f3627,f3628,f3629,f3630,f3631,f3632,f3633,f3634,f3635,f3636,f3637,f3638,f3639,f3640,f3641,f3642,f3643,f3644,f3645,f3646,f3647,f3648,f3649,f3650,f3651,f3652,f3653,f3654,f3655,f3656,f3657,f3658,f3659,f3660,f3661,f3662,f3663,f3664,f3665,f3666,f3667,f3668,f3669,f3670,f3671,f3672,f3673,f3674,f3675,f3676,f3677,f3678,f3679,f3680,f3681,f3682,f3683,f3684,f3685,f3686,f3687,f3688,f3689,f3690,f3691,f3692,f3693,f3694,f3695,f3696,f3697,f3698,f3699,f3700,f3701,f3702,f3703,f3704,f3705,f3706,f3707,f3708,f3709,f3710,f3711,f3712,f3713,f3714,f3715,f3716,f3717,f3718,f3719,f3720,f3721,f3722,f3723,f3724,f3725,f3726,f3727,f3728,f3729,f3730,f3731,f3732,f3733,f3734,f3735,f3736,f3737,f3738,f3739,f3740,f3741,f3742,f3743,f3744,f3745,f3746,f3747,f3748,f3749,f3750,f3751,f3752,f3753,f3754,f3755,f3756,f3757,f3758,f3759,f3760,f3761,f3762,f3763,f3764,f3765,f3766,f3767,f3768,f3769,f3770,f3771,f3772,f3773,f3774,f3775,f3776,f3777,f3778,f3779,f3780,f3781,f3782,f3783,f3784,f3785,f3786,f3787,f3788,f3789,f3790,f3791,f3792,f3793,f3794,f3795,f3796,f3797,f3798,f3799,f3800,f3801,f3802,f3803,f3804,f3805,f3806,f3807,f3808,f3809,f3810,f3811,f3812,f3813,f3814,f3815,f3816,f3817,f3818,f3819,f3820,f3821,f3822,f3823,f3824,f3825,f3826,f3827,f3828,f3829,f3830,f3831,f3832,f3833,f3834,f3835,f3836,f3837,f3838,f3839,f3840,f3841,f3842,f3843,f3844,f3845,f3846,f3847,f3848,f3849,f3850,f3851,f3852,f3853,f3854,f3855,f3856,f3857,f3858,f3859,f3860,f3861,f3862,f3863,f3864,f3865,f3866,f3867,f3868,f3869,f3870,f3871,f3872,f3873,f3874,f3875,f3876,f3877,f3878,f3879,f3880,f3881,f3882,f3883,f3884,f3885,f3886,f3887,f3888,f3889,f3890,f3891,f3892,f3893,f3894,f3895,f3896,f3897,f3898,f3899,f3900,f3901,f3902,f3903,f3904,f3905,f3906,f3907,f3908,f3909,f3910,f3911,f3912,f3913,f3914,f3915,f3916,f3917,f3918,f3919,f3920,f3921,f3922,f3923,f3924,f3925,f3926,f3927,f3928,f3929,f3930,f3931,f3932,f3933,f3934,f3935,f3936,f3937,f3938,f3939,f3940,f3941,f3942,f3943,f3944,f3945,f3946,f3947,f3948,f3949,f3950,f3951,f3952,f3953,f3954,f3955,f3956,f3957,f3958,f3959,f3960,f3961,f3962,f3963,f3964,f3965,f3966,f3967,f3968,f3969,f3970,f3971,f3972,f3973,f3974,f3975,f3976,f3977,f3978,f3979,f3980,f3981,f3982,f3983,f3984,f3985,f3986,f3987,f3988,f3989,f3990,f3991,f3992,f3993,f3994,f3995,f3996,f3997,f3998,f3999,f4000,f4001,f4002,f4003,f4004,f4005,f4006,f4007,f4008,f4009,f4010,f4011,f4012,f4013,f4014,f4015,f4016,f4017,f4018,f4019,f4020,f4021,f4022,f4023,f4024,f4025,f4026,f4027,f4028,f4029,f4030,f4031,f4032,f4033,f4034,f4035,f4036,f4037,f4038,f4039,f4040,f4041,f4042,f4043,f4044,f4045,f4046,f4047,f4048,f4049,f4050,f4051,f4052,f4053,f4054,f4055,f4056,f4057,f4058,f4059,f4060,f4061,f4062,f4063,f4064,f4065,f4066,f4067,f4068,f4069,f4070,f4071,f4072,f4073,f4074,f4075,f4076,f4077,f4078,f4079,f4080,f4081,f4082,f4083,f4084,f4085,f4086,f4087,f4088,f4089,f4090,f4091,f4092,f4093,f4094,f4095,f4096,f4097,f4098,f4099,f4100,f4101,f4102,f4103,f4104,f4105,f4106,f4107,f4108,f4109,f4110,f4111,f4112,f4113,f4114,f4115,f4116,f4117,f4118,f4119,f4120,f4121,f4122,f4123,f4124,f4125,f4126,f4127,f4128,f4129,f4130,f4131,f4132,f4133,f4134,f4135,f4136,f4137,f4138,f4139,f4140,f4141,f4142,f4143,f4144,f4145,f4146,f4147,f4148,f4149,f4150,f4151,f4152,f4153,f4154,f4155,f4156,f4157,f4158,f4159,f4160,f4161,f4162,f4163,f4164,f4165,f4166,f4167,f4168,f4169,f4170,f4171,f4172,f4173,f4174,f4175,f4176,f4177,f4178,f4179,f4180,f4181,f4182,f4183,f4184,f4185,f4186,f4187,f4188,f4189,f4190,f4191,f4192,f4193,f4194,f4195,f4196,f4197,f4198,f4199,f4200,f4201,f4202,f4203,f4204,f4205,f4206,f4207,f4208,f4209,f4210,f4211,f4212,f4213,f4214,f4215,f4216,f4217,f4218,f4219,f4220,f4221,f4222,f4223,f4224,f4225,f4226,f4227,f4228,f4229,f4230,f4231,f4232,f4233,f4234,f4235,f4236,f4237,f4238,f4239,f4240,f4241,f4242,f4243,f4244,f4245,f4246,f4247,f4248,f4249,f4250,f4251,f4252,f4253,f4254,f4255,f4256,f4257,f4258,f4259,f4260,f4261,f4262,f4263,f4264,f4265,f4266,f4267,f4268,f4269,f4270,f4271,f4272,f4273,f4274,f4275,f4276,f4277,f4278,f4279,f4280,f4281,f4282,f4283,f4284,f4285,f4286,f4287,f4288,f4289,f4290,f4291,f4292,f4293,f4294,f4295,f4296,f4297,f4298,f4299,f4300,f4301,f4302,f4303,f4304,f4305,f4306,f4307,f4308,f4309,f4310,f4311,f4312,f4313,f4314,f4315,f4316,f4317,f4318,f4319,f4320,f4321,f4322,f4323,f4324,f4325,f4326,f4327,f4328,f4329,f4330,f4331,f4332,f4333,f4334,f4335,f4336,f4337,f4338,f4339,f4340,f4341,f4342,f4343,f4344,f4345,f4346,f4347,f4348,f4349,f4350,f4351,f4352,f4353,f4354,f4355,f4356,f4357,f4358,f4359,f4360,f4361,f4362,f4363,f4364,f4365,f4366,f4367,f4368,f4369,f4370,f4371,f4372,f4373,f4374,f4375,f4376,f4377,f4378,f4379,f4380,f4381,f4382,f4383,f4384,f4385,f4386,f4387,f4388,f4389,f4390,f4391,f4392,f4393,f4394,f4395,f4396,f4397,f4398,f4399,f4400,f4401,f4402,f4403,f4404,f4405,f4406,f4407,f4408,f4409,f4410,f4411,f4412,f4413,f4414,f4415,f4416,f4417,f4418,f4419,f4420,f4421,f4422,f4423,f4424,f4425,f4426,f4427,f4428,f4429,f4430,f4431,f4432,f4433,f4434,f4435,f4436,f4437,f4438,f4439,f4440,f4441,f4442,f4443,f4444,f4445,f4446,f4447,f4448,f4449,f4450,f4451,f4452,f4453,f4454,f4455,f4456,f4457,f4458,f4459,f4460,f4461,f4462,f4463,f4464,f4465,f4466,f4467,f4468,f4469,f4470,f4471,f4472,f4473,f4474,f4475,f4476,f4477,f4478,f4479,f4480,f4481,f4482,f4483,f4484,f4485,f4486,f4487,f4488,f4489,f4490,f4491,f4492,f4493,f4494,f4495,f4496,f4497,f4498,f4499,f4500,f4501,f4502,f4503,f4504,f4505,f4506,f4507,f4508,f4509,f4510,f4511,f4512,f4513,f4514,f4515,f4516,f4517,f4518,f4519,f4520,f4521,f4522,f4523,f4524,f4525,f4526,f4527,f4528,f4529,f4530,f4531,f4532,f4533,f4534,f4535,f4536,f4537,f4538,f4539,f4540,f4541,f4542,f4543,f4544,f4545,f4546,f4547,f4548,f4549,f4550,f4551,f4552,f4553,f4554,f4555,f4556,f4557,f4558,f4559,f4560,f4561,f4562,f4563,f4564,f4565,f4566,f4567,f4568,f4569,f4570,f4571,f4572,f4573,f4574,f4575,f4576,f4577,f4578,f4579,f4580,f4581,f4582,f4583,f4584,f4585,f4586,f4587,f4588,f4589,f4590,f4591,f4592,f4593,f4594,f4595,f4596,f4597,f4598,f4599,f4600,f4601,f4602,f4603,f4604,f4605,f4606,f4607,f4608,f4609,f4610,f4611,f4612,f4613,f4614,f4615,f4616,f4617,f4618,f4619,f4620,f4621,f4622,f4623,f4624,f4625,f4626,f4627,f4628,f4629,f4630,f4631,f4632,f4633,f4634,f4635,f4636,f4637,f4638,f4639,f4640,f4641,f4642,f4643,f4644,f4645,f4646,f4647,f4648,f4649,f4650,f4651,f4652,f4653,f4654,f4655,f4656,f4657,f4658,f4659,f4660,f4661,f4662,f4663,f4664,f4665,f4666,f4667,f4668,f4669,f4670,f4671,f4672,f4673,f4674,f4675,f4676,f4677,f4678,f4679,f4680,f4681,f4682,f4683,f4684,f4685,f4686,f4687,f4688,f4689,f4690,f4691,f4692,f4693,f4694,f4695,f4696,f4697,f4698,f4699,f4700,f4701,f4702,f4703,f4704,f4705,f4706,f4707,f4708,f4709,f4710,f4711,f4712,f4713,f4714,f4715,f4716,f4717,f4718,f4719,f4720,f4721,f4722,f4723,f4724,f4725,f4726,f4727,f4728,f4729,f4730,f4731,f4732,f4733,f4734,f4735,f4736,f4737,f4738,f4739,f4740,f4741,f4742,f4743,f4744,f4745,f4746,f4747,f4748,f4749,f4750,f4751,f4752,f4753,f4754,f4755,f4756,f4757,f4758,f4759,f4760,f4761,f4762,f4763,f4764,f4765,f4766,f4767,f4768,f4769,f4770,f4771,f4772,f4773,f4774,f4775,f4776,f4777,f4778,f4779,f4780,f4781,f4782,f4783,f4784,f4785,f4786,f4787,f4788,f4789,f4790,f4791,f4792,f4793,f4794,f4795,f4796,f4797,f4798,f4799,f4800,f4801,f4802,f4803,f4804,f4805,f4806,f4807,f4808,f4809,f4810,f4811,f4812,f4813,f4814,f4815,f4816,f4817,f4818,f4819,f4820,f4821,f4822,f4823,f4824,f4825,f4826,f4827,f4828,f4829,f4830,f4831,f4832,f4833,f4834,f4835,f4836,f4837,f4838,f4839,f4840,f4841,f4842,f4843,f4844,f4845,f4846,f4847,f4848,f4849,f4850,f4851,f4852,f4853,f4854,f4855,f4856,f4857,f4858,f4859,f4860,f4861,f4862,f4863,f4864,f4865,f4866,f4867,f4868,f4869,f4870,f4871,f4872,f4873,f4874,f4875,f4876,f4877,f4878,f4879,f4880,f4881,f4882,f4883,f4884,f4885,f4886,f4887,f4888,f4889,f4890,f4891,f4892,f4893,f4894,f4895,f4896,f4897,f4898,f4899,f4900,f4901,f4902,f4903,f4904,f4905,f4906,f4907,f4908,f4909,f4910,f4911,f4912,f4913,f4914,f4915,f4916,f4917,f4918,f4919,f4920,f4921,f4922,f4923,f4924,f4925,f4926,f4927,f4928,f4929,f4930,f4931,f4932,f4933,f4934,f4935,f4936,f4937,f4938,f4939,f4940,f4941,f4942,f4943,f4944,f4945,f4946,f4947,f4948,f4949,f4950,f4951,f4952,f4953,f4954,f4955,f4956,f4957,f4958,f4959,f4960,f4961,f4962,f4963,f4964,f4965,f4966,f4967,f4968,f4969,f4970,f4971,f4972,f4973,f4974,f4975,f4976,f4977,f4978,f4979,f4980,f4981,f4982,f4983,f4984,f4985,f4986,f4987,f4988,f4989,f4990,f4991,f4992,f4993,f4994,f4995,f4996,f4997,f4998,f4999,f5000,f5001,f5002,f5003,f5004,f5005,f5006,f5007,f5008,f5009,f5010,f5011,f5012,f5013,f5014,f5015,f5016,f5017,f5018,f5019,f5020,f5021,f5022,f5023,f5024,f5025,f5026,f5027,f5028,f5029,f5030,f5031,f5032,f5033,f5034,f5035,f5036,f5037,f5038,f5039,f5040,f5041,f5042,f5043,f5044,f5045,f5046,f5047,f5048,f5049,f5050,f5051,f5052,f5053,f5054,f5055,f5056,f5057,f5058,f5059,f5060,f5061,f5062,f5063,f5064,f5065,f5066,f5067,f5068,f5069,f5070,f5071,f5072,f5073,f5074,f5075,f5076,f5077,f5078,f5079,f5080,f5081,f5082,f5083,f5084,f5085,f5086,f5087,f5088,f5089,f5090,f5091,f5092,f5093,f5094,f5095,f5096,f5097,f5098,f5099,f5100,f5101,f5102,f5103,f5104,f5105,f5106,f5107,f5108,f5109,f5110,f5111,f5112,f5113,f5114,f5115,f5116,f5117,f5118,f5119,f5120,f5121,f5122,f5123,f5124,f5125,f5126,f5127,f5128,f5129,f5130,f5131,f5132,f5133,f5134,f5135,f5136,f5137,f5138,f5139,f5140,f5141,f5142,f5143,f5144,f5145,f5146,f5147,f5148,f5149,f5150,f5151,f5152,f5153,f5154,f5155,f5156,f5157,f5158,f5159,f5160,f5161,f5162,f5163,f5164,f5165,f5166,f5167,f5168,f5169,f5170,f5171,f5172,f5173,f5174,f5175,f5176,f5177,f5178,f5179,f5180,f5181,f5182,f5183,f5184,f5185,f5186,f5187,f5188,f5189,f5190,f5191,f5192,f5193,f5194,f5195,f5196,f5197,f5198,f5199,f5200,f5201,f5202,f5203,f5204,f5205,f5206,f5207,f5208,f5209,f5210,f5211,f5212,f5213,f5214,f5215,f5216,f5217,f5218,f5219,f5220,f5221,f5222,f5223,f5224,f5225,f5226,f5227,f5228,f5229,f5230,f5231,f5232,f5233,f5234,f5235,f5236,f5237,f5238,f5239,f5240,f5241,f5242,f5243,f5244,f5245,f5246,f5247,f5248,f5249,f5250,f5251,f5252,f5253,f5254,f5255,f5256,f5257,f5258,f5259,f5260,f5261,f5262,f5263,f5264,f5265,f5266,f5267,f5268,f5269,f5270,f5271,f5272,f5273,f5274,f5275,f5276,f5277,f5278,f5279,f5280,f5281,f5282,f5283,f5284,f5285,f5286,f5287,f5288,f5289,f5290,f5291,f5292,f5293,f5294,f5295,f5296,f5297,f5298,f5299,f5300,f5301,f5302,f5303,f5304,f5305,f5306,f5307,f5308,f5309,f5310,f5311,f5312,f5313,f5314,f5315,f5316,f5317,f5318,f5319,f5320,f5321,f5322,f5323,f5324,f5325,f5326,f5327,f5328,f5329,f5330,f5331,f5332,f5333,f5334,f5335,f5336,f5337,f5338,f5339,f5340,f5341,f5342,f5343,f5344,f5345,f5346,f5347,f5348,f5349,f5350,f5351,f5352,f5353,f5354,f5355,f5356,f5357,f5358,f5359,f5360,f5361,f5362,f5363,f5364,f5365,f5366,f5367,f5368,f5369,f5370,f5371,f5372,f5373,f5374,f5375,f5376,f5377,f5378,f5379,f5380,f5381,f5382,f5383,f5384,f5385,f5386,f5387,f5388,f5389,f5390,f5391,f5392,f5393,f5394,f5395,f5396,f5397,f5398,f5399,f5400,f5401,f5402,f5403,f5404,f5405,f5406,f5407,f5408,f5409,f5410,f5411,f5412,f5413,f5414,f5415,f5416,f5417,f5418,f5419,f5420,f5421,f5422,f5423,f5424,f5425,f5426,f5427,f5428,f5429,f5430,f5431,f5432,f5433,f5434,f5435,f5436,f5437,f5438,f5439,f5440,f5441,f5442,f5443,f5444,f5445,f5446,f5447,f5448,f5449,f5450,f5451,f5452,f5453,f5454,f5455,f5456,f5457,f5458,f5459,f5460,f5461,f5462,f5463,f5464,f5465,f5466,f5467,f5468,f5469,f5470,f5471,f5472,f5473,f5474,f5475,f5476,f5477,f5478,f5479,f5480,f5481,f5482,f5483,f5484,f5485,f5486,f5487,f5488,f5489,f5490,f5491,f5492,f5493,f5494,f5495,f5496,f5497,f5498,f5499,f5500,f5501,f5502,f5503,f5504,f5505,f5506,f5507,f5508,f5509,f5510,f5511,f5512,f5513,f5514,f5515,f5516,f5517,f5518,f5519,f5520,f5521,f5522,f5523,f5524,f5525,f5526,f5527,f5528,f5529,f5530,f5531,f5532,f5533,f5534,f5535,f5536,f5537,f5538,f5539,f5540,f5541,f5542,f5543,f5544,f5545,f5546,f5547,f5548,f5549,f5550,f5551,f5552,f5553,f5554,f5555,f5556,f5557,f5558,f5559,f5560,f5561,f5562,f5563,f5564,f5565,f5566,f5567,f5568,f5569,f5570,f5571,f5572,f5573,f5574,f5575,f5576,f5577,f5578,f5579,f5580,f5581,f5582,f5583,f5584,f5585,f5586,f5587,f5588,f5589,f5590,f5591,f5592,f5593,f5594,f5595,f5596,f5597,f5598,f5599,f5600,f5601,f5602,f5603,f5604,f5605,f5606,f5607,f5608,f5609,f5610,f5611,f5612,f5613,f5614,f5615,f5616,f5617,f5618,f5619,f5620,f5621,f5622,f5623,f5624,f5625,f5626,f5627,f5628,f5629,f5630,f5631,f5632,f5633,f5634,f5635,f5636,f5637,f5638,f5639,f5640,f5641,f5642,f5643,f5644,f5645,f5646,f5647,f5648,f5649,f5650,f5651,f5652,f5653,f5654,f5655,f5656,f5657,f5658,f5659,f5660,f5661,f5662,f5663,f5664,f5665,f5666,f5667,f5668,f5669,f5670,f5671,f5672,f5673,f5674,f5675,f5676,f5677,f5678,f5679,f5680,f5681,f5682,f5683,f5684,f5685,f5686,f5687,f5688,f5689,f5690,f5691,f5692,f5693,f5694,f5695,f5696,f5697,f5698,f5699,f5700,f5701,f5702,f5703,f5704,f5705,f5706,f5707,f5708,f5709,f5710,f5711,f5712,f5713,f5714,f5715,f5716,f5717,f5718,f5719,f5720,f5721,f5722,f5723,f5724,f5725,f5726,f5727,f5728,f5729,f5730,f5731,f5732,f5733,f5734,f5735,f5736,f5737,f5738,f5739,f5740,f5741,f5742,f5743,f5744,f5745,f5746,f5747,f5748,f5749,f5750,f5751,f5752,f5753,f5754,f5755,f5756,f5757,f5758,f5759,f5760,f5761,f5762,f5763,f5764,f5765,f5766,f5767,f5768,f5769,f5770,f5771,f5772,f5773,f5774,f5775,f5776,f5777,f5778,f5779,f5780,f5781,f5782,f5783,f5784,f5785,f5786,f5787,f5788,f5789,f5790,f5791,f5792,f5793,f5794,f5795,f5796,f5797,f5798,f5799,f5800,f5801,f5802,f5803,f5804,f5805,f5806,f5807,f5808,f5809,f5810,f5811,f5812,f5813,f5814,f5815,f5816,f5817,f5818,f5819,f5820,f5821,f5822,f5823,f5824,f5825,f5826,f5827,f5828,f5829,f5830,f5831,f5832,f5833,f5834,f5835,f5836,f5837,f5838,f5839,f5840,f5841,f5842,f5843,f5844,f5845,f5846,f5847,f5848,f5849,f5850,f5851,f5852,f5853,f5854,f5855,f5856,f5857,f5858,f5859,f5860,f5861,f5862,f5863,f5864,f5865,f5866,f5867,f5868,f5869,f5870,f5871,f5872,f5873,f5874,f5875,f5876,f5877,f5878,f5879,f5880,f5881,f5882,f5883,f5884,f5885,f5886,f5887,f5888,f5889,f5890,f5891,f5892,f5893,f5894,f5895,f5896,f5897,f5898,f5899,f5900,f5901,f5902,f5903,f5904,f5905,f5906,f5907,f5908,f5909,f5910,f5911,f5912,f5913,f5914,f5915,f5916,f5917,f5918,f5919,f5920,f5921,f5922,f5923,f5924,f5925,f5926,f5927,f5928,f5929,f5930,f5931,f5932,f5933,f5934,f5935,f5936,f5937,f5938,f5939,f5940,f5941,f5942,f5943,f5944,f5945,f5946,f5947,f5948,f5949,f5950,f5951,f5952,f5953,f5954,f5955,f5956,f5957,f5958,f5959,f5960,f5961,f5962,f5963,f5964,f5965,f5966,f5967,f5968,f5969,f5970,f5971,f5972,f5973,f5974,f5975,f5976,f5977,f5978,f5979,f5980,f5981,f5982,f5983,f5984,f5985,f5986,f5987,f5988,f5989,f5990,f5991,f5992,f5993,f5994,f5995,f5996,f5997,f5998,f5999,f6000,f6001,f6002,f6003,f6004,f6005,f6006,f6007,f6008,f6009,f6010,f6011,f6012,f6013,f6014,f6015,f6016,f6017,f6018,f6019,f6020,f6021,f6022,f6023,f6024,f6025,f6026,f6027,f6028,f6029,f6030,f6031,f6032,f6033,f6034,f6035,f6036,f6037,f6038,f6039,f6040,f6041,f6042,f6043,f6044,f6045,f6046,f6047,f6048,f6049,f6050,f6051,f6052,f6053,f6054,f6055,f6056,f6057,f6058,f6059,f6060,f6061,f6062,f6063,f6064,f6065,f6066,f6067,f6068,f6069,f6070,f6071,f6072,f6073,f6074,f6075,f6076,f6077,f6078,f6079,f6080,f6081,f6082,f6083,f6084,f6085,f6086,f6087,f6088,f6089,f6090,f6091,f6092,f6093,f6094,f6095,f6096,f6097,f6098,f6099,f6100,f6101,f6102,f6103,f6104,f6105,f6106,f6107,f6108,f6109,f6110,f6111,f6112,f6113,f6114,f6115,f6116,f6117,f6118,f6119,f6120,f6121,f6122,f6123,f6124,f6125,f6126,f6127,f6128,f6129,f6130,f6131,f6132,f6133,f6134,f6135,f6136,f6137,f6138,f6139,f6140,f6141,f6142,f6143,f6144,f6145,f6146,f6147,f6148,f6149,f6150,f6151,f6152,f6153,f6154,f6155,f6156,f6157,f6158,f6159,f6160,f6161,f6162,f6163,f6164,f6165,f6166,f6167,f6168,f6169,f6170,f6171,f6172,f6173,f6174,f6175,f6176,f6177,f6178,f6179,f6180,f6181,f6182,f6183,f6184,f6185,f6186,f6187,f6188,f6189,f6190,f6191,f6192,f6193,f6194,f6195,f6196,f6197,f6198,f6199,f6200,f6201,f6202,f6203,f6204,f6205,f6206,f6207,f6208,f6209,f6210,f6211,f6212,f6213,f6214,f6215,f6216,f6217,f6218,f6219,f6220,f6221,f6222,f6223,f6224,f6225,f6226,f6227,f6228,f6229,f6230,f6231,f6232,f6233,f6234,f6235,f6236,f6237,f6238,f6239,f6240,f6241,f6242,f6243,f6244,f6245,f6246,f6247,f6248,f6249,f6250,f6251,f6252,f6253,f6254,f6255,f6256,f6257,f6258,f6259,f6260,f6261,f6262,f6263,f6264,f6265,f6266,f6267,f6268,f6269,f6270,f6271,f6272,f6273,f6274,f6275,f6276,f6277,f6278,f6279,f6280,f6281,f6282,f6283,f6284,f6285,f6286,f6287,f6288,f6289,f6290,f6291,f6292,f6293,f6294,f6295,f6296,f6297,f6298,f6299,f6300,f6301,f6302,f6303,f6304,f6305,f6306,f6307,f6308,f6309,f6310,f6311,f6312,f6313,f6314,f6315,f6316,f6317,f6318,f6319,f6320,f6321,f6322,f6323,f6324,f6325,f6326,f6327,f6328,f6329,f6330,f6331,f6332,f6333,f6334,f6335,f6336,f6337,f6338,f6339,f6340,f6341,f6342,f6343,f6344,f6345,f6346,f6347,f6348,f6349,f6350,f6351,f6352,f6353,f6354,f6355,f6356,f6357,f6358,f6359,f6360,f6361,f6362,f6363,f6364,f6365,f6366,f6367,f6368,f6369,f6370,f6371,f6372,f6373,f6374,f6375,f6376,f6377,f6378,f6379,f6380,f6381,f6382,f6383,f6384,f6385,f6386,f6387,f6388,f6389,f6390,f6391,f6392,f6393,f6394,f6395,f6396,f6397,f6398,f6399,f6400,f6401,f6402,f6403,f6404,f6405,f6406,f6407,f6408,f6409,f6410,f6411,f6412,f6413,f6414,f6415,f6416,f6417,f6418,f6419,f6420,f6421,f6422,f6423,f6424,f6425,f6426,f6427,f6428,f6429,f6430,f6431,f6432,f6433,f6434,f6435,f6436,f6437,f6438,f6439,f6440,f6441,f6442,f6443,f6444,f6445,f6446,f6447,f6448,f6449,f6450,f6451,f6452,f6453,f6454,f6455,f6456,f6457,f6458,f6459,f6460,f6461,f6462,f6463,f6464,f6465,f6466,f6467,f6468,f6469,f6470,f6471,f6472,f6473,f6474,f6475,f6476,f6477,f6478,f6479,f6480,f6481,f6482,f6483,f6484,f6485,f6486,f6487,f6488,f6489,f6490,f6491,f6492,f6493,f6494,f6495,f6496,f6497,f6498,f6499,f6500,f6501,f6502,f6503,f6504,f6505,f6506,f6507,f6508,f6509,f6510,f6511,f6512,f6513,f6514,f6515,f6516,f6517,f6518,f6519,f6520,f6521,f6522,f6523,f6524,f6525,f6526,f6527,f6528,f6529,f6530,f6531,f6532,f6533,f6534,f6535,f6536,f6537,f6538,f6539,f6540,f6541,f6542,f6543,f6544,f6545,f6546,f6547,f6548,f6549,f6550,f6551,f6552,f6553,f6554,f6555,f6556,f6557,f6558,f6559,f6560,f6561,f6562,f6563,f6564,f6565,f6566,f6567,f6568,f6569,f6570,f6571,f6572,f6573,f6574,f6575,f6576,f6577,f6578,f6579,f6580,f6581,f6582,f6583,f6584,f6585,f6586,f6587,f6588,f6589,f6590,f6591,f6592,f6593,f6594,f6595,f6596,f6597,f6598,f6599,f6600,f6601,f6602,f6603,f6604,f6605,f6606,f6607,f6608,f6609,f6610,f6611,f6612,f6613,f6614,f6615,f6616,f6617,f6618,f6619,f6620,f6621,f6622,f6623,f6624,f6625,f6626,f6627,f6628,f6629,f6630,f6631,f6632,f6633,f6634,f6635,f6636,f6637,f6638,f6639,f6640,f6641,f6642,f6643,f6644,f6645,f6646,f6647,f6648,f6649,f6650,f6651,f6652,f6653,f6654,f6655,f6656,f6657,f6658,f6659,f6660,f6661,f6662,f6663,f6664,f6665,f6666,f6667,f6668,f6669,f6670,f6671,f6672,f6673,f6674,f6675,f6676,f6677,f6678,f6679,f6680,f6681,f6682,f6683,f6684,f6685,f6686,f6687,f6688,f6689,f6690,f6691,f6692,f6693,f6694,f6695,f6696,f6697,f6698,f6699,f6700,f6701,f6702,f6703,f6704,f6705,f6706,f6707,f6708,f6709,f6710,f6711,f6712,f6713,f6714,f6715,f6716,f6717,f6718,f6719,f6720,f6721,f6722,f6723,f6724,f6725,f6726,f6727,f6728,f6729,f6730,f6731,f6732,f6733,f6734,f6735,f6736,f6737,f6738,f6739,f6740,f6741,f6742,f6743,f6744,f6745,f6746,f6747,f6748,f6749,f6750,f6751,f6752,f6753,f6754,f6755,f6756,f6757,f6758,f6759,f6760,f6761,f6762,f6763,f6764,f6765,f6766,f6767,f6768,f6769,f6770,f6771,f6772,f6773,f6774,f6775,f6776,f6777,f6778,f6779,f6780,f6781,f6782,f6783,f6784,f6785,f6786,f6787,f6788,f6789,f6790,f6791,f6792,f6793,f6794,f6795,f6796,f6797,f6798,f6799,f6800,f6801,f6802,f6803,f6804,f6805,f6806,f6807,f6808,f6809,f6810,f6811,f6812,f6813,f6814,f6815,f6816,f6817,f6818,f6819,f6820,f6821,f6822,f6823,f6824,f6825,f6826,f6827,f6828,f6829,f6830,f6831,f6832,f6833,f6834,f6835,f6836,f6837,f6838,f6839,f6840,f6841,f6842,f6843,f6844,f6845,f6846,f6847,f6848,f6849,f6850,f6851,f6852,f6853,f6854,f6855,f6856,f6857,f6858,f6859,f6860,f6861,f6862,f6863,f6864,f6865,f6866,f6867,f6868,f6869,f6870,f6871,f6872,f6873,f6874,f6875,f6876,f6877,f6878,f6879,f6880,f6881,f6882,f6883,f6884,f6885,f6886,f6887,f6888,f6889,f6890,f6891,f6892,f6893,f6894,f6895,f6896,f6897,f6898,f6899,f6900,f6901,f6902,f6903,f6904,f6905,f6906,f6907,f6908,f6909,f6910,f6911,f6912,f6913,f6914,f6915,f6916,f6917,f6918,f6919,f6920,f6921,f6922,f6923,f6924,f6925,f6926,f6927,f6928,f6929,f6930,f6931,f6932,f6933,f6934,f6935,f6936,f6937,f6938,f6939,f6940,f6941,f6942,f6943,f6944,f6945,f6946,f6947,f6948,f6949,f6950,f6951,f6952,f6953,f6954,f6955,f6956,f6957,f6958,f6959,f6960,f6961,f6962,f6963,f6964,f6965,f6966,f6967,f6968,f6969,f6970,f6971,f6972,f6973,f6974,f6975,f6976,f6977,f6978,f6979,f6980,f6981,f6982,f6983,f6984,f6985,f6986,f6987,f6988,f6989,f6990,f6991,f6992,f6993,f6994,f6995,f6996,f6997,f6998,f6999,f7000,f7001,f7002,f7003,f7004,f7005,f7006,f7007,f7008,f7009,f7010,f7011,f7012,f7013,f7014,f7015,f7016,f7017,f7018,f7019,f7020,f7021,f7022,f7023,f7024,f7025,f7026,f7027,f7028,f7029,f7030,f7031,f7032,f7033,f7034,f7035,f7036,f7037,f7038,f7039,f7040,f7041,f7042,f7043,f7044,f7045,f7046,f7047,f7048,f7049,f7050,f7051,f7052,f7053,f7054,f7055,f7056,f7057,f7058,f7059,f7060,f7061,f7062,f7063,f7064,f7065,f7066,f7067,f7068,f7069,f7070,f7071,f7072,f7073,f7074,f7075,f7076,f7077,f7078,f7079,f7080,f7081,f7082,f7083,f7084,f7085,f7086,f7087,f7088,f7089,f7090,f7091,f7092,f7093,f7094,f7095,f7096,f7097,f7098,f7099,f7100,f7101,f7102,f7103,f7104,f7105,f7106,f7107,f7108,f7109,f7110,f7111,f7112,f7113,f7114,f7115,f7116,f7117,f7118,f7119,f7120,f7121,f7122,f7123,f7124,f7125,f7126,f7127,f7128,f7129,f7130,f7131,f7132,f7133,f7134,f7135,f7136,f7137,f7138,f7139,f7140,f7141,f7142,f7143,f7144,f7145,f7146,f7147,f7148,f7149,f7150,f7151,f7152,f7153,f7154,f7155,f7156,f7157,f7158,f7159,f7160,f7161,f7162,f7163,f7164,f7165,f7166,f7167,f7168,f7169,f7170,f7171,f7172,f7173,f7174,f7175,f7176,f7177,f7178,f7179,f7180,f7181,f7182,f7183,f7184,f7185,f7186,f7187,f7188,f7189,f7190,f7191,f7192,f7193,f7194,f7195,f7196,f7197,f7198,f7199,f7200,f7201,f7202,f7203,f7204,f7205,f7206,f7207,f7208,f7209,f7210,f7211,f7212,f7213,f7214,f7215,f7216,f7217,f7218,f7219,f7220,f7221,f7222,f7223,f7224,f7225,f7226,f7227,f7228,f7229,f7230,f7231,f7232,f7233,f7234,f7235,f7236,f7237,f7238,f7239,f7240,f7241,f7242,f7243,f7244,f7245,f7246,f7247,f7248,f7249,f7250,f7251,f7252,f7253,f7254,f7255,f7256,f7257,f7258,f7259,f7260,f7261,f7262,f7263,f7264,f7265,f7266,f7267,f7268,f7269,f7270,f7271,f7272,f7273,f7274,f7275,f7276,f7277,f7278,f7279,f7280,f7281,f7282,f7283,f7284,f7285,f7286,f7287,f7288,f7289,f7290,f7291,f7292,f7293,f7294,f7295,f7296,f7297,f7298,f7299,f7300,f7301,f7302,f7303,f7304,f7305,f7306,f7307,f7308,f7309,f7310,f7311,f7312,f7313,f7314,f7315,f7316,f7317,f7318,f7319,f7320,f7321,f7322,f7323,f7324,f7325,f7326,f7327,f7328,f7329,f7330,f7331,f7332,f7333,f7334,f7335,f7336,f7337,f7338,f7339,f7340,f7341,f7342,f7343,f7344,f7345,f7346,f7347,f7348,f7349,f7350,f7351,f7352,f7353,f7354,f7355,f7356,f7357,f7358,f7359,f7360,f7361,f7362,f7363,f7364,f7365,f7366,f7367,f7368,f7369,f7370,f7371,f7372,f7373,f7374,f7375,f7376,f7377,f7378,f7379,f7380,f7381,f7382,f7383,f7384,f7385,f7386,f7387,f7388,f7389,f7390,f7391,f7392,f7393,f7394,f7395,f7396,f7397,f7398,f7399,f7400,f7401,f7402,f7403,f7404,f7405,f7406,f7407,f7408,f7409,f7410,f7411,f7412,f7413,f7414,f7415,f7416,f7417,f7418,f7419,f7420,f7421,f7422,f7423,f7424,f7425,f7426,f7427,f7428,f7429,f7430,f7431,f7432,f7433,f7434,f7435,f7436,f7437,f7438,f7439,f7440,f7441,f7442,f7443,f7444,f7445,f7446,f7447,f7448,f7449,f7450,f7451,f7452,f7453,f7454,f7455,f7456,f7457,f7458,f7459,f7460,f7461,f7462,f7463,f7464,f7465,f7466,f7467,f7468,f7469,f7470,f7471,f7472,f7473,f7474,f7475,f7476,f7477,f7478,f7479,f7480,f7481,f7482,f7483,f7484,f7485,f7486,f7487,f7488,f7489,f7490,f7491,f7492,f7493,f7494,f7495,f7496,f7497,f7498,f7499,f7500,f7501,f7502,f7503,f7504,f7505,f7506,f7507,f7508,f7509,f7510,f7511,f7512,f7513,f7514,f7515,f7516,f7517,f7518,f7519,f7520,f7521,f7522,f7523,f7524,f7525,f7526,f7527,f7528,f7529,f7530,f7531,f7532,f7533,f7534,f7535,f7536,f7537,f7538,f7539,f7540,f7541,f7542,f7543,f7544,f7545,f7546,f7547,f7548,f7549,f7550,f7551,f7552,f7553,f7554,f7555,f7556,f7557,f7558,f7559,f7560,f7561,f7562,f7563,f7564,f7565,f7566,f7567,f7568,f7569,f7570,f7571,f7572,f7573,f7574,f7575,f7576,f7577,f7578,f7579,f7580,f7581,f7582,f7583,f7584,f7585,f7586,f7587,f7588,f7589,f7590,f7591,f7592,f7593,f7594,f7595,f7596,f7597,f7598,f7599,f7600,f7601,f7602,f7603,f7604,f7605,f7606,f7607,f7608,f7609,f7610,f7611,f7612,f7613,f7614,f7615,f7616,f7617,f7618,f7619,f7620,f7621,f7622,f7623,f7624,f7625,f7626,f7627,f7628,f7629,f7630,f7631,f7632,f7633,f7634,f7635,f7636,f7637,f7638,f7639,f7640,f7641,f7642,f7643,f7644,f7645,f7646,f7647,f7648,f7649,f7650,f7651,f7652,f7653,f7654,f7655,f7656,f7657,f7658,f7659,f7660,f7661,f7662,f7663,f7664,f7665,f7666,f7667,f7668,f7669,f7670,f7671,f7672,f7673,f7674,f7675,f7676,f7677,f7678,f7679,f7680,f7681,f7682,f7683,f7684,f7685,f7686,f7687,f7688,f7689,f7690,f7691,f7692,f7693,f7694,f7695,f7696,f7697,f7698,f7699,f7700,f7701,f7702,f7703,f7704,f7705,f7706,f7707,f7708,f7709,f7710,f7711,f7712,f7713,f7714,f7715,f7716,f7717,f7718,f7719,f7720,f7721,f7722,f7723,f7724,f7725,f7726,f7727,f7728,f7729,f7730,f7731,f7732,f7733,f7734,f7735,f7736,f7737,f7738,f7739,f7740,f7741,f7742,f7743,f7744,f7745,f7746,f7747,f7748,f7749,f7750,f7751,f7752,f7753,f7754,f7755,f7756,f7757,f7758,f7759,f7760,f7761,f7762,f7763,f7764,f7765,f7766,f7767,f7768,f7769,f7770,f7771,f7772,f7773,f7774,f7775,f7776,f7777,f7778,f7779,f7780,f7781,f7782,f7783,f7784,f7785,f7786,f7787,f7788,f7789,f7790,f7791,f7792,f7793,f7794,f7795,f7796,f7797,f7798,f7799,f7800,f7801,f7802,f7803,f7804,f7805,f7806,f7807,f7808,f7809,f7810,f7811,f7812,f7813,f7814,f7815,f7816,f7817,f7818,f7819,f7820,f7821,f7822,f7823,f7824,f7825,f7826,f7827,f7828,f7829,f7830,f7831,f7832,f7833,f7834,f7835,f7836,f7837,f7838,f7839,f7840,f7841,f7842,f7843,f7844,f7845,f7846,f7847,f7848,f7849,f7850,f7851,f7852,f7853,f7854,f7855,f7856,f7857,f7858,f7859,f7860,f7861,f7862,f7863,f7864,f7865,f7866,f7867,f7868,f7869,f7870,f7871,f7872,f7873,f7874,f7875,f7876,f7877,f7878,f7879,f7880,f7881,f7882,f7883,f7884,f7885,f7886,f7887,f7888,f7889,f7890,f7891,f7892,f7893,f7894,f7895,f7896,f7897,f7898,f7899,f7900,f7901,f7902,f7903,f7904,f7905,f7906,f7907,f7908,f7909,f7910,f7911,f7912,f7913,f7914,f7915,f7916,f7917,f7918,f7919,f7920,f7921,f7922,f7923,f7924,f7925,f7926,f7927,f7928,f7929,f7930,f7931,f7932,f7933,f7934,f7935,f7936,f7937,f7938,f7939,f7940,f7941,f7942,f7943,f7944,f7945,f7946,f7947,f7948,f7949,f7950,f7951,f7952,f7953,f7954,f7955,f7956,f7957,f7958,f7959,f7960,f7961,f7962,f7963,f7964,f7965,f7966,f7967,f7968,f7969,f7970,f7971,f7972,f7973,f7974,f7975,f7976,f7977,f7978,f7979,f7980,f7981,f7982,f7983,f7984,f7985,f7986,f7987,f7988,f7989,f7990,f7991,f7992,f7993,f7994,f7995,f7996,f7997,f7998,f7999,f8000,f8001,f8002,f8003,f8004,f8005,f8006,f8007,f8008,f8009,f8010,f8011,f8012,f8013,f8014,f8015,f8016,f8017,f8018,f8019,f8020,f8021,f8022,f8023,f8024,f8025,f8026,f8027,f8028,f8029,f8030,f8031,f8032,f8033,f8034,f8035,f8036,f8037,f8038,f8039,f8040,f8041,f8042,f8043,f8044,f8045,f8046,f8047,f8048,f8049,f8050,f8051,f8052,f8053,f8054,f8055,f8056,f8057,f8058,f8059,f8060,f8061,f8062,f8063,f8064,f8065,f8066,f8067,f8068,f8069,f8070,f8071,f8072,f8073,f8074,f8075,f8076,f8077,f8078,f8079,f8080,f8081,f8082,f8083,f8084,f8085,f8086,f8087,f8088,f8089,f8090,f8091,f8092,f8093,f8094,f8095,f8096,f8097,f8098,f8099,f8100,f8101,f8102,f8103,f8104,f8105,f8106,f8107,f8108,f8109,f8110,f8111,f8112,f8113,f8114,f8115,f8116,f8117,f8118,f8119,f8120,f8121,f8122,f8123,f8124,f8125,f8126,f8127,f8128,f8129,f8130,f8131,f8132,f8133,f8134,f8135,f8136,f8137,f8138,f8139,f8140,f8141,f8142,f8143,f8144,f8145,f8146,f8147,f8148,f8149,f8150,f8151,f8152,f8153,f8154,f8155,f8156,f8157,f8158,f8159,f8160,f8161,f8162,f8163,f8164,f8165,f8166,f8167,f8168,f8169,f8170,f8171,f8172,f8173,f8174,f8175,f8176,f8177,f8178,f8179,f8180,f8181,f8182,f8183,f8184,f8185,f8186,f8187,f8188,f8189,f8190,f8191,f8192,f8193,f8194,f8195,f8196,f8197,f8198,f8199,f8200,f8201,f8202,f8203,f8204,f8205,f8206,f8207,f8208,f8209,f8210,f8211,f8212,f8213,f8214,f8215,f8216,f8217,f8218,f8219,f8220,f8221,f8222,f8223,f8224,f8225,f8226,f8227,f8228,f8229,f8230,f8231,f8232,f8233,f8234,f8235,f8236,f8237,f8238,f8239,f8240,f8241,f8242,f8243,f8244,f8245,f8246,f8247,f8248,f8249,f8250,f8251,f8252,f8253,f8254,f8255,f8256,f8257,f8258,f8259,f8260,f8261,f8262,f8263,f8264,f8265,f8266,f8267,f8268,f8269,f8270,f8271,f8272,f8273,f8274,f8275,f8276,f8277,f8278,f8279,f8280,f8281,f8282,f8283,f8284,f8285,f8286,f8287,f8288,f8289,f8290,f8291,f8292,f8293,f8294,f8295,f8296,f8297,f8298,f8299,f8300,f8301,f8302,f8303,f8304,f8305,f8306,f8307,f8308,f8309,f8310,f8311,f8312,f8313,f8314,f8315,f8316,f8317,f8318,f8319,f8320,f8321,f8322,f8323,f8324,f8325,f8326,f8327,f8328,f8329,f8330,f8331,f8332,f8333,f8334,f8335,f8336,f8337,f8338,f8339,f8340,f8341,f8342,f8343,f8344,f8345,f8346,f8347,f8348,f8349,f8350,f8351,f8352,f8353,f8354,f8355,f8356,f8357,f8358,f8359,f8360,f8361,f8362,f8363,f8364,f8365,f8366,f8367,f8368,f8369,f8370,f8371,f8372,f8373,f8374,f8375,f8376,f8377,f8378,f8379,f8380,f8381,f8382,f8383,f8384,f8385,f8386,f8387,f8388,f8389,f8390,f8391,f8392,f8393,f8394,f8395,f8396,f8397,f8398,f8399,f8400,f8401,f8402,f8403,f8404,f8405,f8406,f8407,f8408,f8409,f8410,f8411,f8412,f8413,f8414,f8415,f8416,f8417,f8418,f8419,f8420,f8421,f8422,f8423,f8424,f8425,f8426,f8427,f8428,f8429,f8430,f8431,f8432,f8433,f8434,f8435,f8436,f8437,f8438,f8439,f8440,f8441,f8442,f8443,f8444,f8445,f8446,f8447,f8448,f8449,f8450,f8451,f8452,f8453,f8454,f8455,f8456,f8457,f8458,f8459,f8460,f8461,f8462,f8463,f8464,f8465,f8466,f8467,f8468,f8469,f8470,f8471,f8472,f8473,f8474,f8475,f8476,f8477,f8478,f8479,f8480,f8481,f8482,f8483,f8484,f8485,f8486,f8487,f8488,f8489,f8490,f8491,f8492,f8493,f8494,f8495,f8496,f8497,f8498,f8499,f8500,f8501,f8502,f8503,f8504,f8505,f8506,f8507,f8508,f8509,f8510,f8511,f8512,f8513,f8514,f8515,f8516,f8517,f8518,f8519,f8520,f8521,f8522,f8523,f8524,f8525,f8526,f8527,f8528,f8529,f8530,f8531,f8532,f8533,f8534,f8535,f8536,f8537,f8538,f8539,f8540,f8541,f8542,f8543,f8544,f8545,f8546,f8547,f8548,f8549,f8550,f8551,f8552,f8553,f8554,f8555,f8556,f8557,f8558,f8559,f8560,f8561,f8562,f8563,f8564,f8565,f8566,f8567,f8568,f8569,f8570,f8571,f8572,f8573,f8574,f8575,f8576,f8577,f8578,f8579,f8580,f8581,f8582,f8583,f8584,f8585,f8586,f8587,f8588,f8589,f8590,f8591,f8592,f8593,f8594,f8595,f8596,f8597,f8598,f8599,f8600,f8601,f8602,f8603,f8604,f8605,f8606,f8607,f8608,f8609,f8610,f8611,f8612,f8613,f8614,f8615,f8616,f8617,f8618,f8619,f8620,f8621,f8622,f8623,f8624,f8625,f8626,f8627,f8628,f8629,f8630,f8631,f8632,f8633,f8634,f8635,f8636,f8637,f8638,f8639,f8640,f8641,f8642,f8643,f8644,f8645,f8646,f8647,f8648,f8649,f8650,f8651,f8652,f8653,f8654,f8655,f8656,f8657,f8658,f8659,f8660,f8661,f8662,f8663,f8664,f8665,f8666,f8667,f8668,f8669,f8670,f8671,f8672,f8673,f8674,f8675,f8676,f8677,f8678,f8679,f8680,f8681,f8682,f8683,f8684,f8685,f8686,f8687,f8688,f8689,f8690,f8691,f8692,f8693,f8694,f8695,f8696,f8697,f8698,f8699,f8700,f8701,f8702,f8703,f8704,f8705,f8706,f8707,f8708,f8709,f8710,f8711,f8712,f8713,f8714,f8715,f8716,f8717,f8718,f8719,f8720,f8721,f8722,f8723,f8724,f8725,f8726,f8727,f8728,f8729,f8730,f8731,f8732,f8733,f8734,f8735,f8736,f8737,f8738,f8739,f8740,f8741,f8742,f8743,f8744,f8745,f8746,f8747,f8748,f8749,f8750,f8751,f8752,f8753,f8754,f8755,f8756,f8757,f8758,f8759,f8760,f8761,f8762,f8763,f8764,f8765,f8766,f8767,f8768,f8769,f8770,f8771,f8772,f8773,f8774,f8775,f8776,f8777,f8778,f8779,f8780,f8781,f8782,f8783,f8784,f8785,f8786,f8787,f8788,f8789,f8790,f8791,f8792,f8793,f8794,f8795,f8796,f8797,f8798,f8799,f8800,f8801,f8802,f8803,f8804,f8805,f8806,f8807,f8808,f8809,f8810,f8811,f8812,f8813,f8814,f8815,f8816,f8817,f8818,f8819,f8820,f8821,f8822,f8823,f8824,f8825,f8826,f8827,f8828,f8829,f8830,f8831,f8832,f8833,f8834,f8835,f8836,f8837,f8838,f8839,f8840,f8841,f8842,f8843,f8844,f8845,f8846,f8847,f8848,f8849,f8850,f8851,f8852,f8853,f8854,f8855,f8856,f8857,f8858,f8859,f8860,f8861,f8862,f8863,f8864,f8865,f8866,f8867,f8868,f8869,f8870,f8871,f8872,f8873,f8874,f8875,f8876,f8877,f8878,f8879,f8880,f8881,f8882,f8883,f8884,f8885,f8886,f8887,f8888,f8889,f8890,f8891,f8892,f8893,f8894,f8895,f8896,f8897,f8898,f8899,f8900,f8901,f8902,f8903,f8904,f8905,f8906,f8907,f8908,f8909,f8910,f8911,f8912,f8913,f8914,f8915,f8916,f8917,f8918,f8919,f8920,f8921,f8922,f8923,f8924,f8925,f8926,f8927,f8928,f8929,f8930,f8931,f8932,f8933,f8934,f8935,f8936,f8937,f8938,f8939,f8940,f8941,f8942,f8943,f8944,f8945,f8946,f8947,f8948,f8949,f8950,f8951,f8952,f8953,f8954,f8955,f8956,f8957,f8958,f8959,f8960,f8961,f8962,f8963,f8964,f8965,f8966,f8967,f8968,f8969,f8970,f8971,f8972,f8973,f8974,f8975,f8976,f8977,f8978,f8979,f8980,f8981,f8982,f8983,f8984,f8985,f8986,f8987,f8988,f8989,f8990,f8991,f8992,f8993,f8994,f8995,f8996,f8997,f8998,f8999,f9000,f9001,f9002,f9003,f9004,f9005,f9006,f9007,f9008,f9009,f9010,f9011,f9012,f9013,f9014,f9015,f9016,f9017,f9018,f9019,f9020,f9021,f9022,f9023,f9024,f9025,f9026,f9027,f9028,f9029,f9030,f9031,f9032,f9033,f9034,f9035,f9036,f9037,f9038,f9039,f9040,f9041,f9042,f9043,f9044,f9045,f9046,f9047,f9048,f9049,f9050,f9051,f9052,f9053,f9054,f9055,f9056,f9057,f9058,f9059,f9060,f9061,f9062,f9063,f9064,f9065,f9066,f9067,f9068,f9069,f9070,f9071,f9072,f9073,f9074,f9075,f9076,f9077,f9078,f9079,f9080,f9081,f9082,f9083,f9084,f9085,f9086,f9087,f9088,f9089,f9090,f9091,f9092,f9093,f9094,f9095,f9096,f9097,f9098,f9099,f9100,f9101,f9102,f9103,f9104,f9105,f9106,f9107,f9108,f9109,f9110,f9111,f9112,f9113,f9114,f9115,f9116,f9117,f9118,f9119,f9120,f9121,f9122,f9123,f9124,f9125,f9126,f9127,f9128,f9129,f9130,f9131,f9132,f9133,f9134,f9135,f9136,f9137,f9138,f9139,f9140,f9141,f9142,f9143,f9144,f9145,f9146,f9147,f9148,f9149,f9150,f9151,f9152,f9153,f9154,f9155,f9156,f9157,f9158,f9159,f9160,f9161,f9162,f9163,f9164,f9165,f9166,f9167,f9168,f9169,f9170,f9171,f9172,f9173,f9174,f9175,f9176,f9177,f9178,f9179,f9180,f9181,f9182,f9183,f9184,f9185,f9186,f9187,f9188,f9189,f9190,f9191,f9192,f9193,f9194,f9195,f9196,f9197,f9198,f9199,f9200,f9201,f9202,f9203,f9204,f9205,f9206,f9207,f9208,f9209,f9210,f9211,f9212,f9213,f9214,f9215,f9216,f9217,f9218,f9219,f9220,f9221,f9222,f9223,f9224,f9225,f9226,f9227,f9228,f9229,f9230,f9231,f9232,f9233,f9234,f9235,f9236,f9237,f9238,f9239,f9240,f9241,f9242,f9243,f9244,f9245,f9246,f9247,f9248,f9249,f9250,f9251,f9252,f9253,f9254,f9255,f9256,f9257,f9258,f9259,f9260,f9261,f9262,f9263,f9264,f9265,f9266,f9267,f9268,f9269,f9270,f9271,f9272,f9273,f9274,f9275,f9276,f9277,f9278,f9279,f9280,f9281,f9282,f9283,f9284,f9285,f9286,f9287,f9288,f9289,f9290,f9291,f9292,f9293,f9294,f9295,f9296,f9297,f9298,f9299,f9300,f9301,f9302,f9303,f9304,f9305,f9306,f9307,f9308,f9309,f9310,f9311,f9312,f9313,f9314,f9315,f9316,f9317,f9318,f9319,f9320,f9321,f9322,f9323,f9324,f9325,f9326,f9327,f9328,f9329,f9330,f9331,f9332,f9333,f9334,f9335,f9336,f9337,f9338,f9339,f9340,f9341,f9342,f9343,f9344,f9345,f9346,f9347,f9348,f9349,f9350,f9351,f9352,f9353,f9354,f9355,f9356,f9357,f9358,f9359,f9360,f9361,f9362,f9363,f9364,f9365,f9366,f9367,f9368,f9369,f9370,f9371,f9372,f9373,f9374,f9375,f9376,f9377,f9378,f9379,f9380,f9381,f9382,f9383,f9384,f9385,f9386,f9387,f9388,f9389,f9390,f9391,f9392,f9393,f9394,f9395,f9396,f9397,f9398,f9399,f9400,f9401,f9402,f9403,f9404,f9405,f9406,f9407,f9408,f9409,f9410,f9411,f9412,f9413,f9414,f9415,f9416,f9417,f9418,f9419,f9420,f9421,f9422,f9423,f9424,f9425,f9426,f9427,f9428,f9429,f9430,f9431,f9432,f9433,f9434,f9435,f9436,f9437,f9438,f9439,f9440,f9441,f9442,f9443,f9444,f9445,f9446,f9447,f9448,f9449,f9450,f9451,f9452,f9453,f9454,f9455,f9456,f9457,f9458,f9459,f9460,f9461,f9462,f9463,f9464,f9465,f9466,f9467,f9468,f9469,f9470,f9471,f9472,f9473,f9474,f9475,f9476,f9477,f9478,f9479,f9480,f9481,f9482,f9483,f9484,f9485,f9486,f9487,f9488,f9489,f9490,f9491,f9492,f9493,f9494,f9495,f9496,f9497,f9498,f9499,f9500,f9501,f9502,f9503,f9504,f9505,f9506,f9507,f9508,f9509,f9510,f9511,f9512,f9513,f9514,f9515,f9516,f9517,f9518,f9519,f9520,f9521,f9522,f9523,f9524,f9525,f9526,f9527,f9528,f9529,f9530,f9531,f9532,f9533,f9534,f9535,f9536,f9537,f9538,f9539,f9540,f9541,f9542,f9543,f9544,f9545,f9546,f9547,f9548,f9549,f9550,f9551,f9552,f9553,f9554,f9555,f9556,f9557,f9558,f9559,f9560,f9561,f9562,f9563,f9564,f9565,f9566,f9567,f9568,f9569,f9570,f9571,f9572,f9573,f9574,f9575,f9576,f9577,f9578,f9579,f9580,f9581,f9582,f9583,f9584,f9585,f9586,f9587,f9588,f9589,f9590,f9591,f9592,f9593,f9594,f9595,f9596,f9597,f9598,f9599,f9600,f9601,f9602,f9603,f9604,f9605,f9606,f9607,f9608,f9609,f9610,f9611,f9612,f9613,f9614,f9615,f9616,f9617,f9618,f9619,f9620,f9621,f9622,f9623,f9624,f9625,f9626,f9627,f9628,f9629,f9630,f9631,f9632,f9633,f9634,f9635,f9636,f9637,f9638,f9639,f9640,f9641,f9642,f9643,f9644,f9645,f9646,f9647,f9648,f9649,f9650,f9651,f9652,f9653,f9654,f9655,f9656,f9657,f9658,f9659,f9660,f9661,f9662,f9663,f9664,f9665,f9666,f9667,f9668,f9669,f9670,f9671,f9672,f9673,f9674,f9675,f9676,f9677,f9678,f9679,f9680,f9681,f9682,f9683,f9684,f9685,f9686,f9687,f9688,f9689,f9690,f9691,f9692,f9693,f9694,f9695,f9696,f9697,f9698,f9699,f9700,f9701,f9702,f9703,f9704,f9705,f9706,f9707,f9708,f9709,f9710,f9711,f9712,f9713,f9714,f9715,f9716,f9717,f9718,f9719,f9720,f9721,f9722,f9723,f9724,f9725,f9726,f9727,f9728,f9729,f9730,f9731,f9732,f9733,f9734,f9735,f9736,f9737,f9738,f9739,f9740,f9741,f9742,f9743,f9744,f9745,f9746,f9747,f9748,f9749,f9750,f9751,f9752,f9753,f9754,f9755,f9756,f9757,f9758,f9759,f9760,f9761,f9762,f9763,f9764,f9765,f9766,f9767,f9768,f9769,f9770,f9771,f9772,f9773,f9774,f9775,f9776,f9777,f9778,f9779,f9780,f9781,f9782,f9783,f9784,f9785,f9786,f9787,f9788,f9789,f9790,f9791,f9792,f9793,f9794,f9795,f9796,f9797,f9798,f9799,f9800,f9801,f9802,f9803,f9804,f9805,f9806,f9807,f9808,f9809,f9810,f9811,f9812,f9813,f9814,f9815,f9816,f9817,f9818,f9819,f9820,f9821,f9822,f9823,f9824,f9825,f9826,f9827,f9828,f9829,f9830,f9831,f9832,f9833,f9834,f9835,f9836,f9837,f9838,f9839,f9840,f9841,f9842,f9843,f9844,f9845,f9846,f9847,f9848,f9849,f9850,f9851,f9852,f9853,f9854,f9855,f9856,f9857,f9858,f9859,f9860,f9861,f9862,f9863,f9864,f9865,f9866,f9867,f9868,f9869,f9870,f9871,f9872,f9873,f9874,f9875,f9876,f9877,f9878,f9879,f9880,f9881,f9882,f9883,f9884,f9885,f9886,f9887,f9888,f9889,f9890,f9891,f9892,f9893,f9894,f9895,f9896,f9897,f9898,f9899,f9900,f9901,f9902,f9903,f9904,f9905,f9906,f9907,f9908,f9909,f9910,f9911,f9912,f9913,f9914,f9915,f9916,f9917,f9918,f9919,f9920,f9921,f9922,f9923,f9924,f9925,f9926,f9927,f9928,f9929,f9930,f9931,f9932,f9933,f9934,f9935,f9936,f9937,f9938,f9939,f9940,f9941,f9942,f9943,f9944,f9945,f9946,f9947,f9948,f9949,f9950,f9951,f9952,f9953,f9954,f9955,f9956,f9957,f9958,f9959,f9960,f9961,f9962,f9963,f9964,f9965,f9966,f9967,f9968,f9969,f9970,f9971,f9972,f9973,f9974,f9975,f9976,f9977,f9978,f9979,f9980,f9981,f9982,f9983,f9984,f9985,f9986,f9987,f9988,f9989,f9990,f9991,f9992,f9993,f9994,f9995,f9996,f9997,f9998} + +File: 1 [ { (f0),(f1),(f2),(f3),(f4),(f5),(f6),(f7),(f8),(f9),(f10),(f11),(f12),(f13),(f14),(f15),(f16),(f17),(f18),(f19),(f20),(f21),(f22),(f23),(f24),(f25),(f26),(f27),(f28),(f29),(f30),(f31),(f32),(f33),(f34),(f35),(f36),(f37),(f38),(f39),(f40),(f41),(f42),(f43),(f44),(f45),(f46),(f47),(f48),(f49),(f50),(f51),(f52),(f53),(f54),(f55),(f56),(f57),(f58),(f59),(f60),(f61),(f62),(f63),(f64),(f65),(f66),(f67),(f68),(f69),(f70),(f71),(f72),(f73),(f74),(f75),(f76),(f77),(f78),(f79),(f80),(f81),(f82),(f83),(f84),(f85),(f86),(f87),(f88),(f89),(f90),(f91),(f92),(f93),(f94),(f95),(f96),(f97),(f98),(f99),(f100),(f101),(f102),(f103),(f104),(f105),(f106),(f107),(f108),(f109),(f110),(f111),(f112),(f113),(f114),(f115),(f116),(f117),(f118),(f119),(f120),(f121),(f122),(f123),(f124),(f125),(f126),(f127),(f128),(f129),(f130),(f131),(f132),(f133),(f134),(f135),(f136),(f137),(f138),(f139),(f140),(f141),(f142),(f143),(f144),(f145),(f146),(f147),(f148),(f149),(f150),(f151),(f152),(f153),(f154),(f155),(f156),(f157),(f158),(f159),(f160),(f161),(f162),(f163),(f164),(f165),(f166),(f167),(f168),(f169),(f170),(f171),(f172),(f173),(f174),(f175),(f176),(f177),(f178),(f179),(f180),(f181),(f182),(f183),(f184),(f185),(f186),(f187),(f188),(f189),(f190),(f191),(f192),(f193),(f194),(f195),(f196),(f197),(f198),(f199),(f200),(f201),(f202),(f203),(f204),(f205),(f206),(f207),(f208),(f209),(f210),(f211),(f212),(f213),(f214),(f215),(f216),(f217),(f218),(f219),(f220),(f221),(f222),(f223),(f224),(f225),(f226),(f227),(f228),(f229),(f230),(f231),(f232),(f233),(f234),(f235),(f236),(f237),(f238),(f239),(f240),(f241),(f242),(f243),(f244),(f245),(f246),(f247),(f248),(f249),(f250),(f251),(f252),(f253),(f254),(f255),(f256),(f257),(f258),(f259),(f260),(f261),(f262),(f263),(f264),(f265),(f266),(f267),(f268),(f269),(f270),(f271),(f272),(f273),(f274),(f275),(f276),(f277),(f278),(f279),(f280),(f281),(f282),(f283),(f284),(f285),(f286),(f287),(f288),(f289),(f290),(f291),(f292),(f293),(f294),(f295),(f296),(f297),(f298),(f299),(f300),(f301),(f302),(f303),(f304),(f305),(f306),(f307),(f308),(f309),(f310),(f311),(f312),(f313),(f314),(f315),(f316),(f317),(f318),(f319),(f320),(f321),(f322),(f323),(f324),(f325),(f326),(f327),(f328),(f329),(f330),(f331),(f332),(f333),(f334),(f335),(f336),(f337),(f338),(f339),(f340),(f341),(f342),(f343),(f344),(f345),(f346),(f347),(f348),(f349),(f350),(f351),(f352),(f353),(f354),(f355),(f356),(f357),(f358),(f359),(f360),(f361),(f362),(f363),(f364),(f365),(f366),(f367),(f368),(f369),(f370),(f371),(f372),(f373),(f374),(f375),(f376),(f377),(f378),(f379),(f380),(f381),(f382),(f383),(f384),(f385),(f386),(f387),(f388),(f389),(f390),(f391),(f392),(f393),(f394),(f395),(f396),(f397),(f398),(f399),(f400),(f401),(f402),(f403),(f404),(f405),(f406),(f407),(f408),(f409),(f410),(f411),(f412),(f413),(f414),(f415),(f416),(f417),(f418),(f419),(f420),(f421),(f422),(f423),(f424),(f425),(f426),(f427),(f428),(f429),(f430),(f431),(f432),(f433),(f434),(f435),(f436),(f437),(f438),(f439),(f440),(f441),(f442),(f443),(f444),(f445),(f446),(f447),(f448),(f449),(f450),(f451),(f452),(f453),(f454),(f455),(f456),(f457),(f458),(f459),(f460),(f461),(f462),(f463),(f464),(f465),(f466),(f467),(f468),(f469),(f470),(f471),(f472),(f473),(f474),(f475),(f476),(f477),(f478),(f479),(f480),(f481),(f482),(f483),(f484),(f485),(f486),(f487),(f488),(f489),(f490),(f491),(f492),(f493),(f494),(f495),(f496),(f497),(f498),(f499),(f500),(f501),(f502),(f503),(f504),(f505),(f506),(f507),(f508),(f509),(f510),(f511),(f512),(f513),(f514),(f515),(f516),(f517),(f518),(f519),(f520),(f521),(f522),(f523),(f524),(f525),(f526),(f527),(f528),(f529),(f530),(f531),(f532),(f533),(f534),(f535),(f536),(f537),(f538),(f539),(f540),(f541),(f542),(f543),(f544),(f545),(f546),(f547),(f548),(f549),(f550),(f551),(f552),(f553),(f554),(f555),(f556),(f557),(f558),(f559),(f560),(f561),(f562),(f563),(f564),(f565),(f566),(f567),(f568),(f569),(f570),(f571),(f572),(f573),(f574),(f575),(f576),(f577),(f578),(f579),(f580),(f581),(f582),(f583),(f584),(f585),(f586),(f587),(f588),(f589),(f590),(f591),(f592),(f593),(f594),(f595),(f596),(f597),(f598),(f599),(f600),(f601),(f602),(f603),(f604),(f605),(f606),(f607),(f608),(f609),(f610),(f611),(f612),(f613),(f614),(f615),(f616),(f617),(f618),(f619),(f620),(f621),(f622),(f623),(f624),(f625),(f626),(f627),(f628),(f629),(f630),(f631),(f632),(f633),(f634),(f635),(f636),(f637),(f638),(f639),(f640),(f641),(f642),(f643),(f644),(f645),(f646),(f647),(f648),(f649),(f650),(f651),(f652),(f653),(f654),(f655),(f656),(f657),(f658),(f659),(f660),(f661),(f662),(f663),(f664),(f665),(f666),(f667),(f668),(f669),(f670),(f671),(f672),(f673),(f674),(f675),(f676),(f677),(f678),(f679),(f680),(f681),(f682),(f683),(f684),(f685),(f686),(f687),(f688),(f689),(f690),(f691),(f692),(f693),(f694),(f695),(f696),(f697),(f698),(f699),(f700),(f701),(f702),(f703),(f704),(f705),(f706),(f707),(f708),(f709),(f710),(f711),(f712),(f713),(f714),(f715),(f716),(f717),(f718),(f719),(f720),(f721),(f722),(f723),(f724),(f725),(f726),(f727),(f728),(f729),(f730),(f731),(f732),(f733),(f734),(f735),(f736),(f737),(f738),(f739),(f740),(f741),(f742),(f743),(f744),(f745),(f746),(f747),(f748),(f749),(f750),(f751),(f752),(f753),(f754),(f755),(f756),(f757),(f758),(f759),(f760),(f761),(f762),(f763),(f764),(f765),(f766),(f767),(f768),(f769),(f770),(f771),(f772),(f773),(f774),(f775),(f776),(f777),(f778),(f779),(f780),(f781),(f782),(f783),(f784),(f785),(f786),(f787),(f788),(f789),(f790),(f791),(f792),(f793),(f794),(f795),(f796),(f797),(f798),(f799),(f800),(f801),(f802),(f803),(f804),(f805),(f806),(f807),(f808),(f809),(f810),(f811),(f812),(f813),(f814),(f815),(f816),(f817),(f818),(f819),(f820),(f821),(f822),(f823),(f824),(f825),(f826),(f827),(f828),(f829),(f830),(f831),(f832),(f833),(f834),(f835),(f836),(f837),(f838),(f839),(f840),(f841),(f842),(f843),(f844),(f845),(f846),(f847),(f848),(f849),(f850),(f851),(f852),(f853),(f854),(f855),(f856),(f857),(f858),(f859),(f860),(f861),(f862),(f863),(f864),(f865),(f866),(f867),(f868),(f869),(f870),(f871),(f872),(f873),(f874),(f875),(f876),(f877),(f878),(f879),(f880),(f881),(f882),(f883),(f884),(f885),(f886),(f887),(f888),(f889),(f890),(f891),(f892),(f893),(f894),(f895),(f896),(f897),(f898),(f899),(f900),(f901),(f902),(f903),(f904),(f905),(f906),(f907),(f908),(f909),(f910),(f911),(f912),(f913),(f914),(f915),(f916),(f917),(f918),(f919),(f920),(f921),(f922),(f923),(f924),(f925),(f926),(f927),(f928),(f929),(f930),(f931),(f932),(f933),(f934),(f935),(f936),(f937),(f938),(f939),(f940),(f941),(f942),(f943),(f944),(f945),(f946),(f947),(f948),(f949),(f950),(f951),(f952),(f953),(f954),(f955),(f956),(f957),(f958),(f959),(f960),(f961),(f962),(f963),(f964),(f965),(f966),(f967),(f968),(f969),(f970),(f971),(f972),(f973),(f974),(f975),(f976),(f977),(f978),(f979),(f980),(f981),(f982),(f983),(f984),(f985),(f986),(f987),(f988),(f989),(f990),(f991),(f992),(f993),(f994),(f995),(f996),(f997),(f998),(f999),(f1000),(f1001),(f1002),(f1003),(f1004),(f1005),(f1006),(f1007),(f1008),(f1009),(f1010),(f1011),(f1012),(f1013),(f1014),(f1015),(f1016),(f1017),(f1018),(f1019),(f1020),(f1021),(f1022),(f1023),(f1024),(f1025),(f1026),(f1027),(f1028),(f1029),(f1030),(f1031),(f1032),(f1033),(f1034),(f1035),(f1036),(f1037),(f1038),(f1039),(f1040),(f1041),(f1042),(f1043),(f1044),(f1045),(f1046),(f1047),(f1048),(f1049),(f1050),(f1051),(f1052),(f1053),(f1054),(f1055),(f1056),(f1057),(f1058),(f1059),(f1060),(f1061),(f1062),(f1063),(f1064),(f1065),(f1066),(f1067),(f1068),(f1069),(f1070),(f1071),(f1072),(f1073),(f1074),(f1075),(f1076),(f1077),(f1078),(f1079),(f1080),(f1081),(f1082),(f1083),(f1084),(f1085),(f1086),(f1087),(f1088),(f1089),(f1090),(f1091),(f1092),(f1093),(f1094),(f1095),(f1096),(f1097),(f1098),(f1099),(f1100),(f1101),(f1102),(f1103),(f1104),(f1105),(f1106),(f1107),(f1108),(f1109),(f1110),(f1111),(f1112),(f1113),(f1114),(f1115),(f1116),(f1117),(f1118),(f1119),(f1120),(f1121),(f1122),(f1123),(f1124),(f1125),(f1126),(f1127),(f1128),(f1129),(f1130),(f1131),(f1132),(f1133),(f1134),(f1135),(f1136),(f1137),(f1138),(f1139),(f1140),(f1141),(f1142),(f1143),(f1144),(f1145),(f1146),(f1147),(f1148),(f1149),(f1150),(f1151),(f1152),(f1153),(f1154),(f1155),(f1156),(f1157),(f1158),(f1159),(f1160),(f1161),(f1162),(f1163),(f1164),(f1165),(f1166),(f1167),(f1168),(f1169),(f1170),(f1171),(f1172),(f1173),(f1174),(f1175),(f1176),(f1177),(f1178),(f1179),(f1180),(f1181),(f1182),(f1183),(f1184),(f1185),(f1186),(f1187),(f1188),(f1189),(f1190),(f1191),(f1192),(f1193),(f1194),(f1195),(f1196),(f1197),(f1198),(f1199),(f1200),(f1201),(f1202),(f1203),(f1204),(f1205),(f1206),(f1207),(f1208),(f1209),(f1210),(f1211),(f1212),(f1213),(f1214),(f1215),(f1216),(f1217),(f1218),(f1219),(f1220),(f1221),(f1222),(f1223),(f1224),(f1225),(f1226),(f1227),(f1228),(f1229),(f1230),(f1231),(f1232),(f1233),(f1234),(f1235),(f1236),(f1237),(f1238),(f1239),(f1240),(f1241),(f1242),(f1243),(f1244),(f1245),(f1246),(f1247),(f1248),(f1249),(f1250),(f1251),(f1252),(f1253),(f1254),(f1255),(f1256),(f1257),(f1258),(f1259),(f1260),(f1261),(f1262),(f1263),(f1264),(f1265),(f1266),(f1267),(f1268),(f1269),(f1270),(f1271),(f1272),(f1273),(f1274),(f1275),(f1276),(f1277),(f1278),(f1279),(f1280),(f1281),(f1282),(f1283),(f1284),(f1285),(f1286),(f1287),(f1288),(f1289),(f1290),(f1291),(f1292),(f1293),(f1294),(f1295),(f1296),(f1297),(f1298),(f1299),(f1300),(f1301),(f1302),(f1303),(f1304),(f1305),(f1306),(f1307),(f1308),(f1309),(f1310),(f1311),(f1312),(f1313),(f1314),(f1315),(f1316),(f1317),(f1318),(f1319),(f1320),(f1321),(f1322),(f1323),(f1324),(f1325),(f1326),(f1327),(f1328),(f1329),(f1330),(f1331),(f1332),(f1333),(f1334),(f1335),(f1336),(f1337),(f1338),(f1339),(f1340),(f1341),(f1342),(f1343),(f1344),(f1345),(f1346),(f1347),(f1348),(f1349),(f1350),(f1351),(f1352),(f1353),(f1354),(f1355),(f1356),(f1357),(f1358),(f1359),(f1360),(f1361),(f1362),(f1363),(f1364),(f1365),(f1366),(f1367),(f1368),(f1369),(f1370),(f1371),(f1372),(f1373),(f1374),(f1375),(f1376),(f1377),(f1378),(f1379),(f1380),(f1381),(f1382),(f1383),(f1384),(f1385),(f1386),(f1387),(f1388),(f1389),(f1390),(f1391),(f1392),(f1393),(f1394),(f1395),(f1396),(f1397),(f1398),(f1399),(f1400),(f1401),(f1402),(f1403),(f1404),(f1405),(f1406),(f1407),(f1408),(f1409),(f1410),(f1411),(f1412),(f1413),(f1414),(f1415),(f1416),(f1417),(f1418),(f1419),(f1420),(f1421),(f1422),(f1423),(f1424),(f1425),(f1426),(f1427),(f1428),(f1429),(f1430),(f1431),(f1432),(f1433),(f1434),(f1435),(f1436),(f1437),(f1438),(f1439),(f1440),(f1441),(f1442),(f1443),(f1444),(f1445),(f1446),(f1447),(f1448),(f1449),(f1450),(f1451),(f1452),(f1453),(f1454),(f1455),(f1456),(f1457),(f1458),(f1459),(f1460),(f1461),(f1462),(f1463),(f1464),(f1465),(f1466),(f1467),(f1468),(f1469),(f1470),(f1471),(f1472),(f1473),(f1474),(f1475),(f1476),(f1477),(f1478),(f1479),(f1480),(f1481),(f1482),(f1483),(f1484),(f1485),(f1486),(f1487),(f1488),(f1489),(f1490),(f1491),(f1492),(f1493),(f1494),(f1495),(f1496),(f1497),(f1498),(f1499),(f1500),(f1501),(f1502),(f1503),(f1504),(f1505),(f1506),(f1507),(f1508),(f1509),(f1510),(f1511),(f1512),(f1513),(f1514),(f1515),(f1516),(f1517),(f1518),(f1519),(f1520),(f1521),(f1522),(f1523),(f1524),(f1525),(f1526),(f1527),(f1528),(f1529),(f1530),(f1531),(f1532),(f1533),(f1534),(f1535),(f1536),(f1537),(f1538),(f1539),(f1540),(f1541),(f1542),(f1543),(f1544),(f1545),(f1546),(f1547),(f1548),(f1549),(f1550),(f1551),(f1552),(f1553),(f1554),(f1555),(f1556),(f1557),(f1558),(f1559),(f1560),(f1561),(f1562),(f1563),(f1564),(f1565),(f1566),(f1567),(f1568),(f1569),(f1570),(f1571),(f1572),(f1573),(f1574),(f1575),(f1576),(f1577),(f1578),(f1579),(f1580),(f1581),(f1582),(f1583),(f1584),(f1585),(f1586),(f1587),(f1588),(f1589),(f1590),(f1591),(f1592),(f1593),(f1594),(f1595),(f1596),(f1597),(f1598),(f1599),(f1600),(f1601),(f1602),(f1603),(f1604),(f1605),(f1606),(f1607),(f1608),(f1609),(f1610),(f1611),(f1612),(f1613),(f1614),(f1615),(f1616),(f1617),(f1618),(f1619),(f1620),(f1621),(f1622),(f1623),(f1624),(f1625),(f1626),(f1627),(f1628),(f1629),(f1630),(f1631),(f1632),(f1633),(f1634),(f1635),(f1636),(f1637),(f1638),(f1639),(f1640),(f1641),(f1642),(f1643),(f1644),(f1645),(f1646),(f1647),(f1648),(f1649),(f1650),(f1651),(f1652),(f1653),(f1654),(f1655),(f1656),(f1657),(f1658),(f1659),(f1660),(f1661),(f1662),(f1663),(f1664),(f1665),(f1666),(f1667),(f1668),(f1669),(f1670),(f1671),(f1672),(f1673),(f1674),(f1675),(f1676),(f1677),(f1678),(f1679),(f1680),(f1681),(f1682),(f1683),(f1684),(f1685),(f1686),(f1687),(f1688),(f1689),(f1690),(f1691),(f1692),(f1693),(f1694),(f1695),(f1696),(f1697),(f1698),(f1699),(f1700),(f1701),(f1702),(f1703),(f1704),(f1705),(f1706),(f1707),(f1708),(f1709),(f1710),(f1711),(f1712),(f1713),(f1714),(f1715),(f1716),(f1717),(f1718),(f1719),(f1720),(f1721),(f1722),(f1723),(f1724),(f1725),(f1726),(f1727),(f1728),(f1729),(f1730),(f1731),(f1732),(f1733),(f1734),(f1735),(f1736),(f1737),(f1738),(f1739),(f1740),(f1741),(f1742),(f1743),(f1744),(f1745),(f1746),(f1747),(f1748),(f1749),(f1750),(f1751),(f1752),(f1753),(f1754),(f1755),(f1756),(f1757),(f1758),(f1759),(f1760),(f1761),(f1762),(f1763),(f1764),(f1765),(f1766),(f1767),(f1768),(f1769),(f1770),(f1771),(f1772),(f1773),(f1774),(f1775),(f1776),(f1777),(f1778),(f1779),(f1780),(f1781),(f1782),(f1783),(f1784),(f1785),(f1786),(f1787),(f1788),(f1789),(f1790),(f1791),(f1792),(f1793),(f1794),(f1795),(f1796),(f1797),(f1798),(f1799),(f1800),(f1801),(f1802),(f1803),(f1804),(f1805),(f1806),(f1807),(f1808),(f1809),(f1810),(f1811),(f1812),(f1813),(f1814),(f1815),(f1816),(f1817),(f1818),(f1819),(f1820),(f1821),(f1822),(f1823),(f1824),(f1825),(f1826),(f1827),(f1828),(f1829),(f1830),(f1831),(f1832),(f1833),(f1834),(f1835),(f1836),(f1837),(f1838),(f1839),(f1840),(f1841),(f1842),(f1843),(f1844),(f1845),(f1846),(f1847),(f1848),(f1849),(f1850),(f1851),(f1852),(f1853),(f1854),(f1855),(f1856),(f1857),(f1858),(f1859),(f1860),(f1861),(f1862),(f1863),(f1864),(f1865),(f1866),(f1867),(f1868),(f1869),(f1870),(f1871),(f1872),(f1873),(f1874),(f1875),(f1876),(f1877),(f1878),(f1879),(f1880),(f1881),(f1882),(f1883),(f1884),(f1885),(f1886),(f1887),(f1888),(f1889),(f1890),(f1891),(f1892),(f1893),(f1894),(f1895),(f1896),(f1897),(f1898),(f1899),(f1900),(f1901),(f1902),(f1903),(f1904),(f1905),(f1906),(f1907),(f1908),(f1909),(f1910),(f1911),(f1912),(f1913),(f1914),(f1915),(f1916),(f1917),(f1918),(f1919),(f1920),(f1921),(f1922),(f1923),(f1924),(f1925),(f1926),(f1927),(f1928),(f1929),(f1930),(f1931),(f1932),(f1933),(f1934),(f1935),(f1936),(f1937),(f1938),(f1939),(f1940),(f1941),(f1942),(f1943),(f1944),(f1945),(f1946),(f1947),(f1948),(f1949),(f1950),(f1951),(f1952),(f1953),(f1954),(f1955),(f1956),(f1957),(f1958),(f1959),(f1960),(f1961),(f1962),(f1963),(f1964),(f1965),(f1966),(f1967),(f1968),(f1969),(f1970),(f1971),(f1972),(f1973),(f1974),(f1975),(f1976),(f1977),(f1978),(f1979),(f1980),(f1981),(f1982),(f1983),(f1984),(f1985),(f1986),(f1987),(f1988),(f1989),(f1990),(f1991),(f1992),(f1993),(f1994),(f1995),(f1996),(f1997),(f1998),(f1999),(f2000),(f2001),(f2002),(f2003),(f2004),(f2005),(f2006),(f2007),(f2008),(f2009),(f2010),(f2011),(f2012),(f2013),(f2014),(f2015),(f2016),(f2017),(f2018),(f2019),(f2020),(f2021),(f2022),(f2023),(f2024),(f2025),(f2026),(f2027),(f2028),(f2029),(f2030),(f2031),(f2032),(f2033),(f2034),(f2035),(f2036),(f2037),(f2038),(f2039),(f2040),(f2041),(f2042),(f2043),(f2044),(f2045),(f2046),(f2047),(f2048),(f2049),(f2050),(f2051),(f2052),(f2053),(f2054),(f2055),(f2056),(f2057),(f2058),(f2059),(f2060),(f2061),(f2062),(f2063),(f2064),(f2065),(f2066),(f2067),(f2068),(f2069),(f2070),(f2071),(f2072),(f2073),(f2074),(f2075),(f2076),(f2077),(f2078),(f2079),(f2080),(f2081),(f2082),(f2083),(f2084),(f2085),(f2086),(f2087),(f2088),(f2089),(f2090),(f2091),(f2092),(f2093),(f2094),(f2095),(f2096),(f2097),(f2098),(f2099),(f2100),(f2101),(f2102),(f2103),(f2104),(f2105),(f2106),(f2107),(f2108),(f2109),(f2110),(f2111),(f2112),(f2113),(f2114),(f2115),(f2116),(f2117),(f2118),(f2119),(f2120),(f2121),(f2122),(f2123),(f2124),(f2125),(f2126),(f2127),(f2128),(f2129),(f2130),(f2131),(f2132),(f2133),(f2134),(f2135),(f2136),(f2137),(f2138),(f2139),(f2140),(f2141),(f2142),(f2143),(f2144),(f2145),(f2146),(f2147),(f2148),(f2149),(f2150),(f2151),(f2152),(f2153),(f2154),(f2155),(f2156),(f2157),(f2158),(f2159),(f2160),(f2161),(f2162),(f2163),(f2164),(f2165),(f2166),(f2167),(f2168),(f2169),(f2170),(f2171),(f2172),(f2173),(f2174),(f2175),(f2176),(f2177),(f2178),(f2179),(f2180),(f2181),(f2182),(f2183),(f2184),(f2185),(f2186),(f2187),(f2188),(f2189),(f2190),(f2191),(f2192),(f2193),(f2194),(f2195),(f2196),(f2197),(f2198),(f2199),(f2200),(f2201),(f2202),(f2203),(f2204),(f2205),(f2206),(f2207),(f2208),(f2209),(f2210),(f2211),(f2212),(f2213),(f2214),(f2215),(f2216),(f2217),(f2218),(f2219),(f2220),(f2221),(f2222),(f2223),(f2224),(f2225),(f2226),(f2227),(f2228),(f2229),(f2230),(f2231),(f2232),(f2233),(f2234),(f2235),(f2236),(f2237),(f2238),(f2239),(f2240),(f2241),(f2242),(f2243),(f2244),(f2245),(f2246),(f2247),(f2248),(f2249),(f2250),(f2251),(f2252),(f2253),(f2254),(f2255),(f2256),(f2257),(f2258),(f2259),(f2260),(f2261),(f2262),(f2263),(f2264),(f2265),(f2266),(f2267),(f2268),(f2269),(f2270),(f2271),(f2272),(f2273),(f2274),(f2275),(f2276),(f2277),(f2278),(f2279),(f2280),(f2281),(f2282),(f2283),(f2284),(f2285),(f2286),(f2287),(f2288),(f2289),(f2290),(f2291),(f2292),(f2293),(f2294),(f2295),(f2296),(f2297),(f2298),(f2299),(f2300),(f2301),(f2302),(f2303),(f2304),(f2305),(f2306),(f2307),(f2308),(f2309),(f2310),(f2311),(f2312),(f2313),(f2314),(f2315),(f2316),(f2317),(f2318),(f2319),(f2320),(f2321),(f2322),(f2323),(f2324),(f2325),(f2326),(f2327),(f2328),(f2329),(f2330),(f2331),(f2332),(f2333),(f2334),(f2335),(f2336),(f2337),(f2338),(f2339),(f2340),(f2341),(f2342),(f2343),(f2344),(f2345),(f2346),(f2347),(f2348),(f2349),(f2350),(f2351),(f2352),(f2353),(f2354),(f2355),(f2356),(f2357),(f2358),(f2359),(f2360),(f2361),(f2362),(f2363),(f2364),(f2365),(f2366),(f2367),(f2368),(f2369),(f2370),(f2371),(f2372),(f2373),(f2374),(f2375),(f2376),(f2377),(f2378),(f2379),(f2380),(f2381),(f2382),(f2383),(f2384),(f2385),(f2386),(f2387),(f2388),(f2389),(f2390),(f2391),(f2392),(f2393),(f2394),(f2395),(f2396),(f2397),(f2398),(f2399),(f2400),(f2401),(f2402),(f2403),(f2404),(f2405),(f2406),(f2407),(f2408),(f2409),(f2410),(f2411),(f2412),(f2413),(f2414),(f2415),(f2416),(f2417),(f2418),(f2419),(f2420),(f2421),(f2422),(f2423),(f2424),(f2425),(f2426),(f2427),(f2428),(f2429),(f2430),(f2431),(f2432),(f2433),(f2434),(f2435),(f2436),(f2437),(f2438),(f2439),(f2440),(f2441),(f2442),(f2443),(f2444),(f2445),(f2446),(f2447),(f2448),(f2449),(f2450),(f2451),(f2452),(f2453),(f2454),(f2455),(f2456),(f2457),(f2458),(f2459),(f2460),(f2461),(f2462),(f2463),(f2464),(f2465),(f2466),(f2467),(f2468),(f2469),(f2470),(f2471),(f2472),(f2473),(f2474),(f2475),(f2476),(f2477),(f2478),(f2479),(f2480),(f2481),(f2482),(f2483),(f2484),(f2485),(f2486),(f2487),(f2488),(f2489),(f2490),(f2491),(f2492),(f2493),(f2494),(f2495),(f2496),(f2497),(f2498),(f2499),(f2500),(f2501),(f2502),(f2503),(f2504),(f2505),(f2506),(f2507),(f2508),(f2509),(f2510),(f2511),(f2512),(f2513),(f2514),(f2515),(f2516),(f2517),(f2518),(f2519),(f2520),(f2521),(f2522),(f2523),(f2524),(f2525),(f2526),(f2527),(f2528),(f2529),(f2530),(f2531),(f2532),(f2533),(f2534),(f2535),(f2536),(f2537),(f2538),(f2539),(f2540),(f2541),(f2542),(f2543),(f2544),(f2545),(f2546),(f2547),(f2548),(f2549),(f2550),(f2551),(f2552),(f2553),(f2554),(f2555),(f2556),(f2557),(f2558),(f2559),(f2560),(f2561),(f2562),(f2563),(f2564),(f2565),(f2566),(f2567),(f2568),(f2569),(f2570),(f2571),(f2572),(f2573),(f2574),(f2575),(f2576),(f2577),(f2578),(f2579),(f2580),(f2581),(f2582),(f2583),(f2584),(f2585),(f2586),(f2587),(f2588),(f2589),(f2590),(f2591),(f2592),(f2593),(f2594),(f2595),(f2596),(f2597),(f2598),(f2599),(f2600),(f2601),(f2602),(f2603),(f2604),(f2605),(f2606),(f2607),(f2608),(f2609),(f2610),(f2611),(f2612),(f2613),(f2614),(f2615),(f2616),(f2617),(f2618),(f2619),(f2620),(f2621),(f2622),(f2623),(f2624),(f2625),(f2626),(f2627),(f2628),(f2629),(f2630),(f2631),(f2632),(f2633),(f2634),(f2635),(f2636),(f2637),(f2638),(f2639),(f2640),(f2641),(f2642),(f2643),(f2644),(f2645),(f2646),(f2647),(f2648),(f2649),(f2650),(f2651),(f2652),(f2653),(f2654),(f2655),(f2656),(f2657),(f2658),(f2659),(f2660),(f2661),(f2662),(f2663),(f2664),(f2665),(f2666),(f2667),(f2668),(f2669),(f2670),(f2671),(f2672),(f2673),(f2674),(f2675),(f2676),(f2677),(f2678),(f2679),(f2680),(f2681),(f2682),(f2683),(f2684),(f2685),(f2686),(f2687),(f2688),(f2689),(f2690),(f2691),(f2692),(f2693),(f2694),(f2695),(f2696),(f2697),(f2698),(f2699),(f2700),(f2701),(f2702),(f2703),(f2704),(f2705),(f2706),(f2707),(f2708),(f2709),(f2710),(f2711),(f2712),(f2713),(f2714),(f2715),(f2716),(f2717),(f2718),(f2719),(f2720),(f2721),(f2722),(f2723),(f2724),(f2725),(f2726),(f2727),(f2728),(f2729),(f2730),(f2731),(f2732),(f2733),(f2734),(f2735),(f2736),(f2737),(f2738),(f2739),(f2740),(f2741),(f2742),(f2743),(f2744),(f2745),(f2746),(f2747),(f2748),(f2749),(f2750),(f2751),(f2752),(f2753),(f2754),(f2755),(f2756),(f2757),(f2758),(f2759),(f2760),(f2761),(f2762),(f2763),(f2764),(f2765),(f2766),(f2767),(f2768),(f2769),(f2770),(f2771),(f2772),(f2773),(f2774),(f2775),(f2776),(f2777),(f2778),(f2779),(f2780),(f2781),(f2782),(f2783),(f2784),(f2785),(f2786),(f2787),(f2788),(f2789),(f2790),(f2791),(f2792),(f2793),(f2794),(f2795),(f2796),(f2797),(f2798),(f2799),(f2800),(f2801),(f2802),(f2803),(f2804),(f2805),(f2806),(f2807),(f2808),(f2809),(f2810),(f2811),(f2812),(f2813),(f2814),(f2815),(f2816),(f2817),(f2818),(f2819),(f2820),(f2821),(f2822),(f2823),(f2824),(f2825),(f2826),(f2827),(f2828),(f2829),(f2830),(f2831),(f2832),(f2833),(f2834),(f2835),(f2836),(f2837),(f2838),(f2839),(f2840),(f2841),(f2842),(f2843),(f2844),(f2845),(f2846),(f2847),(f2848),(f2849),(f2850),(f2851),(f2852),(f2853),(f2854),(f2855),(f2856),(f2857),(f2858),(f2859),(f2860),(f2861),(f2862),(f2863),(f2864),(f2865),(f2866),(f2867),(f2868),(f2869),(f2870),(f2871),(f2872),(f2873),(f2874),(f2875),(f2876),(f2877),(f2878),(f2879),(f2880),(f2881),(f2882),(f2883),(f2884),(f2885),(f2886),(f2887),(f2888),(f2889),(f2890),(f2891),(f2892),(f2893),(f2894),(f2895),(f2896),(f2897),(f2898),(f2899),(f2900),(f2901),(f2902),(f2903),(f2904),(f2905),(f2906),(f2907),(f2908),(f2909),(f2910),(f2911),(f2912),(f2913),(f2914),(f2915),(f2916),(f2917),(f2918),(f2919),(f2920),(f2921),(f2922),(f2923),(f2924),(f2925),(f2926),(f2927),(f2928),(f2929),(f2930),(f2931),(f2932),(f2933),(f2934),(f2935),(f2936),(f2937),(f2938),(f2939),(f2940),(f2941),(f2942),(f2943),(f2944),(f2945),(f2946),(f2947),(f2948),(f2949),(f2950),(f2951),(f2952),(f2953),(f2954),(f2955),(f2956),(f2957),(f2958),(f2959),(f2960),(f2961),(f2962),(f2963),(f2964),(f2965),(f2966),(f2967),(f2968),(f2969),(f2970),(f2971),(f2972),(f2973),(f2974),(f2975),(f2976),(f2977),(f2978),(f2979),(f2980),(f2981),(f2982),(f2983),(f2984),(f2985),(f2986),(f2987),(f2988),(f2989),(f2990),(f2991),(f2992),(f2993),(f2994),(f2995),(f2996),(f2997),(f2998),(f2999),(f3000),(f3001),(f3002),(f3003),(f3004),(f3005),(f3006),(f3007),(f3008),(f3009),(f3010),(f3011),(f3012),(f3013),(f3014),(f3015),(f3016),(f3017),(f3018),(f3019),(f3020),(f3021),(f3022),(f3023),(f3024),(f3025),(f3026),(f3027),(f3028),(f3029),(f3030),(f3031),(f3032),(f3033),(f3034),(f3035),(f3036),(f3037),(f3038),(f3039),(f3040),(f3041),(f3042),(f3043),(f3044),(f3045),(f3046),(f3047),(f3048),(f3049),(f3050),(f3051),(f3052),(f3053),(f3054),(f3055),(f3056),(f3057),(f3058),(f3059),(f3060),(f3061),(f3062),(f3063),(f3064),(f3065),(f3066),(f3067),(f3068),(f3069),(f3070),(f3071),(f3072),(f3073),(f3074),(f3075),(f3076),(f3077),(f3078),(f3079),(f3080),(f3081),(f3082),(f3083),(f3084),(f3085),(f3086),(f3087),(f3088),(f3089),(f3090),(f3091),(f3092),(f3093),(f3094),(f3095),(f3096),(f3097),(f3098),(f3099),(f3100),(f3101),(f3102),(f3103),(f3104),(f3105),(f3106),(f3107),(f3108),(f3109),(f3110),(f3111),(f3112),(f3113),(f3114),(f3115),(f3116),(f3117),(f3118),(f3119),(f3120),(f3121),(f3122),(f3123),(f3124),(f3125),(f3126),(f3127),(f3128),(f3129),(f3130),(f3131),(f3132),(f3133),(f3134),(f3135),(f3136),(f3137),(f3138),(f3139),(f3140),(f3141),(f3142),(f3143),(f3144),(f3145),(f3146),(f3147),(f3148),(f3149),(f3150),(f3151),(f3152),(f3153),(f3154),(f3155),(f3156),(f3157),(f3158),(f3159),(f3160),(f3161),(f3162),(f3163),(f3164),(f3165),(f3166),(f3167),(f3168),(f3169),(f3170),(f3171),(f3172),(f3173),(f3174),(f3175),(f3176),(f3177),(f3178),(f3179),(f3180),(f3181),(f3182),(f3183),(f3184),(f3185),(f3186),(f3187),(f3188),(f3189),(f3190),(f3191),(f3192),(f3193),(f3194),(f3195),(f3196),(f3197),(f3198),(f3199),(f3200),(f3201),(f3202),(f3203),(f3204),(f3205),(f3206),(f3207),(f3208),(f3209),(f3210),(f3211),(f3212),(f3213),(f3214),(f3215),(f3216),(f3217),(f3218),(f3219),(f3220),(f3221),(f3222),(f3223),(f3224),(f3225),(f3226),(f3227),(f3228),(f3229),(f3230),(f3231),(f3232),(f3233),(f3234),(f3235),(f3236),(f3237),(f3238),(f3239),(f3240),(f3241),(f3242),(f3243),(f3244),(f3245),(f3246),(f3247),(f3248),(f3249),(f3250),(f3251),(f3252),(f3253),(f3254),(f3255),(f3256),(f3257),(f3258),(f3259),(f3260),(f3261),(f3262),(f3263),(f3264),(f3265),(f3266),(f3267),(f3268),(f3269),(f3270),(f3271),(f3272),(f3273),(f3274),(f3275),(f3276),(f3277),(f3278),(f3279),(f3280),(f3281),(f3282),(f3283),(f3284),(f3285),(f3286),(f3287),(f3288),(f3289),(f3290),(f3291),(f3292),(f3293),(f3294),(f3295),(f3296),(f3297),(f3298),(f3299),(f3300),(f3301),(f3302),(f3303),(f3304),(f3305),(f3306),(f3307),(f3308),(f3309),(f3310),(f3311),(f3312),(f3313),(f3314),(f3315),(f3316),(f3317),(f3318),(f3319),(f3320),(f3321),(f3322),(f3323),(f3324),(f3325),(f3326),(f3327),(f3328),(f3329),(f3330),(f3331),(f3332),(f3333),(f3334),(f3335),(f3336),(f3337),(f3338),(f3339),(f3340),(f3341),(f3342),(f3343),(f3344),(f3345),(f3346),(f3347),(f3348),(f3349),(f3350),(f3351),(f3352),(f3353),(f3354),(f3355),(f3356),(f3357),(f3358),(f3359),(f3360),(f3361),(f3362),(f3363),(f3364),(f3365),(f3366),(f3367),(f3368),(f3369),(f3370),(f3371),(f3372),(f3373),(f3374),(f3375),(f3376),(f3377),(f3378),(f3379),(f3380),(f3381),(f3382),(f3383),(f3384),(f3385),(f3386),(f3387),(f3388),(f3389),(f3390),(f3391),(f3392),(f3393),(f3394),(f3395),(f3396),(f3397),(f3398),(f3399),(f3400),(f3401),(f3402),(f3403),(f3404),(f3405),(f3406),(f3407),(f3408),(f3409),(f3410),(f3411),(f3412),(f3413),(f3414),(f3415),(f3416),(f3417),(f3418),(f3419),(f3420),(f3421),(f3422),(f3423),(f3424),(f3425),(f3426),(f3427),(f3428),(f3429),(f3430),(f3431),(f3432),(f3433),(f3434),(f3435),(f3436),(f3437),(f3438),(f3439),(f3440),(f3441),(f3442),(f3443),(f3444),(f3445),(f3446),(f3447),(f3448),(f3449),(f3450),(f3451),(f3452),(f3453),(f3454),(f3455),(f3456),(f3457),(f3458),(f3459),(f3460),(f3461),(f3462),(f3463),(f3464),(f3465),(f3466),(f3467),(f3468),(f3469),(f3470),(f3471),(f3472),(f3473),(f3474),(f3475),(f3476),(f3477),(f3478),(f3479),(f3480),(f3481),(f3482),(f3483),(f3484),(f3485),(f3486),(f3487),(f3488),(f3489),(f3490),(f3491),(f3492),(f3493),(f3494),(f3495),(f3496),(f3497),(f3498),(f3499),(f3500),(f3501),(f3502),(f3503),(f3504),(f3505),(f3506),(f3507),(f3508),(f3509),(f3510),(f3511),(f3512),(f3513),(f3514),(f3515),(f3516),(f3517),(f3518),(f3519),(f3520),(f3521),(f3522),(f3523),(f3524),(f3525),(f3526),(f3527),(f3528),(f3529),(f3530),(f3531),(f3532),(f3533),(f3534),(f3535),(f3536),(f3537),(f3538),(f3539),(f3540),(f3541),(f3542),(f3543),(f3544),(f3545),(f3546),(f3547),(f3548),(f3549),(f3550),(f3551),(f3552),(f3553),(f3554),(f3555),(f3556),(f3557),(f3558),(f3559),(f3560),(f3561),(f3562),(f3563),(f3564),(f3565),(f3566),(f3567),(f3568),(f3569),(f3570),(f3571),(f3572),(f3573),(f3574),(f3575),(f3576),(f3577),(f3578),(f3579),(f3580),(f3581),(f3582),(f3583),(f3584),(f3585),(f3586),(f3587),(f3588),(f3589),(f3590),(f3591),(f3592),(f3593),(f3594),(f3595),(f3596),(f3597),(f3598),(f3599),(f3600),(f3601),(f3602),(f3603),(f3604),(f3605),(f3606),(f3607),(f3608),(f3609),(f3610),(f3611),(f3612),(f3613),(f3614),(f3615),(f3616),(f3617),(f3618),(f3619),(f3620),(f3621),(f3622),(f3623),(f3624),(f3625),(f3626),(f3627),(f3628),(f3629),(f3630),(f3631),(f3632),(f3633),(f3634),(f3635),(f3636),(f3637),(f3638),(f3639),(f3640),(f3641),(f3642),(f3643),(f3644),(f3645),(f3646),(f3647),(f3648),(f3649),(f3650),(f3651),(f3652),(f3653),(f3654),(f3655),(f3656),(f3657),(f3658),(f3659),(f3660),(f3661),(f3662),(f3663),(f3664),(f3665),(f3666),(f3667),(f3668),(f3669),(f3670),(f3671),(f3672),(f3673),(f3674),(f3675),(f3676),(f3677),(f3678),(f3679),(f3680),(f3681),(f3682),(f3683),(f3684),(f3685),(f3686),(f3687),(f3688),(f3689),(f3690),(f3691),(f3692),(f3693),(f3694),(f3695),(f3696),(f3697),(f3698),(f3699),(f3700),(f3701),(f3702),(f3703),(f3704),(f3705),(f3706),(f3707),(f3708),(f3709),(f3710),(f3711),(f3712),(f3713),(f3714),(f3715),(f3716),(f3717),(f3718),(f3719),(f3720),(f3721),(f3722),(f3723),(f3724),(f3725),(f3726),(f3727),(f3728),(f3729),(f3730),(f3731),(f3732),(f3733),(f3734),(f3735),(f3736),(f3737),(f3738),(f3739),(f3740),(f3741),(f3742),(f3743),(f3744),(f3745),(f3746),(f3747),(f3748),(f3749),(f3750),(f3751),(f3752),(f3753),(f3754),(f3755),(f3756),(f3757),(f3758),(f3759),(f3760),(f3761),(f3762),(f3763),(f3764),(f3765),(f3766),(f3767),(f3768),(f3769),(f3770),(f3771),(f3772),(f3773),(f3774),(f3775),(f3776),(f3777),(f3778),(f3779),(f3780),(f3781),(f3782),(f3783),(f3784),(f3785),(f3786),(f3787),(f3788),(f3789),(f3790),(f3791),(f3792),(f3793),(f3794),(f3795),(f3796),(f3797),(f3798),(f3799),(f3800),(f3801),(f3802),(f3803),(f3804),(f3805),(f3806),(f3807),(f3808),(f3809),(f3810),(f3811),(f3812),(f3813),(f3814),(f3815),(f3816),(f3817),(f3818),(f3819),(f3820),(f3821),(f3822),(f3823),(f3824),(f3825),(f3826),(f3827),(f3828),(f3829),(f3830),(f3831),(f3832),(f3833),(f3834),(f3835),(f3836),(f3837),(f3838),(f3839),(f3840),(f3841),(f3842),(f3843),(f3844),(f3845),(f3846),(f3847),(f3848),(f3849),(f3850),(f3851),(f3852),(f3853),(f3854),(f3855),(f3856),(f3857),(f3858),(f3859),(f3860),(f3861),(f3862),(f3863),(f3864),(f3865),(f3866),(f3867),(f3868),(f3869),(f3870),(f3871),(f3872),(f3873),(f3874),(f3875),(f3876),(f3877),(f3878),(f3879),(f3880),(f3881),(f3882),(f3883),(f3884),(f3885),(f3886),(f3887),(f3888),(f3889),(f3890),(f3891),(f3892),(f3893),(f3894),(f3895),(f3896),(f3897),(f3898),(f3899),(f3900),(f3901),(f3902),(f3903),(f3904),(f3905),(f3906),(f3907),(f3908),(f3909),(f3910),(f3911),(f3912),(f3913),(f3914),(f3915),(f3916),(f3917),(f3918),(f3919),(f3920),(f3921),(f3922),(f3923),(f3924),(f3925),(f3926),(f3927),(f3928),(f3929),(f3930),(f3931),(f3932),(f3933),(f3934),(f3935),(f3936),(f3937),(f3938),(f3939),(f3940),(f3941),(f3942),(f3943),(f3944),(f3945),(f3946),(f3947),(f3948),(f3949),(f3950),(f3951),(f3952),(f3953),(f3954),(f3955),(f3956),(f3957),(f3958),(f3959),(f3960),(f3961),(f3962),(f3963),(f3964),(f3965),(f3966),(f3967),(f3968),(f3969),(f3970),(f3971),(f3972),(f3973),(f3974),(f3975),(f3976),(f3977),(f3978),(f3979),(f3980),(f3981),(f3982),(f3983),(f3984),(f3985),(f3986),(f3987),(f3988),(f3989),(f3990),(f3991),(f3992),(f3993),(f3994),(f3995),(f3996),(f3997),(f3998),(f3999),(f4000),(f4001),(f4002),(f4003),(f4004),(f4005),(f4006),(f4007),(f4008),(f4009),(f4010),(f4011),(f4012),(f4013),(f4014),(f4015),(f4016),(f4017),(f4018),(f4019),(f4020),(f4021),(f4022),(f4023),(f4024),(f4025),(f4026),(f4027),(f4028),(f4029),(f4030),(f4031),(f4032),(f4033),(f4034),(f4035),(f4036),(f4037),(f4038),(f4039),(f4040),(f4041),(f4042),(f4043),(f4044),(f4045),(f4046),(f4047),(f4048),(f4049),(f4050),(f4051),(f4052),(f4053),(f4054),(f4055),(f4056),(f4057),(f4058),(f4059),(f4060),(f4061),(f4062),(f4063),(f4064),(f4065),(f4066),(f4067),(f4068),(f4069),(f4070),(f4071),(f4072),(f4073),(f4074),(f4075),(f4076),(f4077),(f4078),(f4079),(f4080),(f4081),(f4082),(f4083),(f4084),(f4085),(f4086),(f4087),(f4088),(f4089),(f4090),(f4091),(f4092),(f4093),(f4094),(f4095),(f4096),(f4097),(f4098),(f4099),(f4100),(f4101),(f4102),(f4103),(f4104),(f4105),(f4106),(f4107),(f4108),(f4109),(f4110),(f4111),(f4112),(f4113),(f4114),(f4115),(f4116),(f4117),(f4118),(f4119),(f4120),(f4121),(f4122),(f4123),(f4124),(f4125),(f4126),(f4127),(f4128),(f4129),(f4130),(f4131),(f4132),(f4133),(f4134),(f4135),(f4136),(f4137),(f4138),(f4139),(f4140),(f4141),(f4142),(f4143),(f4144),(f4145),(f4146),(f4147),(f4148),(f4149),(f4150),(f4151),(f4152),(f4153),(f4154),(f4155),(f4156),(f4157),(f4158),(f4159),(f4160),(f4161),(f4162),(f4163),(f4164),(f4165),(f4166),(f4167),(f4168),(f4169),(f4170),(f4171),(f4172),(f4173),(f4174),(f4175),(f4176),(f4177),(f4178),(f4179),(f4180),(f4181),(f4182),(f4183),(f4184),(f4185),(f4186),(f4187),(f4188),(f4189),(f4190),(f4191),(f4192),(f4193),(f4194),(f4195),(f4196),(f4197),(f4198),(f4199),(f4200),(f4201),(f4202),(f4203),(f4204),(f4205),(f4206),(f4207),(f4208),(f4209),(f4210),(f4211),(f4212),(f4213),(f4214),(f4215),(f4216),(f4217),(f4218),(f4219),(f4220),(f4221),(f4222),(f4223),(f4224),(f4225),(f4226),(f4227),(f4228),(f4229),(f4230),(f4231),(f4232),(f4233),(f4234),(f4235),(f4236),(f4237),(f4238),(f4239),(f4240),(f4241),(f4242),(f4243),(f4244),(f4245),(f4246),(f4247),(f4248),(f4249),(f4250),(f4251),(f4252),(f4253),(f4254),(f4255),(f4256),(f4257),(f4258),(f4259),(f4260),(f4261),(f4262),(f4263),(f4264),(f4265),(f4266),(f4267),(f4268),(f4269),(f4270),(f4271),(f4272),(f4273),(f4274),(f4275),(f4276),(f4277),(f4278),(f4279),(f4280),(f4281),(f4282),(f4283),(f4284),(f4285),(f4286),(f4287),(f4288),(f4289),(f4290),(f4291),(f4292),(f4293),(f4294),(f4295),(f4296),(f4297),(f4298),(f4299),(f4300),(f4301),(f4302),(f4303),(f4304),(f4305),(f4306),(f4307),(f4308),(f4309),(f4310),(f4311),(f4312),(f4313),(f4314),(f4315),(f4316),(f4317),(f4318),(f4319),(f4320),(f4321),(f4322),(f4323),(f4324),(f4325),(f4326),(f4327),(f4328),(f4329),(f4330),(f4331),(f4332),(f4333),(f4334),(f4335),(f4336),(f4337),(f4338),(f4339),(f4340),(f4341),(f4342),(f4343),(f4344),(f4345),(f4346),(f4347),(f4348),(f4349),(f4350),(f4351),(f4352),(f4353),(f4354),(f4355),(f4356),(f4357),(f4358),(f4359),(f4360),(f4361),(f4362),(f4363),(f4364),(f4365),(f4366),(f4367),(f4368),(f4369),(f4370),(f4371),(f4372),(f4373),(f4374),(f4375),(f4376),(f4377),(f4378),(f4379),(f4380),(f4381),(f4382),(f4383),(f4384),(f4385),(f4386),(f4387),(f4388),(f4389),(f4390),(f4391),(f4392),(f4393),(f4394),(f4395),(f4396),(f4397),(f4398),(f4399),(f4400),(f4401),(f4402),(f4403),(f4404),(f4405),(f4406),(f4407),(f4408),(f4409),(f4410),(f4411),(f4412),(f4413),(f4414),(f4415),(f4416),(f4417),(f4418),(f4419),(f4420),(f4421),(f4422),(f4423),(f4424),(f4425),(f4426),(f4427),(f4428),(f4429),(f4430),(f4431),(f4432),(f4433),(f4434),(f4435),(f4436),(f4437),(f4438),(f4439),(f4440),(f4441),(f4442),(f4443),(f4444),(f4445),(f4446),(f4447),(f4448),(f4449),(f4450),(f4451),(f4452),(f4453),(f4454),(f4455),(f4456),(f4457),(f4458),(f4459),(f4460),(f4461),(f4462),(f4463),(f4464),(f4465),(f4466),(f4467),(f4468),(f4469),(f4470),(f4471),(f4472),(f4473),(f4474),(f4475),(f4476),(f4477),(f4478),(f4479),(f4480),(f4481),(f4482),(f4483),(f4484),(f4485),(f4486),(f4487),(f4488),(f4489),(f4490),(f4491),(f4492),(f4493),(f4494),(f4495),(f4496),(f4497),(f4498),(f4499),(f4500),(f4501),(f4502),(f4503),(f4504),(f4505),(f4506),(f4507),(f4508),(f4509),(f4510),(f4511),(f4512),(f4513),(f4514),(f4515),(f4516),(f4517),(f4518),(f4519),(f4520),(f4521),(f4522),(f4523),(f4524),(f4525),(f4526),(f4527),(f4528),(f4529),(f4530),(f4531),(f4532),(f4533),(f4534),(f4535),(f4536),(f4537),(f4538),(f4539),(f4540),(f4541),(f4542),(f4543),(f4544),(f4545),(f4546),(f4547),(f4548),(f4549),(f4550),(f4551),(f4552),(f4553),(f4554),(f4555),(f4556),(f4557),(f4558),(f4559),(f4560),(f4561),(f4562),(f4563),(f4564),(f4565),(f4566),(f4567),(f4568),(f4569),(f4570),(f4571),(f4572),(f4573),(f4574),(f4575),(f4576),(f4577),(f4578),(f4579),(f4580),(f4581),(f4582),(f4583),(f4584),(f4585),(f4586),(f4587),(f4588),(f4589),(f4590),(f4591),(f4592),(f4593),(f4594),(f4595),(f4596),(f4597),(f4598),(f4599),(f4600),(f4601),(f4602),(f4603),(f4604),(f4605),(f4606),(f4607),(f4608),(f4609),(f4610),(f4611),(f4612),(f4613),(f4614),(f4615),(f4616),(f4617),(f4618),(f4619),(f4620),(f4621),(f4622),(f4623),(f4624),(f4625),(f4626),(f4627),(f4628),(f4629),(f4630),(f4631),(f4632),(f4633),(f4634),(f4635),(f4636),(f4637),(f4638),(f4639),(f4640),(f4641),(f4642),(f4643),(f4644),(f4645),(f4646),(f4647),(f4648),(f4649),(f4650),(f4651),(f4652),(f4653),(f4654),(f4655),(f4656),(f4657),(f4658),(f4659),(f4660),(f4661),(f4662),(f4663),(f4664),(f4665),(f4666),(f4667),(f4668),(f4669),(f4670),(f4671),(f4672),(f4673),(f4674),(f4675),(f4676),(f4677),(f4678),(f4679),(f4680),(f4681),(f4682),(f4683),(f4684),(f4685),(f4686),(f4687),(f4688),(f4689),(f4690),(f4691),(f4692),(f4693),(f4694),(f4695),(f4696),(f4697),(f4698),(f4699),(f4700),(f4701),(f4702),(f4703),(f4704),(f4705),(f4706),(f4707),(f4708),(f4709),(f4710),(f4711),(f4712),(f4713),(f4714),(f4715),(f4716),(f4717),(f4718),(f4719),(f4720),(f4721),(f4722),(f4723),(f4724),(f4725),(f4726),(f4727),(f4728),(f4729),(f4730),(f4731),(f4732),(f4733),(f4734),(f4735),(f4736),(f4737),(f4738),(f4739),(f4740),(f4741),(f4742),(f4743),(f4744),(f4745),(f4746),(f4747),(f4748),(f4749),(f4750),(f4751),(f4752),(f4753),(f4754),(f4755),(f4756),(f4757),(f4758),(f4759),(f4760),(f4761),(f4762),(f4763),(f4764),(f4765),(f4766),(f4767),(f4768),(f4769),(f4770),(f4771),(f4772),(f4773),(f4774),(f4775),(f4776),(f4777),(f4778),(f4779),(f4780),(f4781),(f4782),(f4783),(f4784),(f4785),(f4786),(f4787),(f4788),(f4789),(f4790),(f4791),(f4792),(f4793),(f4794),(f4795),(f4796),(f4797),(f4798),(f4799),(f4800),(f4801),(f4802),(f4803),(f4804),(f4805),(f4806),(f4807),(f4808),(f4809),(f4810),(f4811),(f4812),(f4813),(f4814),(f4815),(f4816),(f4817),(f4818),(f4819),(f4820),(f4821),(f4822),(f4823),(f4824),(f4825),(f4826),(f4827),(f4828),(f4829),(f4830),(f4831),(f4832),(f4833),(f4834),(f4835),(f4836),(f4837),(f4838),(f4839),(f4840),(f4841),(f4842),(f4843),(f4844),(f4845),(f4846),(f4847),(f4848),(f4849),(f4850),(f4851),(f4852),(f4853),(f4854),(f4855),(f4856),(f4857),(f4858),(f4859),(f4860),(f4861),(f4862),(f4863),(f4864),(f4865),(f4866),(f4867),(f4868),(f4869),(f4870),(f4871),(f4872),(f4873),(f4874),(f4875),(f4876),(f4877),(f4878),(f4879),(f4880),(f4881),(f4882),(f4883),(f4884),(f4885),(f4886),(f4887),(f4888),(f4889),(f4890),(f4891),(f4892),(f4893),(f4894),(f4895),(f4896),(f4897),(f4898),(f4899),(f4900),(f4901),(f4902),(f4903),(f4904),(f4905),(f4906),(f4907),(f4908),(f4909),(f4910),(f4911),(f4912),(f4913),(f4914),(f4915),(f4916),(f4917),(f4918),(f4919),(f4920),(f4921),(f4922),(f4923),(f4924),(f4925),(f4926),(f4927),(f4928),(f4929),(f4930),(f4931),(f4932),(f4933),(f4934),(f4935),(f4936),(f4937),(f4938),(f4939),(f4940),(f4941),(f4942),(f4943),(f4944),(f4945),(f4946),(f4947),(f4948),(f4949),(f4950),(f4951),(f4952),(f4953),(f4954),(f4955),(f4956),(f4957),(f4958),(f4959),(f4960),(f4961),(f4962),(f4963),(f4964),(f4965),(f4966),(f4967),(f4968),(f4969),(f4970),(f4971),(f4972),(f4973),(f4974),(f4975),(f4976),(f4977),(f4978),(f4979),(f4980),(f4981),(f4982),(f4983),(f4984),(f4985),(f4986),(f4987),(f4988),(f4989),(f4990),(f4991),(f4992),(f4993),(f4994),(f4995),(f4996),(f4997),(f4998),(f4999),(f5000),(f5001),(f5002),(f5003),(f5004),(f5005),(f5006),(f5007),(f5008),(f5009),(f5010),(f5011),(f5012),(f5013),(f5014),(f5015),(f5016),(f5017),(f5018),(f5019),(f5020),(f5021),(f5022),(f5023),(f5024),(f5025),(f5026),(f5027),(f5028),(f5029),(f5030),(f5031),(f5032),(f5033),(f5034),(f5035),(f5036),(f5037),(f5038),(f5039),(f5040),(f5041),(f5042),(f5043),(f5044),(f5045),(f5046),(f5047),(f5048),(f5049),(f5050),(f5051),(f5052),(f5053),(f5054),(f5055),(f5056),(f5057),(f5058),(f5059),(f5060),(f5061),(f5062),(f5063),(f5064),(f5065),(f5066),(f5067),(f5068),(f5069),(f5070),(f5071),(f5072),(f5073),(f5074),(f5075),(f5076),(f5077),(f5078),(f5079),(f5080),(f5081),(f5082),(f5083),(f5084),(f5085),(f5086),(f5087),(f5088),(f5089),(f5090),(f5091),(f5092),(f5093),(f5094),(f5095),(f5096),(f5097),(f5098),(f5099),(f5100),(f5101),(f5102),(f5103),(f5104),(f5105),(f5106),(f5107),(f5108),(f5109),(f5110),(f5111),(f5112),(f5113),(f5114),(f5115),(f5116),(f5117),(f5118),(f5119),(f5120),(f5121),(f5122),(f5123),(f5124),(f5125),(f5126),(f5127),(f5128),(f5129),(f5130),(f5131),(f5132),(f5133),(f5134),(f5135),(f5136),(f5137),(f5138),(f5139),(f5140),(f5141),(f5142),(f5143),(f5144),(f5145),(f5146),(f5147),(f5148),(f5149),(f5150),(f5151),(f5152),(f5153),(f5154),(f5155),(f5156),(f5157),(f5158),(f5159),(f5160),(f5161),(f5162),(f5163),(f5164),(f5165),(f5166),(f5167),(f5168),(f5169),(f5170),(f5171),(f5172),(f5173),(f5174),(f5175),(f5176),(f5177),(f5178),(f5179),(f5180),(f5181),(f5182),(f5183),(f5184),(f5185),(f5186),(f5187),(f5188),(f5189),(f5190),(f5191),(f5192),(f5193),(f5194),(f5195),(f5196),(f5197),(f5198),(f5199),(f5200),(f5201),(f5202),(f5203),(f5204),(f5205),(f5206),(f5207),(f5208),(f5209),(f5210),(f5211),(f5212),(f5213),(f5214),(f5215),(f5216),(f5217),(f5218),(f5219),(f5220),(f5221),(f5222),(f5223),(f5224),(f5225),(f5226),(f5227),(f5228),(f5229),(f5230),(f5231),(f5232),(f5233),(f5234),(f5235),(f5236),(f5237),(f5238),(f5239),(f5240),(f5241),(f5242),(f5243),(f5244),(f5245),(f5246),(f5247),(f5248),(f5249),(f5250),(f5251),(f5252),(f5253),(f5254),(f5255),(f5256),(f5257),(f5258),(f5259),(f5260),(f5261),(f5262),(f5263),(f5264),(f5265),(f5266),(f5267),(f5268),(f5269),(f5270),(f5271),(f5272),(f5273),(f5274),(f5275),(f5276),(f5277),(f5278),(f5279),(f5280),(f5281),(f5282),(f5283),(f5284),(f5285),(f5286),(f5287),(f5288),(f5289),(f5290),(f5291),(f5292),(f5293),(f5294),(f5295),(f5296),(f5297),(f5298),(f5299),(f5300),(f5301),(f5302),(f5303),(f5304),(f5305),(f5306),(f5307),(f5308),(f5309),(f5310),(f5311),(f5312),(f5313),(f5314),(f5315),(f5316),(f5317),(f5318),(f5319),(f5320),(f5321),(f5322),(f5323),(f5324),(f5325),(f5326),(f5327),(f5328),(f5329),(f5330),(f5331),(f5332),(f5333),(f5334),(f5335),(f5336),(f5337),(f5338),(f5339),(f5340),(f5341),(f5342),(f5343),(f5344),(f5345),(f5346),(f5347),(f5348),(f5349),(f5350),(f5351),(f5352),(f5353),(f5354),(f5355),(f5356),(f5357),(f5358),(f5359),(f5360),(f5361),(f5362),(f5363),(f5364),(f5365),(f5366),(f5367),(f5368),(f5369),(f5370),(f5371),(f5372),(f5373),(f5374),(f5375),(f5376),(f5377),(f5378),(f5379),(f5380),(f5381),(f5382),(f5383),(f5384),(f5385),(f5386),(f5387),(f5388),(f5389),(f5390),(f5391),(f5392),(f5393),(f5394),(f5395),(f5396),(f5397),(f5398),(f5399),(f5400),(f5401),(f5402),(f5403),(f5404),(f5405),(f5406),(f5407),(f5408),(f5409),(f5410),(f5411),(f5412),(f5413),(f5414),(f5415),(f5416),(f5417),(f5418),(f5419),(f5420),(f5421),(f5422),(f5423),(f5424),(f5425),(f5426),(f5427),(f5428),(f5429),(f5430),(f5431),(f5432),(f5433),(f5434),(f5435),(f5436),(f5437),(f5438),(f5439),(f5440),(f5441),(f5442),(f5443),(f5444),(f5445),(f5446),(f5447),(f5448),(f5449),(f5450),(f5451),(f5452),(f5453),(f5454),(f5455),(f5456),(f5457),(f5458),(f5459),(f5460),(f5461),(f5462),(f5463),(f5464),(f5465),(f5466),(f5467),(f5468),(f5469),(f5470),(f5471),(f5472),(f5473),(f5474),(f5475),(f5476),(f5477),(f5478),(f5479),(f5480),(f5481),(f5482),(f5483),(f5484),(f5485),(f5486),(f5487),(f5488),(f5489),(f5490),(f5491),(f5492),(f5493),(f5494),(f5495),(f5496),(f5497),(f5498),(f5499),(f5500),(f5501),(f5502),(f5503),(f5504),(f5505),(f5506),(f5507),(f5508),(f5509),(f5510),(f5511),(f5512),(f5513),(f5514),(f5515),(f5516),(f5517),(f5518),(f5519),(f5520),(f5521),(f5522),(f5523),(f5524),(f5525),(f5526),(f5527),(f5528),(f5529),(f5530),(f5531),(f5532),(f5533),(f5534),(f5535),(f5536),(f5537),(f5538),(f5539),(f5540),(f5541),(f5542),(f5543),(f5544),(f5545),(f5546),(f5547),(f5548),(f5549),(f5550),(f5551),(f5552),(f5553),(f5554),(f5555),(f5556),(f5557),(f5558),(f5559),(f5560),(f5561),(f5562),(f5563),(f5564),(f5565),(f5566),(f5567),(f5568),(f5569),(f5570),(f5571),(f5572),(f5573),(f5574),(f5575),(f5576),(f5577),(f5578),(f5579),(f5580),(f5581),(f5582),(f5583),(f5584),(f5585),(f5586),(f5587),(f5588),(f5589),(f5590),(f5591),(f5592),(f5593),(f5594),(f5595),(f5596),(f5597),(f5598),(f5599),(f5600),(f5601),(f5602),(f5603),(f5604),(f5605),(f5606),(f5607),(f5608),(f5609),(f5610),(f5611),(f5612),(f5613),(f5614),(f5615),(f5616),(f5617),(f5618),(f5619),(f5620),(f5621),(f5622),(f5623),(f5624),(f5625),(f5626),(f5627),(f5628),(f5629),(f5630),(f5631),(f5632),(f5633),(f5634),(f5635),(f5636),(f5637),(f5638),(f5639),(f5640),(f5641),(f5642),(f5643),(f5644),(f5645),(f5646),(f5647),(f5648),(f5649),(f5650),(f5651),(f5652),(f5653),(f5654),(f5655),(f5656),(f5657),(f5658),(f5659),(f5660),(f5661),(f5662),(f5663),(f5664),(f5665),(f5666),(f5667),(f5668),(f5669),(f5670),(f5671),(f5672),(f5673),(f5674),(f5675),(f5676),(f5677),(f5678),(f5679),(f5680),(f5681),(f5682),(f5683),(f5684),(f5685),(f5686),(f5687),(f5688),(f5689),(f5690),(f5691),(f5692),(f5693),(f5694),(f5695),(f5696),(f5697),(f5698),(f5699),(f5700),(f5701),(f5702),(f5703),(f5704),(f5705),(f5706),(f5707),(f5708),(f5709),(f5710),(f5711),(f5712),(f5713),(f5714),(f5715),(f5716),(f5717),(f5718),(f5719),(f5720),(f5721),(f5722),(f5723),(f5724),(f5725),(f5726),(f5727),(f5728),(f5729),(f5730),(f5731),(f5732),(f5733),(f5734),(f5735),(f5736),(f5737),(f5738),(f5739),(f5740),(f5741),(f5742),(f5743),(f5744),(f5745),(f5746),(f5747),(f5748),(f5749),(f5750),(f5751),(f5752),(f5753),(f5754),(f5755),(f5756),(f5757),(f5758),(f5759),(f5760),(f5761),(f5762),(f5763),(f5764),(f5765),(f5766),(f5767),(f5768),(f5769),(f5770),(f5771),(f5772),(f5773),(f5774),(f5775),(f5776),(f5777),(f5778),(f5779),(f5780),(f5781),(f5782),(f5783),(f5784),(f5785),(f5786),(f5787),(f5788),(f5789),(f5790),(f5791),(f5792),(f5793),(f5794),(f5795),(f5796),(f5797),(f5798),(f5799),(f5800),(f5801),(f5802),(f5803),(f5804),(f5805),(f5806),(f5807),(f5808),(f5809),(f5810),(f5811),(f5812),(f5813),(f5814),(f5815),(f5816),(f5817),(f5818),(f5819),(f5820),(f5821),(f5822),(f5823),(f5824),(f5825),(f5826),(f5827),(f5828),(f5829),(f5830),(f5831),(f5832),(f5833),(f5834),(f5835),(f5836),(f5837),(f5838),(f5839),(f5840),(f5841),(f5842),(f5843),(f5844),(f5845),(f5846),(f5847),(f5848),(f5849),(f5850),(f5851),(f5852),(f5853),(f5854),(f5855),(f5856),(f5857),(f5858),(f5859),(f5860),(f5861),(f5862),(f5863),(f5864),(f5865),(f5866),(f5867),(f5868),(f5869),(f5870),(f5871),(f5872),(f5873),(f5874),(f5875),(f5876),(f5877),(f5878),(f5879),(f5880),(f5881),(f5882),(f5883),(f5884),(f5885),(f5886),(f5887),(f5888),(f5889),(f5890),(f5891),(f5892),(f5893),(f5894),(f5895),(f5896),(f5897),(f5898),(f5899),(f5900),(f5901),(f5902),(f5903),(f5904),(f5905),(f5906),(f5907),(f5908),(f5909),(f5910),(f5911),(f5912),(f5913),(f5914),(f5915),(f5916),(f5917),(f5918),(f5919),(f5920),(f5921),(f5922),(f5923),(f5924),(f5925),(f5926),(f5927),(f5928),(f5929),(f5930),(f5931),(f5932),(f5933),(f5934),(f5935),(f5936),(f5937),(f5938),(f5939),(f5940),(f5941),(f5942),(f5943),(f5944),(f5945),(f5946),(f5947),(f5948),(f5949),(f5950),(f5951),(f5952),(f5953),(f5954),(f5955),(f5956),(f5957),(f5958),(f5959),(f5960),(f5961),(f5962),(f5963),(f5964),(f5965),(f5966),(f5967),(f5968),(f5969),(f5970),(f5971),(f5972),(f5973),(f5974),(f5975),(f5976),(f5977),(f5978),(f5979),(f5980),(f5981),(f5982),(f5983),(f5984),(f5985),(f5986),(f5987),(f5988),(f5989),(f5990),(f5991),(f5992),(f5993),(f5994),(f5995),(f5996),(f5997),(f5998),(f5999),(f6000),(f6001),(f6002),(f6003),(f6004),(f6005),(f6006),(f6007),(f6008),(f6009),(f6010),(f6011),(f6012),(f6013),(f6014),(f6015),(f6016),(f6017),(f6018),(f6019),(f6020),(f6021),(f6022),(f6023),(f6024),(f6025),(f6026),(f6027),(f6028),(f6029),(f6030),(f6031),(f6032),(f6033),(f6034),(f6035),(f6036),(f6037),(f6038),(f6039),(f6040),(f6041),(f6042),(f6043),(f6044),(f6045),(f6046),(f6047),(f6048),(f6049),(f6050),(f6051),(f6052),(f6053),(f6054),(f6055),(f6056),(f6057),(f6058),(f6059),(f6060),(f6061),(f6062),(f6063),(f6064),(f6065),(f6066),(f6067),(f6068),(f6069),(f6070),(f6071),(f6072),(f6073),(f6074),(f6075),(f6076),(f6077),(f6078),(f6079),(f6080),(f6081),(f6082),(f6083),(f6084),(f6085),(f6086),(f6087),(f6088),(f6089),(f6090),(f6091),(f6092),(f6093),(f6094),(f6095),(f6096),(f6097),(f6098),(f6099),(f6100),(f6101),(f6102),(f6103),(f6104),(f6105),(f6106),(f6107),(f6108),(f6109),(f6110),(f6111),(f6112),(f6113),(f6114),(f6115),(f6116),(f6117),(f6118),(f6119),(f6120),(f6121),(f6122),(f6123),(f6124),(f6125),(f6126),(f6127),(f6128),(f6129),(f6130),(f6131),(f6132),(f6133),(f6134),(f6135),(f6136),(f6137),(f6138),(f6139),(f6140),(f6141),(f6142),(f6143),(f6144),(f6145),(f6146),(f6147),(f6148),(f6149),(f6150),(f6151),(f6152),(f6153),(f6154),(f6155),(f6156),(f6157),(f6158),(f6159),(f6160),(f6161),(f6162),(f6163),(f6164),(f6165),(f6166),(f6167),(f6168),(f6169),(f6170),(f6171),(f6172),(f6173),(f6174),(f6175),(f6176),(f6177),(f6178),(f6179),(f6180),(f6181),(f6182),(f6183),(f6184),(f6185),(f6186),(f6187),(f6188),(f6189),(f6190),(f6191),(f6192),(f6193),(f6194),(f6195),(f6196),(f6197),(f6198),(f6199),(f6200),(f6201),(f6202),(f6203),(f6204),(f6205),(f6206),(f6207),(f6208),(f6209),(f6210),(f6211),(f6212),(f6213),(f6214),(f6215),(f6216),(f6217),(f6218),(f6219),(f6220),(f6221),(f6222),(f6223),(f6224),(f6225),(f6226),(f6227),(f6228),(f6229),(f6230),(f6231),(f6232),(f6233),(f6234),(f6235),(f6236),(f6237),(f6238),(f6239),(f6240),(f6241),(f6242),(f6243),(f6244),(f6245),(f6246),(f6247),(f6248),(f6249),(f6250),(f6251),(f6252),(f6253),(f6254),(f6255),(f6256),(f6257),(f6258),(f6259),(f6260),(f6261),(f6262),(f6263),(f6264),(f6265),(f6266),(f6267),(f6268),(f6269),(f6270),(f6271),(f6272),(f6273),(f6274),(f6275),(f6276),(f6277),(f6278),(f6279),(f6280),(f6281),(f6282),(f6283),(f6284),(f6285),(f6286),(f6287),(f6288),(f6289),(f6290),(f6291),(f6292),(f6293),(f6294),(f6295),(f6296),(f6297),(f6298),(f6299),(f6300),(f6301),(f6302),(f6303),(f6304),(f6305),(f6306),(f6307),(f6308),(f6309),(f6310),(f6311),(f6312),(f6313),(f6314),(f6315),(f6316),(f6317),(f6318),(f6319),(f6320),(f6321),(f6322),(f6323),(f6324),(f6325),(f6326),(f6327),(f6328),(f6329),(f6330),(f6331),(f6332),(f6333),(f6334),(f6335),(f6336),(f6337),(f6338),(f6339),(f6340),(f6341),(f6342),(f6343),(f6344),(f6345),(f6346),(f6347),(f6348),(f6349),(f6350),(f6351),(f6352),(f6353),(f6354),(f6355),(f6356),(f6357),(f6358),(f6359),(f6360),(f6361),(f6362),(f6363),(f6364),(f6365),(f6366),(f6367),(f6368),(f6369),(f6370),(f6371),(f6372),(f6373),(f6374),(f6375),(f6376),(f6377),(f6378),(f6379),(f6380),(f6381),(f6382),(f6383),(f6384),(f6385),(f6386),(f6387),(f6388),(f6389),(f6390),(f6391),(f6392),(f6393),(f6394),(f6395),(f6396),(f6397),(f6398),(f6399),(f6400),(f6401),(f6402),(f6403),(f6404),(f6405),(f6406),(f6407),(f6408),(f6409),(f6410),(f6411),(f6412),(f6413),(f6414),(f6415),(f6416),(f6417),(f6418),(f6419),(f6420),(f6421),(f6422),(f6423),(f6424),(f6425),(f6426),(f6427),(f6428),(f6429),(f6430),(f6431),(f6432),(f6433),(f6434),(f6435),(f6436),(f6437),(f6438),(f6439),(f6440),(f6441),(f6442),(f6443),(f6444),(f6445),(f6446),(f6447),(f6448),(f6449),(f6450),(f6451),(f6452),(f6453),(f6454),(f6455),(f6456),(f6457),(f6458),(f6459),(f6460),(f6461),(f6462),(f6463),(f6464),(f6465),(f6466),(f6467),(f6468),(f6469),(f6470),(f6471),(f6472),(f6473),(f6474),(f6475),(f6476),(f6477),(f6478),(f6479),(f6480),(f6481),(f6482),(f6483),(f6484),(f6485),(f6486),(f6487),(f6488),(f6489),(f6490),(f6491),(f6492),(f6493),(f6494),(f6495),(f6496),(f6497),(f6498),(f6499),(f6500),(f6501),(f6502),(f6503),(f6504),(f6505),(f6506),(f6507),(f6508),(f6509),(f6510),(f6511),(f6512),(f6513),(f6514),(f6515),(f6516),(f6517),(f6518),(f6519),(f6520),(f6521),(f6522),(f6523),(f6524),(f6525),(f6526),(f6527),(f6528),(f6529),(f6530),(f6531),(f6532),(f6533),(f6534),(f6535),(f6536),(f6537),(f6538),(f6539),(f6540),(f6541),(f6542),(f6543),(f6544),(f6545),(f6546),(f6547),(f6548),(f6549),(f6550),(f6551),(f6552),(f6553),(f6554),(f6555),(f6556),(f6557),(f6558),(f6559),(f6560),(f6561),(f6562),(f6563),(f6564),(f6565),(f6566),(f6567),(f6568),(f6569),(f6570),(f6571),(f6572),(f6573),(f6574),(f6575),(f6576),(f6577),(f6578),(f6579),(f6580),(f6581),(f6582),(f6583),(f6584),(f6585),(f6586),(f6587),(f6588),(f6589),(f6590),(f6591),(f6592),(f6593),(f6594),(f6595),(f6596),(f6597),(f6598),(f6599),(f6600),(f6601),(f6602),(f6603),(f6604),(f6605),(f6606),(f6607),(f6608),(f6609),(f6610),(f6611),(f6612),(f6613),(f6614),(f6615),(f6616),(f6617),(f6618),(f6619),(f6620),(f6621),(f6622),(f6623),(f6624),(f6625),(f6626),(f6627),(f6628),(f6629),(f6630),(f6631),(f6632),(f6633),(f6634),(f6635),(f6636),(f6637),(f6638),(f6639),(f6640),(f6641),(f6642),(f6643),(f6644),(f6645),(f6646),(f6647),(f6648),(f6649),(f6650),(f6651),(f6652),(f6653),(f6654),(f6655),(f6656),(f6657),(f6658),(f6659),(f6660),(f6661),(f6662),(f6663),(f6664),(f6665),(f6666),(f6667),(f6668),(f6669),(f6670),(f6671),(f6672),(f6673),(f6674),(f6675),(f6676),(f6677),(f6678),(f6679),(f6680),(f6681),(f6682),(f6683),(f6684),(f6685),(f6686),(f6687),(f6688),(f6689),(f6690),(f6691),(f6692),(f6693),(f6694),(f6695),(f6696),(f6697),(f6698),(f6699),(f6700),(f6701),(f6702),(f6703),(f6704),(f6705),(f6706),(f6707),(f6708),(f6709),(f6710),(f6711),(f6712),(f6713),(f6714),(f6715),(f6716),(f6717),(f6718),(f6719),(f6720),(f6721),(f6722),(f6723),(f6724),(f6725),(f6726),(f6727),(f6728),(f6729),(f6730),(f6731),(f6732),(f6733),(f6734),(f6735),(f6736),(f6737),(f6738),(f6739),(f6740),(f6741),(f6742),(f6743),(f6744),(f6745),(f6746),(f6747),(f6748),(f6749),(f6750),(f6751),(f6752),(f6753),(f6754),(f6755),(f6756),(f6757),(f6758),(f6759),(f6760),(f6761),(f6762),(f6763),(f6764),(f6765),(f6766),(f6767),(f6768),(f6769),(f6770),(f6771),(f6772),(f6773),(f6774),(f6775),(f6776),(f6777),(f6778),(f6779),(f6780),(f6781),(f6782),(f6783),(f6784),(f6785),(f6786),(f6787),(f6788),(f6789),(f6790),(f6791),(f6792),(f6793),(f6794),(f6795),(f6796),(f6797),(f6798),(f6799),(f6800),(f6801),(f6802),(f6803),(f6804),(f6805),(f6806),(f6807),(f6808),(f6809),(f6810),(f6811),(f6812),(f6813),(f6814),(f6815),(f6816),(f6817),(f6818),(f6819),(f6820),(f6821),(f6822),(f6823),(f6824),(f6825),(f6826),(f6827),(f6828),(f6829),(f6830),(f6831),(f6832),(f6833),(f6834),(f6835),(f6836),(f6837),(f6838),(f6839),(f6840),(f6841),(f6842),(f6843),(f6844),(f6845),(f6846),(f6847),(f6848),(f6849),(f6850),(f6851),(f6852),(f6853),(f6854),(f6855),(f6856),(f6857),(f6858),(f6859),(f6860),(f6861),(f6862),(f6863),(f6864),(f6865),(f6866),(f6867),(f6868),(f6869),(f6870),(f6871),(f6872),(f6873),(f6874),(f6875),(f6876),(f6877),(f6878),(f6879),(f6880),(f6881),(f6882),(f6883),(f6884),(f6885),(f6886),(f6887),(f6888),(f6889),(f6890),(f6891),(f6892),(f6893),(f6894),(f6895),(f6896),(f6897),(f6898),(f6899),(f6900),(f6901),(f6902),(f6903),(f6904),(f6905),(f6906),(f6907),(f6908),(f6909),(f6910),(f6911),(f6912),(f6913),(f6914),(f6915),(f6916),(f6917),(f6918),(f6919),(f6920),(f6921),(f6922),(f6923),(f6924),(f6925),(f6926),(f6927),(f6928),(f6929),(f6930),(f6931),(f6932),(f6933),(f6934),(f6935),(f6936),(f6937),(f6938),(f6939),(f6940),(f6941),(f6942),(f6943),(f6944),(f6945),(f6946),(f6947),(f6948),(f6949),(f6950),(f6951),(f6952),(f6953),(f6954),(f6955),(f6956),(f6957),(f6958),(f6959),(f6960),(f6961),(f6962),(f6963),(f6964),(f6965),(f6966),(f6967),(f6968),(f6969),(f6970),(f6971),(f6972),(f6973),(f6974),(f6975),(f6976),(f6977),(f6978),(f6979),(f6980),(f6981),(f6982),(f6983),(f6984),(f6985),(f6986),(f6987),(f6988),(f6989),(f6990),(f6991),(f6992),(f6993),(f6994),(f6995),(f6996),(f6997),(f6998),(f6999),(f7000),(f7001),(f7002),(f7003),(f7004),(f7005),(f7006),(f7007),(f7008),(f7009),(f7010),(f7011),(f7012),(f7013),(f7014),(f7015),(f7016),(f7017),(f7018),(f7019),(f7020),(f7021),(f7022),(f7023),(f7024),(f7025),(f7026),(f7027),(f7028),(f7029),(f7030),(f7031),(f7032),(f7033),(f7034),(f7035),(f7036),(f7037),(f7038),(f7039),(f7040),(f7041),(f7042),(f7043),(f7044),(f7045),(f7046),(f7047),(f7048),(f7049),(f7050),(f7051),(f7052),(f7053),(f7054),(f7055),(f7056),(f7057),(f7058),(f7059),(f7060),(f7061),(f7062),(f7063),(f7064),(f7065),(f7066),(f7067),(f7068),(f7069),(f7070),(f7071),(f7072),(f7073),(f7074),(f7075),(f7076),(f7077),(f7078),(f7079),(f7080),(f7081),(f7082),(f7083),(f7084),(f7085),(f7086),(f7087),(f7088),(f7089),(f7090),(f7091),(f7092),(f7093),(f7094),(f7095),(f7096),(f7097),(f7098),(f7099),(f7100),(f7101),(f7102),(f7103),(f7104),(f7105),(f7106),(f7107),(f7108),(f7109),(f7110),(f7111),(f7112),(f7113),(f7114),(f7115),(f7116),(f7117),(f7118),(f7119),(f7120),(f7121),(f7122),(f7123),(f7124),(f7125),(f7126),(f7127),(f7128),(f7129),(f7130),(f7131),(f7132),(f7133),(f7134),(f7135),(f7136),(f7137),(f7138),(f7139),(f7140),(f7141),(f7142),(f7143),(f7144),(f7145),(f7146),(f7147),(f7148),(f7149),(f7150),(f7151),(f7152),(f7153),(f7154),(f7155),(f7156),(f7157),(f7158),(f7159),(f7160),(f7161),(f7162),(f7163),(f7164),(f7165),(f7166),(f7167),(f7168),(f7169),(f7170),(f7171),(f7172),(f7173),(f7174),(f7175),(f7176),(f7177),(f7178),(f7179),(f7180),(f7181),(f7182),(f7183),(f7184),(f7185),(f7186),(f7187),(f7188),(f7189),(f7190),(f7191),(f7192),(f7193),(f7194),(f7195),(f7196),(f7197),(f7198),(f7199),(f7200),(f7201),(f7202),(f7203),(f7204),(f7205),(f7206),(f7207),(f7208),(f7209),(f7210),(f7211),(f7212),(f7213),(f7214),(f7215),(f7216),(f7217),(f7218),(f7219),(f7220),(f7221),(f7222),(f7223),(f7224),(f7225),(f7226),(f7227),(f7228),(f7229),(f7230),(f7231),(f7232),(f7233),(f7234),(f7235),(f7236),(f7237),(f7238),(f7239),(f7240),(f7241),(f7242),(f7243),(f7244),(f7245),(f7246),(f7247),(f7248),(f7249),(f7250),(f7251),(f7252),(f7253),(f7254),(f7255),(f7256),(f7257),(f7258),(f7259),(f7260),(f7261),(f7262),(f7263),(f7264),(f7265),(f7266),(f7267),(f7268),(f7269),(f7270),(f7271),(f7272),(f7273),(f7274),(f7275),(f7276),(f7277),(f7278),(f7279),(f7280),(f7281),(f7282),(f7283),(f7284),(f7285),(f7286),(f7287),(f7288),(f7289),(f7290),(f7291),(f7292),(f7293),(f7294),(f7295),(f7296),(f7297),(f7298),(f7299),(f7300),(f7301),(f7302),(f7303),(f7304),(f7305),(f7306),(f7307),(f7308),(f7309),(f7310),(f7311),(f7312),(f7313),(f7314),(f7315),(f7316),(f7317),(f7318),(f7319),(f7320),(f7321),(f7322),(f7323),(f7324),(f7325),(f7326),(f7327),(f7328),(f7329),(f7330),(f7331),(f7332),(f7333),(f7334),(f7335),(f7336),(f7337),(f7338),(f7339),(f7340),(f7341),(f7342),(f7343),(f7344),(f7345),(f7346),(f7347),(f7348),(f7349),(f7350),(f7351),(f7352),(f7353),(f7354),(f7355),(f7356),(f7357),(f7358),(f7359),(f7360),(f7361),(f7362),(f7363),(f7364),(f7365),(f7366),(f7367),(f7368),(f7369),(f7370),(f7371),(f7372),(f7373),(f7374),(f7375),(f7376),(f7377),(f7378),(f7379),(f7380),(f7381),(f7382),(f7383),(f7384),(f7385),(f7386),(f7387),(f7388),(f7389),(f7390),(f7391),(f7392),(f7393),(f7394),(f7395),(f7396),(f7397),(f7398),(f7399),(f7400),(f7401),(f7402),(f7403),(f7404),(f7405),(f7406),(f7407),(f7408),(f7409),(f7410),(f7411),(f7412),(f7413),(f7414),(f7415),(f7416),(f7417),(f7418),(f7419),(f7420),(f7421),(f7422),(f7423),(f7424),(f7425),(f7426),(f7427),(f7428),(f7429),(f7430),(f7431),(f7432),(f7433),(f7434),(f7435),(f7436),(f7437),(f7438),(f7439),(f7440),(f7441),(f7442),(f7443),(f7444),(f7445),(f7446),(f7447),(f7448),(f7449),(f7450),(f7451),(f7452),(f7453),(f7454),(f7455),(f7456),(f7457),(f7458),(f7459),(f7460),(f7461),(f7462),(f7463),(f7464),(f7465),(f7466),(f7467),(f7468),(f7469),(f7470),(f7471),(f7472),(f7473),(f7474),(f7475),(f7476),(f7477),(f7478),(f7479),(f7480),(f7481),(f7482),(f7483),(f7484),(f7485),(f7486),(f7487),(f7488),(f7489),(f7490),(f7491),(f7492),(f7493),(f7494),(f7495),(f7496),(f7497),(f7498),(f7499),(f7500),(f7501),(f7502),(f7503),(f7504),(f7505),(f7506),(f7507),(f7508),(f7509),(f7510),(f7511),(f7512),(f7513),(f7514),(f7515),(f7516),(f7517),(f7518),(f7519),(f7520),(f7521),(f7522),(f7523),(f7524),(f7525),(f7526),(f7527),(f7528),(f7529),(f7530),(f7531),(f7532),(f7533),(f7534),(f7535),(f7536),(f7537),(f7538),(f7539),(f7540),(f7541),(f7542),(f7543),(f7544),(f7545),(f7546),(f7547),(f7548),(f7549),(f7550),(f7551),(f7552),(f7553),(f7554),(f7555),(f7556),(f7557),(f7558),(f7559),(f7560),(f7561),(f7562),(f7563),(f7564),(f7565),(f7566),(f7567),(f7568),(f7569),(f7570),(f7571),(f7572),(f7573),(f7574),(f7575),(f7576),(f7577),(f7578),(f7579),(f7580),(f7581),(f7582),(f7583),(f7584),(f7585),(f7586),(f7587),(f7588),(f7589),(f7590),(f7591),(f7592),(f7593),(f7594),(f7595),(f7596),(f7597),(f7598),(f7599),(f7600),(f7601),(f7602),(f7603),(f7604),(f7605),(f7606),(f7607),(f7608),(f7609),(f7610),(f7611),(f7612),(f7613),(f7614),(f7615),(f7616),(f7617),(f7618),(f7619),(f7620),(f7621),(f7622),(f7623),(f7624),(f7625),(f7626),(f7627),(f7628),(f7629),(f7630),(f7631),(f7632),(f7633),(f7634),(f7635),(f7636),(f7637),(f7638),(f7639),(f7640),(f7641),(f7642),(f7643),(f7644),(f7645),(f7646),(f7647),(f7648),(f7649),(f7650),(f7651),(f7652),(f7653),(f7654),(f7655),(f7656),(f7657),(f7658),(f7659),(f7660),(f7661),(f7662),(f7663),(f7664),(f7665),(f7666),(f7667),(f7668),(f7669),(f7670),(f7671),(f7672),(f7673),(f7674),(f7675),(f7676),(f7677),(f7678),(f7679),(f7680),(f7681),(f7682),(f7683),(f7684),(f7685),(f7686),(f7687),(f7688),(f7689),(f7690),(f7691),(f7692),(f7693),(f7694),(f7695),(f7696),(f7697),(f7698),(f7699),(f7700),(f7701),(f7702),(f7703),(f7704),(f7705),(f7706),(f7707),(f7708),(f7709),(f7710),(f7711),(f7712),(f7713),(f7714),(f7715),(f7716),(f7717),(f7718),(f7719),(f7720),(f7721),(f7722),(f7723),(f7724),(f7725),(f7726),(f7727),(f7728),(f7729),(f7730),(f7731),(f7732),(f7733),(f7734),(f7735),(f7736),(f7737),(f7738),(f7739),(f7740),(f7741),(f7742),(f7743),(f7744),(f7745),(f7746),(f7747),(f7748),(f7749),(f7750),(f7751),(f7752),(f7753),(f7754),(f7755),(f7756),(f7757),(f7758),(f7759),(f7760),(f7761),(f7762),(f7763),(f7764),(f7765),(f7766),(f7767),(f7768),(f7769),(f7770),(f7771),(f7772),(f7773),(f7774),(f7775),(f7776),(f7777),(f7778),(f7779),(f7780),(f7781),(f7782),(f7783),(f7784),(f7785),(f7786),(f7787),(f7788),(f7789),(f7790),(f7791),(f7792),(f7793),(f7794),(f7795),(f7796),(f7797),(f7798),(f7799),(f7800),(f7801),(f7802),(f7803),(f7804),(f7805),(f7806),(f7807),(f7808),(f7809),(f7810),(f7811),(f7812),(f7813),(f7814),(f7815),(f7816),(f7817),(f7818),(f7819),(f7820),(f7821),(f7822),(f7823),(f7824),(f7825),(f7826),(f7827),(f7828),(f7829),(f7830),(f7831),(f7832),(f7833),(f7834),(f7835),(f7836),(f7837),(f7838),(f7839),(f7840),(f7841),(f7842),(f7843),(f7844),(f7845),(f7846),(f7847),(f7848),(f7849),(f7850),(f7851),(f7852),(f7853),(f7854),(f7855),(f7856),(f7857),(f7858),(f7859),(f7860),(f7861),(f7862),(f7863),(f7864),(f7865),(f7866),(f7867),(f7868),(f7869),(f7870),(f7871),(f7872),(f7873),(f7874),(f7875),(f7876),(f7877),(f7878),(f7879),(f7880),(f7881),(f7882),(f7883),(f7884),(f7885),(f7886),(f7887),(f7888),(f7889),(f7890),(f7891),(f7892),(f7893),(f7894),(f7895),(f7896),(f7897),(f7898),(f7899),(f7900),(f7901),(f7902),(f7903),(f7904),(f7905),(f7906),(f7907),(f7908),(f7909),(f7910),(f7911),(f7912),(f7913),(f7914),(f7915),(f7916),(f7917),(f7918),(f7919),(f7920),(f7921),(f7922),(f7923),(f7924),(f7925),(f7926),(f7927),(f7928),(f7929),(f7930),(f7931),(f7932),(f7933),(f7934),(f7935),(f7936),(f7937),(f7938),(f7939),(f7940),(f7941),(f7942),(f7943),(f7944),(f7945),(f7946),(f7947),(f7948),(f7949),(f7950),(f7951),(f7952),(f7953),(f7954),(f7955),(f7956),(f7957),(f7958),(f7959),(f7960),(f7961),(f7962),(f7963),(f7964),(f7965),(f7966),(f7967),(f7968),(f7969),(f7970),(f7971),(f7972),(f7973),(f7974),(f7975),(f7976),(f7977),(f7978),(f7979),(f7980),(f7981),(f7982),(f7983),(f7984),(f7985),(f7986),(f7987),(f7988),(f7989),(f7990),(f7991),(f7992),(f7993),(f7994),(f7995),(f7996),(f7997),(f7998),(f7999),(f8000),(f8001),(f8002),(f8003),(f8004),(f8005),(f8006),(f8007),(f8008),(f8009),(f8010),(f8011),(f8012),(f8013),(f8014),(f8015),(f8016),(f8017),(f8018),(f8019),(f8020),(f8021),(f8022),(f8023),(f8024),(f8025),(f8026),(f8027),(f8028),(f8029),(f8030),(f8031),(f8032),(f8033),(f8034),(f8035),(f8036),(f8037),(f8038),(f8039),(f8040),(f8041),(f8042),(f8043),(f8044),(f8045),(f8046),(f8047),(f8048),(f8049),(f8050),(f8051),(f8052),(f8053),(f8054),(f8055),(f8056),(f8057),(f8058),(f8059),(f8060),(f8061),(f8062),(f8063),(f8064),(f8065),(f8066),(f8067),(f8068),(f8069),(f8070),(f8071),(f8072),(f8073),(f8074),(f8075),(f8076),(f8077),(f8078),(f8079),(f8080),(f8081),(f8082),(f8083),(f8084),(f8085),(f8086),(f8087),(f8088),(f8089),(f8090),(f8091),(f8092),(f8093),(f8094),(f8095),(f8096),(f8097),(f8098),(f8099),(f8100),(f8101),(f8102),(f8103),(f8104),(f8105),(f8106),(f8107),(f8108),(f8109),(f8110),(f8111),(f8112),(f8113),(f8114),(f8115),(f8116),(f8117),(f8118),(f8119),(f8120),(f8121),(f8122),(f8123),(f8124),(f8125),(f8126),(f8127),(f8128),(f8129),(f8130),(f8131),(f8132),(f8133),(f8134),(f8135),(f8136),(f8137),(f8138),(f8139),(f8140),(f8141),(f8142),(f8143),(f8144),(f8145),(f8146),(f8147),(f8148),(f8149),(f8150),(f8151),(f8152),(f8153),(f8154),(f8155),(f8156),(f8157),(f8158),(f8159),(f8160),(f8161),(f8162),(f8163),(f8164),(f8165),(f8166),(f8167),(f8168),(f8169),(f8170),(f8171),(f8172),(f8173),(f8174),(f8175),(f8176),(f8177),(f8178),(f8179),(f8180),(f8181),(f8182),(f8183),(f8184),(f8185),(f8186),(f8187),(f8188),(f8189),(f8190),(f8191),(f8192),(f8193),(f8194),(f8195),(f8196),(f8197),(f8198),(f8199),(f8200),(f8201),(f8202),(f8203),(f8204),(f8205),(f8206),(f8207),(f8208),(f8209),(f8210),(f8211),(f8212),(f8213),(f8214),(f8215),(f8216),(f8217),(f8218),(f8219),(f8220),(f8221),(f8222),(f8223),(f8224),(f8225),(f8226),(f8227),(f8228),(f8229),(f8230),(f8231),(f8232),(f8233),(f8234),(f8235),(f8236),(f8237),(f8238),(f8239),(f8240),(f8241),(f8242),(f8243),(f8244),(f8245),(f8246),(f8247),(f8248),(f8249),(f8250),(f8251),(f8252),(f8253),(f8254),(f8255),(f8256),(f8257),(f8258),(f8259),(f8260),(f8261),(f8262),(f8263),(f8264),(f8265),(f8266),(f8267),(f8268),(f8269),(f8270),(f8271),(f8272),(f8273),(f8274),(f8275),(f8276),(f8277),(f8278),(f8279),(f8280),(f8281),(f8282),(f8283),(f8284),(f8285),(f8286),(f8287),(f8288),(f8289),(f8290),(f8291),(f8292),(f8293),(f8294),(f8295),(f8296),(f8297),(f8298),(f8299),(f8300),(f8301),(f8302),(f8303),(f8304),(f8305),(f8306),(f8307),(f8308),(f8309),(f8310),(f8311),(f8312),(f8313),(f8314),(f8315),(f8316),(f8317),(f8318),(f8319),(f8320),(f8321),(f8322),(f8323),(f8324),(f8325),(f8326),(f8327),(f8328),(f8329),(f8330),(f8331),(f8332),(f8333),(f8334),(f8335),(f8336),(f8337),(f8338),(f8339),(f8340),(f8341),(f8342),(f8343),(f8344),(f8345),(f8346),(f8347),(f8348),(f8349),(f8350),(f8351),(f8352),(f8353),(f8354),(f8355),(f8356),(f8357),(f8358),(f8359),(f8360),(f8361),(f8362),(f8363),(f8364),(f8365),(f8366),(f8367),(f8368),(f8369),(f8370),(f8371),(f8372),(f8373),(f8374),(f8375),(f8376),(f8377),(f8378),(f8379),(f8380),(f8381),(f8382),(f8383),(f8384),(f8385),(f8386),(f8387),(f8388),(f8389),(f8390),(f8391),(f8392),(f8393),(f8394),(f8395),(f8396),(f8397),(f8398),(f8399),(f8400),(f8401),(f8402),(f8403),(f8404),(f8405),(f8406),(f8407),(f8408),(f8409),(f8410),(f8411),(f8412),(f8413),(f8414),(f8415),(f8416),(f8417),(f8418),(f8419),(f8420),(f8421),(f8422),(f8423),(f8424),(f8425),(f8426),(f8427),(f8428),(f8429),(f8430),(f8431),(f8432),(f8433),(f8434),(f8435),(f8436),(f8437),(f8438),(f8439),(f8440),(f8441),(f8442),(f8443),(f8444),(f8445),(f8446),(f8447),(f8448),(f8449),(f8450),(f8451),(f8452),(f8453),(f8454),(f8455),(f8456),(f8457),(f8458),(f8459),(f8460),(f8461),(f8462),(f8463),(f8464),(f8465),(f8466),(f8467),(f8468),(f8469),(f8470),(f8471),(f8472),(f8473),(f8474),(f8475),(f8476),(f8477),(f8478),(f8479),(f8480),(f8481),(f8482),(f8483),(f8484),(f8485),(f8486),(f8487),(f8488),(f8489),(f8490),(f8491),(f8492),(f8493),(f8494),(f8495),(f8496),(f8497),(f8498),(f8499),(f8500),(f8501),(f8502),(f8503),(f8504),(f8505),(f8506),(f8507),(f8508),(f8509),(f8510),(f8511),(f8512),(f8513),(f8514),(f8515),(f8516),(f8517),(f8518),(f8519),(f8520),(f8521),(f8522),(f8523),(f8524),(f8525),(f8526),(f8527),(f8528),(f8529),(f8530),(f8531),(f8532),(f8533),(f8534),(f8535),(f8536),(f8537),(f8538),(f8539),(f8540),(f8541),(f8542),(f8543),(f8544),(f8545),(f8546),(f8547),(f8548),(f8549),(f8550),(f8551),(f8552),(f8553),(f8554),(f8555),(f8556),(f8557),(f8558),(f8559),(f8560),(f8561),(f8562),(f8563),(f8564),(f8565),(f8566),(f8567),(f8568),(f8569),(f8570),(f8571),(f8572),(f8573),(f8574),(f8575),(f8576),(f8577),(f8578),(f8579),(f8580),(f8581),(f8582),(f8583),(f8584),(f8585),(f8586),(f8587),(f8588),(f8589),(f8590),(f8591),(f8592),(f8593),(f8594),(f8595),(f8596),(f8597),(f8598),(f8599),(f8600),(f8601),(f8602),(f8603),(f8604),(f8605),(f8606),(f8607),(f8608),(f8609),(f8610),(f8611),(f8612),(f8613),(f8614),(f8615),(f8616),(f8617),(f8618),(f8619),(f8620),(f8621),(f8622),(f8623),(f8624),(f8625),(f8626),(f8627),(f8628),(f8629),(f8630),(f8631),(f8632),(f8633),(f8634),(f8635),(f8636),(f8637),(f8638),(f8639),(f8640),(f8641),(f8642),(f8643),(f8644),(f8645),(f8646),(f8647),(f8648),(f8649),(f8650),(f8651),(f8652),(f8653),(f8654),(f8655),(f8656),(f8657),(f8658),(f8659),(f8660),(f8661),(f8662),(f8663),(f8664),(f8665),(f8666),(f8667),(f8668),(f8669),(f8670),(f8671),(f8672),(f8673),(f8674),(f8675),(f8676),(f8677),(f8678),(f8679),(f8680),(f8681),(f8682),(f8683),(f8684),(f8685),(f8686),(f8687),(f8688),(f8689),(f8690),(f8691),(f8692),(f8693),(f8694),(f8695),(f8696),(f8697),(f8698),(f8699),(f8700),(f8701),(f8702),(f8703),(f8704),(f8705),(f8706),(f8707),(f8708),(f8709),(f8710),(f8711),(f8712),(f8713),(f8714),(f8715),(f8716),(f8717),(f8718),(f8719),(f8720),(f8721),(f8722),(f8723),(f8724),(f8725),(f8726),(f8727),(f8728),(f8729),(f8730),(f8731),(f8732),(f8733),(f8734),(f8735),(f8736),(f8737),(f8738),(f8739),(f8740),(f8741),(f8742),(f8743),(f8744),(f8745),(f8746),(f8747),(f8748),(f8749),(f8750),(f8751),(f8752),(f8753),(f8754),(f8755),(f8756),(f8757),(f8758),(f8759),(f8760),(f8761),(f8762),(f8763),(f8764),(f8765),(f8766),(f8767),(f8768),(f8769),(f8770),(f8771),(f8772),(f8773),(f8774),(f8775),(f8776),(f8777),(f8778),(f8779),(f8780),(f8781),(f8782),(f8783),(f8784),(f8785),(f8786),(f8787),(f8788),(f8789),(f8790),(f8791),(f8792),(f8793),(f8794),(f8795),(f8796),(f8797),(f8798),(f8799),(f8800),(f8801),(f8802),(f8803),(f8804),(f8805),(f8806),(f8807),(f8808),(f8809),(f8810),(f8811),(f8812),(f8813),(f8814),(f8815),(f8816),(f8817),(f8818),(f8819),(f8820),(f8821),(f8822),(f8823),(f8824),(f8825),(f8826),(f8827),(f8828),(f8829),(f8830),(f8831),(f8832),(f8833),(f8834),(f8835),(f8836),(f8837),(f8838),(f8839),(f8840),(f8841),(f8842),(f8843),(f8844),(f8845),(f8846),(f8847),(f8848),(f8849),(f8850),(f8851),(f8852),(f8853),(f8854),(f8855),(f8856),(f8857),(f8858),(f8859),(f8860),(f8861),(f8862),(f8863),(f8864),(f8865),(f8866),(f8867),(f8868),(f8869),(f8870),(f8871),(f8872),(f8873),(f8874),(f8875),(f8876),(f8877),(f8878),(f8879),(f8880),(f8881),(f8882),(f8883),(f8884),(f8885),(f8886),(f8887),(f8888),(f8889),(f8890),(f8891),(f8892),(f8893),(f8894),(f8895),(f8896),(f8897),(f8898),(f8899),(f8900),(f8901),(f8902),(f8903),(f8904),(f8905),(f8906),(f8907),(f8908),(f8909),(f8910),(f8911),(f8912),(f8913),(f8914),(f8915),(f8916),(f8917),(f8918),(f8919),(f8920),(f8921),(f8922),(f8923),(f8924),(f8925),(f8926),(f8927),(f8928),(f8929),(f8930),(f8931),(f8932),(f8933),(f8934),(f8935),(f8936),(f8937),(f8938),(f8939),(f8940),(f8941),(f8942),(f8943),(f8944),(f8945),(f8946),(f8947),(f8948),(f8949),(f8950),(f8951),(f8952),(f8953),(f8954),(f8955),(f8956),(f8957),(f8958),(f8959),(f8960),(f8961),(f8962),(f8963),(f8964),(f8965),(f8966),(f8967),(f8968),(f8969),(f8970),(f8971),(f8972),(f8973),(f8974),(f8975),(f8976),(f8977),(f8978),(f8979),(f8980),(f8981),(f8982),(f8983),(f8984),(f8985),(f8986),(f8987),(f8988),(f8989),(f8990),(f8991),(f8992),(f8993),(f8994),(f8995),(f8996),(f8997),(f8998),(f8999),(f9000),(f9001),(f9002),(f9003),(f9004),(f9005),(f9006),(f9007),(f9008),(f9009),(f9010),(f9011),(f9012),(f9013),(f9014),(f9015),(f9016),(f9017),(f9018),(f9019),(f9020),(f9021),(f9022),(f9023),(f9024),(f9025),(f9026),(f9027),(f9028),(f9029),(f9030),(f9031),(f9032),(f9033),(f9034),(f9035),(f9036),(f9037),(f9038),(f9039),(f9040),(f9041),(f9042),(f9043),(f9044),(f9045),(f9046),(f9047),(f9048),(f9049),(f9050),(f9051),(f9052),(f9053),(f9054),(f9055),(f9056),(f9057),(f9058),(f9059),(f9060),(f9061),(f9062),(f9063),(f9064),(f9065),(f9066),(f9067),(f9068),(f9069),(f9070),(f9071),(f9072),(f9073),(f9074),(f9075),(f9076),(f9077),(f9078),(f9079),(f9080),(f9081),(f9082),(f9083),(f9084),(f9085),(f9086),(f9087),(f9088),(f9089),(f9090),(f9091),(f9092),(f9093),(f9094),(f9095),(f9096),(f9097),(f9098),(f9099),(f9100),(f9101),(f9102),(f9103),(f9104),(f9105),(f9106),(f9107),(f9108),(f9109),(f9110),(f9111),(f9112),(f9113),(f9114),(f9115),(f9116),(f9117),(f9118),(f9119),(f9120),(f9121),(f9122),(f9123),(f9124),(f9125),(f9126),(f9127),(f9128),(f9129),(f9130),(f9131),(f9132),(f9133),(f9134),(f9135),(f9136),(f9137),(f9138),(f9139),(f9140),(f9141),(f9142),(f9143),(f9144),(f9145),(f9146),(f9147),(f9148),(f9149),(f9150),(f9151),(f9152),(f9153),(f9154),(f9155),(f9156),(f9157),(f9158),(f9159),(f9160),(f9161),(f9162),(f9163),(f9164),(f9165),(f9166),(f9167),(f9168),(f9169),(f9170),(f9171),(f9172),(f9173),(f9174),(f9175),(f9176),(f9177),(f9178),(f9179),(f9180),(f9181),(f9182),(f9183),(f9184),(f9185),(f9186),(f9187),(f9188),(f9189),(f9190),(f9191),(f9192),(f9193),(f9194),(f9195),(f9196),(f9197),(f9198),(f9199),(f9200),(f9201),(f9202),(f9203),(f9204),(f9205),(f9206),(f9207),(f9208),(f9209),(f9210),(f9211),(f9212),(f9213),(f9214),(f9215),(f9216),(f9217),(f9218),(f9219),(f9220),(f9221),(f9222),(f9223),(f9224),(f9225),(f9226),(f9227),(f9228),(f9229),(f9230),(f9231),(f9232),(f9233),(f9234),(f9235),(f9236),(f9237),(f9238),(f9239),(f9240),(f9241),(f9242),(f9243),(f9244),(f9245),(f9246),(f9247),(f9248),(f9249),(f9250),(f9251),(f9252),(f9253),(f9254),(f9255),(f9256),(f9257),(f9258),(f9259),(f9260),(f9261),(f9262),(f9263),(f9264),(f9265),(f9266),(f9267),(f9268),(f9269),(f9270),(f9271),(f9272),(f9273),(f9274),(f9275),(f9276),(f9277),(f9278),(f9279),(f9280),(f9281),(f9282),(f9283),(f9284),(f9285),(f9286),(f9287),(f9288),(f9289),(f9290),(f9291),(f9292),(f9293),(f9294),(f9295),(f9296),(f9297),(f9298),(f9299),(f9300),(f9301),(f9302),(f9303),(f9304),(f9305),(f9306),(f9307),(f9308),(f9309),(f9310),(f9311),(f9312),(f9313),(f9314),(f9315),(f9316),(f9317),(f9318),(f9319),(f9320),(f9321),(f9322),(f9323),(f9324),(f9325),(f9326),(f9327),(f9328),(f9329),(f9330),(f9331),(f9332),(f9333),(f9334),(f9335),(f9336),(f9337),(f9338),(f9339),(f9340),(f9341),(f9342),(f9343),(f9344),(f9345),(f9346),(f9347),(f9348),(f9349),(f9350),(f9351),(f9352),(f9353),(f9354),(f9355),(f9356),(f9357),(f9358),(f9359),(f9360),(f9361),(f9362),(f9363),(f9364),(f9365),(f9366),(f9367),(f9368),(f9369),(f9370),(f9371),(f9372),(f9373),(f9374),(f9375),(f9376),(f9377),(f9378),(f9379),(f9380),(f9381),(f9382),(f9383),(f9384),(f9385),(f9386),(f9387),(f9388),(f9389),(f9390),(f9391),(f9392),(f9393),(f9394),(f9395),(f9396),(f9397),(f9398),(f9399),(f9400),(f9401),(f9402),(f9403),(f9404),(f9405),(f9406),(f9407),(f9408),(f9409),(f9410),(f9411),(f9412),(f9413),(f9414),(f9415),(f9416),(f9417),(f9418),(f9419),(f9420),(f9421),(f9422),(f9423),(f9424),(f9425),(f9426),(f9427),(f9428),(f9429),(f9430),(f9431),(f9432),(f9433),(f9434),(f9435),(f9436),(f9437),(f9438),(f9439),(f9440),(f9441),(f9442),(f9443),(f9444),(f9445),(f9446),(f9447),(f9448),(f9449),(f9450),(f9451),(f9452),(f9453),(f9454),(f9455),(f9456),(f9457),(f9458),(f9459),(f9460),(f9461),(f9462),(f9463),(f9464),(f9465),(f9466),(f9467),(f9468),(f9469),(f9470),(f9471),(f9472),(f9473),(f9474),(f9475),(f9476),(f9477),(f9478),(f9479),(f9480),(f9481),(f9482),(f9483),(f9484),(f9485),(f9486),(f9487),(f9488),(f9489),(f9490),(f9491),(f9492),(f9493),(f9494),(f9495),(f9496),(f9497),(f9498),(f9499),(f9500),(f9501),(f9502),(f9503),(f9504),(f9505),(f9506),(f9507),(f9508),(f9509),(f9510),(f9511),(f9512),(f9513),(f9514),(f9515),(f9516),(f9517),(f9518),(f9519),(f9520),(f9521),(f9522),(f9523),(f9524),(f9525),(f9526),(f9527),(f9528),(f9529),(f9530),(f9531),(f9532),(f9533),(f9534),(f9535),(f9536),(f9537),(f9538),(f9539),(f9540),(f9541),(f9542),(f9543),(f9544),(f9545),(f9546),(f9547),(f9548),(f9549),(f9550),(f9551),(f9552),(f9553),(f9554),(f9555),(f9556),(f9557),(f9558),(f9559),(f9560),(f9561),(f9562),(f9563),(f9564),(f9565),(f9566),(f9567),(f9568),(f9569),(f9570),(f9571),(f9572),(f9573),(f9574),(f9575),(f9576),(f9577),(f9578),(f9579),(f9580),(f9581),(f9582),(f9583),(f9584),(f9585),(f9586),(f9587),(f9588),(f9589),(f9590),(f9591),(f9592),(f9593),(f9594),(f9595),(f9596),(f9597),(f9598),(f9599),(f9600),(f9601),(f9602),(f9603),(f9604),(f9605),(f9606),(f9607),(f9608),(f9609),(f9610),(f9611),(f9612),(f9613),(f9614),(f9615),(f9616),(f9617),(f9618),(f9619),(f9620),(f9621),(f9622),(f9623),(f9624),(f9625),(f9626),(f9627),(f9628),(f9629),(f9630),(f9631),(f9632),(f9633),(f9634),(f9635),(f9636),(f9637),(f9638),(f9639),(f9640),(f9641),(f9642),(f9643),(f9644),(f9645),(f9646),(f9647),(f9648),(f9649),(f9650),(f9651),(f9652),(f9653),(f9654),(f9655),(f9656),(f9657),(f9658),(f9659),(f9660),(f9661),(f9662),(f9663),(f9664),(f9665),(f9666),(f9667),(f9668),(f9669),(f9670),(f9671),(f9672),(f9673),(f9674),(f9675),(f9676),(f9677),(f9678),(f9679),(f9680),(f9681),(f9682),(f9683),(f9684),(f9685),(f9686),(f9687),(f9688),(f9689),(f9690),(f9691),(f9692),(f9693),(f9694),(f9695),(f9696),(f9697),(f9698),(f9699),(f9700),(f9701),(f9702),(f9703),(f9704),(f9705),(f9706),(f9707),(f9708),(f9709),(f9710),(f9711),(f9712),(f9713),(f9714),(f9715),(f9716),(f9717),(f9718),(f9719),(f9720),(f9721),(f9722),(f9723),(f9724),(f9725),(f9726),(f9727),(f9728),(f9729),(f9730),(f9731),(f9732),(f9733),(f9734),(f9735),(f9736),(f9737),(f9738),(f9739),(f9740),(f9741),(f9742),(f9743),(f9744),(f9745),(f9746),(f9747),(f9748),(f9749),(f9750),(f9751),(f9752),(f9753),(f9754),(f9755),(f9756),(f9757),(f9758),(f9759),(f9760),(f9761),(f9762),(f9763),(f9764),(f9765),(f9766),(f9767),(f9768),(f9769),(f9770),(f9771),(f9772),(f9773),(f9774),(f9775),(f9776),(f9777),(f9778),(f9779),(f9780),(f9781),(f9782),(f9783),(f9784),(f9785),(f9786),(f9787),(f9788),(f9789),(f9790),(f9791),(f9792),(f9793),(f9794),(f9795),(f9796),(f9797),(f9798),(f9799),(f9800),(f9801),(f9802),(f9803),(f9804),(f9805),(f9806),(f9807),(f9808),(f9809),(f9810),(f9811),(f9812),(f9813),(f9814),(f9815),(f9816),(f9817),(f9818),(f9819),(f9820),(f9821),(f9822),(f9823),(f9824),(f9825),(f9826),(f9827),(f9828),(f9829),(f9830),(f9831),(f9832),(f9833),(f9834),(f9835),(f9836),(f9837),(f9838),(f9839),(f9840),(f9841),(f9842),(f9843),(f9844),(f9845),(f9846),(f9847),(f9848),(f9849),(f9850),(f9851),(f9852),(f9853),(f9854),(f9855),(f9856),(f9857),(f9858),(f9859),(f9860),(f9861),(f9862),(f9863),(f9864),(f9865),(f9866),(f9867),(f9868),(f9869),(f9870),(f9871),(f9872),(f9873),(f9874),(f9875),(f9876),(f9877),(f9878),(f9879),(f9880),(f9881),(f9882),(f9883),(f9884),(f9885),(f9886),(f9887),(f9888),(f9889),(f9890),(f9891),(f9892),(f9893),(f9894),(f9895),(f9896),(f9897),(f9898),(f9899),(f9900),(f9901),(f9902),(f9903),(f9904),(f9905),(f9906),(f9907),(f9908),(f9909),(f9910),(f9911),(f9912),(f9913),(f9914),(f9915),(f9916),(f9917),(f9918),(f9919),(f9920),(f9921),(f9922),(f9923),(f9924),(f9925),(f9926),(f9927),(f9928),(f9929),(f9930),(f9931),(f9932),(f9933),(f9934),(f9935),(f9936),(f9937),(f9938),(f9939),(f9940),(f9941),(f9942),(f9943),(f9944),(f9945),(f9946),(f9947),(f9948),(f9949),(f9950),(f9951),(f9952),(f9953),(f9954),(f9955),(f9956),(f9957),(f9958),(f9959),(f9960),(f9961),(f9962),(f9963),(f9964),(f9965),(f9966),(f9967),(f9968),(f9969),(f9970),(f9971),(f9972),(f9973),(f9974),(f9975),(f9976),(f9977),(f9978),(f9979),(f9980),(f9981),(f9982),(f9983),(f9984),(f9985),(f9986),(f9987),(f9988),(f9989),(f9990),(f9991),(f9992),(f9993),(f9994),(f9995),(f9996),(f9997),(f9998)} ] +Dir: 1 [ { (d0),(d1),(d2),(d3),(d4),(d5),(d6),(d7),(d8),(d9),(d10),(d11),(d12),(d13),(d14),(d15),(d16),(d17),(d18),(d19),(d20),(d21),(d22),(d23),(d24),(d25),(d26),(d27),(d28),(d29),(d30),(d31),(d32),(d33),(d34),(d35),(d36),(d37),(d38),(d39),(d40),(d41),(d42),(d43),(d44),(d45),(d46),(d47),(d48),(d49),(d50),(d51),(d52),(d53),(d54),(d55),(d56),(d57),(d58),(d59),(d60),(d61),(d62),(d63),(d64),(d65),(d66),(d67),(d68),(d69),(d70),(d71),(d72),(d73),(d74),(d75),(d76),(d77),(d78),(d79),(d80),(d81),(d82),(d83),(d84),(d85),(d86),(d87),(d88),(d89),(d90),(d91),(d92),(d93),(d94),(d95),(d96),(d97),(d98),(d99),(d100),(d101),(d102),(d103),(d104),(d105),(d106),(d107),(d108),(d109),(d110),(d111),(d112),(d113),(d114),(d115),(d116),(d117),(d118),(d119),(d120),(d121),(d122),(d123),(d124),(d125),(d126),(d127),(d128),(d129),(d130),(d131),(d132),(d133),(d134),(d135),(d136),(d137),(d138),(d139),(d140),(d141),(d142),(d143),(d144),(d145),(d146),(d147),(d148),(d149),(d150),(d151),(d152),(d153),(d154),(d155),(d156),(d157),(d158),(d159),(d160),(d161),(d162),(d163),(d164),(d165),(d166),(d167),(d168),(d169),(d170),(d171),(d172),(d173),(d174),(d175),(d176),(d177),(d178),(d179),(d180),(d181),(d182),(d183),(d184),(d185),(d186),(d187),(d188),(d189),(d190),(d191),(d192),(d193),(d194),(d195),(d196),(d197),(d198),(d199),(d200),(d201),(d202),(d203),(d204),(d205),(d206),(d207),(d208),(d209),(d210),(d211),(d212),(d213),(d214),(d215),(d216),(d217),(d218),(d219),(d220),(d221),(d222),(d223),(d224),(d225),(d226),(d227),(d228),(d229),(d230),(d231),(d232),(d233),(d234),(d235),(d236),(d237),(d238),(d239),(d240),(d241),(d242),(d243),(d244),(d245),(d246),(d247),(d248),(d249),(d250),(d251),(d252),(d253),(d254),(d255),(d256),(d257),(d258),(d259),(d260),(d261),(d262),(d263),(d264),(d265),(d266),(d267),(d268),(d269),(d270),(d271),(d272),(d273),(d274),(d275),(d276),(d277),(d278),(d279),(d280),(d281),(d282),(d283),(d284),(d285),(d286),(d287),(d288),(d289),(d290),(d291),(d292),(d293),(d294),(d295),(d296),(d297),(d298),(d299),(d300),(d301),(d302),(d303),(d304),(d305),(d306),(d307),(d308),(d309),(d310),(d311),(d312),(d313),(d314),(d315),(d316),(d317),(d318),(d319),(d320),(d321),(d322),(d323),(d324),(d325),(d326),(d327),(d328),(d329),(d330),(d331),(d332),(d333),(d334),(d335),(d336),(d337),(d338),(d339),(d340),(d341),(d342),(d343),(d344),(d345),(d346),(d347),(d348),(d349),(d350),(d351),(d352),(d353),(d354),(d355),(d356),(d357),(d358),(d359),(d360),(d361),(d362),(d363),(d364),(d365),(d366),(d367),(d368),(d369),(d370),(d371),(d372),(d373),(d374),(d375),(d376),(d377),(d378),(d379),(d380),(d381),(d382),(d383),(d384),(d385),(d386),(d387),(d388),(d389),(d390),(d391),(d392),(d393),(d394),(d395),(d396),(d397),(d398),(d399),(d400),(d401),(d402),(d403),(d404),(d405),(d406),(d407),(d408),(d409),(d410),(d411),(d412),(d413),(d414),(d415),(d416),(d417),(d418),(d419),(d420),(d421),(d422),(d423),(d424),(d425),(d426),(d427),(d428),(d429),(d430),(d431),(d432),(d433),(d434),(d435),(d436),(d437),(d438),(d439),(d440),(d441),(d442),(d443),(d444),(d445),(d446),(d447),(d448),(d449),(d450),(d451),(d452),(d453),(d454),(d455),(d456),(d457),(d458),(d459),(d460),(d461),(d462),(d463),(d464),(d465),(d466),(d467),(d468),(d469),(d470),(d471),(d472),(d473),(d474),(d475),(d476),(d477),(d478),(d479),(d480),(d481),(d482),(d483),(d484),(d485),(d486),(d487),(d488),(d489),(d490),(d491),(d492),(d493),(d494),(d495),(d496),(d497),(d498),(d499),(d500),(d501),(d502),(d503),(d504),(d505),(d506),(d507),(d508),(d509),(d510),(d511),(d512),(d513),(d514),(d515),(d516),(d517),(d518),(d519),(d520),(d521),(d522),(d523),(d524),(d525),(d526),(d527),(d528),(d529),(d530),(d531),(d532),(d533),(d534),(d535),(d536),(d537),(d538),(d539),(d540),(d541),(d542),(d543),(d544),(d545),(d546),(d547),(d548),(d549),(d550),(d551),(d552),(d553),(d554),(d555),(d556),(d557),(d558),(d559),(d560),(d561),(d562),(d563),(d564),(d565),(d566),(d567),(d568),(d569),(d570),(d571),(d572),(d573),(d574),(d575),(d576),(d577),(d578),(d579),(d580),(d581),(d582),(d583),(d584),(d585),(d586),(d587),(d588),(d589),(d590),(d591),(d592),(d593),(d594),(d595),(d596),(d597),(d598),(d599),(d600),(d601),(d602),(d603),(d604),(d605),(d606),(d607),(d608),(d609),(d610),(d611),(d612),(d613),(d614),(d615),(d616),(d617),(d618),(d619),(d620),(d621),(d622),(d623),(d624),(d625),(d626),(d627),(d628),(d629),(d630),(d631),(d632),(d633),(d634),(d635),(d636),(d637),(d638),(d639),(d640),(d641),(d642),(d643),(d644),(d645),(d646),(d647),(d648),(d649),(d650),(d651),(d652),(d653),(d654),(d655),(d656),(d657),(d658),(d659),(d660),(d661),(d662),(d663),(d664),(d665),(d666),(d667),(d668),(d669),(d670),(d671),(d672),(d673),(d674),(d675),(d676),(d677),(d678),(d679),(d680),(d681),(d682),(d683),(d684),(d685),(d686),(d687),(d688),(d689),(d690),(d691),(d692),(d693),(d694),(d695),(d696),(d697),(d698),(d699),(d700),(d701),(d702),(d703),(d704),(d705),(d706),(d707),(d708),(d709),(d710),(d711),(d712),(d713),(d714),(d715),(d716),(d717),(d718),(d719),(d720),(d721),(d722),(d723),(d724),(d725),(d726),(d727),(d728),(d729),(d730),(d731),(d732),(d733),(d734),(d735),(d736),(d737),(d738),(d739),(d740),(d741),(d742),(d743),(d744),(d745),(d746),(d747),(d748),(d749),(d750),(d751),(d752),(d753),(d754),(d755),(d756),(d757),(d758),(d759),(d760),(d761),(d762),(d763),(d764),(d765),(d766),(d767),(d768),(d769),(d770),(d771),(d772),(d773),(d774),(d775),(d776),(d777),(d778),(d779),(d780),(d781),(d782),(d783),(d784),(d785),(d786),(d787),(d788),(d789),(d790),(d791),(d792),(d793),(d794),(d795),(d796),(d797),(d798),(d799),(d800),(d801),(d802),(d803),(d804),(d805),(d806),(d807),(d808),(d809),(d810),(d811),(d812),(d813),(d814),(d815),(d816),(d817),(d818),(d819),(d820),(d821),(d822),(d823),(d824),(d825),(d826),(d827),(d828),(d829),(d830),(d831),(d832),(d833),(d834),(d835),(d836),(d837),(d838),(d839),(d840),(d841),(d842),(d843),(d844),(d845),(d846),(d847),(d848),(d849),(d850),(d851),(d852),(d853),(d854),(d855),(d856),(d857),(d858),(d859),(d860),(d861),(d862),(d863),(d864),(d865),(d866),(d867),(d868),(d869),(d870),(d871),(d872),(d873),(d874),(d875),(d876),(d877),(d878),(d879),(d880),(d881),(d882),(d883),(d884),(d885),(d886),(d887),(d888),(d889),(d890),(d891),(d892),(d893),(d894),(d895),(d896),(d897),(d898),(d899),(d900),(d901),(d902),(d903),(d904),(d905),(d906),(d907),(d908),(d909),(d910),(d911),(d912),(d913),(d914),(d915),(d916),(d917),(d918),(d919),(d920),(d921),(d922),(d923),(d924),(d925),(d926),(d927),(d928),(d929),(d930),(d931),(d932),(d933),(d934),(d935),(d936),(d937),(d938),(d939),(d940),(d941),(d942),(d943),(d944),(d945),(d946),(d947),(d948),(d949),(d950),(d951),(d952),(d953),(d954),(d955),(d956),(d957),(d958),(d959),(d960),(d961),(d962),(d963),(d964),(d965),(d966),(d967),(d968),(d969),(d970),(d971),(d972),(d973),(d974),(d975),(d976),(d977),(d978),(d979),(d980),(d981),(d982),(d983),(d984),(d985),(d986),(d987),(d988),(d989),(d990),(d991),(d992),(d993),(d994),(d995),(d996),(d997),(d998),(d999),(d1000),(d1001),(d1002),(d1003),(d1004),(d1005),(d1006),(d1007),(d1008),(d1009),(d1010),(d1011),(d1012),(d1013),(d1014),(d1015),(d1016),(d1017),(d1018),(d1019),(d1020),(d1021),(d1022),(d1023),(d1024),(d1025),(d1026),(d1027),(d1028),(d1029),(d1030),(d1031),(d1032),(d1033),(d1034),(d1035),(d1036),(d1037),(d1038),(d1039),(d1040),(d1041),(d1042),(d1043),(d1044),(d1045),(d1046),(d1047),(d1048),(d1049),(d1050),(d1051),(d1052),(d1053),(d1054),(d1055),(d1056),(d1057),(d1058),(d1059),(d1060),(d1061),(d1062),(d1063),(d1064),(d1065),(d1066),(d1067),(d1068),(d1069),(d1070),(d1071),(d1072),(d1073),(d1074),(d1075),(d1076),(d1077),(d1078),(d1079),(d1080),(d1081),(d1082),(d1083),(d1084),(d1085),(d1086),(d1087),(d1088),(d1089),(d1090),(d1091),(d1092),(d1093),(d1094),(d1095),(d1096),(d1097),(d1098),(d1099),(d1100),(d1101),(d1102),(d1103),(d1104),(d1105),(d1106),(d1107),(d1108),(d1109),(d1110),(d1111),(d1112),(d1113),(d1114),(d1115),(d1116),(d1117),(d1118),(d1119),(d1120),(d1121),(d1122),(d1123),(d1124),(d1125),(d1126),(d1127),(d1128),(d1129),(d1130),(d1131),(d1132),(d1133),(d1134),(d1135),(d1136),(d1137),(d1138),(d1139),(d1140),(d1141),(d1142),(d1143),(d1144),(d1145),(d1146),(d1147),(d1148),(d1149),(d1150),(d1151),(d1152),(d1153),(d1154),(d1155),(d1156),(d1157),(d1158),(d1159),(d1160),(d1161),(d1162),(d1163),(d1164),(d1165),(d1166),(d1167),(d1168),(d1169),(d1170),(d1171),(d1172),(d1173),(d1174),(d1175),(d1176),(d1177),(d1178),(d1179),(d1180),(d1181),(d1182),(d1183),(d1184),(d1185),(d1186),(d1187),(d1188),(d1189),(d1190),(d1191),(d1192),(d1193),(d1194),(d1195),(d1196),(d1197),(d1198),(d1199),(d1200),(d1201),(d1202),(d1203),(d1204),(d1205),(d1206),(d1207),(d1208),(d1209),(d1210),(d1211),(d1212),(d1213),(d1214),(d1215),(d1216),(d1217),(d1218),(d1219),(d1220),(d1221),(d1222),(d1223),(d1224),(d1225),(d1226),(d1227),(d1228),(d1229),(d1230),(d1231),(d1232),(d1233),(d1234),(d1235),(d1236),(d1237),(d1238),(d1239),(d1240),(d1241),(d1242),(d1243),(d1244),(d1245),(d1246),(d1247),(d1248),(d1249),(d1250),(d1251),(d1252),(d1253),(d1254),(d1255),(d1256),(d1257),(d1258),(d1259),(d1260),(d1261),(d1262),(d1263),(d1264),(d1265),(d1266),(d1267),(d1268),(d1269),(d1270),(d1271),(d1272),(d1273),(d1274),(d1275),(d1276),(d1277),(d1278),(d1279),(d1280),(d1281),(d1282),(d1283),(d1284),(d1285),(d1286),(d1287),(d1288),(d1289),(d1290),(d1291),(d1292),(d1293),(d1294),(d1295),(d1296),(d1297),(d1298),(d1299),(d1300),(d1301),(d1302),(d1303),(d1304),(d1305),(d1306),(d1307),(d1308),(d1309),(d1310),(d1311),(d1312),(d1313),(d1314),(d1315),(d1316),(d1317),(d1318),(d1319),(d1320),(d1321),(d1322),(d1323),(d1324),(d1325),(d1326),(d1327),(d1328),(d1329),(d1330),(d1331),(d1332),(d1333),(d1334),(d1335),(d1336),(d1337),(d1338),(d1339),(d1340),(d1341),(d1342),(d1343),(d1344),(d1345),(d1346),(d1347),(d1348),(d1349),(d1350),(d1351),(d1352),(d1353),(d1354),(d1355),(d1356),(d1357),(d1358),(d1359),(d1360),(d1361),(d1362),(d1363),(d1364),(d1365),(d1366),(d1367),(d1368),(d1369),(d1370),(d1371),(d1372),(d1373),(d1374),(d1375),(d1376),(d1377),(d1378),(d1379),(d1380),(d1381),(d1382),(d1383),(d1384),(d1385),(d1386),(d1387),(d1388),(d1389),(d1390),(d1391),(d1392),(d1393),(d1394),(d1395),(d1396),(d1397),(d1398),(d1399),(d1400),(d1401),(d1402),(d1403),(d1404),(d1405),(d1406),(d1407),(d1408),(d1409),(d1410),(d1411),(d1412),(d1413),(d1414),(d1415),(d1416),(d1417),(d1418),(d1419),(d1420),(d1421),(d1422),(d1423),(d1424),(d1425),(d1426),(d1427),(d1428),(d1429),(d1430),(d1431),(d1432),(d1433),(d1434),(d1435),(d1436),(d1437),(d1438),(d1439),(d1440),(d1441),(d1442),(d1443),(d1444),(d1445),(d1446),(d1447),(d1448),(d1449),(d1450),(d1451),(d1452),(d1453),(d1454),(d1455),(d1456),(d1457),(d1458),(d1459),(d1460),(d1461),(d1462),(d1463),(d1464),(d1465),(d1466),(d1467),(d1468),(d1469),(d1470),(d1471),(d1472),(d1473),(d1474),(d1475),(d1476),(d1477),(d1478),(d1479),(d1480),(d1481),(d1482),(d1483),(d1484),(d1485),(d1486),(d1487),(d1488),(d1489),(d1490),(d1491),(d1492),(d1493),(d1494),(d1495),(d1496),(d1497),(d1498),(d1499),(d1500),(d1501),(d1502),(d1503),(d1504),(d1505),(d1506),(d1507),(d1508),(d1509),(d1510),(d1511),(d1512),(d1513),(d1514),(d1515),(d1516),(d1517),(d1518),(d1519),(d1520),(d1521),(d1522),(d1523),(d1524),(d1525),(d1526),(d1527),(d1528),(d1529),(d1530),(d1531),(d1532),(d1533),(d1534),(d1535),(d1536),(d1537),(d1538),(d1539),(d1540),(d1541),(d1542),(d1543),(d1544),(d1545),(d1546),(d1547),(d1548),(d1549),(d1550),(d1551),(d1552),(d1553),(d1554),(d1555),(d1556),(d1557),(d1558),(d1559),(d1560),(d1561),(d1562),(d1563),(d1564),(d1565),(d1566),(d1567),(d1568),(d1569),(d1570),(d1571),(d1572),(d1573),(d1574),(d1575),(d1576),(d1577),(d1578),(d1579),(d1580),(d1581),(d1582),(d1583),(d1584),(d1585),(d1586),(d1587),(d1588),(d1589),(d1590),(d1591),(d1592),(d1593),(d1594),(d1595),(d1596),(d1597),(d1598),(d1599),(d1600),(d1601),(d1602),(d1603),(d1604),(d1605),(d1606),(d1607),(d1608),(d1609),(d1610),(d1611),(d1612),(d1613),(d1614),(d1615),(d1616),(d1617),(d1618),(d1619),(d1620),(d1621),(d1622),(d1623),(d1624),(d1625),(d1626),(d1627),(d1628),(d1629),(d1630),(d1631),(d1632),(d1633),(d1634),(d1635),(d1636),(d1637),(d1638),(d1639),(d1640),(d1641),(d1642),(d1643),(d1644),(d1645),(d1646),(d1647),(d1648),(d1649),(d1650),(d1651),(d1652),(d1653),(d1654),(d1655),(d1656),(d1657),(d1658),(d1659),(d1660),(d1661),(d1662),(d1663),(d1664),(d1665),(d1666),(d1667),(d1668),(d1669),(d1670),(d1671),(d1672),(d1673),(d1674),(d1675),(d1676),(d1677),(d1678),(d1679),(d1680),(d1681),(d1682),(d1683),(d1684),(d1685),(d1686),(d1687),(d1688),(d1689),(d1690),(d1691),(d1692),(d1693),(d1694),(d1695),(d1696),(d1697),(d1698),(d1699),(d1700),(d1701),(d1702),(d1703),(d1704),(d1705),(d1706),(d1707),(d1708),(d1709),(d1710),(d1711),(d1712),(d1713),(d1714),(d1715),(d1716),(d1717),(d1718),(d1719),(d1720),(d1721),(d1722),(d1723),(d1724),(d1725),(d1726),(d1727),(d1728),(d1729),(d1730),(d1731),(d1732),(d1733),(d1734),(d1735),(d1736),(d1737),(d1738),(d1739),(d1740),(d1741),(d1742),(d1743),(d1744),(d1745),(d1746),(d1747),(d1748),(d1749),(d1750),(d1751),(d1752),(d1753),(d1754),(d1755),(d1756),(d1757),(d1758),(d1759),(d1760),(d1761),(d1762),(d1763),(d1764),(d1765),(d1766),(d1767),(d1768),(d1769),(d1770),(d1771),(d1772),(d1773),(d1774),(d1775),(d1776),(d1777),(d1778),(d1779),(d1780),(d1781),(d1782),(d1783),(d1784),(d1785),(d1786),(d1787),(d1788),(d1789),(d1790),(d1791),(d1792),(d1793),(d1794),(d1795),(d1796),(d1797),(d1798),(d1799),(d1800),(d1801),(d1802),(d1803),(d1804),(d1805),(d1806),(d1807),(d1808),(d1809),(d1810),(d1811),(d1812),(d1813),(d1814),(d1815),(d1816),(d1817),(d1818),(d1819),(d1820),(d1821),(d1822),(d1823),(d1824),(d1825),(d1826),(d1827),(d1828),(d1829),(d1830),(d1831),(d1832),(d1833),(d1834),(d1835),(d1836),(d1837),(d1838),(d1839),(d1840),(d1841),(d1842),(d1843),(d1844),(d1845),(d1846),(d1847),(d1848),(d1849),(d1850),(d1851),(d1852),(d1853),(d1854),(d1855),(d1856),(d1857),(d1858),(d1859),(d1860),(d1861),(d1862),(d1863),(d1864),(d1865),(d1866),(d1867),(d1868),(d1869),(d1870),(d1871),(d1872),(d1873),(d1874),(d1875),(d1876),(d1877),(d1878),(d1879),(d1880),(d1881),(d1882),(d1883),(d1884),(d1885),(d1886),(d1887),(d1888),(d1889),(d1890),(d1891),(d1892),(d1893),(d1894),(d1895),(d1896),(d1897),(d1898),(d1899),(d1900),(d1901),(d1902),(d1903),(d1904),(d1905),(d1906),(d1907),(d1908),(d1909),(d1910),(d1911),(d1912),(d1913),(d1914),(d1915),(d1916),(d1917),(d1918),(d1919),(d1920),(d1921),(d1922),(d1923),(d1924),(d1925),(d1926),(d1927),(d1928),(d1929),(d1930),(d1931),(d1932),(d1933),(d1934),(d1935),(d1936),(d1937),(d1938),(d1939),(d1940),(d1941),(d1942),(d1943),(d1944),(d1945),(d1946),(d1947),(d1948),(d1949),(d1950),(d1951),(d1952),(d1953),(d1954),(d1955),(d1956),(d1957),(d1958),(d1959),(d1960),(d1961),(d1962),(d1963),(d1964),(d1965),(d1966),(d1967),(d1968),(d1969),(d1970),(d1971),(d1972),(d1973),(d1974),(d1975),(d1976),(d1977),(d1978),(d1979),(d1980),(d1981),(d1982),(d1983),(d1984),(d1985),(d1986),(d1987),(d1988),(d1989),(d1990),(d1991),(d1992),(d1993),(d1994),(d1995),(d1996),(d1997),(d1998),(d1999),(d2000),(d2001),(d2002),(d2003),(d2004),(d2005),(d2006),(d2007),(d2008),(d2009),(d2010),(d2011),(d2012),(d2013),(d2014),(d2015),(d2016),(d2017),(d2018),(d2019),(d2020),(d2021),(d2022),(d2023),(d2024),(d2025),(d2026),(d2027),(d2028),(d2029),(d2030),(d2031),(d2032),(d2033),(d2034),(d2035),(d2036),(d2037),(d2038),(d2039),(d2040),(d2041),(d2042),(d2043),(d2044),(d2045),(d2046),(d2047),(d2048),(d2049),(d2050),(d2051),(d2052),(d2053),(d2054),(d2055),(d2056),(d2057),(d2058),(d2059),(d2060),(d2061),(d2062),(d2063),(d2064),(d2065),(d2066),(d2067),(d2068),(d2069),(d2070),(d2071),(d2072),(d2073),(d2074),(d2075),(d2076),(d2077),(d2078),(d2079),(d2080),(d2081),(d2082),(d2083),(d2084),(d2085),(d2086),(d2087),(d2088),(d2089),(d2090),(d2091),(d2092),(d2093),(d2094),(d2095),(d2096),(d2097),(d2098),(d2099),(d2100),(d2101),(d2102),(d2103),(d2104),(d2105),(d2106),(d2107),(d2108),(d2109),(d2110),(d2111),(d2112),(d2113),(d2114),(d2115),(d2116),(d2117),(d2118),(d2119),(d2120),(d2121),(d2122),(d2123),(d2124),(d2125),(d2126),(d2127),(d2128),(d2129),(d2130),(d2131),(d2132),(d2133),(d2134),(d2135),(d2136),(d2137),(d2138),(d2139),(d2140),(d2141),(d2142),(d2143),(d2144),(d2145),(d2146),(d2147),(d2148),(d2149),(d2150),(d2151),(d2152),(d2153),(d2154),(d2155),(d2156),(d2157),(d2158),(d2159),(d2160),(d2161),(d2162),(d2163),(d2164),(d2165),(d2166),(d2167),(d2168),(d2169),(d2170),(d2171),(d2172),(d2173),(d2174),(d2175),(d2176),(d2177),(d2178),(d2179),(d2180),(d2181),(d2182),(d2183),(d2184),(d2185),(d2186),(d2187),(d2188),(d2189),(d2190),(d2191),(d2192),(d2193),(d2194),(d2195),(d2196),(d2197),(d2198),(d2199),(d2200),(d2201),(d2202),(d2203),(d2204),(d2205),(d2206),(d2207),(d2208),(d2209),(d2210),(d2211),(d2212),(d2213),(d2214),(d2215),(d2216),(d2217),(d2218),(d2219),(d2220),(d2221),(d2222),(d2223),(d2224),(d2225),(d2226),(d2227),(d2228),(d2229),(d2230),(d2231),(d2232),(d2233),(d2234),(d2235),(d2236),(d2237),(d2238),(d2239),(d2240),(d2241),(d2242),(d2243),(d2244),(d2245),(d2246),(d2247),(d2248),(d2249),(d2250),(d2251),(d2252),(d2253),(d2254),(d2255),(d2256),(d2257),(d2258),(d2259),(d2260),(d2261),(d2262),(d2263),(d2264),(d2265),(d2266),(d2267),(d2268),(d2269),(d2270),(d2271),(d2272),(d2273),(d2274),(d2275),(d2276),(d2277),(d2278),(d2279),(d2280),(d2281),(d2282),(d2283),(d2284),(d2285),(d2286),(d2287),(d2288),(d2289),(d2290),(d2291),(d2292),(d2293),(d2294),(d2295),(d2296),(d2297),(d2298),(d2299),(d2300),(d2301),(d2302),(d2303),(d2304),(d2305),(d2306),(d2307),(d2308),(d2309),(d2310),(d2311),(d2312),(d2313),(d2314),(d2315),(d2316),(d2317),(d2318),(d2319),(d2320),(d2321),(d2322),(d2323),(d2324),(d2325),(d2326),(d2327),(d2328),(d2329),(d2330),(d2331),(d2332),(d2333),(d2334),(d2335),(d2336),(d2337),(d2338),(d2339),(d2340),(d2341),(d2342),(d2343),(d2344),(d2345),(d2346),(d2347),(d2348),(d2349),(d2350),(d2351),(d2352),(d2353),(d2354),(d2355),(d2356),(d2357),(d2358),(d2359),(d2360),(d2361),(d2362),(d2363),(d2364),(d2365),(d2366),(d2367),(d2368),(d2369),(d2370),(d2371),(d2372),(d2373),(d2374),(d2375),(d2376),(d2377),(d2378),(d2379),(d2380),(d2381),(d2382),(d2383),(d2384),(d2385),(d2386),(d2387),(d2388),(d2389),(d2390),(d2391),(d2392),(d2393),(d2394),(d2395),(d2396),(d2397),(d2398),(d2399),(d2400),(d2401),(d2402),(d2403),(d2404),(d2405),(d2406),(d2407),(d2408),(d2409),(d2410),(d2411),(d2412),(d2413),(d2414),(d2415),(d2416),(d2417),(d2418),(d2419),(d2420),(d2421),(d2422),(d2423),(d2424),(d2425),(d2426),(d2427),(d2428),(d2429),(d2430),(d2431),(d2432),(d2433),(d2434),(d2435),(d2436),(d2437),(d2438),(d2439),(d2440),(d2441),(d2442),(d2443),(d2444),(d2445),(d2446),(d2447),(d2448),(d2449),(d2450),(d2451),(d2452),(d2453),(d2454),(d2455),(d2456),(d2457),(d2458),(d2459),(d2460),(d2461),(d2462),(d2463),(d2464),(d2465),(d2466),(d2467),(d2468),(d2469),(d2470),(d2471),(d2472),(d2473),(d2474),(d2475),(d2476),(d2477),(d2478),(d2479),(d2480),(d2481),(d2482),(d2483),(d2484),(d2485),(d2486),(d2487),(d2488),(d2489),(d2490),(d2491),(d2492),(d2493),(d2494),(d2495),(d2496),(d2497),(d2498),(d2499),(d2500),(d2501),(d2502),(d2503),(d2504),(d2505),(d2506),(d2507),(d2508),(d2509),(d2510),(d2511),(d2512),(d2513),(d2514),(d2515),(d2516),(d2517),(d2518),(d2519),(d2520),(d2521),(d2522),(d2523),(d2524),(d2525),(d2526),(d2527),(d2528),(d2529),(d2530),(d2531),(d2532),(d2533),(d2534),(d2535),(d2536),(d2537),(d2538),(d2539),(d2540),(d2541),(d2542),(d2543),(d2544),(d2545),(d2546),(d2547),(d2548),(d2549),(d2550),(d2551),(d2552),(d2553),(d2554),(d2555),(d2556),(d2557),(d2558),(d2559),(d2560),(d2561),(d2562),(d2563),(d2564),(d2565),(d2566),(d2567),(d2568),(d2569),(d2570),(d2571),(d2572),(d2573),(d2574),(d2575),(d2576),(d2577),(d2578),(d2579),(d2580),(d2581),(d2582),(d2583),(d2584),(d2585),(d2586),(d2587),(d2588),(d2589),(d2590),(d2591),(d2592),(d2593),(d2594),(d2595),(d2596),(d2597),(d2598),(d2599),(d2600),(d2601),(d2602),(d2603),(d2604),(d2605),(d2606),(d2607),(d2608),(d2609),(d2610),(d2611),(d2612),(d2613),(d2614),(d2615),(d2616),(d2617),(d2618),(d2619),(d2620),(d2621),(d2622),(d2623),(d2624),(d2625),(d2626),(d2627),(d2628),(d2629),(d2630),(d2631),(d2632),(d2633),(d2634),(d2635),(d2636),(d2637),(d2638),(d2639),(d2640),(d2641),(d2642),(d2643),(d2644),(d2645),(d2646),(d2647),(d2648),(d2649),(d2650),(d2651),(d2652),(d2653),(d2654),(d2655),(d2656),(d2657),(d2658),(d2659),(d2660),(d2661),(d2662),(d2663),(d2664),(d2665),(d2666),(d2667),(d2668),(d2669),(d2670),(d2671),(d2672),(d2673),(d2674),(d2675),(d2676),(d2677),(d2678),(d2679),(d2680),(d2681),(d2682),(d2683),(d2684),(d2685),(d2686),(d2687),(d2688),(d2689),(d2690),(d2691),(d2692),(d2693),(d2694),(d2695),(d2696),(d2697),(d2698),(d2699),(d2700),(d2701),(d2702),(d2703),(d2704),(d2705),(d2706),(d2707),(d2708),(d2709),(d2710),(d2711),(d2712),(d2713),(d2714),(d2715),(d2716),(d2717),(d2718),(d2719),(d2720),(d2721),(d2722),(d2723),(d2724),(d2725),(d2726),(d2727),(d2728),(d2729),(d2730),(d2731),(d2732),(d2733),(d2734),(d2735),(d2736),(d2737),(d2738),(d2739),(d2740),(d2741),(d2742),(d2743),(d2744),(d2745),(d2746),(d2747),(d2748),(d2749),(d2750),(d2751),(d2752),(d2753),(d2754),(d2755),(d2756),(d2757),(d2758),(d2759),(d2760),(d2761),(d2762),(d2763),(d2764),(d2765),(d2766),(d2767),(d2768),(d2769),(d2770),(d2771),(d2772),(d2773),(d2774),(d2775),(d2776),(d2777),(d2778),(d2779),(d2780),(d2781),(d2782),(d2783),(d2784),(d2785),(d2786),(d2787),(d2788),(d2789),(d2790),(d2791),(d2792),(d2793),(d2794),(d2795),(d2796),(d2797),(d2798),(d2799),(d2800),(d2801),(d2802),(d2803),(d2804),(d2805),(d2806),(d2807),(d2808),(d2809),(d2810),(d2811),(d2812),(d2813),(d2814),(d2815),(d2816),(d2817),(d2818),(d2819),(d2820),(d2821),(d2822),(d2823),(d2824),(d2825),(d2826),(d2827),(d2828),(d2829),(d2830),(d2831),(d2832),(d2833),(d2834),(d2835),(d2836),(d2837),(d2838),(d2839),(d2840),(d2841),(d2842),(d2843),(d2844),(d2845),(d2846),(d2847),(d2848),(d2849),(d2850),(d2851),(d2852),(d2853),(d2854),(d2855),(d2856),(d2857),(d2858),(d2859),(d2860),(d2861),(d2862),(d2863),(d2864),(d2865),(d2866),(d2867),(d2868),(d2869),(d2870),(d2871),(d2872),(d2873),(d2874),(d2875),(d2876),(d2877),(d2878),(d2879),(d2880),(d2881),(d2882),(d2883),(d2884),(d2885),(d2886),(d2887),(d2888),(d2889),(d2890),(d2891),(d2892),(d2893),(d2894),(d2895),(d2896),(d2897),(d2898),(d2899),(d2900),(d2901),(d2902),(d2903),(d2904),(d2905),(d2906),(d2907),(d2908),(d2909),(d2910),(d2911),(d2912),(d2913),(d2914),(d2915),(d2916),(d2917),(d2918),(d2919),(d2920),(d2921),(d2922),(d2923),(d2924),(d2925),(d2926),(d2927),(d2928),(d2929),(d2930),(d2931),(d2932),(d2933),(d2934),(d2935),(d2936),(d2937),(d2938),(d2939),(d2940),(d2941),(d2942),(d2943),(d2944),(d2945),(d2946),(d2947),(d2948),(d2949),(d2950),(d2951),(d2952),(d2953),(d2954),(d2955),(d2956),(d2957),(d2958),(d2959),(d2960),(d2961),(d2962),(d2963),(d2964),(d2965),(d2966),(d2967),(d2968),(d2969),(d2970),(d2971),(d2972),(d2973),(d2974),(d2975),(d2976),(d2977),(d2978),(d2979),(d2980),(d2981),(d2982),(d2983),(d2984),(d2985),(d2986),(d2987),(d2988),(d2989),(d2990),(d2991),(d2992),(d2993),(d2994),(d2995),(d2996),(d2997),(d2998),(d2999),(d3000),(d3001),(d3002),(d3003),(d3004),(d3005),(d3006),(d3007),(d3008),(d3009),(d3010),(d3011),(d3012),(d3013),(d3014),(d3015),(d3016),(d3017),(d3018),(d3019),(d3020),(d3021),(d3022),(d3023),(d3024),(d3025),(d3026),(d3027),(d3028),(d3029),(d3030),(d3031),(d3032),(d3033),(d3034),(d3035),(d3036),(d3037),(d3038),(d3039),(d3040),(d3041),(d3042),(d3043),(d3044),(d3045),(d3046),(d3047),(d3048),(d3049),(d3050),(d3051),(d3052),(d3053),(d3054),(d3055),(d3056),(d3057),(d3058),(d3059),(d3060),(d3061),(d3062),(d3063),(d3064),(d3065),(d3066),(d3067),(d3068),(d3069),(d3070),(d3071),(d3072),(d3073),(d3074),(d3075),(d3076),(d3077),(d3078),(d3079),(d3080),(d3081),(d3082),(d3083),(d3084),(d3085),(d3086),(d3087),(d3088),(d3089),(d3090),(d3091),(d3092),(d3093),(d3094),(d3095),(d3096),(d3097),(d3098),(d3099),(d3100),(d3101),(d3102),(d3103),(d3104),(d3105),(d3106),(d3107),(d3108),(d3109),(d3110),(d3111),(d3112),(d3113),(d3114),(d3115),(d3116),(d3117),(d3118),(d3119),(d3120),(d3121),(d3122),(d3123),(d3124),(d3125),(d3126),(d3127),(d3128),(d3129),(d3130),(d3131),(d3132),(d3133),(d3134),(d3135),(d3136),(d3137),(d3138),(d3139),(d3140),(d3141),(d3142),(d3143),(d3144),(d3145),(d3146),(d3147),(d3148),(d3149),(d3150),(d3151),(d3152),(d3153),(d3154),(d3155),(d3156),(d3157),(d3158),(d3159),(d3160),(d3161),(d3162),(d3163),(d3164),(d3165),(d3166),(d3167),(d3168),(d3169),(d3170),(d3171),(d3172),(d3173),(d3174),(d3175),(d3176),(d3177),(d3178),(d3179),(d3180),(d3181),(d3182),(d3183),(d3184),(d3185),(d3186),(d3187),(d3188),(d3189),(d3190),(d3191),(d3192),(d3193),(d3194),(d3195),(d3196),(d3197),(d3198),(d3199),(d3200),(d3201),(d3202),(d3203),(d3204),(d3205),(d3206),(d3207),(d3208),(d3209),(d3210),(d3211),(d3212),(d3213),(d3214),(d3215),(d3216),(d3217),(d3218),(d3219),(d3220),(d3221),(d3222),(d3223),(d3224),(d3225),(d3226),(d3227),(d3228),(d3229),(d3230),(d3231),(d3232),(d3233),(d3234),(d3235),(d3236),(d3237),(d3238),(d3239),(d3240),(d3241),(d3242),(d3243),(d3244),(d3245),(d3246),(d3247),(d3248),(d3249),(d3250),(d3251),(d3252),(d3253),(d3254),(d3255),(d3256),(d3257),(d3258),(d3259),(d3260),(d3261),(d3262),(d3263),(d3264),(d3265),(d3266),(d3267),(d3268),(d3269),(d3270),(d3271),(d3272),(d3273),(d3274),(d3275),(d3276),(d3277),(d3278),(d3279),(d3280),(d3281),(d3282),(d3283),(d3284),(d3285),(d3286),(d3287),(d3288),(d3289),(d3290),(d3291),(d3292),(d3293),(d3294),(d3295),(d3296),(d3297),(d3298),(d3299),(d3300),(d3301),(d3302),(d3303),(d3304),(d3305),(d3306),(d3307),(d3308),(d3309),(d3310),(d3311),(d3312),(d3313),(d3314),(d3315),(d3316),(d3317),(d3318),(d3319),(d3320),(d3321),(d3322),(d3323),(d3324),(d3325),(d3326),(d3327),(d3328),(d3329),(d3330),(d3331),(d3332),(d3333),(d3334),(d3335),(d3336),(d3337),(d3338),(d3339),(d3340),(d3341),(d3342),(d3343),(d3344),(d3345),(d3346),(d3347),(d3348),(d3349),(d3350),(d3351),(d3352),(d3353),(d3354),(d3355),(d3356),(d3357),(d3358),(d3359),(d3360),(d3361),(d3362),(d3363),(d3364),(d3365),(d3366),(d3367),(d3368),(d3369),(d3370),(d3371),(d3372),(d3373),(d3374),(d3375),(d3376),(d3377),(d3378),(d3379),(d3380),(d3381),(d3382),(d3383),(d3384),(d3385),(d3386),(d3387),(d3388),(d3389),(d3390),(d3391),(d3392),(d3393),(d3394),(d3395),(d3396),(d3397),(d3398),(d3399),(d3400),(d3401),(d3402),(d3403),(d3404),(d3405),(d3406),(d3407),(d3408),(d3409),(d3410),(d3411),(d3412),(d3413),(d3414),(d3415),(d3416),(d3417),(d3418),(d3419),(d3420),(d3421),(d3422),(d3423),(d3424),(d3425),(d3426),(d3427),(d3428),(d3429),(d3430),(d3431),(d3432),(d3433),(d3434),(d3435),(d3436),(d3437),(d3438),(d3439),(d3440),(d3441),(d3442),(d3443),(d3444),(d3445),(d3446),(d3447),(d3448),(d3449),(d3450),(d3451),(d3452),(d3453),(d3454),(d3455),(d3456),(d3457),(d3458),(d3459),(d3460),(d3461),(d3462),(d3463),(d3464),(d3465),(d3466),(d3467),(d3468),(d3469),(d3470),(d3471),(d3472),(d3473),(d3474),(d3475),(d3476),(d3477),(d3478),(d3479),(d3480),(d3481),(d3482),(d3483),(d3484),(d3485),(d3486),(d3487),(d3488),(d3489),(d3490),(d3491),(d3492),(d3493),(d3494),(d3495),(d3496),(d3497),(d3498),(d3499),(d3500),(d3501),(d3502),(d3503),(d3504),(d3505),(d3506),(d3507),(d3508),(d3509),(d3510),(d3511),(d3512),(d3513),(d3514),(d3515),(d3516),(d3517),(d3518),(d3519),(d3520),(d3521),(d3522),(d3523),(d3524),(d3525),(d3526),(d3527),(d3528),(d3529),(d3530),(d3531),(d3532),(d3533),(d3534),(d3535),(d3536),(d3537),(d3538),(d3539),(d3540),(d3541),(d3542),(d3543),(d3544),(d3545),(d3546),(d3547),(d3548),(d3549),(d3550),(d3551),(d3552),(d3553),(d3554),(d3555),(d3556),(d3557),(d3558),(d3559),(d3560),(d3561),(d3562),(d3563),(d3564),(d3565),(d3566),(d3567),(d3568),(d3569),(d3570),(d3571),(d3572),(d3573),(d3574),(d3575),(d3576),(d3577),(d3578),(d3579),(d3580),(d3581),(d3582),(d3583),(d3584),(d3585),(d3586),(d3587),(d3588),(d3589),(d3590),(d3591),(d3592),(d3593),(d3594),(d3595),(d3596),(d3597),(d3598),(d3599),(d3600),(d3601),(d3602),(d3603),(d3604),(d3605),(d3606),(d3607),(d3608),(d3609),(d3610),(d3611),(d3612),(d3613),(d3614),(d3615),(d3616),(d3617),(d3618),(d3619),(d3620),(d3621),(d3622),(d3623),(d3624),(d3625),(d3626),(d3627),(d3628),(d3629),(d3630),(d3631),(d3632),(d3633),(d3634),(d3635),(d3636),(d3637),(d3638),(d3639),(d3640),(d3641),(d3642),(d3643),(d3644),(d3645),(d3646),(d3647),(d3648),(d3649),(d3650),(d3651),(d3652),(d3653),(d3654),(d3655),(d3656),(d3657),(d3658),(d3659),(d3660),(d3661),(d3662),(d3663),(d3664),(d3665),(d3666),(d3667),(d3668),(d3669),(d3670),(d3671),(d3672),(d3673),(d3674),(d3675),(d3676),(d3677),(d3678),(d3679),(d3680),(d3681),(d3682),(d3683),(d3684),(d3685),(d3686),(d3687),(d3688),(d3689),(d3690),(d3691),(d3692),(d3693),(d3694),(d3695),(d3696),(d3697),(d3698),(d3699),(d3700),(d3701),(d3702),(d3703),(d3704),(d3705),(d3706),(d3707),(d3708),(d3709),(d3710),(d3711),(d3712),(d3713),(d3714),(d3715),(d3716),(d3717),(d3718),(d3719),(d3720),(d3721),(d3722),(d3723),(d3724),(d3725),(d3726),(d3727),(d3728),(d3729),(d3730),(d3731),(d3732),(d3733),(d3734),(d3735),(d3736),(d3737),(d3738),(d3739),(d3740),(d3741),(d3742),(d3743),(d3744),(d3745),(d3746),(d3747),(d3748),(d3749),(d3750),(d3751),(d3752),(d3753),(d3754),(d3755),(d3756),(d3757),(d3758),(d3759),(d3760),(d3761),(d3762),(d3763),(d3764),(d3765),(d3766),(d3767),(d3768),(d3769),(d3770),(d3771),(d3772),(d3773),(d3774),(d3775),(d3776),(d3777),(d3778),(d3779),(d3780),(d3781),(d3782),(d3783),(d3784),(d3785),(d3786),(d3787),(d3788),(d3789),(d3790),(d3791),(d3792),(d3793),(d3794),(d3795),(d3796),(d3797),(d3798),(d3799),(d3800),(d3801),(d3802),(d3803),(d3804),(d3805),(d3806),(d3807),(d3808),(d3809),(d3810),(d3811),(d3812),(d3813),(d3814),(d3815),(d3816),(d3817),(d3818),(d3819),(d3820),(d3821),(d3822),(d3823),(d3824),(d3825),(d3826),(d3827),(d3828),(d3829),(d3830),(d3831),(d3832),(d3833),(d3834),(d3835),(d3836),(d3837),(d3838),(d3839),(d3840),(d3841),(d3842),(d3843),(d3844),(d3845),(d3846),(d3847),(d3848),(d3849),(d3850),(d3851),(d3852),(d3853),(d3854),(d3855),(d3856),(d3857),(d3858),(d3859),(d3860),(d3861),(d3862),(d3863),(d3864),(d3865),(d3866),(d3867),(d3868),(d3869),(d3870),(d3871),(d3872),(d3873),(d3874),(d3875),(d3876),(d3877),(d3878),(d3879),(d3880),(d3881),(d3882),(d3883),(d3884),(d3885),(d3886),(d3887),(d3888),(d3889),(d3890),(d3891),(d3892),(d3893),(d3894),(d3895),(d3896),(d3897),(d3898),(d3899),(d3900),(d3901),(d3902),(d3903),(d3904),(d3905),(d3906),(d3907),(d3908),(d3909),(d3910),(d3911),(d3912),(d3913),(d3914),(d3915),(d3916),(d3917),(d3918),(d3919),(d3920),(d3921),(d3922),(d3923),(d3924),(d3925),(d3926),(d3927),(d3928),(d3929),(d3930),(d3931),(d3932),(d3933),(d3934),(d3935),(d3936),(d3937),(d3938),(d3939),(d3940),(d3941),(d3942),(d3943),(d3944),(d3945),(d3946),(d3947),(d3948),(d3949),(d3950),(d3951),(d3952),(d3953),(d3954),(d3955),(d3956),(d3957),(d3958),(d3959),(d3960),(d3961),(d3962),(d3963),(d3964),(d3965),(d3966),(d3967),(d3968),(d3969),(d3970),(d3971),(d3972),(d3973),(d3974),(d3975),(d3976),(d3977),(d3978),(d3979),(d3980),(d3981),(d3982),(d3983),(d3984),(d3985),(d3986),(d3987),(d3988),(d3989),(d3990),(d3991),(d3992),(d3993),(d3994),(d3995),(d3996),(d3997),(d3998),(d3999),(d4000),(d4001),(d4002),(d4003),(d4004),(d4005),(d4006),(d4007),(d4008),(d4009),(d4010),(d4011),(d4012),(d4013),(d4014),(d4015),(d4016),(d4017),(d4018),(d4019),(d4020),(d4021),(d4022),(d4023),(d4024),(d4025),(d4026),(d4027),(d4028),(d4029),(d4030),(d4031),(d4032),(d4033),(d4034),(d4035),(d4036),(d4037),(d4038),(d4039),(d4040),(d4041),(d4042),(d4043),(d4044),(d4045),(d4046),(d4047),(d4048),(d4049),(d4050),(d4051),(d4052),(d4053),(d4054),(d4055),(d4056),(d4057),(d4058),(d4059),(d4060),(d4061),(d4062),(d4063),(d4064),(d4065),(d4066),(d4067),(d4068),(d4069),(d4070),(d4071),(d4072),(d4073),(d4074),(d4075),(d4076),(d4077),(d4078),(d4079),(d4080),(d4081),(d4082),(d4083),(d4084),(d4085),(d4086),(d4087),(d4088),(d4089),(d4090),(d4091),(d4092),(d4093),(d4094),(d4095),(d4096),(d4097),(d4098),(d4099),(d4100),(d4101),(d4102),(d4103),(d4104),(d4105),(d4106),(d4107),(d4108),(d4109),(d4110),(d4111),(d4112),(d4113),(d4114),(d4115),(d4116),(d4117),(d4118),(d4119),(d4120),(d4121),(d4122),(d4123),(d4124),(d4125),(d4126),(d4127),(d4128),(d4129),(d4130),(d4131),(d4132),(d4133),(d4134),(d4135),(d4136),(d4137),(d4138),(d4139),(d4140),(d4141),(d4142),(d4143),(d4144),(d4145),(d4146),(d4147),(d4148),(d4149),(d4150),(d4151),(d4152),(d4153),(d4154),(d4155),(d4156),(d4157),(d4158),(d4159),(d4160),(d4161),(d4162),(d4163),(d4164),(d4165),(d4166),(d4167),(d4168),(d4169),(d4170),(d4171),(d4172),(d4173),(d4174),(d4175),(d4176),(d4177),(d4178),(d4179),(d4180),(d4181),(d4182),(d4183),(d4184),(d4185),(d4186),(d4187),(d4188),(d4189),(d4190),(d4191),(d4192),(d4193),(d4194),(d4195),(d4196),(d4197),(d4198),(d4199),(d4200),(d4201),(d4202),(d4203),(d4204),(d4205),(d4206),(d4207),(d4208),(d4209),(d4210),(d4211),(d4212),(d4213),(d4214),(d4215),(d4216),(d4217),(d4218),(d4219),(d4220),(d4221),(d4222),(d4223),(d4224),(d4225),(d4226),(d4227),(d4228),(d4229),(d4230),(d4231),(d4232),(d4233),(d4234),(d4235),(d4236),(d4237),(d4238),(d4239),(d4240),(d4241),(d4242),(d4243),(d4244),(d4245),(d4246),(d4247),(d4248),(d4249),(d4250),(d4251),(d4252),(d4253),(d4254),(d4255),(d4256),(d4257),(d4258),(d4259),(d4260),(d4261),(d4262),(d4263),(d4264),(d4265),(d4266),(d4267),(d4268),(d4269),(d4270),(d4271),(d4272),(d4273),(d4274),(d4275),(d4276),(d4277),(d4278),(d4279),(d4280),(d4281),(d4282),(d4283),(d4284),(d4285),(d4286),(d4287),(d4288),(d4289),(d4290),(d4291),(d4292),(d4293),(d4294),(d4295),(d4296),(d4297),(d4298),(d4299),(d4300),(d4301),(d4302),(d4303),(d4304),(d4305),(d4306),(d4307),(d4308),(d4309),(d4310),(d4311),(d4312),(d4313),(d4314),(d4315),(d4316),(d4317),(d4318),(d4319),(d4320),(d4321),(d4322),(d4323),(d4324),(d4325),(d4326),(d4327),(d4328),(d4329),(d4330),(d4331),(d4332),(d4333),(d4334),(d4335),(d4336),(d4337),(d4338),(d4339),(d4340),(d4341),(d4342),(d4343),(d4344),(d4345),(d4346),(d4347),(d4348),(d4349),(d4350),(d4351),(d4352),(d4353),(d4354),(d4355),(d4356),(d4357),(d4358),(d4359),(d4360),(d4361),(d4362),(d4363),(d4364),(d4365),(d4366),(d4367),(d4368),(d4369),(d4370),(d4371),(d4372),(d4373),(d4374),(d4375),(d4376),(d4377),(d4378),(d4379),(d4380),(d4381),(d4382),(d4383),(d4384),(d4385),(d4386),(d4387),(d4388),(d4389),(d4390),(d4391),(d4392),(d4393),(d4394),(d4395),(d4396),(d4397),(d4398),(d4399),(d4400),(d4401),(d4402),(d4403),(d4404),(d4405),(d4406),(d4407),(d4408),(d4409),(d4410),(d4411),(d4412),(d4413),(d4414),(d4415),(d4416),(d4417),(d4418),(d4419),(d4420),(d4421),(d4422),(d4423),(d4424),(d4425),(d4426),(d4427),(d4428),(d4429),(d4430),(d4431),(d4432),(d4433),(d4434),(d4435),(d4436),(d4437),(d4438),(d4439),(d4440),(d4441),(d4442),(d4443),(d4444),(d4445),(d4446),(d4447),(d4448),(d4449),(d4450),(d4451),(d4452),(d4453),(d4454),(d4455),(d4456),(d4457),(d4458),(d4459),(d4460),(d4461),(d4462),(d4463),(d4464),(d4465),(d4466),(d4467),(d4468),(d4469),(d4470),(d4471),(d4472),(d4473),(d4474),(d4475),(d4476),(d4477),(d4478),(d4479),(d4480),(d4481),(d4482),(d4483),(d4484),(d4485),(d4486),(d4487),(d4488),(d4489),(d4490),(d4491),(d4492),(d4493),(d4494),(d4495),(d4496),(d4497),(d4498),(d4499),(d4500),(d4501),(d4502),(d4503),(d4504),(d4505),(d4506),(d4507),(d4508),(d4509),(d4510),(d4511),(d4512),(d4513),(d4514),(d4515),(d4516),(d4517),(d4518),(d4519),(d4520),(d4521),(d4522),(d4523),(d4524),(d4525),(d4526),(d4527),(d4528),(d4529),(d4530),(d4531),(d4532),(d4533),(d4534),(d4535),(d4536),(d4537),(d4538),(d4539),(d4540),(d4541),(d4542),(d4543),(d4544),(d4545),(d4546),(d4547),(d4548),(d4549),(d4550),(d4551),(d4552),(d4553),(d4554),(d4555),(d4556),(d4557),(d4558),(d4559),(d4560),(d4561),(d4562),(d4563),(d4564),(d4565),(d4566),(d4567),(d4568),(d4569),(d4570),(d4571),(d4572),(d4573),(d4574),(d4575),(d4576),(d4577),(d4578),(d4579),(d4580),(d4581),(d4582),(d4583),(d4584),(d4585),(d4586),(d4587),(d4588),(d4589),(d4590),(d4591),(d4592),(d4593),(d4594),(d4595),(d4596),(d4597),(d4598),(d4599),(d4600),(d4601),(d4602),(d4603),(d4604),(d4605),(d4606),(d4607),(d4608),(d4609),(d4610),(d4611),(d4612),(d4613),(d4614),(d4615),(d4616),(d4617),(d4618),(d4619),(d4620),(d4621),(d4622),(d4623),(d4624),(d4625),(d4626),(d4627),(d4628),(d4629),(d4630),(d4631),(d4632),(d4633),(d4634),(d4635),(d4636),(d4637),(d4638),(d4639),(d4640),(d4641),(d4642),(d4643),(d4644),(d4645),(d4646),(d4647),(d4648),(d4649),(d4650),(d4651),(d4652),(d4653),(d4654),(d4655),(d4656),(d4657),(d4658),(d4659),(d4660),(d4661),(d4662),(d4663),(d4664),(d4665),(d4666),(d4667),(d4668),(d4669),(d4670),(d4671),(d4672),(d4673),(d4674),(d4675),(d4676),(d4677),(d4678),(d4679),(d4680),(d4681),(d4682),(d4683),(d4684),(d4685),(d4686),(d4687),(d4688),(d4689),(d4690),(d4691),(d4692),(d4693),(d4694),(d4695),(d4696),(d4697),(d4698),(d4699),(d4700),(d4701),(d4702),(d4703),(d4704),(d4705),(d4706),(d4707),(d4708),(d4709),(d4710),(d4711),(d4712),(d4713),(d4714),(d4715),(d4716),(d4717),(d4718),(d4719),(d4720),(d4721),(d4722),(d4723),(d4724),(d4725),(d4726),(d4727),(d4728),(d4729),(d4730),(d4731),(d4732),(d4733),(d4734),(d4735),(d4736),(d4737),(d4738),(d4739),(d4740),(d4741),(d4742),(d4743),(d4744),(d4745),(d4746),(d4747),(d4748),(d4749),(d4750),(d4751),(d4752),(d4753),(d4754),(d4755),(d4756),(d4757),(d4758),(d4759),(d4760),(d4761),(d4762),(d4763),(d4764),(d4765),(d4766),(d4767),(d4768),(d4769),(d4770),(d4771),(d4772),(d4773),(d4774),(d4775),(d4776),(d4777),(d4778),(d4779),(d4780),(d4781),(d4782),(d4783),(d4784),(d4785),(d4786),(d4787),(d4788),(d4789),(d4790),(d4791),(d4792),(d4793),(d4794),(d4795),(d4796),(d4797),(d4798),(d4799),(d4800),(d4801),(d4802),(d4803),(d4804),(d4805),(d4806),(d4807),(d4808),(d4809),(d4810),(d4811),(d4812),(d4813),(d4814),(d4815),(d4816),(d4817),(d4818),(d4819),(d4820),(d4821),(d4822),(d4823),(d4824),(d4825),(d4826),(d4827),(d4828),(d4829),(d4830),(d4831),(d4832),(d4833),(d4834),(d4835),(d4836),(d4837),(d4838),(d4839),(d4840),(d4841),(d4842),(d4843),(d4844),(d4845),(d4846),(d4847),(d4848),(d4849),(d4850),(d4851),(d4852),(d4853),(d4854),(d4855),(d4856),(d4857),(d4858),(d4859),(d4860),(d4861),(d4862),(d4863),(d4864),(d4865),(d4866),(d4867),(d4868),(d4869),(d4870),(d4871),(d4872),(d4873),(d4874),(d4875),(d4876),(d4877),(d4878),(d4879),(d4880),(d4881),(d4882),(d4883),(d4884),(d4885),(d4886),(d4887),(d4888),(d4889),(d4890),(d4891),(d4892),(d4893),(d4894),(d4895),(d4896),(d4897),(d4898),(d4899),(d4900),(d4901),(d4902),(d4903),(d4904),(d4905),(d4906),(d4907),(d4908),(d4909),(d4910),(d4911),(d4912),(d4913),(d4914),(d4915),(d4916),(d4917),(d4918),(d4919),(d4920),(d4921),(d4922),(d4923),(d4924),(d4925),(d4926),(d4927),(d4928),(d4929),(d4930),(d4931),(d4932),(d4933),(d4934),(d4935),(d4936),(d4937),(d4938),(d4939),(d4940),(d4941),(d4942),(d4943),(d4944),(d4945),(d4946),(d4947),(d4948),(d4949),(d4950),(d4951),(d4952),(d4953),(d4954),(d4955),(d4956),(d4957),(d4958),(d4959),(d4960),(d4961),(d4962),(d4963),(d4964),(d4965),(d4966),(d4967),(d4968),(d4969),(d4970),(d4971),(d4972),(d4973),(d4974),(d4975),(d4976),(d4977),(d4978),(d4979),(d4980),(d4981),(d4982),(d4983),(d4984),(d4985),(d4986),(d4987),(d4988),(d4989),(d4990),(d4991),(d4992),(d4993),(d4994),(d4995),(d4996),(d4997),(d4998),(d4999),(d5000),(d5001),(d5002),(d5003),(d5004),(d5005),(d5006),(d5007),(d5008),(d5009),(d5010),(d5011),(d5012),(d5013),(d5014),(d5015),(d5016),(d5017),(d5018),(d5019),(d5020),(d5021),(d5022),(d5023),(d5024),(d5025),(d5026),(d5027),(d5028),(d5029),(d5030),(d5031),(d5032),(d5033),(d5034),(d5035),(d5036),(d5037),(d5038),(d5039),(d5040),(d5041),(d5042),(d5043),(d5044),(d5045),(d5046),(d5047),(d5048),(d5049),(d5050),(d5051),(d5052),(d5053),(d5054),(d5055),(d5056),(d5057),(d5058),(d5059),(d5060),(d5061),(d5062),(d5063),(d5064),(d5065),(d5066),(d5067),(d5068),(d5069),(d5070),(d5071),(d5072),(d5073),(d5074),(d5075),(d5076),(d5077),(d5078),(d5079),(d5080),(d5081),(d5082),(d5083),(d5084),(d5085),(d5086),(d5087),(d5088),(d5089),(d5090),(d5091),(d5092),(d5093),(d5094),(d5095),(d5096),(d5097),(d5098),(d5099),(d5100),(d5101),(d5102),(d5103),(d5104),(d5105),(d5106),(d5107),(d5108),(d5109),(d5110),(d5111),(d5112),(d5113),(d5114),(d5115),(d5116),(d5117),(d5118),(d5119),(d5120),(d5121),(d5122),(d5123),(d5124),(d5125),(d5126),(d5127),(d5128),(d5129),(d5130),(d5131),(d5132),(d5133),(d5134),(d5135),(d5136),(d5137),(d5138),(d5139),(d5140),(d5141),(d5142),(d5143),(d5144),(d5145),(d5146),(d5147),(d5148),(d5149),(d5150),(d5151),(d5152),(d5153),(d5154),(d5155),(d5156),(d5157),(d5158),(d5159),(d5160),(d5161),(d5162),(d5163),(d5164),(d5165),(d5166),(d5167),(d5168),(d5169),(d5170),(d5171),(d5172),(d5173),(d5174),(d5175),(d5176),(d5177),(d5178),(d5179),(d5180),(d5181),(d5182),(d5183),(d5184),(d5185),(d5186),(d5187),(d5188),(d5189),(d5190),(d5191),(d5192),(d5193),(d5194),(d5195),(d5196),(d5197),(d5198),(d5199),(d5200),(d5201),(d5202),(d5203),(d5204),(d5205),(d5206),(d5207),(d5208),(d5209),(d5210),(d5211),(d5212),(d5213),(d5214),(d5215),(d5216),(d5217),(d5218),(d5219),(d5220),(d5221),(d5222),(d5223),(d5224),(d5225),(d5226),(d5227),(d5228),(d5229),(d5230),(d5231),(d5232),(d5233),(d5234),(d5235),(d5236),(d5237),(d5238),(d5239),(d5240),(d5241),(d5242),(d5243),(d5244),(d5245),(d5246),(d5247),(d5248),(d5249),(d5250),(d5251),(d5252),(d5253),(d5254),(d5255),(d5256),(d5257),(d5258),(d5259),(d5260),(d5261),(d5262),(d5263),(d5264),(d5265),(d5266),(d5267),(d5268),(d5269),(d5270),(d5271),(d5272),(d5273),(d5274),(d5275),(d5276),(d5277),(d5278),(d5279),(d5280),(d5281),(d5282),(d5283),(d5284),(d5285),(d5286),(d5287),(d5288),(d5289),(d5290),(d5291),(d5292),(d5293),(d5294),(d5295),(d5296),(d5297),(d5298),(d5299),(d5300),(d5301),(d5302),(d5303),(d5304),(d5305),(d5306),(d5307),(d5308),(d5309),(d5310),(d5311),(d5312),(d5313),(d5314),(d5315),(d5316),(d5317),(d5318),(d5319),(d5320),(d5321),(d5322),(d5323),(d5324),(d5325),(d5326),(d5327),(d5328),(d5329),(d5330),(d5331),(d5332),(d5333),(d5334),(d5335),(d5336),(d5337),(d5338),(d5339),(d5340),(d5341),(d5342),(d5343),(d5344),(d5345),(d5346),(d5347),(d5348),(d5349),(d5350),(d5351),(d5352),(d5353),(d5354),(d5355),(d5356),(d5357),(d5358),(d5359),(d5360),(d5361),(d5362),(d5363),(d5364),(d5365),(d5366),(d5367),(d5368),(d5369),(d5370),(d5371),(d5372),(d5373),(d5374),(d5375),(d5376),(d5377),(d5378),(d5379),(d5380),(d5381),(d5382),(d5383),(d5384),(d5385),(d5386),(d5387),(d5388),(d5389),(d5390),(d5391),(d5392),(d5393),(d5394),(d5395),(d5396),(d5397),(d5398),(d5399),(d5400),(d5401),(d5402),(d5403),(d5404),(d5405),(d5406),(d5407),(d5408),(d5409),(d5410),(d5411),(d5412),(d5413),(d5414),(d5415),(d5416),(d5417),(d5418),(d5419),(d5420),(d5421),(d5422),(d5423),(d5424),(d5425),(d5426),(d5427),(d5428),(d5429),(d5430),(d5431),(d5432),(d5433),(d5434),(d5435),(d5436),(d5437),(d5438),(d5439),(d5440),(d5441),(d5442),(d5443),(d5444),(d5445),(d5446),(d5447),(d5448),(d5449),(d5450),(d5451),(d5452),(d5453),(d5454),(d5455),(d5456),(d5457),(d5458),(d5459),(d5460),(d5461),(d5462),(d5463),(d5464),(d5465),(d5466),(d5467),(d5468),(d5469),(d5470),(d5471),(d5472),(d5473),(d5474),(d5475),(d5476),(d5477),(d5478),(d5479),(d5480),(d5481),(d5482),(d5483),(d5484),(d5485),(d5486),(d5487),(d5488),(d5489),(d5490),(d5491),(d5492),(d5493),(d5494),(d5495),(d5496),(d5497),(d5498),(d5499),(d5500),(d5501),(d5502),(d5503),(d5504),(d5505),(d5506),(d5507),(d5508),(d5509),(d5510),(d5511),(d5512),(d5513),(d5514),(d5515),(d5516),(d5517),(d5518),(d5519),(d5520),(d5521),(d5522),(d5523),(d5524),(d5525),(d5526),(d5527),(d5528),(d5529),(d5530),(d5531),(d5532),(d5533),(d5534),(d5535),(d5536),(d5537),(d5538),(d5539),(d5540),(d5541),(d5542),(d5543),(d5544),(d5545),(d5546),(d5547),(d5548),(d5549),(d5550),(d5551),(d5552),(d5553),(d5554),(d5555),(d5556),(d5557),(d5558),(d5559),(d5560),(d5561),(d5562),(d5563),(d5564),(d5565),(d5566),(d5567),(d5568),(d5569),(d5570),(d5571),(d5572),(d5573),(d5574),(d5575),(d5576),(d5577),(d5578),(d5579),(d5580),(d5581),(d5582),(d5583),(d5584),(d5585),(d5586),(d5587),(d5588),(d5589),(d5590),(d5591),(d5592),(d5593),(d5594),(d5595),(d5596),(d5597),(d5598),(d5599),(d5600),(d5601),(d5602),(d5603),(d5604),(d5605),(d5606),(d5607),(d5608),(d5609),(d5610),(d5611),(d5612),(d5613),(d5614),(d5615),(d5616),(d5617),(d5618),(d5619),(d5620),(d5621),(d5622),(d5623),(d5624),(d5625),(d5626),(d5627),(d5628),(d5629),(d5630),(d5631),(d5632),(d5633),(d5634),(d5635),(d5636),(d5637),(d5638),(d5639),(d5640),(d5641),(d5642),(d5643),(d5644),(d5645),(d5646),(d5647),(d5648),(d5649),(d5650),(d5651),(d5652),(d5653),(d5654),(d5655),(d5656),(d5657),(d5658),(d5659),(d5660),(d5661),(d5662),(d5663),(d5664),(d5665),(d5666),(d5667),(d5668),(d5669),(d5670),(d5671),(d5672),(d5673),(d5674),(d5675),(d5676),(d5677),(d5678),(d5679),(d5680),(d5681),(d5682),(d5683),(d5684),(d5685),(d5686),(d5687),(d5688),(d5689),(d5690),(d5691),(d5692),(d5693),(d5694),(d5695),(d5696),(d5697),(d5698),(d5699),(d5700),(d5701),(d5702),(d5703),(d5704),(d5705),(d5706),(d5707),(d5708),(d5709),(d5710),(d5711),(d5712),(d5713),(d5714),(d5715),(d5716),(d5717),(d5718),(d5719),(d5720),(d5721),(d5722),(d5723),(d5724),(d5725),(d5726),(d5727),(d5728),(d5729),(d5730),(d5731),(d5732),(d5733),(d5734),(d5735),(d5736),(d5737),(d5738),(d5739),(d5740),(d5741),(d5742),(d5743),(d5744),(d5745),(d5746),(d5747),(d5748),(d5749),(d5750),(d5751),(d5752),(d5753),(d5754),(d5755),(d5756),(d5757),(d5758),(d5759),(d5760),(d5761),(d5762),(d5763),(d5764),(d5765),(d5766),(d5767),(d5768),(d5769),(d5770),(d5771),(d5772),(d5773),(d5774),(d5775),(d5776),(d5777),(d5778),(d5779),(d5780),(d5781),(d5782),(d5783),(d5784),(d5785),(d5786),(d5787),(d5788),(d5789),(d5790),(d5791),(d5792),(d5793),(d5794),(d5795),(d5796),(d5797),(d5798),(d5799),(d5800),(d5801),(d5802),(d5803),(d5804),(d5805),(d5806),(d5807),(d5808),(d5809),(d5810),(d5811),(d5812),(d5813),(d5814),(d5815),(d5816),(d5817),(d5818),(d5819),(d5820),(d5821),(d5822),(d5823),(d5824),(d5825),(d5826),(d5827),(d5828),(d5829),(d5830),(d5831),(d5832),(d5833),(d5834),(d5835),(d5836),(d5837),(d5838),(d5839),(d5840),(d5841),(d5842),(d5843),(d5844),(d5845),(d5846),(d5847),(d5848),(d5849),(d5850),(d5851),(d5852),(d5853),(d5854),(d5855),(d5856),(d5857),(d5858),(d5859),(d5860),(d5861),(d5862),(d5863),(d5864),(d5865),(d5866),(d5867),(d5868),(d5869),(d5870),(d5871),(d5872),(d5873),(d5874),(d5875),(d5876),(d5877),(d5878),(d5879),(d5880),(d5881),(d5882),(d5883),(d5884),(d5885),(d5886),(d5887),(d5888),(d5889),(d5890),(d5891),(d5892),(d5893),(d5894),(d5895),(d5896),(d5897),(d5898),(d5899),(d5900),(d5901),(d5902),(d5903),(d5904),(d5905),(d5906),(d5907),(d5908),(d5909),(d5910),(d5911),(d5912),(d5913),(d5914),(d5915),(d5916),(d5917),(d5918),(d5919),(d5920),(d5921),(d5922),(d5923),(d5924),(d5925),(d5926),(d5927),(d5928),(d5929),(d5930),(d5931),(d5932),(d5933),(d5934),(d5935),(d5936),(d5937),(d5938),(d5939),(d5940),(d5941),(d5942),(d5943),(d5944),(d5945),(d5946),(d5947),(d5948),(d5949),(d5950),(d5951),(d5952),(d5953),(d5954),(d5955),(d5956),(d5957),(d5958),(d5959),(d5960),(d5961),(d5962),(d5963),(d5964),(d5965),(d5966),(d5967),(d5968),(d5969),(d5970),(d5971),(d5972),(d5973),(d5974),(d5975),(d5976),(d5977),(d5978),(d5979),(d5980),(d5981),(d5982),(d5983),(d5984),(d5985),(d5986),(d5987),(d5988),(d5989),(d5990),(d5991),(d5992),(d5993),(d5994),(d5995),(d5996),(d5997),(d5998),(d5999),(d6000),(d6001),(d6002),(d6003),(d6004),(d6005),(d6006),(d6007),(d6008),(d6009),(d6010),(d6011),(d6012),(d6013),(d6014),(d6015),(d6016),(d6017),(d6018),(d6019),(d6020),(d6021),(d6022),(d6023),(d6024),(d6025),(d6026),(d6027),(d6028),(d6029),(d6030),(d6031),(d6032),(d6033),(d6034),(d6035),(d6036),(d6037),(d6038),(d6039),(d6040),(d6041),(d6042),(d6043),(d6044),(d6045),(d6046),(d6047),(d6048),(d6049),(d6050),(d6051),(d6052),(d6053),(d6054),(d6055),(d6056),(d6057),(d6058),(d6059),(d6060),(d6061),(d6062),(d6063),(d6064),(d6065),(d6066),(d6067),(d6068),(d6069),(d6070),(d6071),(d6072),(d6073),(d6074),(d6075),(d6076),(d6077),(d6078),(d6079),(d6080),(d6081),(d6082),(d6083),(d6084),(d6085),(d6086),(d6087),(d6088),(d6089),(d6090),(d6091),(d6092),(d6093),(d6094),(d6095),(d6096),(d6097),(d6098),(d6099),(d6100),(d6101),(d6102),(d6103),(d6104),(d6105),(d6106),(d6107),(d6108),(d6109),(d6110),(d6111),(d6112),(d6113),(d6114),(d6115),(d6116),(d6117),(d6118),(d6119),(d6120),(d6121),(d6122),(d6123),(d6124),(d6125),(d6126),(d6127),(d6128),(d6129),(d6130),(d6131),(d6132),(d6133),(d6134),(d6135),(d6136),(d6137),(d6138),(d6139),(d6140),(d6141),(d6142),(d6143),(d6144),(d6145),(d6146),(d6147),(d6148),(d6149),(d6150),(d6151),(d6152),(d6153),(d6154),(d6155),(d6156),(d6157),(d6158),(d6159),(d6160),(d6161),(d6162),(d6163),(d6164),(d6165),(d6166),(d6167),(d6168),(d6169),(d6170),(d6171),(d6172),(d6173),(d6174),(d6175),(d6176),(d6177),(d6178),(d6179),(d6180),(d6181),(d6182),(d6183),(d6184),(d6185),(d6186),(d6187),(d6188),(d6189),(d6190),(d6191),(d6192),(d6193),(d6194),(d6195),(d6196),(d6197),(d6198),(d6199),(d6200),(d6201),(d6202),(d6203),(d6204),(d6205),(d6206),(d6207),(d6208),(d6209),(d6210),(d6211),(d6212),(d6213),(d6214),(d6215),(d6216),(d6217),(d6218),(d6219),(d6220),(d6221),(d6222),(d6223),(d6224),(d6225),(d6226),(d6227),(d6228),(d6229),(d6230),(d6231),(d6232),(d6233),(d6234),(d6235),(d6236),(d6237),(d6238),(d6239),(d6240),(d6241),(d6242),(d6243),(d6244),(d6245),(d6246),(d6247),(d6248),(d6249),(d6250),(d6251),(d6252),(d6253),(d6254),(d6255),(d6256),(d6257),(d6258),(d6259),(d6260),(d6261),(d6262),(d6263),(d6264),(d6265),(d6266),(d6267),(d6268),(d6269),(d6270),(d6271),(d6272),(d6273),(d6274),(d6275),(d6276),(d6277),(d6278),(d6279),(d6280),(d6281),(d6282),(d6283),(d6284),(d6285),(d6286),(d6287),(d6288),(d6289),(d6290),(d6291),(d6292),(d6293),(d6294),(d6295),(d6296),(d6297),(d6298),(d6299),(d6300),(d6301),(d6302),(d6303),(d6304),(d6305),(d6306),(d6307),(d6308),(d6309),(d6310),(d6311),(d6312),(d6313),(d6314),(d6315),(d6316),(d6317),(d6318),(d6319),(d6320),(d6321),(d6322),(d6323),(d6324),(d6325),(d6326),(d6327),(d6328),(d6329),(d6330),(d6331),(d6332),(d6333),(d6334),(d6335),(d6336),(d6337),(d6338),(d6339),(d6340),(d6341),(d6342),(d6343),(d6344),(d6345),(d6346),(d6347),(d6348),(d6349),(d6350),(d6351),(d6352),(d6353),(d6354),(d6355),(d6356),(d6357),(d6358),(d6359),(d6360),(d6361),(d6362),(d6363),(d6364),(d6365),(d6366),(d6367),(d6368),(d6369),(d6370),(d6371),(d6372),(d6373),(d6374),(d6375),(d6376),(d6377),(d6378),(d6379),(d6380),(d6381),(d6382),(d6383),(d6384),(d6385),(d6386),(d6387),(d6388),(d6389),(d6390),(d6391),(d6392),(d6393),(d6394),(d6395),(d6396),(d6397),(d6398),(d6399),(d6400),(d6401),(d6402),(d6403),(d6404),(d6405),(d6406),(d6407),(d6408),(d6409),(d6410),(d6411),(d6412),(d6413),(d6414),(d6415),(d6416),(d6417),(d6418),(d6419),(d6420),(d6421),(d6422),(d6423),(d6424),(d6425),(d6426),(d6427),(d6428),(d6429),(d6430),(d6431),(d6432),(d6433),(d6434),(d6435),(d6436),(d6437),(d6438),(d6439),(d6440),(d6441),(d6442),(d6443),(d6444),(d6445),(d6446),(d6447),(d6448),(d6449),(d6450),(d6451),(d6452),(d6453),(d6454),(d6455),(d6456),(d6457),(d6458),(d6459),(d6460),(d6461),(d6462),(d6463),(d6464),(d6465),(d6466),(d6467),(d6468),(d6469),(d6470),(d6471),(d6472),(d6473),(d6474),(d6475),(d6476),(d6477),(d6478),(d6479),(d6480),(d6481),(d6482),(d6483),(d6484),(d6485),(d6486),(d6487),(d6488),(d6489),(d6490),(d6491),(d6492),(d6493),(d6494),(d6495),(d6496),(d6497),(d6498),(d6499),(d6500),(d6501),(d6502),(d6503),(d6504),(d6505),(d6506),(d6507),(d6508),(d6509),(d6510),(d6511),(d6512),(d6513),(d6514),(d6515),(d6516),(d6517),(d6518),(d6519),(d6520),(d6521),(d6522),(d6523),(d6524),(d6525),(d6526),(d6527),(d6528),(d6529),(d6530),(d6531),(d6532),(d6533),(d6534),(d6535),(d6536),(d6537),(d6538),(d6539),(d6540),(d6541),(d6542),(d6543),(d6544),(d6545),(d6546),(d6547),(d6548),(d6549),(d6550),(d6551),(d6552),(d6553),(d6554),(d6555),(d6556),(d6557),(d6558),(d6559),(d6560),(d6561),(d6562),(d6563),(d6564),(d6565),(d6566),(d6567),(d6568),(d6569),(d6570),(d6571),(d6572),(d6573),(d6574),(d6575),(d6576),(d6577),(d6578),(d6579),(d6580),(d6581),(d6582),(d6583),(d6584),(d6585),(d6586),(d6587),(d6588),(d6589),(d6590),(d6591),(d6592),(d6593),(d6594),(d6595),(d6596),(d6597),(d6598),(d6599),(d6600),(d6601),(d6602),(d6603),(d6604),(d6605),(d6606),(d6607),(d6608),(d6609),(d6610),(d6611),(d6612),(d6613),(d6614),(d6615),(d6616),(d6617),(d6618),(d6619),(d6620),(d6621),(d6622),(d6623),(d6624),(d6625),(d6626),(d6627),(d6628),(d6629),(d6630),(d6631),(d6632),(d6633),(d6634),(d6635),(d6636),(d6637),(d6638),(d6639),(d6640),(d6641),(d6642),(d6643),(d6644),(d6645),(d6646),(d6647),(d6648),(d6649),(d6650),(d6651),(d6652),(d6653),(d6654),(d6655),(d6656),(d6657),(d6658),(d6659),(d6660),(d6661),(d6662),(d6663),(d6664),(d6665),(d6666),(d6667),(d6668),(d6669),(d6670),(d6671),(d6672),(d6673),(d6674),(d6675),(d6676),(d6677),(d6678),(d6679),(d6680),(d6681),(d6682),(d6683),(d6684),(d6685),(d6686),(d6687),(d6688),(d6689),(d6690),(d6691),(d6692),(d6693),(d6694),(d6695),(d6696),(d6697),(d6698),(d6699),(d6700),(d6701),(d6702),(d6703),(d6704),(d6705),(d6706),(d6707),(d6708),(d6709),(d6710),(d6711),(d6712),(d6713),(d6714),(d6715),(d6716),(d6717),(d6718),(d6719),(d6720),(d6721),(d6722),(d6723),(d6724),(d6725),(d6726),(d6727),(d6728),(d6729),(d6730),(d6731),(d6732),(d6733),(d6734),(d6735),(d6736),(d6737),(d6738),(d6739),(d6740),(d6741),(d6742),(d6743),(d6744),(d6745),(d6746),(d6747),(d6748),(d6749),(d6750),(d6751),(d6752),(d6753),(d6754),(d6755),(d6756),(d6757),(d6758),(d6759),(d6760),(d6761),(d6762),(d6763),(d6764),(d6765),(d6766),(d6767),(d6768),(d6769),(d6770),(d6771),(d6772),(d6773),(d6774),(d6775),(d6776),(d6777),(d6778),(d6779),(d6780),(d6781),(d6782),(d6783),(d6784),(d6785),(d6786),(d6787),(d6788),(d6789),(d6790),(d6791),(d6792),(d6793),(d6794),(d6795),(d6796),(d6797),(d6798),(d6799),(d6800),(d6801),(d6802),(d6803),(d6804),(d6805),(d6806),(d6807),(d6808),(d6809),(d6810),(d6811),(d6812),(d6813),(d6814),(d6815),(d6816),(d6817),(d6818),(d6819),(d6820),(d6821),(d6822),(d6823),(d6824),(d6825),(d6826),(d6827),(d6828),(d6829),(d6830),(d6831),(d6832),(d6833),(d6834),(d6835),(d6836),(d6837),(d6838),(d6839),(d6840),(d6841),(d6842),(d6843),(d6844),(d6845),(d6846),(d6847),(d6848),(d6849),(d6850),(d6851),(d6852),(d6853),(d6854),(d6855),(d6856),(d6857),(d6858),(d6859),(d6860),(d6861),(d6862),(d6863),(d6864),(d6865),(d6866),(d6867),(d6868),(d6869),(d6870),(d6871),(d6872),(d6873),(d6874),(d6875),(d6876),(d6877),(d6878),(d6879),(d6880),(d6881),(d6882),(d6883),(d6884),(d6885),(d6886),(d6887),(d6888),(d6889),(d6890),(d6891),(d6892),(d6893),(d6894),(d6895),(d6896),(d6897),(d6898),(d6899),(d6900),(d6901),(d6902),(d6903),(d6904),(d6905),(d6906),(d6907),(d6908),(d6909),(d6910),(d6911),(d6912),(d6913),(d6914),(d6915),(d6916),(d6917),(d6918),(d6919),(d6920),(d6921),(d6922),(d6923),(d6924),(d6925),(d6926),(d6927),(d6928),(d6929),(d6930),(d6931),(d6932),(d6933),(d6934),(d6935),(d6936),(d6937),(d6938),(d6939),(d6940),(d6941),(d6942),(d6943),(d6944),(d6945),(d6946),(d6947),(d6948),(d6949),(d6950),(d6951),(d6952),(d6953),(d6954),(d6955),(d6956),(d6957),(d6958),(d6959),(d6960),(d6961),(d6962),(d6963),(d6964),(d6965),(d6966),(d6967),(d6968),(d6969),(d6970),(d6971),(d6972),(d6973),(d6974),(d6975),(d6976),(d6977),(d6978),(d6979),(d6980),(d6981),(d6982),(d6983),(d6984),(d6985),(d6986),(d6987),(d6988),(d6989),(d6990),(d6991),(d6992),(d6993),(d6994),(d6995),(d6996),(d6997),(d6998),(d6999),(d7000),(d7001),(d7002),(d7003),(d7004),(d7005),(d7006),(d7007),(d7008),(d7009),(d7010),(d7011),(d7012),(d7013),(d7014),(d7015),(d7016),(d7017),(d7018),(d7019),(d7020),(d7021),(d7022),(d7023),(d7024),(d7025),(d7026),(d7027),(d7028),(d7029),(d7030),(d7031),(d7032),(d7033),(d7034),(d7035),(d7036),(d7037),(d7038),(d7039),(d7040),(d7041),(d7042),(d7043),(d7044),(d7045),(d7046),(d7047),(d7048),(d7049),(d7050),(d7051),(d7052),(d7053),(d7054),(d7055),(d7056),(d7057),(d7058),(d7059),(d7060),(d7061),(d7062),(d7063),(d7064),(d7065),(d7066),(d7067),(d7068),(d7069),(d7070),(d7071),(d7072),(d7073),(d7074),(d7075),(d7076),(d7077),(d7078),(d7079),(d7080),(d7081),(d7082),(d7083),(d7084),(d7085),(d7086),(d7087),(d7088),(d7089),(d7090),(d7091),(d7092),(d7093),(d7094),(d7095),(d7096),(d7097),(d7098),(d7099),(d7100),(d7101),(d7102),(d7103),(d7104),(d7105),(d7106),(d7107),(d7108),(d7109),(d7110),(d7111),(d7112),(d7113),(d7114),(d7115),(d7116),(d7117),(d7118),(d7119),(d7120),(d7121),(d7122),(d7123),(d7124),(d7125),(d7126),(d7127),(d7128),(d7129),(d7130),(d7131),(d7132),(d7133),(d7134),(d7135),(d7136),(d7137),(d7138),(d7139),(d7140),(d7141),(d7142),(d7143),(d7144),(d7145),(d7146),(d7147),(d7148),(d7149),(d7150),(d7151),(d7152),(d7153),(d7154),(d7155),(d7156),(d7157),(d7158),(d7159),(d7160),(d7161),(d7162),(d7163),(d7164),(d7165),(d7166),(d7167),(d7168),(d7169),(d7170),(d7171),(d7172),(d7173),(d7174),(d7175),(d7176),(d7177),(d7178),(d7179),(d7180),(d7181),(d7182),(d7183),(d7184),(d7185),(d7186),(d7187),(d7188),(d7189),(d7190),(d7191),(d7192),(d7193),(d7194),(d7195),(d7196),(d7197),(d7198),(d7199),(d7200),(d7201),(d7202),(d7203),(d7204),(d7205),(d7206),(d7207),(d7208),(d7209),(d7210),(d7211),(d7212),(d7213),(d7214),(d7215),(d7216),(d7217),(d7218),(d7219),(d7220),(d7221),(d7222),(d7223),(d7224),(d7225),(d7226),(d7227),(d7228),(d7229),(d7230),(d7231),(d7232),(d7233),(d7234),(d7235),(d7236),(d7237),(d7238),(d7239),(d7240),(d7241),(d7242),(d7243),(d7244),(d7245),(d7246),(d7247),(d7248),(d7249),(d7250),(d7251),(d7252),(d7253),(d7254),(d7255),(d7256),(d7257),(d7258),(d7259),(d7260),(d7261),(d7262),(d7263),(d7264),(d7265),(d7266),(d7267),(d7268),(d7269),(d7270),(d7271),(d7272),(d7273),(d7274),(d7275),(d7276),(d7277),(d7278),(d7279),(d7280),(d7281),(d7282),(d7283),(d7284),(d7285),(d7286),(d7287),(d7288),(d7289),(d7290),(d7291),(d7292),(d7293),(d7294),(d7295),(d7296),(d7297),(d7298),(d7299),(d7300),(d7301),(d7302),(d7303),(d7304),(d7305),(d7306),(d7307),(d7308),(d7309),(d7310),(d7311),(d7312),(d7313),(d7314),(d7315),(d7316),(d7317),(d7318),(d7319),(d7320),(d7321),(d7322),(d7323),(d7324),(d7325),(d7326),(d7327),(d7328),(d7329),(d7330),(d7331),(d7332),(d7333),(d7334),(d7335),(d7336),(d7337),(d7338),(d7339),(d7340),(d7341),(d7342),(d7343),(d7344),(d7345),(d7346),(d7347),(d7348),(d7349),(d7350),(d7351),(d7352),(d7353),(d7354),(d7355),(d7356),(d7357),(d7358),(d7359),(d7360),(d7361),(d7362),(d7363),(d7364),(d7365),(d7366),(d7367),(d7368),(d7369),(d7370),(d7371),(d7372),(d7373),(d7374),(d7375),(d7376),(d7377),(d7378),(d7379),(d7380),(d7381),(d7382),(d7383),(d7384),(d7385),(d7386),(d7387),(d7388),(d7389),(d7390),(d7391),(d7392),(d7393),(d7394),(d7395),(d7396),(d7397),(d7398),(d7399),(d7400),(d7401),(d7402),(d7403),(d7404),(d7405),(d7406),(d7407),(d7408),(d7409),(d7410),(d7411),(d7412),(d7413),(d7414),(d7415),(d7416),(d7417),(d7418),(d7419),(d7420),(d7421),(d7422),(d7423),(d7424),(d7425),(d7426),(d7427),(d7428),(d7429),(d7430),(d7431),(d7432),(d7433),(d7434),(d7435),(d7436),(d7437),(d7438),(d7439),(d7440),(d7441),(d7442),(d7443),(d7444),(d7445),(d7446),(d7447),(d7448),(d7449),(d7450),(d7451),(d7452),(d7453),(d7454),(d7455),(d7456),(d7457),(d7458),(d7459),(d7460),(d7461),(d7462),(d7463),(d7464),(d7465),(d7466),(d7467),(d7468),(d7469),(d7470),(d7471),(d7472),(d7473),(d7474),(d7475),(d7476),(d7477),(d7478),(d7479),(d7480),(d7481),(d7482),(d7483),(d7484),(d7485),(d7486),(d7487),(d7488),(d7489),(d7490),(d7491),(d7492),(d7493),(d7494),(d7495),(d7496),(d7497),(d7498),(d7499),(d7500),(d7501),(d7502),(d7503),(d7504),(d7505),(d7506),(d7507),(d7508),(d7509),(d7510),(d7511),(d7512),(d7513),(d7514),(d7515),(d7516),(d7517),(d7518),(d7519),(d7520),(d7521),(d7522),(d7523),(d7524),(d7525),(d7526),(d7527),(d7528),(d7529),(d7530),(d7531),(d7532),(d7533),(d7534),(d7535),(d7536),(d7537),(d7538),(d7539),(d7540),(d7541),(d7542),(d7543),(d7544),(d7545),(d7546),(d7547),(d7548),(d7549),(d7550),(d7551),(d7552),(d7553),(d7554),(d7555),(d7556),(d7557),(d7558),(d7559),(d7560),(d7561),(d7562),(d7563),(d7564),(d7565),(d7566),(d7567),(d7568),(d7569),(d7570),(d7571),(d7572),(d7573),(d7574),(d7575),(d7576),(d7577),(d7578),(d7579),(d7580),(d7581),(d7582),(d7583),(d7584),(d7585),(d7586),(d7587),(d7588),(d7589),(d7590),(d7591),(d7592),(d7593),(d7594),(d7595),(d7596),(d7597),(d7598),(d7599),(d7600),(d7601),(d7602),(d7603),(d7604),(d7605),(d7606),(d7607),(d7608),(d7609),(d7610),(d7611),(d7612),(d7613),(d7614),(d7615),(d7616),(d7617),(d7618),(d7619),(d7620),(d7621),(d7622),(d7623),(d7624),(d7625),(d7626),(d7627),(d7628),(d7629),(d7630),(d7631),(d7632),(d7633),(d7634),(d7635),(d7636),(d7637),(d7638),(d7639),(d7640),(d7641),(d7642),(d7643),(d7644),(d7645),(d7646),(d7647),(d7648),(d7649),(d7650),(d7651),(d7652),(d7653),(d7654),(d7655),(d7656),(d7657),(d7658),(d7659),(d7660),(d7661),(d7662),(d7663),(d7664),(d7665),(d7666),(d7667),(d7668),(d7669),(d7670),(d7671),(d7672),(d7673),(d7674),(d7675),(d7676),(d7677),(d7678),(d7679),(d7680),(d7681),(d7682),(d7683),(d7684),(d7685),(d7686),(d7687),(d7688),(d7689),(d7690),(d7691),(d7692),(d7693),(d7694),(d7695),(d7696),(d7697),(d7698),(d7699),(d7700),(d7701),(d7702),(d7703),(d7704),(d7705),(d7706),(d7707),(d7708),(d7709),(d7710),(d7711),(d7712),(d7713),(d7714),(d7715),(d7716),(d7717),(d7718),(d7719),(d7720),(d7721),(d7722),(d7723),(d7724),(d7725),(d7726),(d7727),(d7728),(d7729),(d7730),(d7731),(d7732),(d7733),(d7734),(d7735),(d7736),(d7737),(d7738),(d7739),(d7740),(d7741),(d7742),(d7743),(d7744),(d7745),(d7746),(d7747),(d7748),(d7749),(d7750),(d7751),(d7752),(d7753),(d7754),(d7755),(d7756),(d7757),(d7758),(d7759),(d7760),(d7761),(d7762),(d7763),(d7764),(d7765),(d7766),(d7767),(d7768),(d7769),(d7770),(d7771),(d7772),(d7773),(d7774),(d7775),(d7776),(d7777),(d7778),(d7779),(d7780),(d7781),(d7782),(d7783),(d7784),(d7785),(d7786),(d7787),(d7788),(d7789),(d7790),(d7791),(d7792),(d7793),(d7794),(d7795),(d7796),(d7797),(d7798),(d7799),(d7800),(d7801),(d7802),(d7803),(d7804),(d7805),(d7806),(d7807),(d7808),(d7809),(d7810),(d7811),(d7812),(d7813),(d7814),(d7815),(d7816),(d7817),(d7818),(d7819),(d7820),(d7821),(d7822),(d7823),(d7824),(d7825),(d7826),(d7827),(d7828),(d7829),(d7830),(d7831),(d7832),(d7833),(d7834),(d7835),(d7836),(d7837),(d7838),(d7839),(d7840),(d7841),(d7842),(d7843),(d7844),(d7845),(d7846),(d7847),(d7848),(d7849),(d7850),(d7851),(d7852),(d7853),(d7854),(d7855),(d7856),(d7857),(d7858),(d7859),(d7860),(d7861),(d7862),(d7863),(d7864),(d7865),(d7866),(d7867),(d7868),(d7869),(d7870),(d7871),(d7872),(d7873),(d7874),(d7875),(d7876),(d7877),(d7878),(d7879),(d7880),(d7881),(d7882),(d7883),(d7884),(d7885),(d7886),(d7887),(d7888),(d7889),(d7890),(d7891),(d7892),(d7893),(d7894),(d7895),(d7896),(d7897),(d7898),(d7899),(d7900),(d7901),(d7902),(d7903),(d7904),(d7905),(d7906),(d7907),(d7908),(d7909),(d7910),(d7911),(d7912),(d7913),(d7914),(d7915),(d7916),(d7917),(d7918),(d7919),(d7920),(d7921),(d7922),(d7923),(d7924),(d7925),(d7926),(d7927),(d7928),(d7929),(d7930),(d7931),(d7932),(d7933),(d7934),(d7935),(d7936),(d7937),(d7938),(d7939),(d7940),(d7941),(d7942),(d7943),(d7944),(d7945),(d7946),(d7947),(d7948),(d7949),(d7950),(d7951),(d7952),(d7953),(d7954),(d7955),(d7956),(d7957),(d7958),(d7959),(d7960),(d7961),(d7962),(d7963),(d7964),(d7965),(d7966),(d7967),(d7968),(d7969),(d7970),(d7971),(d7972),(d7973),(d7974),(d7975),(d7976),(d7977),(d7978),(d7979),(d7980),(d7981),(d7982),(d7983),(d7984),(d7985),(d7986),(d7987),(d7988),(d7989),(d7990),(d7991),(d7992),(d7993),(d7994),(d7995),(d7996),(d7997),(d7998),(d7999),(d8000),(d8001),(d8002),(d8003),(d8004),(d8005),(d8006),(d8007),(d8008),(d8009),(d8010),(d8011),(d8012),(d8013),(d8014),(d8015),(d8016),(d8017),(d8018),(d8019),(d8020),(d8021),(d8022),(d8023),(d8024),(d8025),(d8026),(d8027),(d8028),(d8029),(d8030),(d8031),(d8032),(d8033),(d8034),(d8035),(d8036),(d8037),(d8038),(d8039),(d8040),(d8041),(d8042),(d8043),(d8044),(d8045),(d8046),(d8047),(d8048),(d8049),(d8050),(d8051),(d8052),(d8053),(d8054),(d8055),(d8056),(d8057),(d8058),(d8059),(d8060),(d8061),(d8062),(d8063),(d8064),(d8065),(d8066),(d8067),(d8068),(d8069),(d8070),(d8071),(d8072),(d8073),(d8074),(d8075),(d8076),(d8077),(d8078),(d8079),(d8080),(d8081),(d8082),(d8083),(d8084),(d8085),(d8086),(d8087),(d8088),(d8089),(d8090),(d8091),(d8092),(d8093),(d8094),(d8095),(d8096),(d8097),(d8098),(d8099),(d8100),(d8101),(d8102),(d8103),(d8104),(d8105),(d8106),(d8107),(d8108),(d8109),(d8110),(d8111),(d8112),(d8113),(d8114),(d8115),(d8116),(d8117),(d8118),(d8119),(d8120),(d8121),(d8122),(d8123),(d8124),(d8125),(d8126),(d8127),(d8128),(d8129),(d8130),(d8131),(d8132),(d8133),(d8134),(d8135),(d8136),(d8137),(d8138),(d8139),(d8140),(d8141),(d8142),(d8143),(d8144),(d8145),(d8146),(d8147),(d8148),(d8149),(d8150),(d8151),(d8152),(d8153),(d8154),(d8155),(d8156),(d8157),(d8158),(d8159),(d8160),(d8161),(d8162),(d8163),(d8164),(d8165),(d8166),(d8167),(d8168),(d8169),(d8170),(d8171),(d8172),(d8173),(d8174),(d8175),(d8176),(d8177),(d8178),(d8179),(d8180),(d8181),(d8182),(d8183),(d8184),(d8185),(d8186),(d8187),(d8188),(d8189),(d8190),(d8191),(d8192),(d8193),(d8194),(d8195),(d8196),(d8197),(d8198),(d8199),(d8200),(d8201),(d8202),(d8203),(d8204),(d8205),(d8206),(d8207),(d8208),(d8209),(d8210),(d8211),(d8212),(d8213),(d8214),(d8215),(d8216),(d8217),(d8218),(d8219),(d8220),(d8221),(d8222),(d8223),(d8224),(d8225),(d8226),(d8227),(d8228),(d8229),(d8230),(d8231),(d8232),(d8233),(d8234),(d8235),(d8236),(d8237),(d8238),(d8239),(d8240),(d8241),(d8242),(d8243),(d8244),(d8245),(d8246),(d8247),(d8248),(d8249),(d8250),(d8251),(d8252),(d8253),(d8254),(d8255),(d8256),(d8257),(d8258),(d8259),(d8260),(d8261),(d8262),(d8263),(d8264),(d8265),(d8266),(d8267),(d8268),(d8269),(d8270),(d8271),(d8272),(d8273),(d8274),(d8275),(d8276),(d8277),(d8278),(d8279),(d8280),(d8281),(d8282),(d8283),(d8284),(d8285),(d8286),(d8287),(d8288),(d8289),(d8290),(d8291),(d8292),(d8293),(d8294),(d8295),(d8296),(d8297),(d8298),(d8299),(d8300),(d8301),(d8302),(d8303),(d8304),(d8305),(d8306),(d8307),(d8308),(d8309),(d8310),(d8311),(d8312),(d8313),(d8314),(d8315),(d8316),(d8317),(d8318),(d8319),(d8320),(d8321),(d8322),(d8323),(d8324),(d8325),(d8326),(d8327),(d8328),(d8329),(d8330),(d8331),(d8332),(d8333),(d8334),(d8335),(d8336),(d8337),(d8338),(d8339),(d8340),(d8341),(d8342),(d8343),(d8344),(d8345),(d8346),(d8347),(d8348),(d8349),(d8350),(d8351),(d8352),(d8353),(d8354),(d8355),(d8356),(d8357),(d8358),(d8359),(d8360),(d8361),(d8362),(d8363),(d8364),(d8365),(d8366),(d8367),(d8368),(d8369),(d8370),(d8371),(d8372),(d8373),(d8374),(d8375),(d8376),(d8377),(d8378),(d8379),(d8380),(d8381),(d8382),(d8383),(d8384),(d8385),(d8386),(d8387),(d8388),(d8389),(d8390),(d8391),(d8392),(d8393),(d8394),(d8395),(d8396),(d8397),(d8398),(d8399),(d8400),(d8401),(d8402),(d8403),(d8404),(d8405),(d8406),(d8407),(d8408),(d8409),(d8410),(d8411),(d8412),(d8413),(d8414),(d8415),(d8416),(d8417),(d8418),(d8419),(d8420),(d8421),(d8422),(d8423),(d8424),(d8425),(d8426),(d8427),(d8428),(d8429),(d8430),(d8431),(d8432),(d8433),(d8434),(d8435),(d8436),(d8437),(d8438),(d8439),(d8440),(d8441),(d8442),(d8443),(d8444),(d8445),(d8446),(d8447),(d8448),(d8449),(d8450),(d8451),(d8452),(d8453),(d8454),(d8455),(d8456),(d8457),(d8458),(d8459),(d8460),(d8461),(d8462),(d8463),(d8464),(d8465),(d8466),(d8467),(d8468),(d8469),(d8470),(d8471),(d8472),(d8473),(d8474),(d8475),(d8476),(d8477),(d8478),(d8479),(d8480),(d8481),(d8482),(d8483),(d8484),(d8485),(d8486),(d8487),(d8488),(d8489),(d8490),(d8491),(d8492),(d8493),(d8494),(d8495),(d8496),(d8497),(d8498),(d8499),(d8500),(d8501),(d8502),(d8503),(d8504),(d8505),(d8506),(d8507),(d8508),(d8509),(d8510),(d8511),(d8512),(d8513),(d8514),(d8515),(d8516),(d8517),(d8518),(d8519),(d8520),(d8521),(d8522),(d8523),(d8524),(d8525),(d8526),(d8527),(d8528),(d8529),(d8530),(d8531),(d8532),(d8533),(d8534),(d8535),(d8536),(d8537),(d8538),(d8539),(d8540),(d8541),(d8542),(d8543),(d8544),(d8545),(d8546),(d8547),(d8548),(d8549),(d8550),(d8551),(d8552),(d8553),(d8554),(d8555),(d8556),(d8557),(d8558),(d8559),(d8560),(d8561),(d8562),(d8563),(d8564),(d8565),(d8566),(d8567),(d8568),(d8569),(d8570),(d8571),(d8572),(d8573),(d8574),(d8575),(d8576),(d8577),(d8578),(d8579),(d8580),(d8581),(d8582),(d8583),(d8584),(d8585),(d8586),(d8587),(d8588),(d8589),(d8590),(d8591),(d8592),(d8593),(d8594),(d8595),(d8596),(d8597),(d8598),(d8599),(d8600),(d8601),(d8602),(d8603),(d8604),(d8605),(d8606),(d8607),(d8608),(d8609),(d8610),(d8611),(d8612),(d8613),(d8614),(d8615),(d8616),(d8617),(d8618),(d8619),(d8620),(d8621),(d8622),(d8623),(d8624),(d8625),(d8626),(d8627),(d8628),(d8629),(d8630),(d8631),(d8632),(d8633),(d8634),(d8635),(d8636),(d8637),(d8638),(d8639),(d8640),(d8641),(d8642),(d8643),(d8644),(d8645),(d8646),(d8647),(d8648),(d8649),(d8650),(d8651),(d8652),(d8653),(d8654),(d8655),(d8656),(d8657),(d8658),(d8659),(d8660),(d8661),(d8662),(d8663),(d8664),(d8665),(d8666),(d8667),(d8668),(d8669),(d8670),(d8671),(d8672),(d8673),(d8674),(d8675),(d8676),(d8677),(d8678),(d8679),(d8680),(d8681),(d8682),(d8683),(d8684),(d8685),(d8686),(d8687),(d8688),(d8689),(d8690),(d8691),(d8692),(d8693),(d8694),(d8695),(d8696),(d8697),(d8698),(d8699),(d8700),(d8701),(d8702),(d8703),(d8704),(d8705),(d8706),(d8707),(d8708),(d8709),(d8710),(d8711),(d8712),(d8713),(d8714),(d8715),(d8716),(d8717),(d8718),(d8719),(d8720),(d8721),(d8722),(d8723),(d8724),(d8725),(d8726),(d8727),(d8728),(d8729),(d8730),(d8731),(d8732),(d8733),(d8734),(d8735),(d8736),(d8737),(d8738),(d8739),(d8740),(d8741),(d8742),(d8743),(d8744),(d8745),(d8746),(d8747),(d8748),(d8749),(d8750),(d8751),(d8752),(d8753),(d8754),(d8755),(d8756),(d8757),(d8758),(d8759),(d8760),(d8761),(d8762),(d8763),(d8764),(d8765),(d8766),(d8767),(d8768),(d8769),(d8770),(d8771),(d8772),(d8773),(d8774),(d8775),(d8776),(d8777),(d8778),(d8779),(d8780),(d8781),(d8782),(d8783),(d8784),(d8785),(d8786),(d8787),(d8788),(d8789),(d8790),(d8791),(d8792),(d8793),(d8794),(d8795),(d8796),(d8797),(d8798),(d8799),(d8800),(d8801),(d8802),(d8803),(d8804),(d8805),(d8806),(d8807),(d8808),(d8809),(d8810),(d8811),(d8812),(d8813),(d8814),(d8815),(d8816),(d8817),(d8818),(d8819),(d8820),(d8821),(d8822),(d8823),(d8824),(d8825),(d8826),(d8827),(d8828),(d8829),(d8830),(d8831),(d8832),(d8833),(d8834),(d8835),(d8836),(d8837),(d8838),(d8839),(d8840),(d8841),(d8842),(d8843),(d8844),(d8845),(d8846),(d8847),(d8848),(d8849),(d8850),(d8851),(d8852),(d8853),(d8854),(d8855),(d8856),(d8857),(d8858),(d8859),(d8860),(d8861),(d8862),(d8863),(d8864),(d8865),(d8866),(d8867),(d8868),(d8869),(d8870),(d8871),(d8872),(d8873),(d8874),(d8875),(d8876),(d8877),(d8878),(d8879),(d8880),(d8881),(d8882),(d8883),(d8884),(d8885),(d8886),(d8887),(d8888),(d8889),(d8890),(d8891),(d8892),(d8893),(d8894),(d8895),(d8896),(d8897),(d8898),(d8899),(d8900),(d8901),(d8902),(d8903),(d8904),(d8905),(d8906),(d8907),(d8908),(d8909),(d8910),(d8911),(d8912),(d8913),(d8914),(d8915),(d8916),(d8917),(d8918),(d8919),(d8920),(d8921),(d8922),(d8923),(d8924),(d8925),(d8926),(d8927),(d8928),(d8929),(d8930),(d8931),(d8932),(d8933),(d8934),(d8935),(d8936),(d8937),(d8938),(d8939),(d8940),(d8941),(d8942),(d8943),(d8944),(d8945),(d8946),(d8947),(d8948),(d8949),(d8950),(d8951),(d8952),(d8953),(d8954),(d8955),(d8956),(d8957),(d8958),(d8959),(d8960),(d8961),(d8962),(d8963),(d8964),(d8965),(d8966),(d8967),(d8968),(d8969),(d8970),(d8971),(d8972),(d8973),(d8974),(d8975),(d8976),(d8977),(d8978),(d8979),(d8980),(d8981),(d8982),(d8983),(d8984),(d8985),(d8986),(d8987),(d8988),(d8989),(d8990),(d8991),(d8992),(d8993),(d8994),(d8995),(d8996),(d8997),(d8998),(d8999),(d9000),(d9001),(d9002),(d9003),(d9004),(d9005),(d9006),(d9007),(d9008),(d9009),(d9010),(d9011),(d9012),(d9013),(d9014),(d9015),(d9016),(d9017),(d9018),(d9019),(d9020),(d9021),(d9022),(d9023),(d9024),(d9025),(d9026),(d9027),(d9028),(d9029),(d9030),(d9031),(d9032),(d9033),(d9034),(d9035),(d9036),(d9037),(d9038),(d9039),(d9040),(d9041),(d9042),(d9043),(d9044),(d9045),(d9046),(d9047),(d9048),(d9049),(d9050),(d9051),(d9052),(d9053),(d9054),(d9055),(d9056),(d9057),(d9058),(d9059),(d9060),(d9061),(d9062),(d9063),(d9064),(d9065),(d9066),(d9067),(d9068),(d9069),(d9070),(d9071),(d9072),(d9073),(d9074),(d9075),(d9076),(d9077),(d9078),(d9079),(d9080),(d9081),(d9082),(d9083),(d9084),(d9085),(d9086),(d9087),(d9088),(d9089),(d9090),(d9091),(d9092),(d9093),(d9094),(d9095),(d9096),(d9097),(d9098),(d9099),(d9100),(d9101),(d9102),(d9103),(d9104),(d9105),(d9106),(d9107),(d9108),(d9109),(d9110),(d9111),(d9112),(d9113),(d9114),(d9115),(d9116),(d9117),(d9118),(d9119),(d9120),(d9121),(d9122),(d9123),(d9124),(d9125),(d9126),(d9127),(d9128),(d9129),(d9130),(d9131),(d9132),(d9133),(d9134),(d9135),(d9136),(d9137),(d9138),(d9139),(d9140),(d9141),(d9142),(d9143),(d9144),(d9145),(d9146),(d9147),(d9148),(d9149),(d9150),(d9151),(d9152),(d9153),(d9154),(d9155),(d9156),(d9157),(d9158),(d9159),(d9160),(d9161),(d9162),(d9163),(d9164),(d9165),(d9166),(d9167),(d9168),(d9169),(d9170),(d9171),(d9172),(d9173),(d9174),(d9175),(d9176),(d9177),(d9178),(d9179),(d9180),(d9181),(d9182),(d9183),(d9184),(d9185),(d9186),(d9187),(d9188),(d9189),(d9190),(d9191),(d9192),(d9193),(d9194),(d9195),(d9196),(d9197),(d9198),(d9199),(d9200),(d9201),(d9202),(d9203),(d9204),(d9205),(d9206),(d9207),(d9208),(d9209),(d9210),(d9211),(d9212),(d9213),(d9214),(d9215),(d9216),(d9217),(d9218),(d9219),(d9220),(d9221),(d9222),(d9223),(d9224),(d9225),(d9226),(d9227),(d9228),(d9229),(d9230),(d9231),(d9232),(d9233),(d9234),(d9235),(d9236),(d9237),(d9238),(d9239),(d9240),(d9241),(d9242),(d9243),(d9244),(d9245),(d9246),(d9247),(d9248),(d9249),(d9250),(d9251),(d9252),(d9253),(d9254),(d9255),(d9256),(d9257),(d9258),(d9259),(d9260),(d9261),(d9262),(d9263),(d9264),(d9265),(d9266),(d9267),(d9268),(d9269),(d9270),(d9271),(d9272),(d9273),(d9274),(d9275),(d9276),(d9277),(d9278),(d9279),(d9280),(d9281),(d9282),(d9283),(d9284),(d9285),(d9286),(d9287),(d9288),(d9289),(d9290),(d9291),(d9292),(d9293),(d9294),(d9295),(d9296),(d9297),(d9298),(d9299),(d9300),(d9301),(d9302),(d9303),(d9304),(d9305),(d9306),(d9307),(d9308),(d9309),(d9310),(d9311),(d9312),(d9313),(d9314),(d9315),(d9316),(d9317),(d9318),(d9319),(d9320),(d9321),(d9322),(d9323),(d9324),(d9325),(d9326),(d9327),(d9328),(d9329),(d9330),(d9331),(d9332),(d9333),(d9334),(d9335),(d9336),(d9337),(d9338),(d9339),(d9340),(d9341),(d9342),(d9343),(d9344),(d9345),(d9346),(d9347),(d9348),(d9349),(d9350),(d9351),(d9352),(d9353),(d9354),(d9355),(d9356),(d9357),(d9358),(d9359),(d9360),(d9361),(d9362),(d9363),(d9364),(d9365),(d9366),(d9367),(d9368),(d9369),(d9370),(d9371),(d9372),(d9373),(d9374),(d9375),(d9376),(d9377),(d9378),(d9379),(d9380),(d9381),(d9382),(d9383),(d9384),(d9385),(d9386),(d9387),(d9388),(d9389),(d9390),(d9391),(d9392),(d9393),(d9394),(d9395),(d9396),(d9397),(d9398),(d9399),(d9400),(d9401),(d9402),(d9403),(d9404),(d9405),(d9406),(d9407),(d9408),(d9409),(d9410),(d9411),(d9412),(d9413),(d9414),(d9415),(d9416),(d9417),(d9418),(d9419),(d9420),(d9421),(d9422),(d9423),(d9424),(d9425),(d9426),(d9427),(d9428),(d9429),(d9430),(d9431),(d9432),(d9433),(d9434),(d9435),(d9436),(d9437),(d9438),(d9439),(d9440),(d9441),(d9442),(d9443),(d9444),(d9445),(d9446),(d9447),(d9448),(d9449),(d9450),(d9451),(d9452),(d9453),(d9454),(d9455),(d9456),(d9457),(d9458),(d9459),(d9460),(d9461),(d9462),(d9463),(d9464),(d9465),(d9466),(d9467),(d9468),(d9469),(d9470),(d9471),(d9472),(d9473),(d9474),(d9475),(d9476),(d9477),(d9478),(d9479),(d9480),(d9481),(d9482),(d9483),(d9484),(d9485),(d9486),(d9487),(d9488),(d9489),(d9490),(d9491),(d9492),(d9493),(d9494),(d9495),(d9496),(d9497),(d9498),(d9499),(d9500),(d9501),(d9502),(d9503),(d9504),(d9505),(d9506),(d9507),(d9508),(d9509),(d9510),(d9511),(d9512),(d9513),(d9514),(d9515),(d9516),(d9517),(d9518),(d9519),(d9520),(d9521),(d9522),(d9523),(d9524),(d9525),(d9526),(d9527),(d9528),(d9529),(d9530),(d9531),(d9532),(d9533),(d9534),(d9535),(d9536),(d9537),(d9538),(d9539),(d9540),(d9541),(d9542),(d9543),(d9544),(d9545),(d9546),(d9547),(d9548),(d9549),(d9550),(d9551),(d9552),(d9553),(d9554),(d9555),(d9556),(d9557),(d9558),(d9559),(d9560),(d9561),(d9562),(d9563),(d9564),(d9565),(d9566),(d9567),(d9568),(d9569),(d9570),(d9571),(d9572),(d9573),(d9574),(d9575),(d9576),(d9577),(d9578),(d9579),(d9580),(d9581),(d9582),(d9583),(d9584),(d9585),(d9586),(d9587),(d9588),(d9589),(d9590),(d9591),(d9592),(d9593),(d9594),(d9595),(d9596),(d9597),(d9598),(d9599),(d9600),(d9601),(d9602),(d9603),(d9604),(d9605),(d9606),(d9607),(d9608),(d9609),(d9610),(d9611),(d9612),(d9613),(d9614),(d9615),(d9616),(d9617),(d9618),(d9619),(d9620),(d9621),(d9622),(d9623),(d9624),(d9625),(d9626),(d9627),(d9628),(d9629),(d9630),(d9631),(d9632),(d9633),(d9634),(d9635),(d9636),(d9637),(d9638),(d9639),(d9640),(d9641),(d9642),(d9643),(d9644),(d9645),(d9646),(d9647),(d9648),(d9649),(d9650),(d9651),(d9652),(d9653),(d9654),(d9655),(d9656),(d9657),(d9658),(d9659),(d9660),(d9661),(d9662),(d9663),(d9664),(d9665),(d9666),(d9667),(d9668),(d9669),(d9670),(d9671),(d9672),(d9673),(d9674),(d9675),(d9676),(d9677),(d9678),(d9679),(d9680),(d9681),(d9682),(d9683),(d9684),(d9685),(d9686),(d9687),(d9688),(d9689),(d9690),(d9691),(d9692),(d9693),(d9694),(d9695),(d9696),(d9697),(d9698),(d9699),(d9700),(d9701),(d9702),(d9703),(d9704),(d9705),(d9706),(d9707),(d9708),(d9709),(d9710),(d9711),(d9712),(d9713),(d9714),(d9715),(d9716),(d9717),(d9718),(d9719),(d9720),(d9721),(d9722),(d9723),(d9724),(d9725),(d9726),(d9727),(d9728),(d9729),(d9730),(d9731),(d9732),(d9733),(d9734),(d9735),(d9736),(d9737),(d9738),(d9739),(d9740),(d9741),(d9742),(d9743),(d9744),(d9745),(d9746),(d9747),(d9748),(d9749),(d9750),(d9751),(d9752),(d9753),(d9754),(d9755),(d9756),(d9757),(d9758),(d9759),(d9760),(d9761),(d9762),(d9763),(d9764),(d9765),(d9766),(d9767),(d9768),(d9769),(d9770),(d9771),(d9772),(d9773),(d9774),(d9775),(d9776),(d9777),(d9778),(d9779),(d9780),(d9781),(d9782),(d9783),(d9784),(d9785),(d9786),(d9787),(d9788),(d9789),(d9790),(d9791),(d9792),(d9793),(d9794),(d9795),(d9796),(d9797),(d9798),(d9799),(d9800),(d9801),(d9802),(d9803),(d9804),(d9805),(d9806),(d9807),(d9808),(d9809),(d9810),(d9811),(d9812),(d9813),(d9814),(d9815),(d9816),(d9817),(d9818),(d9819),(d9820),(d9821),(d9822),(d9823),(d9824),(d9825),(d9826),(d9827),(d9828),(d9829),(d9830),(d9831),(d9832),(d9833),(d9834),(d9835),(d9836),(d9837),(d9838),(d9839),(d9840),(d9841),(d9842),(d9843),(d9844),(d9845),(d9846),(d9847),(d9848),(d9849),(d9850),(d9851),(d9852),(d9853),(d9854),(d9855),(d9856),(d9857),(d9858),(d9859),(d9860),(d9861),(d9862),(d9863),(d9864),(d9865),(d9866),(d9867),(d9868),(d9869),(d9870),(d9871),(d9872),(d9873),(d9874),(d9875),(d9876),(d9877),(d9878),(d9879),(d9880),(d9881),(d9882),(d9883),(d9884),(d9885),(d9886),(d9887),(d9888),(d9889),(d9890),(d9891),(d9892),(d9893),(d9894),(d9895),(d9896),(d9897),(d9898),(d9899),(d9900),(d9901),(d9902),(d9903),(d9904),(d9905),(d9906),(d9907),(d9908),(d9909),(d9910),(d9911),(d9912),(d9913),(d9914),(d9915),(d9916),(d9917),(d9918),(d9919),(d9920),(d9921),(d9922),(d9923),(d9924),(d9925),(d9926),(d9927),(d9928),(d9929),(d9930),(d9931),(d9932),(d9933),(d9934),(d9935),(d9936),(d9937),(d9938),(d9939),(d9940),(d9941),(d9942),(d9943),(d9944),(d9945),(d9946),(d9947),(d9948),(d9949),(d9950),(d9951),(d9952),(d9953),(d9954),(d9955),(d9956),(d9957),(d9958),(d9959),(d9960),(d9961),(d9962),(d9963),(d9964),(d9965),(d9966),(d9967),(d9968),(d9969),(d9970),(d9971),(d9972),(d9973),(d9974),(d9975),(d9976),(d9977),(d9978),(d9979),(d9980),(d9981),(d9982),(d9983),(d9984),(d9985),(d9986),(d9987),(d9988),(d9989),(d9990),(d9991),(d9992),(d9993),(d9994),(d9995),(d9996),(d9997),(d9998)} ] +Root :1 [{(d0)}] +contents: [ [ [d0,d1],[d0,d2],[d2,d3],[d2,d4],[d4,d5],[d4,d6],[d6,d7],[d6,d8],[d8,d9],[d8,d10],[d10,d11],[d10,d12],[d12,d13],[d12,d14],[d14,d15],[d14,d16],[d16,d17],[d16,d18],[d18,d19],[d18,d20],[d20,d21],[d20,d22],[d22,d23],[d22,d24],[d24,d25],[d24,d26],[d26,d27],[d26,d28],[d28,d29],[d28,d30],[d30,d31],[d30,d32],[d32,d33],[d32,d34],[d34,d35],[d34,d36],[d36,d37],[d36,d38],[d38,d39],[d38,d40],[d40,d41],[d40,d42],[d42,d43],[d42,d44],[d44,d45],[d44,d46],[d46,d47],[d46,d48],[d48,d49],[d48,d50],[d50,d51],[d50,d52],[d52,d53],[d52,d54],[d54,d55],[d54,d56],[d56,d57],[d56,d58],[d58,d59],[d58,d60],[d60,d61],[d60,d62],[d62,d63],[d62,d64],[d64,d65],[d64,d66],[d66,d67],[d66,d68],[d68,d69],[d68,d70],[d70,d71],[d70,d72],[d72,d73],[d72,d74],[d74,d75],[d74,d76],[d76,d77],[d76,d78],[d78,d79],[d78,d80],[d80,d81],[d80,d82],[d82,d83],[d82,d84],[d84,d85],[d84,d86],[d86,d87],[d86,d88],[d88,d89],[d88,d90],[d90,d91],[d90,d92],[d92,d93],[d92,d94],[d94,d95],[d94,d96],[d96,d97],[d96,d98],[d98,d99],[d98,d100],[d100,d101],[d100,d102],[d102,d103],[d102,d104],[d104,d105],[d104,d106],[d106,d107],[d106,d108],[d108,d109],[d108,d110],[d110,d111],[d110,d112],[d112,d113],[d112,d114],[d114,d115],[d114,d116],[d116,d117],[d116,d118],[d118,d119],[d118,d120],[d120,d121],[d120,d122],[d122,d123],[d122,d124],[d124,d125],[d124,d126],[d126,d127],[d126,d128],[d128,d129],[d128,d130],[d130,d131],[d130,d132],[d132,d133],[d132,d134],[d134,d135],[d134,d136],[d136,d137],[d136,d138],[d138,d139],[d138,d140],[d140,d141],[d140,d142],[d142,d143],[d142,d144],[d144,d145],[d144,d146],[d146,d147],[d146,d148],[d148,d149],[d148,d150],[d150,d151],[d150,d152],[d152,d153],[d152,d154],[d154,d155],[d154,d156],[d156,d157],[d156,d158],[d158,d159],[d158,d160],[d160,d161],[d160,d162],[d162,d163],[d162,d164],[d164,d165],[d164,d166],[d166,d167],[d166,d168],[d168,d169],[d168,d170],[d170,d171],[d170,d172],[d172,d173],[d172,d174],[d174,d175],[d174,d176],[d176,d177],[d176,d178],[d178,d179],[d178,d180],[d180,d181],[d180,d182],[d182,d183],[d182,d184],[d184,d185],[d184,d186],[d186,d187],[d186,d188],[d188,d189],[d188,d190],[d190,d191],[d190,d192],[d192,d193],[d192,d194],[d194,d195],[d194,d196],[d196,d197],[d196,d198],[d198,d199],[d198,d200],[d200,d201],[d200,d202],[d202,d203],[d202,d204],[d204,d205],[d204,d206],[d206,d207],[d206,d208],[d208,d209],[d208,d210],[d210,d211],[d210,d212],[d212,d213],[d212,d214],[d214,d215],[d214,d216],[d216,d217],[d216,d218],[d218,d219],[d218,d220],[d220,d221],[d220,d222],[d222,d223],[d222,d224],[d224,d225],[d224,d226],[d226,d227],[d226,d228],[d228,d229],[d228,d230],[d230,d231],[d230,d232],[d232,d233],[d232,d234],[d234,d235],[d234,d236],[d236,d237],[d236,d238],[d238,d239],[d238,d240],[d240,d241],[d240,d242],[d242,d243],[d242,d244],[d244,d245],[d244,d246],[d246,d247],[d246,d248],[d248,d249],[d248,d250],[d250,d251],[d250,d252],[d252,d253],[d252,d254],[d254,d255],[d254,d256],[d256,d257],[d256,d258],[d258,d259],[d258,d260],[d260,d261],[d260,d262],[d262,d263],[d262,d264],[d264,d265],[d264,d266],[d266,d267],[d266,d268],[d268,d269],[d268,d270],[d270,d271],[d270,d272],[d272,d273],[d272,d274],[d274,d275],[d274,d276],[d276,d277],[d276,d278],[d278,d279],[d278,d280],[d280,d281],[d280,d282],[d282,d283],[d282,d284],[d284,d285],[d284,d286],[d286,d287],[d286,d288],[d288,d289],[d288,d290],[d290,d291],[d290,d292],[d292,d293],[d292,d294],[d294,d295],[d294,d296],[d296,d297],[d296,d298],[d298,d299],[d298,d300],[d300,d301],[d300,d302],[d302,d303],[d302,d304],[d304,d305],[d304,d306],[d306,d307],[d306,d308],[d308,d309],[d308,d310],[d310,d311],[d310,d312],[d312,d313],[d312,d314],[d314,d315],[d314,d316],[d316,d317],[d316,d318],[d318,d319],[d318,d320],[d320,d321],[d320,d322],[d322,d323],[d322,d324],[d324,d325],[d324,d326],[d326,d327],[d326,d328],[d328,d329],[d328,d330],[d330,d331],[d330,d332],[d332,d333],[d332,d334],[d334,d335],[d334,d336],[d336,d337],[d336,d338],[d338,d339],[d338,d340],[d340,d341],[d340,d342],[d342,d343],[d342,d344],[d344,d345],[d344,d346],[d346,d347],[d346,d348],[d348,d349],[d348,d350],[d350,d351],[d350,d352],[d352,d353],[d352,d354],[d354,d355],[d354,d356],[d356,d357],[d356,d358],[d358,d359],[d358,d360],[d360,d361],[d360,d362],[d362,d363],[d362,d364],[d364,d365],[d364,d366],[d366,d367],[d366,d368],[d368,d369],[d368,d370],[d370,d371],[d370,d372],[d372,d373],[d372,d374],[d374,d375],[d374,d376],[d376,d377],[d376,d378],[d378,d379],[d378,d380],[d380,d381],[d380,d382],[d382,d383],[d382,d384],[d384,d385],[d384,d386],[d386,d387],[d386,d388],[d388,d389],[d388,d390],[d390,d391],[d390,d392],[d392,d393],[d392,d394],[d394,d395],[d394,d396],[d396,d397],[d396,d398],[d398,d399],[d398,d400],[d400,d401],[d400,d402],[d402,d403],[d402,d404],[d404,d405],[d404,d406],[d406,d407],[d406,d408],[d408,d409],[d408,d410],[d410,d411],[d410,d412],[d412,d413],[d412,d414],[d414,d415],[d414,d416],[d416,d417],[d416,d418],[d418,d419],[d418,d420],[d420,d421],[d420,d422],[d422,d423],[d422,d424],[d424,d425],[d424,d426],[d426,d427],[d426,d428],[d428,d429],[d428,d430],[d430,d431],[d430,d432],[d432,d433],[d432,d434],[d434,d435],[d434,d436],[d436,d437],[d436,d438],[d438,d439],[d438,d440],[d440,d441],[d440,d442],[d442,d443],[d442,d444],[d444,d445],[d444,d446],[d446,d447],[d446,d448],[d448,d449],[d448,d450],[d450,d451],[d450,d452],[d452,d453],[d452,d454],[d454,d455],[d454,d456],[d456,d457],[d456,d458],[d458,d459],[d458,d460],[d460,d461],[d460,d462],[d462,d463],[d462,d464],[d464,d465],[d464,d466],[d466,d467],[d466,d468],[d468,d469],[d468,d470],[d470,d471],[d470,d472],[d472,d473],[d472,d474],[d474,d475],[d474,d476],[d476,d477],[d476,d478],[d478,d479],[d478,d480],[d480,d481],[d480,d482],[d482,d483],[d482,d484],[d484,d485],[d484,d486],[d486,d487],[d486,d488],[d488,d489],[d488,d490],[d490,d491],[d490,d492],[d492,d493],[d492,d494],[d494,d495],[d494,d496],[d496,d497],[d496,d498],[d498,d499],[d498,d500],[d500,d501],[d500,d502],[d502,d503],[d502,d504],[d504,d505],[d504,d506],[d506,d507],[d506,d508],[d508,d509],[d508,d510],[d510,d511],[d510,d512],[d512,d513],[d512,d514],[d514,d515],[d514,d516],[d516,d517],[d516,d518],[d518,d519],[d518,d520],[d520,d521],[d520,d522],[d522,d523],[d522,d524],[d524,d525],[d524,d526],[d526,d527],[d526,d528],[d528,d529],[d528,d530],[d530,d531],[d530,d532],[d532,d533],[d532,d534],[d534,d535],[d534,d536],[d536,d537],[d536,d538],[d538,d539],[d538,d540],[d540,d541],[d540,d542],[d542,d543],[d542,d544],[d544,d545],[d544,d546],[d546,d547],[d546,d548],[d548,d549],[d548,d550],[d550,d551],[d550,d552],[d552,d553],[d552,d554],[d554,d555],[d554,d556],[d556,d557],[d556,d558],[d558,d559],[d558,d560],[d560,d561],[d560,d562],[d562,d563],[d562,d564],[d564,d565],[d564,d566],[d566,d567],[d566,d568],[d568,d569],[d568,d570],[d570,d571],[d570,d572],[d572,d573],[d572,d574],[d574,d575],[d574,d576],[d576,d577],[d576,d578],[d578,d579],[d578,d580],[d580,d581],[d580,d582],[d582,d583],[d582,d584],[d584,d585],[d584,d586],[d586,d587],[d586,d588],[d588,d589],[d588,d590],[d590,d591],[d590,d592],[d592,d593],[d592,d594],[d594,d595],[d594,d596],[d596,d597],[d596,d598],[d598,d599],[d598,d600],[d600,d601],[d600,d602],[d602,d603],[d602,d604],[d604,d605],[d604,d606],[d606,d607],[d606,d608],[d608,d609],[d608,d610],[d610,d611],[d610,d612],[d612,d613],[d612,d614],[d614,d615],[d614,d616],[d616,d617],[d616,d618],[d618,d619],[d618,d620],[d620,d621],[d620,d622],[d622,d623],[d622,d624],[d624,d625],[d624,d626],[d626,d627],[d626,d628],[d628,d629],[d628,d630],[d630,d631],[d630,d632],[d632,d633],[d632,d634],[d634,d635],[d634,d636],[d636,d637],[d636,d638],[d638,d639],[d638,d640],[d640,d641],[d640,d642],[d642,d643],[d642,d644],[d644,d645],[d644,d646],[d646,d647],[d646,d648],[d648,d649],[d648,d650],[d650,d651],[d650,d652],[d652,d653],[d652,d654],[d654,d655],[d654,d656],[d656,d657],[d656,d658],[d658,d659],[d658,d660],[d660,d661],[d660,d662],[d662,d663],[d662,d664],[d664,d665],[d664,d666],[d666,d667],[d666,d668],[d668,d669],[d668,d670],[d670,d671],[d670,d672],[d672,d673],[d672,d674],[d674,d675],[d674,d676],[d676,d677],[d676,d678],[d678,d679],[d678,d680],[d680,d681],[d680,d682],[d682,d683],[d682,d684],[d684,d685],[d684,d686],[d686,d687],[d686,d688],[d688,d689],[d688,d690],[d690,d691],[d690,d692],[d692,d693],[d692,d694],[d694,d695],[d694,d696],[d696,d697],[d696,d698],[d698,d699],[d698,d700],[d700,d701],[d700,d702],[d702,d703],[d702,d704],[d704,d705],[d704,d706],[d706,d707],[d706,d708],[d708,d709],[d708,d710],[d710,d711],[d710,d712],[d712,d713],[d712,d714],[d714,d715],[d714,d716],[d716,d717],[d716,d718],[d718,d719],[d718,d720],[d720,d721],[d720,d722],[d722,d723],[d722,d724],[d724,d725],[d724,d726],[d726,d727],[d726,d728],[d728,d729],[d728,d730],[d730,d731],[d730,d732],[d732,d733],[d732,d734],[d734,d735],[d734,d736],[d736,d737],[d736,d738],[d738,d739],[d738,d740],[d740,d741],[d740,d742],[d742,d743],[d742,d744],[d744,d745],[d744,d746],[d746,d747],[d746,d748],[d748,d749],[d748,d750],[d750,d751],[d750,d752],[d752,d753],[d752,d754],[d754,d755],[d754,d756],[d756,d757],[d756,d758],[d758,d759],[d758,d760],[d760,d761],[d760,d762],[d762,d763],[d762,d764],[d764,d765],[d764,d766],[d766,d767],[d766,d768],[d768,d769],[d768,d770],[d770,d771],[d770,d772],[d772,d773],[d772,d774],[d774,d775],[d774,d776],[d776,d777],[d776,d778],[d778,d779],[d778,d780],[d780,d781],[d780,d782],[d782,d783],[d782,d784],[d784,d785],[d784,d786],[d786,d787],[d786,d788],[d788,d789],[d788,d790],[d790,d791],[d790,d792],[d792,d793],[d792,d794],[d794,d795],[d794,d796],[d796,d797],[d796,d798],[d798,d799],[d798,d800],[d800,d801],[d800,d802],[d802,d803],[d802,d804],[d804,d805],[d804,d806],[d806,d807],[d806,d808],[d808,d809],[d808,d810],[d810,d811],[d810,d812],[d812,d813],[d812,d814],[d814,d815],[d814,d816],[d816,d817],[d816,d818],[d818,d819],[d818,d820],[d820,d821],[d820,d822],[d822,d823],[d822,d824],[d824,d825],[d824,d826],[d826,d827],[d826,d828],[d828,d829],[d828,d830],[d830,d831],[d830,d832],[d832,d833],[d832,d834],[d834,d835],[d834,d836],[d836,d837],[d836,d838],[d838,d839],[d838,d840],[d840,d841],[d840,d842],[d842,d843],[d842,d844],[d844,d845],[d844,d846],[d846,d847],[d846,d848],[d848,d849],[d848,d850],[d850,d851],[d850,d852],[d852,d853],[d852,d854],[d854,d855],[d854,d856],[d856,d857],[d856,d858],[d858,d859],[d858,d860],[d860,d861],[d860,d862],[d862,d863],[d862,d864],[d864,d865],[d864,d866],[d866,d867],[d866,d868],[d868,d869],[d868,d870],[d870,d871],[d870,d872],[d872,d873],[d872,d874],[d874,d875],[d874,d876],[d876,d877],[d876,d878],[d878,d879],[d878,d880],[d880,d881],[d880,d882],[d882,d883],[d882,d884],[d884,d885],[d884,d886],[d886,d887],[d886,d888],[d888,d889],[d888,d890],[d890,d891],[d890,d892],[d892,d893],[d892,d894],[d894,d895],[d894,d896],[d896,d897],[d896,d898],[d898,d899],[d898,d900],[d900,d901],[d900,d902],[d902,d903],[d902,d904],[d904,d905],[d904,d906],[d906,d907],[d906,d908],[d908,d909],[d908,d910],[d910,d911],[d910,d912],[d912,d913],[d912,d914],[d914,d915],[d914,d916],[d916,d917],[d916,d918],[d918,d919],[d918,d920],[d920,d921],[d920,d922],[d922,d923],[d922,d924],[d924,d925],[d924,d926],[d926,d927],[d926,d928],[d928,d929],[d928,d930],[d930,d931],[d930,d932],[d932,d933],[d932,d934],[d934,d935],[d934,d936],[d936,d937],[d936,d938],[d938,d939],[d938,d940],[d940,d941],[d940,d942],[d942,d943],[d942,d944],[d944,d945],[d944,d946],[d946,d947],[d946,d948],[d948,d949],[d948,d950],[d950,d951],[d950,d952],[d952,d953],[d952,d954],[d954,d955],[d954,d956],[d956,d957],[d956,d958],[d958,d959],[d958,d960],[d960,d961],[d960,d962],[d962,d963],[d962,d964],[d964,d965],[d964,d966],[d966,d967],[d966,d968],[d968,d969],[d968,d970],[d970,d971],[d970,d972],[d972,d973],[d972,d974],[d974,d975],[d974,d976],[d976,d977],[d976,d978],[d978,d979],[d978,d980],[d980,d981],[d980,d982],[d982,d983],[d982,d984],[d984,d985],[d984,d986],[d986,d987],[d986,d988],[d988,d989],[d988,d990],[d990,d991],[d990,d992],[d992,d993],[d992,d994],[d994,d995],[d994,d996],[d996,d997],[d996,d998],[d998,d999],[d998,d1000],[d1000,d1001],[d1000,d1002],[d1002,d1003],[d1002,d1004],[d1004,d1005],[d1004,d1006],[d1006,d1007],[d1006,d1008],[d1008,d1009],[d1008,d1010],[d1010,d1011],[d1010,d1012],[d1012,d1013],[d1012,d1014],[d1014,d1015],[d1014,d1016],[d1016,d1017],[d1016,d1018],[d1018,d1019],[d1018,d1020],[d1020,d1021],[d1020,d1022],[d1022,d1023],[d1022,d1024],[d1024,d1025],[d1024,d1026],[d1026,d1027],[d1026,d1028],[d1028,d1029],[d1028,d1030],[d1030,d1031],[d1030,d1032],[d1032,d1033],[d1032,d1034],[d1034,d1035],[d1034,d1036],[d1036,d1037],[d1036,d1038],[d1038,d1039],[d1038,d1040],[d1040,d1041],[d1040,d1042],[d1042,d1043],[d1042,d1044],[d1044,d1045],[d1044,d1046],[d1046,d1047],[d1046,d1048],[d1048,d1049],[d1048,d1050],[d1050,d1051],[d1050,d1052],[d1052,d1053],[d1052,d1054],[d1054,d1055],[d1054,d1056],[d1056,d1057],[d1056,d1058],[d1058,d1059],[d1058,d1060],[d1060,d1061],[d1060,d1062],[d1062,d1063],[d1062,d1064],[d1064,d1065],[d1064,d1066],[d1066,d1067],[d1066,d1068],[d1068,d1069],[d1068,d1070],[d1070,d1071],[d1070,d1072],[d1072,d1073],[d1072,d1074],[d1074,d1075],[d1074,d1076],[d1076,d1077],[d1076,d1078],[d1078,d1079],[d1078,d1080],[d1080,d1081],[d1080,d1082],[d1082,d1083],[d1082,d1084],[d1084,d1085],[d1084,d1086],[d1086,d1087],[d1086,d1088],[d1088,d1089],[d1088,d1090],[d1090,d1091],[d1090,d1092],[d1092,d1093],[d1092,d1094],[d1094,d1095],[d1094,d1096],[d1096,d1097],[d1096,d1098],[d1098,d1099],[d1098,d1100],[d1100,d1101],[d1100,d1102],[d1102,d1103],[d1102,d1104],[d1104,d1105],[d1104,d1106],[d1106,d1107],[d1106,d1108],[d1108,d1109],[d1108,d1110],[d1110,d1111],[d1110,d1112],[d1112,d1113],[d1112,d1114],[d1114,d1115],[d1114,d1116],[d1116,d1117],[d1116,d1118],[d1118,d1119],[d1118,d1120],[d1120,d1121],[d1120,d1122],[d1122,d1123],[d1122,d1124],[d1124,d1125],[d1124,d1126],[d1126,d1127],[d1126,d1128],[d1128,d1129],[d1128,d1130],[d1130,d1131],[d1130,d1132],[d1132,d1133],[d1132,d1134],[d1134,d1135],[d1134,d1136],[d1136,d1137],[d1136,d1138],[d1138,d1139],[d1138,d1140],[d1140,d1141],[d1140,d1142],[d1142,d1143],[d1142,d1144],[d1144,d1145],[d1144,d1146],[d1146,d1147],[d1146,d1148],[d1148,d1149],[d1148,d1150],[d1150,d1151],[d1150,d1152],[d1152,d1153],[d1152,d1154],[d1154,d1155],[d1154,d1156],[d1156,d1157],[d1156,d1158],[d1158,d1159],[d1158,d1160],[d1160,d1161],[d1160,d1162],[d1162,d1163],[d1162,d1164],[d1164,d1165],[d1164,d1166],[d1166,d1167],[d1166,d1168],[d1168,d1169],[d1168,d1170],[d1170,d1171],[d1170,d1172],[d1172,d1173],[d1172,d1174],[d1174,d1175],[d1174,d1176],[d1176,d1177],[d1176,d1178],[d1178,d1179],[d1178,d1180],[d1180,d1181],[d1180,d1182],[d1182,d1183],[d1182,d1184],[d1184,d1185],[d1184,d1186],[d1186,d1187],[d1186,d1188],[d1188,d1189],[d1188,d1190],[d1190,d1191],[d1190,d1192],[d1192,d1193],[d1192,d1194],[d1194,d1195],[d1194,d1196],[d1196,d1197],[d1196,d1198],[d1198,d1199],[d1198,d1200],[d1200,d1201],[d1200,d1202],[d1202,d1203],[d1202,d1204],[d1204,d1205],[d1204,d1206],[d1206,d1207],[d1206,d1208],[d1208,d1209],[d1208,d1210],[d1210,d1211],[d1210,d1212],[d1212,d1213],[d1212,d1214],[d1214,d1215],[d1214,d1216],[d1216,d1217],[d1216,d1218],[d1218,d1219],[d1218,d1220],[d1220,d1221],[d1220,d1222],[d1222,d1223],[d1222,d1224],[d1224,d1225],[d1224,d1226],[d1226,d1227],[d1226,d1228],[d1228,d1229],[d1228,d1230],[d1230,d1231],[d1230,d1232],[d1232,d1233],[d1232,d1234],[d1234,d1235],[d1234,d1236],[d1236,d1237],[d1236,d1238],[d1238,d1239],[d1238,d1240],[d1240,d1241],[d1240,d1242],[d1242,d1243],[d1242,d1244],[d1244,d1245],[d1244,d1246],[d1246,d1247],[d1246,d1248],[d1248,d1249],[d1248,d1250],[d1250,d1251],[d1250,d1252],[d1252,d1253],[d1252,d1254],[d1254,d1255],[d1254,d1256],[d1256,d1257],[d1256,d1258],[d1258,d1259],[d1258,d1260],[d1260,d1261],[d1260,d1262],[d1262,d1263],[d1262,d1264],[d1264,d1265],[d1264,d1266],[d1266,d1267],[d1266,d1268],[d1268,d1269],[d1268,d1270],[d1270,d1271],[d1270,d1272],[d1272,d1273],[d1272,d1274],[d1274,d1275],[d1274,d1276],[d1276,d1277],[d1276,d1278],[d1278,d1279],[d1278,d1280],[d1280,d1281],[d1280,d1282],[d1282,d1283],[d1282,d1284],[d1284,d1285],[d1284,d1286],[d1286,d1287],[d1286,d1288],[d1288,d1289],[d1288,d1290],[d1290,d1291],[d1290,d1292],[d1292,d1293],[d1292,d1294],[d1294,d1295],[d1294,d1296],[d1296,d1297],[d1296,d1298],[d1298,d1299],[d1298,d1300],[d1300,d1301],[d1300,d1302],[d1302,d1303],[d1302,d1304],[d1304,d1305],[d1304,d1306],[d1306,d1307],[d1306,d1308],[d1308,d1309],[d1308,d1310],[d1310,d1311],[d1310,d1312],[d1312,d1313],[d1312,d1314],[d1314,d1315],[d1314,d1316],[d1316,d1317],[d1316,d1318],[d1318,d1319],[d1318,d1320],[d1320,d1321],[d1320,d1322],[d1322,d1323],[d1322,d1324],[d1324,d1325],[d1324,d1326],[d1326,d1327],[d1326,d1328],[d1328,d1329],[d1328,d1330],[d1330,d1331],[d1330,d1332],[d1332,d1333],[d1332,d1334],[d1334,d1335],[d1334,d1336],[d1336,d1337],[d1336,d1338],[d1338,d1339],[d1338,d1340],[d1340,d1341],[d1340,d1342],[d1342,d1343],[d1342,d1344],[d1344,d1345],[d1344,d1346],[d1346,d1347],[d1346,d1348],[d1348,d1349],[d1348,d1350],[d1350,d1351],[d1350,d1352],[d1352,d1353],[d1352,d1354],[d1354,d1355],[d1354,d1356],[d1356,d1357],[d1356,d1358],[d1358,d1359],[d1358,d1360],[d1360,d1361],[d1360,d1362],[d1362,d1363],[d1362,d1364],[d1364,d1365],[d1364,d1366],[d1366,d1367],[d1366,d1368],[d1368,d1369],[d1368,d1370],[d1370,d1371],[d1370,d1372],[d1372,d1373],[d1372,d1374],[d1374,d1375],[d1374,d1376],[d1376,d1377],[d1376,d1378],[d1378,d1379],[d1378,d1380],[d1380,d1381],[d1380,d1382],[d1382,d1383],[d1382,d1384],[d1384,d1385],[d1384,d1386],[d1386,d1387],[d1386,d1388],[d1388,d1389],[d1388,d1390],[d1390,d1391],[d1390,d1392],[d1392,d1393],[d1392,d1394],[d1394,d1395],[d1394,d1396],[d1396,d1397],[d1396,d1398],[d1398,d1399],[d1398,d1400],[d1400,d1401],[d1400,d1402],[d1402,d1403],[d1402,d1404],[d1404,d1405],[d1404,d1406],[d1406,d1407],[d1406,d1408],[d1408,d1409],[d1408,d1410],[d1410,d1411],[d1410,d1412],[d1412,d1413],[d1412,d1414],[d1414,d1415],[d1414,d1416],[d1416,d1417],[d1416,d1418],[d1418,d1419],[d1418,d1420],[d1420,d1421],[d1420,d1422],[d1422,d1423],[d1422,d1424],[d1424,d1425],[d1424,d1426],[d1426,d1427],[d1426,d1428],[d1428,d1429],[d1428,d1430],[d1430,d1431],[d1430,d1432],[d1432,d1433],[d1432,d1434],[d1434,d1435],[d1434,d1436],[d1436,d1437],[d1436,d1438],[d1438,d1439],[d1438,d1440],[d1440,d1441],[d1440,d1442],[d1442,d1443],[d1442,d1444],[d1444,d1445],[d1444,d1446],[d1446,d1447],[d1446,d1448],[d1448,d1449],[d1448,d1450],[d1450,d1451],[d1450,d1452],[d1452,d1453],[d1452,d1454],[d1454,d1455],[d1454,d1456],[d1456,d1457],[d1456,d1458],[d1458,d1459],[d1458,d1460],[d1460,d1461],[d1460,d1462],[d1462,d1463],[d1462,d1464],[d1464,d1465],[d1464,d1466],[d1466,d1467],[d1466,d1468],[d1468,d1469],[d1468,d1470],[d1470,d1471],[d1470,d1472],[d1472,d1473],[d1472,d1474],[d1474,d1475],[d1474,d1476],[d1476,d1477],[d1476,d1478],[d1478,d1479],[d1478,d1480],[d1480,d1481],[d1480,d1482],[d1482,d1483],[d1482,d1484],[d1484,d1485],[d1484,d1486],[d1486,d1487],[d1486,d1488],[d1488,d1489],[d1488,d1490],[d1490,d1491],[d1490,d1492],[d1492,d1493],[d1492,d1494],[d1494,d1495],[d1494,d1496],[d1496,d1497],[d1496,d1498],[d1498,d1499],[d1498,d1500],[d1500,d1501],[d1500,d1502],[d1502,d1503],[d1502,d1504],[d1504,d1505],[d1504,d1506],[d1506,d1507],[d1506,d1508],[d1508,d1509],[d1508,d1510],[d1510,d1511],[d1510,d1512],[d1512,d1513],[d1512,d1514],[d1514,d1515],[d1514,d1516],[d1516,d1517],[d1516,d1518],[d1518,d1519],[d1518,d1520],[d1520,d1521],[d1520,d1522],[d1522,d1523],[d1522,d1524],[d1524,d1525],[d1524,d1526],[d1526,d1527],[d1526,d1528],[d1528,d1529],[d1528,d1530],[d1530,d1531],[d1530,d1532],[d1532,d1533],[d1532,d1534],[d1534,d1535],[d1534,d1536],[d1536,d1537],[d1536,d1538],[d1538,d1539],[d1538,d1540],[d1540,d1541],[d1540,d1542],[d1542,d1543],[d1542,d1544],[d1544,d1545],[d1544,d1546],[d1546,d1547],[d1546,d1548],[d1548,d1549],[d1548,d1550],[d1550,d1551],[d1550,d1552],[d1552,d1553],[d1552,d1554],[d1554,d1555],[d1554,d1556],[d1556,d1557],[d1556,d1558],[d1558,d1559],[d1558,d1560],[d1560,d1561],[d1560,d1562],[d1562,d1563],[d1562,d1564],[d1564,d1565],[d1564,d1566],[d1566,d1567],[d1566,d1568],[d1568,d1569],[d1568,d1570],[d1570,d1571],[d1570,d1572],[d1572,d1573],[d1572,d1574],[d1574,d1575],[d1574,d1576],[d1576,d1577],[d1576,d1578],[d1578,d1579],[d1578,d1580],[d1580,d1581],[d1580,d1582],[d1582,d1583],[d1582,d1584],[d1584,d1585],[d1584,d1586],[d1586,d1587],[d1586,d1588],[d1588,d1589],[d1588,d1590],[d1590,d1591],[d1590,d1592],[d1592,d1593],[d1592,d1594],[d1594,d1595],[d1594,d1596],[d1596,d1597],[d1596,d1598],[d1598,d1599],[d1598,d1600],[d1600,d1601],[d1600,d1602],[d1602,d1603],[d1602,d1604],[d1604,d1605],[d1604,d1606],[d1606,d1607],[d1606,d1608],[d1608,d1609],[d1608,d1610],[d1610,d1611],[d1610,d1612],[d1612,d1613],[d1612,d1614],[d1614,d1615],[d1614,d1616],[d1616,d1617],[d1616,d1618],[d1618,d1619],[d1618,d1620],[d1620,d1621],[d1620,d1622],[d1622,d1623],[d1622,d1624],[d1624,d1625],[d1624,d1626],[d1626,d1627],[d1626,d1628],[d1628,d1629],[d1628,d1630],[d1630,d1631],[d1630,d1632],[d1632,d1633],[d1632,d1634],[d1634,d1635],[d1634,d1636],[d1636,d1637],[d1636,d1638],[d1638,d1639],[d1638,d1640],[d1640,d1641],[d1640,d1642],[d1642,d1643],[d1642,d1644],[d1644,d1645],[d1644,d1646],[d1646,d1647],[d1646,d1648],[d1648,d1649],[d1648,d1650],[d1650,d1651],[d1650,d1652],[d1652,d1653],[d1652,d1654],[d1654,d1655],[d1654,d1656],[d1656,d1657],[d1656,d1658],[d1658,d1659],[d1658,d1660],[d1660,d1661],[d1660,d1662],[d1662,d1663],[d1662,d1664],[d1664,d1665],[d1664,d1666],[d1666,d1667],[d1666,d1668],[d1668,d1669],[d1668,d1670],[d1670,d1671],[d1670,d1672],[d1672,d1673],[d1672,d1674],[d1674,d1675],[d1674,d1676],[d1676,d1677],[d1676,d1678],[d1678,d1679],[d1678,d1680],[d1680,d1681],[d1680,d1682],[d1682,d1683],[d1682,d1684],[d1684,d1685],[d1684,d1686],[d1686,d1687],[d1686,d1688],[d1688,d1689],[d1688,d1690],[d1690,d1691],[d1690,d1692],[d1692,d1693],[d1692,d1694],[d1694,d1695],[d1694,d1696],[d1696,d1697],[d1696,d1698],[d1698,d1699],[d1698,d1700],[d1700,d1701],[d1700,d1702],[d1702,d1703],[d1702,d1704],[d1704,d1705],[d1704,d1706],[d1706,d1707],[d1706,d1708],[d1708,d1709],[d1708,d1710],[d1710,d1711],[d1710,d1712],[d1712,d1713],[d1712,d1714],[d1714,d1715],[d1714,d1716],[d1716,d1717],[d1716,d1718],[d1718,d1719],[d1718,d1720],[d1720,d1721],[d1720,d1722],[d1722,d1723],[d1722,d1724],[d1724,d1725],[d1724,d1726],[d1726,d1727],[d1726,d1728],[d1728,d1729],[d1728,d1730],[d1730,d1731],[d1730,d1732],[d1732,d1733],[d1732,d1734],[d1734,d1735],[d1734,d1736],[d1736,d1737],[d1736,d1738],[d1738,d1739],[d1738,d1740],[d1740,d1741],[d1740,d1742],[d1742,d1743],[d1742,d1744],[d1744,d1745],[d1744,d1746],[d1746,d1747],[d1746,d1748],[d1748,d1749],[d1748,d1750],[d1750,d1751],[d1750,d1752],[d1752,d1753],[d1752,d1754],[d1754,d1755],[d1754,d1756],[d1756,d1757],[d1756,d1758],[d1758,d1759],[d1758,d1760],[d1760,d1761],[d1760,d1762],[d1762,d1763],[d1762,d1764],[d1764,d1765],[d1764,d1766],[d1766,d1767],[d1766,d1768],[d1768,d1769],[d1768,d1770],[d1770,d1771],[d1770,d1772],[d1772,d1773],[d1772,d1774],[d1774,d1775],[d1774,d1776],[d1776,d1777],[d1776,d1778],[d1778,d1779],[d1778,d1780],[d1780,d1781],[d1780,d1782],[d1782,d1783],[d1782,d1784],[d1784,d1785],[d1784,d1786],[d1786,d1787],[d1786,d1788],[d1788,d1789],[d1788,d1790],[d1790,d1791],[d1790,d1792],[d1792,d1793],[d1792,d1794],[d1794,d1795],[d1794,d1796],[d1796,d1797],[d1796,d1798],[d1798,d1799],[d1798,d1800],[d1800,d1801],[d1800,d1802],[d1802,d1803],[d1802,d1804],[d1804,d1805],[d1804,d1806],[d1806,d1807],[d1806,d1808],[d1808,d1809],[d1808,d1810],[d1810,d1811],[d1810,d1812],[d1812,d1813],[d1812,d1814],[d1814,d1815],[d1814,d1816],[d1816,d1817],[d1816,d1818],[d1818,d1819],[d1818,d1820],[d1820,d1821],[d1820,d1822],[d1822,d1823],[d1822,d1824],[d1824,d1825],[d1824,d1826],[d1826,d1827],[d1826,d1828],[d1828,d1829],[d1828,d1830],[d1830,d1831],[d1830,d1832],[d1832,d1833],[d1832,d1834],[d1834,d1835],[d1834,d1836],[d1836,d1837],[d1836,d1838],[d1838,d1839],[d1838,d1840],[d1840,d1841],[d1840,d1842],[d1842,d1843],[d1842,d1844],[d1844,d1845],[d1844,d1846],[d1846,d1847],[d1846,d1848],[d1848,d1849],[d1848,d1850],[d1850,d1851],[d1850,d1852],[d1852,d1853],[d1852,d1854],[d1854,d1855],[d1854,d1856],[d1856,d1857],[d1856,d1858],[d1858,d1859],[d1858,d1860],[d1860,d1861],[d1860,d1862],[d1862,d1863],[d1862,d1864],[d1864,d1865],[d1864,d1866],[d1866,d1867],[d1866,d1868],[d1868,d1869],[d1868,d1870],[d1870,d1871],[d1870,d1872],[d1872,d1873],[d1872,d1874],[d1874,d1875],[d1874,d1876],[d1876,d1877],[d1876,d1878],[d1878,d1879],[d1878,d1880],[d1880,d1881],[d1880,d1882],[d1882,d1883],[d1882,d1884],[d1884,d1885],[d1884,d1886],[d1886,d1887],[d1886,d1888],[d1888,d1889],[d1888,d1890],[d1890,d1891],[d1890,d1892],[d1892,d1893],[d1892,d1894],[d1894,d1895],[d1894,d1896],[d1896,d1897],[d1896,d1898],[d1898,d1899],[d1898,d1900],[d1900,d1901],[d1900,d1902],[d1902,d1903],[d1902,d1904],[d1904,d1905],[d1904,d1906],[d1906,d1907],[d1906,d1908],[d1908,d1909],[d1908,d1910],[d1910,d1911],[d1910,d1912],[d1912,d1913],[d1912,d1914],[d1914,d1915],[d1914,d1916],[d1916,d1917],[d1916,d1918],[d1918,d1919],[d1918,d1920],[d1920,d1921],[d1920,d1922],[d1922,d1923],[d1922,d1924],[d1924,d1925],[d1924,d1926],[d1926,d1927],[d1926,d1928],[d1928,d1929],[d1928,d1930],[d1930,d1931],[d1930,d1932],[d1932,d1933],[d1932,d1934],[d1934,d1935],[d1934,d1936],[d1936,d1937],[d1936,d1938],[d1938,d1939],[d1938,d1940],[d1940,d1941],[d1940,d1942],[d1942,d1943],[d1942,d1944],[d1944,d1945],[d1944,d1946],[d1946,d1947],[d1946,d1948],[d1948,d1949],[d1948,d1950],[d1950,d1951],[d1950,d1952],[d1952,d1953],[d1952,d1954],[d1954,d1955],[d1954,d1956],[d1956,d1957],[d1956,d1958],[d1958,d1959],[d1958,d1960],[d1960,d1961],[d1960,d1962],[d1962,d1963],[d1962,d1964],[d1964,d1965],[d1964,d1966],[d1966,d1967],[d1966,d1968],[d1968,d1969],[d1968,d1970],[d1970,d1971],[d1970,d1972],[d1972,d1973],[d1972,d1974],[d1974,d1975],[d1974,d1976],[d1976,d1977],[d1976,d1978],[d1978,d1979],[d1978,d1980],[d1980,d1981],[d1980,d1982],[d1982,d1983],[d1982,d1984],[d1984,d1985],[d1984,d1986],[d1986,d1987],[d1986,d1988],[d1988,d1989],[d1988,d1990],[d1990,d1991],[d1990,d1992],[d1992,d1993],[d1992,d1994],[d1994,d1995],[d1994,d1996],[d1996,d1997],[d1996,d1998],[d1998,d1999],[d1998,d2000],[d2000,d2001],[d2000,d2002],[d2002,d2003],[d2002,d2004],[d2004,d2005],[d2004,d2006],[d2006,d2007],[d2006,d2008],[d2008,d2009],[d2008,d2010],[d2010,d2011],[d2010,d2012],[d2012,d2013],[d2012,d2014],[d2014,d2015],[d2014,d2016],[d2016,d2017],[d2016,d2018],[d2018,d2019],[d2018,d2020],[d2020,d2021],[d2020,d2022],[d2022,d2023],[d2022,d2024],[d2024,d2025],[d2024,d2026],[d2026,d2027],[d2026,d2028],[d2028,d2029],[d2028,d2030],[d2030,d2031],[d2030,d2032],[d2032,d2033],[d2032,d2034],[d2034,d2035],[d2034,d2036],[d2036,d2037],[d2036,d2038],[d2038,d2039],[d2038,d2040],[d2040,d2041],[d2040,d2042],[d2042,d2043],[d2042,d2044],[d2044,d2045],[d2044,d2046],[d2046,d2047],[d2046,d2048],[d2048,d2049],[d2048,d2050],[d2050,d2051],[d2050,d2052],[d2052,d2053],[d2052,d2054],[d2054,d2055],[d2054,d2056],[d2056,d2057],[d2056,d2058],[d2058,d2059],[d2058,d2060],[d2060,d2061],[d2060,d2062],[d2062,d2063],[d2062,d2064],[d2064,d2065],[d2064,d2066],[d2066,d2067],[d2066,d2068],[d2068,d2069],[d2068,d2070],[d2070,d2071],[d2070,d2072],[d2072,d2073],[d2072,d2074],[d2074,d2075],[d2074,d2076],[d2076,d2077],[d2076,d2078],[d2078,d2079],[d2078,d2080],[d2080,d2081],[d2080,d2082],[d2082,d2083],[d2082,d2084],[d2084,d2085],[d2084,d2086],[d2086,d2087],[d2086,d2088],[d2088,d2089],[d2088,d2090],[d2090,d2091],[d2090,d2092],[d2092,d2093],[d2092,d2094],[d2094,d2095],[d2094,d2096],[d2096,d2097],[d2096,d2098],[d2098,d2099],[d2098,d2100],[d2100,d2101],[d2100,d2102],[d2102,d2103],[d2102,d2104],[d2104,d2105],[d2104,d2106],[d2106,d2107],[d2106,d2108],[d2108,d2109],[d2108,d2110],[d2110,d2111],[d2110,d2112],[d2112,d2113],[d2112,d2114],[d2114,d2115],[d2114,d2116],[d2116,d2117],[d2116,d2118],[d2118,d2119],[d2118,d2120],[d2120,d2121],[d2120,d2122],[d2122,d2123],[d2122,d2124],[d2124,d2125],[d2124,d2126],[d2126,d2127],[d2126,d2128],[d2128,d2129],[d2128,d2130],[d2130,d2131],[d2130,d2132],[d2132,d2133],[d2132,d2134],[d2134,d2135],[d2134,d2136],[d2136,d2137],[d2136,d2138],[d2138,d2139],[d2138,d2140],[d2140,d2141],[d2140,d2142],[d2142,d2143],[d2142,d2144],[d2144,d2145],[d2144,d2146],[d2146,d2147],[d2146,d2148],[d2148,d2149],[d2148,d2150],[d2150,d2151],[d2150,d2152],[d2152,d2153],[d2152,d2154],[d2154,d2155],[d2154,d2156],[d2156,d2157],[d2156,d2158],[d2158,d2159],[d2158,d2160],[d2160,d2161],[d2160,d2162],[d2162,d2163],[d2162,d2164],[d2164,d2165],[d2164,d2166],[d2166,d2167],[d2166,d2168],[d2168,d2169],[d2168,d2170],[d2170,d2171],[d2170,d2172],[d2172,d2173],[d2172,d2174],[d2174,d2175],[d2174,d2176],[d2176,d2177],[d2176,d2178],[d2178,d2179],[d2178,d2180],[d2180,d2181],[d2180,d2182],[d2182,d2183],[d2182,d2184],[d2184,d2185],[d2184,d2186],[d2186,d2187],[d2186,d2188],[d2188,d2189],[d2188,d2190],[d2190,d2191],[d2190,d2192],[d2192,d2193],[d2192,d2194],[d2194,d2195],[d2194,d2196],[d2196,d2197],[d2196,d2198],[d2198,d2199],[d2198,d2200],[d2200,d2201],[d2200,d2202],[d2202,d2203],[d2202,d2204],[d2204,d2205],[d2204,d2206],[d2206,d2207],[d2206,d2208],[d2208,d2209],[d2208,d2210],[d2210,d2211],[d2210,d2212],[d2212,d2213],[d2212,d2214],[d2214,d2215],[d2214,d2216],[d2216,d2217],[d2216,d2218],[d2218,d2219],[d2218,d2220],[d2220,d2221],[d2220,d2222],[d2222,d2223],[d2222,d2224],[d2224,d2225],[d2224,d2226],[d2226,d2227],[d2226,d2228],[d2228,d2229],[d2228,d2230],[d2230,d2231],[d2230,d2232],[d2232,d2233],[d2232,d2234],[d2234,d2235],[d2234,d2236],[d2236,d2237],[d2236,d2238],[d2238,d2239],[d2238,d2240],[d2240,d2241],[d2240,d2242],[d2242,d2243],[d2242,d2244],[d2244,d2245],[d2244,d2246],[d2246,d2247],[d2246,d2248],[d2248,d2249],[d2248,d2250],[d2250,d2251],[d2250,d2252],[d2252,d2253],[d2252,d2254],[d2254,d2255],[d2254,d2256],[d2256,d2257],[d2256,d2258],[d2258,d2259],[d2258,d2260],[d2260,d2261],[d2260,d2262],[d2262,d2263],[d2262,d2264],[d2264,d2265],[d2264,d2266],[d2266,d2267],[d2266,d2268],[d2268,d2269],[d2268,d2270],[d2270,d2271],[d2270,d2272],[d2272,d2273],[d2272,d2274],[d2274,d2275],[d2274,d2276],[d2276,d2277],[d2276,d2278],[d2278,d2279],[d2278,d2280],[d2280,d2281],[d2280,d2282],[d2282,d2283],[d2282,d2284],[d2284,d2285],[d2284,d2286],[d2286,d2287],[d2286,d2288],[d2288,d2289],[d2288,d2290],[d2290,d2291],[d2290,d2292],[d2292,d2293],[d2292,d2294],[d2294,d2295],[d2294,d2296],[d2296,d2297],[d2296,d2298],[d2298,d2299],[d2298,d2300],[d2300,d2301],[d2300,d2302],[d2302,d2303],[d2302,d2304],[d2304,d2305],[d2304,d2306],[d2306,d2307],[d2306,d2308],[d2308,d2309],[d2308,d2310],[d2310,d2311],[d2310,d2312],[d2312,d2313],[d2312,d2314],[d2314,d2315],[d2314,d2316],[d2316,d2317],[d2316,d2318],[d2318,d2319],[d2318,d2320],[d2320,d2321],[d2320,d2322],[d2322,d2323],[d2322,d2324],[d2324,d2325],[d2324,d2326],[d2326,d2327],[d2326,d2328],[d2328,d2329],[d2328,d2330],[d2330,d2331],[d2330,d2332],[d2332,d2333],[d2332,d2334],[d2334,d2335],[d2334,d2336],[d2336,d2337],[d2336,d2338],[d2338,d2339],[d2338,d2340],[d2340,d2341],[d2340,d2342],[d2342,d2343],[d2342,d2344],[d2344,d2345],[d2344,d2346],[d2346,d2347],[d2346,d2348],[d2348,d2349],[d2348,d2350],[d2350,d2351],[d2350,d2352],[d2352,d2353],[d2352,d2354],[d2354,d2355],[d2354,d2356],[d2356,d2357],[d2356,d2358],[d2358,d2359],[d2358,d2360],[d2360,d2361],[d2360,d2362],[d2362,d2363],[d2362,d2364],[d2364,d2365],[d2364,d2366],[d2366,d2367],[d2366,d2368],[d2368,d2369],[d2368,d2370],[d2370,d2371],[d2370,d2372],[d2372,d2373],[d2372,d2374],[d2374,d2375],[d2374,d2376],[d2376,d2377],[d2376,d2378],[d2378,d2379],[d2378,d2380],[d2380,d2381],[d2380,d2382],[d2382,d2383],[d2382,d2384],[d2384,d2385],[d2384,d2386],[d2386,d2387],[d2386,d2388],[d2388,d2389],[d2388,d2390],[d2390,d2391],[d2390,d2392],[d2392,d2393],[d2392,d2394],[d2394,d2395],[d2394,d2396],[d2396,d2397],[d2396,d2398],[d2398,d2399],[d2398,d2400],[d2400,d2401],[d2400,d2402],[d2402,d2403],[d2402,d2404],[d2404,d2405],[d2404,d2406],[d2406,d2407],[d2406,d2408],[d2408,d2409],[d2408,d2410],[d2410,d2411],[d2410,d2412],[d2412,d2413],[d2412,d2414],[d2414,d2415],[d2414,d2416],[d2416,d2417],[d2416,d2418],[d2418,d2419],[d2418,d2420],[d2420,d2421],[d2420,d2422],[d2422,d2423],[d2422,d2424],[d2424,d2425],[d2424,d2426],[d2426,d2427],[d2426,d2428],[d2428,d2429],[d2428,d2430],[d2430,d2431],[d2430,d2432],[d2432,d2433],[d2432,d2434],[d2434,d2435],[d2434,d2436],[d2436,d2437],[d2436,d2438],[d2438,d2439],[d2438,d2440],[d2440,d2441],[d2440,d2442],[d2442,d2443],[d2442,d2444],[d2444,d2445],[d2444,d2446],[d2446,d2447],[d2446,d2448],[d2448,d2449],[d2448,d2450],[d2450,d2451],[d2450,d2452],[d2452,d2453],[d2452,d2454],[d2454,d2455],[d2454,d2456],[d2456,d2457],[d2456,d2458],[d2458,d2459],[d2458,d2460],[d2460,d2461],[d2460,d2462],[d2462,d2463],[d2462,d2464],[d2464,d2465],[d2464,d2466],[d2466,d2467],[d2466,d2468],[d2468,d2469],[d2468,d2470],[d2470,d2471],[d2470,d2472],[d2472,d2473],[d2472,d2474],[d2474,d2475],[d2474,d2476],[d2476,d2477],[d2476,d2478],[d2478,d2479],[d2478,d2480],[d2480,d2481],[d2480,d2482],[d2482,d2483],[d2482,d2484],[d2484,d2485],[d2484,d2486],[d2486,d2487],[d2486,d2488],[d2488,d2489],[d2488,d2490],[d2490,d2491],[d2490,d2492],[d2492,d2493],[d2492,d2494],[d2494,d2495],[d2494,d2496],[d2496,d2497],[d2496,d2498],[d2498,d2499],[d2498,d2500],[d2500,d2501],[d2500,d2502],[d2502,d2503],[d2502,d2504],[d2504,d2505],[d2504,d2506],[d2506,d2507],[d2506,d2508],[d2508,d2509],[d2508,d2510],[d2510,d2511],[d2510,d2512],[d2512,d2513],[d2512,d2514],[d2514,d2515],[d2514,d2516],[d2516,d2517],[d2516,d2518],[d2518,d2519],[d2518,d2520],[d2520,d2521],[d2520,d2522],[d2522,d2523],[d2522,d2524],[d2524,d2525],[d2524,d2526],[d2526,d2527],[d2526,d2528],[d2528,d2529],[d2528,d2530],[d2530,d2531],[d2530,d2532],[d2532,d2533],[d2532,d2534],[d2534,d2535],[d2534,d2536],[d2536,d2537],[d2536,d2538],[d2538,d2539],[d2538,d2540],[d2540,d2541],[d2540,d2542],[d2542,d2543],[d2542,d2544],[d2544,d2545],[d2544,d2546],[d2546,d2547],[d2546,d2548],[d2548,d2549],[d2548,d2550],[d2550,d2551],[d2550,d2552],[d2552,d2553],[d2552,d2554],[d2554,d2555],[d2554,d2556],[d2556,d2557],[d2556,d2558],[d2558,d2559],[d2558,d2560],[d2560,d2561],[d2560,d2562],[d2562,d2563],[d2562,d2564],[d2564,d2565],[d2564,d2566],[d2566,d2567],[d2566,d2568],[d2568,d2569],[d2568,d2570],[d2570,d2571],[d2570,d2572],[d2572,d2573],[d2572,d2574],[d2574,d2575],[d2574,d2576],[d2576,d2577],[d2576,d2578],[d2578,d2579],[d2578,d2580],[d2580,d2581],[d2580,d2582],[d2582,d2583],[d2582,d2584],[d2584,d2585],[d2584,d2586],[d2586,d2587],[d2586,d2588],[d2588,d2589],[d2588,d2590],[d2590,d2591],[d2590,d2592],[d2592,d2593],[d2592,d2594],[d2594,d2595],[d2594,d2596],[d2596,d2597],[d2596,d2598],[d2598,d2599],[d2598,d2600],[d2600,d2601],[d2600,d2602],[d2602,d2603],[d2602,d2604],[d2604,d2605],[d2604,d2606],[d2606,d2607],[d2606,d2608],[d2608,d2609],[d2608,d2610],[d2610,d2611],[d2610,d2612],[d2612,d2613],[d2612,d2614],[d2614,d2615],[d2614,d2616],[d2616,d2617],[d2616,d2618],[d2618,d2619],[d2618,d2620],[d2620,d2621],[d2620,d2622],[d2622,d2623],[d2622,d2624],[d2624,d2625],[d2624,d2626],[d2626,d2627],[d2626,d2628],[d2628,d2629],[d2628,d2630],[d2630,d2631],[d2630,d2632],[d2632,d2633],[d2632,d2634],[d2634,d2635],[d2634,d2636],[d2636,d2637],[d2636,d2638],[d2638,d2639],[d2638,d2640],[d2640,d2641],[d2640,d2642],[d2642,d2643],[d2642,d2644],[d2644,d2645],[d2644,d2646],[d2646,d2647],[d2646,d2648],[d2648,d2649],[d2648,d2650],[d2650,d2651],[d2650,d2652],[d2652,d2653],[d2652,d2654],[d2654,d2655],[d2654,d2656],[d2656,d2657],[d2656,d2658],[d2658,d2659],[d2658,d2660],[d2660,d2661],[d2660,d2662],[d2662,d2663],[d2662,d2664],[d2664,d2665],[d2664,d2666],[d2666,d2667],[d2666,d2668],[d2668,d2669],[d2668,d2670],[d2670,d2671],[d2670,d2672],[d2672,d2673],[d2672,d2674],[d2674,d2675],[d2674,d2676],[d2676,d2677],[d2676,d2678],[d2678,d2679],[d2678,d2680],[d2680,d2681],[d2680,d2682],[d2682,d2683],[d2682,d2684],[d2684,d2685],[d2684,d2686],[d2686,d2687],[d2686,d2688],[d2688,d2689],[d2688,d2690],[d2690,d2691],[d2690,d2692],[d2692,d2693],[d2692,d2694],[d2694,d2695],[d2694,d2696],[d2696,d2697],[d2696,d2698],[d2698,d2699],[d2698,d2700],[d2700,d2701],[d2700,d2702],[d2702,d2703],[d2702,d2704],[d2704,d2705],[d2704,d2706],[d2706,d2707],[d2706,d2708],[d2708,d2709],[d2708,d2710],[d2710,d2711],[d2710,d2712],[d2712,d2713],[d2712,d2714],[d2714,d2715],[d2714,d2716],[d2716,d2717],[d2716,d2718],[d2718,d2719],[d2718,d2720],[d2720,d2721],[d2720,d2722],[d2722,d2723],[d2722,d2724],[d2724,d2725],[d2724,d2726],[d2726,d2727],[d2726,d2728],[d2728,d2729],[d2728,d2730],[d2730,d2731],[d2730,d2732],[d2732,d2733],[d2732,d2734],[d2734,d2735],[d2734,d2736],[d2736,d2737],[d2736,d2738],[d2738,d2739],[d2738,d2740],[d2740,d2741],[d2740,d2742],[d2742,d2743],[d2742,d2744],[d2744,d2745],[d2744,d2746],[d2746,d2747],[d2746,d2748],[d2748,d2749],[d2748,d2750],[d2750,d2751],[d2750,d2752],[d2752,d2753],[d2752,d2754],[d2754,d2755],[d2754,d2756],[d2756,d2757],[d2756,d2758],[d2758,d2759],[d2758,d2760],[d2760,d2761],[d2760,d2762],[d2762,d2763],[d2762,d2764],[d2764,d2765],[d2764,d2766],[d2766,d2767],[d2766,d2768],[d2768,d2769],[d2768,d2770],[d2770,d2771],[d2770,d2772],[d2772,d2773],[d2772,d2774],[d2774,d2775],[d2774,d2776],[d2776,d2777],[d2776,d2778],[d2778,d2779],[d2778,d2780],[d2780,d2781],[d2780,d2782],[d2782,d2783],[d2782,d2784],[d2784,d2785],[d2784,d2786],[d2786,d2787],[d2786,d2788],[d2788,d2789],[d2788,d2790],[d2790,d2791],[d2790,d2792],[d2792,d2793],[d2792,d2794],[d2794,d2795],[d2794,d2796],[d2796,d2797],[d2796,d2798],[d2798,d2799],[d2798,d2800],[d2800,d2801],[d2800,d2802],[d2802,d2803],[d2802,d2804],[d2804,d2805],[d2804,d2806],[d2806,d2807],[d2806,d2808],[d2808,d2809],[d2808,d2810],[d2810,d2811],[d2810,d2812],[d2812,d2813],[d2812,d2814],[d2814,d2815],[d2814,d2816],[d2816,d2817],[d2816,d2818],[d2818,d2819],[d2818,d2820],[d2820,d2821],[d2820,d2822],[d2822,d2823],[d2822,d2824],[d2824,d2825],[d2824,d2826],[d2826,d2827],[d2826,d2828],[d2828,d2829],[d2828,d2830],[d2830,d2831],[d2830,d2832],[d2832,d2833],[d2832,d2834],[d2834,d2835],[d2834,d2836],[d2836,d2837],[d2836,d2838],[d2838,d2839],[d2838,d2840],[d2840,d2841],[d2840,d2842],[d2842,d2843],[d2842,d2844],[d2844,d2845],[d2844,d2846],[d2846,d2847],[d2846,d2848],[d2848,d2849],[d2848,d2850],[d2850,d2851],[d2850,d2852],[d2852,d2853],[d2852,d2854],[d2854,d2855],[d2854,d2856],[d2856,d2857],[d2856,d2858],[d2858,d2859],[d2858,d2860],[d2860,d2861],[d2860,d2862],[d2862,d2863],[d2862,d2864],[d2864,d2865],[d2864,d2866],[d2866,d2867],[d2866,d2868],[d2868,d2869],[d2868,d2870],[d2870,d2871],[d2870,d2872],[d2872,d2873],[d2872,d2874],[d2874,d2875],[d2874,d2876],[d2876,d2877],[d2876,d2878],[d2878,d2879],[d2878,d2880],[d2880,d2881],[d2880,d2882],[d2882,d2883],[d2882,d2884],[d2884,d2885],[d2884,d2886],[d2886,d2887],[d2886,d2888],[d2888,d2889],[d2888,d2890],[d2890,d2891],[d2890,d2892],[d2892,d2893],[d2892,d2894],[d2894,d2895],[d2894,d2896],[d2896,d2897],[d2896,d2898],[d2898,d2899],[d2898,d2900],[d2900,d2901],[d2900,d2902],[d2902,d2903],[d2902,d2904],[d2904,d2905],[d2904,d2906],[d2906,d2907],[d2906,d2908],[d2908,d2909],[d2908,d2910],[d2910,d2911],[d2910,d2912],[d2912,d2913],[d2912,d2914],[d2914,d2915],[d2914,d2916],[d2916,d2917],[d2916,d2918],[d2918,d2919],[d2918,d2920],[d2920,d2921],[d2920,d2922],[d2922,d2923],[d2922,d2924],[d2924,d2925],[d2924,d2926],[d2926,d2927],[d2926,d2928],[d2928,d2929],[d2928,d2930],[d2930,d2931],[d2930,d2932],[d2932,d2933],[d2932,d2934],[d2934,d2935],[d2934,d2936],[d2936,d2937],[d2936,d2938],[d2938,d2939],[d2938,d2940],[d2940,d2941],[d2940,d2942],[d2942,d2943],[d2942,d2944],[d2944,d2945],[d2944,d2946],[d2946,d2947],[d2946,d2948],[d2948,d2949],[d2948,d2950],[d2950,d2951],[d2950,d2952],[d2952,d2953],[d2952,d2954],[d2954,d2955],[d2954,d2956],[d2956,d2957],[d2956,d2958],[d2958,d2959],[d2958,d2960],[d2960,d2961],[d2960,d2962],[d2962,d2963],[d2962,d2964],[d2964,d2965],[d2964,d2966],[d2966,d2967],[d2966,d2968],[d2968,d2969],[d2968,d2970],[d2970,d2971],[d2970,d2972],[d2972,d2973],[d2972,d2974],[d2974,d2975],[d2974,d2976],[d2976,d2977],[d2976,d2978],[d2978,d2979],[d2978,d2980],[d2980,d2981],[d2980,d2982],[d2982,d2983],[d2982,d2984],[d2984,d2985],[d2984,d2986],[d2986,d2987],[d2986,d2988],[d2988,d2989],[d2988,d2990],[d2990,d2991],[d2990,d2992],[d2992,d2993],[d2992,d2994],[d2994,d2995],[d2994,d2996],[d2996,d2997],[d2996,d2998],[d2998,d2999],[d2998,d3000],[d3000,d3001],[d3000,d3002],[d3002,d3003],[d3002,d3004],[d3004,d3005],[d3004,d3006],[d3006,d3007],[d3006,d3008],[d3008,d3009],[d3008,d3010],[d3010,d3011],[d3010,d3012],[d3012,d3013],[d3012,d3014],[d3014,d3015],[d3014,d3016],[d3016,d3017],[d3016,d3018],[d3018,d3019],[d3018,d3020],[d3020,d3021],[d3020,d3022],[d3022,d3023],[d3022,d3024],[d3024,d3025],[d3024,d3026],[d3026,d3027],[d3026,d3028],[d3028,d3029],[d3028,d3030],[d3030,d3031],[d3030,d3032],[d3032,d3033],[d3032,d3034],[d3034,d3035],[d3034,d3036],[d3036,d3037],[d3036,d3038],[d3038,d3039],[d3038,d3040],[d3040,d3041],[d3040,d3042],[d3042,d3043],[d3042,d3044],[d3044,d3045],[d3044,d3046],[d3046,d3047],[d3046,d3048],[d3048,d3049],[d3048,d3050],[d3050,d3051],[d3050,d3052],[d3052,d3053],[d3052,d3054],[d3054,d3055],[d3054,d3056],[d3056,d3057],[d3056,d3058],[d3058,d3059],[d3058,d3060],[d3060,d3061],[d3060,d3062],[d3062,d3063],[d3062,d3064],[d3064,d3065],[d3064,d3066],[d3066,d3067],[d3066,d3068],[d3068,d3069],[d3068,d3070],[d3070,d3071],[d3070,d3072],[d3072,d3073],[d3072,d3074],[d3074,d3075],[d3074,d3076],[d3076,d3077],[d3076,d3078],[d3078,d3079],[d3078,d3080],[d3080,d3081],[d3080,d3082],[d3082,d3083],[d3082,d3084],[d3084,d3085],[d3084,d3086],[d3086,d3087],[d3086,d3088],[d3088,d3089],[d3088,d3090],[d3090,d3091],[d3090,d3092],[d3092,d3093],[d3092,d3094],[d3094,d3095],[d3094,d3096],[d3096,d3097],[d3096,d3098],[d3098,d3099],[d3098,d3100],[d3100,d3101],[d3100,d3102],[d3102,d3103],[d3102,d3104],[d3104,d3105],[d3104,d3106],[d3106,d3107],[d3106,d3108],[d3108,d3109],[d3108,d3110],[d3110,d3111],[d3110,d3112],[d3112,d3113],[d3112,d3114],[d3114,d3115],[d3114,d3116],[d3116,d3117],[d3116,d3118],[d3118,d3119],[d3118,d3120],[d3120,d3121],[d3120,d3122],[d3122,d3123],[d3122,d3124],[d3124,d3125],[d3124,d3126],[d3126,d3127],[d3126,d3128],[d3128,d3129],[d3128,d3130],[d3130,d3131],[d3130,d3132],[d3132,d3133],[d3132,d3134],[d3134,d3135],[d3134,d3136],[d3136,d3137],[d3136,d3138],[d3138,d3139],[d3138,d3140],[d3140,d3141],[d3140,d3142],[d3142,d3143],[d3142,d3144],[d3144,d3145],[d3144,d3146],[d3146,d3147],[d3146,d3148],[d3148,d3149],[d3148,d3150],[d3150,d3151],[d3150,d3152],[d3152,d3153],[d3152,d3154],[d3154,d3155],[d3154,d3156],[d3156,d3157],[d3156,d3158],[d3158,d3159],[d3158,d3160],[d3160,d3161],[d3160,d3162],[d3162,d3163],[d3162,d3164],[d3164,d3165],[d3164,d3166],[d3166,d3167],[d3166,d3168],[d3168,d3169],[d3168,d3170],[d3170,d3171],[d3170,d3172],[d3172,d3173],[d3172,d3174],[d3174,d3175],[d3174,d3176],[d3176,d3177],[d3176,d3178],[d3178,d3179],[d3178,d3180],[d3180,d3181],[d3180,d3182],[d3182,d3183],[d3182,d3184],[d3184,d3185],[d3184,d3186],[d3186,d3187],[d3186,d3188],[d3188,d3189],[d3188,d3190],[d3190,d3191],[d3190,d3192],[d3192,d3193],[d3192,d3194],[d3194,d3195],[d3194,d3196],[d3196,d3197],[d3196,d3198],[d3198,d3199],[d3198,d3200],[d3200,d3201],[d3200,d3202],[d3202,d3203],[d3202,d3204],[d3204,d3205],[d3204,d3206],[d3206,d3207],[d3206,d3208],[d3208,d3209],[d3208,d3210],[d3210,d3211],[d3210,d3212],[d3212,d3213],[d3212,d3214],[d3214,d3215],[d3214,d3216],[d3216,d3217],[d3216,d3218],[d3218,d3219],[d3218,d3220],[d3220,d3221],[d3220,d3222],[d3222,d3223],[d3222,d3224],[d3224,d3225],[d3224,d3226],[d3226,d3227],[d3226,d3228],[d3228,d3229],[d3228,d3230],[d3230,d3231],[d3230,d3232],[d3232,d3233],[d3232,d3234],[d3234,d3235],[d3234,d3236],[d3236,d3237],[d3236,d3238],[d3238,d3239],[d3238,d3240],[d3240,d3241],[d3240,d3242],[d3242,d3243],[d3242,d3244],[d3244,d3245],[d3244,d3246],[d3246,d3247],[d3246,d3248],[d3248,d3249],[d3248,d3250],[d3250,d3251],[d3250,d3252],[d3252,d3253],[d3252,d3254],[d3254,d3255],[d3254,d3256],[d3256,d3257],[d3256,d3258],[d3258,d3259],[d3258,d3260],[d3260,d3261],[d3260,d3262],[d3262,d3263],[d3262,d3264],[d3264,d3265],[d3264,d3266],[d3266,d3267],[d3266,d3268],[d3268,d3269],[d3268,d3270],[d3270,d3271],[d3270,d3272],[d3272,d3273],[d3272,d3274],[d3274,d3275],[d3274,d3276],[d3276,d3277],[d3276,d3278],[d3278,d3279],[d3278,d3280],[d3280,d3281],[d3280,d3282],[d3282,d3283],[d3282,d3284],[d3284,d3285],[d3284,d3286],[d3286,d3287],[d3286,d3288],[d3288,d3289],[d3288,d3290],[d3290,d3291],[d3290,d3292],[d3292,d3293],[d3292,d3294],[d3294,d3295],[d3294,d3296],[d3296,d3297],[d3296,d3298],[d3298,d3299],[d3298,d3300],[d3300,d3301],[d3300,d3302],[d3302,d3303],[d3302,d3304],[d3304,d3305],[d3304,d3306],[d3306,d3307],[d3306,d3308],[d3308,d3309],[d3308,d3310],[d3310,d3311],[d3310,d3312],[d3312,d3313],[d3312,d3314],[d3314,d3315],[d3314,d3316],[d3316,d3317],[d3316,d3318],[d3318,d3319],[d3318,d3320],[d3320,d3321],[d3320,d3322],[d3322,d3323],[d3322,d3324],[d3324,d3325],[d3324,d3326],[d3326,d3327],[d3326,d3328],[d3328,d3329],[d3328,d3330],[d3330,d3331],[d3330,d3332],[d3332,d3333],[d3332,d3334],[d3334,d3335],[d3334,d3336],[d3336,d3337],[d3336,d3338],[d3338,d3339],[d3338,d3340],[d3340,d3341],[d3340,d3342],[d3342,d3343],[d3342,d3344],[d3344,d3345],[d3344,d3346],[d3346,d3347],[d3346,d3348],[d3348,d3349],[d3348,d3350],[d3350,d3351],[d3350,d3352],[d3352,d3353],[d3352,d3354],[d3354,d3355],[d3354,d3356],[d3356,d3357],[d3356,d3358],[d3358,d3359],[d3358,d3360],[d3360,d3361],[d3360,d3362],[d3362,d3363],[d3362,d3364],[d3364,d3365],[d3364,d3366],[d3366,d3367],[d3366,d3368],[d3368,d3369],[d3368,d3370],[d3370,d3371],[d3370,d3372],[d3372,d3373],[d3372,d3374],[d3374,d3375],[d3374,d3376],[d3376,d3377],[d3376,d3378],[d3378,d3379],[d3378,d3380],[d3380,d3381],[d3380,d3382],[d3382,d3383],[d3382,d3384],[d3384,d3385],[d3384,d3386],[d3386,d3387],[d3386,d3388],[d3388,d3389],[d3388,d3390],[d3390,d3391],[d3390,d3392],[d3392,d3393],[d3392,d3394],[d3394,d3395],[d3394,d3396],[d3396,d3397],[d3396,d3398],[d3398,d3399],[d3398,d3400],[d3400,d3401],[d3400,d3402],[d3402,d3403],[d3402,d3404],[d3404,d3405],[d3404,d3406],[d3406,d3407],[d3406,d3408],[d3408,d3409],[d3408,d3410],[d3410,d3411],[d3410,d3412],[d3412,d3413],[d3412,d3414],[d3414,d3415],[d3414,d3416],[d3416,d3417],[d3416,d3418],[d3418,d3419],[d3418,d3420],[d3420,d3421],[d3420,d3422],[d3422,d3423],[d3422,d3424],[d3424,d3425],[d3424,d3426],[d3426,d3427],[d3426,d3428],[d3428,d3429],[d3428,d3430],[d3430,d3431],[d3430,d3432],[d3432,d3433],[d3432,d3434],[d3434,d3435],[d3434,d3436],[d3436,d3437],[d3436,d3438],[d3438,d3439],[d3438,d3440],[d3440,d3441],[d3440,d3442],[d3442,d3443],[d3442,d3444],[d3444,d3445],[d3444,d3446],[d3446,d3447],[d3446,d3448],[d3448,d3449],[d3448,d3450],[d3450,d3451],[d3450,d3452],[d3452,d3453],[d3452,d3454],[d3454,d3455],[d3454,d3456],[d3456,d3457],[d3456,d3458],[d3458,d3459],[d3458,d3460],[d3460,d3461],[d3460,d3462],[d3462,d3463],[d3462,d3464],[d3464,d3465],[d3464,d3466],[d3466,d3467],[d3466,d3468],[d3468,d3469],[d3468,d3470],[d3470,d3471],[d3470,d3472],[d3472,d3473],[d3472,d3474],[d3474,d3475],[d3474,d3476],[d3476,d3477],[d3476,d3478],[d3478,d3479],[d3478,d3480],[d3480,d3481],[d3480,d3482],[d3482,d3483],[d3482,d3484],[d3484,d3485],[d3484,d3486],[d3486,d3487],[d3486,d3488],[d3488,d3489],[d3488,d3490],[d3490,d3491],[d3490,d3492],[d3492,d3493],[d3492,d3494],[d3494,d3495],[d3494,d3496],[d3496,d3497],[d3496,d3498],[d3498,d3499],[d3498,d3500],[d3500,d3501],[d3500,d3502],[d3502,d3503],[d3502,d3504],[d3504,d3505],[d3504,d3506],[d3506,d3507],[d3506,d3508],[d3508,d3509],[d3508,d3510],[d3510,d3511],[d3510,d3512],[d3512,d3513],[d3512,d3514],[d3514,d3515],[d3514,d3516],[d3516,d3517],[d3516,d3518],[d3518,d3519],[d3518,d3520],[d3520,d3521],[d3520,d3522],[d3522,d3523],[d3522,d3524],[d3524,d3525],[d3524,d3526],[d3526,d3527],[d3526,d3528],[d3528,d3529],[d3528,d3530],[d3530,d3531],[d3530,d3532],[d3532,d3533],[d3532,d3534],[d3534,d3535],[d3534,d3536],[d3536,d3537],[d3536,d3538],[d3538,d3539],[d3538,d3540],[d3540,d3541],[d3540,d3542],[d3542,d3543],[d3542,d3544],[d3544,d3545],[d3544,d3546],[d3546,d3547],[d3546,d3548],[d3548,d3549],[d3548,d3550],[d3550,d3551],[d3550,d3552],[d3552,d3553],[d3552,d3554],[d3554,d3555],[d3554,d3556],[d3556,d3557],[d3556,d3558],[d3558,d3559],[d3558,d3560],[d3560,d3561],[d3560,d3562],[d3562,d3563],[d3562,d3564],[d3564,d3565],[d3564,d3566],[d3566,d3567],[d3566,d3568],[d3568,d3569],[d3568,d3570],[d3570,d3571],[d3570,d3572],[d3572,d3573],[d3572,d3574],[d3574,d3575],[d3574,d3576],[d3576,d3577],[d3576,d3578],[d3578,d3579],[d3578,d3580],[d3580,d3581],[d3580,d3582],[d3582,d3583],[d3582,d3584],[d3584,d3585],[d3584,d3586],[d3586,d3587],[d3586,d3588],[d3588,d3589],[d3588,d3590],[d3590,d3591],[d3590,d3592],[d3592,d3593],[d3592,d3594],[d3594,d3595],[d3594,d3596],[d3596,d3597],[d3596,d3598],[d3598,d3599],[d3598,d3600],[d3600,d3601],[d3600,d3602],[d3602,d3603],[d3602,d3604],[d3604,d3605],[d3604,d3606],[d3606,d3607],[d3606,d3608],[d3608,d3609],[d3608,d3610],[d3610,d3611],[d3610,d3612],[d3612,d3613],[d3612,d3614],[d3614,d3615],[d3614,d3616],[d3616,d3617],[d3616,d3618],[d3618,d3619],[d3618,d3620],[d3620,d3621],[d3620,d3622],[d3622,d3623],[d3622,d3624],[d3624,d3625],[d3624,d3626],[d3626,d3627],[d3626,d3628],[d3628,d3629],[d3628,d3630],[d3630,d3631],[d3630,d3632],[d3632,d3633],[d3632,d3634],[d3634,d3635],[d3634,d3636],[d3636,d3637],[d3636,d3638],[d3638,d3639],[d3638,d3640],[d3640,d3641],[d3640,d3642],[d3642,d3643],[d3642,d3644],[d3644,d3645],[d3644,d3646],[d3646,d3647],[d3646,d3648],[d3648,d3649],[d3648,d3650],[d3650,d3651],[d3650,d3652],[d3652,d3653],[d3652,d3654],[d3654,d3655],[d3654,d3656],[d3656,d3657],[d3656,d3658],[d3658,d3659],[d3658,d3660],[d3660,d3661],[d3660,d3662],[d3662,d3663],[d3662,d3664],[d3664,d3665],[d3664,d3666],[d3666,d3667],[d3666,d3668],[d3668,d3669],[d3668,d3670],[d3670,d3671],[d3670,d3672],[d3672,d3673],[d3672,d3674],[d3674,d3675],[d3674,d3676],[d3676,d3677],[d3676,d3678],[d3678,d3679],[d3678,d3680],[d3680,d3681],[d3680,d3682],[d3682,d3683],[d3682,d3684],[d3684,d3685],[d3684,d3686],[d3686,d3687],[d3686,d3688],[d3688,d3689],[d3688,d3690],[d3690,d3691],[d3690,d3692],[d3692,d3693],[d3692,d3694],[d3694,d3695],[d3694,d3696],[d3696,d3697],[d3696,d3698],[d3698,d3699],[d3698,d3700],[d3700,d3701],[d3700,d3702],[d3702,d3703],[d3702,d3704],[d3704,d3705],[d3704,d3706],[d3706,d3707],[d3706,d3708],[d3708,d3709],[d3708,d3710],[d3710,d3711],[d3710,d3712],[d3712,d3713],[d3712,d3714],[d3714,d3715],[d3714,d3716],[d3716,d3717],[d3716,d3718],[d3718,d3719],[d3718,d3720],[d3720,d3721],[d3720,d3722],[d3722,d3723],[d3722,d3724],[d3724,d3725],[d3724,d3726],[d3726,d3727],[d3726,d3728],[d3728,d3729],[d3728,d3730],[d3730,d3731],[d3730,d3732],[d3732,d3733],[d3732,d3734],[d3734,d3735],[d3734,d3736],[d3736,d3737],[d3736,d3738],[d3738,d3739],[d3738,d3740],[d3740,d3741],[d3740,d3742],[d3742,d3743],[d3742,d3744],[d3744,d3745],[d3744,d3746],[d3746,d3747],[d3746,d3748],[d3748,d3749],[d3748,d3750],[d3750,d3751],[d3750,d3752],[d3752,d3753],[d3752,d3754],[d3754,d3755],[d3754,d3756],[d3756,d3757],[d3756,d3758],[d3758,d3759],[d3758,d3760],[d3760,d3761],[d3760,d3762],[d3762,d3763],[d3762,d3764],[d3764,d3765],[d3764,d3766],[d3766,d3767],[d3766,d3768],[d3768,d3769],[d3768,d3770],[d3770,d3771],[d3770,d3772],[d3772,d3773],[d3772,d3774],[d3774,d3775],[d3774,d3776],[d3776,d3777],[d3776,d3778],[d3778,d3779],[d3778,d3780],[d3780,d3781],[d3780,d3782],[d3782,d3783],[d3782,d3784],[d3784,d3785],[d3784,d3786],[d3786,d3787],[d3786,d3788],[d3788,d3789],[d3788,d3790],[d3790,d3791],[d3790,d3792],[d3792,d3793],[d3792,d3794],[d3794,d3795],[d3794,d3796],[d3796,d3797],[d3796,d3798],[d3798,d3799],[d3798,d3800],[d3800,d3801],[d3800,d3802],[d3802,d3803],[d3802,d3804],[d3804,d3805],[d3804,d3806],[d3806,d3807],[d3806,d3808],[d3808,d3809],[d3808,d3810],[d3810,d3811],[d3810,d3812],[d3812,d3813],[d3812,d3814],[d3814,d3815],[d3814,d3816],[d3816,d3817],[d3816,d3818],[d3818,d3819],[d3818,d3820],[d3820,d3821],[d3820,d3822],[d3822,d3823],[d3822,d3824],[d3824,d3825],[d3824,d3826],[d3826,d3827],[d3826,d3828],[d3828,d3829],[d3828,d3830],[d3830,d3831],[d3830,d3832],[d3832,d3833],[d3832,d3834],[d3834,d3835],[d3834,d3836],[d3836,d3837],[d3836,d3838],[d3838,d3839],[d3838,d3840],[d3840,d3841],[d3840,d3842],[d3842,d3843],[d3842,d3844],[d3844,d3845],[d3844,d3846],[d3846,d3847],[d3846,d3848],[d3848,d3849],[d3848,d3850],[d3850,d3851],[d3850,d3852],[d3852,d3853],[d3852,d3854],[d3854,d3855],[d3854,d3856],[d3856,d3857],[d3856,d3858],[d3858,d3859],[d3858,d3860],[d3860,d3861],[d3860,d3862],[d3862,d3863],[d3862,d3864],[d3864,d3865],[d3864,d3866],[d3866,d3867],[d3866,d3868],[d3868,d3869],[d3868,d3870],[d3870,d3871],[d3870,d3872],[d3872,d3873],[d3872,d3874],[d3874,d3875],[d3874,d3876],[d3876,d3877],[d3876,d3878],[d3878,d3879],[d3878,d3880],[d3880,d3881],[d3880,d3882],[d3882,d3883],[d3882,d3884],[d3884,d3885],[d3884,d3886],[d3886,d3887],[d3886,d3888],[d3888,d3889],[d3888,d3890],[d3890,d3891],[d3890,d3892],[d3892,d3893],[d3892,d3894],[d3894,d3895],[d3894,d3896],[d3896,d3897],[d3896,d3898],[d3898,d3899],[d3898,d3900],[d3900,d3901],[d3900,d3902],[d3902,d3903],[d3902,d3904],[d3904,d3905],[d3904,d3906],[d3906,d3907],[d3906,d3908],[d3908,d3909],[d3908,d3910],[d3910,d3911],[d3910,d3912],[d3912,d3913],[d3912,d3914],[d3914,d3915],[d3914,d3916],[d3916,d3917],[d3916,d3918],[d3918,d3919],[d3918,d3920],[d3920,d3921],[d3920,d3922],[d3922,d3923],[d3922,d3924],[d3924,d3925],[d3924,d3926],[d3926,d3927],[d3926,d3928],[d3928,d3929],[d3928,d3930],[d3930,d3931],[d3930,d3932],[d3932,d3933],[d3932,d3934],[d3934,d3935],[d3934,d3936],[d3936,d3937],[d3936,d3938],[d3938,d3939],[d3938,d3940],[d3940,d3941],[d3940,d3942],[d3942,d3943],[d3942,d3944],[d3944,d3945],[d3944,d3946],[d3946,d3947],[d3946,d3948],[d3948,d3949],[d3948,d3950],[d3950,d3951],[d3950,d3952],[d3952,d3953],[d3952,d3954],[d3954,d3955],[d3954,d3956],[d3956,d3957],[d3956,d3958],[d3958,d3959],[d3958,d3960],[d3960,d3961],[d3960,d3962],[d3962,d3963],[d3962,d3964],[d3964,d3965],[d3964,d3966],[d3966,d3967],[d3966,d3968],[d3968,d3969],[d3968,d3970],[d3970,d3971],[d3970,d3972],[d3972,d3973],[d3972,d3974],[d3974,d3975],[d3974,d3976],[d3976,d3977],[d3976,d3978],[d3978,d3979],[d3978,d3980],[d3980,d3981],[d3980,d3982],[d3982,d3983],[d3982,d3984],[d3984,d3985],[d3984,d3986],[d3986,d3987],[d3986,d3988],[d3988,d3989],[d3988,d3990],[d3990,d3991],[d3990,d3992],[d3992,d3993],[d3992,d3994],[d3994,d3995],[d3994,d3996],[d3996,d3997],[d3996,d3998],[d3998,d3999],[d3998,d4000],[d4000,d4001],[d4000,d4002],[d4002,d4003],[d4002,d4004],[d4004,d4005],[d4004,d4006],[d4006,d4007],[d4006,d4008],[d4008,d4009],[d4008,d4010],[d4010,d4011],[d4010,d4012],[d4012,d4013],[d4012,d4014],[d4014,d4015],[d4014,d4016],[d4016,d4017],[d4016,d4018],[d4018,d4019],[d4018,d4020],[d4020,d4021],[d4020,d4022],[d4022,d4023],[d4022,d4024],[d4024,d4025],[d4024,d4026],[d4026,d4027],[d4026,d4028],[d4028,d4029],[d4028,d4030],[d4030,d4031],[d4030,d4032],[d4032,d4033],[d4032,d4034],[d4034,d4035],[d4034,d4036],[d4036,d4037],[d4036,d4038],[d4038,d4039],[d4038,d4040],[d4040,d4041],[d4040,d4042],[d4042,d4043],[d4042,d4044],[d4044,d4045],[d4044,d4046],[d4046,d4047],[d4046,d4048],[d4048,d4049],[d4048,d4050],[d4050,d4051],[d4050,d4052],[d4052,d4053],[d4052,d4054],[d4054,d4055],[d4054,d4056],[d4056,d4057],[d4056,d4058],[d4058,d4059],[d4058,d4060],[d4060,d4061],[d4060,d4062],[d4062,d4063],[d4062,d4064],[d4064,d4065],[d4064,d4066],[d4066,d4067],[d4066,d4068],[d4068,d4069],[d4068,d4070],[d4070,d4071],[d4070,d4072],[d4072,d4073],[d4072,d4074],[d4074,d4075],[d4074,d4076],[d4076,d4077],[d4076,d4078],[d4078,d4079],[d4078,d4080],[d4080,d4081],[d4080,d4082],[d4082,d4083],[d4082,d4084],[d4084,d4085],[d4084,d4086],[d4086,d4087],[d4086,d4088],[d4088,d4089],[d4088,d4090],[d4090,d4091],[d4090,d4092],[d4092,d4093],[d4092,d4094],[d4094,d4095],[d4094,d4096],[d4096,d4097],[d4096,d4098],[d4098,d4099],[d4098,d4100],[d4100,d4101],[d4100,d4102],[d4102,d4103],[d4102,d4104],[d4104,d4105],[d4104,d4106],[d4106,d4107],[d4106,d4108],[d4108,d4109],[d4108,d4110],[d4110,d4111],[d4110,d4112],[d4112,d4113],[d4112,d4114],[d4114,d4115],[d4114,d4116],[d4116,d4117],[d4116,d4118],[d4118,d4119],[d4118,d4120],[d4120,d4121],[d4120,d4122],[d4122,d4123],[d4122,d4124],[d4124,d4125],[d4124,d4126],[d4126,d4127],[d4126,d4128],[d4128,d4129],[d4128,d4130],[d4130,d4131],[d4130,d4132],[d4132,d4133],[d4132,d4134],[d4134,d4135],[d4134,d4136],[d4136,d4137],[d4136,d4138],[d4138,d4139],[d4138,d4140],[d4140,d4141],[d4140,d4142],[d4142,d4143],[d4142,d4144],[d4144,d4145],[d4144,d4146],[d4146,d4147],[d4146,d4148],[d4148,d4149],[d4148,d4150],[d4150,d4151],[d4150,d4152],[d4152,d4153],[d4152,d4154],[d4154,d4155],[d4154,d4156],[d4156,d4157],[d4156,d4158],[d4158,d4159],[d4158,d4160],[d4160,d4161],[d4160,d4162],[d4162,d4163],[d4162,d4164],[d4164,d4165],[d4164,d4166],[d4166,d4167],[d4166,d4168],[d4168,d4169],[d4168,d4170],[d4170,d4171],[d4170,d4172],[d4172,d4173],[d4172,d4174],[d4174,d4175],[d4174,d4176],[d4176,d4177],[d4176,d4178],[d4178,d4179],[d4178,d4180],[d4180,d4181],[d4180,d4182],[d4182,d4183],[d4182,d4184],[d4184,d4185],[d4184,d4186],[d4186,d4187],[d4186,d4188],[d4188,d4189],[d4188,d4190],[d4190,d4191],[d4190,d4192],[d4192,d4193],[d4192,d4194],[d4194,d4195],[d4194,d4196],[d4196,d4197],[d4196,d4198],[d4198,d4199],[d4198,d4200],[d4200,d4201],[d4200,d4202],[d4202,d4203],[d4202,d4204],[d4204,d4205],[d4204,d4206],[d4206,d4207],[d4206,d4208],[d4208,d4209],[d4208,d4210],[d4210,d4211],[d4210,d4212],[d4212,d4213],[d4212,d4214],[d4214,d4215],[d4214,d4216],[d4216,d4217],[d4216,d4218],[d4218,d4219],[d4218,d4220],[d4220,d4221],[d4220,d4222],[d4222,d4223],[d4222,d4224],[d4224,d4225],[d4224,d4226],[d4226,d4227],[d4226,d4228],[d4228,d4229],[d4228,d4230],[d4230,d4231],[d4230,d4232],[d4232,d4233],[d4232,d4234],[d4234,d4235],[d4234,d4236],[d4236,d4237],[d4236,d4238],[d4238,d4239],[d4238,d4240],[d4240,d4241],[d4240,d4242],[d4242,d4243],[d4242,d4244],[d4244,d4245],[d4244,d4246],[d4246,d4247],[d4246,d4248],[d4248,d4249],[d4248,d4250],[d4250,d4251],[d4250,d4252],[d4252,d4253],[d4252,d4254],[d4254,d4255],[d4254,d4256],[d4256,d4257],[d4256,d4258],[d4258,d4259],[d4258,d4260],[d4260,d4261],[d4260,d4262],[d4262,d4263],[d4262,d4264],[d4264,d4265],[d4264,d4266],[d4266,d4267],[d4266,d4268],[d4268,d4269],[d4268,d4270],[d4270,d4271],[d4270,d4272],[d4272,d4273],[d4272,d4274],[d4274,d4275],[d4274,d4276],[d4276,d4277],[d4276,d4278],[d4278,d4279],[d4278,d4280],[d4280,d4281],[d4280,d4282],[d4282,d4283],[d4282,d4284],[d4284,d4285],[d4284,d4286],[d4286,d4287],[d4286,d4288],[d4288,d4289],[d4288,d4290],[d4290,d4291],[d4290,d4292],[d4292,d4293],[d4292,d4294],[d4294,d4295],[d4294,d4296],[d4296,d4297],[d4296,d4298],[d4298,d4299],[d4298,d4300],[d4300,d4301],[d4300,d4302],[d4302,d4303],[d4302,d4304],[d4304,d4305],[d4304,d4306],[d4306,d4307],[d4306,d4308],[d4308,d4309],[d4308,d4310],[d4310,d4311],[d4310,d4312],[d4312,d4313],[d4312,d4314],[d4314,d4315],[d4314,d4316],[d4316,d4317],[d4316,d4318],[d4318,d4319],[d4318,d4320],[d4320,d4321],[d4320,d4322],[d4322,d4323],[d4322,d4324],[d4324,d4325],[d4324,d4326],[d4326,d4327],[d4326,d4328],[d4328,d4329],[d4328,d4330],[d4330,d4331],[d4330,d4332],[d4332,d4333],[d4332,d4334],[d4334,d4335],[d4334,d4336],[d4336,d4337],[d4336,d4338],[d4338,d4339],[d4338,d4340],[d4340,d4341],[d4340,d4342],[d4342,d4343],[d4342,d4344],[d4344,d4345],[d4344,d4346],[d4346,d4347],[d4346,d4348],[d4348,d4349],[d4348,d4350],[d4350,d4351],[d4350,d4352],[d4352,d4353],[d4352,d4354],[d4354,d4355],[d4354,d4356],[d4356,d4357],[d4356,d4358],[d4358,d4359],[d4358,d4360],[d4360,d4361],[d4360,d4362],[d4362,d4363],[d4362,d4364],[d4364,d4365],[d4364,d4366],[d4366,d4367],[d4366,d4368],[d4368,d4369],[d4368,d4370],[d4370,d4371],[d4370,d4372],[d4372,d4373],[d4372,d4374],[d4374,d4375],[d4374,d4376],[d4376,d4377],[d4376,d4378],[d4378,d4379],[d4378,d4380],[d4380,d4381],[d4380,d4382],[d4382,d4383],[d4382,d4384],[d4384,d4385],[d4384,d4386],[d4386,d4387],[d4386,d4388],[d4388,d4389],[d4388,d4390],[d4390,d4391],[d4390,d4392],[d4392,d4393],[d4392,d4394],[d4394,d4395],[d4394,d4396],[d4396,d4397],[d4396,d4398],[d4398,d4399],[d4398,d4400],[d4400,d4401],[d4400,d4402],[d4402,d4403],[d4402,d4404],[d4404,d4405],[d4404,d4406],[d4406,d4407],[d4406,d4408],[d4408,d4409],[d4408,d4410],[d4410,d4411],[d4410,d4412],[d4412,d4413],[d4412,d4414],[d4414,d4415],[d4414,d4416],[d4416,d4417],[d4416,d4418],[d4418,d4419],[d4418,d4420],[d4420,d4421],[d4420,d4422],[d4422,d4423],[d4422,d4424],[d4424,d4425],[d4424,d4426],[d4426,d4427],[d4426,d4428],[d4428,d4429],[d4428,d4430],[d4430,d4431],[d4430,d4432],[d4432,d4433],[d4432,d4434],[d4434,d4435],[d4434,d4436],[d4436,d4437],[d4436,d4438],[d4438,d4439],[d4438,d4440],[d4440,d4441],[d4440,d4442],[d4442,d4443],[d4442,d4444],[d4444,d4445],[d4444,d4446],[d4446,d4447],[d4446,d4448],[d4448,d4449],[d4448,d4450],[d4450,d4451],[d4450,d4452],[d4452,d4453],[d4452,d4454],[d4454,d4455],[d4454,d4456],[d4456,d4457],[d4456,d4458],[d4458,d4459],[d4458,d4460],[d4460,d4461],[d4460,d4462],[d4462,d4463],[d4462,d4464],[d4464,d4465],[d4464,d4466],[d4466,d4467],[d4466,d4468],[d4468,d4469],[d4468,d4470],[d4470,d4471],[d4470,d4472],[d4472,d4473],[d4472,d4474],[d4474,d4475],[d4474,d4476],[d4476,d4477],[d4476,d4478],[d4478,d4479],[d4478,d4480],[d4480,d4481],[d4480,d4482],[d4482,d4483],[d4482,d4484],[d4484,d4485],[d4484,d4486],[d4486,d4487],[d4486,d4488],[d4488,d4489],[d4488,d4490],[d4490,d4491],[d4490,d4492],[d4492,d4493],[d4492,d4494],[d4494,d4495],[d4494,d4496],[d4496,d4497],[d4496,d4498],[d4498,d4499],[d4498,d4500],[d4500,d4501],[d4500,d4502],[d4502,d4503],[d4502,d4504],[d4504,d4505],[d4504,d4506],[d4506,d4507],[d4506,d4508],[d4508,d4509],[d4508,d4510],[d4510,d4511],[d4510,d4512],[d4512,d4513],[d4512,d4514],[d4514,d4515],[d4514,d4516],[d4516,d4517],[d4516,d4518],[d4518,d4519],[d4518,d4520],[d4520,d4521],[d4520,d4522],[d4522,d4523],[d4522,d4524],[d4524,d4525],[d4524,d4526],[d4526,d4527],[d4526,d4528],[d4528,d4529],[d4528,d4530],[d4530,d4531],[d4530,d4532],[d4532,d4533],[d4532,d4534],[d4534,d4535],[d4534,d4536],[d4536,d4537],[d4536,d4538],[d4538,d4539],[d4538,d4540],[d4540,d4541],[d4540,d4542],[d4542,d4543],[d4542,d4544],[d4544,d4545],[d4544,d4546],[d4546,d4547],[d4546,d4548],[d4548,d4549],[d4548,d4550],[d4550,d4551],[d4550,d4552],[d4552,d4553],[d4552,d4554],[d4554,d4555],[d4554,d4556],[d4556,d4557],[d4556,d4558],[d4558,d4559],[d4558,d4560],[d4560,d4561],[d4560,d4562],[d4562,d4563],[d4562,d4564],[d4564,d4565],[d4564,d4566],[d4566,d4567],[d4566,d4568],[d4568,d4569],[d4568,d4570],[d4570,d4571],[d4570,d4572],[d4572,d4573],[d4572,d4574],[d4574,d4575],[d4574,d4576],[d4576,d4577],[d4576,d4578],[d4578,d4579],[d4578,d4580],[d4580,d4581],[d4580,d4582],[d4582,d4583],[d4582,d4584],[d4584,d4585],[d4584,d4586],[d4586,d4587],[d4586,d4588],[d4588,d4589],[d4588,d4590],[d4590,d4591],[d4590,d4592],[d4592,d4593],[d4592,d4594],[d4594,d4595],[d4594,d4596],[d4596,d4597],[d4596,d4598],[d4598,d4599],[d4598,d4600],[d4600,d4601],[d4600,d4602],[d4602,d4603],[d4602,d4604],[d4604,d4605],[d4604,d4606],[d4606,d4607],[d4606,d4608],[d4608,d4609],[d4608,d4610],[d4610,d4611],[d4610,d4612],[d4612,d4613],[d4612,d4614],[d4614,d4615],[d4614,d4616],[d4616,d4617],[d4616,d4618],[d4618,d4619],[d4618,d4620],[d4620,d4621],[d4620,d4622],[d4622,d4623],[d4622,d4624],[d4624,d4625],[d4624,d4626],[d4626,d4627],[d4626,d4628],[d4628,d4629],[d4628,d4630],[d4630,d4631],[d4630,d4632],[d4632,d4633],[d4632,d4634],[d4634,d4635],[d4634,d4636],[d4636,d4637],[d4636,d4638],[d4638,d4639],[d4638,d4640],[d4640,d4641],[d4640,d4642],[d4642,d4643],[d4642,d4644],[d4644,d4645],[d4644,d4646],[d4646,d4647],[d4646,d4648],[d4648,d4649],[d4648,d4650],[d4650,d4651],[d4650,d4652],[d4652,d4653],[d4652,d4654],[d4654,d4655],[d4654,d4656],[d4656,d4657],[d4656,d4658],[d4658,d4659],[d4658,d4660],[d4660,d4661],[d4660,d4662],[d4662,d4663],[d4662,d4664],[d4664,d4665],[d4664,d4666],[d4666,d4667],[d4666,d4668],[d4668,d4669],[d4668,d4670],[d4670,d4671],[d4670,d4672],[d4672,d4673],[d4672,d4674],[d4674,d4675],[d4674,d4676],[d4676,d4677],[d4676,d4678],[d4678,d4679],[d4678,d4680],[d4680,d4681],[d4680,d4682],[d4682,d4683],[d4682,d4684],[d4684,d4685],[d4684,d4686],[d4686,d4687],[d4686,d4688],[d4688,d4689],[d4688,d4690],[d4690,d4691],[d4690,d4692],[d4692,d4693],[d4692,d4694],[d4694,d4695],[d4694,d4696],[d4696,d4697],[d4696,d4698],[d4698,d4699],[d4698,d4700],[d4700,d4701],[d4700,d4702],[d4702,d4703],[d4702,d4704],[d4704,d4705],[d4704,d4706],[d4706,d4707],[d4706,d4708],[d4708,d4709],[d4708,d4710],[d4710,d4711],[d4710,d4712],[d4712,d4713],[d4712,d4714],[d4714,d4715],[d4714,d4716],[d4716,d4717],[d4716,d4718],[d4718,d4719],[d4718,d4720],[d4720,d4721],[d4720,d4722],[d4722,d4723],[d4722,d4724],[d4724,d4725],[d4724,d4726],[d4726,d4727],[d4726,d4728],[d4728,d4729],[d4728,d4730],[d4730,d4731],[d4730,d4732],[d4732,d4733],[d4732,d4734],[d4734,d4735],[d4734,d4736],[d4736,d4737],[d4736,d4738],[d4738,d4739],[d4738,d4740],[d4740,d4741],[d4740,d4742],[d4742,d4743],[d4742,d4744],[d4744,d4745],[d4744,d4746],[d4746,d4747],[d4746,d4748],[d4748,d4749],[d4748,d4750],[d4750,d4751],[d4750,d4752],[d4752,d4753],[d4752,d4754],[d4754,d4755],[d4754,d4756],[d4756,d4757],[d4756,d4758],[d4758,d4759],[d4758,d4760],[d4760,d4761],[d4760,d4762],[d4762,d4763],[d4762,d4764],[d4764,d4765],[d4764,d4766],[d4766,d4767],[d4766,d4768],[d4768,d4769],[d4768,d4770],[d4770,d4771],[d4770,d4772],[d4772,d4773],[d4772,d4774],[d4774,d4775],[d4774,d4776],[d4776,d4777],[d4776,d4778],[d4778,d4779],[d4778,d4780],[d4780,d4781],[d4780,d4782],[d4782,d4783],[d4782,d4784],[d4784,d4785],[d4784,d4786],[d4786,d4787],[d4786,d4788],[d4788,d4789],[d4788,d4790],[d4790,d4791],[d4790,d4792],[d4792,d4793],[d4792,d4794],[d4794,d4795],[d4794,d4796],[d4796,d4797],[d4796,d4798],[d4798,d4799],[d4798,d4800],[d4800,d4801],[d4800,d4802],[d4802,d4803],[d4802,d4804],[d4804,d4805],[d4804,d4806],[d4806,d4807],[d4806,d4808],[d4808,d4809],[d4808,d4810],[d4810,d4811],[d4810,d4812],[d4812,d4813],[d4812,d4814],[d4814,d4815],[d4814,d4816],[d4816,d4817],[d4816,d4818],[d4818,d4819],[d4818,d4820],[d4820,d4821],[d4820,d4822],[d4822,d4823],[d4822,d4824],[d4824,d4825],[d4824,d4826],[d4826,d4827],[d4826,d4828],[d4828,d4829],[d4828,d4830],[d4830,d4831],[d4830,d4832],[d4832,d4833],[d4832,d4834],[d4834,d4835],[d4834,d4836],[d4836,d4837],[d4836,d4838],[d4838,d4839],[d4838,d4840],[d4840,d4841],[d4840,d4842],[d4842,d4843],[d4842,d4844],[d4844,d4845],[d4844,d4846],[d4846,d4847],[d4846,d4848],[d4848,d4849],[d4848,d4850],[d4850,d4851],[d4850,d4852],[d4852,d4853],[d4852,d4854],[d4854,d4855],[d4854,d4856],[d4856,d4857],[d4856,d4858],[d4858,d4859],[d4858,d4860],[d4860,d4861],[d4860,d4862],[d4862,d4863],[d4862,d4864],[d4864,d4865],[d4864,d4866],[d4866,d4867],[d4866,d4868],[d4868,d4869],[d4868,d4870],[d4870,d4871],[d4870,d4872],[d4872,d4873],[d4872,d4874],[d4874,d4875],[d4874,d4876],[d4876,d4877],[d4876,d4878],[d4878,d4879],[d4878,d4880],[d4880,d4881],[d4880,d4882],[d4882,d4883],[d4882,d4884],[d4884,d4885],[d4884,d4886],[d4886,d4887],[d4886,d4888],[d4888,d4889],[d4888,d4890],[d4890,d4891],[d4890,d4892],[d4892,d4893],[d4892,d4894],[d4894,d4895],[d4894,d4896],[d4896,d4897],[d4896,d4898],[d4898,d4899],[d4898,d4900],[d4900,d4901],[d4900,d4902],[d4902,d4903],[d4902,d4904],[d4904,d4905],[d4904,d4906],[d4906,d4907],[d4906,d4908],[d4908,d4909],[d4908,d4910],[d4910,d4911],[d4910,d4912],[d4912,d4913],[d4912,d4914],[d4914,d4915],[d4914,d4916],[d4916,d4917],[d4916,d4918],[d4918,d4919],[d4918,d4920],[d4920,d4921],[d4920,d4922],[d4922,d4923],[d4922,d4924],[d4924,d4925],[d4924,d4926],[d4926,d4927],[d4926,d4928],[d4928,d4929],[d4928,d4930],[d4930,d4931],[d4930,d4932],[d4932,d4933],[d4932,d4934],[d4934,d4935],[d4934,d4936],[d4936,d4937],[d4936,d4938],[d4938,d4939],[d4938,d4940],[d4940,d4941],[d4940,d4942],[d4942,d4943],[d4942,d4944],[d4944,d4945],[d4944,d4946],[d4946,d4947],[d4946,d4948],[d4948,d4949],[d4948,d4950],[d4950,d4951],[d4950,d4952],[d4952,d4953],[d4952,d4954],[d4954,d4955],[d4954,d4956],[d4956,d4957],[d4956,d4958],[d4958,d4959],[d4958,d4960],[d4960,d4961],[d4960,d4962],[d4962,d4963],[d4962,d4964],[d4964,d4965],[d4964,d4966],[d4966,d4967],[d4966,d4968],[d4968,d4969],[d4968,d4970],[d4970,d4971],[d4970,d4972],[d4972,d4973],[d4972,d4974],[d4974,d4975],[d4974,d4976],[d4976,d4977],[d4976,d4978],[d4978,d4979],[d4978,d4980],[d4980,d4981],[d4980,d4982],[d4982,d4983],[d4982,d4984],[d4984,d4985],[d4984,d4986],[d4986,d4987],[d4986,d4988],[d4988,d4989],[d4988,d4990],[d4990,d4991],[d4990,d4992],[d4992,d4993],[d4992,d4994],[d4994,d4995],[d4994,d4996],[d4996,d4997],[d4996,d4998],[d4998,d4999],[d4998,d5000],[d5000,d5001],[d5000,d5002],[d5002,d5003],[d5002,d5004],[d5004,d5005],[d5004,d5006],[d5006,d5007],[d5006,d5008],[d5008,d5009],[d5008,d5010],[d5010,d5011],[d5010,d5012],[d5012,d5013],[d5012,d5014],[d5014,d5015],[d5014,d5016],[d5016,d5017],[d5016,d5018],[d5018,d5019],[d5018,d5020],[d5020,d5021],[d5020,d5022],[d5022,d5023],[d5022,d5024],[d5024,d5025],[d5024,d5026],[d5026,d5027],[d5026,d5028],[d5028,d5029],[d5028,d5030],[d5030,d5031],[d5030,d5032],[d5032,d5033],[d5032,d5034],[d5034,d5035],[d5034,d5036],[d5036,d5037],[d5036,d5038],[d5038,d5039],[d5038,d5040],[d5040,d5041],[d5040,d5042],[d5042,d5043],[d5042,d5044],[d5044,d5045],[d5044,d5046],[d5046,d5047],[d5046,d5048],[d5048,d5049],[d5048,d5050],[d5050,d5051],[d5050,d5052],[d5052,d5053],[d5052,d5054],[d5054,d5055],[d5054,d5056],[d5056,d5057],[d5056,d5058],[d5058,d5059],[d5058,d5060],[d5060,d5061],[d5060,d5062],[d5062,d5063],[d5062,d5064],[d5064,d5065],[d5064,d5066],[d5066,d5067],[d5066,d5068],[d5068,d5069],[d5068,d5070],[d5070,d5071],[d5070,d5072],[d5072,d5073],[d5072,d5074],[d5074,d5075],[d5074,d5076],[d5076,d5077],[d5076,d5078],[d5078,d5079],[d5078,d5080],[d5080,d5081],[d5080,d5082],[d5082,d5083],[d5082,d5084],[d5084,d5085],[d5084,d5086],[d5086,d5087],[d5086,d5088],[d5088,d5089],[d5088,d5090],[d5090,d5091],[d5090,d5092],[d5092,d5093],[d5092,d5094],[d5094,d5095],[d5094,d5096],[d5096,d5097],[d5096,d5098],[d5098,d5099],[d5098,d5100],[d5100,d5101],[d5100,d5102],[d5102,d5103],[d5102,d5104],[d5104,d5105],[d5104,d5106],[d5106,d5107],[d5106,d5108],[d5108,d5109],[d5108,d5110],[d5110,d5111],[d5110,d5112],[d5112,d5113],[d5112,d5114],[d5114,d5115],[d5114,d5116],[d5116,d5117],[d5116,d5118],[d5118,d5119],[d5118,d5120],[d5120,d5121],[d5120,d5122],[d5122,d5123],[d5122,d5124],[d5124,d5125],[d5124,d5126],[d5126,d5127],[d5126,d5128],[d5128,d5129],[d5128,d5130],[d5130,d5131],[d5130,d5132],[d5132,d5133],[d5132,d5134],[d5134,d5135],[d5134,d5136],[d5136,d5137],[d5136,d5138],[d5138,d5139],[d5138,d5140],[d5140,d5141],[d5140,d5142],[d5142,d5143],[d5142,d5144],[d5144,d5145],[d5144,d5146],[d5146,d5147],[d5146,d5148],[d5148,d5149],[d5148,d5150],[d5150,d5151],[d5150,d5152],[d5152,d5153],[d5152,d5154],[d5154,d5155],[d5154,d5156],[d5156,d5157],[d5156,d5158],[d5158,d5159],[d5158,d5160],[d5160,d5161],[d5160,d5162],[d5162,d5163],[d5162,d5164],[d5164,d5165],[d5164,d5166],[d5166,d5167],[d5166,d5168],[d5168,d5169],[d5168,d5170],[d5170,d5171],[d5170,d5172],[d5172,d5173],[d5172,d5174],[d5174,d5175],[d5174,d5176],[d5176,d5177],[d5176,d5178],[d5178,d5179],[d5178,d5180],[d5180,d5181],[d5180,d5182],[d5182,d5183],[d5182,d5184],[d5184,d5185],[d5184,d5186],[d5186,d5187],[d5186,d5188],[d5188,d5189],[d5188,d5190],[d5190,d5191],[d5190,d5192],[d5192,d5193],[d5192,d5194],[d5194,d5195],[d5194,d5196],[d5196,d5197],[d5196,d5198],[d5198,d5199],[d5198,d5200],[d5200,d5201],[d5200,d5202],[d5202,d5203],[d5202,d5204],[d5204,d5205],[d5204,d5206],[d5206,d5207],[d5206,d5208],[d5208,d5209],[d5208,d5210],[d5210,d5211],[d5210,d5212],[d5212,d5213],[d5212,d5214],[d5214,d5215],[d5214,d5216],[d5216,d5217],[d5216,d5218],[d5218,d5219],[d5218,d5220],[d5220,d5221],[d5220,d5222],[d5222,d5223],[d5222,d5224],[d5224,d5225],[d5224,d5226],[d5226,d5227],[d5226,d5228],[d5228,d5229],[d5228,d5230],[d5230,d5231],[d5230,d5232],[d5232,d5233],[d5232,d5234],[d5234,d5235],[d5234,d5236],[d5236,d5237],[d5236,d5238],[d5238,d5239],[d5238,d5240],[d5240,d5241],[d5240,d5242],[d5242,d5243],[d5242,d5244],[d5244,d5245],[d5244,d5246],[d5246,d5247],[d5246,d5248],[d5248,d5249],[d5248,d5250],[d5250,d5251],[d5250,d5252],[d5252,d5253],[d5252,d5254],[d5254,d5255],[d5254,d5256],[d5256,d5257],[d5256,d5258],[d5258,d5259],[d5258,d5260],[d5260,d5261],[d5260,d5262],[d5262,d5263],[d5262,d5264],[d5264,d5265],[d5264,d5266],[d5266,d5267],[d5266,d5268],[d5268,d5269],[d5268,d5270],[d5270,d5271],[d5270,d5272],[d5272,d5273],[d5272,d5274],[d5274,d5275],[d5274,d5276],[d5276,d5277],[d5276,d5278],[d5278,d5279],[d5278,d5280],[d5280,d5281],[d5280,d5282],[d5282,d5283],[d5282,d5284],[d5284,d5285],[d5284,d5286],[d5286,d5287],[d5286,d5288],[d5288,d5289],[d5288,d5290],[d5290,d5291],[d5290,d5292],[d5292,d5293],[d5292,d5294],[d5294,d5295],[d5294,d5296],[d5296,d5297],[d5296,d5298],[d5298,d5299],[d5298,d5300],[d5300,d5301],[d5300,d5302],[d5302,d5303],[d5302,d5304],[d5304,d5305],[d5304,d5306],[d5306,d5307],[d5306,d5308],[d5308,d5309],[d5308,d5310],[d5310,d5311],[d5310,d5312],[d5312,d5313],[d5312,d5314],[d5314,d5315],[d5314,d5316],[d5316,d5317],[d5316,d5318],[d5318,d5319],[d5318,d5320],[d5320,d5321],[d5320,d5322],[d5322,d5323],[d5322,d5324],[d5324,d5325],[d5324,d5326],[d5326,d5327],[d5326,d5328],[d5328,d5329],[d5328,d5330],[d5330,d5331],[d5330,d5332],[d5332,d5333],[d5332,d5334],[d5334,d5335],[d5334,d5336],[d5336,d5337],[d5336,d5338],[d5338,d5339],[d5338,d5340],[d5340,d5341],[d5340,d5342],[d5342,d5343],[d5342,d5344],[d5344,d5345],[d5344,d5346],[d5346,d5347],[d5346,d5348],[d5348,d5349],[d5348,d5350],[d5350,d5351],[d5350,d5352],[d5352,d5353],[d5352,d5354],[d5354,d5355],[d5354,d5356],[d5356,d5357],[d5356,d5358],[d5358,d5359],[d5358,d5360],[d5360,d5361],[d5360,d5362],[d5362,d5363],[d5362,d5364],[d5364,d5365],[d5364,d5366],[d5366,d5367],[d5366,d5368],[d5368,d5369],[d5368,d5370],[d5370,d5371],[d5370,d5372],[d5372,d5373],[d5372,d5374],[d5374,d5375],[d5374,d5376],[d5376,d5377],[d5376,d5378],[d5378,d5379],[d5378,d5380],[d5380,d5381],[d5380,d5382],[d5382,d5383],[d5382,d5384],[d5384,d5385],[d5384,d5386],[d5386,d5387],[d5386,d5388],[d5388,d5389],[d5388,d5390],[d5390,d5391],[d5390,d5392],[d5392,d5393],[d5392,d5394],[d5394,d5395],[d5394,d5396],[d5396,d5397],[d5396,d5398],[d5398,d5399],[d5398,d5400],[d5400,d5401],[d5400,d5402],[d5402,d5403],[d5402,d5404],[d5404,d5405],[d5404,d5406],[d5406,d5407],[d5406,d5408],[d5408,d5409],[d5408,d5410],[d5410,d5411],[d5410,d5412],[d5412,d5413],[d5412,d5414],[d5414,d5415],[d5414,d5416],[d5416,d5417],[d5416,d5418],[d5418,d5419],[d5418,d5420],[d5420,d5421],[d5420,d5422],[d5422,d5423],[d5422,d5424],[d5424,d5425],[d5424,d5426],[d5426,d5427],[d5426,d5428],[d5428,d5429],[d5428,d5430],[d5430,d5431],[d5430,d5432],[d5432,d5433],[d5432,d5434],[d5434,d5435],[d5434,d5436],[d5436,d5437],[d5436,d5438],[d5438,d5439],[d5438,d5440],[d5440,d5441],[d5440,d5442],[d5442,d5443],[d5442,d5444],[d5444,d5445],[d5444,d5446],[d5446,d5447],[d5446,d5448],[d5448,d5449],[d5448,d5450],[d5450,d5451],[d5450,d5452],[d5452,d5453],[d5452,d5454],[d5454,d5455],[d5454,d5456],[d5456,d5457],[d5456,d5458],[d5458,d5459],[d5458,d5460],[d5460,d5461],[d5460,d5462],[d5462,d5463],[d5462,d5464],[d5464,d5465],[d5464,d5466],[d5466,d5467],[d5466,d5468],[d5468,d5469],[d5468,d5470],[d5470,d5471],[d5470,d5472],[d5472,d5473],[d5472,d5474],[d5474,d5475],[d5474,d5476],[d5476,d5477],[d5476,d5478],[d5478,d5479],[d5478,d5480],[d5480,d5481],[d5480,d5482],[d5482,d5483],[d5482,d5484],[d5484,d5485],[d5484,d5486],[d5486,d5487],[d5486,d5488],[d5488,d5489],[d5488,d5490],[d5490,d5491],[d5490,d5492],[d5492,d5493],[d5492,d5494],[d5494,d5495],[d5494,d5496],[d5496,d5497],[d5496,d5498],[d5498,d5499],[d5498,d5500],[d5500,d5501],[d5500,d5502],[d5502,d5503],[d5502,d5504],[d5504,d5505],[d5504,d5506],[d5506,d5507],[d5506,d5508],[d5508,d5509],[d5508,d5510],[d5510,d5511],[d5510,d5512],[d5512,d5513],[d5512,d5514],[d5514,d5515],[d5514,d5516],[d5516,d5517],[d5516,d5518],[d5518,d5519],[d5518,d5520],[d5520,d5521],[d5520,d5522],[d5522,d5523],[d5522,d5524],[d5524,d5525],[d5524,d5526],[d5526,d5527],[d5526,d5528],[d5528,d5529],[d5528,d5530],[d5530,d5531],[d5530,d5532],[d5532,d5533],[d5532,d5534],[d5534,d5535],[d5534,d5536],[d5536,d5537],[d5536,d5538],[d5538,d5539],[d5538,d5540],[d5540,d5541],[d5540,d5542],[d5542,d5543],[d5542,d5544],[d5544,d5545],[d5544,d5546],[d5546,d5547],[d5546,d5548],[d5548,d5549],[d5548,d5550],[d5550,d5551],[d5550,d5552],[d5552,d5553],[d5552,d5554],[d5554,d5555],[d5554,d5556],[d5556,d5557],[d5556,d5558],[d5558,d5559],[d5558,d5560],[d5560,d5561],[d5560,d5562],[d5562,d5563],[d5562,d5564],[d5564,d5565],[d5564,d5566],[d5566,d5567],[d5566,d5568],[d5568,d5569],[d5568,d5570],[d5570,d5571],[d5570,d5572],[d5572,d5573],[d5572,d5574],[d5574,d5575],[d5574,d5576],[d5576,d5577],[d5576,d5578],[d5578,d5579],[d5578,d5580],[d5580,d5581],[d5580,d5582],[d5582,d5583],[d5582,d5584],[d5584,d5585],[d5584,d5586],[d5586,d5587],[d5586,d5588],[d5588,d5589],[d5588,d5590],[d5590,d5591],[d5590,d5592],[d5592,d5593],[d5592,d5594],[d5594,d5595],[d5594,d5596],[d5596,d5597],[d5596,d5598],[d5598,d5599],[d5598,d5600],[d5600,d5601],[d5600,d5602],[d5602,d5603],[d5602,d5604],[d5604,d5605],[d5604,d5606],[d5606,d5607],[d5606,d5608],[d5608,d5609],[d5608,d5610],[d5610,d5611],[d5610,d5612],[d5612,d5613],[d5612,d5614],[d5614,d5615],[d5614,d5616],[d5616,d5617],[d5616,d5618],[d5618,d5619],[d5618,d5620],[d5620,d5621],[d5620,d5622],[d5622,d5623],[d5622,d5624],[d5624,d5625],[d5624,d5626],[d5626,d5627],[d5626,d5628],[d5628,d5629],[d5628,d5630],[d5630,d5631],[d5630,d5632],[d5632,d5633],[d5632,d5634],[d5634,d5635],[d5634,d5636],[d5636,d5637],[d5636,d5638],[d5638,d5639],[d5638,d5640],[d5640,d5641],[d5640,d5642],[d5642,d5643],[d5642,d5644],[d5644,d5645],[d5644,d5646],[d5646,d5647],[d5646,d5648],[d5648,d5649],[d5648,d5650],[d5650,d5651],[d5650,d5652],[d5652,d5653],[d5652,d5654],[d5654,d5655],[d5654,d5656],[d5656,d5657],[d5656,d5658],[d5658,d5659],[d5658,d5660],[d5660,d5661],[d5660,d5662],[d5662,d5663],[d5662,d5664],[d5664,d5665],[d5664,d5666],[d5666,d5667],[d5666,d5668],[d5668,d5669],[d5668,d5670],[d5670,d5671],[d5670,d5672],[d5672,d5673],[d5672,d5674],[d5674,d5675],[d5674,d5676],[d5676,d5677],[d5676,d5678],[d5678,d5679],[d5678,d5680],[d5680,d5681],[d5680,d5682],[d5682,d5683],[d5682,d5684],[d5684,d5685],[d5684,d5686],[d5686,d5687],[d5686,d5688],[d5688,d5689],[d5688,d5690],[d5690,d5691],[d5690,d5692],[d5692,d5693],[d5692,d5694],[d5694,d5695],[d5694,d5696],[d5696,d5697],[d5696,d5698],[d5698,d5699],[d5698,d5700],[d5700,d5701],[d5700,d5702],[d5702,d5703],[d5702,d5704],[d5704,d5705],[d5704,d5706],[d5706,d5707],[d5706,d5708],[d5708,d5709],[d5708,d5710],[d5710,d5711],[d5710,d5712],[d5712,d5713],[d5712,d5714],[d5714,d5715],[d5714,d5716],[d5716,d5717],[d5716,d5718],[d5718,d5719],[d5718,d5720],[d5720,d5721],[d5720,d5722],[d5722,d5723],[d5722,d5724],[d5724,d5725],[d5724,d5726],[d5726,d5727],[d5726,d5728],[d5728,d5729],[d5728,d5730],[d5730,d5731],[d5730,d5732],[d5732,d5733],[d5732,d5734],[d5734,d5735],[d5734,d5736],[d5736,d5737],[d5736,d5738],[d5738,d5739],[d5738,d5740],[d5740,d5741],[d5740,d5742],[d5742,d5743],[d5742,d5744],[d5744,d5745],[d5744,d5746],[d5746,d5747],[d5746,d5748],[d5748,d5749],[d5748,d5750],[d5750,d5751],[d5750,d5752],[d5752,d5753],[d5752,d5754],[d5754,d5755],[d5754,d5756],[d5756,d5757],[d5756,d5758],[d5758,d5759],[d5758,d5760],[d5760,d5761],[d5760,d5762],[d5762,d5763],[d5762,d5764],[d5764,d5765],[d5764,d5766],[d5766,d5767],[d5766,d5768],[d5768,d5769],[d5768,d5770],[d5770,d5771],[d5770,d5772],[d5772,d5773],[d5772,d5774],[d5774,d5775],[d5774,d5776],[d5776,d5777],[d5776,d5778],[d5778,d5779],[d5778,d5780],[d5780,d5781],[d5780,d5782],[d5782,d5783],[d5782,d5784],[d5784,d5785],[d5784,d5786],[d5786,d5787],[d5786,d5788],[d5788,d5789],[d5788,d5790],[d5790,d5791],[d5790,d5792],[d5792,d5793],[d5792,d5794],[d5794,d5795],[d5794,d5796],[d5796,d5797],[d5796,d5798],[d5798,d5799],[d5798,d5800],[d5800,d5801],[d5800,d5802],[d5802,d5803],[d5802,d5804],[d5804,d5805],[d5804,d5806],[d5806,d5807],[d5806,d5808],[d5808,d5809],[d5808,d5810],[d5810,d5811],[d5810,d5812],[d5812,d5813],[d5812,d5814],[d5814,d5815],[d5814,d5816],[d5816,d5817],[d5816,d5818],[d5818,d5819],[d5818,d5820],[d5820,d5821],[d5820,d5822],[d5822,d5823],[d5822,d5824],[d5824,d5825],[d5824,d5826],[d5826,d5827],[d5826,d5828],[d5828,d5829],[d5828,d5830],[d5830,d5831],[d5830,d5832],[d5832,d5833],[d5832,d5834],[d5834,d5835],[d5834,d5836],[d5836,d5837],[d5836,d5838],[d5838,d5839],[d5838,d5840],[d5840,d5841],[d5840,d5842],[d5842,d5843],[d5842,d5844],[d5844,d5845],[d5844,d5846],[d5846,d5847],[d5846,d5848],[d5848,d5849],[d5848,d5850],[d5850,d5851],[d5850,d5852],[d5852,d5853],[d5852,d5854],[d5854,d5855],[d5854,d5856],[d5856,d5857],[d5856,d5858],[d5858,d5859],[d5858,d5860],[d5860,d5861],[d5860,d5862],[d5862,d5863],[d5862,d5864],[d5864,d5865],[d5864,d5866],[d5866,d5867],[d5866,d5868],[d5868,d5869],[d5868,d5870],[d5870,d5871],[d5870,d5872],[d5872,d5873],[d5872,d5874],[d5874,d5875],[d5874,d5876],[d5876,d5877],[d5876,d5878],[d5878,d5879],[d5878,d5880],[d5880,d5881],[d5880,d5882],[d5882,d5883],[d5882,d5884],[d5884,d5885],[d5884,d5886],[d5886,d5887],[d5886,d5888],[d5888,d5889],[d5888,d5890],[d5890,d5891],[d5890,d5892],[d5892,d5893],[d5892,d5894],[d5894,d5895],[d5894,d5896],[d5896,d5897],[d5896,d5898],[d5898,d5899],[d5898,d5900],[d5900,d5901],[d5900,d5902],[d5902,d5903],[d5902,d5904],[d5904,d5905],[d5904,d5906],[d5906,d5907],[d5906,d5908],[d5908,d5909],[d5908,d5910],[d5910,d5911],[d5910,d5912],[d5912,d5913],[d5912,d5914],[d5914,d5915],[d5914,d5916],[d5916,d5917],[d5916,d5918],[d5918,d5919],[d5918,d5920],[d5920,d5921],[d5920,d5922],[d5922,d5923],[d5922,d5924],[d5924,d5925],[d5924,d5926],[d5926,d5927],[d5926,d5928],[d5928,d5929],[d5928,d5930],[d5930,d5931],[d5930,d5932],[d5932,d5933],[d5932,d5934],[d5934,d5935],[d5934,d5936],[d5936,d5937],[d5936,d5938],[d5938,d5939],[d5938,d5940],[d5940,d5941],[d5940,d5942],[d5942,d5943],[d5942,d5944],[d5944,d5945],[d5944,d5946],[d5946,d5947],[d5946,d5948],[d5948,d5949],[d5948,d5950],[d5950,d5951],[d5950,d5952],[d5952,d5953],[d5952,d5954],[d5954,d5955],[d5954,d5956],[d5956,d5957],[d5956,d5958],[d5958,d5959],[d5958,d5960],[d5960,d5961],[d5960,d5962],[d5962,d5963],[d5962,d5964],[d5964,d5965],[d5964,d5966],[d5966,d5967],[d5966,d5968],[d5968,d5969],[d5968,d5970],[d5970,d5971],[d5970,d5972],[d5972,d5973],[d5972,d5974],[d5974,d5975],[d5974,d5976],[d5976,d5977],[d5976,d5978],[d5978,d5979],[d5978,d5980],[d5980,d5981],[d5980,d5982],[d5982,d5983],[d5982,d5984],[d5984,d5985],[d5984,d5986],[d5986,d5987],[d5986,d5988],[d5988,d5989],[d5988,d5990],[d5990,d5991],[d5990,d5992],[d5992,d5993],[d5992,d5994],[d5994,d5995],[d5994,d5996],[d5996,d5997],[d5996,d5998],[d5998,d5999],[d5998,d6000],[d6000,d6001],[d6000,d6002],[d6002,d6003],[d6002,d6004],[d6004,d6005],[d6004,d6006],[d6006,d6007],[d6006,d6008],[d6008,d6009],[d6008,d6010],[d6010,d6011],[d6010,d6012],[d6012,d6013],[d6012,d6014],[d6014,d6015],[d6014,d6016],[d6016,d6017],[d6016,d6018],[d6018,d6019],[d6018,d6020],[d6020,d6021],[d6020,d6022],[d6022,d6023],[d6022,d6024],[d6024,d6025],[d6024,d6026],[d6026,d6027],[d6026,d6028],[d6028,d6029],[d6028,d6030],[d6030,d6031],[d6030,d6032],[d6032,d6033],[d6032,d6034],[d6034,d6035],[d6034,d6036],[d6036,d6037],[d6036,d6038],[d6038,d6039],[d6038,d6040],[d6040,d6041],[d6040,d6042],[d6042,d6043],[d6042,d6044],[d6044,d6045],[d6044,d6046],[d6046,d6047],[d6046,d6048],[d6048,d6049],[d6048,d6050],[d6050,d6051],[d6050,d6052],[d6052,d6053],[d6052,d6054],[d6054,d6055],[d6054,d6056],[d6056,d6057],[d6056,d6058],[d6058,d6059],[d6058,d6060],[d6060,d6061],[d6060,d6062],[d6062,d6063],[d6062,d6064],[d6064,d6065],[d6064,d6066],[d6066,d6067],[d6066,d6068],[d6068,d6069],[d6068,d6070],[d6070,d6071],[d6070,d6072],[d6072,d6073],[d6072,d6074],[d6074,d6075],[d6074,d6076],[d6076,d6077],[d6076,d6078],[d6078,d6079],[d6078,d6080],[d6080,d6081],[d6080,d6082],[d6082,d6083],[d6082,d6084],[d6084,d6085],[d6084,d6086],[d6086,d6087],[d6086,d6088],[d6088,d6089],[d6088,d6090],[d6090,d6091],[d6090,d6092],[d6092,d6093],[d6092,d6094],[d6094,d6095],[d6094,d6096],[d6096,d6097],[d6096,d6098],[d6098,d6099],[d6098,d6100],[d6100,d6101],[d6100,d6102],[d6102,d6103],[d6102,d6104],[d6104,d6105],[d6104,d6106],[d6106,d6107],[d6106,d6108],[d6108,d6109],[d6108,d6110],[d6110,d6111],[d6110,d6112],[d6112,d6113],[d6112,d6114],[d6114,d6115],[d6114,d6116],[d6116,d6117],[d6116,d6118],[d6118,d6119],[d6118,d6120],[d6120,d6121],[d6120,d6122],[d6122,d6123],[d6122,d6124],[d6124,d6125],[d6124,d6126],[d6126,d6127],[d6126,d6128],[d6128,d6129],[d6128,d6130],[d6130,d6131],[d6130,d6132],[d6132,d6133],[d6132,d6134],[d6134,d6135],[d6134,d6136],[d6136,d6137],[d6136,d6138],[d6138,d6139],[d6138,d6140],[d6140,d6141],[d6140,d6142],[d6142,d6143],[d6142,d6144],[d6144,d6145],[d6144,d6146],[d6146,d6147],[d6146,d6148],[d6148,d6149],[d6148,d6150],[d6150,d6151],[d6150,d6152],[d6152,d6153],[d6152,d6154],[d6154,d6155],[d6154,d6156],[d6156,d6157],[d6156,d6158],[d6158,d6159],[d6158,d6160],[d6160,d6161],[d6160,d6162],[d6162,d6163],[d6162,d6164],[d6164,d6165],[d6164,d6166],[d6166,d6167],[d6166,d6168],[d6168,d6169],[d6168,d6170],[d6170,d6171],[d6170,d6172],[d6172,d6173],[d6172,d6174],[d6174,d6175],[d6174,d6176],[d6176,d6177],[d6176,d6178],[d6178,d6179],[d6178,d6180],[d6180,d6181],[d6180,d6182],[d6182,d6183],[d6182,d6184],[d6184,d6185],[d6184,d6186],[d6186,d6187],[d6186,d6188],[d6188,d6189],[d6188,d6190],[d6190,d6191],[d6190,d6192],[d6192,d6193],[d6192,d6194],[d6194,d6195],[d6194,d6196],[d6196,d6197],[d6196,d6198],[d6198,d6199],[d6198,d6200],[d6200,d6201],[d6200,d6202],[d6202,d6203],[d6202,d6204],[d6204,d6205],[d6204,d6206],[d6206,d6207],[d6206,d6208],[d6208,d6209],[d6208,d6210],[d6210,d6211],[d6210,d6212],[d6212,d6213],[d6212,d6214],[d6214,d6215],[d6214,d6216],[d6216,d6217],[d6216,d6218],[d6218,d6219],[d6218,d6220],[d6220,d6221],[d6220,d6222],[d6222,d6223],[d6222,d6224],[d6224,d6225],[d6224,d6226],[d6226,d6227],[d6226,d6228],[d6228,d6229],[d6228,d6230],[d6230,d6231],[d6230,d6232],[d6232,d6233],[d6232,d6234],[d6234,d6235],[d6234,d6236],[d6236,d6237],[d6236,d6238],[d6238,d6239],[d6238,d6240],[d6240,d6241],[d6240,d6242],[d6242,d6243],[d6242,d6244],[d6244,d6245],[d6244,d6246],[d6246,d6247],[d6246,d6248],[d6248,d6249],[d6248,d6250],[d6250,d6251],[d6250,d6252],[d6252,d6253],[d6252,d6254],[d6254,d6255],[d6254,d6256],[d6256,d6257],[d6256,d6258],[d6258,d6259],[d6258,d6260],[d6260,d6261],[d6260,d6262],[d6262,d6263],[d6262,d6264],[d6264,d6265],[d6264,d6266],[d6266,d6267],[d6266,d6268],[d6268,d6269],[d6268,d6270],[d6270,d6271],[d6270,d6272],[d6272,d6273],[d6272,d6274],[d6274,d6275],[d6274,d6276],[d6276,d6277],[d6276,d6278],[d6278,d6279],[d6278,d6280],[d6280,d6281],[d6280,d6282],[d6282,d6283],[d6282,d6284],[d6284,d6285],[d6284,d6286],[d6286,d6287],[d6286,d6288],[d6288,d6289],[d6288,d6290],[d6290,d6291],[d6290,d6292],[d6292,d6293],[d6292,d6294],[d6294,d6295],[d6294,d6296],[d6296,d6297],[d6296,d6298],[d6298,d6299],[d6298,d6300],[d6300,d6301],[d6300,d6302],[d6302,d6303],[d6302,d6304],[d6304,d6305],[d6304,d6306],[d6306,d6307],[d6306,d6308],[d6308,d6309],[d6308,d6310],[d6310,d6311],[d6310,d6312],[d6312,d6313],[d6312,d6314],[d6314,d6315],[d6314,d6316],[d6316,d6317],[d6316,d6318],[d6318,d6319],[d6318,d6320],[d6320,d6321],[d6320,d6322],[d6322,d6323],[d6322,d6324],[d6324,d6325],[d6324,d6326],[d6326,d6327],[d6326,d6328],[d6328,d6329],[d6328,d6330],[d6330,d6331],[d6330,d6332],[d6332,d6333],[d6332,d6334],[d6334,d6335],[d6334,d6336],[d6336,d6337],[d6336,d6338],[d6338,d6339],[d6338,d6340],[d6340,d6341],[d6340,d6342],[d6342,d6343],[d6342,d6344],[d6344,d6345],[d6344,d6346],[d6346,d6347],[d6346,d6348],[d6348,d6349],[d6348,d6350],[d6350,d6351],[d6350,d6352],[d6352,d6353],[d6352,d6354],[d6354,d6355],[d6354,d6356],[d6356,d6357],[d6356,d6358],[d6358,d6359],[d6358,d6360],[d6360,d6361],[d6360,d6362],[d6362,d6363],[d6362,d6364],[d6364,d6365],[d6364,d6366],[d6366,d6367],[d6366,d6368],[d6368,d6369],[d6368,d6370],[d6370,d6371],[d6370,d6372],[d6372,d6373],[d6372,d6374],[d6374,d6375],[d6374,d6376],[d6376,d6377],[d6376,d6378],[d6378,d6379],[d6378,d6380],[d6380,d6381],[d6380,d6382],[d6382,d6383],[d6382,d6384],[d6384,d6385],[d6384,d6386],[d6386,d6387],[d6386,d6388],[d6388,d6389],[d6388,d6390],[d6390,d6391],[d6390,d6392],[d6392,d6393],[d6392,d6394],[d6394,d6395],[d6394,d6396],[d6396,d6397],[d6396,d6398],[d6398,d6399],[d6398,d6400],[d6400,d6401],[d6400,d6402],[d6402,d6403],[d6402,d6404],[d6404,d6405],[d6404,d6406],[d6406,d6407],[d6406,d6408],[d6408,d6409],[d6408,d6410],[d6410,d6411],[d6410,d6412],[d6412,d6413],[d6412,d6414],[d6414,d6415],[d6414,d6416],[d6416,d6417],[d6416,d6418],[d6418,d6419],[d6418,d6420],[d6420,d6421],[d6420,d6422],[d6422,d6423],[d6422,d6424],[d6424,d6425],[d6424,d6426],[d6426,d6427],[d6426,d6428],[d6428,d6429],[d6428,d6430],[d6430,d6431],[d6430,d6432],[d6432,d6433],[d6432,d6434],[d6434,d6435],[d6434,d6436],[d6436,d6437],[d6436,d6438],[d6438,d6439],[d6438,d6440],[d6440,d6441],[d6440,d6442],[d6442,d6443],[d6442,d6444],[d6444,d6445],[d6444,d6446],[d6446,d6447],[d6446,d6448],[d6448,d6449],[d6448,d6450],[d6450,d6451],[d6450,d6452],[d6452,d6453],[d6452,d6454],[d6454,d6455],[d6454,d6456],[d6456,d6457],[d6456,d6458],[d6458,d6459],[d6458,d6460],[d6460,d6461],[d6460,d6462],[d6462,d6463],[d6462,d6464],[d6464,d6465],[d6464,d6466],[d6466,d6467],[d6466,d6468],[d6468,d6469],[d6468,d6470],[d6470,d6471],[d6470,d6472],[d6472,d6473],[d6472,d6474],[d6474,d6475],[d6474,d6476],[d6476,d6477],[d6476,d6478],[d6478,d6479],[d6478,d6480],[d6480,d6481],[d6480,d6482],[d6482,d6483],[d6482,d6484],[d6484,d6485],[d6484,d6486],[d6486,d6487],[d6486,d6488],[d6488,d6489],[d6488,d6490],[d6490,d6491],[d6490,d6492],[d6492,d6493],[d6492,d6494],[d6494,d6495],[d6494,d6496],[d6496,d6497],[d6496,d6498],[d6498,d6499],[d6498,d6500],[d6500,d6501],[d6500,d6502],[d6502,d6503],[d6502,d6504],[d6504,d6505],[d6504,d6506],[d6506,d6507],[d6506,d6508],[d6508,d6509],[d6508,d6510],[d6510,d6511],[d6510,d6512],[d6512,d6513],[d6512,d6514],[d6514,d6515],[d6514,d6516],[d6516,d6517],[d6516,d6518],[d6518,d6519],[d6518,d6520],[d6520,d6521],[d6520,d6522],[d6522,d6523],[d6522,d6524],[d6524,d6525],[d6524,d6526],[d6526,d6527],[d6526,d6528],[d6528,d6529],[d6528,d6530],[d6530,d6531],[d6530,d6532],[d6532,d6533],[d6532,d6534],[d6534,d6535],[d6534,d6536],[d6536,d6537],[d6536,d6538],[d6538,d6539],[d6538,d6540],[d6540,d6541],[d6540,d6542],[d6542,d6543],[d6542,d6544],[d6544,d6545],[d6544,d6546],[d6546,d6547],[d6546,d6548],[d6548,d6549],[d6548,d6550],[d6550,d6551],[d6550,d6552],[d6552,d6553],[d6552,d6554],[d6554,d6555],[d6554,d6556],[d6556,d6557],[d6556,d6558],[d6558,d6559],[d6558,d6560],[d6560,d6561],[d6560,d6562],[d6562,d6563],[d6562,d6564],[d6564,d6565],[d6564,d6566],[d6566,d6567],[d6566,d6568],[d6568,d6569],[d6568,d6570],[d6570,d6571],[d6570,d6572],[d6572,d6573],[d6572,d6574],[d6574,d6575],[d6574,d6576],[d6576,d6577],[d6576,d6578],[d6578,d6579],[d6578,d6580],[d6580,d6581],[d6580,d6582],[d6582,d6583],[d6582,d6584],[d6584,d6585],[d6584,d6586],[d6586,d6587],[d6586,d6588],[d6588,d6589],[d6588,d6590],[d6590,d6591],[d6590,d6592],[d6592,d6593],[d6592,d6594],[d6594,d6595],[d6594,d6596],[d6596,d6597],[d6596,d6598],[d6598,d6599],[d6598,d6600],[d6600,d6601],[d6600,d6602],[d6602,d6603],[d6602,d6604],[d6604,d6605],[d6604,d6606],[d6606,d6607],[d6606,d6608],[d6608,d6609],[d6608,d6610],[d6610,d6611],[d6610,d6612],[d6612,d6613],[d6612,d6614],[d6614,d6615],[d6614,d6616],[d6616,d6617],[d6616,d6618],[d6618,d6619],[d6618,d6620],[d6620,d6621],[d6620,d6622],[d6622,d6623],[d6622,d6624],[d6624,d6625],[d6624,d6626],[d6626,d6627],[d6626,d6628],[d6628,d6629],[d6628,d6630],[d6630,d6631],[d6630,d6632],[d6632,d6633],[d6632,d6634],[d6634,d6635],[d6634,d6636],[d6636,d6637],[d6636,d6638],[d6638,d6639],[d6638,d6640],[d6640,d6641],[d6640,d6642],[d6642,d6643],[d6642,d6644],[d6644,d6645],[d6644,d6646],[d6646,d6647],[d6646,d6648],[d6648,d6649],[d6648,d6650],[d6650,d6651],[d6650,d6652],[d6652,d6653],[d6652,d6654],[d6654,d6655],[d6654,d6656],[d6656,d6657],[d6656,d6658],[d6658,d6659],[d6658,d6660],[d6660,d6661],[d6660,d6662],[d6662,d6663],[d6662,d6664],[d6664,d6665],[d6664,d6666],[d6666,d6667],[d6666,d6668],[d6668,d6669],[d6668,d6670],[d6670,d6671],[d6670,d6672],[d6672,d6673],[d6672,d6674],[d6674,d6675],[d6674,d6676],[d6676,d6677],[d6676,d6678],[d6678,d6679],[d6678,d6680],[d6680,d6681],[d6680,d6682],[d6682,d6683],[d6682,d6684],[d6684,d6685],[d6684,d6686],[d6686,d6687],[d6686,d6688],[d6688,d6689],[d6688,d6690],[d6690,d6691],[d6690,d6692],[d6692,d6693],[d6692,d6694],[d6694,d6695],[d6694,d6696],[d6696,d6697],[d6696,d6698],[d6698,d6699],[d6698,d6700],[d6700,d6701],[d6700,d6702],[d6702,d6703],[d6702,d6704],[d6704,d6705],[d6704,d6706],[d6706,d6707],[d6706,d6708],[d6708,d6709],[d6708,d6710],[d6710,d6711],[d6710,d6712],[d6712,d6713],[d6712,d6714],[d6714,d6715],[d6714,d6716],[d6716,d6717],[d6716,d6718],[d6718,d6719],[d6718,d6720],[d6720,d6721],[d6720,d6722],[d6722,d6723],[d6722,d6724],[d6724,d6725],[d6724,d6726],[d6726,d6727],[d6726,d6728],[d6728,d6729],[d6728,d6730],[d6730,d6731],[d6730,d6732],[d6732,d6733],[d6732,d6734],[d6734,d6735],[d6734,d6736],[d6736,d6737],[d6736,d6738],[d6738,d6739],[d6738,d6740],[d6740,d6741],[d6740,d6742],[d6742,d6743],[d6742,d6744],[d6744,d6745],[d6744,d6746],[d6746,d6747],[d6746,d6748],[d6748,d6749],[d6748,d6750],[d6750,d6751],[d6750,d6752],[d6752,d6753],[d6752,d6754],[d6754,d6755],[d6754,d6756],[d6756,d6757],[d6756,d6758],[d6758,d6759],[d6758,d6760],[d6760,d6761],[d6760,d6762],[d6762,d6763],[d6762,d6764],[d6764,d6765],[d6764,d6766],[d6766,d6767],[d6766,d6768],[d6768,d6769],[d6768,d6770],[d6770,d6771],[d6770,d6772],[d6772,d6773],[d6772,d6774],[d6774,d6775],[d6774,d6776],[d6776,d6777],[d6776,d6778],[d6778,d6779],[d6778,d6780],[d6780,d6781],[d6780,d6782],[d6782,d6783],[d6782,d6784],[d6784,d6785],[d6784,d6786],[d6786,d6787],[d6786,d6788],[d6788,d6789],[d6788,d6790],[d6790,d6791],[d6790,d6792],[d6792,d6793],[d6792,d6794],[d6794,d6795],[d6794,d6796],[d6796,d6797],[d6796,d6798],[d6798,d6799],[d6798,d6800],[d6800,d6801],[d6800,d6802],[d6802,d6803],[d6802,d6804],[d6804,d6805],[d6804,d6806],[d6806,d6807],[d6806,d6808],[d6808,d6809],[d6808,d6810],[d6810,d6811],[d6810,d6812],[d6812,d6813],[d6812,d6814],[d6814,d6815],[d6814,d6816],[d6816,d6817],[d6816,d6818],[d6818,d6819],[d6818,d6820],[d6820,d6821],[d6820,d6822],[d6822,d6823],[d6822,d6824],[d6824,d6825],[d6824,d6826],[d6826,d6827],[d6826,d6828],[d6828,d6829],[d6828,d6830],[d6830,d6831],[d6830,d6832],[d6832,d6833],[d6832,d6834],[d6834,d6835],[d6834,d6836],[d6836,d6837],[d6836,d6838],[d6838,d6839],[d6838,d6840],[d6840,d6841],[d6840,d6842],[d6842,d6843],[d6842,d6844],[d6844,d6845],[d6844,d6846],[d6846,d6847],[d6846,d6848],[d6848,d6849],[d6848,d6850],[d6850,d6851],[d6850,d6852],[d6852,d6853],[d6852,d6854],[d6854,d6855],[d6854,d6856],[d6856,d6857],[d6856,d6858],[d6858,d6859],[d6858,d6860],[d6860,d6861],[d6860,d6862],[d6862,d6863],[d6862,d6864],[d6864,d6865],[d6864,d6866],[d6866,d6867],[d6866,d6868],[d6868,d6869],[d6868,d6870],[d6870,d6871],[d6870,d6872],[d6872,d6873],[d6872,d6874],[d6874,d6875],[d6874,d6876],[d6876,d6877],[d6876,d6878],[d6878,d6879],[d6878,d6880],[d6880,d6881],[d6880,d6882],[d6882,d6883],[d6882,d6884],[d6884,d6885],[d6884,d6886],[d6886,d6887],[d6886,d6888],[d6888,d6889],[d6888,d6890],[d6890,d6891],[d6890,d6892],[d6892,d6893],[d6892,d6894],[d6894,d6895],[d6894,d6896],[d6896,d6897],[d6896,d6898],[d6898,d6899],[d6898,d6900],[d6900,d6901],[d6900,d6902],[d6902,d6903],[d6902,d6904],[d6904,d6905],[d6904,d6906],[d6906,d6907],[d6906,d6908],[d6908,d6909],[d6908,d6910],[d6910,d6911],[d6910,d6912],[d6912,d6913],[d6912,d6914],[d6914,d6915],[d6914,d6916],[d6916,d6917],[d6916,d6918],[d6918,d6919],[d6918,d6920],[d6920,d6921],[d6920,d6922],[d6922,d6923],[d6922,d6924],[d6924,d6925],[d6924,d6926],[d6926,d6927],[d6926,d6928],[d6928,d6929],[d6928,d6930],[d6930,d6931],[d6930,d6932],[d6932,d6933],[d6932,d6934],[d6934,d6935],[d6934,d6936],[d6936,d6937],[d6936,d6938],[d6938,d6939],[d6938,d6940],[d6940,d6941],[d6940,d6942],[d6942,d6943],[d6942,d6944],[d6944,d6945],[d6944,d6946],[d6946,d6947],[d6946,d6948],[d6948,d6949],[d6948,d6950],[d6950,d6951],[d6950,d6952],[d6952,d6953],[d6952,d6954],[d6954,d6955],[d6954,d6956],[d6956,d6957],[d6956,d6958],[d6958,d6959],[d6958,d6960],[d6960,d6961],[d6960,d6962],[d6962,d6963],[d6962,d6964],[d6964,d6965],[d6964,d6966],[d6966,d6967],[d6966,d6968],[d6968,d6969],[d6968,d6970],[d6970,d6971],[d6970,d6972],[d6972,d6973],[d6972,d6974],[d6974,d6975],[d6974,d6976],[d6976,d6977],[d6976,d6978],[d6978,d6979],[d6978,d6980],[d6980,d6981],[d6980,d6982],[d6982,d6983],[d6982,d6984],[d6984,d6985],[d6984,d6986],[d6986,d6987],[d6986,d6988],[d6988,d6989],[d6988,d6990],[d6990,d6991],[d6990,d6992],[d6992,d6993],[d6992,d6994],[d6994,d6995],[d6994,d6996],[d6996,d6997],[d6996,d6998],[d6998,d6999],[d6998,d7000],[d7000,d7001],[d7000,d7002],[d7002,d7003],[d7002,d7004],[d7004,d7005],[d7004,d7006],[d7006,d7007],[d7006,d7008],[d7008,d7009],[d7008,d7010],[d7010,d7011],[d7010,d7012],[d7012,d7013],[d7012,d7014],[d7014,d7015],[d7014,d7016],[d7016,d7017],[d7016,d7018],[d7018,d7019],[d7018,d7020],[d7020,d7021],[d7020,d7022],[d7022,d7023],[d7022,d7024],[d7024,d7025],[d7024,d7026],[d7026,d7027],[d7026,d7028],[d7028,d7029],[d7028,d7030],[d7030,d7031],[d7030,d7032],[d7032,d7033],[d7032,d7034],[d7034,d7035],[d7034,d7036],[d7036,d7037],[d7036,d7038],[d7038,d7039],[d7038,d7040],[d7040,d7041],[d7040,d7042],[d7042,d7043],[d7042,d7044],[d7044,d7045],[d7044,d7046],[d7046,d7047],[d7046,d7048],[d7048,d7049],[d7048,d7050],[d7050,d7051],[d7050,d7052],[d7052,d7053],[d7052,d7054],[d7054,d7055],[d7054,d7056],[d7056,d7057],[d7056,d7058],[d7058,d7059],[d7058,d7060],[d7060,d7061],[d7060,d7062],[d7062,d7063],[d7062,d7064],[d7064,d7065],[d7064,d7066],[d7066,d7067],[d7066,d7068],[d7068,d7069],[d7068,d7070],[d7070,d7071],[d7070,d7072],[d7072,d7073],[d7072,d7074],[d7074,d7075],[d7074,d7076],[d7076,d7077],[d7076,d7078],[d7078,d7079],[d7078,d7080],[d7080,d7081],[d7080,d7082],[d7082,d7083],[d7082,d7084],[d7084,d7085],[d7084,d7086],[d7086,d7087],[d7086,d7088],[d7088,d7089],[d7088,d7090],[d7090,d7091],[d7090,d7092],[d7092,d7093],[d7092,d7094],[d7094,d7095],[d7094,d7096],[d7096,d7097],[d7096,d7098],[d7098,d7099],[d7098,d7100],[d7100,d7101],[d7100,d7102],[d7102,d7103],[d7102,d7104],[d7104,d7105],[d7104,d7106],[d7106,d7107],[d7106,d7108],[d7108,d7109],[d7108,d7110],[d7110,d7111],[d7110,d7112],[d7112,d7113],[d7112,d7114],[d7114,d7115],[d7114,d7116],[d7116,d7117],[d7116,d7118],[d7118,d7119],[d7118,d7120],[d7120,d7121],[d7120,d7122],[d7122,d7123],[d7122,d7124],[d7124,d7125],[d7124,d7126],[d7126,d7127],[d7126,d7128],[d7128,d7129],[d7128,d7130],[d7130,d7131],[d7130,d7132],[d7132,d7133],[d7132,d7134],[d7134,d7135],[d7134,d7136],[d7136,d7137],[d7136,d7138],[d7138,d7139],[d7138,d7140],[d7140,d7141],[d7140,d7142],[d7142,d7143],[d7142,d7144],[d7144,d7145],[d7144,d7146],[d7146,d7147],[d7146,d7148],[d7148,d7149],[d7148,d7150],[d7150,d7151],[d7150,d7152],[d7152,d7153],[d7152,d7154],[d7154,d7155],[d7154,d7156],[d7156,d7157],[d7156,d7158],[d7158,d7159],[d7158,d7160],[d7160,d7161],[d7160,d7162],[d7162,d7163],[d7162,d7164],[d7164,d7165],[d7164,d7166],[d7166,d7167],[d7166,d7168],[d7168,d7169],[d7168,d7170],[d7170,d7171],[d7170,d7172],[d7172,d7173],[d7172,d7174],[d7174,d7175],[d7174,d7176],[d7176,d7177],[d7176,d7178],[d7178,d7179],[d7178,d7180],[d7180,d7181],[d7180,d7182],[d7182,d7183],[d7182,d7184],[d7184,d7185],[d7184,d7186],[d7186,d7187],[d7186,d7188],[d7188,d7189],[d7188,d7190],[d7190,d7191],[d7190,d7192],[d7192,d7193],[d7192,d7194],[d7194,d7195],[d7194,d7196],[d7196,d7197],[d7196,d7198],[d7198,d7199],[d7198,d7200],[d7200,d7201],[d7200,d7202],[d7202,d7203],[d7202,d7204],[d7204,d7205],[d7204,d7206],[d7206,d7207],[d7206,d7208],[d7208,d7209],[d7208,d7210],[d7210,d7211],[d7210,d7212],[d7212,d7213],[d7212,d7214],[d7214,d7215],[d7214,d7216],[d7216,d7217],[d7216,d7218],[d7218,d7219],[d7218,d7220],[d7220,d7221],[d7220,d7222],[d7222,d7223],[d7222,d7224],[d7224,d7225],[d7224,d7226],[d7226,d7227],[d7226,d7228],[d7228,d7229],[d7228,d7230],[d7230,d7231],[d7230,d7232],[d7232,d7233],[d7232,d7234],[d7234,d7235],[d7234,d7236],[d7236,d7237],[d7236,d7238],[d7238,d7239],[d7238,d7240],[d7240,d7241],[d7240,d7242],[d7242,d7243],[d7242,d7244],[d7244,d7245],[d7244,d7246],[d7246,d7247],[d7246,d7248],[d7248,d7249],[d7248,d7250],[d7250,d7251],[d7250,d7252],[d7252,d7253],[d7252,d7254],[d7254,d7255],[d7254,d7256],[d7256,d7257],[d7256,d7258],[d7258,d7259],[d7258,d7260],[d7260,d7261],[d7260,d7262],[d7262,d7263],[d7262,d7264],[d7264,d7265],[d7264,d7266],[d7266,d7267],[d7266,d7268],[d7268,d7269],[d7268,d7270],[d7270,d7271],[d7270,d7272],[d7272,d7273],[d7272,d7274],[d7274,d7275],[d7274,d7276],[d7276,d7277],[d7276,d7278],[d7278,d7279],[d7278,d7280],[d7280,d7281],[d7280,d7282],[d7282,d7283],[d7282,d7284],[d7284,d7285],[d7284,d7286],[d7286,d7287],[d7286,d7288],[d7288,d7289],[d7288,d7290],[d7290,d7291],[d7290,d7292],[d7292,d7293],[d7292,d7294],[d7294,d7295],[d7294,d7296],[d7296,d7297],[d7296,d7298],[d7298,d7299],[d7298,d7300],[d7300,d7301],[d7300,d7302],[d7302,d7303],[d7302,d7304],[d7304,d7305],[d7304,d7306],[d7306,d7307],[d7306,d7308],[d7308,d7309],[d7308,d7310],[d7310,d7311],[d7310,d7312],[d7312,d7313],[d7312,d7314],[d7314,d7315],[d7314,d7316],[d7316,d7317],[d7316,d7318],[d7318,d7319],[d7318,d7320],[d7320,d7321],[d7320,d7322],[d7322,d7323],[d7322,d7324],[d7324,d7325],[d7324,d7326],[d7326,d7327],[d7326,d7328],[d7328,d7329],[d7328,d7330],[d7330,d7331],[d7330,d7332],[d7332,d7333],[d7332,d7334],[d7334,d7335],[d7334,d7336],[d7336,d7337],[d7336,d7338],[d7338,d7339],[d7338,d7340],[d7340,d7341],[d7340,d7342],[d7342,d7343],[d7342,d7344],[d7344,d7345],[d7344,d7346],[d7346,d7347],[d7346,d7348],[d7348,d7349],[d7348,d7350],[d7350,d7351],[d7350,d7352],[d7352,d7353],[d7352,d7354],[d7354,d7355],[d7354,d7356],[d7356,d7357],[d7356,d7358],[d7358,d7359],[d7358,d7360],[d7360,d7361],[d7360,d7362],[d7362,d7363],[d7362,d7364],[d7364,d7365],[d7364,d7366],[d7366,d7367],[d7366,d7368],[d7368,d7369],[d7368,d7370],[d7370,d7371],[d7370,d7372],[d7372,d7373],[d7372,d7374],[d7374,d7375],[d7374,d7376],[d7376,d7377],[d7376,d7378],[d7378,d7379],[d7378,d7380],[d7380,d7381],[d7380,d7382],[d7382,d7383],[d7382,d7384],[d7384,d7385],[d7384,d7386],[d7386,d7387],[d7386,d7388],[d7388,d7389],[d7388,d7390],[d7390,d7391],[d7390,d7392],[d7392,d7393],[d7392,d7394],[d7394,d7395],[d7394,d7396],[d7396,d7397],[d7396,d7398],[d7398,d7399],[d7398,d7400],[d7400,d7401],[d7400,d7402],[d7402,d7403],[d7402,d7404],[d7404,d7405],[d7404,d7406],[d7406,d7407],[d7406,d7408],[d7408,d7409],[d7408,d7410],[d7410,d7411],[d7410,d7412],[d7412,d7413],[d7412,d7414],[d7414,d7415],[d7414,d7416],[d7416,d7417],[d7416,d7418],[d7418,d7419],[d7418,d7420],[d7420,d7421],[d7420,d7422],[d7422,d7423],[d7422,d7424],[d7424,d7425],[d7424,d7426],[d7426,d7427],[d7426,d7428],[d7428,d7429],[d7428,d7430],[d7430,d7431],[d7430,d7432],[d7432,d7433],[d7432,d7434],[d7434,d7435],[d7434,d7436],[d7436,d7437],[d7436,d7438],[d7438,d7439],[d7438,d7440],[d7440,d7441],[d7440,d7442],[d7442,d7443],[d7442,d7444],[d7444,d7445],[d7444,d7446],[d7446,d7447],[d7446,d7448],[d7448,d7449],[d7448,d7450],[d7450,d7451],[d7450,d7452],[d7452,d7453],[d7452,d7454],[d7454,d7455],[d7454,d7456],[d7456,d7457],[d7456,d7458],[d7458,d7459],[d7458,d7460],[d7460,d7461],[d7460,d7462],[d7462,d7463],[d7462,d7464],[d7464,d7465],[d7464,d7466],[d7466,d7467],[d7466,d7468],[d7468,d7469],[d7468,d7470],[d7470,d7471],[d7470,d7472],[d7472,d7473],[d7472,d7474],[d7474,d7475],[d7474,d7476],[d7476,d7477],[d7476,d7478],[d7478,d7479],[d7478,d7480],[d7480,d7481],[d7480,d7482],[d7482,d7483],[d7482,d7484],[d7484,d7485],[d7484,d7486],[d7486,d7487],[d7486,d7488],[d7488,d7489],[d7488,d7490],[d7490,d7491],[d7490,d7492],[d7492,d7493],[d7492,d7494],[d7494,d7495],[d7494,d7496],[d7496,d7497],[d7496,d7498],[d7498,d7499],[d7498,d7500],[d7500,d7501],[d7500,d7502],[d7502,d7503],[d7502,d7504],[d7504,d7505],[d7504,d7506],[d7506,d7507],[d7506,d7508],[d7508,d7509],[d7508,d7510],[d7510,d7511],[d7510,d7512],[d7512,d7513],[d7512,d7514],[d7514,d7515],[d7514,d7516],[d7516,d7517],[d7516,d7518],[d7518,d7519],[d7518,d7520],[d7520,d7521],[d7520,d7522],[d7522,d7523],[d7522,d7524],[d7524,d7525],[d7524,d7526],[d7526,d7527],[d7526,d7528],[d7528,d7529],[d7528,d7530],[d7530,d7531],[d7530,d7532],[d7532,d7533],[d7532,d7534],[d7534,d7535],[d7534,d7536],[d7536,d7537],[d7536,d7538],[d7538,d7539],[d7538,d7540],[d7540,d7541],[d7540,d7542],[d7542,d7543],[d7542,d7544],[d7544,d7545],[d7544,d7546],[d7546,d7547],[d7546,d7548],[d7548,d7549],[d7548,d7550],[d7550,d7551],[d7550,d7552],[d7552,d7553],[d7552,d7554],[d7554,d7555],[d7554,d7556],[d7556,d7557],[d7556,d7558],[d7558,d7559],[d7558,d7560],[d7560,d7561],[d7560,d7562],[d7562,d7563],[d7562,d7564],[d7564,d7565],[d7564,d7566],[d7566,d7567],[d7566,d7568],[d7568,d7569],[d7568,d7570],[d7570,d7571],[d7570,d7572],[d7572,d7573],[d7572,d7574],[d7574,d7575],[d7574,d7576],[d7576,d7577],[d7576,d7578],[d7578,d7579],[d7578,d7580],[d7580,d7581],[d7580,d7582],[d7582,d7583],[d7582,d7584],[d7584,d7585],[d7584,d7586],[d7586,d7587],[d7586,d7588],[d7588,d7589],[d7588,d7590],[d7590,d7591],[d7590,d7592],[d7592,d7593],[d7592,d7594],[d7594,d7595],[d7594,d7596],[d7596,d7597],[d7596,d7598],[d7598,d7599],[d7598,d7600],[d7600,d7601],[d7600,d7602],[d7602,d7603],[d7602,d7604],[d7604,d7605],[d7604,d7606],[d7606,d7607],[d7606,d7608],[d7608,d7609],[d7608,d7610],[d7610,d7611],[d7610,d7612],[d7612,d7613],[d7612,d7614],[d7614,d7615],[d7614,d7616],[d7616,d7617],[d7616,d7618],[d7618,d7619],[d7618,d7620],[d7620,d7621],[d7620,d7622],[d7622,d7623],[d7622,d7624],[d7624,d7625],[d7624,d7626],[d7626,d7627],[d7626,d7628],[d7628,d7629],[d7628,d7630],[d7630,d7631],[d7630,d7632],[d7632,d7633],[d7632,d7634],[d7634,d7635],[d7634,d7636],[d7636,d7637],[d7636,d7638],[d7638,d7639],[d7638,d7640],[d7640,d7641],[d7640,d7642],[d7642,d7643],[d7642,d7644],[d7644,d7645],[d7644,d7646],[d7646,d7647],[d7646,d7648],[d7648,d7649],[d7648,d7650],[d7650,d7651],[d7650,d7652],[d7652,d7653],[d7652,d7654],[d7654,d7655],[d7654,d7656],[d7656,d7657],[d7656,d7658],[d7658,d7659],[d7658,d7660],[d7660,d7661],[d7660,d7662],[d7662,d7663],[d7662,d7664],[d7664,d7665],[d7664,d7666],[d7666,d7667],[d7666,d7668],[d7668,d7669],[d7668,d7670],[d7670,d7671],[d7670,d7672],[d7672,d7673],[d7672,d7674],[d7674,d7675],[d7674,d7676],[d7676,d7677],[d7676,d7678],[d7678,d7679],[d7678,d7680],[d7680,d7681],[d7680,d7682],[d7682,d7683],[d7682,d7684],[d7684,d7685],[d7684,d7686],[d7686,d7687],[d7686,d7688],[d7688,d7689],[d7688,d7690],[d7690,d7691],[d7690,d7692],[d7692,d7693],[d7692,d7694],[d7694,d7695],[d7694,d7696],[d7696,d7697],[d7696,d7698],[d7698,d7699],[d7698,d7700],[d7700,d7701],[d7700,d7702],[d7702,d7703],[d7702,d7704],[d7704,d7705],[d7704,d7706],[d7706,d7707],[d7706,d7708],[d7708,d7709],[d7708,d7710],[d7710,d7711],[d7710,d7712],[d7712,d7713],[d7712,d7714],[d7714,d7715],[d7714,d7716],[d7716,d7717],[d7716,d7718],[d7718,d7719],[d7718,d7720],[d7720,d7721],[d7720,d7722],[d7722,d7723],[d7722,d7724],[d7724,d7725],[d7724,d7726],[d7726,d7727],[d7726,d7728],[d7728,d7729],[d7728,d7730],[d7730,d7731],[d7730,d7732],[d7732,d7733],[d7732,d7734],[d7734,d7735],[d7734,d7736],[d7736,d7737],[d7736,d7738],[d7738,d7739],[d7738,d7740],[d7740,d7741],[d7740,d7742],[d7742,d7743],[d7742,d7744],[d7744,d7745],[d7744,d7746],[d7746,d7747],[d7746,d7748],[d7748,d7749],[d7748,d7750],[d7750,d7751],[d7750,d7752],[d7752,d7753],[d7752,d7754],[d7754,d7755],[d7754,d7756],[d7756,d7757],[d7756,d7758],[d7758,d7759],[d7758,d7760],[d7760,d7761],[d7760,d7762],[d7762,d7763],[d7762,d7764],[d7764,d7765],[d7764,d7766],[d7766,d7767],[d7766,d7768],[d7768,d7769],[d7768,d7770],[d7770,d7771],[d7770,d7772],[d7772,d7773],[d7772,d7774],[d7774,d7775],[d7774,d7776],[d7776,d7777],[d7776,d7778],[d7778,d7779],[d7778,d7780],[d7780,d7781],[d7780,d7782],[d7782,d7783],[d7782,d7784],[d7784,d7785],[d7784,d7786],[d7786,d7787],[d7786,d7788],[d7788,d7789],[d7788,d7790],[d7790,d7791],[d7790,d7792],[d7792,d7793],[d7792,d7794],[d7794,d7795],[d7794,d7796],[d7796,d7797],[d7796,d7798],[d7798,d7799],[d7798,d7800],[d7800,d7801],[d7800,d7802],[d7802,d7803],[d7802,d7804],[d7804,d7805],[d7804,d7806],[d7806,d7807],[d7806,d7808],[d7808,d7809],[d7808,d7810],[d7810,d7811],[d7810,d7812],[d7812,d7813],[d7812,d7814],[d7814,d7815],[d7814,d7816],[d7816,d7817],[d7816,d7818],[d7818,d7819],[d7818,d7820],[d7820,d7821],[d7820,d7822],[d7822,d7823],[d7822,d7824],[d7824,d7825],[d7824,d7826],[d7826,d7827],[d7826,d7828],[d7828,d7829],[d7828,d7830],[d7830,d7831],[d7830,d7832],[d7832,d7833],[d7832,d7834],[d7834,d7835],[d7834,d7836],[d7836,d7837],[d7836,d7838],[d7838,d7839],[d7838,d7840],[d7840,d7841],[d7840,d7842],[d7842,d7843],[d7842,d7844],[d7844,d7845],[d7844,d7846],[d7846,d7847],[d7846,d7848],[d7848,d7849],[d7848,d7850],[d7850,d7851],[d7850,d7852],[d7852,d7853],[d7852,d7854],[d7854,d7855],[d7854,d7856],[d7856,d7857],[d7856,d7858],[d7858,d7859],[d7858,d7860],[d7860,d7861],[d7860,d7862],[d7862,d7863],[d7862,d7864],[d7864,d7865],[d7864,d7866],[d7866,d7867],[d7866,d7868],[d7868,d7869],[d7868,d7870],[d7870,d7871],[d7870,d7872],[d7872,d7873],[d7872,d7874],[d7874,d7875],[d7874,d7876],[d7876,d7877],[d7876,d7878],[d7878,d7879],[d7878,d7880],[d7880,d7881],[d7880,d7882],[d7882,d7883],[d7882,d7884],[d7884,d7885],[d7884,d7886],[d7886,d7887],[d7886,d7888],[d7888,d7889],[d7888,d7890],[d7890,d7891],[d7890,d7892],[d7892,d7893],[d7892,d7894],[d7894,d7895],[d7894,d7896],[d7896,d7897],[d7896,d7898],[d7898,d7899],[d7898,d7900],[d7900,d7901],[d7900,d7902],[d7902,d7903],[d7902,d7904],[d7904,d7905],[d7904,d7906],[d7906,d7907],[d7906,d7908],[d7908,d7909],[d7908,d7910],[d7910,d7911],[d7910,d7912],[d7912,d7913],[d7912,d7914],[d7914,d7915],[d7914,d7916],[d7916,d7917],[d7916,d7918],[d7918,d7919],[d7918,d7920],[d7920,d7921],[d7920,d7922],[d7922,d7923],[d7922,d7924],[d7924,d7925],[d7924,d7926],[d7926,d7927],[d7926,d7928],[d7928,d7929],[d7928,d7930],[d7930,d7931],[d7930,d7932],[d7932,d7933],[d7932,d7934],[d7934,d7935],[d7934,d7936],[d7936,d7937],[d7936,d7938],[d7938,d7939],[d7938,d7940],[d7940,d7941],[d7940,d7942],[d7942,d7943],[d7942,d7944],[d7944,d7945],[d7944,d7946],[d7946,d7947],[d7946,d7948],[d7948,d7949],[d7948,d7950],[d7950,d7951],[d7950,d7952],[d7952,d7953],[d7952,d7954],[d7954,d7955],[d7954,d7956],[d7956,d7957],[d7956,d7958],[d7958,d7959],[d7958,d7960],[d7960,d7961],[d7960,d7962],[d7962,d7963],[d7962,d7964],[d7964,d7965],[d7964,d7966],[d7966,d7967],[d7966,d7968],[d7968,d7969],[d7968,d7970],[d7970,d7971],[d7970,d7972],[d7972,d7973],[d7972,d7974],[d7974,d7975],[d7974,d7976],[d7976,d7977],[d7976,d7978],[d7978,d7979],[d7978,d7980],[d7980,d7981],[d7980,d7982],[d7982,d7983],[d7982,d7984],[d7984,d7985],[d7984,d7986],[d7986,d7987],[d7986,d7988],[d7988,d7989],[d7988,d7990],[d7990,d7991],[d7990,d7992],[d7992,d7993],[d7992,d7994],[d7994,d7995],[d7994,d7996],[d7996,d7997],[d7996,d7998],[d7998,d7999],[d7998,d8000],[d8000,d8001],[d8000,d8002],[d8002,d8003],[d8002,d8004],[d8004,d8005],[d8004,d8006],[d8006,d8007],[d8006,d8008],[d8008,d8009],[d8008,d8010],[d8010,d8011],[d8010,d8012],[d8012,d8013],[d8012,d8014],[d8014,d8015],[d8014,d8016],[d8016,d8017],[d8016,d8018],[d8018,d8019],[d8018,d8020],[d8020,d8021],[d8020,d8022],[d8022,d8023],[d8022,d8024],[d8024,d8025],[d8024,d8026],[d8026,d8027],[d8026,d8028],[d8028,d8029],[d8028,d8030],[d8030,d8031],[d8030,d8032],[d8032,d8033],[d8032,d8034],[d8034,d8035],[d8034,d8036],[d8036,d8037],[d8036,d8038],[d8038,d8039],[d8038,d8040],[d8040,d8041],[d8040,d8042],[d8042,d8043],[d8042,d8044],[d8044,d8045],[d8044,d8046],[d8046,d8047],[d8046,d8048],[d8048,d8049],[d8048,d8050],[d8050,d8051],[d8050,d8052],[d8052,d8053],[d8052,d8054],[d8054,d8055],[d8054,d8056],[d8056,d8057],[d8056,d8058],[d8058,d8059],[d8058,d8060],[d8060,d8061],[d8060,d8062],[d8062,d8063],[d8062,d8064],[d8064,d8065],[d8064,d8066],[d8066,d8067],[d8066,d8068],[d8068,d8069],[d8068,d8070],[d8070,d8071],[d8070,d8072],[d8072,d8073],[d8072,d8074],[d8074,d8075],[d8074,d8076],[d8076,d8077],[d8076,d8078],[d8078,d8079],[d8078,d8080],[d8080,d8081],[d8080,d8082],[d8082,d8083],[d8082,d8084],[d8084,d8085],[d8084,d8086],[d8086,d8087],[d8086,d8088],[d8088,d8089],[d8088,d8090],[d8090,d8091],[d8090,d8092],[d8092,d8093],[d8092,d8094],[d8094,d8095],[d8094,d8096],[d8096,d8097],[d8096,d8098],[d8098,d8099],[d8098,d8100],[d8100,d8101],[d8100,d8102],[d8102,d8103],[d8102,d8104],[d8104,d8105],[d8104,d8106],[d8106,d8107],[d8106,d8108],[d8108,d8109],[d8108,d8110],[d8110,d8111],[d8110,d8112],[d8112,d8113],[d8112,d8114],[d8114,d8115],[d8114,d8116],[d8116,d8117],[d8116,d8118],[d8118,d8119],[d8118,d8120],[d8120,d8121],[d8120,d8122],[d8122,d8123],[d8122,d8124],[d8124,d8125],[d8124,d8126],[d8126,d8127],[d8126,d8128],[d8128,d8129],[d8128,d8130],[d8130,d8131],[d8130,d8132],[d8132,d8133],[d8132,d8134],[d8134,d8135],[d8134,d8136],[d8136,d8137],[d8136,d8138],[d8138,d8139],[d8138,d8140],[d8140,d8141],[d8140,d8142],[d8142,d8143],[d8142,d8144],[d8144,d8145],[d8144,d8146],[d8146,d8147],[d8146,d8148],[d8148,d8149],[d8148,d8150],[d8150,d8151],[d8150,d8152],[d8152,d8153],[d8152,d8154],[d8154,d8155],[d8154,d8156],[d8156,d8157],[d8156,d8158],[d8158,d8159],[d8158,d8160],[d8160,d8161],[d8160,d8162],[d8162,d8163],[d8162,d8164],[d8164,d8165],[d8164,d8166],[d8166,d8167],[d8166,d8168],[d8168,d8169],[d8168,d8170],[d8170,d8171],[d8170,d8172],[d8172,d8173],[d8172,d8174],[d8174,d8175],[d8174,d8176],[d8176,d8177],[d8176,d8178],[d8178,d8179],[d8178,d8180],[d8180,d8181],[d8180,d8182],[d8182,d8183],[d8182,d8184],[d8184,d8185],[d8184,d8186],[d8186,d8187],[d8186,d8188],[d8188,d8189],[d8188,d8190],[d8190,d8191],[d8190,d8192],[d8192,d8193],[d8192,d8194],[d8194,d8195],[d8194,d8196],[d8196,d8197],[d8196,d8198],[d8198,d8199],[d8198,d8200],[d8200,d8201],[d8200,d8202],[d8202,d8203],[d8202,d8204],[d8204,d8205],[d8204,d8206],[d8206,d8207],[d8206,d8208],[d8208,d8209],[d8208,d8210],[d8210,d8211],[d8210,d8212],[d8212,d8213],[d8212,d8214],[d8214,d8215],[d8214,d8216],[d8216,d8217],[d8216,d8218],[d8218,d8219],[d8218,d8220],[d8220,d8221],[d8220,d8222],[d8222,d8223],[d8222,d8224],[d8224,d8225],[d8224,d8226],[d8226,d8227],[d8226,d8228],[d8228,d8229],[d8228,d8230],[d8230,d8231],[d8230,d8232],[d8232,d8233],[d8232,d8234],[d8234,d8235],[d8234,d8236],[d8236,d8237],[d8236,d8238],[d8238,d8239],[d8238,d8240],[d8240,d8241],[d8240,d8242],[d8242,d8243],[d8242,d8244],[d8244,d8245],[d8244,d8246],[d8246,d8247],[d8246,d8248],[d8248,d8249],[d8248,d8250],[d8250,d8251],[d8250,d8252],[d8252,d8253],[d8252,d8254],[d8254,d8255],[d8254,d8256],[d8256,d8257],[d8256,d8258],[d8258,d8259],[d8258,d8260],[d8260,d8261],[d8260,d8262],[d8262,d8263],[d8262,d8264],[d8264,d8265],[d8264,d8266],[d8266,d8267],[d8266,d8268],[d8268,d8269],[d8268,d8270],[d8270,d8271],[d8270,d8272],[d8272,d8273],[d8272,d8274],[d8274,d8275],[d8274,d8276],[d8276,d8277],[d8276,d8278],[d8278,d8279],[d8278,d8280],[d8280,d8281],[d8280,d8282],[d8282,d8283],[d8282,d8284],[d8284,d8285],[d8284,d8286],[d8286,d8287],[d8286,d8288],[d8288,d8289],[d8288,d8290],[d8290,d8291],[d8290,d8292],[d8292,d8293],[d8292,d8294],[d8294,d8295],[d8294,d8296],[d8296,d8297],[d8296,d8298],[d8298,d8299],[d8298,d8300],[d8300,d8301],[d8300,d8302],[d8302,d8303],[d8302,d8304],[d8304,d8305],[d8304,d8306],[d8306,d8307],[d8306,d8308],[d8308,d8309],[d8308,d8310],[d8310,d8311],[d8310,d8312],[d8312,d8313],[d8312,d8314],[d8314,d8315],[d8314,d8316],[d8316,d8317],[d8316,d8318],[d8318,d8319],[d8318,d8320],[d8320,d8321],[d8320,d8322],[d8322,d8323],[d8322,d8324],[d8324,d8325],[d8324,d8326],[d8326,d8327],[d8326,d8328],[d8328,d8329],[d8328,d8330],[d8330,d8331],[d8330,d8332],[d8332,d8333],[d8332,d8334],[d8334,d8335],[d8334,d8336],[d8336,d8337],[d8336,d8338],[d8338,d8339],[d8338,d8340],[d8340,d8341],[d8340,d8342],[d8342,d8343],[d8342,d8344],[d8344,d8345],[d8344,d8346],[d8346,d8347],[d8346,d8348],[d8348,d8349],[d8348,d8350],[d8350,d8351],[d8350,d8352],[d8352,d8353],[d8352,d8354],[d8354,d8355],[d8354,d8356],[d8356,d8357],[d8356,d8358],[d8358,d8359],[d8358,d8360],[d8360,d8361],[d8360,d8362],[d8362,d8363],[d8362,d8364],[d8364,d8365],[d8364,d8366],[d8366,d8367],[d8366,d8368],[d8368,d8369],[d8368,d8370],[d8370,d8371],[d8370,d8372],[d8372,d8373],[d8372,d8374],[d8374,d8375],[d8374,d8376],[d8376,d8377],[d8376,d8378],[d8378,d8379],[d8378,d8380],[d8380,d8381],[d8380,d8382],[d8382,d8383],[d8382,d8384],[d8384,d8385],[d8384,d8386],[d8386,d8387],[d8386,d8388],[d8388,d8389],[d8388,d8390],[d8390,d8391],[d8390,d8392],[d8392,d8393],[d8392,d8394],[d8394,d8395],[d8394,d8396],[d8396,d8397],[d8396,d8398],[d8398,d8399],[d8398,d8400],[d8400,d8401],[d8400,d8402],[d8402,d8403],[d8402,d8404],[d8404,d8405],[d8404,d8406],[d8406,d8407],[d8406,d8408],[d8408,d8409],[d8408,d8410],[d8410,d8411],[d8410,d8412],[d8412,d8413],[d8412,d8414],[d8414,d8415],[d8414,d8416],[d8416,d8417],[d8416,d8418],[d8418,d8419],[d8418,d8420],[d8420,d8421],[d8420,d8422],[d8422,d8423],[d8422,d8424],[d8424,d8425],[d8424,d8426],[d8426,d8427],[d8426,d8428],[d8428,d8429],[d8428,d8430],[d8430,d8431],[d8430,d8432],[d8432,d8433],[d8432,d8434],[d8434,d8435],[d8434,d8436],[d8436,d8437],[d8436,d8438],[d8438,d8439],[d8438,d8440],[d8440,d8441],[d8440,d8442],[d8442,d8443],[d8442,d8444],[d8444,d8445],[d8444,d8446],[d8446,d8447],[d8446,d8448],[d8448,d8449],[d8448,d8450],[d8450,d8451],[d8450,d8452],[d8452,d8453],[d8452,d8454],[d8454,d8455],[d8454,d8456],[d8456,d8457],[d8456,d8458],[d8458,d8459],[d8458,d8460],[d8460,d8461],[d8460,d8462],[d8462,d8463],[d8462,d8464],[d8464,d8465],[d8464,d8466],[d8466,d8467],[d8466,d8468],[d8468,d8469],[d8468,d8470],[d8470,d8471],[d8470,d8472],[d8472,d8473],[d8472,d8474],[d8474,d8475],[d8474,d8476],[d8476,d8477],[d8476,d8478],[d8478,d8479],[d8478,d8480],[d8480,d8481],[d8480,d8482],[d8482,d8483],[d8482,d8484],[d8484,d8485],[d8484,d8486],[d8486,d8487],[d8486,d8488],[d8488,d8489],[d8488,d8490],[d8490,d8491],[d8490,d8492],[d8492,d8493],[d8492,d8494],[d8494,d8495],[d8494,d8496],[d8496,d8497],[d8496,d8498],[d8498,d8499],[d8498,d8500],[d8500,d8501],[d8500,d8502],[d8502,d8503],[d8502,d8504],[d8504,d8505],[d8504,d8506],[d8506,d8507],[d8506,d8508],[d8508,d8509],[d8508,d8510],[d8510,d8511],[d8510,d8512],[d8512,d8513],[d8512,d8514],[d8514,d8515],[d8514,d8516],[d8516,d8517],[d8516,d8518],[d8518,d8519],[d8518,d8520],[d8520,d8521],[d8520,d8522],[d8522,d8523],[d8522,d8524],[d8524,d8525],[d8524,d8526],[d8526,d8527],[d8526,d8528],[d8528,d8529],[d8528,d8530],[d8530,d8531],[d8530,d8532],[d8532,d8533],[d8532,d8534],[d8534,d8535],[d8534,d8536],[d8536,d8537],[d8536,d8538],[d8538,d8539],[d8538,d8540],[d8540,d8541],[d8540,d8542],[d8542,d8543],[d8542,d8544],[d8544,d8545],[d8544,d8546],[d8546,d8547],[d8546,d8548],[d8548,d8549],[d8548,d8550],[d8550,d8551],[d8550,d8552],[d8552,d8553],[d8552,d8554],[d8554,d8555],[d8554,d8556],[d8556,d8557],[d8556,d8558],[d8558,d8559],[d8558,d8560],[d8560,d8561],[d8560,d8562],[d8562,d8563],[d8562,d8564],[d8564,d8565],[d8564,d8566],[d8566,d8567],[d8566,d8568],[d8568,d8569],[d8568,d8570],[d8570,d8571],[d8570,d8572],[d8572,d8573],[d8572,d8574],[d8574,d8575],[d8574,d8576],[d8576,d8577],[d8576,d8578],[d8578,d8579],[d8578,d8580],[d8580,d8581],[d8580,d8582],[d8582,d8583],[d8582,d8584],[d8584,d8585],[d8584,d8586],[d8586,d8587],[d8586,d8588],[d8588,d8589],[d8588,d8590],[d8590,d8591],[d8590,d8592],[d8592,d8593],[d8592,d8594],[d8594,d8595],[d8594,d8596],[d8596,d8597],[d8596,d8598],[d8598,d8599],[d8598,d8600],[d8600,d8601],[d8600,d8602],[d8602,d8603],[d8602,d8604],[d8604,d8605],[d8604,d8606],[d8606,d8607],[d8606,d8608],[d8608,d8609],[d8608,d8610],[d8610,d8611],[d8610,d8612],[d8612,d8613],[d8612,d8614],[d8614,d8615],[d8614,d8616],[d8616,d8617],[d8616,d8618],[d8618,d8619],[d8618,d8620],[d8620,d8621],[d8620,d8622],[d8622,d8623],[d8622,d8624],[d8624,d8625],[d8624,d8626],[d8626,d8627],[d8626,d8628],[d8628,d8629],[d8628,d8630],[d8630,d8631],[d8630,d8632],[d8632,d8633],[d8632,d8634],[d8634,d8635],[d8634,d8636],[d8636,d8637],[d8636,d8638],[d8638,d8639],[d8638,d8640],[d8640,d8641],[d8640,d8642],[d8642,d8643],[d8642,d8644],[d8644,d8645],[d8644,d8646],[d8646,d8647],[d8646,d8648],[d8648,d8649],[d8648,d8650],[d8650,d8651],[d8650,d8652],[d8652,d8653],[d8652,d8654],[d8654,d8655],[d8654,d8656],[d8656,d8657],[d8656,d8658],[d8658,d8659],[d8658,d8660],[d8660,d8661],[d8660,d8662],[d8662,d8663],[d8662,d8664],[d8664,d8665],[d8664,d8666],[d8666,d8667],[d8666,d8668],[d8668,d8669],[d8668,d8670],[d8670,d8671],[d8670,d8672],[d8672,d8673],[d8672,d8674],[d8674,d8675],[d8674,d8676],[d8676,d8677],[d8676,d8678],[d8678,d8679],[d8678,d8680],[d8680,d8681],[d8680,d8682],[d8682,d8683],[d8682,d8684],[d8684,d8685],[d8684,d8686],[d8686,d8687],[d8686,d8688],[d8688,d8689],[d8688,d8690],[d8690,d8691],[d8690,d8692],[d8692,d8693],[d8692,d8694],[d8694,d8695],[d8694,d8696],[d8696,d8697],[d8696,d8698],[d8698,d8699],[d8698,d8700],[d8700,d8701],[d8700,d8702],[d8702,d8703],[d8702,d8704],[d8704,d8705],[d8704,d8706],[d8706,d8707],[d8706,d8708],[d8708,d8709],[d8708,d8710],[d8710,d8711],[d8710,d8712],[d8712,d8713],[d8712,d8714],[d8714,d8715],[d8714,d8716],[d8716,d8717],[d8716,d8718],[d8718,d8719],[d8718,d8720],[d8720,d8721],[d8720,d8722],[d8722,d8723],[d8722,d8724],[d8724,d8725],[d8724,d8726],[d8726,d8727],[d8726,d8728],[d8728,d8729],[d8728,d8730],[d8730,d8731],[d8730,d8732],[d8732,d8733],[d8732,d8734],[d8734,d8735],[d8734,d8736],[d8736,d8737],[d8736,d8738],[d8738,d8739],[d8738,d8740],[d8740,d8741],[d8740,d8742],[d8742,d8743],[d8742,d8744],[d8744,d8745],[d8744,d8746],[d8746,d8747],[d8746,d8748],[d8748,d8749],[d8748,d8750],[d8750,d8751],[d8750,d8752],[d8752,d8753],[d8752,d8754],[d8754,d8755],[d8754,d8756],[d8756,d8757],[d8756,d8758],[d8758,d8759],[d8758,d8760],[d8760,d8761],[d8760,d8762],[d8762,d8763],[d8762,d8764],[d8764,d8765],[d8764,d8766],[d8766,d8767],[d8766,d8768],[d8768,d8769],[d8768,d8770],[d8770,d8771],[d8770,d8772],[d8772,d8773],[d8772,d8774],[d8774,d8775],[d8774,d8776],[d8776,d8777],[d8776,d8778],[d8778,d8779],[d8778,d8780],[d8780,d8781],[d8780,d8782],[d8782,d8783],[d8782,d8784],[d8784,d8785],[d8784,d8786],[d8786,d8787],[d8786,d8788],[d8788,d8789],[d8788,d8790],[d8790,d8791],[d8790,d8792],[d8792,d8793],[d8792,d8794],[d8794,d8795],[d8794,d8796],[d8796,d8797],[d8796,d8798],[d8798,d8799],[d8798,d8800],[d8800,d8801],[d8800,d8802],[d8802,d8803],[d8802,d8804],[d8804,d8805],[d8804,d8806],[d8806,d8807],[d8806,d8808],[d8808,d8809],[d8808,d8810],[d8810,d8811],[d8810,d8812],[d8812,d8813],[d8812,d8814],[d8814,d8815],[d8814,d8816],[d8816,d8817],[d8816,d8818],[d8818,d8819],[d8818,d8820],[d8820,d8821],[d8820,d8822],[d8822,d8823],[d8822,d8824],[d8824,d8825],[d8824,d8826],[d8826,d8827],[d8826,d8828],[d8828,d8829],[d8828,d8830],[d8830,d8831],[d8830,d8832],[d8832,d8833],[d8832,d8834],[d8834,d8835],[d8834,d8836],[d8836,d8837],[d8836,d8838],[d8838,d8839],[d8838,d8840],[d8840,d8841],[d8840,d8842],[d8842,d8843],[d8842,d8844],[d8844,d8845],[d8844,d8846],[d8846,d8847],[d8846,d8848],[d8848,d8849],[d8848,d8850],[d8850,d8851],[d8850,d8852],[d8852,d8853],[d8852,d8854],[d8854,d8855],[d8854,d8856],[d8856,d8857],[d8856,d8858],[d8858,d8859],[d8858,d8860],[d8860,d8861],[d8860,d8862],[d8862,d8863],[d8862,d8864],[d8864,d8865],[d8864,d8866],[d8866,d8867],[d8866,d8868],[d8868,d8869],[d8868,d8870],[d8870,d8871],[d8870,d8872],[d8872,d8873],[d8872,d8874],[d8874,d8875],[d8874,d8876],[d8876,d8877],[d8876,d8878],[d8878,d8879],[d8878,d8880],[d8880,d8881],[d8880,d8882],[d8882,d8883],[d8882,d8884],[d8884,d8885],[d8884,d8886],[d8886,d8887],[d8886,d8888],[d8888,d8889],[d8888,d8890],[d8890,d8891],[d8890,d8892],[d8892,d8893],[d8892,d8894],[d8894,d8895],[d8894,d8896],[d8896,d8897],[d8896,d8898],[d8898,d8899],[d8898,d8900],[d8900,d8901],[d8900,d8902],[d8902,d8903],[d8902,d8904],[d8904,d8905],[d8904,d8906],[d8906,d8907],[d8906,d8908],[d8908,d8909],[d8908,d8910],[d8910,d8911],[d8910,d8912],[d8912,d8913],[d8912,d8914],[d8914,d8915],[d8914,d8916],[d8916,d8917],[d8916,d8918],[d8918,d8919],[d8918,d8920],[d8920,d8921],[d8920,d8922],[d8922,d8923],[d8922,d8924],[d8924,d8925],[d8924,d8926],[d8926,d8927],[d8926,d8928],[d8928,d8929],[d8928,d8930],[d8930,d8931],[d8930,d8932],[d8932,d8933],[d8932,d8934],[d8934,d8935],[d8934,d8936],[d8936,d8937],[d8936,d8938],[d8938,d8939],[d8938,d8940],[d8940,d8941],[d8940,d8942],[d8942,d8943],[d8942,d8944],[d8944,d8945],[d8944,d8946],[d8946,d8947],[d8946,d8948],[d8948,d8949],[d8948,d8950],[d8950,d8951],[d8950,d8952],[d8952,d8953],[d8952,d8954],[d8954,d8955],[d8954,d8956],[d8956,d8957],[d8956,d8958],[d8958,d8959],[d8958,d8960],[d8960,d8961],[d8960,d8962],[d8962,d8963],[d8962,d8964],[d8964,d8965],[d8964,d8966],[d8966,d8967],[d8966,d8968],[d8968,d8969],[d8968,d8970],[d8970,d8971],[d8970,d8972],[d8972,d8973],[d8972,d8974],[d8974,d8975],[d8974,d8976],[d8976,d8977],[d8976,d8978],[d8978,d8979],[d8978,d8980],[d8980,d8981],[d8980,d8982],[d8982,d8983],[d8982,d8984],[d8984,d8985],[d8984,d8986],[d8986,d8987],[d8986,d8988],[d8988,d8989],[d8988,d8990],[d8990,d8991],[d8990,d8992],[d8992,d8993],[d8992,d8994],[d8994,d8995],[d8994,d8996],[d8996,d8997],[d8996,d8998],[d8998,d8999],[d8998,d9000],[d9000,d9001],[d9000,d9002],[d9002,d9003],[d9002,d9004],[d9004,d9005],[d9004,d9006],[d9006,d9007],[d9006,d9008],[d9008,d9009],[d9008,d9010],[d9010,d9011],[d9010,d9012],[d9012,d9013],[d9012,d9014],[d9014,d9015],[d9014,d9016],[d9016,d9017],[d9016,d9018],[d9018,d9019],[d9018,d9020],[d9020,d9021],[d9020,d9022],[d9022,d9023],[d9022,d9024],[d9024,d9025],[d9024,d9026],[d9026,d9027],[d9026,d9028],[d9028,d9029],[d9028,d9030],[d9030,d9031],[d9030,d9032],[d9032,d9033],[d9032,d9034],[d9034,d9035],[d9034,d9036],[d9036,d9037],[d9036,d9038],[d9038,d9039],[d9038,d9040],[d9040,d9041],[d9040,d9042],[d9042,d9043],[d9042,d9044],[d9044,d9045],[d9044,d9046],[d9046,d9047],[d9046,d9048],[d9048,d9049],[d9048,d9050],[d9050,d9051],[d9050,d9052],[d9052,d9053],[d9052,d9054],[d9054,d9055],[d9054,d9056],[d9056,d9057],[d9056,d9058],[d9058,d9059],[d9058,d9060],[d9060,d9061],[d9060,d9062],[d9062,d9063],[d9062,d9064],[d9064,d9065],[d9064,d9066],[d9066,d9067],[d9066,d9068],[d9068,d9069],[d9068,d9070],[d9070,d9071],[d9070,d9072],[d9072,d9073],[d9072,d9074],[d9074,d9075],[d9074,d9076],[d9076,d9077],[d9076,d9078],[d9078,d9079],[d9078,d9080],[d9080,d9081],[d9080,d9082],[d9082,d9083],[d9082,d9084],[d9084,d9085],[d9084,d9086],[d9086,d9087],[d9086,d9088],[d9088,d9089],[d9088,d9090],[d9090,d9091],[d9090,d9092],[d9092,d9093],[d9092,d9094],[d9094,d9095],[d9094,d9096],[d9096,d9097],[d9096,d9098],[d9098,d9099],[d9098,d9100],[d9100,d9101],[d9100,d9102],[d9102,d9103],[d9102,d9104],[d9104,d9105],[d9104,d9106],[d9106,d9107],[d9106,d9108],[d9108,d9109],[d9108,d9110],[d9110,d9111],[d9110,d9112],[d9112,d9113],[d9112,d9114],[d9114,d9115],[d9114,d9116],[d9116,d9117],[d9116,d9118],[d9118,d9119],[d9118,d9120],[d9120,d9121],[d9120,d9122],[d9122,d9123],[d9122,d9124],[d9124,d9125],[d9124,d9126],[d9126,d9127],[d9126,d9128],[d9128,d9129],[d9128,d9130],[d9130,d9131],[d9130,d9132],[d9132,d9133],[d9132,d9134],[d9134,d9135],[d9134,d9136],[d9136,d9137],[d9136,d9138],[d9138,d9139],[d9138,d9140],[d9140,d9141],[d9140,d9142],[d9142,d9143],[d9142,d9144],[d9144,d9145],[d9144,d9146],[d9146,d9147],[d9146,d9148],[d9148,d9149],[d9148,d9150],[d9150,d9151],[d9150,d9152],[d9152,d9153],[d9152,d9154],[d9154,d9155],[d9154,d9156],[d9156,d9157],[d9156,d9158],[d9158,d9159],[d9158,d9160],[d9160,d9161],[d9160,d9162],[d9162,d9163],[d9162,d9164],[d9164,d9165],[d9164,d9166],[d9166,d9167],[d9166,d9168],[d9168,d9169],[d9168,d9170],[d9170,d9171],[d9170,d9172],[d9172,d9173],[d9172,d9174],[d9174,d9175],[d9174,d9176],[d9176,d9177],[d9176,d9178],[d9178,d9179],[d9178,d9180],[d9180,d9181],[d9180,d9182],[d9182,d9183],[d9182,d9184],[d9184,d9185],[d9184,d9186],[d9186,d9187],[d9186,d9188],[d9188,d9189],[d9188,d9190],[d9190,d9191],[d9190,d9192],[d9192,d9193],[d9192,d9194],[d9194,d9195],[d9194,d9196],[d9196,d9197],[d9196,d9198],[d9198,d9199],[d9198,d9200],[d9200,d9201],[d9200,d9202],[d9202,d9203],[d9202,d9204],[d9204,d9205],[d9204,d9206],[d9206,d9207],[d9206,d9208],[d9208,d9209],[d9208,d9210],[d9210,d9211],[d9210,d9212],[d9212,d9213],[d9212,d9214],[d9214,d9215],[d9214,d9216],[d9216,d9217],[d9216,d9218],[d9218,d9219],[d9218,d9220],[d9220,d9221],[d9220,d9222],[d9222,d9223],[d9222,d9224],[d9224,d9225],[d9224,d9226],[d9226,d9227],[d9226,d9228],[d9228,d9229],[d9228,d9230],[d9230,d9231],[d9230,d9232],[d9232,d9233],[d9232,d9234],[d9234,d9235],[d9234,d9236],[d9236,d9237],[d9236,d9238],[d9238,d9239],[d9238,d9240],[d9240,d9241],[d9240,d9242],[d9242,d9243],[d9242,d9244],[d9244,d9245],[d9244,d9246],[d9246,d9247],[d9246,d9248],[d9248,d9249],[d9248,d9250],[d9250,d9251],[d9250,d9252],[d9252,d9253],[d9252,d9254],[d9254,d9255],[d9254,d9256],[d9256,d9257],[d9256,d9258],[d9258,d9259],[d9258,d9260],[d9260,d9261],[d9260,d9262],[d9262,d9263],[d9262,d9264],[d9264,d9265],[d9264,d9266],[d9266,d9267],[d9266,d9268],[d9268,d9269],[d9268,d9270],[d9270,d9271],[d9270,d9272],[d9272,d9273],[d9272,d9274],[d9274,d9275],[d9274,d9276],[d9276,d9277],[d9276,d9278],[d9278,d9279],[d9278,d9280],[d9280,d9281],[d9280,d9282],[d9282,d9283],[d9282,d9284],[d9284,d9285],[d9284,d9286],[d9286,d9287],[d9286,d9288],[d9288,d9289],[d9288,d9290],[d9290,d9291],[d9290,d9292],[d9292,d9293],[d9292,d9294],[d9294,d9295],[d9294,d9296],[d9296,d9297],[d9296,d9298],[d9298,d9299],[d9298,d9300],[d9300,d9301],[d9300,d9302],[d9302,d9303],[d9302,d9304],[d9304,d9305],[d9304,d9306],[d9306,d9307],[d9306,d9308],[d9308,d9309],[d9308,d9310],[d9310,d9311],[d9310,d9312],[d9312,d9313],[d9312,d9314],[d9314,d9315],[d9314,d9316],[d9316,d9317],[d9316,d9318],[d9318,d9319],[d9318,d9320],[d9320,d9321],[d9320,d9322],[d9322,d9323],[d9322,d9324],[d9324,d9325],[d9324,d9326],[d9326,d9327],[d9326,d9328],[d9328,d9329],[d9328,d9330],[d9330,d9331],[d9330,d9332],[d9332,d9333],[d9332,d9334],[d9334,d9335],[d9334,d9336],[d9336,d9337],[d9336,d9338],[d9338,d9339],[d9338,d9340],[d9340,d9341],[d9340,d9342],[d9342,d9343],[d9342,d9344],[d9344,d9345],[d9344,d9346],[d9346,d9347],[d9346,d9348],[d9348,d9349],[d9348,d9350],[d9350,d9351],[d9350,d9352],[d9352,d9353],[d9352,d9354],[d9354,d9355],[d9354,d9356],[d9356,d9357],[d9356,d9358],[d9358,d9359],[d9358,d9360],[d9360,d9361],[d9360,d9362],[d9362,d9363],[d9362,d9364],[d9364,d9365],[d9364,d9366],[d9366,d9367],[d9366,d9368],[d9368,d9369],[d9368,d9370],[d9370,d9371],[d9370,d9372],[d9372,d9373],[d9372,d9374],[d9374,d9375],[d9374,d9376],[d9376,d9377],[d9376,d9378],[d9378,d9379],[d9378,d9380],[d9380,d9381],[d9380,d9382],[d9382,d9383],[d9382,d9384],[d9384,d9385],[d9384,d9386],[d9386,d9387],[d9386,d9388],[d9388,d9389],[d9388,d9390],[d9390,d9391],[d9390,d9392],[d9392,d9393],[d9392,d9394],[d9394,d9395],[d9394,d9396],[d9396,d9397],[d9396,d9398],[d9398,d9399],[d9398,d9400],[d9400,d9401],[d9400,d9402],[d9402,d9403],[d9402,d9404],[d9404,d9405],[d9404,d9406],[d9406,d9407],[d9406,d9408],[d9408,d9409],[d9408,d9410],[d9410,d9411],[d9410,d9412],[d9412,d9413],[d9412,d9414],[d9414,d9415],[d9414,d9416],[d9416,d9417],[d9416,d9418],[d9418,d9419],[d9418,d9420],[d9420,d9421],[d9420,d9422],[d9422,d9423],[d9422,d9424],[d9424,d9425],[d9424,d9426],[d9426,d9427],[d9426,d9428],[d9428,d9429],[d9428,d9430],[d9430,d9431],[d9430,d9432],[d9432,d9433],[d9432,d9434],[d9434,d9435],[d9434,d9436],[d9436,d9437],[d9436,d9438],[d9438,d9439],[d9438,d9440],[d9440,d9441],[d9440,d9442],[d9442,d9443],[d9442,d9444],[d9444,d9445],[d9444,d9446],[d9446,d9447],[d9446,d9448],[d9448,d9449],[d9448,d9450],[d9450,d9451],[d9450,d9452],[d9452,d9453],[d9452,d9454],[d9454,d9455],[d9454,d9456],[d9456,d9457],[d9456,d9458],[d9458,d9459],[d9458,d9460],[d9460,d9461],[d9460,d9462],[d9462,d9463],[d9462,d9464],[d9464,d9465],[d9464,d9466],[d9466,d9467],[d9466,d9468],[d9468,d9469],[d9468,d9470],[d9470,d9471],[d9470,d9472],[d9472,d9473],[d9472,d9474],[d9474,d9475],[d9474,d9476],[d9476,d9477],[d9476,d9478],[d9478,d9479],[d9478,d9480],[d9480,d9481],[d9480,d9482],[d9482,d9483],[d9482,d9484],[d9484,d9485],[d9484,d9486],[d9486,d9487],[d9486,d9488],[d9488,d9489],[d9488,d9490],[d9490,d9491],[d9490,d9492],[d9492,d9493],[d9492,d9494],[d9494,d9495],[d9494,d9496],[d9496,d9497],[d9496,d9498],[d9498,d9499],[d9498,d9500],[d9500,d9501],[d9500,d9502],[d9502,d9503],[d9502,d9504],[d9504,d9505],[d9504,d9506],[d9506,d9507],[d9506,d9508],[d9508,d9509],[d9508,d9510],[d9510,d9511],[d9510,d9512],[d9512,d9513],[d9512,d9514],[d9514,d9515],[d9514,d9516],[d9516,d9517],[d9516,d9518],[d9518,d9519],[d9518,d9520],[d9520,d9521],[d9520,d9522],[d9522,d9523],[d9522,d9524],[d9524,d9525],[d9524,d9526],[d9526,d9527],[d9526,d9528],[d9528,d9529],[d9528,d9530],[d9530,d9531],[d9530,d9532],[d9532,d9533],[d9532,d9534],[d9534,d9535],[d9534,d9536],[d9536,d9537],[d9536,d9538],[d9538,d9539],[d9538,d9540],[d9540,d9541],[d9540,d9542],[d9542,d9543],[d9542,d9544],[d9544,d9545],[d9544,d9546],[d9546,d9547],[d9546,d9548],[d9548,d9549],[d9548,d9550],[d9550,d9551],[d9550,d9552],[d9552,d9553],[d9552,d9554],[d9554,d9555],[d9554,d9556],[d9556,d9557],[d9556,d9558],[d9558,d9559],[d9558,d9560],[d9560,d9561],[d9560,d9562],[d9562,d9563],[d9562,d9564],[d9564,d9565],[d9564,d9566],[d9566,d9567],[d9566,d9568],[d9568,d9569],[d9568,d9570],[d9570,d9571],[d9570,d9572],[d9572,d9573],[d9572,d9574],[d9574,d9575],[d9574,d9576],[d9576,d9577],[d9576,d9578],[d9578,d9579],[d9578,d9580],[d9580,d9581],[d9580,d9582],[d9582,d9583],[d9582,d9584],[d9584,d9585],[d9584,d9586],[d9586,d9587],[d9586,d9588],[d9588,d9589],[d9588,d9590],[d9590,d9591],[d9590,d9592],[d9592,d9593],[d9592,d9594],[d9594,d9595],[d9594,d9596],[d9596,d9597],[d9596,d9598],[d9598,d9599],[d9598,d9600],[d9600,d9601],[d9600,d9602],[d9602,d9603],[d9602,d9604],[d9604,d9605],[d9604,d9606],[d9606,d9607],[d9606,d9608],[d9608,d9609],[d9608,d9610],[d9610,d9611],[d9610,d9612],[d9612,d9613],[d9612,d9614],[d9614,d9615],[d9614,d9616],[d9616,d9617],[d9616,d9618],[d9618,d9619],[d9618,d9620],[d9620,d9621],[d9620,d9622],[d9622,d9623],[d9622,d9624],[d9624,d9625],[d9624,d9626],[d9626,d9627],[d9626,d9628],[d9628,d9629],[d9628,d9630],[d9630,d9631],[d9630,d9632],[d9632,d9633],[d9632,d9634],[d9634,d9635],[d9634,d9636],[d9636,d9637],[d9636,d9638],[d9638,d9639],[d9638,d9640],[d9640,d9641],[d9640,d9642],[d9642,d9643],[d9642,d9644],[d9644,d9645],[d9644,d9646],[d9646,d9647],[d9646,d9648],[d9648,d9649],[d9648,d9650],[d9650,d9651],[d9650,d9652],[d9652,d9653],[d9652,d9654],[d9654,d9655],[d9654,d9656],[d9656,d9657],[d9656,d9658],[d9658,d9659],[d9658,d9660],[d9660,d9661],[d9660,d9662],[d9662,d9663],[d9662,d9664],[d9664,d9665],[d9664,d9666],[d9666,d9667],[d9666,d9668],[d9668,d9669],[d9668,d9670],[d9670,d9671],[d9670,d9672],[d9672,d9673],[d9672,d9674],[d9674,d9675],[d9674,d9676],[d9676,d9677],[d9676,d9678],[d9678,d9679],[d9678,d9680],[d9680,d9681],[d9680,d9682],[d9682,d9683],[d9682,d9684],[d9684,d9685],[d9684,d9686],[d9686,d9687],[d9686,d9688],[d9688,d9689],[d9688,d9690],[d9690,d9691],[d9690,d9692],[d9692,d9693],[d9692,d9694],[d9694,d9695],[d9694,d9696],[d9696,d9697],[d9696,d9698],[d9698,d9699],[d9698,d9700],[d9700,d9701],[d9700,d9702],[d9702,d9703],[d9702,d9704],[d9704,d9705],[d9704,d9706],[d9706,d9707],[d9706,d9708],[d9708,d9709],[d9708,d9710],[d9710,d9711],[d9710,d9712],[d9712,d9713],[d9712,d9714],[d9714,d9715],[d9714,d9716],[d9716,d9717],[d9716,d9718],[d9718,d9719],[d9718,d9720],[d9720,d9721],[d9720,d9722],[d9722,d9723],[d9722,d9724],[d9724,d9725],[d9724,d9726],[d9726,d9727],[d9726,d9728],[d9728,d9729],[d9728,d9730],[d9730,d9731],[d9730,d9732],[d9732,d9733],[d9732,d9734],[d9734,d9735],[d9734,d9736],[d9736,d9737],[d9736,d9738],[d9738,d9739],[d9738,d9740],[d9740,d9741],[d9740,d9742],[d9742,d9743],[d9742,d9744],[d9744,d9745],[d9744,d9746],[d9746,d9747],[d9746,d9748],[d9748,d9749],[d9748,d9750],[d9750,d9751],[d9750,d9752],[d9752,d9753],[d9752,d9754],[d9754,d9755],[d9754,d9756],[d9756,d9757],[d9756,d9758],[d9758,d9759],[d9758,d9760],[d9760,d9761],[d9760,d9762],[d9762,d9763],[d9762,d9764],[d9764,d9765],[d9764,d9766],[d9766,d9767],[d9766,d9768],[d9768,d9769],[d9768,d9770],[d9770,d9771],[d9770,d9772],[d9772,d9773],[d9772,d9774],[d9774,d9775],[d9774,d9776],[d9776,d9777],[d9776,d9778],[d9778,d9779],[d9778,d9780],[d9780,d9781],[d9780,d9782],[d9782,d9783],[d9782,d9784],[d9784,d9785],[d9784,d9786],[d9786,d9787],[d9786,d9788],[d9788,d9789],[d9788,d9790],[d9790,d9791],[d9790,d9792],[d9792,d9793],[d9792,d9794],[d9794,d9795],[d9794,d9796],[d9796,d9797],[d9796,d9798],[d9798,d9799],[d9798,d9800],[d9800,d9801],[d9800,d9802],[d9802,d9803],[d9802,d9804],[d9804,d9805],[d9804,d9806],[d9806,d9807],[d9806,d9808],[d9808,d9809],[d9808,d9810],[d9810,d9811],[d9810,d9812],[d9812,d9813],[d9812,d9814],[d9814,d9815],[d9814,d9816],[d9816,d9817],[d9816,d9818],[d9818,d9819],[d9818,d9820],[d9820,d9821],[d9820,d9822],[d9822,d9823],[d9822,d9824],[d9824,d9825],[d9824,d9826],[d9826,d9827],[d9826,d9828],[d9828,d9829],[d9828,d9830],[d9830,d9831],[d9830,d9832],[d9832,d9833],[d9832,d9834],[d9834,d9835],[d9834,d9836],[d9836,d9837],[d9836,d9838],[d9838,d9839],[d9838,d9840],[d9840,d9841],[d9840,d9842],[d9842,d9843],[d9842,d9844],[d9844,d9845],[d9844,d9846],[d9846,d9847],[d9846,d9848],[d9848,d9849],[d9848,d9850],[d9850,d9851],[d9850,d9852],[d9852,d9853],[d9852,d9854],[d9854,d9855],[d9854,d9856],[d9856,d9857],[d9856,d9858],[d9858,d9859],[d9858,d9860],[d9860,d9861],[d9860,d9862],[d9862,d9863],[d9862,d9864],[d9864,d9865],[d9864,d9866],[d9866,d9867],[d9866,d9868],[d9868,d9869],[d9868,d9870],[d9870,d9871],[d9870,d9872],[d9872,d9873],[d9872,d9874],[d9874,d9875],[d9874,d9876],[d9876,d9877],[d9876,d9878],[d9878,d9879],[d9878,d9880],[d9880,d9881],[d9880,d9882],[d9882,d9883],[d9882,d9884],[d9884,d9885],[d9884,d9886],[d9886,d9887],[d9886,d9888],[d9888,d9889],[d9888,d9890],[d9890,d9891],[d9890,d9892],[d9892,d9893],[d9892,d9894],[d9894,d9895],[d9894,d9896],[d9896,d9897],[d9896,d9898],[d9898,d9899],[d9898,d9900],[d9900,d9901],[d9900,d9902],[d9902,d9903],[d9902,d9904],[d9904,d9905],[d9904,d9906],[d9906,d9907],[d9906,d9908],[d9908,d9909],[d9908,d9910],[d9910,d9911],[d9910,d9912],[d9912,d9913],[d9912,d9914],[d9914,d9915],[d9914,d9916],[d9916,d9917],[d9916,d9918],[d9918,d9919],[d9918,d9920],[d9920,d9921],[d9920,d9922],[d9922,d9923],[d9922,d9924],[d9924,d9925],[d9924,d9926],[d9926,d9927],[d9926,d9928],[d9928,d9929],[d9928,d9930],[d9930,d9931],[d9930,d9932],[d9932,d9933],[d9932,d9934],[d9934,d9935],[d9934,d9936],[d9936,d9937],[d9936,d9938],[d9938,d9939],[d9938,d9940],[d9940,d9941],[d9940,d9942],[d9942,d9943],[d9942,d9944],[d9944,d9945],[d9944,d9946],[d9946,d9947],[d9946,d9948],[d9948,d9949],[d9948,d9950],[d9950,d9951],[d9950,d9952],[d9952,d9953],[d9952,d9954],[d9954,d9955],[d9954,d9956],[d9956,d9957],[d9956,d9958],[d9958,d9959],[d9958,d9960],[d9960,d9961],[d9960,d9962],[d9962,d9963],[d9962,d9964],[d9964,d9965],[d9964,d9966],[d9966,d9967],[d9966,d9968],[d9968,d9969],[d9968,d9970],[d9970,d9971],[d9970,d9972],[d9972,d9973],[d9972,d9974],[d9974,d9975],[d9974,d9976],[d9976,d9977],[d9976,d9978],[d9978,d9979],[d9978,d9980],[d9980,d9981],[d9980,d9982],[d9982,d9983],[d9982,d9984],[d9984,d9985],[d9984,d9986],[d9986,d9987],[d9986,d9988],[d9988,d9989],[d9988,d9990],[d9990,d9991],[d9990,d9992],[d9992,d9993],[d9992,d9994],[d9994,d9995],[d9994,d9996],[d9996,d9997],[d9996,d9998],[d1,f0],[d1,f1],[d3,f2],[d3,f3],[d5,f4],[d5,f5],[d7,f6],[d7,f7],[d9,f8],[d9,f9],[d11,f10],[d11,f11],[d13,f12],[d13,f13],[d15,f14],[d15,f15],[d17,f16],[d17,f17],[d19,f18],[d19,f19],[d21,f20],[d21,f21],[d23,f22],[d23,f23],[d25,f24],[d25,f25],[d27,f26],[d27,f27],[d29,f28],[d29,f29],[d31,f30],[d31,f31],[d33,f32],[d33,f33],[d35,f34],[d35,f35],[d37,f36],[d37,f37],[d39,f38],[d39,f39],[d41,f40],[d41,f41],[d43,f42],[d43,f43],[d45,f44],[d45,f45],[d47,f46],[d47,f47],[d49,f48],[d49,f49],[d51,f50],[d51,f51],[d53,f52],[d53,f53],[d55,f54],[d55,f55],[d57,f56],[d57,f57],[d59,f58],[d59,f59],[d61,f60],[d61,f61],[d63,f62],[d63,f63],[d65,f64],[d65,f65],[d67,f66],[d67,f67],[d69,f68],[d69,f69],[d71,f70],[d71,f71],[d73,f72],[d73,f73],[d75,f74],[d75,f75],[d77,f76],[d77,f77],[d79,f78],[d79,f79],[d81,f80],[d81,f81],[d83,f82],[d83,f83],[d85,f84],[d85,f85],[d87,f86],[d87,f87],[d89,f88],[d89,f89],[d91,f90],[d91,f91],[d93,f92],[d93,f93],[d95,f94],[d95,f95],[d97,f96],[d97,f97],[d99,f98],[d99,f99],[d101,f100],[d101,f101],[d103,f102],[d103,f103],[d105,f104],[d105,f105],[d107,f106],[d107,f107],[d109,f108],[d109,f109],[d111,f110],[d111,f111],[d113,f112],[d113,f113],[d115,f114],[d115,f115],[d117,f116],[d117,f117],[d119,f118],[d119,f119],[d121,f120],[d121,f121],[d123,f122],[d123,f123],[d125,f124],[d125,f125],[d127,f126],[d127,f127],[d129,f128],[d129,f129],[d131,f130],[d131,f131],[d133,f132],[d133,f133],[d135,f134],[d135,f135],[d137,f136],[d137,f137],[d139,f138],[d139,f139],[d141,f140],[d141,f141],[d143,f142],[d143,f143],[d145,f144],[d145,f145],[d147,f146],[d147,f147],[d149,f148],[d149,f149],[d151,f150],[d151,f151],[d153,f152],[d153,f153],[d155,f154],[d155,f155],[d157,f156],[d157,f157],[d159,f158],[d159,f159],[d161,f160],[d161,f161],[d163,f162],[d163,f163],[d165,f164],[d165,f165],[d167,f166],[d167,f167],[d169,f168],[d169,f169],[d171,f170],[d171,f171],[d173,f172],[d173,f173],[d175,f174],[d175,f175],[d177,f176],[d177,f177],[d179,f178],[d179,f179],[d181,f180],[d181,f181],[d183,f182],[d183,f183],[d185,f184],[d185,f185],[d187,f186],[d187,f187],[d189,f188],[d189,f189],[d191,f190],[d191,f191],[d193,f192],[d193,f193],[d195,f194],[d195,f195],[d197,f196],[d197,f197],[d199,f198],[d199,f199],[d201,f200],[d201,f201],[d203,f202],[d203,f203],[d205,f204],[d205,f205],[d207,f206],[d207,f207],[d209,f208],[d209,f209],[d211,f210],[d211,f211],[d213,f212],[d213,f213],[d215,f214],[d215,f215],[d217,f216],[d217,f217],[d219,f218],[d219,f219],[d221,f220],[d221,f221],[d223,f222],[d223,f223],[d225,f224],[d225,f225],[d227,f226],[d227,f227],[d229,f228],[d229,f229],[d231,f230],[d231,f231],[d233,f232],[d233,f233],[d235,f234],[d235,f235],[d237,f236],[d237,f237],[d239,f238],[d239,f239],[d241,f240],[d241,f241],[d243,f242],[d243,f243],[d245,f244],[d245,f245],[d247,f246],[d247,f247],[d249,f248],[d249,f249],[d251,f250],[d251,f251],[d253,f252],[d253,f253],[d255,f254],[d255,f255],[d257,f256],[d257,f257],[d259,f258],[d259,f259],[d261,f260],[d261,f261],[d263,f262],[d263,f263],[d265,f264],[d265,f265],[d267,f266],[d267,f267],[d269,f268],[d269,f269],[d271,f270],[d271,f271],[d273,f272],[d273,f273],[d275,f274],[d275,f275],[d277,f276],[d277,f277],[d279,f278],[d279,f279],[d281,f280],[d281,f281],[d283,f282],[d283,f283],[d285,f284],[d285,f285],[d287,f286],[d287,f287],[d289,f288],[d289,f289],[d291,f290],[d291,f291],[d293,f292],[d293,f293],[d295,f294],[d295,f295],[d297,f296],[d297,f297],[d299,f298],[d299,f299],[d301,f300],[d301,f301],[d303,f302],[d303,f303],[d305,f304],[d305,f305],[d307,f306],[d307,f307],[d309,f308],[d309,f309],[d311,f310],[d311,f311],[d313,f312],[d313,f313],[d315,f314],[d315,f315],[d317,f316],[d317,f317],[d319,f318],[d319,f319],[d321,f320],[d321,f321],[d323,f322],[d323,f323],[d325,f324],[d325,f325],[d327,f326],[d327,f327],[d329,f328],[d329,f329],[d331,f330],[d331,f331],[d333,f332],[d333,f333],[d335,f334],[d335,f335],[d337,f336],[d337,f337],[d339,f338],[d339,f339],[d341,f340],[d341,f341],[d343,f342],[d343,f343],[d345,f344],[d345,f345],[d347,f346],[d347,f347],[d349,f348],[d349,f349],[d351,f350],[d351,f351],[d353,f352],[d353,f353],[d355,f354],[d355,f355],[d357,f356],[d357,f357],[d359,f358],[d359,f359],[d361,f360],[d361,f361],[d363,f362],[d363,f363],[d365,f364],[d365,f365],[d367,f366],[d367,f367],[d369,f368],[d369,f369],[d371,f370],[d371,f371],[d373,f372],[d373,f373],[d375,f374],[d375,f375],[d377,f376],[d377,f377],[d379,f378],[d379,f379],[d381,f380],[d381,f381],[d383,f382],[d383,f383],[d385,f384],[d385,f385],[d387,f386],[d387,f387],[d389,f388],[d389,f389],[d391,f390],[d391,f391],[d393,f392],[d393,f393],[d395,f394],[d395,f395],[d397,f396],[d397,f397],[d399,f398],[d399,f399],[d401,f400],[d401,f401],[d403,f402],[d403,f403],[d405,f404],[d405,f405],[d407,f406],[d407,f407],[d409,f408],[d409,f409],[d411,f410],[d411,f411],[d413,f412],[d413,f413],[d415,f414],[d415,f415],[d417,f416],[d417,f417],[d419,f418],[d419,f419],[d421,f420],[d421,f421],[d423,f422],[d423,f423],[d425,f424],[d425,f425],[d427,f426],[d427,f427],[d429,f428],[d429,f429],[d431,f430],[d431,f431],[d433,f432],[d433,f433],[d435,f434],[d435,f435],[d437,f436],[d437,f437],[d439,f438],[d439,f439],[d441,f440],[d441,f441],[d443,f442],[d443,f443],[d445,f444],[d445,f445],[d447,f446],[d447,f447],[d449,f448],[d449,f449],[d451,f450],[d451,f451],[d453,f452],[d453,f453],[d455,f454],[d455,f455],[d457,f456],[d457,f457],[d459,f458],[d459,f459],[d461,f460],[d461,f461],[d463,f462],[d463,f463],[d465,f464],[d465,f465],[d467,f466],[d467,f467],[d469,f468],[d469,f469],[d471,f470],[d471,f471],[d473,f472],[d473,f473],[d475,f474],[d475,f475],[d477,f476],[d477,f477],[d479,f478],[d479,f479],[d481,f480],[d481,f481],[d483,f482],[d483,f483],[d485,f484],[d485,f485],[d487,f486],[d487,f487],[d489,f488],[d489,f489],[d491,f490],[d491,f491],[d493,f492],[d493,f493],[d495,f494],[d495,f495],[d497,f496],[d497,f497],[d499,f498],[d499,f499],[d501,f500],[d501,f501],[d503,f502],[d503,f503],[d505,f504],[d505,f505],[d507,f506],[d507,f507],[d509,f508],[d509,f509],[d511,f510],[d511,f511],[d513,f512],[d513,f513],[d515,f514],[d515,f515],[d517,f516],[d517,f517],[d519,f518],[d519,f519],[d521,f520],[d521,f521],[d523,f522],[d523,f523],[d525,f524],[d525,f525],[d527,f526],[d527,f527],[d529,f528],[d529,f529],[d531,f530],[d531,f531],[d533,f532],[d533,f533],[d535,f534],[d535,f535],[d537,f536],[d537,f537],[d539,f538],[d539,f539],[d541,f540],[d541,f541],[d543,f542],[d543,f543],[d545,f544],[d545,f545],[d547,f546],[d547,f547],[d549,f548],[d549,f549],[d551,f550],[d551,f551],[d553,f552],[d553,f553],[d555,f554],[d555,f555],[d557,f556],[d557,f557],[d559,f558],[d559,f559],[d561,f560],[d561,f561],[d563,f562],[d563,f563],[d565,f564],[d565,f565],[d567,f566],[d567,f567],[d569,f568],[d569,f569],[d571,f570],[d571,f571],[d573,f572],[d573,f573],[d575,f574],[d575,f575],[d577,f576],[d577,f577],[d579,f578],[d579,f579],[d581,f580],[d581,f581],[d583,f582],[d583,f583],[d585,f584],[d585,f585],[d587,f586],[d587,f587],[d589,f588],[d589,f589],[d591,f590],[d591,f591],[d593,f592],[d593,f593],[d595,f594],[d595,f595],[d597,f596],[d597,f597],[d599,f598],[d599,f599],[d601,f600],[d601,f601],[d603,f602],[d603,f603],[d605,f604],[d605,f605],[d607,f606],[d607,f607],[d609,f608],[d609,f609],[d611,f610],[d611,f611],[d613,f612],[d613,f613],[d615,f614],[d615,f615],[d617,f616],[d617,f617],[d619,f618],[d619,f619],[d621,f620],[d621,f621],[d623,f622],[d623,f623],[d625,f624],[d625,f625],[d627,f626],[d627,f627],[d629,f628],[d629,f629],[d631,f630],[d631,f631],[d633,f632],[d633,f633],[d635,f634],[d635,f635],[d637,f636],[d637,f637],[d639,f638],[d639,f639],[d641,f640],[d641,f641],[d643,f642],[d643,f643],[d645,f644],[d645,f645],[d647,f646],[d647,f647],[d649,f648],[d649,f649],[d651,f650],[d651,f651],[d653,f652],[d653,f653],[d655,f654],[d655,f655],[d657,f656],[d657,f657],[d659,f658],[d659,f659],[d661,f660],[d661,f661],[d663,f662],[d663,f663],[d665,f664],[d665,f665],[d667,f666],[d667,f667],[d669,f668],[d669,f669],[d671,f670],[d671,f671],[d673,f672],[d673,f673],[d675,f674],[d675,f675],[d677,f676],[d677,f677],[d679,f678],[d679,f679],[d681,f680],[d681,f681],[d683,f682],[d683,f683],[d685,f684],[d685,f685],[d687,f686],[d687,f687],[d689,f688],[d689,f689],[d691,f690],[d691,f691],[d693,f692],[d693,f693],[d695,f694],[d695,f695],[d697,f696],[d697,f697],[d699,f698],[d699,f699],[d701,f700],[d701,f701],[d703,f702],[d703,f703],[d705,f704],[d705,f705],[d707,f706],[d707,f707],[d709,f708],[d709,f709],[d711,f710],[d711,f711],[d713,f712],[d713,f713],[d715,f714],[d715,f715],[d717,f716],[d717,f717],[d719,f718],[d719,f719],[d721,f720],[d721,f721],[d723,f722],[d723,f723],[d725,f724],[d725,f725],[d727,f726],[d727,f727],[d729,f728],[d729,f729],[d731,f730],[d731,f731],[d733,f732],[d733,f733],[d735,f734],[d735,f735],[d737,f736],[d737,f737],[d739,f738],[d739,f739],[d741,f740],[d741,f741],[d743,f742],[d743,f743],[d745,f744],[d745,f745],[d747,f746],[d747,f747],[d749,f748],[d749,f749],[d751,f750],[d751,f751],[d753,f752],[d753,f753],[d755,f754],[d755,f755],[d757,f756],[d757,f757],[d759,f758],[d759,f759],[d761,f760],[d761,f761],[d763,f762],[d763,f763],[d765,f764],[d765,f765],[d767,f766],[d767,f767],[d769,f768],[d769,f769],[d771,f770],[d771,f771],[d773,f772],[d773,f773],[d775,f774],[d775,f775],[d777,f776],[d777,f777],[d779,f778],[d779,f779],[d781,f780],[d781,f781],[d783,f782],[d783,f783],[d785,f784],[d785,f785],[d787,f786],[d787,f787],[d789,f788],[d789,f789],[d791,f790],[d791,f791],[d793,f792],[d793,f793],[d795,f794],[d795,f795],[d797,f796],[d797,f797],[d799,f798],[d799,f799],[d801,f800],[d801,f801],[d803,f802],[d803,f803],[d805,f804],[d805,f805],[d807,f806],[d807,f807],[d809,f808],[d809,f809],[d811,f810],[d811,f811],[d813,f812],[d813,f813],[d815,f814],[d815,f815],[d817,f816],[d817,f817],[d819,f818],[d819,f819],[d821,f820],[d821,f821],[d823,f822],[d823,f823],[d825,f824],[d825,f825],[d827,f826],[d827,f827],[d829,f828],[d829,f829],[d831,f830],[d831,f831],[d833,f832],[d833,f833],[d835,f834],[d835,f835],[d837,f836],[d837,f837],[d839,f838],[d839,f839],[d841,f840],[d841,f841],[d843,f842],[d843,f843],[d845,f844],[d845,f845],[d847,f846],[d847,f847],[d849,f848],[d849,f849],[d851,f850],[d851,f851],[d853,f852],[d853,f853],[d855,f854],[d855,f855],[d857,f856],[d857,f857],[d859,f858],[d859,f859],[d861,f860],[d861,f861],[d863,f862],[d863,f863],[d865,f864],[d865,f865],[d867,f866],[d867,f867],[d869,f868],[d869,f869],[d871,f870],[d871,f871],[d873,f872],[d873,f873],[d875,f874],[d875,f875],[d877,f876],[d877,f877],[d879,f878],[d879,f879],[d881,f880],[d881,f881],[d883,f882],[d883,f883],[d885,f884],[d885,f885],[d887,f886],[d887,f887],[d889,f888],[d889,f889],[d891,f890],[d891,f891],[d893,f892],[d893,f893],[d895,f894],[d895,f895],[d897,f896],[d897,f897],[d899,f898],[d899,f899],[d901,f900],[d901,f901],[d903,f902],[d903,f903],[d905,f904],[d905,f905],[d907,f906],[d907,f907],[d909,f908],[d909,f909],[d911,f910],[d911,f911],[d913,f912],[d913,f913],[d915,f914],[d915,f915],[d917,f916],[d917,f917],[d919,f918],[d919,f919],[d921,f920],[d921,f921],[d923,f922],[d923,f923],[d925,f924],[d925,f925],[d927,f926],[d927,f927],[d929,f928],[d929,f929],[d931,f930],[d931,f931],[d933,f932],[d933,f933],[d935,f934],[d935,f935],[d937,f936],[d937,f937],[d939,f938],[d939,f939],[d941,f940],[d941,f941],[d943,f942],[d943,f943],[d945,f944],[d945,f945],[d947,f946],[d947,f947],[d949,f948],[d949,f949],[d951,f950],[d951,f951],[d953,f952],[d953,f953],[d955,f954],[d955,f955],[d957,f956],[d957,f957],[d959,f958],[d959,f959],[d961,f960],[d961,f961],[d963,f962],[d963,f963],[d965,f964],[d965,f965],[d967,f966],[d967,f967],[d969,f968],[d969,f969],[d971,f970],[d971,f971],[d973,f972],[d973,f973],[d975,f974],[d975,f975],[d977,f976],[d977,f977],[d979,f978],[d979,f979],[d981,f980],[d981,f981],[d983,f982],[d983,f983],[d985,f984],[d985,f985],[d987,f986],[d987,f987],[d989,f988],[d989,f989],[d991,f990],[d991,f991],[d993,f992],[d993,f993],[d995,f994],[d995,f995],[d997,f996],[d997,f997],[d999,f998],[d999,f999],[d1001,f1000],[d1001,f1001],[d1003,f1002],[d1003,f1003],[d1005,f1004],[d1005,f1005],[d1007,f1006],[d1007,f1007],[d1009,f1008],[d1009,f1009],[d1011,f1010],[d1011,f1011],[d1013,f1012],[d1013,f1013],[d1015,f1014],[d1015,f1015],[d1017,f1016],[d1017,f1017],[d1019,f1018],[d1019,f1019],[d1021,f1020],[d1021,f1021],[d1023,f1022],[d1023,f1023],[d1025,f1024],[d1025,f1025],[d1027,f1026],[d1027,f1027],[d1029,f1028],[d1029,f1029],[d1031,f1030],[d1031,f1031],[d1033,f1032],[d1033,f1033],[d1035,f1034],[d1035,f1035],[d1037,f1036],[d1037,f1037],[d1039,f1038],[d1039,f1039],[d1041,f1040],[d1041,f1041],[d1043,f1042],[d1043,f1043],[d1045,f1044],[d1045,f1045],[d1047,f1046],[d1047,f1047],[d1049,f1048],[d1049,f1049],[d1051,f1050],[d1051,f1051],[d1053,f1052],[d1053,f1053],[d1055,f1054],[d1055,f1055],[d1057,f1056],[d1057,f1057],[d1059,f1058],[d1059,f1059],[d1061,f1060],[d1061,f1061],[d1063,f1062],[d1063,f1063],[d1065,f1064],[d1065,f1065],[d1067,f1066],[d1067,f1067],[d1069,f1068],[d1069,f1069],[d1071,f1070],[d1071,f1071],[d1073,f1072],[d1073,f1073],[d1075,f1074],[d1075,f1075],[d1077,f1076],[d1077,f1077],[d1079,f1078],[d1079,f1079],[d1081,f1080],[d1081,f1081],[d1083,f1082],[d1083,f1083],[d1085,f1084],[d1085,f1085],[d1087,f1086],[d1087,f1087],[d1089,f1088],[d1089,f1089],[d1091,f1090],[d1091,f1091],[d1093,f1092],[d1093,f1093],[d1095,f1094],[d1095,f1095],[d1097,f1096],[d1097,f1097],[d1099,f1098],[d1099,f1099],[d1101,f1100],[d1101,f1101],[d1103,f1102],[d1103,f1103],[d1105,f1104],[d1105,f1105],[d1107,f1106],[d1107,f1107],[d1109,f1108],[d1109,f1109],[d1111,f1110],[d1111,f1111],[d1113,f1112],[d1113,f1113],[d1115,f1114],[d1115,f1115],[d1117,f1116],[d1117,f1117],[d1119,f1118],[d1119,f1119],[d1121,f1120],[d1121,f1121],[d1123,f1122],[d1123,f1123],[d1125,f1124],[d1125,f1125],[d1127,f1126],[d1127,f1127],[d1129,f1128],[d1129,f1129],[d1131,f1130],[d1131,f1131],[d1133,f1132],[d1133,f1133],[d1135,f1134],[d1135,f1135],[d1137,f1136],[d1137,f1137],[d1139,f1138],[d1139,f1139],[d1141,f1140],[d1141,f1141],[d1143,f1142],[d1143,f1143],[d1145,f1144],[d1145,f1145],[d1147,f1146],[d1147,f1147],[d1149,f1148],[d1149,f1149],[d1151,f1150],[d1151,f1151],[d1153,f1152],[d1153,f1153],[d1155,f1154],[d1155,f1155],[d1157,f1156],[d1157,f1157],[d1159,f1158],[d1159,f1159],[d1161,f1160],[d1161,f1161],[d1163,f1162],[d1163,f1163],[d1165,f1164],[d1165,f1165],[d1167,f1166],[d1167,f1167],[d1169,f1168],[d1169,f1169],[d1171,f1170],[d1171,f1171],[d1173,f1172],[d1173,f1173],[d1175,f1174],[d1175,f1175],[d1177,f1176],[d1177,f1177],[d1179,f1178],[d1179,f1179],[d1181,f1180],[d1181,f1181],[d1183,f1182],[d1183,f1183],[d1185,f1184],[d1185,f1185],[d1187,f1186],[d1187,f1187],[d1189,f1188],[d1189,f1189],[d1191,f1190],[d1191,f1191],[d1193,f1192],[d1193,f1193],[d1195,f1194],[d1195,f1195],[d1197,f1196],[d1197,f1197],[d1199,f1198],[d1199,f1199],[d1201,f1200],[d1201,f1201],[d1203,f1202],[d1203,f1203],[d1205,f1204],[d1205,f1205],[d1207,f1206],[d1207,f1207],[d1209,f1208],[d1209,f1209],[d1211,f1210],[d1211,f1211],[d1213,f1212],[d1213,f1213],[d1215,f1214],[d1215,f1215],[d1217,f1216],[d1217,f1217],[d1219,f1218],[d1219,f1219],[d1221,f1220],[d1221,f1221],[d1223,f1222],[d1223,f1223],[d1225,f1224],[d1225,f1225],[d1227,f1226],[d1227,f1227],[d1229,f1228],[d1229,f1229],[d1231,f1230],[d1231,f1231],[d1233,f1232],[d1233,f1233],[d1235,f1234],[d1235,f1235],[d1237,f1236],[d1237,f1237],[d1239,f1238],[d1239,f1239],[d1241,f1240],[d1241,f1241],[d1243,f1242],[d1243,f1243],[d1245,f1244],[d1245,f1245],[d1247,f1246],[d1247,f1247],[d1249,f1248],[d1249,f1249],[d1251,f1250],[d1251,f1251],[d1253,f1252],[d1253,f1253],[d1255,f1254],[d1255,f1255],[d1257,f1256],[d1257,f1257],[d1259,f1258],[d1259,f1259],[d1261,f1260],[d1261,f1261],[d1263,f1262],[d1263,f1263],[d1265,f1264],[d1265,f1265],[d1267,f1266],[d1267,f1267],[d1269,f1268],[d1269,f1269],[d1271,f1270],[d1271,f1271],[d1273,f1272],[d1273,f1273],[d1275,f1274],[d1275,f1275],[d1277,f1276],[d1277,f1277],[d1279,f1278],[d1279,f1279],[d1281,f1280],[d1281,f1281],[d1283,f1282],[d1283,f1283],[d1285,f1284],[d1285,f1285],[d1287,f1286],[d1287,f1287],[d1289,f1288],[d1289,f1289],[d1291,f1290],[d1291,f1291],[d1293,f1292],[d1293,f1293],[d1295,f1294],[d1295,f1295],[d1297,f1296],[d1297,f1297],[d1299,f1298],[d1299,f1299],[d1301,f1300],[d1301,f1301],[d1303,f1302],[d1303,f1303],[d1305,f1304],[d1305,f1305],[d1307,f1306],[d1307,f1307],[d1309,f1308],[d1309,f1309],[d1311,f1310],[d1311,f1311],[d1313,f1312],[d1313,f1313],[d1315,f1314],[d1315,f1315],[d1317,f1316],[d1317,f1317],[d1319,f1318],[d1319,f1319],[d1321,f1320],[d1321,f1321],[d1323,f1322],[d1323,f1323],[d1325,f1324],[d1325,f1325],[d1327,f1326],[d1327,f1327],[d1329,f1328],[d1329,f1329],[d1331,f1330],[d1331,f1331],[d1333,f1332],[d1333,f1333],[d1335,f1334],[d1335,f1335],[d1337,f1336],[d1337,f1337],[d1339,f1338],[d1339,f1339],[d1341,f1340],[d1341,f1341],[d1343,f1342],[d1343,f1343],[d1345,f1344],[d1345,f1345],[d1347,f1346],[d1347,f1347],[d1349,f1348],[d1349,f1349],[d1351,f1350],[d1351,f1351],[d1353,f1352],[d1353,f1353],[d1355,f1354],[d1355,f1355],[d1357,f1356],[d1357,f1357],[d1359,f1358],[d1359,f1359],[d1361,f1360],[d1361,f1361],[d1363,f1362],[d1363,f1363],[d1365,f1364],[d1365,f1365],[d1367,f1366],[d1367,f1367],[d1369,f1368],[d1369,f1369],[d1371,f1370],[d1371,f1371],[d1373,f1372],[d1373,f1373],[d1375,f1374],[d1375,f1375],[d1377,f1376],[d1377,f1377],[d1379,f1378],[d1379,f1379],[d1381,f1380],[d1381,f1381],[d1383,f1382],[d1383,f1383],[d1385,f1384],[d1385,f1385],[d1387,f1386],[d1387,f1387],[d1389,f1388],[d1389,f1389],[d1391,f1390],[d1391,f1391],[d1393,f1392],[d1393,f1393],[d1395,f1394],[d1395,f1395],[d1397,f1396],[d1397,f1397],[d1399,f1398],[d1399,f1399],[d1401,f1400],[d1401,f1401],[d1403,f1402],[d1403,f1403],[d1405,f1404],[d1405,f1405],[d1407,f1406],[d1407,f1407],[d1409,f1408],[d1409,f1409],[d1411,f1410],[d1411,f1411],[d1413,f1412],[d1413,f1413],[d1415,f1414],[d1415,f1415],[d1417,f1416],[d1417,f1417],[d1419,f1418],[d1419,f1419],[d1421,f1420],[d1421,f1421],[d1423,f1422],[d1423,f1423],[d1425,f1424],[d1425,f1425],[d1427,f1426],[d1427,f1427],[d1429,f1428],[d1429,f1429],[d1431,f1430],[d1431,f1431],[d1433,f1432],[d1433,f1433],[d1435,f1434],[d1435,f1435],[d1437,f1436],[d1437,f1437],[d1439,f1438],[d1439,f1439],[d1441,f1440],[d1441,f1441],[d1443,f1442],[d1443,f1443],[d1445,f1444],[d1445,f1445],[d1447,f1446],[d1447,f1447],[d1449,f1448],[d1449,f1449],[d1451,f1450],[d1451,f1451],[d1453,f1452],[d1453,f1453],[d1455,f1454],[d1455,f1455],[d1457,f1456],[d1457,f1457],[d1459,f1458],[d1459,f1459],[d1461,f1460],[d1461,f1461],[d1463,f1462],[d1463,f1463],[d1465,f1464],[d1465,f1465],[d1467,f1466],[d1467,f1467],[d1469,f1468],[d1469,f1469],[d1471,f1470],[d1471,f1471],[d1473,f1472],[d1473,f1473],[d1475,f1474],[d1475,f1475],[d1477,f1476],[d1477,f1477],[d1479,f1478],[d1479,f1479],[d1481,f1480],[d1481,f1481],[d1483,f1482],[d1483,f1483],[d1485,f1484],[d1485,f1485],[d1487,f1486],[d1487,f1487],[d1489,f1488],[d1489,f1489],[d1491,f1490],[d1491,f1491],[d1493,f1492],[d1493,f1493],[d1495,f1494],[d1495,f1495],[d1497,f1496],[d1497,f1497],[d1499,f1498],[d1499,f1499],[d1501,f1500],[d1501,f1501],[d1503,f1502],[d1503,f1503],[d1505,f1504],[d1505,f1505],[d1507,f1506],[d1507,f1507],[d1509,f1508],[d1509,f1509],[d1511,f1510],[d1511,f1511],[d1513,f1512],[d1513,f1513],[d1515,f1514],[d1515,f1515],[d1517,f1516],[d1517,f1517],[d1519,f1518],[d1519,f1519],[d1521,f1520],[d1521,f1521],[d1523,f1522],[d1523,f1523],[d1525,f1524],[d1525,f1525],[d1527,f1526],[d1527,f1527],[d1529,f1528],[d1529,f1529],[d1531,f1530],[d1531,f1531],[d1533,f1532],[d1533,f1533],[d1535,f1534],[d1535,f1535],[d1537,f1536],[d1537,f1537],[d1539,f1538],[d1539,f1539],[d1541,f1540],[d1541,f1541],[d1543,f1542],[d1543,f1543],[d1545,f1544],[d1545,f1545],[d1547,f1546],[d1547,f1547],[d1549,f1548],[d1549,f1549],[d1551,f1550],[d1551,f1551],[d1553,f1552],[d1553,f1553],[d1555,f1554],[d1555,f1555],[d1557,f1556],[d1557,f1557],[d1559,f1558],[d1559,f1559],[d1561,f1560],[d1561,f1561],[d1563,f1562],[d1563,f1563],[d1565,f1564],[d1565,f1565],[d1567,f1566],[d1567,f1567],[d1569,f1568],[d1569,f1569],[d1571,f1570],[d1571,f1571],[d1573,f1572],[d1573,f1573],[d1575,f1574],[d1575,f1575],[d1577,f1576],[d1577,f1577],[d1579,f1578],[d1579,f1579],[d1581,f1580],[d1581,f1581],[d1583,f1582],[d1583,f1583],[d1585,f1584],[d1585,f1585],[d1587,f1586],[d1587,f1587],[d1589,f1588],[d1589,f1589],[d1591,f1590],[d1591,f1591],[d1593,f1592],[d1593,f1593],[d1595,f1594],[d1595,f1595],[d1597,f1596],[d1597,f1597],[d1599,f1598],[d1599,f1599],[d1601,f1600],[d1601,f1601],[d1603,f1602],[d1603,f1603],[d1605,f1604],[d1605,f1605],[d1607,f1606],[d1607,f1607],[d1609,f1608],[d1609,f1609],[d1611,f1610],[d1611,f1611],[d1613,f1612],[d1613,f1613],[d1615,f1614],[d1615,f1615],[d1617,f1616],[d1617,f1617],[d1619,f1618],[d1619,f1619],[d1621,f1620],[d1621,f1621],[d1623,f1622],[d1623,f1623],[d1625,f1624],[d1625,f1625],[d1627,f1626],[d1627,f1627],[d1629,f1628],[d1629,f1629],[d1631,f1630],[d1631,f1631],[d1633,f1632],[d1633,f1633],[d1635,f1634],[d1635,f1635],[d1637,f1636],[d1637,f1637],[d1639,f1638],[d1639,f1639],[d1641,f1640],[d1641,f1641],[d1643,f1642],[d1643,f1643],[d1645,f1644],[d1645,f1645],[d1647,f1646],[d1647,f1647],[d1649,f1648],[d1649,f1649],[d1651,f1650],[d1651,f1651],[d1653,f1652],[d1653,f1653],[d1655,f1654],[d1655,f1655],[d1657,f1656],[d1657,f1657],[d1659,f1658],[d1659,f1659],[d1661,f1660],[d1661,f1661],[d1663,f1662],[d1663,f1663],[d1665,f1664],[d1665,f1665],[d1667,f1666],[d1667,f1667],[d1669,f1668],[d1669,f1669],[d1671,f1670],[d1671,f1671],[d1673,f1672],[d1673,f1673],[d1675,f1674],[d1675,f1675],[d1677,f1676],[d1677,f1677],[d1679,f1678],[d1679,f1679],[d1681,f1680],[d1681,f1681],[d1683,f1682],[d1683,f1683],[d1685,f1684],[d1685,f1685],[d1687,f1686],[d1687,f1687],[d1689,f1688],[d1689,f1689],[d1691,f1690],[d1691,f1691],[d1693,f1692],[d1693,f1693],[d1695,f1694],[d1695,f1695],[d1697,f1696],[d1697,f1697],[d1699,f1698],[d1699,f1699],[d1701,f1700],[d1701,f1701],[d1703,f1702],[d1703,f1703],[d1705,f1704],[d1705,f1705],[d1707,f1706],[d1707,f1707],[d1709,f1708],[d1709,f1709],[d1711,f1710],[d1711,f1711],[d1713,f1712],[d1713,f1713],[d1715,f1714],[d1715,f1715],[d1717,f1716],[d1717,f1717],[d1719,f1718],[d1719,f1719],[d1721,f1720],[d1721,f1721],[d1723,f1722],[d1723,f1723],[d1725,f1724],[d1725,f1725],[d1727,f1726],[d1727,f1727],[d1729,f1728],[d1729,f1729],[d1731,f1730],[d1731,f1731],[d1733,f1732],[d1733,f1733],[d1735,f1734],[d1735,f1735],[d1737,f1736],[d1737,f1737],[d1739,f1738],[d1739,f1739],[d1741,f1740],[d1741,f1741],[d1743,f1742],[d1743,f1743],[d1745,f1744],[d1745,f1745],[d1747,f1746],[d1747,f1747],[d1749,f1748],[d1749,f1749],[d1751,f1750],[d1751,f1751],[d1753,f1752],[d1753,f1753],[d1755,f1754],[d1755,f1755],[d1757,f1756],[d1757,f1757],[d1759,f1758],[d1759,f1759],[d1761,f1760],[d1761,f1761],[d1763,f1762],[d1763,f1763],[d1765,f1764],[d1765,f1765],[d1767,f1766],[d1767,f1767],[d1769,f1768],[d1769,f1769],[d1771,f1770],[d1771,f1771],[d1773,f1772],[d1773,f1773],[d1775,f1774],[d1775,f1775],[d1777,f1776],[d1777,f1777],[d1779,f1778],[d1779,f1779],[d1781,f1780],[d1781,f1781],[d1783,f1782],[d1783,f1783],[d1785,f1784],[d1785,f1785],[d1787,f1786],[d1787,f1787],[d1789,f1788],[d1789,f1789],[d1791,f1790],[d1791,f1791],[d1793,f1792],[d1793,f1793],[d1795,f1794],[d1795,f1795],[d1797,f1796],[d1797,f1797],[d1799,f1798],[d1799,f1799],[d1801,f1800],[d1801,f1801],[d1803,f1802],[d1803,f1803],[d1805,f1804],[d1805,f1805],[d1807,f1806],[d1807,f1807],[d1809,f1808],[d1809,f1809],[d1811,f1810],[d1811,f1811],[d1813,f1812],[d1813,f1813],[d1815,f1814],[d1815,f1815],[d1817,f1816],[d1817,f1817],[d1819,f1818],[d1819,f1819],[d1821,f1820],[d1821,f1821],[d1823,f1822],[d1823,f1823],[d1825,f1824],[d1825,f1825],[d1827,f1826],[d1827,f1827],[d1829,f1828],[d1829,f1829],[d1831,f1830],[d1831,f1831],[d1833,f1832],[d1833,f1833],[d1835,f1834],[d1835,f1835],[d1837,f1836],[d1837,f1837],[d1839,f1838],[d1839,f1839],[d1841,f1840],[d1841,f1841],[d1843,f1842],[d1843,f1843],[d1845,f1844],[d1845,f1845],[d1847,f1846],[d1847,f1847],[d1849,f1848],[d1849,f1849],[d1851,f1850],[d1851,f1851],[d1853,f1852],[d1853,f1853],[d1855,f1854],[d1855,f1855],[d1857,f1856],[d1857,f1857],[d1859,f1858],[d1859,f1859],[d1861,f1860],[d1861,f1861],[d1863,f1862],[d1863,f1863],[d1865,f1864],[d1865,f1865],[d1867,f1866],[d1867,f1867],[d1869,f1868],[d1869,f1869],[d1871,f1870],[d1871,f1871],[d1873,f1872],[d1873,f1873],[d1875,f1874],[d1875,f1875],[d1877,f1876],[d1877,f1877],[d1879,f1878],[d1879,f1879],[d1881,f1880],[d1881,f1881],[d1883,f1882],[d1883,f1883],[d1885,f1884],[d1885,f1885],[d1887,f1886],[d1887,f1887],[d1889,f1888],[d1889,f1889],[d1891,f1890],[d1891,f1891],[d1893,f1892],[d1893,f1893],[d1895,f1894],[d1895,f1895],[d1897,f1896],[d1897,f1897],[d1899,f1898],[d1899,f1899],[d1901,f1900],[d1901,f1901],[d1903,f1902],[d1903,f1903],[d1905,f1904],[d1905,f1905],[d1907,f1906],[d1907,f1907],[d1909,f1908],[d1909,f1909],[d1911,f1910],[d1911,f1911],[d1913,f1912],[d1913,f1913],[d1915,f1914],[d1915,f1915],[d1917,f1916],[d1917,f1917],[d1919,f1918],[d1919,f1919],[d1921,f1920],[d1921,f1921],[d1923,f1922],[d1923,f1923],[d1925,f1924],[d1925,f1925],[d1927,f1926],[d1927,f1927],[d1929,f1928],[d1929,f1929],[d1931,f1930],[d1931,f1931],[d1933,f1932],[d1933,f1933],[d1935,f1934],[d1935,f1935],[d1937,f1936],[d1937,f1937],[d1939,f1938],[d1939,f1939],[d1941,f1940],[d1941,f1941],[d1943,f1942],[d1943,f1943],[d1945,f1944],[d1945,f1945],[d1947,f1946],[d1947,f1947],[d1949,f1948],[d1949,f1949],[d1951,f1950],[d1951,f1951],[d1953,f1952],[d1953,f1953],[d1955,f1954],[d1955,f1955],[d1957,f1956],[d1957,f1957],[d1959,f1958],[d1959,f1959],[d1961,f1960],[d1961,f1961],[d1963,f1962],[d1963,f1963],[d1965,f1964],[d1965,f1965],[d1967,f1966],[d1967,f1967],[d1969,f1968],[d1969,f1969],[d1971,f1970],[d1971,f1971],[d1973,f1972],[d1973,f1973],[d1975,f1974],[d1975,f1975],[d1977,f1976],[d1977,f1977],[d1979,f1978],[d1979,f1979],[d1981,f1980],[d1981,f1981],[d1983,f1982],[d1983,f1983],[d1985,f1984],[d1985,f1985],[d1987,f1986],[d1987,f1987],[d1989,f1988],[d1989,f1989],[d1991,f1990],[d1991,f1991],[d1993,f1992],[d1993,f1993],[d1995,f1994],[d1995,f1995],[d1997,f1996],[d1997,f1997],[d1999,f1998],[d1999,f1999],[d2001,f2000],[d2001,f2001],[d2003,f2002],[d2003,f2003],[d2005,f2004],[d2005,f2005],[d2007,f2006],[d2007,f2007],[d2009,f2008],[d2009,f2009],[d2011,f2010],[d2011,f2011],[d2013,f2012],[d2013,f2013],[d2015,f2014],[d2015,f2015],[d2017,f2016],[d2017,f2017],[d2019,f2018],[d2019,f2019],[d2021,f2020],[d2021,f2021],[d2023,f2022],[d2023,f2023],[d2025,f2024],[d2025,f2025],[d2027,f2026],[d2027,f2027],[d2029,f2028],[d2029,f2029],[d2031,f2030],[d2031,f2031],[d2033,f2032],[d2033,f2033],[d2035,f2034],[d2035,f2035],[d2037,f2036],[d2037,f2037],[d2039,f2038],[d2039,f2039],[d2041,f2040],[d2041,f2041],[d2043,f2042],[d2043,f2043],[d2045,f2044],[d2045,f2045],[d2047,f2046],[d2047,f2047],[d2049,f2048],[d2049,f2049],[d2051,f2050],[d2051,f2051],[d2053,f2052],[d2053,f2053],[d2055,f2054],[d2055,f2055],[d2057,f2056],[d2057,f2057],[d2059,f2058],[d2059,f2059],[d2061,f2060],[d2061,f2061],[d2063,f2062],[d2063,f2063],[d2065,f2064],[d2065,f2065],[d2067,f2066],[d2067,f2067],[d2069,f2068],[d2069,f2069],[d2071,f2070],[d2071,f2071],[d2073,f2072],[d2073,f2073],[d2075,f2074],[d2075,f2075],[d2077,f2076],[d2077,f2077],[d2079,f2078],[d2079,f2079],[d2081,f2080],[d2081,f2081],[d2083,f2082],[d2083,f2083],[d2085,f2084],[d2085,f2085],[d2087,f2086],[d2087,f2087],[d2089,f2088],[d2089,f2089],[d2091,f2090],[d2091,f2091],[d2093,f2092],[d2093,f2093],[d2095,f2094],[d2095,f2095],[d2097,f2096],[d2097,f2097],[d2099,f2098],[d2099,f2099],[d2101,f2100],[d2101,f2101],[d2103,f2102],[d2103,f2103],[d2105,f2104],[d2105,f2105],[d2107,f2106],[d2107,f2107],[d2109,f2108],[d2109,f2109],[d2111,f2110],[d2111,f2111],[d2113,f2112],[d2113,f2113],[d2115,f2114],[d2115,f2115],[d2117,f2116],[d2117,f2117],[d2119,f2118],[d2119,f2119],[d2121,f2120],[d2121,f2121],[d2123,f2122],[d2123,f2123],[d2125,f2124],[d2125,f2125],[d2127,f2126],[d2127,f2127],[d2129,f2128],[d2129,f2129],[d2131,f2130],[d2131,f2131],[d2133,f2132],[d2133,f2133],[d2135,f2134],[d2135,f2135],[d2137,f2136],[d2137,f2137],[d2139,f2138],[d2139,f2139],[d2141,f2140],[d2141,f2141],[d2143,f2142],[d2143,f2143],[d2145,f2144],[d2145,f2145],[d2147,f2146],[d2147,f2147],[d2149,f2148],[d2149,f2149],[d2151,f2150],[d2151,f2151],[d2153,f2152],[d2153,f2153],[d2155,f2154],[d2155,f2155],[d2157,f2156],[d2157,f2157],[d2159,f2158],[d2159,f2159],[d2161,f2160],[d2161,f2161],[d2163,f2162],[d2163,f2163],[d2165,f2164],[d2165,f2165],[d2167,f2166],[d2167,f2167],[d2169,f2168],[d2169,f2169],[d2171,f2170],[d2171,f2171],[d2173,f2172],[d2173,f2173],[d2175,f2174],[d2175,f2175],[d2177,f2176],[d2177,f2177],[d2179,f2178],[d2179,f2179],[d2181,f2180],[d2181,f2181],[d2183,f2182],[d2183,f2183],[d2185,f2184],[d2185,f2185],[d2187,f2186],[d2187,f2187],[d2189,f2188],[d2189,f2189],[d2191,f2190],[d2191,f2191],[d2193,f2192],[d2193,f2193],[d2195,f2194],[d2195,f2195],[d2197,f2196],[d2197,f2197],[d2199,f2198],[d2199,f2199],[d2201,f2200],[d2201,f2201],[d2203,f2202],[d2203,f2203],[d2205,f2204],[d2205,f2205],[d2207,f2206],[d2207,f2207],[d2209,f2208],[d2209,f2209],[d2211,f2210],[d2211,f2211],[d2213,f2212],[d2213,f2213],[d2215,f2214],[d2215,f2215],[d2217,f2216],[d2217,f2217],[d2219,f2218],[d2219,f2219],[d2221,f2220],[d2221,f2221],[d2223,f2222],[d2223,f2223],[d2225,f2224],[d2225,f2225],[d2227,f2226],[d2227,f2227],[d2229,f2228],[d2229,f2229],[d2231,f2230],[d2231,f2231],[d2233,f2232],[d2233,f2233],[d2235,f2234],[d2235,f2235],[d2237,f2236],[d2237,f2237],[d2239,f2238],[d2239,f2239],[d2241,f2240],[d2241,f2241],[d2243,f2242],[d2243,f2243],[d2245,f2244],[d2245,f2245],[d2247,f2246],[d2247,f2247],[d2249,f2248],[d2249,f2249],[d2251,f2250],[d2251,f2251],[d2253,f2252],[d2253,f2253],[d2255,f2254],[d2255,f2255],[d2257,f2256],[d2257,f2257],[d2259,f2258],[d2259,f2259],[d2261,f2260],[d2261,f2261],[d2263,f2262],[d2263,f2263],[d2265,f2264],[d2265,f2265],[d2267,f2266],[d2267,f2267],[d2269,f2268],[d2269,f2269],[d2271,f2270],[d2271,f2271],[d2273,f2272],[d2273,f2273],[d2275,f2274],[d2275,f2275],[d2277,f2276],[d2277,f2277],[d2279,f2278],[d2279,f2279],[d2281,f2280],[d2281,f2281],[d2283,f2282],[d2283,f2283],[d2285,f2284],[d2285,f2285],[d2287,f2286],[d2287,f2287],[d2289,f2288],[d2289,f2289],[d2291,f2290],[d2291,f2291],[d2293,f2292],[d2293,f2293],[d2295,f2294],[d2295,f2295],[d2297,f2296],[d2297,f2297],[d2299,f2298],[d2299,f2299],[d2301,f2300],[d2301,f2301],[d2303,f2302],[d2303,f2303],[d2305,f2304],[d2305,f2305],[d2307,f2306],[d2307,f2307],[d2309,f2308],[d2309,f2309],[d2311,f2310],[d2311,f2311],[d2313,f2312],[d2313,f2313],[d2315,f2314],[d2315,f2315],[d2317,f2316],[d2317,f2317],[d2319,f2318],[d2319,f2319],[d2321,f2320],[d2321,f2321],[d2323,f2322],[d2323,f2323],[d2325,f2324],[d2325,f2325],[d2327,f2326],[d2327,f2327],[d2329,f2328],[d2329,f2329],[d2331,f2330],[d2331,f2331],[d2333,f2332],[d2333,f2333],[d2335,f2334],[d2335,f2335],[d2337,f2336],[d2337,f2337],[d2339,f2338],[d2339,f2339],[d2341,f2340],[d2341,f2341],[d2343,f2342],[d2343,f2343],[d2345,f2344],[d2345,f2345],[d2347,f2346],[d2347,f2347],[d2349,f2348],[d2349,f2349],[d2351,f2350],[d2351,f2351],[d2353,f2352],[d2353,f2353],[d2355,f2354],[d2355,f2355],[d2357,f2356],[d2357,f2357],[d2359,f2358],[d2359,f2359],[d2361,f2360],[d2361,f2361],[d2363,f2362],[d2363,f2363],[d2365,f2364],[d2365,f2365],[d2367,f2366],[d2367,f2367],[d2369,f2368],[d2369,f2369],[d2371,f2370],[d2371,f2371],[d2373,f2372],[d2373,f2373],[d2375,f2374],[d2375,f2375],[d2377,f2376],[d2377,f2377],[d2379,f2378],[d2379,f2379],[d2381,f2380],[d2381,f2381],[d2383,f2382],[d2383,f2383],[d2385,f2384],[d2385,f2385],[d2387,f2386],[d2387,f2387],[d2389,f2388],[d2389,f2389],[d2391,f2390],[d2391,f2391],[d2393,f2392],[d2393,f2393],[d2395,f2394],[d2395,f2395],[d2397,f2396],[d2397,f2397],[d2399,f2398],[d2399,f2399],[d2401,f2400],[d2401,f2401],[d2403,f2402],[d2403,f2403],[d2405,f2404],[d2405,f2405],[d2407,f2406],[d2407,f2407],[d2409,f2408],[d2409,f2409],[d2411,f2410],[d2411,f2411],[d2413,f2412],[d2413,f2413],[d2415,f2414],[d2415,f2415],[d2417,f2416],[d2417,f2417],[d2419,f2418],[d2419,f2419],[d2421,f2420],[d2421,f2421],[d2423,f2422],[d2423,f2423],[d2425,f2424],[d2425,f2425],[d2427,f2426],[d2427,f2427],[d2429,f2428],[d2429,f2429],[d2431,f2430],[d2431,f2431],[d2433,f2432],[d2433,f2433],[d2435,f2434],[d2435,f2435],[d2437,f2436],[d2437,f2437],[d2439,f2438],[d2439,f2439],[d2441,f2440],[d2441,f2441],[d2443,f2442],[d2443,f2443],[d2445,f2444],[d2445,f2445],[d2447,f2446],[d2447,f2447],[d2449,f2448],[d2449,f2449],[d2451,f2450],[d2451,f2451],[d2453,f2452],[d2453,f2453],[d2455,f2454],[d2455,f2455],[d2457,f2456],[d2457,f2457],[d2459,f2458],[d2459,f2459],[d2461,f2460],[d2461,f2461],[d2463,f2462],[d2463,f2463],[d2465,f2464],[d2465,f2465],[d2467,f2466],[d2467,f2467],[d2469,f2468],[d2469,f2469],[d2471,f2470],[d2471,f2471],[d2473,f2472],[d2473,f2473],[d2475,f2474],[d2475,f2475],[d2477,f2476],[d2477,f2477],[d2479,f2478],[d2479,f2479],[d2481,f2480],[d2481,f2481],[d2483,f2482],[d2483,f2483],[d2485,f2484],[d2485,f2485],[d2487,f2486],[d2487,f2487],[d2489,f2488],[d2489,f2489],[d2491,f2490],[d2491,f2491],[d2493,f2492],[d2493,f2493],[d2495,f2494],[d2495,f2495],[d2497,f2496],[d2497,f2497],[d2499,f2498],[d2499,f2499],[d2501,f2500],[d2501,f2501],[d2503,f2502],[d2503,f2503],[d2505,f2504],[d2505,f2505],[d2507,f2506],[d2507,f2507],[d2509,f2508],[d2509,f2509],[d2511,f2510],[d2511,f2511],[d2513,f2512],[d2513,f2513],[d2515,f2514],[d2515,f2515],[d2517,f2516],[d2517,f2517],[d2519,f2518],[d2519,f2519],[d2521,f2520],[d2521,f2521],[d2523,f2522],[d2523,f2523],[d2525,f2524],[d2525,f2525],[d2527,f2526],[d2527,f2527],[d2529,f2528],[d2529,f2529],[d2531,f2530],[d2531,f2531],[d2533,f2532],[d2533,f2533],[d2535,f2534],[d2535,f2535],[d2537,f2536],[d2537,f2537],[d2539,f2538],[d2539,f2539],[d2541,f2540],[d2541,f2541],[d2543,f2542],[d2543,f2543],[d2545,f2544],[d2545,f2545],[d2547,f2546],[d2547,f2547],[d2549,f2548],[d2549,f2549],[d2551,f2550],[d2551,f2551],[d2553,f2552],[d2553,f2553],[d2555,f2554],[d2555,f2555],[d2557,f2556],[d2557,f2557],[d2559,f2558],[d2559,f2559],[d2561,f2560],[d2561,f2561],[d2563,f2562],[d2563,f2563],[d2565,f2564],[d2565,f2565],[d2567,f2566],[d2567,f2567],[d2569,f2568],[d2569,f2569],[d2571,f2570],[d2571,f2571],[d2573,f2572],[d2573,f2573],[d2575,f2574],[d2575,f2575],[d2577,f2576],[d2577,f2577],[d2579,f2578],[d2579,f2579],[d2581,f2580],[d2581,f2581],[d2583,f2582],[d2583,f2583],[d2585,f2584],[d2585,f2585],[d2587,f2586],[d2587,f2587],[d2589,f2588],[d2589,f2589],[d2591,f2590],[d2591,f2591],[d2593,f2592],[d2593,f2593],[d2595,f2594],[d2595,f2595],[d2597,f2596],[d2597,f2597],[d2599,f2598],[d2599,f2599],[d2601,f2600],[d2601,f2601],[d2603,f2602],[d2603,f2603],[d2605,f2604],[d2605,f2605],[d2607,f2606],[d2607,f2607],[d2609,f2608],[d2609,f2609],[d2611,f2610],[d2611,f2611],[d2613,f2612],[d2613,f2613],[d2615,f2614],[d2615,f2615],[d2617,f2616],[d2617,f2617],[d2619,f2618],[d2619,f2619],[d2621,f2620],[d2621,f2621],[d2623,f2622],[d2623,f2623],[d2625,f2624],[d2625,f2625],[d2627,f2626],[d2627,f2627],[d2629,f2628],[d2629,f2629],[d2631,f2630],[d2631,f2631],[d2633,f2632],[d2633,f2633],[d2635,f2634],[d2635,f2635],[d2637,f2636],[d2637,f2637],[d2639,f2638],[d2639,f2639],[d2641,f2640],[d2641,f2641],[d2643,f2642],[d2643,f2643],[d2645,f2644],[d2645,f2645],[d2647,f2646],[d2647,f2647],[d2649,f2648],[d2649,f2649],[d2651,f2650],[d2651,f2651],[d2653,f2652],[d2653,f2653],[d2655,f2654],[d2655,f2655],[d2657,f2656],[d2657,f2657],[d2659,f2658],[d2659,f2659],[d2661,f2660],[d2661,f2661],[d2663,f2662],[d2663,f2663],[d2665,f2664],[d2665,f2665],[d2667,f2666],[d2667,f2667],[d2669,f2668],[d2669,f2669],[d2671,f2670],[d2671,f2671],[d2673,f2672],[d2673,f2673],[d2675,f2674],[d2675,f2675],[d2677,f2676],[d2677,f2677],[d2679,f2678],[d2679,f2679],[d2681,f2680],[d2681,f2681],[d2683,f2682],[d2683,f2683],[d2685,f2684],[d2685,f2685],[d2687,f2686],[d2687,f2687],[d2689,f2688],[d2689,f2689],[d2691,f2690],[d2691,f2691],[d2693,f2692],[d2693,f2693],[d2695,f2694],[d2695,f2695],[d2697,f2696],[d2697,f2697],[d2699,f2698],[d2699,f2699],[d2701,f2700],[d2701,f2701],[d2703,f2702],[d2703,f2703],[d2705,f2704],[d2705,f2705],[d2707,f2706],[d2707,f2707],[d2709,f2708],[d2709,f2709],[d2711,f2710],[d2711,f2711],[d2713,f2712],[d2713,f2713],[d2715,f2714],[d2715,f2715],[d2717,f2716],[d2717,f2717],[d2719,f2718],[d2719,f2719],[d2721,f2720],[d2721,f2721],[d2723,f2722],[d2723,f2723],[d2725,f2724],[d2725,f2725],[d2727,f2726],[d2727,f2727],[d2729,f2728],[d2729,f2729],[d2731,f2730],[d2731,f2731],[d2733,f2732],[d2733,f2733],[d2735,f2734],[d2735,f2735],[d2737,f2736],[d2737,f2737],[d2739,f2738],[d2739,f2739],[d2741,f2740],[d2741,f2741],[d2743,f2742],[d2743,f2743],[d2745,f2744],[d2745,f2745],[d2747,f2746],[d2747,f2747],[d2749,f2748],[d2749,f2749],[d2751,f2750],[d2751,f2751],[d2753,f2752],[d2753,f2753],[d2755,f2754],[d2755,f2755],[d2757,f2756],[d2757,f2757],[d2759,f2758],[d2759,f2759],[d2761,f2760],[d2761,f2761],[d2763,f2762],[d2763,f2763],[d2765,f2764],[d2765,f2765],[d2767,f2766],[d2767,f2767],[d2769,f2768],[d2769,f2769],[d2771,f2770],[d2771,f2771],[d2773,f2772],[d2773,f2773],[d2775,f2774],[d2775,f2775],[d2777,f2776],[d2777,f2777],[d2779,f2778],[d2779,f2779],[d2781,f2780],[d2781,f2781],[d2783,f2782],[d2783,f2783],[d2785,f2784],[d2785,f2785],[d2787,f2786],[d2787,f2787],[d2789,f2788],[d2789,f2789],[d2791,f2790],[d2791,f2791],[d2793,f2792],[d2793,f2793],[d2795,f2794],[d2795,f2795],[d2797,f2796],[d2797,f2797],[d2799,f2798],[d2799,f2799],[d2801,f2800],[d2801,f2801],[d2803,f2802],[d2803,f2803],[d2805,f2804],[d2805,f2805],[d2807,f2806],[d2807,f2807],[d2809,f2808],[d2809,f2809],[d2811,f2810],[d2811,f2811],[d2813,f2812],[d2813,f2813],[d2815,f2814],[d2815,f2815],[d2817,f2816],[d2817,f2817],[d2819,f2818],[d2819,f2819],[d2821,f2820],[d2821,f2821],[d2823,f2822],[d2823,f2823],[d2825,f2824],[d2825,f2825],[d2827,f2826],[d2827,f2827],[d2829,f2828],[d2829,f2829],[d2831,f2830],[d2831,f2831],[d2833,f2832],[d2833,f2833],[d2835,f2834],[d2835,f2835],[d2837,f2836],[d2837,f2837],[d2839,f2838],[d2839,f2839],[d2841,f2840],[d2841,f2841],[d2843,f2842],[d2843,f2843],[d2845,f2844],[d2845,f2845],[d2847,f2846],[d2847,f2847],[d2849,f2848],[d2849,f2849],[d2851,f2850],[d2851,f2851],[d2853,f2852],[d2853,f2853],[d2855,f2854],[d2855,f2855],[d2857,f2856],[d2857,f2857],[d2859,f2858],[d2859,f2859],[d2861,f2860],[d2861,f2861],[d2863,f2862],[d2863,f2863],[d2865,f2864],[d2865,f2865],[d2867,f2866],[d2867,f2867],[d2869,f2868],[d2869,f2869],[d2871,f2870],[d2871,f2871],[d2873,f2872],[d2873,f2873],[d2875,f2874],[d2875,f2875],[d2877,f2876],[d2877,f2877],[d2879,f2878],[d2879,f2879],[d2881,f2880],[d2881,f2881],[d2883,f2882],[d2883,f2883],[d2885,f2884],[d2885,f2885],[d2887,f2886],[d2887,f2887],[d2889,f2888],[d2889,f2889],[d2891,f2890],[d2891,f2891],[d2893,f2892],[d2893,f2893],[d2895,f2894],[d2895,f2895],[d2897,f2896],[d2897,f2897],[d2899,f2898],[d2899,f2899],[d2901,f2900],[d2901,f2901],[d2903,f2902],[d2903,f2903],[d2905,f2904],[d2905,f2905],[d2907,f2906],[d2907,f2907],[d2909,f2908],[d2909,f2909],[d2911,f2910],[d2911,f2911],[d2913,f2912],[d2913,f2913],[d2915,f2914],[d2915,f2915],[d2917,f2916],[d2917,f2917],[d2919,f2918],[d2919,f2919],[d2921,f2920],[d2921,f2921],[d2923,f2922],[d2923,f2923],[d2925,f2924],[d2925,f2925],[d2927,f2926],[d2927,f2927],[d2929,f2928],[d2929,f2929],[d2931,f2930],[d2931,f2931],[d2933,f2932],[d2933,f2933],[d2935,f2934],[d2935,f2935],[d2937,f2936],[d2937,f2937],[d2939,f2938],[d2939,f2939],[d2941,f2940],[d2941,f2941],[d2943,f2942],[d2943,f2943],[d2945,f2944],[d2945,f2945],[d2947,f2946],[d2947,f2947],[d2949,f2948],[d2949,f2949],[d2951,f2950],[d2951,f2951],[d2953,f2952],[d2953,f2953],[d2955,f2954],[d2955,f2955],[d2957,f2956],[d2957,f2957],[d2959,f2958],[d2959,f2959],[d2961,f2960],[d2961,f2961],[d2963,f2962],[d2963,f2963],[d2965,f2964],[d2965,f2965],[d2967,f2966],[d2967,f2967],[d2969,f2968],[d2969,f2969],[d2971,f2970],[d2971,f2971],[d2973,f2972],[d2973,f2973],[d2975,f2974],[d2975,f2975],[d2977,f2976],[d2977,f2977],[d2979,f2978],[d2979,f2979],[d2981,f2980],[d2981,f2981],[d2983,f2982],[d2983,f2983],[d2985,f2984],[d2985,f2985],[d2987,f2986],[d2987,f2987],[d2989,f2988],[d2989,f2989],[d2991,f2990],[d2991,f2991],[d2993,f2992],[d2993,f2993],[d2995,f2994],[d2995,f2995],[d2997,f2996],[d2997,f2997],[d2999,f2998],[d2999,f2999],[d3001,f3000],[d3001,f3001],[d3003,f3002],[d3003,f3003],[d3005,f3004],[d3005,f3005],[d3007,f3006],[d3007,f3007],[d3009,f3008],[d3009,f3009],[d3011,f3010],[d3011,f3011],[d3013,f3012],[d3013,f3013],[d3015,f3014],[d3015,f3015],[d3017,f3016],[d3017,f3017],[d3019,f3018],[d3019,f3019],[d3021,f3020],[d3021,f3021],[d3023,f3022],[d3023,f3023],[d3025,f3024],[d3025,f3025],[d3027,f3026],[d3027,f3027],[d3029,f3028],[d3029,f3029],[d3031,f3030],[d3031,f3031],[d3033,f3032],[d3033,f3033],[d3035,f3034],[d3035,f3035],[d3037,f3036],[d3037,f3037],[d3039,f3038],[d3039,f3039],[d3041,f3040],[d3041,f3041],[d3043,f3042],[d3043,f3043],[d3045,f3044],[d3045,f3045],[d3047,f3046],[d3047,f3047],[d3049,f3048],[d3049,f3049],[d3051,f3050],[d3051,f3051],[d3053,f3052],[d3053,f3053],[d3055,f3054],[d3055,f3055],[d3057,f3056],[d3057,f3057],[d3059,f3058],[d3059,f3059],[d3061,f3060],[d3061,f3061],[d3063,f3062],[d3063,f3063],[d3065,f3064],[d3065,f3065],[d3067,f3066],[d3067,f3067],[d3069,f3068],[d3069,f3069],[d3071,f3070],[d3071,f3071],[d3073,f3072],[d3073,f3073],[d3075,f3074],[d3075,f3075],[d3077,f3076],[d3077,f3077],[d3079,f3078],[d3079,f3079],[d3081,f3080],[d3081,f3081],[d3083,f3082],[d3083,f3083],[d3085,f3084],[d3085,f3085],[d3087,f3086],[d3087,f3087],[d3089,f3088],[d3089,f3089],[d3091,f3090],[d3091,f3091],[d3093,f3092],[d3093,f3093],[d3095,f3094],[d3095,f3095],[d3097,f3096],[d3097,f3097],[d3099,f3098],[d3099,f3099],[d3101,f3100],[d3101,f3101],[d3103,f3102],[d3103,f3103],[d3105,f3104],[d3105,f3105],[d3107,f3106],[d3107,f3107],[d3109,f3108],[d3109,f3109],[d3111,f3110],[d3111,f3111],[d3113,f3112],[d3113,f3113],[d3115,f3114],[d3115,f3115],[d3117,f3116],[d3117,f3117],[d3119,f3118],[d3119,f3119],[d3121,f3120],[d3121,f3121],[d3123,f3122],[d3123,f3123],[d3125,f3124],[d3125,f3125],[d3127,f3126],[d3127,f3127],[d3129,f3128],[d3129,f3129],[d3131,f3130],[d3131,f3131],[d3133,f3132],[d3133,f3133],[d3135,f3134],[d3135,f3135],[d3137,f3136],[d3137,f3137],[d3139,f3138],[d3139,f3139],[d3141,f3140],[d3141,f3141],[d3143,f3142],[d3143,f3143],[d3145,f3144],[d3145,f3145],[d3147,f3146],[d3147,f3147],[d3149,f3148],[d3149,f3149],[d3151,f3150],[d3151,f3151],[d3153,f3152],[d3153,f3153],[d3155,f3154],[d3155,f3155],[d3157,f3156],[d3157,f3157],[d3159,f3158],[d3159,f3159],[d3161,f3160],[d3161,f3161],[d3163,f3162],[d3163,f3163],[d3165,f3164],[d3165,f3165],[d3167,f3166],[d3167,f3167],[d3169,f3168],[d3169,f3169],[d3171,f3170],[d3171,f3171],[d3173,f3172],[d3173,f3173],[d3175,f3174],[d3175,f3175],[d3177,f3176],[d3177,f3177],[d3179,f3178],[d3179,f3179],[d3181,f3180],[d3181,f3181],[d3183,f3182],[d3183,f3183],[d3185,f3184],[d3185,f3185],[d3187,f3186],[d3187,f3187],[d3189,f3188],[d3189,f3189],[d3191,f3190],[d3191,f3191],[d3193,f3192],[d3193,f3193],[d3195,f3194],[d3195,f3195],[d3197,f3196],[d3197,f3197],[d3199,f3198],[d3199,f3199],[d3201,f3200],[d3201,f3201],[d3203,f3202],[d3203,f3203],[d3205,f3204],[d3205,f3205],[d3207,f3206],[d3207,f3207],[d3209,f3208],[d3209,f3209],[d3211,f3210],[d3211,f3211],[d3213,f3212],[d3213,f3213],[d3215,f3214],[d3215,f3215],[d3217,f3216],[d3217,f3217],[d3219,f3218],[d3219,f3219],[d3221,f3220],[d3221,f3221],[d3223,f3222],[d3223,f3223],[d3225,f3224],[d3225,f3225],[d3227,f3226],[d3227,f3227],[d3229,f3228],[d3229,f3229],[d3231,f3230],[d3231,f3231],[d3233,f3232],[d3233,f3233],[d3235,f3234],[d3235,f3235],[d3237,f3236],[d3237,f3237],[d3239,f3238],[d3239,f3239],[d3241,f3240],[d3241,f3241],[d3243,f3242],[d3243,f3243],[d3245,f3244],[d3245,f3245],[d3247,f3246],[d3247,f3247],[d3249,f3248],[d3249,f3249],[d3251,f3250],[d3251,f3251],[d3253,f3252],[d3253,f3253],[d3255,f3254],[d3255,f3255],[d3257,f3256],[d3257,f3257],[d3259,f3258],[d3259,f3259],[d3261,f3260],[d3261,f3261],[d3263,f3262],[d3263,f3263],[d3265,f3264],[d3265,f3265],[d3267,f3266],[d3267,f3267],[d3269,f3268],[d3269,f3269],[d3271,f3270],[d3271,f3271],[d3273,f3272],[d3273,f3273],[d3275,f3274],[d3275,f3275],[d3277,f3276],[d3277,f3277],[d3279,f3278],[d3279,f3279],[d3281,f3280],[d3281,f3281],[d3283,f3282],[d3283,f3283],[d3285,f3284],[d3285,f3285],[d3287,f3286],[d3287,f3287],[d3289,f3288],[d3289,f3289],[d3291,f3290],[d3291,f3291],[d3293,f3292],[d3293,f3293],[d3295,f3294],[d3295,f3295],[d3297,f3296],[d3297,f3297],[d3299,f3298],[d3299,f3299],[d3301,f3300],[d3301,f3301],[d3303,f3302],[d3303,f3303],[d3305,f3304],[d3305,f3305],[d3307,f3306],[d3307,f3307],[d3309,f3308],[d3309,f3309],[d3311,f3310],[d3311,f3311],[d3313,f3312],[d3313,f3313],[d3315,f3314],[d3315,f3315],[d3317,f3316],[d3317,f3317],[d3319,f3318],[d3319,f3319],[d3321,f3320],[d3321,f3321],[d3323,f3322],[d3323,f3323],[d3325,f3324],[d3325,f3325],[d3327,f3326],[d3327,f3327],[d3329,f3328],[d3329,f3329],[d3331,f3330],[d3331,f3331],[d3333,f3332],[d3333,f3333],[d3335,f3334],[d3335,f3335],[d3337,f3336],[d3337,f3337],[d3339,f3338],[d3339,f3339],[d3341,f3340],[d3341,f3341],[d3343,f3342],[d3343,f3343],[d3345,f3344],[d3345,f3345],[d3347,f3346],[d3347,f3347],[d3349,f3348],[d3349,f3349],[d3351,f3350],[d3351,f3351],[d3353,f3352],[d3353,f3353],[d3355,f3354],[d3355,f3355],[d3357,f3356],[d3357,f3357],[d3359,f3358],[d3359,f3359],[d3361,f3360],[d3361,f3361],[d3363,f3362],[d3363,f3363],[d3365,f3364],[d3365,f3365],[d3367,f3366],[d3367,f3367],[d3369,f3368],[d3369,f3369],[d3371,f3370],[d3371,f3371],[d3373,f3372],[d3373,f3373],[d3375,f3374],[d3375,f3375],[d3377,f3376],[d3377,f3377],[d3379,f3378],[d3379,f3379],[d3381,f3380],[d3381,f3381],[d3383,f3382],[d3383,f3383],[d3385,f3384],[d3385,f3385],[d3387,f3386],[d3387,f3387],[d3389,f3388],[d3389,f3389],[d3391,f3390],[d3391,f3391],[d3393,f3392],[d3393,f3393],[d3395,f3394],[d3395,f3395],[d3397,f3396],[d3397,f3397],[d3399,f3398],[d3399,f3399],[d3401,f3400],[d3401,f3401],[d3403,f3402],[d3403,f3403],[d3405,f3404],[d3405,f3405],[d3407,f3406],[d3407,f3407],[d3409,f3408],[d3409,f3409],[d3411,f3410],[d3411,f3411],[d3413,f3412],[d3413,f3413],[d3415,f3414],[d3415,f3415],[d3417,f3416],[d3417,f3417],[d3419,f3418],[d3419,f3419],[d3421,f3420],[d3421,f3421],[d3423,f3422],[d3423,f3423],[d3425,f3424],[d3425,f3425],[d3427,f3426],[d3427,f3427],[d3429,f3428],[d3429,f3429],[d3431,f3430],[d3431,f3431],[d3433,f3432],[d3433,f3433],[d3435,f3434],[d3435,f3435],[d3437,f3436],[d3437,f3437],[d3439,f3438],[d3439,f3439],[d3441,f3440],[d3441,f3441],[d3443,f3442],[d3443,f3443],[d3445,f3444],[d3445,f3445],[d3447,f3446],[d3447,f3447],[d3449,f3448],[d3449,f3449],[d3451,f3450],[d3451,f3451],[d3453,f3452],[d3453,f3453],[d3455,f3454],[d3455,f3455],[d3457,f3456],[d3457,f3457],[d3459,f3458],[d3459,f3459],[d3461,f3460],[d3461,f3461],[d3463,f3462],[d3463,f3463],[d3465,f3464],[d3465,f3465],[d3467,f3466],[d3467,f3467],[d3469,f3468],[d3469,f3469],[d3471,f3470],[d3471,f3471],[d3473,f3472],[d3473,f3473],[d3475,f3474],[d3475,f3475],[d3477,f3476],[d3477,f3477],[d3479,f3478],[d3479,f3479],[d3481,f3480],[d3481,f3481],[d3483,f3482],[d3483,f3483],[d3485,f3484],[d3485,f3485],[d3487,f3486],[d3487,f3487],[d3489,f3488],[d3489,f3489],[d3491,f3490],[d3491,f3491],[d3493,f3492],[d3493,f3493],[d3495,f3494],[d3495,f3495],[d3497,f3496],[d3497,f3497],[d3499,f3498],[d3499,f3499],[d3501,f3500],[d3501,f3501],[d3503,f3502],[d3503,f3503],[d3505,f3504],[d3505,f3505],[d3507,f3506],[d3507,f3507],[d3509,f3508],[d3509,f3509],[d3511,f3510],[d3511,f3511],[d3513,f3512],[d3513,f3513],[d3515,f3514],[d3515,f3515],[d3517,f3516],[d3517,f3517],[d3519,f3518],[d3519,f3519],[d3521,f3520],[d3521,f3521],[d3523,f3522],[d3523,f3523],[d3525,f3524],[d3525,f3525],[d3527,f3526],[d3527,f3527],[d3529,f3528],[d3529,f3529],[d3531,f3530],[d3531,f3531],[d3533,f3532],[d3533,f3533],[d3535,f3534],[d3535,f3535],[d3537,f3536],[d3537,f3537],[d3539,f3538],[d3539,f3539],[d3541,f3540],[d3541,f3541],[d3543,f3542],[d3543,f3543],[d3545,f3544],[d3545,f3545],[d3547,f3546],[d3547,f3547],[d3549,f3548],[d3549,f3549],[d3551,f3550],[d3551,f3551],[d3553,f3552],[d3553,f3553],[d3555,f3554],[d3555,f3555],[d3557,f3556],[d3557,f3557],[d3559,f3558],[d3559,f3559],[d3561,f3560],[d3561,f3561],[d3563,f3562],[d3563,f3563],[d3565,f3564],[d3565,f3565],[d3567,f3566],[d3567,f3567],[d3569,f3568],[d3569,f3569],[d3571,f3570],[d3571,f3571],[d3573,f3572],[d3573,f3573],[d3575,f3574],[d3575,f3575],[d3577,f3576],[d3577,f3577],[d3579,f3578],[d3579,f3579],[d3581,f3580],[d3581,f3581],[d3583,f3582],[d3583,f3583],[d3585,f3584],[d3585,f3585],[d3587,f3586],[d3587,f3587],[d3589,f3588],[d3589,f3589],[d3591,f3590],[d3591,f3591],[d3593,f3592],[d3593,f3593],[d3595,f3594],[d3595,f3595],[d3597,f3596],[d3597,f3597],[d3599,f3598],[d3599,f3599],[d3601,f3600],[d3601,f3601],[d3603,f3602],[d3603,f3603],[d3605,f3604],[d3605,f3605],[d3607,f3606],[d3607,f3607],[d3609,f3608],[d3609,f3609],[d3611,f3610],[d3611,f3611],[d3613,f3612],[d3613,f3613],[d3615,f3614],[d3615,f3615],[d3617,f3616],[d3617,f3617],[d3619,f3618],[d3619,f3619],[d3621,f3620],[d3621,f3621],[d3623,f3622],[d3623,f3623],[d3625,f3624],[d3625,f3625],[d3627,f3626],[d3627,f3627],[d3629,f3628],[d3629,f3629],[d3631,f3630],[d3631,f3631],[d3633,f3632],[d3633,f3633],[d3635,f3634],[d3635,f3635],[d3637,f3636],[d3637,f3637],[d3639,f3638],[d3639,f3639],[d3641,f3640],[d3641,f3641],[d3643,f3642],[d3643,f3643],[d3645,f3644],[d3645,f3645],[d3647,f3646],[d3647,f3647],[d3649,f3648],[d3649,f3649],[d3651,f3650],[d3651,f3651],[d3653,f3652],[d3653,f3653],[d3655,f3654],[d3655,f3655],[d3657,f3656],[d3657,f3657],[d3659,f3658],[d3659,f3659],[d3661,f3660],[d3661,f3661],[d3663,f3662],[d3663,f3663],[d3665,f3664],[d3665,f3665],[d3667,f3666],[d3667,f3667],[d3669,f3668],[d3669,f3669],[d3671,f3670],[d3671,f3671],[d3673,f3672],[d3673,f3673],[d3675,f3674],[d3675,f3675],[d3677,f3676],[d3677,f3677],[d3679,f3678],[d3679,f3679],[d3681,f3680],[d3681,f3681],[d3683,f3682],[d3683,f3683],[d3685,f3684],[d3685,f3685],[d3687,f3686],[d3687,f3687],[d3689,f3688],[d3689,f3689],[d3691,f3690],[d3691,f3691],[d3693,f3692],[d3693,f3693],[d3695,f3694],[d3695,f3695],[d3697,f3696],[d3697,f3697],[d3699,f3698],[d3699,f3699],[d3701,f3700],[d3701,f3701],[d3703,f3702],[d3703,f3703],[d3705,f3704],[d3705,f3705],[d3707,f3706],[d3707,f3707],[d3709,f3708],[d3709,f3709],[d3711,f3710],[d3711,f3711],[d3713,f3712],[d3713,f3713],[d3715,f3714],[d3715,f3715],[d3717,f3716],[d3717,f3717],[d3719,f3718],[d3719,f3719],[d3721,f3720],[d3721,f3721],[d3723,f3722],[d3723,f3723],[d3725,f3724],[d3725,f3725],[d3727,f3726],[d3727,f3727],[d3729,f3728],[d3729,f3729],[d3731,f3730],[d3731,f3731],[d3733,f3732],[d3733,f3733],[d3735,f3734],[d3735,f3735],[d3737,f3736],[d3737,f3737],[d3739,f3738],[d3739,f3739],[d3741,f3740],[d3741,f3741],[d3743,f3742],[d3743,f3743],[d3745,f3744],[d3745,f3745],[d3747,f3746],[d3747,f3747],[d3749,f3748],[d3749,f3749],[d3751,f3750],[d3751,f3751],[d3753,f3752],[d3753,f3753],[d3755,f3754],[d3755,f3755],[d3757,f3756],[d3757,f3757],[d3759,f3758],[d3759,f3759],[d3761,f3760],[d3761,f3761],[d3763,f3762],[d3763,f3763],[d3765,f3764],[d3765,f3765],[d3767,f3766],[d3767,f3767],[d3769,f3768],[d3769,f3769],[d3771,f3770],[d3771,f3771],[d3773,f3772],[d3773,f3773],[d3775,f3774],[d3775,f3775],[d3777,f3776],[d3777,f3777],[d3779,f3778],[d3779,f3779],[d3781,f3780],[d3781,f3781],[d3783,f3782],[d3783,f3783],[d3785,f3784],[d3785,f3785],[d3787,f3786],[d3787,f3787],[d3789,f3788],[d3789,f3789],[d3791,f3790],[d3791,f3791],[d3793,f3792],[d3793,f3793],[d3795,f3794],[d3795,f3795],[d3797,f3796],[d3797,f3797],[d3799,f3798],[d3799,f3799],[d3801,f3800],[d3801,f3801],[d3803,f3802],[d3803,f3803],[d3805,f3804],[d3805,f3805],[d3807,f3806],[d3807,f3807],[d3809,f3808],[d3809,f3809],[d3811,f3810],[d3811,f3811],[d3813,f3812],[d3813,f3813],[d3815,f3814],[d3815,f3815],[d3817,f3816],[d3817,f3817],[d3819,f3818],[d3819,f3819],[d3821,f3820],[d3821,f3821],[d3823,f3822],[d3823,f3823],[d3825,f3824],[d3825,f3825],[d3827,f3826],[d3827,f3827],[d3829,f3828],[d3829,f3829],[d3831,f3830],[d3831,f3831],[d3833,f3832],[d3833,f3833],[d3835,f3834],[d3835,f3835],[d3837,f3836],[d3837,f3837],[d3839,f3838],[d3839,f3839],[d3841,f3840],[d3841,f3841],[d3843,f3842],[d3843,f3843],[d3845,f3844],[d3845,f3845],[d3847,f3846],[d3847,f3847],[d3849,f3848],[d3849,f3849],[d3851,f3850],[d3851,f3851],[d3853,f3852],[d3853,f3853],[d3855,f3854],[d3855,f3855],[d3857,f3856],[d3857,f3857],[d3859,f3858],[d3859,f3859],[d3861,f3860],[d3861,f3861],[d3863,f3862],[d3863,f3863],[d3865,f3864],[d3865,f3865],[d3867,f3866],[d3867,f3867],[d3869,f3868],[d3869,f3869],[d3871,f3870],[d3871,f3871],[d3873,f3872],[d3873,f3873],[d3875,f3874],[d3875,f3875],[d3877,f3876],[d3877,f3877],[d3879,f3878],[d3879,f3879],[d3881,f3880],[d3881,f3881],[d3883,f3882],[d3883,f3883],[d3885,f3884],[d3885,f3885],[d3887,f3886],[d3887,f3887],[d3889,f3888],[d3889,f3889],[d3891,f3890],[d3891,f3891],[d3893,f3892],[d3893,f3893],[d3895,f3894],[d3895,f3895],[d3897,f3896],[d3897,f3897],[d3899,f3898],[d3899,f3899],[d3901,f3900],[d3901,f3901],[d3903,f3902],[d3903,f3903],[d3905,f3904],[d3905,f3905],[d3907,f3906],[d3907,f3907],[d3909,f3908],[d3909,f3909],[d3911,f3910],[d3911,f3911],[d3913,f3912],[d3913,f3913],[d3915,f3914],[d3915,f3915],[d3917,f3916],[d3917,f3917],[d3919,f3918],[d3919,f3919],[d3921,f3920],[d3921,f3921],[d3923,f3922],[d3923,f3923],[d3925,f3924],[d3925,f3925],[d3927,f3926],[d3927,f3927],[d3929,f3928],[d3929,f3929],[d3931,f3930],[d3931,f3931],[d3933,f3932],[d3933,f3933],[d3935,f3934],[d3935,f3935],[d3937,f3936],[d3937,f3937],[d3939,f3938],[d3939,f3939],[d3941,f3940],[d3941,f3941],[d3943,f3942],[d3943,f3943],[d3945,f3944],[d3945,f3945],[d3947,f3946],[d3947,f3947],[d3949,f3948],[d3949,f3949],[d3951,f3950],[d3951,f3951],[d3953,f3952],[d3953,f3953],[d3955,f3954],[d3955,f3955],[d3957,f3956],[d3957,f3957],[d3959,f3958],[d3959,f3959],[d3961,f3960],[d3961,f3961],[d3963,f3962],[d3963,f3963],[d3965,f3964],[d3965,f3965],[d3967,f3966],[d3967,f3967],[d3969,f3968],[d3969,f3969],[d3971,f3970],[d3971,f3971],[d3973,f3972],[d3973,f3973],[d3975,f3974],[d3975,f3975],[d3977,f3976],[d3977,f3977],[d3979,f3978],[d3979,f3979],[d3981,f3980],[d3981,f3981],[d3983,f3982],[d3983,f3983],[d3985,f3984],[d3985,f3985],[d3987,f3986],[d3987,f3987],[d3989,f3988],[d3989,f3989],[d3991,f3990],[d3991,f3991],[d3993,f3992],[d3993,f3993],[d3995,f3994],[d3995,f3995],[d3997,f3996],[d3997,f3997],[d3999,f3998],[d3999,f3999],[d4001,f4000],[d4001,f4001],[d4003,f4002],[d4003,f4003],[d4005,f4004],[d4005,f4005],[d4007,f4006],[d4007,f4007],[d4009,f4008],[d4009,f4009],[d4011,f4010],[d4011,f4011],[d4013,f4012],[d4013,f4013],[d4015,f4014],[d4015,f4015],[d4017,f4016],[d4017,f4017],[d4019,f4018],[d4019,f4019],[d4021,f4020],[d4021,f4021],[d4023,f4022],[d4023,f4023],[d4025,f4024],[d4025,f4025],[d4027,f4026],[d4027,f4027],[d4029,f4028],[d4029,f4029],[d4031,f4030],[d4031,f4031],[d4033,f4032],[d4033,f4033],[d4035,f4034],[d4035,f4035],[d4037,f4036],[d4037,f4037],[d4039,f4038],[d4039,f4039],[d4041,f4040],[d4041,f4041],[d4043,f4042],[d4043,f4043],[d4045,f4044],[d4045,f4045],[d4047,f4046],[d4047,f4047],[d4049,f4048],[d4049,f4049],[d4051,f4050],[d4051,f4051],[d4053,f4052],[d4053,f4053],[d4055,f4054],[d4055,f4055],[d4057,f4056],[d4057,f4057],[d4059,f4058],[d4059,f4059],[d4061,f4060],[d4061,f4061],[d4063,f4062],[d4063,f4063],[d4065,f4064],[d4065,f4065],[d4067,f4066],[d4067,f4067],[d4069,f4068],[d4069,f4069],[d4071,f4070],[d4071,f4071],[d4073,f4072],[d4073,f4073],[d4075,f4074],[d4075,f4075],[d4077,f4076],[d4077,f4077],[d4079,f4078],[d4079,f4079],[d4081,f4080],[d4081,f4081],[d4083,f4082],[d4083,f4083],[d4085,f4084],[d4085,f4085],[d4087,f4086],[d4087,f4087],[d4089,f4088],[d4089,f4089],[d4091,f4090],[d4091,f4091],[d4093,f4092],[d4093,f4093],[d4095,f4094],[d4095,f4095],[d4097,f4096],[d4097,f4097],[d4099,f4098],[d4099,f4099],[d4101,f4100],[d4101,f4101],[d4103,f4102],[d4103,f4103],[d4105,f4104],[d4105,f4105],[d4107,f4106],[d4107,f4107],[d4109,f4108],[d4109,f4109],[d4111,f4110],[d4111,f4111],[d4113,f4112],[d4113,f4113],[d4115,f4114],[d4115,f4115],[d4117,f4116],[d4117,f4117],[d4119,f4118],[d4119,f4119],[d4121,f4120],[d4121,f4121],[d4123,f4122],[d4123,f4123],[d4125,f4124],[d4125,f4125],[d4127,f4126],[d4127,f4127],[d4129,f4128],[d4129,f4129],[d4131,f4130],[d4131,f4131],[d4133,f4132],[d4133,f4133],[d4135,f4134],[d4135,f4135],[d4137,f4136],[d4137,f4137],[d4139,f4138],[d4139,f4139],[d4141,f4140],[d4141,f4141],[d4143,f4142],[d4143,f4143],[d4145,f4144],[d4145,f4145],[d4147,f4146],[d4147,f4147],[d4149,f4148],[d4149,f4149],[d4151,f4150],[d4151,f4151],[d4153,f4152],[d4153,f4153],[d4155,f4154],[d4155,f4155],[d4157,f4156],[d4157,f4157],[d4159,f4158],[d4159,f4159],[d4161,f4160],[d4161,f4161],[d4163,f4162],[d4163,f4163],[d4165,f4164],[d4165,f4165],[d4167,f4166],[d4167,f4167],[d4169,f4168],[d4169,f4169],[d4171,f4170],[d4171,f4171],[d4173,f4172],[d4173,f4173],[d4175,f4174],[d4175,f4175],[d4177,f4176],[d4177,f4177],[d4179,f4178],[d4179,f4179],[d4181,f4180],[d4181,f4181],[d4183,f4182],[d4183,f4183],[d4185,f4184],[d4185,f4185],[d4187,f4186],[d4187,f4187],[d4189,f4188],[d4189,f4189],[d4191,f4190],[d4191,f4191],[d4193,f4192],[d4193,f4193],[d4195,f4194],[d4195,f4195],[d4197,f4196],[d4197,f4197],[d4199,f4198],[d4199,f4199],[d4201,f4200],[d4201,f4201],[d4203,f4202],[d4203,f4203],[d4205,f4204],[d4205,f4205],[d4207,f4206],[d4207,f4207],[d4209,f4208],[d4209,f4209],[d4211,f4210],[d4211,f4211],[d4213,f4212],[d4213,f4213],[d4215,f4214],[d4215,f4215],[d4217,f4216],[d4217,f4217],[d4219,f4218],[d4219,f4219],[d4221,f4220],[d4221,f4221],[d4223,f4222],[d4223,f4223],[d4225,f4224],[d4225,f4225],[d4227,f4226],[d4227,f4227],[d4229,f4228],[d4229,f4229],[d4231,f4230],[d4231,f4231],[d4233,f4232],[d4233,f4233],[d4235,f4234],[d4235,f4235],[d4237,f4236],[d4237,f4237],[d4239,f4238],[d4239,f4239],[d4241,f4240],[d4241,f4241],[d4243,f4242],[d4243,f4243],[d4245,f4244],[d4245,f4245],[d4247,f4246],[d4247,f4247],[d4249,f4248],[d4249,f4249],[d4251,f4250],[d4251,f4251],[d4253,f4252],[d4253,f4253],[d4255,f4254],[d4255,f4255],[d4257,f4256],[d4257,f4257],[d4259,f4258],[d4259,f4259],[d4261,f4260],[d4261,f4261],[d4263,f4262],[d4263,f4263],[d4265,f4264],[d4265,f4265],[d4267,f4266],[d4267,f4267],[d4269,f4268],[d4269,f4269],[d4271,f4270],[d4271,f4271],[d4273,f4272],[d4273,f4273],[d4275,f4274],[d4275,f4275],[d4277,f4276],[d4277,f4277],[d4279,f4278],[d4279,f4279],[d4281,f4280],[d4281,f4281],[d4283,f4282],[d4283,f4283],[d4285,f4284],[d4285,f4285],[d4287,f4286],[d4287,f4287],[d4289,f4288],[d4289,f4289],[d4291,f4290],[d4291,f4291],[d4293,f4292],[d4293,f4293],[d4295,f4294],[d4295,f4295],[d4297,f4296],[d4297,f4297],[d4299,f4298],[d4299,f4299],[d4301,f4300],[d4301,f4301],[d4303,f4302],[d4303,f4303],[d4305,f4304],[d4305,f4305],[d4307,f4306],[d4307,f4307],[d4309,f4308],[d4309,f4309],[d4311,f4310],[d4311,f4311],[d4313,f4312],[d4313,f4313],[d4315,f4314],[d4315,f4315],[d4317,f4316],[d4317,f4317],[d4319,f4318],[d4319,f4319],[d4321,f4320],[d4321,f4321],[d4323,f4322],[d4323,f4323],[d4325,f4324],[d4325,f4325],[d4327,f4326],[d4327,f4327],[d4329,f4328],[d4329,f4329],[d4331,f4330],[d4331,f4331],[d4333,f4332],[d4333,f4333],[d4335,f4334],[d4335,f4335],[d4337,f4336],[d4337,f4337],[d4339,f4338],[d4339,f4339],[d4341,f4340],[d4341,f4341],[d4343,f4342],[d4343,f4343],[d4345,f4344],[d4345,f4345],[d4347,f4346],[d4347,f4347],[d4349,f4348],[d4349,f4349],[d4351,f4350],[d4351,f4351],[d4353,f4352],[d4353,f4353],[d4355,f4354],[d4355,f4355],[d4357,f4356],[d4357,f4357],[d4359,f4358],[d4359,f4359],[d4361,f4360],[d4361,f4361],[d4363,f4362],[d4363,f4363],[d4365,f4364],[d4365,f4365],[d4367,f4366],[d4367,f4367],[d4369,f4368],[d4369,f4369],[d4371,f4370],[d4371,f4371],[d4373,f4372],[d4373,f4373],[d4375,f4374],[d4375,f4375],[d4377,f4376],[d4377,f4377],[d4379,f4378],[d4379,f4379],[d4381,f4380],[d4381,f4381],[d4383,f4382],[d4383,f4383],[d4385,f4384],[d4385,f4385],[d4387,f4386],[d4387,f4387],[d4389,f4388],[d4389,f4389],[d4391,f4390],[d4391,f4391],[d4393,f4392],[d4393,f4393],[d4395,f4394],[d4395,f4395],[d4397,f4396],[d4397,f4397],[d4399,f4398],[d4399,f4399],[d4401,f4400],[d4401,f4401],[d4403,f4402],[d4403,f4403],[d4405,f4404],[d4405,f4405],[d4407,f4406],[d4407,f4407],[d4409,f4408],[d4409,f4409],[d4411,f4410],[d4411,f4411],[d4413,f4412],[d4413,f4413],[d4415,f4414],[d4415,f4415],[d4417,f4416],[d4417,f4417],[d4419,f4418],[d4419,f4419],[d4421,f4420],[d4421,f4421],[d4423,f4422],[d4423,f4423],[d4425,f4424],[d4425,f4425],[d4427,f4426],[d4427,f4427],[d4429,f4428],[d4429,f4429],[d4431,f4430],[d4431,f4431],[d4433,f4432],[d4433,f4433],[d4435,f4434],[d4435,f4435],[d4437,f4436],[d4437,f4437],[d4439,f4438],[d4439,f4439],[d4441,f4440],[d4441,f4441],[d4443,f4442],[d4443,f4443],[d4445,f4444],[d4445,f4445],[d4447,f4446],[d4447,f4447],[d4449,f4448],[d4449,f4449],[d4451,f4450],[d4451,f4451],[d4453,f4452],[d4453,f4453],[d4455,f4454],[d4455,f4455],[d4457,f4456],[d4457,f4457],[d4459,f4458],[d4459,f4459],[d4461,f4460],[d4461,f4461],[d4463,f4462],[d4463,f4463],[d4465,f4464],[d4465,f4465],[d4467,f4466],[d4467,f4467],[d4469,f4468],[d4469,f4469],[d4471,f4470],[d4471,f4471],[d4473,f4472],[d4473,f4473],[d4475,f4474],[d4475,f4475],[d4477,f4476],[d4477,f4477],[d4479,f4478],[d4479,f4479],[d4481,f4480],[d4481,f4481],[d4483,f4482],[d4483,f4483],[d4485,f4484],[d4485,f4485],[d4487,f4486],[d4487,f4487],[d4489,f4488],[d4489,f4489],[d4491,f4490],[d4491,f4491],[d4493,f4492],[d4493,f4493],[d4495,f4494],[d4495,f4495],[d4497,f4496],[d4497,f4497],[d4499,f4498],[d4499,f4499],[d4501,f4500],[d4501,f4501],[d4503,f4502],[d4503,f4503],[d4505,f4504],[d4505,f4505],[d4507,f4506],[d4507,f4507],[d4509,f4508],[d4509,f4509],[d4511,f4510],[d4511,f4511],[d4513,f4512],[d4513,f4513],[d4515,f4514],[d4515,f4515],[d4517,f4516],[d4517,f4517],[d4519,f4518],[d4519,f4519],[d4521,f4520],[d4521,f4521],[d4523,f4522],[d4523,f4523],[d4525,f4524],[d4525,f4525],[d4527,f4526],[d4527,f4527],[d4529,f4528],[d4529,f4529],[d4531,f4530],[d4531,f4531],[d4533,f4532],[d4533,f4533],[d4535,f4534],[d4535,f4535],[d4537,f4536],[d4537,f4537],[d4539,f4538],[d4539,f4539],[d4541,f4540],[d4541,f4541],[d4543,f4542],[d4543,f4543],[d4545,f4544],[d4545,f4545],[d4547,f4546],[d4547,f4547],[d4549,f4548],[d4549,f4549],[d4551,f4550],[d4551,f4551],[d4553,f4552],[d4553,f4553],[d4555,f4554],[d4555,f4555],[d4557,f4556],[d4557,f4557],[d4559,f4558],[d4559,f4559],[d4561,f4560],[d4561,f4561],[d4563,f4562],[d4563,f4563],[d4565,f4564],[d4565,f4565],[d4567,f4566],[d4567,f4567],[d4569,f4568],[d4569,f4569],[d4571,f4570],[d4571,f4571],[d4573,f4572],[d4573,f4573],[d4575,f4574],[d4575,f4575],[d4577,f4576],[d4577,f4577],[d4579,f4578],[d4579,f4579],[d4581,f4580],[d4581,f4581],[d4583,f4582],[d4583,f4583],[d4585,f4584],[d4585,f4585],[d4587,f4586],[d4587,f4587],[d4589,f4588],[d4589,f4589],[d4591,f4590],[d4591,f4591],[d4593,f4592],[d4593,f4593],[d4595,f4594],[d4595,f4595],[d4597,f4596],[d4597,f4597],[d4599,f4598],[d4599,f4599],[d4601,f4600],[d4601,f4601],[d4603,f4602],[d4603,f4603],[d4605,f4604],[d4605,f4605],[d4607,f4606],[d4607,f4607],[d4609,f4608],[d4609,f4609],[d4611,f4610],[d4611,f4611],[d4613,f4612],[d4613,f4613],[d4615,f4614],[d4615,f4615],[d4617,f4616],[d4617,f4617],[d4619,f4618],[d4619,f4619],[d4621,f4620],[d4621,f4621],[d4623,f4622],[d4623,f4623],[d4625,f4624],[d4625,f4625],[d4627,f4626],[d4627,f4627],[d4629,f4628],[d4629,f4629],[d4631,f4630],[d4631,f4631],[d4633,f4632],[d4633,f4633],[d4635,f4634],[d4635,f4635],[d4637,f4636],[d4637,f4637],[d4639,f4638],[d4639,f4639],[d4641,f4640],[d4641,f4641],[d4643,f4642],[d4643,f4643],[d4645,f4644],[d4645,f4645],[d4647,f4646],[d4647,f4647],[d4649,f4648],[d4649,f4649],[d4651,f4650],[d4651,f4651],[d4653,f4652],[d4653,f4653],[d4655,f4654],[d4655,f4655],[d4657,f4656],[d4657,f4657],[d4659,f4658],[d4659,f4659],[d4661,f4660],[d4661,f4661],[d4663,f4662],[d4663,f4663],[d4665,f4664],[d4665,f4665],[d4667,f4666],[d4667,f4667],[d4669,f4668],[d4669,f4669],[d4671,f4670],[d4671,f4671],[d4673,f4672],[d4673,f4673],[d4675,f4674],[d4675,f4675],[d4677,f4676],[d4677,f4677],[d4679,f4678],[d4679,f4679],[d4681,f4680],[d4681,f4681],[d4683,f4682],[d4683,f4683],[d4685,f4684],[d4685,f4685],[d4687,f4686],[d4687,f4687],[d4689,f4688],[d4689,f4689],[d4691,f4690],[d4691,f4691],[d4693,f4692],[d4693,f4693],[d4695,f4694],[d4695,f4695],[d4697,f4696],[d4697,f4697],[d4699,f4698],[d4699,f4699],[d4701,f4700],[d4701,f4701],[d4703,f4702],[d4703,f4703],[d4705,f4704],[d4705,f4705],[d4707,f4706],[d4707,f4707],[d4709,f4708],[d4709,f4709],[d4711,f4710],[d4711,f4711],[d4713,f4712],[d4713,f4713],[d4715,f4714],[d4715,f4715],[d4717,f4716],[d4717,f4717],[d4719,f4718],[d4719,f4719],[d4721,f4720],[d4721,f4721],[d4723,f4722],[d4723,f4723],[d4725,f4724],[d4725,f4725],[d4727,f4726],[d4727,f4727],[d4729,f4728],[d4729,f4729],[d4731,f4730],[d4731,f4731],[d4733,f4732],[d4733,f4733],[d4735,f4734],[d4735,f4735],[d4737,f4736],[d4737,f4737],[d4739,f4738],[d4739,f4739],[d4741,f4740],[d4741,f4741],[d4743,f4742],[d4743,f4743],[d4745,f4744],[d4745,f4745],[d4747,f4746],[d4747,f4747],[d4749,f4748],[d4749,f4749],[d4751,f4750],[d4751,f4751],[d4753,f4752],[d4753,f4753],[d4755,f4754],[d4755,f4755],[d4757,f4756],[d4757,f4757],[d4759,f4758],[d4759,f4759],[d4761,f4760],[d4761,f4761],[d4763,f4762],[d4763,f4763],[d4765,f4764],[d4765,f4765],[d4767,f4766],[d4767,f4767],[d4769,f4768],[d4769,f4769],[d4771,f4770],[d4771,f4771],[d4773,f4772],[d4773,f4773],[d4775,f4774],[d4775,f4775],[d4777,f4776],[d4777,f4777],[d4779,f4778],[d4779,f4779],[d4781,f4780],[d4781,f4781],[d4783,f4782],[d4783,f4783],[d4785,f4784],[d4785,f4785],[d4787,f4786],[d4787,f4787],[d4789,f4788],[d4789,f4789],[d4791,f4790],[d4791,f4791],[d4793,f4792],[d4793,f4793],[d4795,f4794],[d4795,f4795],[d4797,f4796],[d4797,f4797],[d4799,f4798],[d4799,f4799],[d4801,f4800],[d4801,f4801],[d4803,f4802],[d4803,f4803],[d4805,f4804],[d4805,f4805],[d4807,f4806],[d4807,f4807],[d4809,f4808],[d4809,f4809],[d4811,f4810],[d4811,f4811],[d4813,f4812],[d4813,f4813],[d4815,f4814],[d4815,f4815],[d4817,f4816],[d4817,f4817],[d4819,f4818],[d4819,f4819],[d4821,f4820],[d4821,f4821],[d4823,f4822],[d4823,f4823],[d4825,f4824],[d4825,f4825],[d4827,f4826],[d4827,f4827],[d4829,f4828],[d4829,f4829],[d4831,f4830],[d4831,f4831],[d4833,f4832],[d4833,f4833],[d4835,f4834],[d4835,f4835],[d4837,f4836],[d4837,f4837],[d4839,f4838],[d4839,f4839],[d4841,f4840],[d4841,f4841],[d4843,f4842],[d4843,f4843],[d4845,f4844],[d4845,f4845],[d4847,f4846],[d4847,f4847],[d4849,f4848],[d4849,f4849],[d4851,f4850],[d4851,f4851],[d4853,f4852],[d4853,f4853],[d4855,f4854],[d4855,f4855],[d4857,f4856],[d4857,f4857],[d4859,f4858],[d4859,f4859],[d4861,f4860],[d4861,f4861],[d4863,f4862],[d4863,f4863],[d4865,f4864],[d4865,f4865],[d4867,f4866],[d4867,f4867],[d4869,f4868],[d4869,f4869],[d4871,f4870],[d4871,f4871],[d4873,f4872],[d4873,f4873],[d4875,f4874],[d4875,f4875],[d4877,f4876],[d4877,f4877],[d4879,f4878],[d4879,f4879],[d4881,f4880],[d4881,f4881],[d4883,f4882],[d4883,f4883],[d4885,f4884],[d4885,f4885],[d4887,f4886],[d4887,f4887],[d4889,f4888],[d4889,f4889],[d4891,f4890],[d4891,f4891],[d4893,f4892],[d4893,f4893],[d4895,f4894],[d4895,f4895],[d4897,f4896],[d4897,f4897],[d4899,f4898],[d4899,f4899],[d4901,f4900],[d4901,f4901],[d4903,f4902],[d4903,f4903],[d4905,f4904],[d4905,f4905],[d4907,f4906],[d4907,f4907],[d4909,f4908],[d4909,f4909],[d4911,f4910],[d4911,f4911],[d4913,f4912],[d4913,f4913],[d4915,f4914],[d4915,f4915],[d4917,f4916],[d4917,f4917],[d4919,f4918],[d4919,f4919],[d4921,f4920],[d4921,f4921],[d4923,f4922],[d4923,f4923],[d4925,f4924],[d4925,f4925],[d4927,f4926],[d4927,f4927],[d4929,f4928],[d4929,f4929],[d4931,f4930],[d4931,f4931],[d4933,f4932],[d4933,f4933],[d4935,f4934],[d4935,f4935],[d4937,f4936],[d4937,f4937],[d4939,f4938],[d4939,f4939],[d4941,f4940],[d4941,f4941],[d4943,f4942],[d4943,f4943],[d4945,f4944],[d4945,f4945],[d4947,f4946],[d4947,f4947],[d4949,f4948],[d4949,f4949],[d4951,f4950],[d4951,f4951],[d4953,f4952],[d4953,f4953],[d4955,f4954],[d4955,f4955],[d4957,f4956],[d4957,f4957],[d4959,f4958],[d4959,f4959],[d4961,f4960],[d4961,f4961],[d4963,f4962],[d4963,f4963],[d4965,f4964],[d4965,f4965],[d4967,f4966],[d4967,f4967],[d4969,f4968],[d4969,f4969],[d4971,f4970],[d4971,f4971],[d4973,f4972],[d4973,f4973],[d4975,f4974],[d4975,f4975],[d4977,f4976],[d4977,f4977],[d4979,f4978],[d4979,f4979],[d4981,f4980],[d4981,f4981],[d4983,f4982],[d4983,f4983],[d4985,f4984],[d4985,f4985],[d4987,f4986],[d4987,f4987],[d4989,f4988],[d4989,f4989],[d4991,f4990],[d4991,f4991],[d4993,f4992],[d4993,f4993],[d4995,f4994],[d4995,f4995],[d4997,f4996],[d4997,f4997],[d4999,f4998],[d4999,f4999],[d5001,f5000],[d5001,f5001],[d5003,f5002],[d5003,f5003],[d5005,f5004],[d5005,f5005],[d5007,f5006],[d5007,f5007],[d5009,f5008],[d5009,f5009],[d5011,f5010],[d5011,f5011],[d5013,f5012],[d5013,f5013],[d5015,f5014],[d5015,f5015],[d5017,f5016],[d5017,f5017],[d5019,f5018],[d5019,f5019],[d5021,f5020],[d5021,f5021],[d5023,f5022],[d5023,f5023],[d5025,f5024],[d5025,f5025],[d5027,f5026],[d5027,f5027],[d5029,f5028],[d5029,f5029],[d5031,f5030],[d5031,f5031],[d5033,f5032],[d5033,f5033],[d5035,f5034],[d5035,f5035],[d5037,f5036],[d5037,f5037],[d5039,f5038],[d5039,f5039],[d5041,f5040],[d5041,f5041],[d5043,f5042],[d5043,f5043],[d5045,f5044],[d5045,f5045],[d5047,f5046],[d5047,f5047],[d5049,f5048],[d5049,f5049],[d5051,f5050],[d5051,f5051],[d5053,f5052],[d5053,f5053],[d5055,f5054],[d5055,f5055],[d5057,f5056],[d5057,f5057],[d5059,f5058],[d5059,f5059],[d5061,f5060],[d5061,f5061],[d5063,f5062],[d5063,f5063],[d5065,f5064],[d5065,f5065],[d5067,f5066],[d5067,f5067],[d5069,f5068],[d5069,f5069],[d5071,f5070],[d5071,f5071],[d5073,f5072],[d5073,f5073],[d5075,f5074],[d5075,f5075],[d5077,f5076],[d5077,f5077],[d5079,f5078],[d5079,f5079],[d5081,f5080],[d5081,f5081],[d5083,f5082],[d5083,f5083],[d5085,f5084],[d5085,f5085],[d5087,f5086],[d5087,f5087],[d5089,f5088],[d5089,f5089],[d5091,f5090],[d5091,f5091],[d5093,f5092],[d5093,f5093],[d5095,f5094],[d5095,f5095],[d5097,f5096],[d5097,f5097],[d5099,f5098],[d5099,f5099],[d5101,f5100],[d5101,f5101],[d5103,f5102],[d5103,f5103],[d5105,f5104],[d5105,f5105],[d5107,f5106],[d5107,f5107],[d5109,f5108],[d5109,f5109],[d5111,f5110],[d5111,f5111],[d5113,f5112],[d5113,f5113],[d5115,f5114],[d5115,f5115],[d5117,f5116],[d5117,f5117],[d5119,f5118],[d5119,f5119],[d5121,f5120],[d5121,f5121],[d5123,f5122],[d5123,f5123],[d5125,f5124],[d5125,f5125],[d5127,f5126],[d5127,f5127],[d5129,f5128],[d5129,f5129],[d5131,f5130],[d5131,f5131],[d5133,f5132],[d5133,f5133],[d5135,f5134],[d5135,f5135],[d5137,f5136],[d5137,f5137],[d5139,f5138],[d5139,f5139],[d5141,f5140],[d5141,f5141],[d5143,f5142],[d5143,f5143],[d5145,f5144],[d5145,f5145],[d5147,f5146],[d5147,f5147],[d5149,f5148],[d5149,f5149],[d5151,f5150],[d5151,f5151],[d5153,f5152],[d5153,f5153],[d5155,f5154],[d5155,f5155],[d5157,f5156],[d5157,f5157],[d5159,f5158],[d5159,f5159],[d5161,f5160],[d5161,f5161],[d5163,f5162],[d5163,f5163],[d5165,f5164],[d5165,f5165],[d5167,f5166],[d5167,f5167],[d5169,f5168],[d5169,f5169],[d5171,f5170],[d5171,f5171],[d5173,f5172],[d5173,f5173],[d5175,f5174],[d5175,f5175],[d5177,f5176],[d5177,f5177],[d5179,f5178],[d5179,f5179],[d5181,f5180],[d5181,f5181],[d5183,f5182],[d5183,f5183],[d5185,f5184],[d5185,f5185],[d5187,f5186],[d5187,f5187],[d5189,f5188],[d5189,f5189],[d5191,f5190],[d5191,f5191],[d5193,f5192],[d5193,f5193],[d5195,f5194],[d5195,f5195],[d5197,f5196],[d5197,f5197],[d5199,f5198],[d5199,f5199],[d5201,f5200],[d5201,f5201],[d5203,f5202],[d5203,f5203],[d5205,f5204],[d5205,f5205],[d5207,f5206],[d5207,f5207],[d5209,f5208],[d5209,f5209],[d5211,f5210],[d5211,f5211],[d5213,f5212],[d5213,f5213],[d5215,f5214],[d5215,f5215],[d5217,f5216],[d5217,f5217],[d5219,f5218],[d5219,f5219],[d5221,f5220],[d5221,f5221],[d5223,f5222],[d5223,f5223],[d5225,f5224],[d5225,f5225],[d5227,f5226],[d5227,f5227],[d5229,f5228],[d5229,f5229],[d5231,f5230],[d5231,f5231],[d5233,f5232],[d5233,f5233],[d5235,f5234],[d5235,f5235],[d5237,f5236],[d5237,f5237],[d5239,f5238],[d5239,f5239],[d5241,f5240],[d5241,f5241],[d5243,f5242],[d5243,f5243],[d5245,f5244],[d5245,f5245],[d5247,f5246],[d5247,f5247],[d5249,f5248],[d5249,f5249],[d5251,f5250],[d5251,f5251],[d5253,f5252],[d5253,f5253],[d5255,f5254],[d5255,f5255],[d5257,f5256],[d5257,f5257],[d5259,f5258],[d5259,f5259],[d5261,f5260],[d5261,f5261],[d5263,f5262],[d5263,f5263],[d5265,f5264],[d5265,f5265],[d5267,f5266],[d5267,f5267],[d5269,f5268],[d5269,f5269],[d5271,f5270],[d5271,f5271],[d5273,f5272],[d5273,f5273],[d5275,f5274],[d5275,f5275],[d5277,f5276],[d5277,f5277],[d5279,f5278],[d5279,f5279],[d5281,f5280],[d5281,f5281],[d5283,f5282],[d5283,f5283],[d5285,f5284],[d5285,f5285],[d5287,f5286],[d5287,f5287],[d5289,f5288],[d5289,f5289],[d5291,f5290],[d5291,f5291],[d5293,f5292],[d5293,f5293],[d5295,f5294],[d5295,f5295],[d5297,f5296],[d5297,f5297],[d5299,f5298],[d5299,f5299],[d5301,f5300],[d5301,f5301],[d5303,f5302],[d5303,f5303],[d5305,f5304],[d5305,f5305],[d5307,f5306],[d5307,f5307],[d5309,f5308],[d5309,f5309],[d5311,f5310],[d5311,f5311],[d5313,f5312],[d5313,f5313],[d5315,f5314],[d5315,f5315],[d5317,f5316],[d5317,f5317],[d5319,f5318],[d5319,f5319],[d5321,f5320],[d5321,f5321],[d5323,f5322],[d5323,f5323],[d5325,f5324],[d5325,f5325],[d5327,f5326],[d5327,f5327],[d5329,f5328],[d5329,f5329],[d5331,f5330],[d5331,f5331],[d5333,f5332],[d5333,f5333],[d5335,f5334],[d5335,f5335],[d5337,f5336],[d5337,f5337],[d5339,f5338],[d5339,f5339],[d5341,f5340],[d5341,f5341],[d5343,f5342],[d5343,f5343],[d5345,f5344],[d5345,f5345],[d5347,f5346],[d5347,f5347],[d5349,f5348],[d5349,f5349],[d5351,f5350],[d5351,f5351],[d5353,f5352],[d5353,f5353],[d5355,f5354],[d5355,f5355],[d5357,f5356],[d5357,f5357],[d5359,f5358],[d5359,f5359],[d5361,f5360],[d5361,f5361],[d5363,f5362],[d5363,f5363],[d5365,f5364],[d5365,f5365],[d5367,f5366],[d5367,f5367],[d5369,f5368],[d5369,f5369],[d5371,f5370],[d5371,f5371],[d5373,f5372],[d5373,f5373],[d5375,f5374],[d5375,f5375],[d5377,f5376],[d5377,f5377],[d5379,f5378],[d5379,f5379],[d5381,f5380],[d5381,f5381],[d5383,f5382],[d5383,f5383],[d5385,f5384],[d5385,f5385],[d5387,f5386],[d5387,f5387],[d5389,f5388],[d5389,f5389],[d5391,f5390],[d5391,f5391],[d5393,f5392],[d5393,f5393],[d5395,f5394],[d5395,f5395],[d5397,f5396],[d5397,f5397],[d5399,f5398],[d5399,f5399],[d5401,f5400],[d5401,f5401],[d5403,f5402],[d5403,f5403],[d5405,f5404],[d5405,f5405],[d5407,f5406],[d5407,f5407],[d5409,f5408],[d5409,f5409],[d5411,f5410],[d5411,f5411],[d5413,f5412],[d5413,f5413],[d5415,f5414],[d5415,f5415],[d5417,f5416],[d5417,f5417],[d5419,f5418],[d5419,f5419],[d5421,f5420],[d5421,f5421],[d5423,f5422],[d5423,f5423],[d5425,f5424],[d5425,f5425],[d5427,f5426],[d5427,f5427],[d5429,f5428],[d5429,f5429],[d5431,f5430],[d5431,f5431],[d5433,f5432],[d5433,f5433],[d5435,f5434],[d5435,f5435],[d5437,f5436],[d5437,f5437],[d5439,f5438],[d5439,f5439],[d5441,f5440],[d5441,f5441],[d5443,f5442],[d5443,f5443],[d5445,f5444],[d5445,f5445],[d5447,f5446],[d5447,f5447],[d5449,f5448],[d5449,f5449],[d5451,f5450],[d5451,f5451],[d5453,f5452],[d5453,f5453],[d5455,f5454],[d5455,f5455],[d5457,f5456],[d5457,f5457],[d5459,f5458],[d5459,f5459],[d5461,f5460],[d5461,f5461],[d5463,f5462],[d5463,f5463],[d5465,f5464],[d5465,f5465],[d5467,f5466],[d5467,f5467],[d5469,f5468],[d5469,f5469],[d5471,f5470],[d5471,f5471],[d5473,f5472],[d5473,f5473],[d5475,f5474],[d5475,f5475],[d5477,f5476],[d5477,f5477],[d5479,f5478],[d5479,f5479],[d5481,f5480],[d5481,f5481],[d5483,f5482],[d5483,f5483],[d5485,f5484],[d5485,f5485],[d5487,f5486],[d5487,f5487],[d5489,f5488],[d5489,f5489],[d5491,f5490],[d5491,f5491],[d5493,f5492],[d5493,f5493],[d5495,f5494],[d5495,f5495],[d5497,f5496],[d5497,f5497],[d5499,f5498],[d5499,f5499],[d5501,f5500],[d5501,f5501],[d5503,f5502],[d5503,f5503],[d5505,f5504],[d5505,f5505],[d5507,f5506],[d5507,f5507],[d5509,f5508],[d5509,f5509],[d5511,f5510],[d5511,f5511],[d5513,f5512],[d5513,f5513],[d5515,f5514],[d5515,f5515],[d5517,f5516],[d5517,f5517],[d5519,f5518],[d5519,f5519],[d5521,f5520],[d5521,f5521],[d5523,f5522],[d5523,f5523],[d5525,f5524],[d5525,f5525],[d5527,f5526],[d5527,f5527],[d5529,f5528],[d5529,f5529],[d5531,f5530],[d5531,f5531],[d5533,f5532],[d5533,f5533],[d5535,f5534],[d5535,f5535],[d5537,f5536],[d5537,f5537],[d5539,f5538],[d5539,f5539],[d5541,f5540],[d5541,f5541],[d5543,f5542],[d5543,f5543],[d5545,f5544],[d5545,f5545],[d5547,f5546],[d5547,f5547],[d5549,f5548],[d5549,f5549],[d5551,f5550],[d5551,f5551],[d5553,f5552],[d5553,f5553],[d5555,f5554],[d5555,f5555],[d5557,f5556],[d5557,f5557],[d5559,f5558],[d5559,f5559],[d5561,f5560],[d5561,f5561],[d5563,f5562],[d5563,f5563],[d5565,f5564],[d5565,f5565],[d5567,f5566],[d5567,f5567],[d5569,f5568],[d5569,f5569],[d5571,f5570],[d5571,f5571],[d5573,f5572],[d5573,f5573],[d5575,f5574],[d5575,f5575],[d5577,f5576],[d5577,f5577],[d5579,f5578],[d5579,f5579],[d5581,f5580],[d5581,f5581],[d5583,f5582],[d5583,f5583],[d5585,f5584],[d5585,f5585],[d5587,f5586],[d5587,f5587],[d5589,f5588],[d5589,f5589],[d5591,f5590],[d5591,f5591],[d5593,f5592],[d5593,f5593],[d5595,f5594],[d5595,f5595],[d5597,f5596],[d5597,f5597],[d5599,f5598],[d5599,f5599],[d5601,f5600],[d5601,f5601],[d5603,f5602],[d5603,f5603],[d5605,f5604],[d5605,f5605],[d5607,f5606],[d5607,f5607],[d5609,f5608],[d5609,f5609],[d5611,f5610],[d5611,f5611],[d5613,f5612],[d5613,f5613],[d5615,f5614],[d5615,f5615],[d5617,f5616],[d5617,f5617],[d5619,f5618],[d5619,f5619],[d5621,f5620],[d5621,f5621],[d5623,f5622],[d5623,f5623],[d5625,f5624],[d5625,f5625],[d5627,f5626],[d5627,f5627],[d5629,f5628],[d5629,f5629],[d5631,f5630],[d5631,f5631],[d5633,f5632],[d5633,f5633],[d5635,f5634],[d5635,f5635],[d5637,f5636],[d5637,f5637],[d5639,f5638],[d5639,f5639],[d5641,f5640],[d5641,f5641],[d5643,f5642],[d5643,f5643],[d5645,f5644],[d5645,f5645],[d5647,f5646],[d5647,f5647],[d5649,f5648],[d5649,f5649],[d5651,f5650],[d5651,f5651],[d5653,f5652],[d5653,f5653],[d5655,f5654],[d5655,f5655],[d5657,f5656],[d5657,f5657],[d5659,f5658],[d5659,f5659],[d5661,f5660],[d5661,f5661],[d5663,f5662],[d5663,f5663],[d5665,f5664],[d5665,f5665],[d5667,f5666],[d5667,f5667],[d5669,f5668],[d5669,f5669],[d5671,f5670],[d5671,f5671],[d5673,f5672],[d5673,f5673],[d5675,f5674],[d5675,f5675],[d5677,f5676],[d5677,f5677],[d5679,f5678],[d5679,f5679],[d5681,f5680],[d5681,f5681],[d5683,f5682],[d5683,f5683],[d5685,f5684],[d5685,f5685],[d5687,f5686],[d5687,f5687],[d5689,f5688],[d5689,f5689],[d5691,f5690],[d5691,f5691],[d5693,f5692],[d5693,f5693],[d5695,f5694],[d5695,f5695],[d5697,f5696],[d5697,f5697],[d5699,f5698],[d5699,f5699],[d5701,f5700],[d5701,f5701],[d5703,f5702],[d5703,f5703],[d5705,f5704],[d5705,f5705],[d5707,f5706],[d5707,f5707],[d5709,f5708],[d5709,f5709],[d5711,f5710],[d5711,f5711],[d5713,f5712],[d5713,f5713],[d5715,f5714],[d5715,f5715],[d5717,f5716],[d5717,f5717],[d5719,f5718],[d5719,f5719],[d5721,f5720],[d5721,f5721],[d5723,f5722],[d5723,f5723],[d5725,f5724],[d5725,f5725],[d5727,f5726],[d5727,f5727],[d5729,f5728],[d5729,f5729],[d5731,f5730],[d5731,f5731],[d5733,f5732],[d5733,f5733],[d5735,f5734],[d5735,f5735],[d5737,f5736],[d5737,f5737],[d5739,f5738],[d5739,f5739],[d5741,f5740],[d5741,f5741],[d5743,f5742],[d5743,f5743],[d5745,f5744],[d5745,f5745],[d5747,f5746],[d5747,f5747],[d5749,f5748],[d5749,f5749],[d5751,f5750],[d5751,f5751],[d5753,f5752],[d5753,f5753],[d5755,f5754],[d5755,f5755],[d5757,f5756],[d5757,f5757],[d5759,f5758],[d5759,f5759],[d5761,f5760],[d5761,f5761],[d5763,f5762],[d5763,f5763],[d5765,f5764],[d5765,f5765],[d5767,f5766],[d5767,f5767],[d5769,f5768],[d5769,f5769],[d5771,f5770],[d5771,f5771],[d5773,f5772],[d5773,f5773],[d5775,f5774],[d5775,f5775],[d5777,f5776],[d5777,f5777],[d5779,f5778],[d5779,f5779],[d5781,f5780],[d5781,f5781],[d5783,f5782],[d5783,f5783],[d5785,f5784],[d5785,f5785],[d5787,f5786],[d5787,f5787],[d5789,f5788],[d5789,f5789],[d5791,f5790],[d5791,f5791],[d5793,f5792],[d5793,f5793],[d5795,f5794],[d5795,f5795],[d5797,f5796],[d5797,f5797],[d5799,f5798],[d5799,f5799],[d5801,f5800],[d5801,f5801],[d5803,f5802],[d5803,f5803],[d5805,f5804],[d5805,f5805],[d5807,f5806],[d5807,f5807],[d5809,f5808],[d5809,f5809],[d5811,f5810],[d5811,f5811],[d5813,f5812],[d5813,f5813],[d5815,f5814],[d5815,f5815],[d5817,f5816],[d5817,f5817],[d5819,f5818],[d5819,f5819],[d5821,f5820],[d5821,f5821],[d5823,f5822],[d5823,f5823],[d5825,f5824],[d5825,f5825],[d5827,f5826],[d5827,f5827],[d5829,f5828],[d5829,f5829],[d5831,f5830],[d5831,f5831],[d5833,f5832],[d5833,f5833],[d5835,f5834],[d5835,f5835],[d5837,f5836],[d5837,f5837],[d5839,f5838],[d5839,f5839],[d5841,f5840],[d5841,f5841],[d5843,f5842],[d5843,f5843],[d5845,f5844],[d5845,f5845],[d5847,f5846],[d5847,f5847],[d5849,f5848],[d5849,f5849],[d5851,f5850],[d5851,f5851],[d5853,f5852],[d5853,f5853],[d5855,f5854],[d5855,f5855],[d5857,f5856],[d5857,f5857],[d5859,f5858],[d5859,f5859],[d5861,f5860],[d5861,f5861],[d5863,f5862],[d5863,f5863],[d5865,f5864],[d5865,f5865],[d5867,f5866],[d5867,f5867],[d5869,f5868],[d5869,f5869],[d5871,f5870],[d5871,f5871],[d5873,f5872],[d5873,f5873],[d5875,f5874],[d5875,f5875],[d5877,f5876],[d5877,f5877],[d5879,f5878],[d5879,f5879],[d5881,f5880],[d5881,f5881],[d5883,f5882],[d5883,f5883],[d5885,f5884],[d5885,f5885],[d5887,f5886],[d5887,f5887],[d5889,f5888],[d5889,f5889],[d5891,f5890],[d5891,f5891],[d5893,f5892],[d5893,f5893],[d5895,f5894],[d5895,f5895],[d5897,f5896],[d5897,f5897],[d5899,f5898],[d5899,f5899],[d5901,f5900],[d5901,f5901],[d5903,f5902],[d5903,f5903],[d5905,f5904],[d5905,f5905],[d5907,f5906],[d5907,f5907],[d5909,f5908],[d5909,f5909],[d5911,f5910],[d5911,f5911],[d5913,f5912],[d5913,f5913],[d5915,f5914],[d5915,f5915],[d5917,f5916],[d5917,f5917],[d5919,f5918],[d5919,f5919],[d5921,f5920],[d5921,f5921],[d5923,f5922],[d5923,f5923],[d5925,f5924],[d5925,f5925],[d5927,f5926],[d5927,f5927],[d5929,f5928],[d5929,f5929],[d5931,f5930],[d5931,f5931],[d5933,f5932],[d5933,f5933],[d5935,f5934],[d5935,f5935],[d5937,f5936],[d5937,f5937],[d5939,f5938],[d5939,f5939],[d5941,f5940],[d5941,f5941],[d5943,f5942],[d5943,f5943],[d5945,f5944],[d5945,f5945],[d5947,f5946],[d5947,f5947],[d5949,f5948],[d5949,f5949],[d5951,f5950],[d5951,f5951],[d5953,f5952],[d5953,f5953],[d5955,f5954],[d5955,f5955],[d5957,f5956],[d5957,f5957],[d5959,f5958],[d5959,f5959],[d5961,f5960],[d5961,f5961],[d5963,f5962],[d5963,f5963],[d5965,f5964],[d5965,f5965],[d5967,f5966],[d5967,f5967],[d5969,f5968],[d5969,f5969],[d5971,f5970],[d5971,f5971],[d5973,f5972],[d5973,f5973],[d5975,f5974],[d5975,f5975],[d5977,f5976],[d5977,f5977],[d5979,f5978],[d5979,f5979],[d5981,f5980],[d5981,f5981],[d5983,f5982],[d5983,f5983],[d5985,f5984],[d5985,f5985],[d5987,f5986],[d5987,f5987],[d5989,f5988],[d5989,f5989],[d5991,f5990],[d5991,f5991],[d5993,f5992],[d5993,f5993],[d5995,f5994],[d5995,f5995],[d5997,f5996],[d5997,f5997],[d5999,f5998],[d5999,f5999],[d6001,f6000],[d6001,f6001],[d6003,f6002],[d6003,f6003],[d6005,f6004],[d6005,f6005],[d6007,f6006],[d6007,f6007],[d6009,f6008],[d6009,f6009],[d6011,f6010],[d6011,f6011],[d6013,f6012],[d6013,f6013],[d6015,f6014],[d6015,f6015],[d6017,f6016],[d6017,f6017],[d6019,f6018],[d6019,f6019],[d6021,f6020],[d6021,f6021],[d6023,f6022],[d6023,f6023],[d6025,f6024],[d6025,f6025],[d6027,f6026],[d6027,f6027],[d6029,f6028],[d6029,f6029],[d6031,f6030],[d6031,f6031],[d6033,f6032],[d6033,f6033],[d6035,f6034],[d6035,f6035],[d6037,f6036],[d6037,f6037],[d6039,f6038],[d6039,f6039],[d6041,f6040],[d6041,f6041],[d6043,f6042],[d6043,f6043],[d6045,f6044],[d6045,f6045],[d6047,f6046],[d6047,f6047],[d6049,f6048],[d6049,f6049],[d6051,f6050],[d6051,f6051],[d6053,f6052],[d6053,f6053],[d6055,f6054],[d6055,f6055],[d6057,f6056],[d6057,f6057],[d6059,f6058],[d6059,f6059],[d6061,f6060],[d6061,f6061],[d6063,f6062],[d6063,f6063],[d6065,f6064],[d6065,f6065],[d6067,f6066],[d6067,f6067],[d6069,f6068],[d6069,f6069],[d6071,f6070],[d6071,f6071],[d6073,f6072],[d6073,f6073],[d6075,f6074],[d6075,f6075],[d6077,f6076],[d6077,f6077],[d6079,f6078],[d6079,f6079],[d6081,f6080],[d6081,f6081],[d6083,f6082],[d6083,f6083],[d6085,f6084],[d6085,f6085],[d6087,f6086],[d6087,f6087],[d6089,f6088],[d6089,f6089],[d6091,f6090],[d6091,f6091],[d6093,f6092],[d6093,f6093],[d6095,f6094],[d6095,f6095],[d6097,f6096],[d6097,f6097],[d6099,f6098],[d6099,f6099],[d6101,f6100],[d6101,f6101],[d6103,f6102],[d6103,f6103],[d6105,f6104],[d6105,f6105],[d6107,f6106],[d6107,f6107],[d6109,f6108],[d6109,f6109],[d6111,f6110],[d6111,f6111],[d6113,f6112],[d6113,f6113],[d6115,f6114],[d6115,f6115],[d6117,f6116],[d6117,f6117],[d6119,f6118],[d6119,f6119],[d6121,f6120],[d6121,f6121],[d6123,f6122],[d6123,f6123],[d6125,f6124],[d6125,f6125],[d6127,f6126],[d6127,f6127],[d6129,f6128],[d6129,f6129],[d6131,f6130],[d6131,f6131],[d6133,f6132],[d6133,f6133],[d6135,f6134],[d6135,f6135],[d6137,f6136],[d6137,f6137],[d6139,f6138],[d6139,f6139],[d6141,f6140],[d6141,f6141],[d6143,f6142],[d6143,f6143],[d6145,f6144],[d6145,f6145],[d6147,f6146],[d6147,f6147],[d6149,f6148],[d6149,f6149],[d6151,f6150],[d6151,f6151],[d6153,f6152],[d6153,f6153],[d6155,f6154],[d6155,f6155],[d6157,f6156],[d6157,f6157],[d6159,f6158],[d6159,f6159],[d6161,f6160],[d6161,f6161],[d6163,f6162],[d6163,f6163],[d6165,f6164],[d6165,f6165],[d6167,f6166],[d6167,f6167],[d6169,f6168],[d6169,f6169],[d6171,f6170],[d6171,f6171],[d6173,f6172],[d6173,f6173],[d6175,f6174],[d6175,f6175],[d6177,f6176],[d6177,f6177],[d6179,f6178],[d6179,f6179],[d6181,f6180],[d6181,f6181],[d6183,f6182],[d6183,f6183],[d6185,f6184],[d6185,f6185],[d6187,f6186],[d6187,f6187],[d6189,f6188],[d6189,f6189],[d6191,f6190],[d6191,f6191],[d6193,f6192],[d6193,f6193],[d6195,f6194],[d6195,f6195],[d6197,f6196],[d6197,f6197],[d6199,f6198],[d6199,f6199],[d6201,f6200],[d6201,f6201],[d6203,f6202],[d6203,f6203],[d6205,f6204],[d6205,f6205],[d6207,f6206],[d6207,f6207],[d6209,f6208],[d6209,f6209],[d6211,f6210],[d6211,f6211],[d6213,f6212],[d6213,f6213],[d6215,f6214],[d6215,f6215],[d6217,f6216],[d6217,f6217],[d6219,f6218],[d6219,f6219],[d6221,f6220],[d6221,f6221],[d6223,f6222],[d6223,f6223],[d6225,f6224],[d6225,f6225],[d6227,f6226],[d6227,f6227],[d6229,f6228],[d6229,f6229],[d6231,f6230],[d6231,f6231],[d6233,f6232],[d6233,f6233],[d6235,f6234],[d6235,f6235],[d6237,f6236],[d6237,f6237],[d6239,f6238],[d6239,f6239],[d6241,f6240],[d6241,f6241],[d6243,f6242],[d6243,f6243],[d6245,f6244],[d6245,f6245],[d6247,f6246],[d6247,f6247],[d6249,f6248],[d6249,f6249],[d6251,f6250],[d6251,f6251],[d6253,f6252],[d6253,f6253],[d6255,f6254],[d6255,f6255],[d6257,f6256],[d6257,f6257],[d6259,f6258],[d6259,f6259],[d6261,f6260],[d6261,f6261],[d6263,f6262],[d6263,f6263],[d6265,f6264],[d6265,f6265],[d6267,f6266],[d6267,f6267],[d6269,f6268],[d6269,f6269],[d6271,f6270],[d6271,f6271],[d6273,f6272],[d6273,f6273],[d6275,f6274],[d6275,f6275],[d6277,f6276],[d6277,f6277],[d6279,f6278],[d6279,f6279],[d6281,f6280],[d6281,f6281],[d6283,f6282],[d6283,f6283],[d6285,f6284],[d6285,f6285],[d6287,f6286],[d6287,f6287],[d6289,f6288],[d6289,f6289],[d6291,f6290],[d6291,f6291],[d6293,f6292],[d6293,f6293],[d6295,f6294],[d6295,f6295],[d6297,f6296],[d6297,f6297],[d6299,f6298],[d6299,f6299],[d6301,f6300],[d6301,f6301],[d6303,f6302],[d6303,f6303],[d6305,f6304],[d6305,f6305],[d6307,f6306],[d6307,f6307],[d6309,f6308],[d6309,f6309],[d6311,f6310],[d6311,f6311],[d6313,f6312],[d6313,f6313],[d6315,f6314],[d6315,f6315],[d6317,f6316],[d6317,f6317],[d6319,f6318],[d6319,f6319],[d6321,f6320],[d6321,f6321],[d6323,f6322],[d6323,f6323],[d6325,f6324],[d6325,f6325],[d6327,f6326],[d6327,f6327],[d6329,f6328],[d6329,f6329],[d6331,f6330],[d6331,f6331],[d6333,f6332],[d6333,f6333],[d6335,f6334],[d6335,f6335],[d6337,f6336],[d6337,f6337],[d6339,f6338],[d6339,f6339],[d6341,f6340],[d6341,f6341],[d6343,f6342],[d6343,f6343],[d6345,f6344],[d6345,f6345],[d6347,f6346],[d6347,f6347],[d6349,f6348],[d6349,f6349],[d6351,f6350],[d6351,f6351],[d6353,f6352],[d6353,f6353],[d6355,f6354],[d6355,f6355],[d6357,f6356],[d6357,f6357],[d6359,f6358],[d6359,f6359],[d6361,f6360],[d6361,f6361],[d6363,f6362],[d6363,f6363],[d6365,f6364],[d6365,f6365],[d6367,f6366],[d6367,f6367],[d6369,f6368],[d6369,f6369],[d6371,f6370],[d6371,f6371],[d6373,f6372],[d6373,f6373],[d6375,f6374],[d6375,f6375],[d6377,f6376],[d6377,f6377],[d6379,f6378],[d6379,f6379],[d6381,f6380],[d6381,f6381],[d6383,f6382],[d6383,f6383],[d6385,f6384],[d6385,f6385],[d6387,f6386],[d6387,f6387],[d6389,f6388],[d6389,f6389],[d6391,f6390],[d6391,f6391],[d6393,f6392],[d6393,f6393],[d6395,f6394],[d6395,f6395],[d6397,f6396],[d6397,f6397],[d6399,f6398],[d6399,f6399],[d6401,f6400],[d6401,f6401],[d6403,f6402],[d6403,f6403],[d6405,f6404],[d6405,f6405],[d6407,f6406],[d6407,f6407],[d6409,f6408],[d6409,f6409],[d6411,f6410],[d6411,f6411],[d6413,f6412],[d6413,f6413],[d6415,f6414],[d6415,f6415],[d6417,f6416],[d6417,f6417],[d6419,f6418],[d6419,f6419],[d6421,f6420],[d6421,f6421],[d6423,f6422],[d6423,f6423],[d6425,f6424],[d6425,f6425],[d6427,f6426],[d6427,f6427],[d6429,f6428],[d6429,f6429],[d6431,f6430],[d6431,f6431],[d6433,f6432],[d6433,f6433],[d6435,f6434],[d6435,f6435],[d6437,f6436],[d6437,f6437],[d6439,f6438],[d6439,f6439],[d6441,f6440],[d6441,f6441],[d6443,f6442],[d6443,f6443],[d6445,f6444],[d6445,f6445],[d6447,f6446],[d6447,f6447],[d6449,f6448],[d6449,f6449],[d6451,f6450],[d6451,f6451],[d6453,f6452],[d6453,f6453],[d6455,f6454],[d6455,f6455],[d6457,f6456],[d6457,f6457],[d6459,f6458],[d6459,f6459],[d6461,f6460],[d6461,f6461],[d6463,f6462],[d6463,f6463],[d6465,f6464],[d6465,f6465],[d6467,f6466],[d6467,f6467],[d6469,f6468],[d6469,f6469],[d6471,f6470],[d6471,f6471],[d6473,f6472],[d6473,f6473],[d6475,f6474],[d6475,f6475],[d6477,f6476],[d6477,f6477],[d6479,f6478],[d6479,f6479],[d6481,f6480],[d6481,f6481],[d6483,f6482],[d6483,f6483],[d6485,f6484],[d6485,f6485],[d6487,f6486],[d6487,f6487],[d6489,f6488],[d6489,f6489],[d6491,f6490],[d6491,f6491],[d6493,f6492],[d6493,f6493],[d6495,f6494],[d6495,f6495],[d6497,f6496],[d6497,f6497],[d6499,f6498],[d6499,f6499],[d6501,f6500],[d6501,f6501],[d6503,f6502],[d6503,f6503],[d6505,f6504],[d6505,f6505],[d6507,f6506],[d6507,f6507],[d6509,f6508],[d6509,f6509],[d6511,f6510],[d6511,f6511],[d6513,f6512],[d6513,f6513],[d6515,f6514],[d6515,f6515],[d6517,f6516],[d6517,f6517],[d6519,f6518],[d6519,f6519],[d6521,f6520],[d6521,f6521],[d6523,f6522],[d6523,f6523],[d6525,f6524],[d6525,f6525],[d6527,f6526],[d6527,f6527],[d6529,f6528],[d6529,f6529],[d6531,f6530],[d6531,f6531],[d6533,f6532],[d6533,f6533],[d6535,f6534],[d6535,f6535],[d6537,f6536],[d6537,f6537],[d6539,f6538],[d6539,f6539],[d6541,f6540],[d6541,f6541],[d6543,f6542],[d6543,f6543],[d6545,f6544],[d6545,f6545],[d6547,f6546],[d6547,f6547],[d6549,f6548],[d6549,f6549],[d6551,f6550],[d6551,f6551],[d6553,f6552],[d6553,f6553],[d6555,f6554],[d6555,f6555],[d6557,f6556],[d6557,f6557],[d6559,f6558],[d6559,f6559],[d6561,f6560],[d6561,f6561],[d6563,f6562],[d6563,f6563],[d6565,f6564],[d6565,f6565],[d6567,f6566],[d6567,f6567],[d6569,f6568],[d6569,f6569],[d6571,f6570],[d6571,f6571],[d6573,f6572],[d6573,f6573],[d6575,f6574],[d6575,f6575],[d6577,f6576],[d6577,f6577],[d6579,f6578],[d6579,f6579],[d6581,f6580],[d6581,f6581],[d6583,f6582],[d6583,f6583],[d6585,f6584],[d6585,f6585],[d6587,f6586],[d6587,f6587],[d6589,f6588],[d6589,f6589],[d6591,f6590],[d6591,f6591],[d6593,f6592],[d6593,f6593],[d6595,f6594],[d6595,f6595],[d6597,f6596],[d6597,f6597],[d6599,f6598],[d6599,f6599],[d6601,f6600],[d6601,f6601],[d6603,f6602],[d6603,f6603],[d6605,f6604],[d6605,f6605],[d6607,f6606],[d6607,f6607],[d6609,f6608],[d6609,f6609],[d6611,f6610],[d6611,f6611],[d6613,f6612],[d6613,f6613],[d6615,f6614],[d6615,f6615],[d6617,f6616],[d6617,f6617],[d6619,f6618],[d6619,f6619],[d6621,f6620],[d6621,f6621],[d6623,f6622],[d6623,f6623],[d6625,f6624],[d6625,f6625],[d6627,f6626],[d6627,f6627],[d6629,f6628],[d6629,f6629],[d6631,f6630],[d6631,f6631],[d6633,f6632],[d6633,f6633],[d6635,f6634],[d6635,f6635],[d6637,f6636],[d6637,f6637],[d6639,f6638],[d6639,f6639],[d6641,f6640],[d6641,f6641],[d6643,f6642],[d6643,f6643],[d6645,f6644],[d6645,f6645],[d6647,f6646],[d6647,f6647],[d6649,f6648],[d6649,f6649],[d6651,f6650],[d6651,f6651],[d6653,f6652],[d6653,f6653],[d6655,f6654],[d6655,f6655],[d6657,f6656],[d6657,f6657],[d6659,f6658],[d6659,f6659],[d6661,f6660],[d6661,f6661],[d6663,f6662],[d6663,f6663],[d6665,f6664],[d6665,f6665],[d6667,f6666],[d6667,f6667],[d6669,f6668],[d6669,f6669],[d6671,f6670],[d6671,f6671],[d6673,f6672],[d6673,f6673],[d6675,f6674],[d6675,f6675],[d6677,f6676],[d6677,f6677],[d6679,f6678],[d6679,f6679],[d6681,f6680],[d6681,f6681],[d6683,f6682],[d6683,f6683],[d6685,f6684],[d6685,f6685],[d6687,f6686],[d6687,f6687],[d6689,f6688],[d6689,f6689],[d6691,f6690],[d6691,f6691],[d6693,f6692],[d6693,f6693],[d6695,f6694],[d6695,f6695],[d6697,f6696],[d6697,f6697],[d6699,f6698],[d6699,f6699],[d6701,f6700],[d6701,f6701],[d6703,f6702],[d6703,f6703],[d6705,f6704],[d6705,f6705],[d6707,f6706],[d6707,f6707],[d6709,f6708],[d6709,f6709],[d6711,f6710],[d6711,f6711],[d6713,f6712],[d6713,f6713],[d6715,f6714],[d6715,f6715],[d6717,f6716],[d6717,f6717],[d6719,f6718],[d6719,f6719],[d6721,f6720],[d6721,f6721],[d6723,f6722],[d6723,f6723],[d6725,f6724],[d6725,f6725],[d6727,f6726],[d6727,f6727],[d6729,f6728],[d6729,f6729],[d6731,f6730],[d6731,f6731],[d6733,f6732],[d6733,f6733],[d6735,f6734],[d6735,f6735],[d6737,f6736],[d6737,f6737],[d6739,f6738],[d6739,f6739],[d6741,f6740],[d6741,f6741],[d6743,f6742],[d6743,f6743],[d6745,f6744],[d6745,f6745],[d6747,f6746],[d6747,f6747],[d6749,f6748],[d6749,f6749],[d6751,f6750],[d6751,f6751],[d6753,f6752],[d6753,f6753],[d6755,f6754],[d6755,f6755],[d6757,f6756],[d6757,f6757],[d6759,f6758],[d6759,f6759],[d6761,f6760],[d6761,f6761],[d6763,f6762],[d6763,f6763],[d6765,f6764],[d6765,f6765],[d6767,f6766],[d6767,f6767],[d6769,f6768],[d6769,f6769],[d6771,f6770],[d6771,f6771],[d6773,f6772],[d6773,f6773],[d6775,f6774],[d6775,f6775],[d6777,f6776],[d6777,f6777],[d6779,f6778],[d6779,f6779],[d6781,f6780],[d6781,f6781],[d6783,f6782],[d6783,f6783],[d6785,f6784],[d6785,f6785],[d6787,f6786],[d6787,f6787],[d6789,f6788],[d6789,f6789],[d6791,f6790],[d6791,f6791],[d6793,f6792],[d6793,f6793],[d6795,f6794],[d6795,f6795],[d6797,f6796],[d6797,f6797],[d6799,f6798],[d6799,f6799],[d6801,f6800],[d6801,f6801],[d6803,f6802],[d6803,f6803],[d6805,f6804],[d6805,f6805],[d6807,f6806],[d6807,f6807],[d6809,f6808],[d6809,f6809],[d6811,f6810],[d6811,f6811],[d6813,f6812],[d6813,f6813],[d6815,f6814],[d6815,f6815],[d6817,f6816],[d6817,f6817],[d6819,f6818],[d6819,f6819],[d6821,f6820],[d6821,f6821],[d6823,f6822],[d6823,f6823],[d6825,f6824],[d6825,f6825],[d6827,f6826],[d6827,f6827],[d6829,f6828],[d6829,f6829],[d6831,f6830],[d6831,f6831],[d6833,f6832],[d6833,f6833],[d6835,f6834],[d6835,f6835],[d6837,f6836],[d6837,f6837],[d6839,f6838],[d6839,f6839],[d6841,f6840],[d6841,f6841],[d6843,f6842],[d6843,f6843],[d6845,f6844],[d6845,f6845],[d6847,f6846],[d6847,f6847],[d6849,f6848],[d6849,f6849],[d6851,f6850],[d6851,f6851],[d6853,f6852],[d6853,f6853],[d6855,f6854],[d6855,f6855],[d6857,f6856],[d6857,f6857],[d6859,f6858],[d6859,f6859],[d6861,f6860],[d6861,f6861],[d6863,f6862],[d6863,f6863],[d6865,f6864],[d6865,f6865],[d6867,f6866],[d6867,f6867],[d6869,f6868],[d6869,f6869],[d6871,f6870],[d6871,f6871],[d6873,f6872],[d6873,f6873],[d6875,f6874],[d6875,f6875],[d6877,f6876],[d6877,f6877],[d6879,f6878],[d6879,f6879],[d6881,f6880],[d6881,f6881],[d6883,f6882],[d6883,f6883],[d6885,f6884],[d6885,f6885],[d6887,f6886],[d6887,f6887],[d6889,f6888],[d6889,f6889],[d6891,f6890],[d6891,f6891],[d6893,f6892],[d6893,f6893],[d6895,f6894],[d6895,f6895],[d6897,f6896],[d6897,f6897],[d6899,f6898],[d6899,f6899],[d6901,f6900],[d6901,f6901],[d6903,f6902],[d6903,f6903],[d6905,f6904],[d6905,f6905],[d6907,f6906],[d6907,f6907],[d6909,f6908],[d6909,f6909],[d6911,f6910],[d6911,f6911],[d6913,f6912],[d6913,f6913],[d6915,f6914],[d6915,f6915],[d6917,f6916],[d6917,f6917],[d6919,f6918],[d6919,f6919],[d6921,f6920],[d6921,f6921],[d6923,f6922],[d6923,f6923],[d6925,f6924],[d6925,f6925],[d6927,f6926],[d6927,f6927],[d6929,f6928],[d6929,f6929],[d6931,f6930],[d6931,f6931],[d6933,f6932],[d6933,f6933],[d6935,f6934],[d6935,f6935],[d6937,f6936],[d6937,f6937],[d6939,f6938],[d6939,f6939],[d6941,f6940],[d6941,f6941],[d6943,f6942],[d6943,f6943],[d6945,f6944],[d6945,f6945],[d6947,f6946],[d6947,f6947],[d6949,f6948],[d6949,f6949],[d6951,f6950],[d6951,f6951],[d6953,f6952],[d6953,f6953],[d6955,f6954],[d6955,f6955],[d6957,f6956],[d6957,f6957],[d6959,f6958],[d6959,f6959],[d6961,f6960],[d6961,f6961],[d6963,f6962],[d6963,f6963],[d6965,f6964],[d6965,f6965],[d6967,f6966],[d6967,f6967],[d6969,f6968],[d6969,f6969],[d6971,f6970],[d6971,f6971],[d6973,f6972],[d6973,f6973],[d6975,f6974],[d6975,f6975],[d6977,f6976],[d6977,f6977],[d6979,f6978],[d6979,f6979],[d6981,f6980],[d6981,f6981],[d6983,f6982],[d6983,f6983],[d6985,f6984],[d6985,f6985],[d6987,f6986],[d6987,f6987],[d6989,f6988],[d6989,f6989],[d6991,f6990],[d6991,f6991],[d6993,f6992],[d6993,f6993],[d6995,f6994],[d6995,f6995],[d6997,f6996],[d6997,f6997],[d6999,f6998],[d6999,f6999],[d7001,f7000],[d7001,f7001],[d7003,f7002],[d7003,f7003],[d7005,f7004],[d7005,f7005],[d7007,f7006],[d7007,f7007],[d7009,f7008],[d7009,f7009],[d7011,f7010],[d7011,f7011],[d7013,f7012],[d7013,f7013],[d7015,f7014],[d7015,f7015],[d7017,f7016],[d7017,f7017],[d7019,f7018],[d7019,f7019],[d7021,f7020],[d7021,f7021],[d7023,f7022],[d7023,f7023],[d7025,f7024],[d7025,f7025],[d7027,f7026],[d7027,f7027],[d7029,f7028],[d7029,f7029],[d7031,f7030],[d7031,f7031],[d7033,f7032],[d7033,f7033],[d7035,f7034],[d7035,f7035],[d7037,f7036],[d7037,f7037],[d7039,f7038],[d7039,f7039],[d7041,f7040],[d7041,f7041],[d7043,f7042],[d7043,f7043],[d7045,f7044],[d7045,f7045],[d7047,f7046],[d7047,f7047],[d7049,f7048],[d7049,f7049],[d7051,f7050],[d7051,f7051],[d7053,f7052],[d7053,f7053],[d7055,f7054],[d7055,f7055],[d7057,f7056],[d7057,f7057],[d7059,f7058],[d7059,f7059],[d7061,f7060],[d7061,f7061],[d7063,f7062],[d7063,f7063],[d7065,f7064],[d7065,f7065],[d7067,f7066],[d7067,f7067],[d7069,f7068],[d7069,f7069],[d7071,f7070],[d7071,f7071],[d7073,f7072],[d7073,f7073],[d7075,f7074],[d7075,f7075],[d7077,f7076],[d7077,f7077],[d7079,f7078],[d7079,f7079],[d7081,f7080],[d7081,f7081],[d7083,f7082],[d7083,f7083],[d7085,f7084],[d7085,f7085],[d7087,f7086],[d7087,f7087],[d7089,f7088],[d7089,f7089],[d7091,f7090],[d7091,f7091],[d7093,f7092],[d7093,f7093],[d7095,f7094],[d7095,f7095],[d7097,f7096],[d7097,f7097],[d7099,f7098],[d7099,f7099],[d7101,f7100],[d7101,f7101],[d7103,f7102],[d7103,f7103],[d7105,f7104],[d7105,f7105],[d7107,f7106],[d7107,f7107],[d7109,f7108],[d7109,f7109],[d7111,f7110],[d7111,f7111],[d7113,f7112],[d7113,f7113],[d7115,f7114],[d7115,f7115],[d7117,f7116],[d7117,f7117],[d7119,f7118],[d7119,f7119],[d7121,f7120],[d7121,f7121],[d7123,f7122],[d7123,f7123],[d7125,f7124],[d7125,f7125],[d7127,f7126],[d7127,f7127],[d7129,f7128],[d7129,f7129],[d7131,f7130],[d7131,f7131],[d7133,f7132],[d7133,f7133],[d7135,f7134],[d7135,f7135],[d7137,f7136],[d7137,f7137],[d7139,f7138],[d7139,f7139],[d7141,f7140],[d7141,f7141],[d7143,f7142],[d7143,f7143],[d7145,f7144],[d7145,f7145],[d7147,f7146],[d7147,f7147],[d7149,f7148],[d7149,f7149],[d7151,f7150],[d7151,f7151],[d7153,f7152],[d7153,f7153],[d7155,f7154],[d7155,f7155],[d7157,f7156],[d7157,f7157],[d7159,f7158],[d7159,f7159],[d7161,f7160],[d7161,f7161],[d7163,f7162],[d7163,f7163],[d7165,f7164],[d7165,f7165],[d7167,f7166],[d7167,f7167],[d7169,f7168],[d7169,f7169],[d7171,f7170],[d7171,f7171],[d7173,f7172],[d7173,f7173],[d7175,f7174],[d7175,f7175],[d7177,f7176],[d7177,f7177],[d7179,f7178],[d7179,f7179],[d7181,f7180],[d7181,f7181],[d7183,f7182],[d7183,f7183],[d7185,f7184],[d7185,f7185],[d7187,f7186],[d7187,f7187],[d7189,f7188],[d7189,f7189],[d7191,f7190],[d7191,f7191],[d7193,f7192],[d7193,f7193],[d7195,f7194],[d7195,f7195],[d7197,f7196],[d7197,f7197],[d7199,f7198],[d7199,f7199],[d7201,f7200],[d7201,f7201],[d7203,f7202],[d7203,f7203],[d7205,f7204],[d7205,f7205],[d7207,f7206],[d7207,f7207],[d7209,f7208],[d7209,f7209],[d7211,f7210],[d7211,f7211],[d7213,f7212],[d7213,f7213],[d7215,f7214],[d7215,f7215],[d7217,f7216],[d7217,f7217],[d7219,f7218],[d7219,f7219],[d7221,f7220],[d7221,f7221],[d7223,f7222],[d7223,f7223],[d7225,f7224],[d7225,f7225],[d7227,f7226],[d7227,f7227],[d7229,f7228],[d7229,f7229],[d7231,f7230],[d7231,f7231],[d7233,f7232],[d7233,f7233],[d7235,f7234],[d7235,f7235],[d7237,f7236],[d7237,f7237],[d7239,f7238],[d7239,f7239],[d7241,f7240],[d7241,f7241],[d7243,f7242],[d7243,f7243],[d7245,f7244],[d7245,f7245],[d7247,f7246],[d7247,f7247],[d7249,f7248],[d7249,f7249],[d7251,f7250],[d7251,f7251],[d7253,f7252],[d7253,f7253],[d7255,f7254],[d7255,f7255],[d7257,f7256],[d7257,f7257],[d7259,f7258],[d7259,f7259],[d7261,f7260],[d7261,f7261],[d7263,f7262],[d7263,f7263],[d7265,f7264],[d7265,f7265],[d7267,f7266],[d7267,f7267],[d7269,f7268],[d7269,f7269],[d7271,f7270],[d7271,f7271],[d7273,f7272],[d7273,f7273],[d7275,f7274],[d7275,f7275],[d7277,f7276],[d7277,f7277],[d7279,f7278],[d7279,f7279],[d7281,f7280],[d7281,f7281],[d7283,f7282],[d7283,f7283],[d7285,f7284],[d7285,f7285],[d7287,f7286],[d7287,f7287],[d7289,f7288],[d7289,f7289],[d7291,f7290],[d7291,f7291],[d7293,f7292],[d7293,f7293],[d7295,f7294],[d7295,f7295],[d7297,f7296],[d7297,f7297],[d7299,f7298],[d7299,f7299],[d7301,f7300],[d7301,f7301],[d7303,f7302],[d7303,f7303],[d7305,f7304],[d7305,f7305],[d7307,f7306],[d7307,f7307],[d7309,f7308],[d7309,f7309],[d7311,f7310],[d7311,f7311],[d7313,f7312],[d7313,f7313],[d7315,f7314],[d7315,f7315],[d7317,f7316],[d7317,f7317],[d7319,f7318],[d7319,f7319],[d7321,f7320],[d7321,f7321],[d7323,f7322],[d7323,f7323],[d7325,f7324],[d7325,f7325],[d7327,f7326],[d7327,f7327],[d7329,f7328],[d7329,f7329],[d7331,f7330],[d7331,f7331],[d7333,f7332],[d7333,f7333],[d7335,f7334],[d7335,f7335],[d7337,f7336],[d7337,f7337],[d7339,f7338],[d7339,f7339],[d7341,f7340],[d7341,f7341],[d7343,f7342],[d7343,f7343],[d7345,f7344],[d7345,f7345],[d7347,f7346],[d7347,f7347],[d7349,f7348],[d7349,f7349],[d7351,f7350],[d7351,f7351],[d7353,f7352],[d7353,f7353],[d7355,f7354],[d7355,f7355],[d7357,f7356],[d7357,f7357],[d7359,f7358],[d7359,f7359],[d7361,f7360],[d7361,f7361],[d7363,f7362],[d7363,f7363],[d7365,f7364],[d7365,f7365],[d7367,f7366],[d7367,f7367],[d7369,f7368],[d7369,f7369],[d7371,f7370],[d7371,f7371],[d7373,f7372],[d7373,f7373],[d7375,f7374],[d7375,f7375],[d7377,f7376],[d7377,f7377],[d7379,f7378],[d7379,f7379],[d7381,f7380],[d7381,f7381],[d7383,f7382],[d7383,f7383],[d7385,f7384],[d7385,f7385],[d7387,f7386],[d7387,f7387],[d7389,f7388],[d7389,f7389],[d7391,f7390],[d7391,f7391],[d7393,f7392],[d7393,f7393],[d7395,f7394],[d7395,f7395],[d7397,f7396],[d7397,f7397],[d7399,f7398],[d7399,f7399],[d7401,f7400],[d7401,f7401],[d7403,f7402],[d7403,f7403],[d7405,f7404],[d7405,f7405],[d7407,f7406],[d7407,f7407],[d7409,f7408],[d7409,f7409],[d7411,f7410],[d7411,f7411],[d7413,f7412],[d7413,f7413],[d7415,f7414],[d7415,f7415],[d7417,f7416],[d7417,f7417],[d7419,f7418],[d7419,f7419],[d7421,f7420],[d7421,f7421],[d7423,f7422],[d7423,f7423],[d7425,f7424],[d7425,f7425],[d7427,f7426],[d7427,f7427],[d7429,f7428],[d7429,f7429],[d7431,f7430],[d7431,f7431],[d7433,f7432],[d7433,f7433],[d7435,f7434],[d7435,f7435],[d7437,f7436],[d7437,f7437],[d7439,f7438],[d7439,f7439],[d7441,f7440],[d7441,f7441],[d7443,f7442],[d7443,f7443],[d7445,f7444],[d7445,f7445],[d7447,f7446],[d7447,f7447],[d7449,f7448],[d7449,f7449],[d7451,f7450],[d7451,f7451],[d7453,f7452],[d7453,f7453],[d7455,f7454],[d7455,f7455],[d7457,f7456],[d7457,f7457],[d7459,f7458],[d7459,f7459],[d7461,f7460],[d7461,f7461],[d7463,f7462],[d7463,f7463],[d7465,f7464],[d7465,f7465],[d7467,f7466],[d7467,f7467],[d7469,f7468],[d7469,f7469],[d7471,f7470],[d7471,f7471],[d7473,f7472],[d7473,f7473],[d7475,f7474],[d7475,f7475],[d7477,f7476],[d7477,f7477],[d7479,f7478],[d7479,f7479],[d7481,f7480],[d7481,f7481],[d7483,f7482],[d7483,f7483],[d7485,f7484],[d7485,f7485],[d7487,f7486],[d7487,f7487],[d7489,f7488],[d7489,f7489],[d7491,f7490],[d7491,f7491],[d7493,f7492],[d7493,f7493],[d7495,f7494],[d7495,f7495],[d7497,f7496],[d7497,f7497],[d7499,f7498],[d7499,f7499],[d7501,f7500],[d7501,f7501],[d7503,f7502],[d7503,f7503],[d7505,f7504],[d7505,f7505],[d7507,f7506],[d7507,f7507],[d7509,f7508],[d7509,f7509],[d7511,f7510],[d7511,f7511],[d7513,f7512],[d7513,f7513],[d7515,f7514],[d7515,f7515],[d7517,f7516],[d7517,f7517],[d7519,f7518],[d7519,f7519],[d7521,f7520],[d7521,f7521],[d7523,f7522],[d7523,f7523],[d7525,f7524],[d7525,f7525],[d7527,f7526],[d7527,f7527],[d7529,f7528],[d7529,f7529],[d7531,f7530],[d7531,f7531],[d7533,f7532],[d7533,f7533],[d7535,f7534],[d7535,f7535],[d7537,f7536],[d7537,f7537],[d7539,f7538],[d7539,f7539],[d7541,f7540],[d7541,f7541],[d7543,f7542],[d7543,f7543],[d7545,f7544],[d7545,f7545],[d7547,f7546],[d7547,f7547],[d7549,f7548],[d7549,f7549],[d7551,f7550],[d7551,f7551],[d7553,f7552],[d7553,f7553],[d7555,f7554],[d7555,f7555],[d7557,f7556],[d7557,f7557],[d7559,f7558],[d7559,f7559],[d7561,f7560],[d7561,f7561],[d7563,f7562],[d7563,f7563],[d7565,f7564],[d7565,f7565],[d7567,f7566],[d7567,f7567],[d7569,f7568],[d7569,f7569],[d7571,f7570],[d7571,f7571],[d7573,f7572],[d7573,f7573],[d7575,f7574],[d7575,f7575],[d7577,f7576],[d7577,f7577],[d7579,f7578],[d7579,f7579],[d7581,f7580],[d7581,f7581],[d7583,f7582],[d7583,f7583],[d7585,f7584],[d7585,f7585],[d7587,f7586],[d7587,f7587],[d7589,f7588],[d7589,f7589],[d7591,f7590],[d7591,f7591],[d7593,f7592],[d7593,f7593],[d7595,f7594],[d7595,f7595],[d7597,f7596],[d7597,f7597],[d7599,f7598],[d7599,f7599],[d7601,f7600],[d7601,f7601],[d7603,f7602],[d7603,f7603],[d7605,f7604],[d7605,f7605],[d7607,f7606],[d7607,f7607],[d7609,f7608],[d7609,f7609],[d7611,f7610],[d7611,f7611],[d7613,f7612],[d7613,f7613],[d7615,f7614],[d7615,f7615],[d7617,f7616],[d7617,f7617],[d7619,f7618],[d7619,f7619],[d7621,f7620],[d7621,f7621],[d7623,f7622],[d7623,f7623],[d7625,f7624],[d7625,f7625],[d7627,f7626],[d7627,f7627],[d7629,f7628],[d7629,f7629],[d7631,f7630],[d7631,f7631],[d7633,f7632],[d7633,f7633],[d7635,f7634],[d7635,f7635],[d7637,f7636],[d7637,f7637],[d7639,f7638],[d7639,f7639],[d7641,f7640],[d7641,f7641],[d7643,f7642],[d7643,f7643],[d7645,f7644],[d7645,f7645],[d7647,f7646],[d7647,f7647],[d7649,f7648],[d7649,f7649],[d7651,f7650],[d7651,f7651],[d7653,f7652],[d7653,f7653],[d7655,f7654],[d7655,f7655],[d7657,f7656],[d7657,f7657],[d7659,f7658],[d7659,f7659],[d7661,f7660],[d7661,f7661],[d7663,f7662],[d7663,f7663],[d7665,f7664],[d7665,f7665],[d7667,f7666],[d7667,f7667],[d7669,f7668],[d7669,f7669],[d7671,f7670],[d7671,f7671],[d7673,f7672],[d7673,f7673],[d7675,f7674],[d7675,f7675],[d7677,f7676],[d7677,f7677],[d7679,f7678],[d7679,f7679],[d7681,f7680],[d7681,f7681],[d7683,f7682],[d7683,f7683],[d7685,f7684],[d7685,f7685],[d7687,f7686],[d7687,f7687],[d7689,f7688],[d7689,f7689],[d7691,f7690],[d7691,f7691],[d7693,f7692],[d7693,f7693],[d7695,f7694],[d7695,f7695],[d7697,f7696],[d7697,f7697],[d7699,f7698],[d7699,f7699],[d7701,f7700],[d7701,f7701],[d7703,f7702],[d7703,f7703],[d7705,f7704],[d7705,f7705],[d7707,f7706],[d7707,f7707],[d7709,f7708],[d7709,f7709],[d7711,f7710],[d7711,f7711],[d7713,f7712],[d7713,f7713],[d7715,f7714],[d7715,f7715],[d7717,f7716],[d7717,f7717],[d7719,f7718],[d7719,f7719],[d7721,f7720],[d7721,f7721],[d7723,f7722],[d7723,f7723],[d7725,f7724],[d7725,f7725],[d7727,f7726],[d7727,f7727],[d7729,f7728],[d7729,f7729],[d7731,f7730],[d7731,f7731],[d7733,f7732],[d7733,f7733],[d7735,f7734],[d7735,f7735],[d7737,f7736],[d7737,f7737],[d7739,f7738],[d7739,f7739],[d7741,f7740],[d7741,f7741],[d7743,f7742],[d7743,f7743],[d7745,f7744],[d7745,f7745],[d7747,f7746],[d7747,f7747],[d7749,f7748],[d7749,f7749],[d7751,f7750],[d7751,f7751],[d7753,f7752],[d7753,f7753],[d7755,f7754],[d7755,f7755],[d7757,f7756],[d7757,f7757],[d7759,f7758],[d7759,f7759],[d7761,f7760],[d7761,f7761],[d7763,f7762],[d7763,f7763],[d7765,f7764],[d7765,f7765],[d7767,f7766],[d7767,f7767],[d7769,f7768],[d7769,f7769],[d7771,f7770],[d7771,f7771],[d7773,f7772],[d7773,f7773],[d7775,f7774],[d7775,f7775],[d7777,f7776],[d7777,f7777],[d7779,f7778],[d7779,f7779],[d7781,f7780],[d7781,f7781],[d7783,f7782],[d7783,f7783],[d7785,f7784],[d7785,f7785],[d7787,f7786],[d7787,f7787],[d7789,f7788],[d7789,f7789],[d7791,f7790],[d7791,f7791],[d7793,f7792],[d7793,f7793],[d7795,f7794],[d7795,f7795],[d7797,f7796],[d7797,f7797],[d7799,f7798],[d7799,f7799],[d7801,f7800],[d7801,f7801],[d7803,f7802],[d7803,f7803],[d7805,f7804],[d7805,f7805],[d7807,f7806],[d7807,f7807],[d7809,f7808],[d7809,f7809],[d7811,f7810],[d7811,f7811],[d7813,f7812],[d7813,f7813],[d7815,f7814],[d7815,f7815],[d7817,f7816],[d7817,f7817],[d7819,f7818],[d7819,f7819],[d7821,f7820],[d7821,f7821],[d7823,f7822],[d7823,f7823],[d7825,f7824],[d7825,f7825],[d7827,f7826],[d7827,f7827],[d7829,f7828],[d7829,f7829],[d7831,f7830],[d7831,f7831],[d7833,f7832],[d7833,f7833],[d7835,f7834],[d7835,f7835],[d7837,f7836],[d7837,f7837],[d7839,f7838],[d7839,f7839],[d7841,f7840],[d7841,f7841],[d7843,f7842],[d7843,f7843],[d7845,f7844],[d7845,f7845],[d7847,f7846],[d7847,f7847],[d7849,f7848],[d7849,f7849],[d7851,f7850],[d7851,f7851],[d7853,f7852],[d7853,f7853],[d7855,f7854],[d7855,f7855],[d7857,f7856],[d7857,f7857],[d7859,f7858],[d7859,f7859],[d7861,f7860],[d7861,f7861],[d7863,f7862],[d7863,f7863],[d7865,f7864],[d7865,f7865],[d7867,f7866],[d7867,f7867],[d7869,f7868],[d7869,f7869],[d7871,f7870],[d7871,f7871],[d7873,f7872],[d7873,f7873],[d7875,f7874],[d7875,f7875],[d7877,f7876],[d7877,f7877],[d7879,f7878],[d7879,f7879],[d7881,f7880],[d7881,f7881],[d7883,f7882],[d7883,f7883],[d7885,f7884],[d7885,f7885],[d7887,f7886],[d7887,f7887],[d7889,f7888],[d7889,f7889],[d7891,f7890],[d7891,f7891],[d7893,f7892],[d7893,f7893],[d7895,f7894],[d7895,f7895],[d7897,f7896],[d7897,f7897],[d7899,f7898],[d7899,f7899],[d7901,f7900],[d7901,f7901],[d7903,f7902],[d7903,f7903],[d7905,f7904],[d7905,f7905],[d7907,f7906],[d7907,f7907],[d7909,f7908],[d7909,f7909],[d7911,f7910],[d7911,f7911],[d7913,f7912],[d7913,f7913],[d7915,f7914],[d7915,f7915],[d7917,f7916],[d7917,f7917],[d7919,f7918],[d7919,f7919],[d7921,f7920],[d7921,f7921],[d7923,f7922],[d7923,f7923],[d7925,f7924],[d7925,f7925],[d7927,f7926],[d7927,f7927],[d7929,f7928],[d7929,f7929],[d7931,f7930],[d7931,f7931],[d7933,f7932],[d7933,f7933],[d7935,f7934],[d7935,f7935],[d7937,f7936],[d7937,f7937],[d7939,f7938],[d7939,f7939],[d7941,f7940],[d7941,f7941],[d7943,f7942],[d7943,f7943],[d7945,f7944],[d7945,f7945],[d7947,f7946],[d7947,f7947],[d7949,f7948],[d7949,f7949],[d7951,f7950],[d7951,f7951],[d7953,f7952],[d7953,f7953],[d7955,f7954],[d7955,f7955],[d7957,f7956],[d7957,f7957],[d7959,f7958],[d7959,f7959],[d7961,f7960],[d7961,f7961],[d7963,f7962],[d7963,f7963],[d7965,f7964],[d7965,f7965],[d7967,f7966],[d7967,f7967],[d7969,f7968],[d7969,f7969],[d7971,f7970],[d7971,f7971],[d7973,f7972],[d7973,f7973],[d7975,f7974],[d7975,f7975],[d7977,f7976],[d7977,f7977],[d7979,f7978],[d7979,f7979],[d7981,f7980],[d7981,f7981],[d7983,f7982],[d7983,f7983],[d7985,f7984],[d7985,f7985],[d7987,f7986],[d7987,f7987],[d7989,f7988],[d7989,f7989],[d7991,f7990],[d7991,f7991],[d7993,f7992],[d7993,f7993],[d7995,f7994],[d7995,f7995],[d7997,f7996],[d7997,f7997],[d7999,f7998],[d7999,f7999],[d8001,f8000],[d8001,f8001],[d8003,f8002],[d8003,f8003],[d8005,f8004],[d8005,f8005],[d8007,f8006],[d8007,f8007],[d8009,f8008],[d8009,f8009],[d8011,f8010],[d8011,f8011],[d8013,f8012],[d8013,f8013],[d8015,f8014],[d8015,f8015],[d8017,f8016],[d8017,f8017],[d8019,f8018],[d8019,f8019],[d8021,f8020],[d8021,f8021],[d8023,f8022],[d8023,f8023],[d8025,f8024],[d8025,f8025],[d8027,f8026],[d8027,f8027],[d8029,f8028],[d8029,f8029],[d8031,f8030],[d8031,f8031],[d8033,f8032],[d8033,f8033],[d8035,f8034],[d8035,f8035],[d8037,f8036],[d8037,f8037],[d8039,f8038],[d8039,f8039],[d8041,f8040],[d8041,f8041],[d8043,f8042],[d8043,f8043],[d8045,f8044],[d8045,f8045],[d8047,f8046],[d8047,f8047],[d8049,f8048],[d8049,f8049],[d8051,f8050],[d8051,f8051],[d8053,f8052],[d8053,f8053],[d8055,f8054],[d8055,f8055],[d8057,f8056],[d8057,f8057],[d8059,f8058],[d8059,f8059],[d8061,f8060],[d8061,f8061],[d8063,f8062],[d8063,f8063],[d8065,f8064],[d8065,f8065],[d8067,f8066],[d8067,f8067],[d8069,f8068],[d8069,f8069],[d8071,f8070],[d8071,f8071],[d8073,f8072],[d8073,f8073],[d8075,f8074],[d8075,f8075],[d8077,f8076],[d8077,f8077],[d8079,f8078],[d8079,f8079],[d8081,f8080],[d8081,f8081],[d8083,f8082],[d8083,f8083],[d8085,f8084],[d8085,f8085],[d8087,f8086],[d8087,f8087],[d8089,f8088],[d8089,f8089],[d8091,f8090],[d8091,f8091],[d8093,f8092],[d8093,f8093],[d8095,f8094],[d8095,f8095],[d8097,f8096],[d8097,f8097],[d8099,f8098],[d8099,f8099],[d8101,f8100],[d8101,f8101],[d8103,f8102],[d8103,f8103],[d8105,f8104],[d8105,f8105],[d8107,f8106],[d8107,f8107],[d8109,f8108],[d8109,f8109],[d8111,f8110],[d8111,f8111],[d8113,f8112],[d8113,f8113],[d8115,f8114],[d8115,f8115],[d8117,f8116],[d8117,f8117],[d8119,f8118],[d8119,f8119],[d8121,f8120],[d8121,f8121],[d8123,f8122],[d8123,f8123],[d8125,f8124],[d8125,f8125],[d8127,f8126],[d8127,f8127],[d8129,f8128],[d8129,f8129],[d8131,f8130],[d8131,f8131],[d8133,f8132],[d8133,f8133],[d8135,f8134],[d8135,f8135],[d8137,f8136],[d8137,f8137],[d8139,f8138],[d8139,f8139],[d8141,f8140],[d8141,f8141],[d8143,f8142],[d8143,f8143],[d8145,f8144],[d8145,f8145],[d8147,f8146],[d8147,f8147],[d8149,f8148],[d8149,f8149],[d8151,f8150],[d8151,f8151],[d8153,f8152],[d8153,f8153],[d8155,f8154],[d8155,f8155],[d8157,f8156],[d8157,f8157],[d8159,f8158],[d8159,f8159],[d8161,f8160],[d8161,f8161],[d8163,f8162],[d8163,f8163],[d8165,f8164],[d8165,f8165],[d8167,f8166],[d8167,f8167],[d8169,f8168],[d8169,f8169],[d8171,f8170],[d8171,f8171],[d8173,f8172],[d8173,f8173],[d8175,f8174],[d8175,f8175],[d8177,f8176],[d8177,f8177],[d8179,f8178],[d8179,f8179],[d8181,f8180],[d8181,f8181],[d8183,f8182],[d8183,f8183],[d8185,f8184],[d8185,f8185],[d8187,f8186],[d8187,f8187],[d8189,f8188],[d8189,f8189],[d8191,f8190],[d8191,f8191],[d8193,f8192],[d8193,f8193],[d8195,f8194],[d8195,f8195],[d8197,f8196],[d8197,f8197],[d8199,f8198],[d8199,f8199],[d8201,f8200],[d8201,f8201],[d8203,f8202],[d8203,f8203],[d8205,f8204],[d8205,f8205],[d8207,f8206],[d8207,f8207],[d8209,f8208],[d8209,f8209],[d8211,f8210],[d8211,f8211],[d8213,f8212],[d8213,f8213],[d8215,f8214],[d8215,f8215],[d8217,f8216],[d8217,f8217],[d8219,f8218],[d8219,f8219],[d8221,f8220],[d8221,f8221],[d8223,f8222],[d8223,f8223],[d8225,f8224],[d8225,f8225],[d8227,f8226],[d8227,f8227],[d8229,f8228],[d8229,f8229],[d8231,f8230],[d8231,f8231],[d8233,f8232],[d8233,f8233],[d8235,f8234],[d8235,f8235],[d8237,f8236],[d8237,f8237],[d8239,f8238],[d8239,f8239],[d8241,f8240],[d8241,f8241],[d8243,f8242],[d8243,f8243],[d8245,f8244],[d8245,f8245],[d8247,f8246],[d8247,f8247],[d8249,f8248],[d8249,f8249],[d8251,f8250],[d8251,f8251],[d8253,f8252],[d8253,f8253],[d8255,f8254],[d8255,f8255],[d8257,f8256],[d8257,f8257],[d8259,f8258],[d8259,f8259],[d8261,f8260],[d8261,f8261],[d8263,f8262],[d8263,f8263],[d8265,f8264],[d8265,f8265],[d8267,f8266],[d8267,f8267],[d8269,f8268],[d8269,f8269],[d8271,f8270],[d8271,f8271],[d8273,f8272],[d8273,f8273],[d8275,f8274],[d8275,f8275],[d8277,f8276],[d8277,f8277],[d8279,f8278],[d8279,f8279],[d8281,f8280],[d8281,f8281],[d8283,f8282],[d8283,f8283],[d8285,f8284],[d8285,f8285],[d8287,f8286],[d8287,f8287],[d8289,f8288],[d8289,f8289],[d8291,f8290],[d8291,f8291],[d8293,f8292],[d8293,f8293],[d8295,f8294],[d8295,f8295],[d8297,f8296],[d8297,f8297],[d8299,f8298],[d8299,f8299],[d8301,f8300],[d8301,f8301],[d8303,f8302],[d8303,f8303],[d8305,f8304],[d8305,f8305],[d8307,f8306],[d8307,f8307],[d8309,f8308],[d8309,f8309],[d8311,f8310],[d8311,f8311],[d8313,f8312],[d8313,f8313],[d8315,f8314],[d8315,f8315],[d8317,f8316],[d8317,f8317],[d8319,f8318],[d8319,f8319],[d8321,f8320],[d8321,f8321],[d8323,f8322],[d8323,f8323],[d8325,f8324],[d8325,f8325],[d8327,f8326],[d8327,f8327],[d8329,f8328],[d8329,f8329],[d8331,f8330],[d8331,f8331],[d8333,f8332],[d8333,f8333],[d8335,f8334],[d8335,f8335],[d8337,f8336],[d8337,f8337],[d8339,f8338],[d8339,f8339],[d8341,f8340],[d8341,f8341],[d8343,f8342],[d8343,f8343],[d8345,f8344],[d8345,f8345],[d8347,f8346],[d8347,f8347],[d8349,f8348],[d8349,f8349],[d8351,f8350],[d8351,f8351],[d8353,f8352],[d8353,f8353],[d8355,f8354],[d8355,f8355],[d8357,f8356],[d8357,f8357],[d8359,f8358],[d8359,f8359],[d8361,f8360],[d8361,f8361],[d8363,f8362],[d8363,f8363],[d8365,f8364],[d8365,f8365],[d8367,f8366],[d8367,f8367],[d8369,f8368],[d8369,f8369],[d8371,f8370],[d8371,f8371],[d8373,f8372],[d8373,f8373],[d8375,f8374],[d8375,f8375],[d8377,f8376],[d8377,f8377],[d8379,f8378],[d8379,f8379],[d8381,f8380],[d8381,f8381],[d8383,f8382],[d8383,f8383],[d8385,f8384],[d8385,f8385],[d8387,f8386],[d8387,f8387],[d8389,f8388],[d8389,f8389],[d8391,f8390],[d8391,f8391],[d8393,f8392],[d8393,f8393],[d8395,f8394],[d8395,f8395],[d8397,f8396],[d8397,f8397],[d8399,f8398],[d8399,f8399],[d8401,f8400],[d8401,f8401],[d8403,f8402],[d8403,f8403],[d8405,f8404],[d8405,f8405],[d8407,f8406],[d8407,f8407],[d8409,f8408],[d8409,f8409],[d8411,f8410],[d8411,f8411],[d8413,f8412],[d8413,f8413],[d8415,f8414],[d8415,f8415],[d8417,f8416],[d8417,f8417],[d8419,f8418],[d8419,f8419],[d8421,f8420],[d8421,f8421],[d8423,f8422],[d8423,f8423],[d8425,f8424],[d8425,f8425],[d8427,f8426],[d8427,f8427],[d8429,f8428],[d8429,f8429],[d8431,f8430],[d8431,f8431],[d8433,f8432],[d8433,f8433],[d8435,f8434],[d8435,f8435],[d8437,f8436],[d8437,f8437],[d8439,f8438],[d8439,f8439],[d8441,f8440],[d8441,f8441],[d8443,f8442],[d8443,f8443],[d8445,f8444],[d8445,f8445],[d8447,f8446],[d8447,f8447],[d8449,f8448],[d8449,f8449],[d8451,f8450],[d8451,f8451],[d8453,f8452],[d8453,f8453],[d8455,f8454],[d8455,f8455],[d8457,f8456],[d8457,f8457],[d8459,f8458],[d8459,f8459],[d8461,f8460],[d8461,f8461],[d8463,f8462],[d8463,f8463],[d8465,f8464],[d8465,f8465],[d8467,f8466],[d8467,f8467],[d8469,f8468],[d8469,f8469],[d8471,f8470],[d8471,f8471],[d8473,f8472],[d8473,f8473],[d8475,f8474],[d8475,f8475],[d8477,f8476],[d8477,f8477],[d8479,f8478],[d8479,f8479],[d8481,f8480],[d8481,f8481],[d8483,f8482],[d8483,f8483],[d8485,f8484],[d8485,f8485],[d8487,f8486],[d8487,f8487],[d8489,f8488],[d8489,f8489],[d8491,f8490],[d8491,f8491],[d8493,f8492],[d8493,f8493],[d8495,f8494],[d8495,f8495],[d8497,f8496],[d8497,f8497],[d8499,f8498],[d8499,f8499],[d8501,f8500],[d8501,f8501],[d8503,f8502],[d8503,f8503],[d8505,f8504],[d8505,f8505],[d8507,f8506],[d8507,f8507],[d8509,f8508],[d8509,f8509],[d8511,f8510],[d8511,f8511],[d8513,f8512],[d8513,f8513],[d8515,f8514],[d8515,f8515],[d8517,f8516],[d8517,f8517],[d8519,f8518],[d8519,f8519],[d8521,f8520],[d8521,f8521],[d8523,f8522],[d8523,f8523],[d8525,f8524],[d8525,f8525],[d8527,f8526],[d8527,f8527],[d8529,f8528],[d8529,f8529],[d8531,f8530],[d8531,f8531],[d8533,f8532],[d8533,f8533],[d8535,f8534],[d8535,f8535],[d8537,f8536],[d8537,f8537],[d8539,f8538],[d8539,f8539],[d8541,f8540],[d8541,f8541],[d8543,f8542],[d8543,f8543],[d8545,f8544],[d8545,f8545],[d8547,f8546],[d8547,f8547],[d8549,f8548],[d8549,f8549],[d8551,f8550],[d8551,f8551],[d8553,f8552],[d8553,f8553],[d8555,f8554],[d8555,f8555],[d8557,f8556],[d8557,f8557],[d8559,f8558],[d8559,f8559],[d8561,f8560],[d8561,f8561],[d8563,f8562],[d8563,f8563],[d8565,f8564],[d8565,f8565],[d8567,f8566],[d8567,f8567],[d8569,f8568],[d8569,f8569],[d8571,f8570],[d8571,f8571],[d8573,f8572],[d8573,f8573],[d8575,f8574],[d8575,f8575],[d8577,f8576],[d8577,f8577],[d8579,f8578],[d8579,f8579],[d8581,f8580],[d8581,f8581],[d8583,f8582],[d8583,f8583],[d8585,f8584],[d8585,f8585],[d8587,f8586],[d8587,f8587],[d8589,f8588],[d8589,f8589],[d8591,f8590],[d8591,f8591],[d8593,f8592],[d8593,f8593],[d8595,f8594],[d8595,f8595],[d8597,f8596],[d8597,f8597],[d8599,f8598],[d8599,f8599],[d8601,f8600],[d8601,f8601],[d8603,f8602],[d8603,f8603],[d8605,f8604],[d8605,f8605],[d8607,f8606],[d8607,f8607],[d8609,f8608],[d8609,f8609],[d8611,f8610],[d8611,f8611],[d8613,f8612],[d8613,f8613],[d8615,f8614],[d8615,f8615],[d8617,f8616],[d8617,f8617],[d8619,f8618],[d8619,f8619],[d8621,f8620],[d8621,f8621],[d8623,f8622],[d8623,f8623],[d8625,f8624],[d8625,f8625],[d8627,f8626],[d8627,f8627],[d8629,f8628],[d8629,f8629],[d8631,f8630],[d8631,f8631],[d8633,f8632],[d8633,f8633],[d8635,f8634],[d8635,f8635],[d8637,f8636],[d8637,f8637],[d8639,f8638],[d8639,f8639],[d8641,f8640],[d8641,f8641],[d8643,f8642],[d8643,f8643],[d8645,f8644],[d8645,f8645],[d8647,f8646],[d8647,f8647],[d8649,f8648],[d8649,f8649],[d8651,f8650],[d8651,f8651],[d8653,f8652],[d8653,f8653],[d8655,f8654],[d8655,f8655],[d8657,f8656],[d8657,f8657],[d8659,f8658],[d8659,f8659],[d8661,f8660],[d8661,f8661],[d8663,f8662],[d8663,f8663],[d8665,f8664],[d8665,f8665],[d8667,f8666],[d8667,f8667],[d8669,f8668],[d8669,f8669],[d8671,f8670],[d8671,f8671],[d8673,f8672],[d8673,f8673],[d8675,f8674],[d8675,f8675],[d8677,f8676],[d8677,f8677],[d8679,f8678],[d8679,f8679],[d8681,f8680],[d8681,f8681],[d8683,f8682],[d8683,f8683],[d8685,f8684],[d8685,f8685],[d8687,f8686],[d8687,f8687],[d8689,f8688],[d8689,f8689],[d8691,f8690],[d8691,f8691],[d8693,f8692],[d8693,f8693],[d8695,f8694],[d8695,f8695],[d8697,f8696],[d8697,f8697],[d8699,f8698],[d8699,f8699],[d8701,f8700],[d8701,f8701],[d8703,f8702],[d8703,f8703],[d8705,f8704],[d8705,f8705],[d8707,f8706],[d8707,f8707],[d8709,f8708],[d8709,f8709],[d8711,f8710],[d8711,f8711],[d8713,f8712],[d8713,f8713],[d8715,f8714],[d8715,f8715],[d8717,f8716],[d8717,f8717],[d8719,f8718],[d8719,f8719],[d8721,f8720],[d8721,f8721],[d8723,f8722],[d8723,f8723],[d8725,f8724],[d8725,f8725],[d8727,f8726],[d8727,f8727],[d8729,f8728],[d8729,f8729],[d8731,f8730],[d8731,f8731],[d8733,f8732],[d8733,f8733],[d8735,f8734],[d8735,f8735],[d8737,f8736],[d8737,f8737],[d8739,f8738],[d8739,f8739],[d8741,f8740],[d8741,f8741],[d8743,f8742],[d8743,f8743],[d8745,f8744],[d8745,f8745],[d8747,f8746],[d8747,f8747],[d8749,f8748],[d8749,f8749],[d8751,f8750],[d8751,f8751],[d8753,f8752],[d8753,f8753],[d8755,f8754],[d8755,f8755],[d8757,f8756],[d8757,f8757],[d8759,f8758],[d8759,f8759],[d8761,f8760],[d8761,f8761],[d8763,f8762],[d8763,f8763],[d8765,f8764],[d8765,f8765],[d8767,f8766],[d8767,f8767],[d8769,f8768],[d8769,f8769],[d8771,f8770],[d8771,f8771],[d8773,f8772],[d8773,f8773],[d8775,f8774],[d8775,f8775],[d8777,f8776],[d8777,f8777],[d8779,f8778],[d8779,f8779],[d8781,f8780],[d8781,f8781],[d8783,f8782],[d8783,f8783],[d8785,f8784],[d8785,f8785],[d8787,f8786],[d8787,f8787],[d8789,f8788],[d8789,f8789],[d8791,f8790],[d8791,f8791],[d8793,f8792],[d8793,f8793],[d8795,f8794],[d8795,f8795],[d8797,f8796],[d8797,f8797],[d8799,f8798],[d8799,f8799],[d8801,f8800],[d8801,f8801],[d8803,f8802],[d8803,f8803],[d8805,f8804],[d8805,f8805],[d8807,f8806],[d8807,f8807],[d8809,f8808],[d8809,f8809],[d8811,f8810],[d8811,f8811],[d8813,f8812],[d8813,f8813],[d8815,f8814],[d8815,f8815],[d8817,f8816],[d8817,f8817],[d8819,f8818],[d8819,f8819],[d8821,f8820],[d8821,f8821],[d8823,f8822],[d8823,f8823],[d8825,f8824],[d8825,f8825],[d8827,f8826],[d8827,f8827],[d8829,f8828],[d8829,f8829],[d8831,f8830],[d8831,f8831],[d8833,f8832],[d8833,f8833],[d8835,f8834],[d8835,f8835],[d8837,f8836],[d8837,f8837],[d8839,f8838],[d8839,f8839],[d8841,f8840],[d8841,f8841],[d8843,f8842],[d8843,f8843],[d8845,f8844],[d8845,f8845],[d8847,f8846],[d8847,f8847],[d8849,f8848],[d8849,f8849],[d8851,f8850],[d8851,f8851],[d8853,f8852],[d8853,f8853],[d8855,f8854],[d8855,f8855],[d8857,f8856],[d8857,f8857],[d8859,f8858],[d8859,f8859],[d8861,f8860],[d8861,f8861],[d8863,f8862],[d8863,f8863],[d8865,f8864],[d8865,f8865],[d8867,f8866],[d8867,f8867],[d8869,f8868],[d8869,f8869],[d8871,f8870],[d8871,f8871],[d8873,f8872],[d8873,f8873],[d8875,f8874],[d8875,f8875],[d8877,f8876],[d8877,f8877],[d8879,f8878],[d8879,f8879],[d8881,f8880],[d8881,f8881],[d8883,f8882],[d8883,f8883],[d8885,f8884],[d8885,f8885],[d8887,f8886],[d8887,f8887],[d8889,f8888],[d8889,f8889],[d8891,f8890],[d8891,f8891],[d8893,f8892],[d8893,f8893],[d8895,f8894],[d8895,f8895],[d8897,f8896],[d8897,f8897],[d8899,f8898],[d8899,f8899],[d8901,f8900],[d8901,f8901],[d8903,f8902],[d8903,f8903],[d8905,f8904],[d8905,f8905],[d8907,f8906],[d8907,f8907],[d8909,f8908],[d8909,f8909],[d8911,f8910],[d8911,f8911],[d8913,f8912],[d8913,f8913],[d8915,f8914],[d8915,f8915],[d8917,f8916],[d8917,f8917],[d8919,f8918],[d8919,f8919],[d8921,f8920],[d8921,f8921],[d8923,f8922],[d8923,f8923],[d8925,f8924],[d8925,f8925],[d8927,f8926],[d8927,f8927],[d8929,f8928],[d8929,f8929],[d8931,f8930],[d8931,f8931],[d8933,f8932],[d8933,f8933],[d8935,f8934],[d8935,f8935],[d8937,f8936],[d8937,f8937],[d8939,f8938],[d8939,f8939],[d8941,f8940],[d8941,f8941],[d8943,f8942],[d8943,f8943],[d8945,f8944],[d8945,f8945],[d8947,f8946],[d8947,f8947],[d8949,f8948],[d8949,f8949],[d8951,f8950],[d8951,f8951],[d8953,f8952],[d8953,f8953],[d8955,f8954],[d8955,f8955],[d8957,f8956],[d8957,f8957],[d8959,f8958],[d8959,f8959],[d8961,f8960],[d8961,f8961],[d8963,f8962],[d8963,f8963],[d8965,f8964],[d8965,f8965],[d8967,f8966],[d8967,f8967],[d8969,f8968],[d8969,f8969],[d8971,f8970],[d8971,f8971],[d8973,f8972],[d8973,f8973],[d8975,f8974],[d8975,f8975],[d8977,f8976],[d8977,f8977],[d8979,f8978],[d8979,f8979],[d8981,f8980],[d8981,f8981],[d8983,f8982],[d8983,f8983],[d8985,f8984],[d8985,f8985],[d8987,f8986],[d8987,f8987],[d8989,f8988],[d8989,f8989],[d8991,f8990],[d8991,f8991],[d8993,f8992],[d8993,f8993],[d8995,f8994],[d8995,f8995],[d8997,f8996],[d8997,f8997],[d8999,f8998],[d8999,f8999],[d9001,f9000],[d9001,f9001],[d9003,f9002],[d9003,f9003],[d9005,f9004],[d9005,f9005],[d9007,f9006],[d9007,f9007],[d9009,f9008],[d9009,f9009],[d9011,f9010],[d9011,f9011],[d9013,f9012],[d9013,f9013],[d9015,f9014],[d9015,f9015],[d9017,f9016],[d9017,f9017],[d9019,f9018],[d9019,f9019],[d9021,f9020],[d9021,f9021],[d9023,f9022],[d9023,f9023],[d9025,f9024],[d9025,f9025],[d9027,f9026],[d9027,f9027],[d9029,f9028],[d9029,f9029],[d9031,f9030],[d9031,f9031],[d9033,f9032],[d9033,f9033],[d9035,f9034],[d9035,f9035],[d9037,f9036],[d9037,f9037],[d9039,f9038],[d9039,f9039],[d9041,f9040],[d9041,f9041],[d9043,f9042],[d9043,f9043],[d9045,f9044],[d9045,f9045],[d9047,f9046],[d9047,f9047],[d9049,f9048],[d9049,f9049],[d9051,f9050],[d9051,f9051],[d9053,f9052],[d9053,f9053],[d9055,f9054],[d9055,f9055],[d9057,f9056],[d9057,f9057],[d9059,f9058],[d9059,f9059],[d9061,f9060],[d9061,f9061],[d9063,f9062],[d9063,f9063],[d9065,f9064],[d9065,f9065],[d9067,f9066],[d9067,f9067],[d9069,f9068],[d9069,f9069],[d9071,f9070],[d9071,f9071],[d9073,f9072],[d9073,f9073],[d9075,f9074],[d9075,f9075],[d9077,f9076],[d9077,f9077],[d9079,f9078],[d9079,f9079],[d9081,f9080],[d9081,f9081],[d9083,f9082],[d9083,f9083],[d9085,f9084],[d9085,f9085],[d9087,f9086],[d9087,f9087],[d9089,f9088],[d9089,f9089],[d9091,f9090],[d9091,f9091],[d9093,f9092],[d9093,f9093],[d9095,f9094],[d9095,f9095],[d9097,f9096],[d9097,f9097],[d9099,f9098],[d9099,f9099],[d9101,f9100],[d9101,f9101],[d9103,f9102],[d9103,f9103],[d9105,f9104],[d9105,f9105],[d9107,f9106],[d9107,f9107],[d9109,f9108],[d9109,f9109],[d9111,f9110],[d9111,f9111],[d9113,f9112],[d9113,f9113],[d9115,f9114],[d9115,f9115],[d9117,f9116],[d9117,f9117],[d9119,f9118],[d9119,f9119],[d9121,f9120],[d9121,f9121],[d9123,f9122],[d9123,f9123],[d9125,f9124],[d9125,f9125],[d9127,f9126],[d9127,f9127],[d9129,f9128],[d9129,f9129],[d9131,f9130],[d9131,f9131],[d9133,f9132],[d9133,f9133],[d9135,f9134],[d9135,f9135],[d9137,f9136],[d9137,f9137],[d9139,f9138],[d9139,f9139],[d9141,f9140],[d9141,f9141],[d9143,f9142],[d9143,f9143],[d9145,f9144],[d9145,f9145],[d9147,f9146],[d9147,f9147],[d9149,f9148],[d9149,f9149],[d9151,f9150],[d9151,f9151],[d9153,f9152],[d9153,f9153],[d9155,f9154],[d9155,f9155],[d9157,f9156],[d9157,f9157],[d9159,f9158],[d9159,f9159],[d9161,f9160],[d9161,f9161],[d9163,f9162],[d9163,f9163],[d9165,f9164],[d9165,f9165],[d9167,f9166],[d9167,f9167],[d9169,f9168],[d9169,f9169],[d9171,f9170],[d9171,f9171],[d9173,f9172],[d9173,f9173],[d9175,f9174],[d9175,f9175],[d9177,f9176],[d9177,f9177],[d9179,f9178],[d9179,f9179],[d9181,f9180],[d9181,f9181],[d9183,f9182],[d9183,f9183],[d9185,f9184],[d9185,f9185],[d9187,f9186],[d9187,f9187],[d9189,f9188],[d9189,f9189],[d9191,f9190],[d9191,f9191],[d9193,f9192],[d9193,f9193],[d9195,f9194],[d9195,f9195],[d9197,f9196],[d9197,f9197],[d9199,f9198],[d9199,f9199],[d9201,f9200],[d9201,f9201],[d9203,f9202],[d9203,f9203],[d9205,f9204],[d9205,f9205],[d9207,f9206],[d9207,f9207],[d9209,f9208],[d9209,f9209],[d9211,f9210],[d9211,f9211],[d9213,f9212],[d9213,f9213],[d9215,f9214],[d9215,f9215],[d9217,f9216],[d9217,f9217],[d9219,f9218],[d9219,f9219],[d9221,f9220],[d9221,f9221],[d9223,f9222],[d9223,f9223],[d9225,f9224],[d9225,f9225],[d9227,f9226],[d9227,f9227],[d9229,f9228],[d9229,f9229],[d9231,f9230],[d9231,f9231],[d9233,f9232],[d9233,f9233],[d9235,f9234],[d9235,f9235],[d9237,f9236],[d9237,f9237],[d9239,f9238],[d9239,f9239],[d9241,f9240],[d9241,f9241],[d9243,f9242],[d9243,f9243],[d9245,f9244],[d9245,f9245],[d9247,f9246],[d9247,f9247],[d9249,f9248],[d9249,f9249],[d9251,f9250],[d9251,f9251],[d9253,f9252],[d9253,f9253],[d9255,f9254],[d9255,f9255],[d9257,f9256],[d9257,f9257],[d9259,f9258],[d9259,f9259],[d9261,f9260],[d9261,f9261],[d9263,f9262],[d9263,f9263],[d9265,f9264],[d9265,f9265],[d9267,f9266],[d9267,f9267],[d9269,f9268],[d9269,f9269],[d9271,f9270],[d9271,f9271],[d9273,f9272],[d9273,f9273],[d9275,f9274],[d9275,f9275],[d9277,f9276],[d9277,f9277],[d9279,f9278],[d9279,f9279],[d9281,f9280],[d9281,f9281],[d9283,f9282],[d9283,f9283],[d9285,f9284],[d9285,f9285],[d9287,f9286],[d9287,f9287],[d9289,f9288],[d9289,f9289],[d9291,f9290],[d9291,f9291],[d9293,f9292],[d9293,f9293],[d9295,f9294],[d9295,f9295],[d9297,f9296],[d9297,f9297],[d9299,f9298],[d9299,f9299],[d9301,f9300],[d9301,f9301],[d9303,f9302],[d9303,f9303],[d9305,f9304],[d9305,f9305],[d9307,f9306],[d9307,f9307],[d9309,f9308],[d9309,f9309],[d9311,f9310],[d9311,f9311],[d9313,f9312],[d9313,f9313],[d9315,f9314],[d9315,f9315],[d9317,f9316],[d9317,f9317],[d9319,f9318],[d9319,f9319],[d9321,f9320],[d9321,f9321],[d9323,f9322],[d9323,f9323],[d9325,f9324],[d9325,f9325],[d9327,f9326],[d9327,f9327],[d9329,f9328],[d9329,f9329],[d9331,f9330],[d9331,f9331],[d9333,f9332],[d9333,f9333],[d9335,f9334],[d9335,f9335],[d9337,f9336],[d9337,f9337],[d9339,f9338],[d9339,f9339],[d9341,f9340],[d9341,f9341],[d9343,f9342],[d9343,f9343],[d9345,f9344],[d9345,f9345],[d9347,f9346],[d9347,f9347],[d9349,f9348],[d9349,f9349],[d9351,f9350],[d9351,f9351],[d9353,f9352],[d9353,f9353],[d9355,f9354],[d9355,f9355],[d9357,f9356],[d9357,f9357],[d9359,f9358],[d9359,f9359],[d9361,f9360],[d9361,f9361],[d9363,f9362],[d9363,f9363],[d9365,f9364],[d9365,f9365],[d9367,f9366],[d9367,f9367],[d9369,f9368],[d9369,f9369],[d9371,f9370],[d9371,f9371],[d9373,f9372],[d9373,f9373],[d9375,f9374],[d9375,f9375],[d9377,f9376],[d9377,f9377],[d9379,f9378],[d9379,f9379],[d9381,f9380],[d9381,f9381],[d9383,f9382],[d9383,f9383],[d9385,f9384],[d9385,f9385],[d9387,f9386],[d9387,f9387],[d9389,f9388],[d9389,f9389],[d9391,f9390],[d9391,f9391],[d9393,f9392],[d9393,f9393],[d9395,f9394],[d9395,f9395],[d9397,f9396],[d9397,f9397],[d9399,f9398],[d9399,f9399],[d9401,f9400],[d9401,f9401],[d9403,f9402],[d9403,f9403],[d9405,f9404],[d9405,f9405],[d9407,f9406],[d9407,f9407],[d9409,f9408],[d9409,f9409],[d9411,f9410],[d9411,f9411],[d9413,f9412],[d9413,f9413],[d9415,f9414],[d9415,f9415],[d9417,f9416],[d9417,f9417],[d9419,f9418],[d9419,f9419],[d9421,f9420],[d9421,f9421],[d9423,f9422],[d9423,f9423],[d9425,f9424],[d9425,f9425],[d9427,f9426],[d9427,f9427],[d9429,f9428],[d9429,f9429],[d9431,f9430],[d9431,f9431],[d9433,f9432],[d9433,f9433],[d9435,f9434],[d9435,f9435],[d9437,f9436],[d9437,f9437],[d9439,f9438],[d9439,f9439],[d9441,f9440],[d9441,f9441],[d9443,f9442],[d9443,f9443],[d9445,f9444],[d9445,f9445],[d9447,f9446],[d9447,f9447],[d9449,f9448],[d9449,f9449],[d9451,f9450],[d9451,f9451],[d9453,f9452],[d9453,f9453],[d9455,f9454],[d9455,f9455],[d9457,f9456],[d9457,f9457],[d9459,f9458],[d9459,f9459],[d9461,f9460],[d9461,f9461],[d9463,f9462],[d9463,f9463],[d9465,f9464],[d9465,f9465],[d9467,f9466],[d9467,f9467],[d9469,f9468],[d9469,f9469],[d9471,f9470],[d9471,f9471],[d9473,f9472],[d9473,f9473],[d9475,f9474],[d9475,f9475],[d9477,f9476],[d9477,f9477],[d9479,f9478],[d9479,f9479],[d9481,f9480],[d9481,f9481],[d9483,f9482],[d9483,f9483],[d9485,f9484],[d9485,f9485],[d9487,f9486],[d9487,f9487],[d9489,f9488],[d9489,f9489],[d9491,f9490],[d9491,f9491],[d9493,f9492],[d9493,f9493],[d9495,f9494],[d9495,f9495],[d9497,f9496],[d9497,f9497],[d9499,f9498],[d9499,f9499],[d9501,f9500],[d9501,f9501],[d9503,f9502],[d9503,f9503],[d9505,f9504],[d9505,f9505],[d9507,f9506],[d9507,f9507],[d9509,f9508],[d9509,f9509],[d9511,f9510],[d9511,f9511],[d9513,f9512],[d9513,f9513],[d9515,f9514],[d9515,f9515],[d9517,f9516],[d9517,f9517],[d9519,f9518],[d9519,f9519],[d9521,f9520],[d9521,f9521],[d9523,f9522],[d9523,f9523],[d9525,f9524],[d9525,f9525],[d9527,f9526],[d9527,f9527],[d9529,f9528],[d9529,f9529],[d9531,f9530],[d9531,f9531],[d9533,f9532],[d9533,f9533],[d9535,f9534],[d9535,f9535],[d9537,f9536],[d9537,f9537],[d9539,f9538],[d9539,f9539],[d9541,f9540],[d9541,f9541],[d9543,f9542],[d9543,f9543],[d9545,f9544],[d9545,f9545],[d9547,f9546],[d9547,f9547],[d9549,f9548],[d9549,f9549],[d9551,f9550],[d9551,f9551],[d9553,f9552],[d9553,f9553],[d9555,f9554],[d9555,f9555],[d9557,f9556],[d9557,f9557],[d9559,f9558],[d9559,f9559],[d9561,f9560],[d9561,f9561],[d9563,f9562],[d9563,f9563],[d9565,f9564],[d9565,f9565],[d9567,f9566],[d9567,f9567],[d9569,f9568],[d9569,f9569],[d9571,f9570],[d9571,f9571],[d9573,f9572],[d9573,f9573],[d9575,f9574],[d9575,f9575],[d9577,f9576],[d9577,f9577],[d9579,f9578],[d9579,f9579],[d9581,f9580],[d9581,f9581],[d9583,f9582],[d9583,f9583],[d9585,f9584],[d9585,f9585],[d9587,f9586],[d9587,f9587],[d9589,f9588],[d9589,f9589],[d9591,f9590],[d9591,f9591],[d9593,f9592],[d9593,f9593],[d9595,f9594],[d9595,f9595],[d9597,f9596],[d9597,f9597],[d9599,f9598],[d9599,f9599],[d9601,f9600],[d9601,f9601],[d9603,f9602],[d9603,f9603],[d9605,f9604],[d9605,f9605],[d9607,f9606],[d9607,f9607],[d9609,f9608],[d9609,f9609],[d9611,f9610],[d9611,f9611],[d9613,f9612],[d9613,f9613],[d9615,f9614],[d9615,f9615],[d9617,f9616],[d9617,f9617],[d9619,f9618],[d9619,f9619],[d9621,f9620],[d9621,f9621],[d9623,f9622],[d9623,f9623],[d9625,f9624],[d9625,f9625],[d9627,f9626],[d9627,f9627],[d9629,f9628],[d9629,f9629],[d9631,f9630],[d9631,f9631],[d9633,f9632],[d9633,f9633],[d9635,f9634],[d9635,f9635],[d9637,f9636],[d9637,f9637],[d9639,f9638],[d9639,f9639],[d9641,f9640],[d9641,f9641],[d9643,f9642],[d9643,f9643],[d9645,f9644],[d9645,f9645],[d9647,f9646],[d9647,f9647],[d9649,f9648],[d9649,f9649],[d9651,f9650],[d9651,f9651],[d9653,f9652],[d9653,f9653],[d9655,f9654],[d9655,f9655],[d9657,f9656],[d9657,f9657],[d9659,f9658],[d9659,f9659],[d9661,f9660],[d9661,f9661],[d9663,f9662],[d9663,f9663],[d9665,f9664],[d9665,f9665],[d9667,f9666],[d9667,f9667],[d9669,f9668],[d9669,f9669],[d9671,f9670],[d9671,f9671],[d9673,f9672],[d9673,f9673],[d9675,f9674],[d9675,f9675],[d9677,f9676],[d9677,f9677],[d9679,f9678],[d9679,f9679],[d9681,f9680],[d9681,f9681],[d9683,f9682],[d9683,f9683],[d9685,f9684],[d9685,f9685],[d9687,f9686],[d9687,f9687],[d9689,f9688],[d9689,f9689],[d9691,f9690],[d9691,f9691],[d9693,f9692],[d9693,f9693],[d9695,f9694],[d9695,f9695],[d9697,f9696],[d9697,f9697],[d9699,f9698],[d9699,f9699],[d9701,f9700],[d9701,f9701],[d9703,f9702],[d9703,f9703],[d9705,f9704],[d9705,f9705],[d9707,f9706],[d9707,f9707],[d9709,f9708],[d9709,f9709],[d9711,f9710],[d9711,f9711],[d9713,f9712],[d9713,f9713],[d9715,f9714],[d9715,f9715],[d9717,f9716],[d9717,f9717],[d9719,f9718],[d9719,f9719],[d9721,f9720],[d9721,f9721],[d9723,f9722],[d9723,f9723],[d9725,f9724],[d9725,f9725],[d9727,f9726],[d9727,f9727],[d9729,f9728],[d9729,f9729],[d9731,f9730],[d9731,f9731],[d9733,f9732],[d9733,f9733],[d9735,f9734],[d9735,f9735],[d9737,f9736],[d9737,f9737],[d9739,f9738],[d9739,f9739],[d9741,f9740],[d9741,f9741],[d9743,f9742],[d9743,f9743],[d9745,f9744],[d9745,f9745],[d9747,f9746],[d9747,f9747],[d9749,f9748],[d9749,f9749],[d9751,f9750],[d9751,f9751],[d9753,f9752],[d9753,f9753],[d9755,f9754],[d9755,f9755],[d9757,f9756],[d9757,f9757],[d9759,f9758],[d9759,f9759],[d9761,f9760],[d9761,f9761],[d9763,f9762],[d9763,f9763],[d9765,f9764],[d9765,f9765],[d9767,f9766],[d9767,f9767],[d9769,f9768],[d9769,f9769],[d9771,f9770],[d9771,f9771],[d9773,f9772],[d9773,f9773],[d9775,f9774],[d9775,f9775],[d9777,f9776],[d9777,f9777],[d9779,f9778],[d9779,f9779],[d9781,f9780],[d9781,f9781],[d9783,f9782],[d9783,f9783],[d9785,f9784],[d9785,f9785],[d9787,f9786],[d9787,f9787],[d9789,f9788],[d9789,f9789],[d9791,f9790],[d9791,f9791],[d9793,f9792],[d9793,f9793],[d9795,f9794],[d9795,f9795],[d9797,f9796],[d9797,f9797],[d9799,f9798],[d9799,f9799],[d9801,f9800],[d9801,f9801],[d9803,f9802],[d9803,f9803],[d9805,f9804],[d9805,f9805],[d9807,f9806],[d9807,f9807],[d9809,f9808],[d9809,f9809],[d9811,f9810],[d9811,f9811],[d9813,f9812],[d9813,f9813],[d9815,f9814],[d9815,f9815],[d9817,f9816],[d9817,f9817],[d9819,f9818],[d9819,f9819],[d9821,f9820],[d9821,f9821],[d9823,f9822],[d9823,f9823],[d9825,f9824],[d9825,f9825],[d9827,f9826],[d9827,f9827],[d9829,f9828],[d9829,f9829],[d9831,f9830],[d9831,f9831],[d9833,f9832],[d9833,f9833],[d9835,f9834],[d9835,f9835],[d9837,f9836],[d9837,f9837],[d9839,f9838],[d9839,f9839],[d9841,f9840],[d9841,f9841],[d9843,f9842],[d9843,f9843],[d9845,f9844],[d9845,f9845],[d9847,f9846],[d9847,f9847],[d9849,f9848],[d9849,f9849],[d9851,f9850],[d9851,f9851],[d9853,f9852],[d9853,f9853],[d9855,f9854],[d9855,f9855],[d9857,f9856],[d9857,f9857],[d9859,f9858],[d9859,f9859],[d9861,f9860],[d9861,f9861],[d9863,f9862],[d9863,f9863],[d9865,f9864],[d9865,f9865],[d9867,f9866],[d9867,f9867],[d9869,f9868],[d9869,f9869],[d9871,f9870],[d9871,f9871],[d9873,f9872],[d9873,f9873],[d9875,f9874],[d9875,f9875],[d9877,f9876],[d9877,f9877],[d9879,f9878],[d9879,f9879],[d9881,f9880],[d9881,f9881],[d9883,f9882],[d9883,f9883],[d9885,f9884],[d9885,f9885],[d9887,f9886],[d9887,f9887],[d9889,f9888],[d9889,f9889],[d9891,f9890],[d9891,f9891],[d9893,f9892],[d9893,f9893],[d9895,f9894],[d9895,f9895],[d9897,f9896],[d9897,f9897],[d9899,f9898],[d9899,f9899],[d9901,f9900],[d9901,f9901],[d9903,f9902],[d9903,f9903],[d9905,f9904],[d9905,f9905],[d9907,f9906],[d9907,f9907],[d9909,f9908],[d9909,f9909],[d9911,f9910],[d9911,f9911],[d9913,f9912],[d9913,f9913],[d9915,f9914],[d9915,f9915],[d9917,f9916],[d9917,f9917],[d9919,f9918],[d9919,f9919],[d9921,f9920],[d9921,f9921],[d9923,f9922],[d9923,f9923],[d9925,f9924],[d9925,f9925],[d9927,f9926],[d9927,f9927],[d9929,f9928],[d9929,f9929],[d9931,f9930],[d9931,f9931],[d9933,f9932],[d9933,f9933],[d9935,f9934],[d9935,f9935],[d9937,f9936],[d9937,f9937],[d9939,f9938],[d9939,f9939],[d9941,f9940],[d9941,f9941],[d9943,f9942],[d9943,f9943],[d9945,f9944],[d9945,f9945],[d9947,f9946],[d9947,f9947],[d9949,f9948],[d9949,f9949],[d9951,f9950],[d9951,f9951],[d9953,f9952],[d9953,f9953],[d9955,f9954],[d9955,f9955],[d9957,f9956],[d9957,f9957],[d9959,f9958],[d9959,f9959],[d9961,f9960],[d9961,f9961],[d9963,f9962],[d9963,f9963],[d9965,f9964],[d9965,f9965],[d9967,f9966],[d9967,f9967],[d9969,f9968],[d9969,f9969],[d9971,f9970],[d9971,f9971],[d9973,f9972],[d9973,f9973],[d9975,f9974],[d9975,f9975],[d9977,f9976],[d9977,f9977],[d9979,f9978],[d9979,f9979],[d9981,f9980],[d9981,f9981],[d9983,f9982],[d9983,f9983],[d9985,f9984],[d9985,f9985],[d9987,f9986],[d9987,f9987],[d9989,f9988],[d9989,f9989],[d9991,f9990],[d9991,f9991],[d9993,f9992],[d9993,f9993],[d9995,f9994],[d9995,f9995],[d9997,f9996],[d9997,f9997],[d9998,f9998] ] ] + + +contents in Dir -> (Dir + File) +all d:Dir | not (d in d.^contents) +Root in Dir +(File + Dir) in Root.*contents \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/List.kodkod b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/List.kodkod new file mode 100644 index 00000000..3303616e --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/List.kodkod @@ -0,0 +1,30 @@ +[Thing0, Thing1, Thing2, List0, List1, List2] + +Thing: [[[Thing2]]] +List:[[[List0], [List1]]] +EmptyList:[[[List0]]] +NonEmptyList:[[[List1], [List2]]] +car:[[[List1, Thing2], [List2, Thing2]]] +cdr:[[[List1, List0], [List2, List1]]] +equivTo:[[[List0, List0], [List1, List1], [List2, List2]]] +prefixes:[[[List0, List0], [List0, List2], [List1, List0], [List1, List1], [List2, List0], [List2, List1], [List2, List2]]] + +List = (EmptyList + NonEmptyList) +no (EmptyList & NonEmptyList) +equivTo in (List -> List) +prefixes in (List -> List) + +function[car: NonEmptyList -> one Thing] +function[cdr: NonEmptyList -> one List] + +Thing in (List . car) + +all L: List | some (EmptyList & (L . *cdr)) +all a: List, b: List | a in (b.equivTo) <=> ((a . car) = (b . car) && (b . cdr) in ((a . cdr) . equivTo)) + +(List -> EmptyList) in prefixes + +--all a: NonEmptyList, b: NonEmptyList | a in (b . prefixes) <=> ((a . car) = (b . car) && (a . cdr) in ((b . cdr) . prefixes)) + +--some a: NonEmptyList, b: NonEmptyList | !(a = b) && b in (a . prefixes) + diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/PigeonHole b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/PigeonHole new file mode 100644 index 00000000..2866c5a1 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/PigeonHole @@ -0,0 +1,17 @@ +{Pigeon0, Pigeon1, Pigeon2, Pigeon3, Hole0, Hole1, Hole2, Hole3} + +Pigeon: [[[Pigeon0], [Pigeon1], [Pigeon2], [Pigeon3]]] +Hole: [[[Hole0], [Hole1], [Hole2], [Hole3]]] +hole: [[], [[Pigeon0, Hole0], [Pigeon0, Hole1], [Pigeon0, Hole2], [Pigeon0, Hole3], [Pigeon1, Hole0], [Pigeon1, Hole1], [Pigeon1, Hole2], [Pigeon1, Hole3], [Pigeon2, Hole0], [Pigeon2, Hole1], [Pigeon2, Hole2], [Pigeon2, Hole3], [Pigeon3, Hole0], [Pigeon3, Hole1], [Pigeon3, Hole2], [Pigeon3, Hole3]]] + +function[hole: Pigeon -> one Hole] + +-- all p1, p2: Pigeon , h1, h2: Hole | !(p1 = p2) => not (p1.hole = p2.hole) + +-- all disj p1, p2, x1: Pigeon | not (p1.hole = p2.hole) + +-- all disj p1, p2: Pigeon, disj h1, h2: Hole | not (p1.hole = p2.hole) + +-- all disj x1, x2: Pigeon, disj h1, h2: Hole | not (x1.hole = x2.hole) + +no disj p1, p2: Pigeon | p1.hole = p2.hole diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/PigeonHole3 b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/PigeonHole3 new file mode 100644 index 00000000..2866c5a1 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/PigeonHole3 @@ -0,0 +1,17 @@ +{Pigeon0, Pigeon1, Pigeon2, Pigeon3, Hole0, Hole1, Hole2, Hole3} + +Pigeon: [[[Pigeon0], [Pigeon1], [Pigeon2], [Pigeon3]]] +Hole: [[[Hole0], [Hole1], [Hole2], [Hole3]]] +hole: [[], [[Pigeon0, Hole0], [Pigeon0, Hole1], [Pigeon0, Hole2], [Pigeon0, Hole3], [Pigeon1, Hole0], [Pigeon1, Hole1], [Pigeon1, Hole2], [Pigeon1, Hole3], [Pigeon2, Hole0], [Pigeon2, Hole1], [Pigeon2, Hole2], [Pigeon2, Hole3], [Pigeon3, Hole0], [Pigeon3, Hole1], [Pigeon3, Hole2], [Pigeon3, Hole3]]] + +function[hole: Pigeon -> one Hole] + +-- all p1, p2: Pigeon , h1, h2: Hole | !(p1 = p2) => not (p1.hole = p2.hole) + +-- all disj p1, p2, x1: Pigeon | not (p1.hole = p2.hole) + +-- all disj p1, p2: Pigeon, disj h1, h2: Hole | not (p1.hole = p2.hole) + +-- all disj x1, x2: Pigeon, disj h1, h2: Hole | not (x1.hole = x2.hole) + +no disj p1, p2: Pigeon | p1.hole = p2.hole diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/RingElection.kodkod b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/RingElection.kodkod new file mode 100644 index 00000000..6baab683 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/RingElection.kodkod @@ -0,0 +1,101 @@ +[Process0, Process1, Process2, Time0, Time1, Time2, Time3] + +Process: [[], [[Process0], [Process1], [Process3]]] +succ: [[], [[Process0, Process0], [Process0, Process1], [Process0, Process2], [Process1, Process0], [Process1, Process1], [Process1, Process2], [Process2, Process0], [Process2, Process1], [Process2, Process2]]] +toSend: [[], [[Process0, Process0, Time0], [Process0, Process0, Time1], [Process0, Process0, Time2], [Process0, Process0, Time3], [Process0, Process1, Time0], [Process0, Process1, Time1], [Process0, Process1, Time2], [Process0, Process1, Time3], [Process0, Process2, Time0], [Process0, Process2, Time1], [Process0, Process2, Time2], [Process0, Process2, Time3], [Process1, Process0, Time0], [Process1, Process0, Time1], [Process1, Process0, Time2], [Process1, Process0, Time3], [Process1, Process1, Time0], [Process1, Process1, Time1], [Process1, Process1, Time2], [Process1, Process1, Time3], [Process1, Process2, Time0], [Process1, Process2, Time1], [Process1, Process2, Time2], [Process1, Process2, Time3], [Process2, Process0, Time0], [Process2, Process0, Time1], [Process2, Process0, Time2], [Process2, Process0, Time3], [Process2, Process1, Time0], [Process2, Process1, Time1], [Process2, Process1, Time2], [Process2, Process1, Time3], [Process2, Process2, Time0], [Process2, Process2, Time1], [Process2, Process2, Time2], [Process2, Process2, Time3]]] +elected: [[], [[Process0, Time0], [Process0, Time1], [Process0, Time2], [Process0, Time3], [Process1, Time0], [Process1, Time1], [Process1, Time2], [Process1, Time3], [Process2, Time0], [Process2, Time1], [Process2, Time2], [Process2, Time3]]] +pord: [[], [[Process0, Process0], [Process0, Process1], [Process0, Process2], [Process1, Process0], [Process1, Process1], [Process1, Process2], [Process2, Process0], [Process2, Process1], [Process2, Process2]]] +pfirst: [[], [[Process0], [Process1], [Process2]]] +plast: [[], [[Process0], [Process1], [Process2]]] +Time: [[], [[Time0], [Time1], [Time2], [Time3]]] +tord: [[], [[Time0, Time0], [Time0, Time1], [Time0, Time2], [Time0, Time3], [Time1, Time0], [Time1, Time1], [Time1, Time2], [Time1, Time3], [Time2, Time0], [Time2, Time1], [Time2, Time2], [Time2, Time3], [Time3, Time0], [Time3, Time1], [Time3, Time2], [Time3, Time3]]] +tfirst: [[], [[Time0], [Time1], [Time2], [Time3]]] +tlast: [[], [[Time0], [Time1], [Time2], [Time3]]] +next: [[], []] + +/** +open util/ordering[Time] as TO +open util/ordering[Process] as PO +**/ +ord[tord, Time, tfirst, tlast] && +ord[pord, Process, pfirst, plast] && +/** +sig Time {} +sig Process { + succ: Process, + toSend: Process -> Time, + elected: set Time + } +**/ +function[succ: Process -> one Process] +elected in (Process -> Time) + +/** +fact ring {all p: Process | Process in p.^succ} +**/ +all p: Process | Process in (p . ^succ) + +/** +fact defineElected { + no elected.first + all t: Time-first | elected.t = {p: Process | p in p.toSend.t - p.toSend.(t.prev)} + } +**/ +no (elected . tfirst) +all t: Time - tfirst | elected.t = {p: Process | p in p.toSend.t - p.toSend.(t.~tord)} +/** + +pred init [t: Time] { + all p: Process | p.toSend.t = p + } + +pred step [t, t': Time, p: Process] { + let from = p.toSend, to = p.succ.toSend | + some id: from.t { + from.t' = from.t - id + to.t' = to.t + (id - p.succ.prevs) + } + } + +pred skip [t, t': Time, p: Process] { + p.toSend.t = p.toSend.t' + } + +fact traces { + init [first] + all t: Time-last | + let t' = t.next | + all p: Process | + step [t, t', p] or step [t, t', succ.p] or skip [t, t', p] + } +**/ +all p: Process | p.toSend.tfirst = p +all t: Time - tlast | all p: Process | + (some id: (p . toSend) . t | + ((p . toSend) . (t . tord)) = (((p . toSend) . t) - id) && + (((p . succ) . toSend) . (t . tord)) = ((((p . succ) . toSend) . t) + (id - + ((p . succ) . ^~pord)))) || + (some id: ((succ . p) . toSend) . t | + (((succ . p) . toSend) . (t . tord)) = ((((succ . p) . toSend) . t) - id) + && + ((((succ . p) . succ) . toSend) . (t . tord)) = (((((succ . p) . succ) . + toSend) . t) + (id - (((succ . p) . succ) . ^~pord)))) || + ((p . toSend) . t) = ((p . toSend) . (t . tord)) + +/** +pred show { some elected } +**/ +some elected + +/** + all t: Time-tlast | + let t' = t.next | + all p: Process | t'.toSend = p.toSend.t.k +**/ + +/** +*****check AtMostOneElected for 3 Process, 4 Time***** +---INSTANCE--- +relations: {Process=[[Process0], [Process1], [Process2]], succ=[[Process0, Process1], [Process1, Process2], [Process2, Process0]], toSend=[[Process0, Process0, Time0], [Process0, Process0, Time1], [Process0, Process0, Time2], [Process0, Process0, Time3], [Process0, Process2, Time1], [Process1, Process1, Time0], [Process1, Process1, Time1], [Process1, Process1, Time2], [Process1, Process1, Time3], [Process1, Process2, Time2], [Process2, Process2, Time0], [Process2, Process2, Time3]], elected=[[Process2, Time3]], pord=[[Process0, Process1], [Process1, Process2]], pfirst=[[Process0]], plast=[[Process2]], Time=[[Time0], [Time1], [Time2], [Time3]], tord=[[Time0, Time1], [Time1, Time2], [Time2, Time3]], tfirst=[[Time0]], tlast=[[Time3]]} +ints: [] +**/ \ No newline at end of file diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/ToyFilesystem.kodkod b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/ToyFilesystem.kodkod new file mode 100644 index 00000000..af620315 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/ToyFilesystem.kodkod @@ -0,0 +1,11 @@ +{d0, d1, f0, f1, f2} + +Root: [{(d0)}] +Dir: [ {(d0), (d1)}] +File: [{(f0), (f1), (f2)}] +contents : [[[d0, d1], [d0, f2], [d1, f0], [d1, f1]]] + +contents in Dir -> (Dir + File) +all d: Dir | !(d in d.^contents) +Root in Dir +(File + Dir) in Root.*contents diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/isFunction b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/isFunction new file mode 100644 index 00000000..15e31973 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/isFunction @@ -0,0 +1,12 @@ +{Domain0, Domain1, Domain2, Domain3, Range0, Range1, Range2, Range3} + +Domain: [[[Domain0], [Domain1], [Domain2], [Domain3]]] +Range: [[[Range0], [Range1], [Range2], [Range3]]] +func: [ [[Domain0, Range3], [Domain1, Range2], [Domain2, Range1], [Domain3, Range0]] ] + +-func: [ {} , {[Domain0, Range0], [Domain0, Range1], [Domain0, Range2], [Domain0, Range2], [Domain0, Range3], [Domain1, Range0], [Domain1, Range1], [Domain1, Range2], [Domain1, Range3], [Domain2, Range0], [Domain2, Range1], [Domain2, Range2], [Domain2, Range3], [Domain3, Range0], [Domain3, Range1], [Domain3, Range2], [Domain3, Range3]}] + +--function[hole: Domain -> one Range] + +all disj a1, a2 :Domain | a1.func != a2.func +all a: Domain | one a.func diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/isfunction.als b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/isfunction.als new file mode 100644 index 00000000..2fc1dbde --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/isfunction.als @@ -0,0 +1,15 @@ +model test/crocopat + +sig Domain { + function: set Range, +} + +sig Range {} + +pred isFunction { + all disj a1, a2 :Domain | a1.function != a2.function + all d : Domain | one d.function + all r : Range | one r.~function +} + +run isFunction for exactly 4 Domain, exactly 4 Range diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/myaddressbook.als b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/myaddressbook.als new file mode 100644 index 00000000..dbd0b11c --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/myaddressbook.als @@ -0,0 +1,40 @@ +model appendixA/addressBook2 + +sig Addr, Name { } + +sig Book { + addr: Name -> (Name + Addr) + } + +/* + +---------------- +x: m e + +---------------- +r: A m -> n B +all a: A | n a.r +all b: B | m r.b + +---------------- +r: A -> (B m -> n C) +all a: A | a.r in B m -> n C + +---------------- +r: (A m -> n B) -> C +all c: C | r.c in A m -> n B +---------------- + +*/ + +--addr: Book -> (Name lone -> Addr) +pred show1 { + all b: Book | b.addr in Name lone -> Addr +} + +//r: (A m -> n B) -> C +pred show2 { + all b: Book | b.addr in Name lone -> Addr +} + +run show1 for 3 diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/pigeonhole.als b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/pigeonhole.als new file mode 100644 index 00000000..95fec987 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/pigeonhole.als @@ -0,0 +1,16 @@ +sig Pigeon { hole: Hole } + +sig Hole {} + +fact {no disj p1, p2: Pigeon | p1.hole = p2.hole} + +pred aPigeonPerHole() { + // holes are not shared + -- all p1, p2: Pigeon | p1 != p2 implies p1.hole != p2.hole + -- all p1, p2: Pigeon, h1, h2: Hole | p1 != p2 => p1.hole != p2.hole + -- no disj p1, p2: Pigeon | p1.hole = p2.hole + + +} + +run aPigeonPerHole for exactly 4 Pigeon, exactly 4 Hole diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/tougnut.als b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/tougnut.als new file mode 100644 index 00000000..1ab02e61 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/kodkod/tougnut.als @@ -0,0 +1,20 @@ +model internal/tougnut + +open util/ordering[Cell] + +sig Cell { covered: Cell -> Cell -> Cell } + +pred covering() { + // opposite corners not on the board + let board = Cell->Cell - (first->first + last->last) | covered in board->board + + // covering relation is symmetric + all x,y: Cell | y.(x.covered)->x->y in covered + + // each pair of cells on the board should be covered + // by a domino, which also covers ONE of its neighbors + all x,y: Cell | one y.(x.covered) && y.(x.covered) in (prev[x]+next[x])->y + x->(prev[y] + next[y]) + +} + +run covering for 10 diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/out/Generics1.ecore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/out/Generics1.ecore new file mode 100644 index 00000000..b6eb4c81 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/out/Generics1.ecore @@ -0,0 +1,132 @@ + + + +
+
+
+ + +
+ + +
+ + +
+ + +
+ + + +
+
+
+ + +
+
+
+ + + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/out/My.ecore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/out/My.ecore new file mode 100644 index 00000000..8200983d --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/out/My.ecore @@ -0,0 +1,30 @@ + + + +
+ + +
+ + +
+ + +
+ + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/out/bookstore.ecore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/out/bookstore.ecore new file mode 100644 index 00000000..93dc47a1 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/out/bookstore.ecore @@ -0,0 +1,38 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/out/test1.ecore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/out/test1.ecore new file mode 100644 index 00000000..368df068 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/out/test1.ecore @@ -0,0 +1,94 @@ + + + +
+ + +
+ + +
+ + +
+ + + +
+ + + + + + + + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.alloyinecore/target/test-classes/out/yunus.ecore b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/out/yunus.ecore new file mode 100644 index 00000000..3593acb9 --- /dev/null +++ b/Source/eu.modelwriter.core.alloyinecore/target/test-classes/out/yunus.ecore @@ -0,0 +1,103 @@ + + + +
+ + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.svgutil/.classpath b/Source/eu.modelwriter.core.svgutil/.classpath new file mode 100644 index 00000000..fc012b4a --- /dev/null +++ b/Source/eu.modelwriter.core.svgutil/.classpath @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.core.svgutil/.gitignore b/Source/eu.modelwriter.core.svgutil/.gitignore new file mode 100644 index 00000000..ae3c1726 --- /dev/null +++ b/Source/eu.modelwriter.core.svgutil/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/Source/eu.modelwriter.core.svgutil/.project b/Source/eu.modelwriter.core.svgutil/.project new file mode 100644 index 00000000..6b5dd94a --- /dev/null +++ b/Source/eu.modelwriter.core.svgutil/.project @@ -0,0 +1,17 @@ + + + eu.modelwriter.core.svgutil + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/Source/eu.modelwriter.core.svgutil/.settings/org.eclipse.jdt.core.prefs b/Source/eu.modelwriter.core.svgutil/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..3a215370 --- /dev/null +++ b/Source/eu.modelwriter.core.svgutil/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/Source/eu.modelwriter.core.svgutil/lib/LICENSE.dom-documentation.txt b/Source/eu.modelwriter.core.svgutil/lib/LICENSE.dom-documentation.txt new file mode 100644 index 00000000..966651b3 --- /dev/null +++ b/Source/eu.modelwriter.core.svgutil/lib/LICENSE.dom-documentation.txt @@ -0,0 +1,86 @@ +xml-commons/java/external/LICENSE.dom-documentation.txt $Id: LICENSE.dom-documentation.txt 201084 2002-12-09 16:15:21Z vhardy $ + + +This license came from: http://www.w3.org/Consortium/Legal/copyright-documents-19990405 + + +W3C DOCUMENT NOTICE AND LICENSE +Copyright 1994-2001 World +Wide Web Consortium, World +Wide Web Consortium, (Massachusetts Institute of +Technology, Institut National de +Recherche en Informatique et en Automatique, Keio University). All Rights Reserved. +http://www.w3.org/Consortium/Legal/ + +Public documents on the W3C site are provided by the copyright +holders under the following license. The software or Document Type +Definitions (DTDs) associated with W3C specifications are governed +by the Software Notice. By using and/or copying this document, or the +W3C document from which this statement is linked, you (the +licensee) agree that you have read, understood, and will comply +with the following terms and conditions: + +Permission to use, copy, and distribute the contents of this +document, or the W3C document from which this statement is linked, +in any medium for any purpose and without fee or royalty is hereby +granted, provided that you include the following on ALL +copies of the document, or portions thereof, that you use: + +A link or URL to the original W3C document. + +The pre-existing copyright notice of the original author, or if +it doesn't exist, a notice of the form: "Copyright [$date-of-document] World Wide Web +Consortium, (Massachusetts +Institute of Technology, Institut National de Recherche en Informatique et en +Automatique, Keio +University). All Rights Reserved. +http://www.w3.org/Consortium/Legal/" (Hypertext is preferred, but a +textual representation is permitted.) + +If it exists, the STATUS of the W3C document. + +When space permits, inclusion of the full text of this NOTICE +should be provided. We request that authorship +attribution be provided in any software, documents, or other items +or products that you create pursuant to the implementation of the +contents of this document, or any portion thereof. + +No right to create modifications or derivatives of W3C documents +is granted pursuant to this license. However, if additional +requirements (documented in the Copyright +FAQ) are satisfied, the right to create modifications or +derivatives issometimes granted by the W3C to individuals +complying with those requirements. + +THIS DOCUMENT IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO +REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT +NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS +OF THE DOCUMENT ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE +IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY +PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. +COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, +SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE +DOCUMENT OR THE PERFORMANCE OR IMPLEMENTATION OF THE CONTENTS +THEREOF. + +The name and trademarks of copyright holders may NOT be used in +advertising or publicity pertaining to this document or its +contents without specific, written prior permission. Title to +copyright in this document will at all times remain with copyright +holders. + +---------------------------------------------------------------------------- +This formulation of W3C's notice and license became active on +April 05 1999 so as to account for the treatment of DTDs, schema's and +bindings. See the older formulation for the policy prior to this date. +Please see +our Copyright FAQ for common questions +about using materials from our site, including specific terms and +conditions for packages like libwww, Amaya, and Jigsaw. +Other questions about this notice can be directed to site-policy@w3.org. + +webmaster +(last updated by reagle on 1999/04/99.) \ No newline at end of file diff --git a/Source/eu.modelwriter.core.svgutil/lib/LICENSE.dom-software.txt b/Source/eu.modelwriter.core.svgutil/lib/LICENSE.dom-software.txt new file mode 100644 index 00000000..a50b37c3 --- /dev/null +++ b/Source/eu.modelwriter.core.svgutil/lib/LICENSE.dom-software.txt @@ -0,0 +1,74 @@ +xml-commons/java/external/LICENSE.dom-software.txt $Id: LICENSE.dom-software.txt 201084 2002-12-09 16:15:21Z vhardy $ + + +This license came from: http://www.w3.org/Consortium/Legal/copyright-software-19980720 + + +W3C SOFTWARE NOTICE AND LICENSE +Copyright 1994-2001 World +Wide Web Consortium, World +Wide Web Consortium, (Massachusetts Institute of +Technology, Institut National de +Recherche en Informatique et en Automatique, Keio University). All Rights Reserved. +http://www.w3.org/Consortium/Legal/ + +This W3C work (including software, documents, or other related +items) is being provided by the copyright holders under the +following license. By obtaining, using and/or copying this work, +you (the licensee) agree that you have read, understood, and will +comply with the following terms and conditions: +Permission to use, copy, modify, and distribute this software +and its documentation, with or without modification, for any +purpose and without fee or royalty is hereby granted, provided that +you include the following on ALL copies of the software and +documentation or portions thereof, including modifications, that +you make: + +The full text of this NOTICE in a location viewable to users of +the redistributed or derivative work. + +Any pre-existing intellectual property disclaimers, notices, or +terms and conditions. If none exist, a short notice of the +following form (hypertext is preferred, text is permitted) should +be used within the body of any redistributed or derivative code: +"Copyright [$date-of-software] World Wide Web Consortium, (Massachusetts Institute of +Technology, Institut National de +Recherche en Informatique et en Automatique, Keio University). All Rights Reserved. +http://www.w3.org/Consortium/Legal/" + +Notice of any changes or modifications to the W3C files, +including the date changes were made. (We recommend you provide +URIs to the location from which the code is derived.) + +THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND +COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF +MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE +USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD +PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. +COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, +SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE +SOFTWARE OR DOCUMENTATION. + +The name and trademarks of copyright holders may NOT be used in +advertising or publicity pertaining to the software without +specific, written prior permission. Title to copyright in this +software and any associated documentation will at all times remain +with copyright holders. +____________________________________ +This formulation of W3C's notice and license became active on +August 14 1998 so as to improve compatibility with GPL. This +version ensures that W3C software licensing terms are no more +restrictive than GPL and consequently W3C software may be +distributed in GPL packages. See the older formulation for the +policy prior to this date. Please see our Copyright FAQ for common +questions about using materials from +our site, including specific terms and conditions for packages like +libwww, Amaya, and Jigsaw. +Other questions about this notice can be +directed to site-policy@w3.org. + +webmaster +(last updated $Date: 2002-12-09 17:15:21 +0100 (Mon, 09 Dec 2002) $) \ No newline at end of file diff --git a/Source/eu.modelwriter.core.svgutil/lib/LICENSE.fop-transcoder-allinone-1.1.txt b/Source/eu.modelwriter.core.svgutil/lib/LICENSE.fop-transcoder-allinone-1.1.txt new file mode 100644 index 00000000..5bbb4fe3 --- /dev/null +++ b/Source/eu.modelwriter.core.svgutil/lib/LICENSE.fop-transcoder-allinone-1.1.txt @@ -0,0 +1,2 @@ +The fop-transcoder-allinone-1.1.jar file is licensed under the Apache License 2.0, which +can be found in the distribution root directory in the LICENSE file. diff --git a/Source/eu.modelwriter.core.svgutil/lib/LICENSE.js.txt b/Source/eu.modelwriter.core.svgutil/lib/LICENSE.js.txt new file mode 100644 index 00000000..817c87bc --- /dev/null +++ b/Source/eu.modelwriter.core.svgutil/lib/LICENSE.js.txt @@ -0,0 +1,890 @@ +This distribution includes a binary distribution of Mozilla Rhino 1.6 release 5 +plus one patch. + +You can get the unpatched 1.6R5 release of Rhino from the following URL: + + ftp://ftp.mozilla.org/pub/mozilla.org/js/rhino1_6R5.zip + +To obtain the source code for the 1.6R5 release of Rhino, issue the following +commands: + + cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot \ + co -D2006-11-20 mozilla/js/rhino + +The patch is available here: + + https://bugzilla.mozilla.org/attachment.cgi?id=288467 + +which is attached to this bug: + + https://bugzilla.mozilla.org/show_bug.cgi?id=367627 + +Rhino is licensed under both the MPL (Mozilla Public License) 1.1 and the +GPL (GNU General Public License) 2.0, which are duplicated below. + +The Rhino jar also includes four classes: + org.mozilla.javascript.tools.debugger.downloaded.AbstractCellEditor.java + org.mozilla.javascript.tools.debugger.downloaded.JTreeTable.java + org.mozilla.javascript.tools.debugger.downloaded.TreeTableModel.java + org.mozilla.javascript.tools.debugger.downloaded.TreeTableModelAdapter.java +Which come from: + http://java.sun.com/products/jfc/tsc/articles/treetable2 + +Under the following license: + +Code sample +License +Copyright 1994-2006 Sun Microsystems, Inc. All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + + * Redistribution of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistribution in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + +Neither the name of Sun Microsystems, Inc. or the names of +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +This software is provided "AS IS," without a warranty of any kind. ALL +EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, +INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN +MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR +ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR +DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR +ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR +DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE +DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, +ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF +SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +You acknowledge that this software is not designed, licensed or +intended for use in the design, construction, operation or maintenance +of any nuclear facility. + + + +============================================================================== + + MOZILLA PUBLIC LICENSE + Version 1.1 + + --------------- + +1. Definitions. + + 1.0.1. "Commercial Use" means distribution or otherwise making the + Covered Code available to a third party. + + 1.1. "Contributor" means each entity that creates or contributes to + the creation of Modifications. + + 1.2. "Contributor Version" means the combination of the Original + Code, prior Modifications used by a Contributor, and the Modifications + made by that particular Contributor. + + 1.3. "Covered Code" means the Original Code or Modifications or the + combination of the Original Code and Modifications, in each case + including portions thereof. + + 1.4. "Electronic Distribution Mechanism" means a mechanism generally + accepted in the software development community for the electronic + transfer of data. + + 1.5. "Executable" means Covered Code in any form other than Source + Code. + + 1.6. "Initial Developer" means the individual or entity identified + as the Initial Developer in the Source Code notice required by Exhibit + A. + + 1.7. "Larger Work" means a work which combines Covered Code or + portions thereof with code not governed by the terms of this License. + + 1.8. "License" means this document. + + 1.8.1. "Licensable" means having the right to grant, to the maximum + extent possible, whether at the time of the initial grant or + subsequently acquired, any and all of the rights conveyed herein. + + 1.9. "Modifications" means any addition to or deletion from the + substance or structure of either the Original Code or any previous + Modifications. When Covered Code is released as a series of files, a + Modification is: + A. Any addition to or deletion from the contents of a file + containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or + previous Modifications. + + 1.10. "Original Code" means Source Code of computer software code + which is described in the Source Code notice required by Exhibit A as + Original Code, and which, at the time of its release under this + License is not already Covered Code governed by this License. + + 1.10.1. "Patent Claims" means any patent claim(s), now owned or + hereafter acquired, including without limitation, method, process, + and apparatus claims, in any patent Licensable by grantor. + + 1.11. "Source Code" means the preferred form of the Covered Code for + making modifications to it, including all modules it contains, plus + any associated interface definition files, scripts used to control + compilation and installation of an Executable, or source code + differential comparisons against either the Original Code or another + well known, available Covered Code of the Contributor's choice. The + Source Code can be in a compressed or archival form, provided the + appropriate decompression or de-archiving software is widely available + for no charge. + + 1.12. "You" (or "Your") means an individual or a legal entity + exercising rights under, and complying with all of the terms of, this + License or a future version of this License issued under Section 6.1. + For legal entities, "You" includes any entity which controls, is + controlled by, or is under common control with You. For purposes of + this definition, "control" means (a) the power, direct or indirect, + to cause the direction or management of such entity, whether by + contract or otherwise, or (b) ownership of more than fifty percent + (50%) of the outstanding shares or beneficial ownership of such + entity. + +2. Source Code License. + + 2.1. The Initial Developer Grant. + The Initial Developer hereby grants You a world-wide, royalty-free, + non-exclusive license, subject to third party intellectual property + claims: + (a) under intellectual property rights (other than patent or + trademark) Licensable by Initial Developer to use, reproduce, + modify, display, perform, sublicense and distribute the Original + Code (or portions thereof) with or without Modifications, and/or + as part of a Larger Work; and + + (b) under Patents Claims infringed by the making, using or + selling of Original Code, to make, have made, use, practice, + sell, and offer for sale, and/or otherwise dispose of the + Original Code (or portions thereof). + + (c) the licenses granted in this Section 2.1(a) and (b) are + effective on the date Initial Developer first distributes + Original Code under the terms of this License. + + (d) Notwithstanding Section 2.1(b) above, no patent license is + granted: 1) for code that You delete from the Original Code; 2) + separate from the Original Code; or 3) for infringements caused + by: i) the modification of the Original Code or ii) the + combination of the Original Code with other software or devices. + + 2.2. Contributor Grant. + Subject to third party intellectual property claims, each Contributor + hereby grants You a world-wide, royalty-free, non-exclusive license + + (a) under intellectual property rights (other than patent or + trademark) Licensable by Contributor, to use, reproduce, modify, + display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an + unmodified basis, with other Modifications, as Covered Code + and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using, or + selling of Modifications made by that Contributor either alone + and/or in combination with its Contributor Version (or portions + of such combination), to make, use, sell, offer for sale, have + made, and/or otherwise dispose of: 1) Modifications made by that + Contributor (or portions thereof); and 2) the combination of + Modifications made by that Contributor with its Contributor + Version (or portions of such combination). + + (c) the licenses granted in Sections 2.2(a) and 2.2(b) are + effective on the date Contributor first makes Commercial Use of + the Covered Code. + + (d) Notwithstanding Section 2.2(b) above, no patent license is + granted: 1) for any code that Contributor has deleted from the + Contributor Version; 2) separate from the Contributor Version; + 3) for infringements caused by: i) third party modifications of + Contributor Version or ii) the combination of Modifications made + by that Contributor with other software (except as part of the + Contributor Version) or other devices; or 4) under Patent Claims + infringed by Covered Code in the absence of Modifications made by + that Contributor. + +3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are + governed by the terms of this License, including without limitation + Section 2.2. The Source Code version of Covered Code may be + distributed only under the terms of this License or a future version + of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You + distribute. You may not offer or impose any terms on any Source Code + version that alters or restricts the applicable version of this + License or the recipients' rights hereunder. However, You may include + an additional document offering the additional rights described in + Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be + made available in Source Code form under the terms of this License + either on the same media as an Executable version or via an accepted + Electronic Distribution Mechanism to anyone to whom you made an + Executable version available; and if made available via Electronic + Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six + (6) months after a subsequent version of that particular Modification + has been made available to such recipients. You are responsible for + ensuring that the Source Code version remains available even if the + Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which You contribute to contain a + file documenting the changes You made to create that Covered Code and + the date of any change. You must include a prominent statement that + the Modification is derived, directly or indirectly, from Original + Code provided by the Initial Developer and including the name of the + Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the + origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + (a) Third Party Claims. + If Contributor has knowledge that a license under a third party's + intellectual property rights is required to exercise the rights + granted by such Contributor under Sections 2.1 or 2.2, + Contributor must include a text file with the Source Code + distribution titled "LEGAL" which describes the claim and the + party making the claim in sufficient detail that a recipient will + know whom to contact. If Contributor obtains such knowledge after + the Modification is made available as described in Section 3.2, + Contributor shall promptly modify the LEGAL file in all copies + Contributor makes available thereafter and shall take other steps + (such as notifying appropriate mailing lists or newsgroups) + reasonably calculated to inform those who received the Covered + Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Contributor's Modifications include an application programming + interface and Contributor has knowledge of patent licenses which + are reasonably necessary to implement that API, Contributor must + also include this information in the LEGAL file. + + (c) Representations. + Contributor represents that, except as disclosed pursuant to + Section 3.4(a) above, Contributor believes that Contributor's + Modifications are Contributor's original creation(s) and/or + Contributor has sufficient rights to grant the rights conveyed by + this License. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source + Code. If it is not possible to put such notice in a particular Source + Code file due to its structure, then You must include such notice in a + location (such as a relevant directory) where a user would be likely + to look for such a notice. If You created one or more Modification(s) + You may add your name as a Contributor to the notice described in + Exhibit A. You must also duplicate this License in any documentation + for the Source Code where You describe recipients' rights or ownership + rights relating to Covered Code. You may choose to offer, and to + charge a fee for, warranty, support, indemnity or liability + obligations to one or more recipients of Covered Code. However, You + may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than + any such warranty, support, indemnity or liability obligation is + offered by You alone, and You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the + Initial Developer or such Contributor as a result of warranty, + support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the + requirements of Section 3.1-3.5 have been met for that Covered Code, + and if You include a notice stating that the Source Code version of + the Covered Code is available under the terms of this License, + including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included + in any notice in an Executable version, related documentation or + collateral in which You describe recipients' rights relating to the + Covered Code. You may distribute the Executable version of Covered + Code or ownership rights under a license of Your choice, which may + contain terms different from this License, provided that You are in + compliance with the terms of this License and that the license for the + Executable version does not attempt to limit or alter the recipient's + rights in the Source Code version from the rights set forth in this + License. If You distribute the Executable version under a different + license You must make it absolutely clear that any terms which differ + from this License are offered by You alone, not by the Initial + Developer or any Contributor. You hereby agree to indemnify the + Initial Developer and every Contributor for any liability incurred by + the Initial Developer or such Contributor as a result of any such + terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code + not governed by the terms of this License and distribute the Larger + Work as a single product. In such a case, You must make sure the + requirements of this License are fulfilled for the Covered Code. + +4. Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Code due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description + must be included in the LEGAL file described in Section 3.4 and must + be included with all distributions of the Source Code. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Application of this License. + + This License applies to code to which the Initial Developer has + attached the notice in Exhibit A and to related Covered Code. + +6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation ("Netscape") may publish revised + and/or new versions of the License from time to time. Each version + will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the + License, You may always continue to use it under the terms of that + version. You may also choose to use such Covered Code under the terms + of any subsequent version of the License published by Netscape. No one + other than Netscape has the right to modify the terms applicable to + Covered Code created under this License. + + 6.3. Derivative Works. + If You create or use a modified version of this License (which you may + only do in order to apply it to code which is not already Covered Code + governed by this License), You must (a) rename Your license so that + the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", + "MPL", "NPL" or any confusingly similar phrase do not appear in your + license (except to note that your license differs from this License) + and (b) otherwise make it clear that Your version of the license + contains terms which differ from the Mozilla Public License and + Netscape Public License. (Filling in the name of the Initial + Developer, Original Code or Contributor in the notice described in + Exhibit A shall not of themselves be deemed to be modifications of + this License.) + +7. DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF + DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. + THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE + IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, + YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER + OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF + ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +8. TERMINATION. + + 8.1. This License and the rights granted hereunder will terminate + automatically if You fail to comply with terms herein and fail to cure + such breach within 30 days of becoming aware of the breach. All + sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their + nature, must remain in effect beyond the termination of this License + shall survive. + + 8.2. If You initiate litigation by asserting a patent infringement + claim (excluding declatory judgment actions) against Initial Developer + or a Contributor (the Initial Developer or Contributor against whom + You file such action is referred to as "Participant") alleging that: + + (a) such Participant's Contributor Version directly or indirectly + infringes any patent, then any and all rights granted by such + Participant to You under Sections 2.1 and/or 2.2 of this License + shall, upon 60 days notice from Participant terminate prospectively, + unless if within 60 days after receipt of notice You either: (i) + agree in writing to pay Participant a mutually agreeable reasonable + royalty for Your past and future use of Modifications made by such + Participant, or (ii) withdraw Your litigation claim with respect to + the Contributor Version against such Participant. If within 60 days + of notice, a reasonable royalty and payment arrangement are not + mutually agreed upon in writing by the parties or the litigation claim + is not withdrawn, the rights granted by Participant to You under + Sections 2.1 and/or 2.2 automatically terminate at the expiration of + the 60 day notice period specified above. + + (b) any software, hardware, or device, other than such Participant's + Contributor Version, directly or indirectly infringes any patent, then + any rights granted to You by such Participant under Sections 2.1(b) + and 2.2(b) are revoked effective as of the date You first made, used, + sold, distributed, or had made, Modifications made by that + Participant. + + 8.3. If You assert a patent infringement claim against Participant + alleging that such Participant's Contributor Version directly or + indirectly infringes any patent where such claim is resolved (such as + by license or settlement) prior to the initiation of patent + infringement litigation, then the reasonable value of the licenses + granted by such Participant under Sections 2.1 or 2.2 shall be taken + into account in determining the amount or value of any payment or + license. + + 8.4. In the event of termination under Sections 8.1 or 8.2 above, + all end user license agreements (excluding distributors and resellers) + which have been validly granted by You or any distributor hereunder + prior to termination shall survive termination. + +9. LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT + (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL + DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, + OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR + ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY + CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, + WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER + COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN + INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF + LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY + RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW + PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE + EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO + THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + +10. U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in + 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer + software" and "commercial computer software documentation," as such + terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 + C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), + all U.S. Government End Users acquire Covered Code with only those + rights set forth herein. + +11. MISCELLANEOUS. + + This License represents the complete agreement concerning subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. This License shall be governed by + California law provisions (except to the extent applicable law, if + any, provides otherwise), excluding its conflict-of-law provisions. + With respect to disputes in which at least one party is a citizen of, + or an entity chartered or registered to do business in the United + States of America, any litigation relating to this License shall be + subject to the jurisdiction of the Federal Courts of the Northern + District of California, with venue lying in Santa Clara County, + California, with the losing party responsible for costs, including + without limitation, court costs and reasonable attorneys' fees and + expenses. The application of the United Nations Convention on + Contracts for the International Sale of Goods is expressly excluded. + Any law or regulation which provides that the language of a contract + shall be construed against the drafter shall not apply to this + License. + +12. RESPONSIBILITY FOR CLAIMS. + + As between Initial Developer and the Contributors, each party is + responsible for claims and damages arising, directly or indirectly, + out of its utilization of rights under this License and You agree to + work with Initial Developer and Contributors to distribute such + responsibility on an equitable basis. Nothing herein is intended or + shall be deemed to constitute any admission of liability. + +13. MULTIPLE-LICENSED CODE. + + Initial Developer may designate portions of the Covered Code as + "Multiple-Licensed". "Multiple-Licensed" means that the Initial + Developer permits you to utilize portions of the Covered Code under + Your choice of the NPL or the alternative licenses, if any, specified + by the Initial Developer in the file described in Exhibit A. + +EXHIBIT A -Mozilla Public License. + + ``The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + License for the specific language governing rights and limitations + under the License. + + The Original Code is ______________________________________. + + The Initial Developer of the Original Code is ________________________. + Portions created by ______________________ are Copyright (C) ______ + _______________________. All Rights Reserved. + + Contributor(s): ______________________________________. + + Alternatively, the contents of this file may be used under the terms + of the _____ license (the "[___] License"), in which case the + provisions of [______] License are applicable instead of those + above. If you wish to allow use of your version of this file only + under the terms of the [____] License and not to allow others to use + your version of this file under the MPL, indicate your decision by + deleting the provisions above and replace them with the notice and + other provisions required by the [___] License. If you do not delete + the provisions above, a recipient may use your version of this file + under either the MPL or the [___] License." + + [NOTE: The text of this Exhibit A may differ slightly from the text of + the notices in the Source Code files of the Original Code. You should + use the text of this Exhibit A rather than the text found in the + Original Code Source Code for Your Modifications.] + +============================================================================== + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. + +============================================================================== diff --git a/Source/eu.modelwriter.core.svgutil/lib/LICENSE.sax.txt b/Source/eu.modelwriter.core.svgutil/lib/LICENSE.sax.txt new file mode 100644 index 00000000..739cb51a --- /dev/null +++ b/Source/eu.modelwriter.core.svgutil/lib/LICENSE.sax.txt @@ -0,0 +1,23 @@ +xml-commons/java/external/LICENSE.sax.txt $Id: LICENSE.sax.txt 201084 2002-12-09 16:15:21Z vhardy $ + + +This license came from: http://www.megginson.com/SAX/copying.html + However please note future versions of SAX may be covered + under http://saxproject.org/?selected=pd + + +This page is now out of date -- see the new SAX site at +http://www.saxproject.org/ for more up-to-date +releases and other information. Please change your bookmarks. + + +SAX2 is Free! + +I hereby abandon any property rights to SAX 2.0 (the Simple API for +XML), and release all of the SAX 2.0 source code, compiled code, and +documentation contained in this distribution into the Public Domain. +SAX comes with NO WARRANTY or guarantee of fitness for any +purpose. + +David Megginson, david@megginson.com +2000-05-05 \ No newline at end of file diff --git a/Source/eu.modelwriter.core.svgutil/lib/LICENSE.xalan-2.7.0.txt b/Source/eu.modelwriter.core.svgutil/lib/LICENSE.xalan-2.7.0.txt new file mode 100644 index 00000000..925acdf7 --- /dev/null +++ b/Source/eu.modelwriter.core.svgutil/lib/LICENSE.xalan-2.7.0.txt @@ -0,0 +1,2 @@ +The xalan-2.7.0.jar file is licensed under the Apache License 2.0, which +can be found in the distribution root directory in the LICENSE file. diff --git a/Source/eu.modelwriter.core.svgutil/lib/LICENSE.xerces_2_5_0.txt b/Source/eu.modelwriter.core.svgutil/lib/LICENSE.xerces_2_5_0.txt new file mode 100644 index 00000000..b6d4a8bc --- /dev/null +++ b/Source/eu.modelwriter.core.svgutil/lib/LICENSE.xerces_2_5_0.txt @@ -0,0 +1,60 @@ +The xerces_2_5_0.jar file comes from the Apache Xerces project +(http://xmlapache.org/dist/xerces-j/), and is licensed under the +Apache Software License, Version 1.1, which is reproduced below. + +/* + * The Apache Software License, Version 1.1 + * + * + * Copyright (c) 1999-2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Xerces" and "Apache Software Foundation" must + * not be used to endorse or promote products derived from this + * software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * nor may "Apache" appear in their name, without prior written + * permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation and was + * originally based on software copyright (c) 1999, International + * Business Machines, Inc., http://www.ibm.com. For more + * information on the Apache Software Foundation, please see + * . + */ diff --git a/Source/eu.modelwriter.core.svgutil/lib/LICENSE.xmlgraphics-commons-2.0.txt b/Source/eu.modelwriter.core.svgutil/lib/LICENSE.xmlgraphics-commons-2.0.txt new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/Source/eu.modelwriter.core.svgutil/lib/LICENSE.xmlgraphics-commons-2.0.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Source/eu.modelwriter.core.svgutil/lib/README.fop-transcoder-allinone-1.1.txt b/Source/eu.modelwriter.core.svgutil/lib/README.fop-transcoder-allinone-1.1.txt new file mode 100644 index 00000000..d5f8c04c --- /dev/null +++ b/Source/eu.modelwriter.core.svgutil/lib/README.fop-transcoder-allinone-1.1.txt @@ -0,0 +1,8 @@ +The fop-transcoder-allinone-1.1.jar file is built from the Apache FOP project +(http://xmlgraphics.apache.org/fop), version 1.1. + +This is only needed if you want to transcode to PDF, otherwise it can +be removed. + +The pdf-transcoder.jar file is licensed under the Apache License 2.0, which +can be found in the distribution root directory in the LICENSE file. diff --git a/Source/eu.modelwriter.core.svgutil/lib/README.js.txt b/Source/eu.modelwriter.core.svgutil/lib/README.js.txt new file mode 100644 index 00000000..72df38f4 --- /dev/null +++ b/Source/eu.modelwriter.core.svgutil/lib/README.js.txt @@ -0,0 +1,23 @@ +This distribution includes a binary distribution of Mozilla Rhino 1.6 release 5 +plus one patch. + +You can get the unpatched 1.6R5 release of Rhino from the following URL: + + ftp://ftp.mozilla.org/pub/mozilla.org/js/rhino1_6R5.zip + +To obtain the source code for the 1.6R5 release of Rhino, issue the following +commands: + + cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot \ + co -D2006-11-20 mozilla/js/rhino + +The patch is available here: + + https://bugzilla.mozilla.org/attachment.cgi?id=288467 + +which is attached to this bug: + + https://bugzilla.mozilla.org/show_bug.cgi?id=367627 + +Rhino is licensed under both the MPL (Mozilla Public License) 1.1 and the +GPL (GNU General Public License) 2.0, which are in the LICENSE.js.txt file. diff --git a/Source/eu.modelwriter.core.svgutil/lib/README.xalan-2.7.0.txt b/Source/eu.modelwriter.core.svgutil/lib/README.xalan-2.7.0.txt new file mode 100644 index 00000000..1febebd7 --- /dev/null +++ b/Source/eu.modelwriter.core.svgutil/lib/README.xalan-2.7.0.txt @@ -0,0 +1,4 @@ +The xalan-2.7.0.jar file comes from the Apache Xalan project +(http://xml.apache.org/xalan-j/), and is licensed under the +Apache License 2.0, which can be found in the distribution root directory +in the LICENSE file. diff --git a/Source/eu.modelwriter.core.svgutil/lib/README.xerces_2_5_0.txt b/Source/eu.modelwriter.core.svgutil/lib/README.xerces_2_5_0.txt new file mode 100644 index 00000000..6090b005 --- /dev/null +++ b/Source/eu.modelwriter.core.svgutil/lib/README.xerces_2_5_0.txt @@ -0,0 +1,4 @@ +The xerces_2_5_0.jar file comes from the Apache Xerces project +(http://xml.apache.org/dist/xerces-j/), and is licensed under the +Apache Software License, Version 1.1, which is in the +LICENSE.xerces_2_5_0.txt file. diff --git a/Source/eu.modelwriter.core.svgutil/lib/README.xml-apis-1.3.04.txt b/Source/eu.modelwriter.core.svgutil/lib/README.xml-apis-1.3.04.txt new file mode 100644 index 00000000..dcfbcdfc --- /dev/null +++ b/Source/eu.modelwriter.core.svgutil/lib/README.xml-apis-1.3.04.txt @@ -0,0 +1,30 @@ +This distribution includes xml-apis.jar from the XML Commons External +1.3.04 binary distribution, which can also be obtained from: + + http://xml.apache.org/mirrors.cgi + +Source code is available from the XML Commons web site: + + http://xml.apache.org/commons/ + +xml-apis.jar contains: + + - DOM Level 2 Events + - DOM Level 2 HTML + - DOM Level 2 Style + - DOM Level 2 Traversal and Range + - DOM Level 2 Views + - DOM Level 3 Core + - DOM Level 3 Load and Save + - DOM Level 3 XPath + - JAXP 1.3 (JSR 206) + - SAX + +All DOM code is licensed under the W3C Software License, and DOM documentation +under the W3C Document License. See LICENSE.dom-software.txt and +LICENSE.dom-documentation.txt. + +The JAXP 1.3 code is licensed under the Apache Software License 2.0, which is +in the LICENSE in the root directory of this distribution. + +SAX is public domain. See LICENSE.sax.txt. diff --git a/Source/eu.modelwriter.core.svgutil/lib/README.xml-apis-ext-1.3.04.txt b/Source/eu.modelwriter.core.svgutil/lib/README.xml-apis-ext-1.3.04.txt new file mode 100644 index 00000000..03a0a1ea --- /dev/null +++ b/Source/eu.modelwriter.core.svgutil/lib/README.xml-apis-ext-1.3.04.txt @@ -0,0 +1,19 @@ +This distribution includes xml-apis-ext.jar from the XML Commons External +1.3.04 binary distribution, which can also be obtained from: + + http://xml.apache.org/mirrors.cgi + +Source code is available from the XML Commons web site: + + http://xml.apache.org/commons/ + +xml-apis-ext.jar contains: + + - SAC 1.3 + - SMIL Java bindings + - SVG 1.1 Java bindings + +SAC 1.3, the SMIL Java bindings and the SVG 1.1 Java bindings are licensed +under the W3C Software License. Related documentation is licensed under the +W3C Document License. See LICENSE.dom-software.txt and +LICENSE.dom-documentation.txt. diff --git a/Source/eu.modelwriter.core.svgutil/lib/Squiggle.icns b/Source/eu.modelwriter.core.svgutil/lib/Squiggle.icns new file mode 100644 index 00000000..b4875d6c Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/Squiggle.icns differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/batik-anim-1.8.jar b/Source/eu.modelwriter.core.svgutil/lib/batik-anim-1.8.jar new file mode 100644 index 00000000..9470058c Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/batik-anim-1.8.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/batik-awt-util-1.8.jar b/Source/eu.modelwriter.core.svgutil/lib/batik-awt-util-1.8.jar new file mode 100644 index 00000000..740acb74 Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/batik-awt-util-1.8.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/batik-bridge-1.8.jar b/Source/eu.modelwriter.core.svgutil/lib/batik-bridge-1.8.jar new file mode 100644 index 00000000..36e8e036 Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/batik-bridge-1.8.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/batik-codec-1.8.jar b/Source/eu.modelwriter.core.svgutil/lib/batik-codec-1.8.jar new file mode 100644 index 00000000..07b6e79c Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/batik-codec-1.8.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/batik-css-1.8.jar b/Source/eu.modelwriter.core.svgutil/lib/batik-css-1.8.jar new file mode 100644 index 00000000..1c9fb195 Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/batik-css-1.8.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/batik-dom-1.8.jar b/Source/eu.modelwriter.core.svgutil/lib/batik-dom-1.8.jar new file mode 100644 index 00000000..4899b514 Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/batik-dom-1.8.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/batik-ext-1.8.jar b/Source/eu.modelwriter.core.svgutil/lib/batik-ext-1.8.jar new file mode 100644 index 00000000..d7c850b1 Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/batik-ext-1.8.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/batik-extension-1.8.jar b/Source/eu.modelwriter.core.svgutil/lib/batik-extension-1.8.jar new file mode 100644 index 00000000..5aa9b7a1 Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/batik-extension-1.8.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/batik-gui-util-1.8.jar b/Source/eu.modelwriter.core.svgutil/lib/batik-gui-util-1.8.jar new file mode 100644 index 00000000..15eb1960 Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/batik-gui-util-1.8.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/batik-gvt-1.8.jar b/Source/eu.modelwriter.core.svgutil/lib/batik-gvt-1.8.jar new file mode 100644 index 00000000..7bb4e58d Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/batik-gvt-1.8.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/batik-parser-1.8.jar b/Source/eu.modelwriter.core.svgutil/lib/batik-parser-1.8.jar new file mode 100644 index 00000000..1c1223d4 Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/batik-parser-1.8.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/batik-script-1.8.jar b/Source/eu.modelwriter.core.svgutil/lib/batik-script-1.8.jar new file mode 100644 index 00000000..c3e9a9f7 Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/batik-script-1.8.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/batik-svg-dom-1.8.jar b/Source/eu.modelwriter.core.svgutil/lib/batik-svg-dom-1.8.jar new file mode 100644 index 00000000..64295503 Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/batik-svg-dom-1.8.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/batik-svggen-1.8.jar b/Source/eu.modelwriter.core.svgutil/lib/batik-svggen-1.8.jar new file mode 100644 index 00000000..9aaa826a Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/batik-svggen-1.8.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/batik-swing-1.8.jar b/Source/eu.modelwriter.core.svgutil/lib/batik-swing-1.8.jar new file mode 100644 index 00000000..43fa2e08 Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/batik-swing-1.8.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/batik-transcoder-1.8.jar b/Source/eu.modelwriter.core.svgutil/lib/batik-transcoder-1.8.jar new file mode 100644 index 00000000..f3c3c4f8 Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/batik-transcoder-1.8.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/batik-util-1.8.jar b/Source/eu.modelwriter.core.svgutil/lib/batik-util-1.8.jar new file mode 100644 index 00000000..23e36253 Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/batik-util-1.8.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/batik-xml-1.8.jar b/Source/eu.modelwriter.core.svgutil/lib/batik-xml-1.8.jar new file mode 100644 index 00000000..1101455a Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/batik-xml-1.8.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/fop-transcoder-allinone-1.1.jar b/Source/eu.modelwriter.core.svgutil/lib/fop-transcoder-allinone-1.1.jar new file mode 100644 index 00000000..931a8e6d Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/fop-transcoder-allinone-1.1.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/js.jar b/Source/eu.modelwriter.core.svgutil/lib/js.jar new file mode 100644 index 00000000..ccad3cc1 Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/lib/js.jar differ diff --git a/Source/eu.modelwriter.core.svgutil/lib/make-squiggle-app.sh b/Source/eu.modelwriter.core.svgutil/lib/make-squiggle-app.sh new file mode 100644 index 00000000..14cbe856 --- /dev/null +++ b/Source/eu.modelwriter.core.svgutil/lib/make-squiggle-app.sh @@ -0,0 +1,87 @@ +#!/bin/bash +# ----------------------------------------------------------------------------- +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# make-squiggle-app.sh +# +# Creates a Mac OS X application bundle for Squiggle, then opens a Finder +# window for the current directory so that the user can drag the icon +# into their desired installation location (probably /Applications). +# +# $Id: make-squiggle-app.sh.template 985243 2010-08-13 15:30:25Z helder $ +# ----------------------------------------------------------------------------- + +trap 'echo Error creating application bundle.; exit 1' ERR + +cd `dirname "$0"`/.. + +APP=Squiggle.app +CON=$APP/Contents +MAC=$CON/MacOS +RES=$CON/Resources + +[ -e $APP ] && echo $APP already exists: please move it out of the way before running this script. && exit 1 + +echo Creating $APP in `pwd`... + +mkdir $APP $CON $MAC $RES + +cat >$CON/Info.plist < + + + + CFBundleExecutable + Squiggle + CFBundleVersion + 1.8 + CFBundleShortVersionString + 1.8 + CFBundleIconFile + Squiggle.icns + CFBundleIdentifier + org.apache.batik + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Squiggle + CFBundlePackageType + APPL + CFBundleSignature + ???? + NSHumanReadableCopyright + Copyright © 2015 Apache Software Foundation. All Rights Reserved. + + +EOF + +cat >$MAC/Squiggle < paths = Files.walk(Paths.get(folderPath))) { + paths.forEach(path -> { + File file = path.toFile(); + if (file.isFile() && file.getName().endsWith(".svg")) { + try { + System.out.println("Editing: " + file.getName()); + editSVG(file.getAbsolutePath(), width, height, padding, color); + System.out.println("Done"); + } catch (IOException e) { + System.out.println("Failed"); + } + } + }); + } catch (IOException e) { + System.out.println("IO Exception, check folder path"); + } + } + + private static void setupArgs(String[] args) { + if (args.length > 0) + folderPath = args[0]; + else + folderPath = "../eu.modelwriter.core.alloyinecore.ui/icons/full/exp16"; + if (args.length >= 5) { + width = args[1]; + height = args[2]; + padding = args[3]; + color = "#" + args[4]; + } else { + width = "16"; + height = "16"; + padding = "0"; + color = "#000000"; + } + System.out.println("SVG Editor:"); + System.out.println("With: " + width); + System.out.println("Height: " + height); + System.out.println("Padding: " + padding); + System.out.println("Color: " + color); + System.out.println("---------------------"); + } + + private static void editSVG(String filePath, String width, String height, String padding, + String color) throws IOException { + try { + Document document = loadDocument(filePath); + Element svgElement = (Element) document.getElementsByTagName("svg").item(0); + svgElement.setAttribute("width", width); + svgElement.setAttribute("height", height); + String style = svgElement.getAttribute("style"); + // Set color + String fillStyle = "fill:" + color; + if (!style.contains("fill")) { + style += + style.isEmpty() ? fillStyle : (style.endsWith(";") ? fillStyle : (";" + fillStyle)); + } else { + style = style.replaceAll("fill:\\s*#(......|...)", fillStyle); + } + // Set padding + String paddingStyle = "padding: " + padding + "px"; + if (!style.contains("padding")) { + style += style.isEmpty() ? paddingStyle + : (style.endsWith(";") ? paddingStyle : (";" + paddingStyle)); + } else { + style = style.replaceAll("padding:\\s*\\d*px", paddingStyle); + } + svgElement.setAttribute("style", style); + saveDocument(document, filePath); + } catch (ParserConfigurationException | SAXException e) { + e.printStackTrace(); + } + } + + public static void editSVG(String filePath, int width, int height, int padding, String hexColor) + throws IOException { + editSVG(filePath, String.valueOf(width), String.valueOf(height), String.valueOf(padding), + hexColor); + } + + public static Document loadDocument(String path) + throws IOException, ParserConfigurationException, SAXException { + File file = new File(path); + FileInputStream svgInputStream = new FileInputStream(file); + String parser = XMLResourceDescriptor.getXMLParserClassName(); + SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(parser); + Document doc = factory.createDocument(parser, svgInputStream); + return doc; + } + + public static void saveDocument(Document doc, String savePath) throws IOException { + byte[] fileData = transcodeToSVG(doc); + FileOutputStream fileSave = new FileOutputStream(savePath); + fileSave.write(fileData); + fileSave.flush(); + fileSave.close(); + } + + public static byte[] transcodeToSVG(Document doc) { + try { + // Determine output type: + SVGTranscoder t = new SVGTranscoder(); + + // Set transcoder input/output + TranscoderInput input = new TranscoderInput(doc); + ByteArrayOutputStream bytestream = new ByteArrayOutputStream(); + OutputStreamWriter ostream = new OutputStreamWriter(bytestream); + TranscoderOutput output = new TranscoderOutput(ostream); + + // Perform transcoding + t.transcode(input, output); + ostream.flush(); + ostream.close(); + + return bytestream.toByteArray(); + + } catch (IOException | TranscoderException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/Source/eu.modelwriter.core.svgutil/svgutil.jar b/Source/eu.modelwriter.core.svgutil/svgutil.jar new file mode 100644 index 00000000..67215561 Binary files /dev/null and b/Source/eu.modelwriter.core.svgutil/svgutil.jar differ diff --git a/Source/eu.modelwriter.kodkod.core/.classpath b/Source/eu.modelwriter.kodkod.core/.classpath new file mode 100644 index 00000000..7949eed3 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Source/eu.modelwriter.kodkod.core/.gitignore b/Source/eu.modelwriter.kodkod.core/.gitignore new file mode 100644 index 00000000..ae3c1726 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/Source/eu.modelwriter.kodkod.core/.project b/Source/eu.modelwriter.kodkod.core/.project new file mode 100644 index 00000000..595314c0 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/.project @@ -0,0 +1,28 @@ + + + eu.modelwriter.kodkod.core + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/Source/eu.modelwriter.kodkod.core/.settings/org.eclipse.jdt.core.prefs b/Source/eu.modelwriter.kodkod.core/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..0c68a61d --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/Source/eu.modelwriter.kodkod.core/META-INF/MANIFEST.MF b/Source/eu.modelwriter.kodkod.core/META-INF/MANIFEST.MF new file mode 100644 index 00000000..143e31a3 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/META-INF/MANIFEST.MF @@ -0,0 +1,22 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Core +Bundle-SymbolicName: eu.modelwriter.kodkod.core +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: eu.modelwriter.kodkod.core.Activator +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ActivationPolicy: lazy +Export-Package: eu.modelwriter.kodkod.core; + uses:="org.osgi.framework, + org.antlr.v4.runtime, + org.antlr.v4.runtime.tree, + kodkod.instance, + org.antlr.v4.runtime.atn, + org.eclipse.ui.plugin", + eu.modelwriter.kodkod.core.model, + eu.modelwriter.kodkod.core.printer +Bundle-ClassPath: lib/antlr-4.5.1-complete.jar, + ., + lib/kodkod.jar diff --git a/Source/eu.modelwriter.kodkod.core/build.properties b/Source/eu.modelwriter.kodkod.core/build.properties new file mode 100644 index 00000000..267af3c5 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/build.properties @@ -0,0 +1,6 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + lib/antlr-4.5.1-complete.jar,\ + lib/kodkod.jar diff --git a/Source/eu.modelwriter.kodkod.core/lib/antlr-4.5.1-complete.jar b/Source/eu.modelwriter.kodkod.core/lib/antlr-4.5.1-complete.jar new file mode 100644 index 00000000..2e24ebe8 Binary files /dev/null and b/Source/eu.modelwriter.kodkod.core/lib/antlr-4.5.1-complete.jar differ diff --git a/Source/eu.modelwriter.kodkod.core/lib/kodkod.jar b/Source/eu.modelwriter.kodkod.core/lib/kodkod.jar new file mode 100644 index 00000000..ecbb6172 Binary files /dev/null and b/Source/eu.modelwriter.kodkod.core/lib/kodkod.jar differ diff --git a/Source/eu.modelwriter.kodkod.core/sourceFile/List.kodkod b/Source/eu.modelwriter.kodkod.core/sourceFile/List.kodkod new file mode 100644 index 00000000..5afd430a --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/sourceFile/List.kodkod @@ -0,0 +1,24 @@ +universe {Thing0, Thing1, Thing2, List0, List1, List2} + +relations { +Thing: [[[Thing2]]] +List: [[[List0], [List1], [List2]]] +EmptyList: List [[[List0]]] +NonEmptyList: List [[[List1], [List2]]] +car: NonEmptyList -> one Thing [[[List1, Thing2], [List2, Thing2]]] +cdr: NonEmptyList -> one List [[[List1, List0], [List2, List1]]] +equivTo: List -> List [[[List0, List0], [List1, List1], [List2, List2]]] +prefixes: List -> List [[[List0, List0], [List0, List2], [List1, List0], [List1, List1], [List2, List0], [List2, List1], [List2, List2]]]} + +List = (EmptyList + NonEmptyList) +no (EmptyList & NonEmptyList) +--equivTo in (List -> List) +--prefixes in (List -> List) +function[car: NonEmptyList -> one Thing] +function[cdr: NonEmptyList -> one List] +Thing in (List . car) +all L: List | some (EmptyList & (L . *cdr)) +all a: List, b: List | a in (b . equivTo) <=> ((a . car) = (b . car) && (b . cdr) in ((a . cdr) . equivTo)) +(List -> EmptyList) in prefixes +all a: NonEmptyList, b: NonEmptyList | a in (b . prefixes) <=> ((a . car) = (b . car) && (a . cdr) in ((b . cdr) . prefixes)) +some a: NonEmptyList, b: NonEmptyList | !(a = b) && b in (a . prefixes) \ No newline at end of file diff --git a/Source/eu.modelwriter.kodkod.core/sourceFile/TypeDefinitions.kodkod b/Source/eu.modelwriter.kodkod.core/sourceFile/TypeDefinitions.kodkod new file mode 100644 index 00000000..745116b8 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/sourceFile/TypeDefinitions.kodkod @@ -0,0 +1,22 @@ +universe {d0, d1, d2, d3, f0, f1, f2, f3} + +Relations { +File 1: [ {(f0), (f1), (f2), (f3)} ] +Dir 1 : [ {(d0), (d1), (d2)} ] +Root 1 : Dir [{(d0)}] --type checking : arity check must be performed +contents 2: Dir -> File [[[d0, d1], [d0, d2], [d0, f0], [d0, f1], [d0, f2] ]] --type checking : arity check must be performed +A: Root [[(a0), (a1)]] +B: [[(b1), (b2)]] +C: [[(c1), (c2)]] +r0: A one -> one B [[[d0, d1], [d0, d2], [d0, f0], [d0, f1], [d0, f2] ]] --bounds are now irrelavant +r1: A -> (B one -> C) [[[a0, b1, c1], [a0, b2, c2], [a0, b0, c1], [a0, b1, c2], [a0, b2, c1]]] --if it is defined as exact bounds, it may be checked! +r2: (A -> B) -> C [[[a0, b1, c1], [a0, b2, c2], [a0, b0, c1], [a0, b1, c2], [a0, b2, c1]]] +r3: (A -> B -> C) [[[a0, b1, c1], [a0, b2, c2], [a0, b0, c1], [a0, b1, c2], [a0, b2, c1]]] +r4: (A -> B) lone -> C [[]] --if type is defined and but not bounds, LB is set to empty set, but upper bound is set to the cartesian product defined +r5: A -> B -> C [[[d0, d1], [d0, d2], [d0, f0], [d0, f1], [d0, f2] ]] --type checking error, arity does not conform to bounds. +r6: (Alias -> Addr) + (Group -> (Addr + Alias + Group)) [[]]} --type checking error, undefined relations + +contents in Dir -> (Dir + File) +all d:Dir | not (d in d.^contents) +Root in Dir +(File + Dir) in Root.*contents diff --git a/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/Activator.java b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/Activator.java new file mode 100644 index 00000000..fbf78b48 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/Activator.java @@ -0,0 +1,50 @@ +package eu.modelwriter.kodkod.core; + +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "eu.modelwriter.kodkod.core"; //$NON-NLS-1$ + + // The shared instance + private static Activator plugin; + + /** + * The constructor + */ + public Activator() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + +} diff --git a/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/Kodkod.g4 b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/Kodkod.g4 new file mode 100644 index 00000000..7fb0da62 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/Kodkod.g4 @@ -0,0 +1,296 @@ +grammar Kodkod; + +@parser::header {} + +@parser::members { + public java.util.Stack declarations = new java.util.Stack(); + public java.util.List atoms = new java.util.ArrayList(); + public java.util.List formulas = new java.util.ArrayList(); + public java.util.Map relations = new java.util.HashMap(); + public kodkod.instance.Universe universe = null; + public kodkod.instance.Bounds bounds = null; + + private boolean isRelation() { return this.relations.containsKey(getCurrentToken().getText()); } + private String getLocation() { return "["+ getCurrentToken().getLine()+ ","+ getCurrentToken().getCharPositionInLine()+ "]";} + private String context = null; + private int declareVariables(java.util.List vars, int var) { + System.out.println("Quantifier context: "); + for (VariableIdContext vc : vars) { + String s = vc.getText(); declarations.add(s); var++; System.out.println(s); + } + return var; + } +} + +problem: options? universe {System.out.println(universe);} relations {System.out.println(bounds);} formulas+=formula* {} { + System.out.println("declarations= "+declarations); + declarations.clear(); +}; + +options: 'options' '{' option (',' option) '}'; + +option: 'symmetry_breaking' ':' integer #symmetryBreaking + | 'bit_width' ':' integer #bitWidth + | 'skolem_depth' ':' integer #skolemDepth + | 'sharing' ':' integer #sharing +; + +universe +@init{context="universe";} +:'universe' (('{' (atoms+=atom (',' atoms+=atom)*)'}') | ('[' (atoms+=atom (',' atoms+=atom)*) ']') ){ + System.out.println("universe:"); + for (AtomContext atom : $atoms) { + String s = atom.getText(); System.out.println(s); + if (atoms.contains(s)) {System.err.println("duplicated atom found: '"+ s + "' at "+ getLocation());} + else {atoms.add(s);} + } + this.universe = new kodkod.instance.Universe(this.atoms); + this.bounds = new kodkod.instance.Bounds(this.universe); + context = null; +}; + +relations: 'relations' '{' relation* '}' +; + +relation @init{context="relations";} +: (relationId arity? ':' expression? '[' (lowerBound = tupleSet (',' upperBound = tupleSet)?) ']') { + String name = $relationId.text; + System.out.println("relation " + name); + if (relations.containsKey(name)) {System.err.println("duplicated relation found: '"+ name + "' at "+ getLocation());} + + kodkod.ast.Relation relation = null; + int arity = 0; + if ($arity.text != null && !$arity.text.isEmpty()) {arity = Integer.parseInt($arity.text);} + + kodkod.instance.TupleSet lowerBound = null; + java.util.List tuplesInLowerBound = new java.util.ArrayList(); + if ($lowerBound.ctx != null && !$lowerBound.ctx.tuples.isEmpty()){ + if (arity == 0) {arity = $lowerBound.ctx.tuples.get(0).atoms.size();} + for (TupleContext tuple : $lowerBound.ctx.tuples) { + java.util.List atoms = new java.util.ArrayList(); + for (AtomContext atom : tuple.atoms) { + if (atom.getText() == null || atom.getText().isEmpty()) continue; + atoms.add(atom.getText()); + } + if (!atoms.isEmpty()) tuplesInLowerBound.add(this.universe.factory().tuple(atoms)); + } + lowerBound = this.universe.factory().setOf(tuplesInLowerBound); + System.out.println("lb: " +lowerBound); + } + + kodkod.instance.TupleSet upperBound = null; + java.util.List tuplesInUpperBound = new java.util.ArrayList(); + if ($upperBound.ctx != null && !$upperBound.ctx.tuples.isEmpty()){ + if (lowerBound == null && arity == 0) {arity = $upperBound.ctx.tuples.get(0).atoms.size();} + for (TupleContext tuple : $upperBound.ctx.tuples) { + java.util.List atoms = new java.util.ArrayList(); + for (AtomContext atom : tuple.atoms) { + if (atom.getText() == null || atom.getText().isEmpty()) continue; + atoms.add(atom.getText()); + } + if (!atoms.isEmpty()) tuplesInUpperBound.add(this.universe.factory().tuple(atoms)); + } + upperBound = this.universe.factory().setOf(tuplesInUpperBound); + System.out.println("up: " +upperBound); + } + + if (lowerBound == null && upperBound == null && arity == 0) {arity = 1;} + + if (lowerBound == null) {lowerBound = this.universe.factory().noneOf(arity);} + + System.out.println(arity); + if (arity == 0) { + System.err.println("0 arity is detected on relation: '"+ name + "' at "+ getLocation()); + } else if (arity > 0) { + relation = kodkod.ast.Relation.nary(name, arity); + } + + if (upperBound == null) {this.bounds.boundExactly(relation, lowerBound);} + else {this.bounds.bound(relation, lowerBound, upperBound);} + this.relations.put(name, relation); +}; + +tupleSet: '{' (tuples+=tuple (',' tuples+=tuple)*)? '}' + | '[' (tuples+=tuple (',' tuples+=tuple)*)? ']' + | '{' left=tuple range='..' right=tuple '}' + | '[' left=tuple range='..' right=tuple ']' + ; + +tuple: '(' atoms+=atom (',' atoms+=atom)* ')' | '[' atoms+=atom (',' atoms+=atom)* ']'; +// The +, -, and & operators denote the union, difference, and intersection of two tuple sets, respectively. +// The -> operator denotes the Cartesian product of two tuple sets. car :2 [ none, { rel1a -> rel1b } ] +// Tuple sets can be specified exhaustively by listing all their tuples. 'none' is a synonym for '{}'. +// If all the tuples have consecutive indices, the range operator .. can be used. car :2 [ none, {(A1, A2) .. (A3, A4)} ] + +atom: id=IDENTIFIER { + if (context != null && !context.isEmpty() && !context.equals("universe")) { + System.out.print("atom found: " + $id.text + "-> "); + if ( atoms.contains($id.text) ) {System.out.println("defined");} + else {System.err.println("undefined atom found: '" +$id.text + "' at " + getLocation());} + } +} | INT ; +relationId: IDENTIFIER; +variableId: IDENTIFIER; +integer: INT; +arity: INT; //positive integer + +/* +All binary operators associate to the left, with the exception of implication, which associates to the right. +So, for example, p => q => r is parsed as p => (q => r), and a.b.c is parsed as (a.b).c. +*/ + +//Decls, Expression, Formula, IntExpression: kodkod.ast.Node +formula locals [int var = 0;]: + 'no' expression #no //Formula f = expr.no() --Returns the formula 'no expr'. + | 'lone' expression #lone //Formula f = expr.lone() --Returns the formula 'lone expr'. + | 'one' expression #one //Formula f = expr.one() --Returns the formula 'one expr'. + | 'some' expression #some //Formula f = expr.some() --Returns the formula 'some expr'. + + //Set Operators: These operators can be applied to any pair of relations so long as they have the same arity. + | left=expression not=('!' | 'not')? 'in' right=expression #in //Formula f = left.in(right) --Returns the formula 'left in right' (subset). + | left=expression not=('!' | 'not')? '=' right=expression #equal //Formula f = left.eq(right) --Returns the formula 'left = right' (equal). + + //Integer Comparison Operators + | left=intexpression not=('!' | 'not')? '=' right=intexpression #eq //Formula f= left.eq(right) --Returns a formula stating that the given int expression and left have the same value. + | left=intexpression not=('!' | 'not')? '<' right=intexpression #lt //Formula f= left.lt(right) --Returns a formula stating that the value of this int expression is less than the value of the given int expression. + | left=intexpression not=('!' | 'not')? '<=' right=intexpression #lte //Formula f= left.lte(right)--Returns a formula stating that the value of this int expression is less than or equal to the value of the given int expression. + | left=intexpression not=('!' | 'not')? '>' right=intexpression #gt //Formula f= left.qt(right) --Returns a formula stating that the value of this int expression is greater than the value of the given int expression. + | left=intexpression not=('!' | 'not')? '>=' right=intexpression #gte //Formula f= left.qte(right)--Returns a formula stating that the value of this int expression is greater than or equal to the value of the given int expression + + | {$formula::var = 0;}('sum' decls '|' intexpression) + {for (int i = 0; i < $formula::var; i++) declarations.pop();} #sumDeclaration //IntExpression iexpr = sum(Decls decls); + + | 'acyclic' '[' relationId ']' #acyclic // + | 'function' '[' rel=relationId ':' domain=expression '->' op=('one' | 'lone') range=expression ']' #function //Relation rel; Formula f = rel.function(domain, range); Formula f = rel.partialFunction(domain, range); --Returns a formula stating that this relation is a total function or partial function with the specified domain and range. + | 'ord' '[' rel=relationId ',' ordered=relationId ',' first=relationId ',' last=relationId ']' #totalOrder //Relation rel; Formula f = rel.totalOrder(Relation ordered, Relation first, Relation last) --Returns a formula stating that this relation imposes a total ordering over the atoms in the set ordered, and that thet first and last elements in the ordering are given by the relations first and last. + + //Logical Operators + //NotFormula + | op=('!' | 'not') formula #not //Formula f = formula.not() --Returns the negation of this formula. + + //BinaryFormula (AND, IFF, IMPLIES, OR) + | left=formula op=('&&' | 'and' ) right=formula #and //Formula f = left.and(right) --Returns the conjunction of left and the specified formula. + | left=formula op=('||' | 'or' ) right=formula #or //Formula f = left.or(right) --Returns the disjunction of left and the specified formula + | left=formula op=('=>' | 'if' ) right=formula #implies //Formula f = left.implies(right) --Returns the implication of the specified formula by left. + | left=formula op=('<=>' | 'iff') right=formula #iff //Formula f = left.iff(right) --Returns a formula that equates left and the specified formula. + + | {$formula::var = 0;}('all' decls ('|' (formula | '{' formula* '}' ) | '{' formula* '}')) + {for (int i = 0; i < $formula::var; i++) declarations.pop();} #forAll //Formula f = formula.forAll(decls) --Returns a formula that represents a universal quantification of this formula over the given declarations + | {$formula::var = 0;}('some' decls ('|' (formula | '{' formula* '}' ) | '{' formula* '}')) + {for (int i = 0; i < $formula::var; i++) declarations.pop();} #forSome //Formula f = formula.forSome(decls) --Returns a formula that represents an existential quantification of this formula over the given declarations. + | {$formula::var = 0;}('no' decls ('|' (formula | '{' formula* '}' ) | '{' formula* '}')) + {for (int i = 0; i < $formula::var; i++) declarations.pop();} #forNo //no x: e | F is true when F is true for no bindings of the variable x. + | {$formula::var = 0;}('one' decls ('|' (formula | '{' formula* '}' ) | '{' formula* '}')) + {for (int i = 0; i < $formula::var; i++) declarations.pop();} #forOne //one x: e | F is true when F is true for exactly one binding of the variable x. (unique existential quantification) + | {$formula::var = 0;}('lone' decls ('|' (formula | '{' formula* '}' ) | '{' formula* '}')) + {for (int i = 0; i < $formula::var; i++) declarations.pop();} #forLone //lone x: e | F is true when F is true for at most one binding of the variable x. + + | {$formula::var = 0;}('let' letDecls ('|' (formula | '{' formula* '}' ) | '{' formula* '}')) + {for (int i = 0; i < $formula::var; i++) declarations.pop();} #let + + //Constant Formulas + | 'true' #true //Formula f = Formula.FALSE --Constant formula false + | 'false' #false //Formula f = Formula.TRUE --Constant formula true + + | '(' formula ')' #f_paranthesis +; + +/* +**For the set theoretic operations (union, difference, and intersection) and for relational override, +the arguments are required to have the same arity. +*/ +expression: + {!isRelation()}? variableId { + System.out.print("variable found: " + $variableId.text + "-> "); + String s = $variableId.text; + if ( declarations.contains(s) ) {System.out.println("defined");} + else {System.err.println("undefined variable found: '"+ s + "' at "+ getLocation());} + } #var //ConstantExpression, Relation, Variable + | {isRelation()}? relationId #rel + + + // Relational Operators + // **These expressions are required to be binary + | '~' expression #transpose //Expression: expr.transpose() --Returns the transpose of expr. + | '^' expression #closure //Expression: expr.closure() --Returns the transitive closure of expr. + | '*' expression #reflexive //Expression: expr.reflexiveClosure()--Returns the reflexive transitive closure of expr. + + // Set theoretic operations: + // **These operators can be applied to any pair of relations so long as they have the same arity. + | left=expression '+' right=expression #union //Expression: left.union(right) --Returns the union of left and the specified expression. + | left=expression '&' right=expression #intersection //Expression: left.intersection(right) --Returns the intersection of left and the specified expression. + | left=expression '-' right=expression #difference //Expression: left.difference(right) --Returns the difference of left and the specified expression. + + //Relational Operators + | left=expression '.' right=expression #join //Expression expr = left.join(right) --Returns the join of left and the specified expression. + | right=expression '[' left=expression ']' #boxjoin //Expression expr = left.join(right) --e1[e2] = e2.e1 -- + | left=expression leftMult=('set' | 'one' | 'lone' | 'some')? '->' rightMult=('set' | 'one' | 'lone' | 'some')? right=expression #product //Expression expr = left.product(right) --Returns the product of left and the specified expression + | left=expression '++' right=expression #override //Expression expr = left.override(right) --Returns the relational override of left with the specified expression. + + //A comprehension expression, e.g. { a: A, b: B | a.r = b } + //Comprehensions make relations from properties + //{x1: e1, x2: e2, … | F} The relation obtained by taking all tuples x1 -> x2 -> … + // in which x1 is drawn from the set e1, x2 is drawn from the set e2, and so on, + // and for which the constraint F holds. The expressions e1, e2, and so on, must be unary, + // and may not be prefixed by (or contain) multiplicity keywords + //all d: decls.decls[int] | decl.variable.arity = 1 and decl.multiplicity = ONE + | {$formula::var = 0;}('{' comprehensionDecls '|' formula '}') + {for (int i = 0; i < $formula::var; i++) declarations.pop();} #comprehension //Expression f = formula.comprehension(Decls decls) //Returns the comprehension expression constructed from this formula and the given declarations. + + | op=('=>' | 'if') condition=formula 'then' thenExpr=expression 'else' elseExpr=expression #ifExpression + + //Constants + | 'iden' #iden //Expression expr = Expression.IDEN --The identity relation: maps all atoms in a universe of discourse to themselves. + | 'none' #none //Expression expr = Expression.NONE --The empty relation: contains no atoms. + | 'univ' #univ //Expression expr = Expression.UNIV --The universal relation: contains all atoms in a universe of discourse. + | 'ints' #ints //Expression expr = Expression.INTS --The integer relation: contains all atoms bound to integers + + | '(' expression ')' #e_paranthesis +; + +intexpression: + op=('=>' | 'if') condition=formula 'then' thenExpr=intexpression 'else' elseExpr=intexpression #ifIntExpression + | 'sum' expression #sum //IntExpression iexpr = exp.sum(); --Returns the sum of the integer atoms in this expression. + | '#' expression #count //IntExpression iexpr = exp.count(); --Returns the cardinality(the number of elements in the set) of this expression + | left=intexpression ('+' | 'plus') right=intexpression #plus //IntExpression iexpr = this.plus(intExpr); --Returns an IntExpression that represents the sum of this and the given int node + | left=intexpression ('-' | 'minus') right=intexpression #minus //IntExpression iexpr = this.minus(intExpr); --Returns an IntExpression that represents the difference between this and the given int node. + | left=intexpression ('*' | 'mul') right=intexpression #multiply //IntExpression iexpr = this.minus(intExpr); --Returns an IntExpression that represents the product of this and the given int node. + | left=intexpression ('/' | 'div') right=intexpression #divide //IntExpression iexpr = this.divide(intExpr); --Returns an IntExpression that represents the quotient of the division between this and the given int node. + | left=intexpression ('%' | 'modulo') right=intexpression #modulo //IntExpression iexpr = this.modulo(intExpr); --Returns an IntExpression that represents the remainder of the division between this and the given int node. + | sign='-'? integer #intConstant + | '(' intexpression ')' #i_paranthesis + ; + +//A variable declaration, such as 'x : lone X'. Declarations are used with quantified formulas and comprehension expressions. +decls: decl (',' decl)*; + +decl: disj='disj'? vars+=variableId (',' vars+=variableId)* ':' 'one'? expression + {$formula::var = declareVariables($vars, $formula::var);} #oneOf //Decl d = var.oneOf(expression) + | disj='disj'? vars+=variableId (',' vars+=variableId)* ':' 'lone' expression + {$formula::var = declareVariables($vars, $formula::var);} #loneOf //Decl d = var.loneOf(expression) + | disj='disj'? vars+=variableId (',' vars+=variableId)* ':' 'some' expression + {$formula::var = declareVariables($vars, $formula::var);} #someOf //Decl d = var.someOf(expression) + | disj='disj'? vars+=variableId (',' vars+=variableId)* ':' 'set' expression + {$formula::var = declareVariables($vars, $formula::var);} #setOf //Decl d = var.setOf(expression) +; + +letDecls: letDecl (',' letDecl)*; + +letDecl: (vars+=variableId (',' vars+=variableId)* '=' expression) + {$formula::var = declareVariables($vars, $formula::var);} ; + +comprehensionDecls: comprehensionDecl (',' comprehensionDecl)*; + +comprehensionDecl: disj='disj'? (vars+=variableId (',' vars+=variableId)* ':' 'one'? expression) + {$formula::var = declareVariables($vars, $formula::var);} +; + +INT : DIGIT+ ; +IDENTIFIER : LETTER (LETTER | APOSTROPHE | DIGIT)* ; +fragment +LETTER: [a-zA-Z]; +DIGIT: [0-9]; +APOSTROPHE: '\''; +MULTILINE_COMMENT : '/**' .*? '**/' -> skip; +SINGLELINE_COMMENT : '--' .*? '\r'? '\n' -> skip; +WS: [ \t\r\n]+ -> skip ; // toss out whitespace diff --git a/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/Kodkod.tokens b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/Kodkod.tokens new file mode 100644 index 00000000..45e96013 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/Kodkod.tokens @@ -0,0 +1,148 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +T__7=8 +T__8=9 +T__9=10 +T__10=11 +T__11=12 +T__12=13 +T__13=14 +T__14=15 +T__15=16 +T__16=17 +T__17=18 +T__18=19 +T__19=20 +T__20=21 +T__21=22 +T__22=23 +T__23=24 +T__24=25 +T__25=26 +T__26=27 +T__27=28 +T__28=29 +T__29=30 +T__30=31 +T__31=32 +T__32=33 +T__33=34 +T__34=35 +T__35=36 +T__36=37 +T__37=38 +T__38=39 +T__39=40 +T__40=41 +T__41=42 +T__42=43 +T__43=44 +T__44=45 +T__45=46 +T__46=47 +T__47=48 +T__48=49 +T__49=50 +T__50=51 +T__51=52 +T__52=53 +T__53=54 +T__54=55 +T__55=56 +T__56=57 +T__57=58 +T__58=59 +T__59=60 +T__60=61 +T__61=62 +T__62=63 +T__63=64 +T__64=65 +T__65=66 +T__66=67 +T__67=68 +T__68=69 +T__69=70 +INT=71 +IDENTIFIER=72 +DIGIT=73 +APOSTROPHE=74 +MULTILINE_COMMENT=75 +SINGLELINE_COMMENT=76 +WS=77 +'options'=1 +'{'=2 +','=3 +'}'=4 +'symmetry_breaking'=5 +':'=6 +'bit_width'=7 +'skolem_depth'=8 +'sharing'=9 +'universe'=10 +'['=11 +']'=12 +'relations'=13 +'..'=14 +'('=15 +')'=16 +'no'=17 +'lone'=18 +'one'=19 +'some'=20 +'!'=21 +'not'=22 +'in'=23 +'='=24 +'<'=25 +'<='=26 +'>'=27 +'>='=28 +'sum'=29 +'|'=30 +'acyclic'=31 +'function'=32 +'->'=33 +'ord'=34 +'&&'=35 +'and'=36 +'||'=37 +'or'=38 +'=>'=39 +'if'=40 +'<=>'=41 +'iff'=42 +'all'=43 +'let'=44 +'true'=45 +'false'=46 +'~'=47 +'^'=48 +'*'=49 +'+'=50 +'&'=51 +'-'=52 +'.'=53 +'set'=54 +'++'=55 +'then'=56 +'else'=57 +'iden'=58 +'none'=59 +'univ'=60 +'ints'=61 +'#'=62 +'plus'=63 +'minus'=64 +'mul'=65 +'/'=66 +'div'=67 +'%'=68 +'modulo'=69 +'disj'=70 +'\''=74 diff --git a/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/KodkodAnalyzer.java b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/KodkodAnalyzer.java new file mode 100644 index 00000000..93daadca --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/KodkodAnalyzer.java @@ -0,0 +1,63 @@ +package eu.modelwriter.kodkod.core; + +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTree; + +import eu.modelwriter.kodkod.core.model.Universe; +import eu.modelwriter.kodkod.core.recognizer.KodkodLexer; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.ProblemContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.RelationsContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.UniverseContext; + +public class KodkodAnalyzer { + public enum PARSE_AREA { + FULL_DOCUMENT, OPTIONS, UNIVERSE, RELATION, FORMULAS + } + + public static ProblemContext problem; + + public Universe parseKodkod(final String kodkodString, final PARSE_AREA area) { + final ANTLRInputStream input = new ANTLRInputStream(kodkodString); + final KodkodLexer lexer = new KodkodLexer(input); + final CommonTokenStream tokens = new CommonTokenStream(lexer); + final KodkodParser parser = new KodkodParser(tokens); + final ModelBuildVisitor mbv = new ModelBuildVisitor(); + + ParseTree tree = null; + switch (area) { + case FULL_DOCUMENT: + tree = KodkodAnalyzer.problem = parser.problem(); + break; + case OPTIONS: + tree = parser.options(); + return null; + case UNIVERSE: + tree = parser.universe(); + break; + case RELATION: + final UniverseContext universe = parser.universe(); + final RelationsContext relations = parser.relations(); + if (parser.getNumberOfSyntaxErrors() == 0) { + mbv.visitUniverse(universe); + mbv.visitRelations(relations); + return mbv.getUniverse(); + } + break; + case FORMULAS: + tree = KodkodAnalyzer.problem = parser.problem(); + return null; + default: + tree = KodkodAnalyzer.problem = parser.problem(); + break; + } + + if (parser.getNumberOfSyntaxErrors() == 0) { + mbv.visit(tree); + return mbv.getUniverse(); + } else { + return null; + } + } +} diff --git a/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/KodkodLexer.tokens b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/KodkodLexer.tokens new file mode 100644 index 00000000..45e96013 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/KodkodLexer.tokens @@ -0,0 +1,148 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +T__7=8 +T__8=9 +T__9=10 +T__10=11 +T__11=12 +T__12=13 +T__13=14 +T__14=15 +T__15=16 +T__16=17 +T__17=18 +T__18=19 +T__19=20 +T__20=21 +T__21=22 +T__22=23 +T__23=24 +T__24=25 +T__25=26 +T__26=27 +T__27=28 +T__28=29 +T__29=30 +T__30=31 +T__31=32 +T__32=33 +T__33=34 +T__34=35 +T__35=36 +T__36=37 +T__37=38 +T__38=39 +T__39=40 +T__40=41 +T__41=42 +T__42=43 +T__43=44 +T__44=45 +T__45=46 +T__46=47 +T__47=48 +T__48=49 +T__49=50 +T__50=51 +T__51=52 +T__52=53 +T__53=54 +T__54=55 +T__55=56 +T__56=57 +T__57=58 +T__58=59 +T__59=60 +T__60=61 +T__61=62 +T__62=63 +T__63=64 +T__64=65 +T__65=66 +T__66=67 +T__67=68 +T__68=69 +T__69=70 +INT=71 +IDENTIFIER=72 +DIGIT=73 +APOSTROPHE=74 +MULTILINE_COMMENT=75 +SINGLELINE_COMMENT=76 +WS=77 +'options'=1 +'{'=2 +','=3 +'}'=4 +'symmetry_breaking'=5 +':'=6 +'bit_width'=7 +'skolem_depth'=8 +'sharing'=9 +'universe'=10 +'['=11 +']'=12 +'relations'=13 +'..'=14 +'('=15 +')'=16 +'no'=17 +'lone'=18 +'one'=19 +'some'=20 +'!'=21 +'not'=22 +'in'=23 +'='=24 +'<'=25 +'<='=26 +'>'=27 +'>='=28 +'sum'=29 +'|'=30 +'acyclic'=31 +'function'=32 +'->'=33 +'ord'=34 +'&&'=35 +'and'=36 +'||'=37 +'or'=38 +'=>'=39 +'if'=40 +'<=>'=41 +'iff'=42 +'all'=43 +'let'=44 +'true'=45 +'false'=46 +'~'=47 +'^'=48 +'*'=49 +'+'=50 +'&'=51 +'-'=52 +'.'=53 +'set'=54 +'++'=55 +'then'=56 +'else'=57 +'iden'=58 +'none'=59 +'univ'=60 +'ints'=61 +'#'=62 +'plus'=63 +'minus'=64 +'mul'=65 +'/'=66 +'div'=67 +'%'=68 +'modulo'=69 +'disj'=70 +'\''=74 diff --git a/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/ModelBuildVisitor.java b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/ModelBuildVisitor.java new file mode 100644 index 00000000..d74fa2ff --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/ModelBuildVisitor.java @@ -0,0 +1,193 @@ +package eu.modelwriter.kodkod.core; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map.Entry; + +import eu.modelwriter.kodkod.core.model.Atom; +import eu.modelwriter.kodkod.core.model.Relation; +import eu.modelwriter.kodkod.core.model.Tuple; +import eu.modelwriter.kodkod.core.model.Universe; +import eu.modelwriter.kodkod.core.recognizer.KodkodBaseVisitor; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.AtomContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.ProblemContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.ProductContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.RelationContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.RelationIdContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.RelationsContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.TupleContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.TupleSetContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.UniverseContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.VarContext; + +public class ModelBuildVisitor extends KodkodBaseVisitor { + + private static Universe universe; + private boolean isLowerBound; + private final HashMap> domainNRange4Rel = + new HashMap>(); + private final HashMap unaryNParent = new HashMap(); + // private final HashMap controlTable = new HashMap(); + + public Universe getUniverse() { + return ModelBuildVisitor.universe; + } + + private void setTypes() { + for (final Entry> entry : this.domainNRange4Rel.entrySet()) { + final Relation[] types = new Relation[2]; + types[0] = ModelBuildVisitor.universe.getRelation(entry.getValue().get(0)); + types[1] = ModelBuildVisitor.universe.getRelation(entry.getValue().get(1)); + final Relation aRelation = ModelBuildVisitor.universe.getRelation(entry.getKey()); + + aRelation.setParent(types[0]); + while (!types[0].getTypes().isEmpty()) { + types[0] = types[0].getTypes().get(0).get(0); + } + + aRelation.addTypes(types); + } + } + + private void setUnaryParents() { + for (final Entry entry : this.unaryNParent.entrySet()) { + ModelBuildVisitor.universe.getRelation(entry.getKey()) + .addTypes(ModelBuildVisitor.universe.getRelation(entry.getValue())); + } + } + + @Override + public Atom visitAtom(final AtomContext ctx) { + final Atom newAtom = + new Atom(ctx.IDENTIFIER() == null ? ctx.INT().getText() : ctx.IDENTIFIER().getText()); + return newAtom; + } + + @Override + public Universe visitProblem(final ProblemContext ctx) { + ModelBuildVisitor.universe = new Universe(); + this.visitUniverse(ctx.universe()); + this.visitRelations(ctx.relations()); + + return ModelBuildVisitor.universe; + } + + @Override + public ArrayList visitProduct(final ProductContext ctx) { + final ArrayList domainNRange = new ArrayList(); + domainNRange.add((String) this.visit(ctx.left)); + domainNRange.add((String) this.visit(ctx.right)); + return domainNRange; + } + + @SuppressWarnings("unchecked") + @Override + public Relation visitRelation(final RelationContext ctx) { + final Relation newRelation = new Relation(this.visitRelationId(ctx.relationId())); + if (ctx.expression() != null) { + if (this.visit(ctx.expression()) instanceof ArrayList) { + this.domainNRange4Rel.put(newRelation.getName(), + (ArrayList) this.visit(ctx.expression())); + } else { + this.unaryNParent.put(newRelation.getName(), (String) this.visit(ctx.expression())); + } + } + + final TupleSetContext lBtupleSet = ctx.lowerBound; + this.isLowerBound = true; + final ArrayList lBTuples = this.visitTupleSet(lBtupleSet); + for (final Tuple tuple : lBTuples) { + newRelation.addTuple(tuple); + } + + final TupleSetContext uBtupleSet = ctx.upperBound; + if (uBtupleSet != null) { + this.isLowerBound = false; + final ArrayList uBTuples = this.visitTupleSet(uBtupleSet); + for (final Tuple tuple : uBTuples) { + newRelation.addTuple(tuple); + } + } + return newRelation; + } + + @Override + public String visitRelationId(final RelationIdContext ctx) { + return ctx.IDENTIFIER().getText(); + } + + @Override + public Universe visitRelations(final RelationsContext ctx) { + // this.controlTable.clear(); + this.domainNRange4Rel.clear(); + this.unaryNParent.clear(); + ModelBuildVisitor.universe.getRelations().clear(); + + for (final RelationContext relationContext : ctx.relation()) { + final Relation newRelation = this.visitRelation(relationContext); + // if (!ModelBuildVisitor.universe.contains(newRelation)) { + ModelBuildVisitor.universe.addRelation(newRelation); + // } else { + // this.controlTable.put(newRelation, true); + // } + } + + this.setUnaryParents(); + this.setTypes(); + + // for (final Relation uncheckedRel : this.controlTable.keySet()) { + // if (this.controlTable.get(uncheckedRel) == null) { + // ModelBuildVisitor.universe.removeRelation(uncheckedRel); + // } else { + // final Relation ourRel = ModelBuildVisitor.universe.getRelation(uncheckedRel.getName()); + // if (!ModelBuildVisitor.universe.fullyEqual(ourRel, uncheckedRel)) { + // ModelBuildVisitor.universe.removeRelation(ourRel); + // ModelBuildVisitor.universe.addRelation(uncheckedRel); + // } + // } + // } + + return ModelBuildVisitor.universe; + } + + @Override + public Tuple visitTuple(final TupleContext ctx) { + final Tuple newTuple = new Tuple(); + final List atom = ctx.atom(); + for (final AtomContext atomContext : atom) { + newTuple.addAtom(this.visitAtom(atomContext)); + } + newTuple.setLowerBound(this.isLowerBound); + return newTuple; + } + + + @Override + public ArrayList visitTupleSet(final TupleSetContext ctx) { + final ArrayList tuples = new ArrayList(); + final List tuple = ctx.tuple(); + for (final TupleContext tupleContext : tuple) { + tuples.add(this.visitTuple(tupleContext)); + } + return tuples; + } + + + @Override + public Universe visitUniverse(final UniverseContext ctx) { + final List atoms = ctx.atom(); + for (final AtomContext atomContext : atoms) { + final Atom visitAtom = this.visitAtom(atomContext); + if (!ModelBuildVisitor.universe.contains(visitAtom)) { + ModelBuildVisitor.universe.addAtom(visitAtom); + } + } + return ModelBuildVisitor.universe; + } + + @Override + public String visitVar(final VarContext ctx) { + return ctx.getText(); + } +} diff --git a/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/model/Atom.java b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/model/Atom.java new file mode 100644 index 00000000..614d5fa1 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/model/Atom.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.core.model; + +import java.io.Serializable; + +public class Atom { + private String text; + private Serializable data; + private String id; + + public Atom(String text) { + this.text = text; + } + + public String getText() { + return this.text; + } + + public Serializable getData() { + return data; + } + + public void setData(Serializable data) { + this.data = data; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + +} diff --git a/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/model/Relation.java b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/model/Relation.java new file mode 100644 index 00000000..1247197d --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/model/Relation.java @@ -0,0 +1,237 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.core.model; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class Relation { + public enum Multiplicity { + ONE, LONE, SOME + } + + private final String name; + private final List tuples; + private final List> types; + private int id; + private Relation parent; + private Multiplicity multiplicity; + private boolean Abstract; + private boolean Private; + private boolean Meta; + private boolean Enum; + + public Relation(final String name) { + this.name = name; + this.tuples = new ArrayList(); + this.types = new ArrayList>(); + this.id = -1; + } + + /** + * @param isLowerBound if added tuple is one of lowerBound tuple then set this parameter true + * @param atoms + */ + public void addAtomWithTuple(final boolean isLowerBound, final Atom... atoms) { + final Tuple tuple = new Tuple(); + tuple.setLowerBound(isLowerBound); + for (final Atom atom : atoms) { + tuple.addAtom(atom); + } + this.addTuple(tuple); + } + + public void addTuple(final Tuple newTuple) { + this.tuples.add(newTuple); + } + + public void addTypes(final Relation... relations) { + final List type = new ArrayList<>(); + + for (final Relation relation : relations) { + type.add(relation); + } + + this.types.add(type); + } + + public boolean contains(final Tuple tuple) { + for (final Tuple t : this.tuples) { + if (t.getText().equals(tuple.getText())) { + return true; + } + } + return false; + } + + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + if (obj == this) { + return true; + } + + return this.getName().equals(((Relation) obj).getName()); + } + + public int getArity() { + if (this.tuples != null && this.tuples.size() != 0) { + return this.tuples.get(0).getArity(); + } + return 0; + } + + public int getId() { + return this.id; + } + + public Multiplicity getMultiplicity() { + return this.multiplicity; + } + + public String getName() { + return this.name; + } + + public Relation getParent() { + return this.parent; + } + + public ArrayList getRelatedTuplesWith(final Atom atom) { + final ArrayList tuples = new ArrayList(); + for (final Tuple tuple : this.tuples) { + if (tuple.contains(atom)) { + tuples.add(tuple); + } + } + return tuples; + } + + public Tuple getTuple(final Atom... atoms) { + final Iterator iterator = this.getTuples().iterator(); + while (iterator.hasNext()) { + boolean found = true; + final Tuple tuple = iterator.next(); + for (int i = 0; i < tuple.getArity(); i++) { + if (!atoms[i].getText().equals(tuple.getAtom(i).getText())) { + found = false; + break; + } + } + if (found) { + return tuple; + } + } + return null; + } + + public Tuple getTuple(final int index) { + return this.tuples.get(index); + } + + public int getTupleCount() { + return this.tuples.size(); + } + + public List getTuples() { + return this.tuples; + } + + public List> getTypes() { + return this.types; + } + + public boolean isAbstract() { + return this.Abstract; + } + + public boolean isEnum() { + return this.Enum; + } + + public boolean isMeta() { + return this.Meta; + } + + public boolean isPrivate() { + return this.Private; + } + + public void removeTuple(final Atom... atoms) { + final Iterator iterator = this.getTuples().iterator(); + while (iterator.hasNext()) { + boolean found = true; + final Tuple tuple = iterator.next(); + for (int i = 0; i < tuple.getArity(); i++) { + if (!atoms[i].getText().equals(tuple.getAtom(i).getText())) { + found = false; + break; + } + } + if (found) { + iterator.remove(); + } + } + } + + public void removeTuple(final Tuple tuple) { + final Iterator iterator = this.getTuples().iterator(); + while (iterator.hasNext()) { + final Tuple tuple2 = iterator.next(); + if (tuple2.equals(tuple)) { + iterator.remove(); + } + } + } + + public void setAbstract(final boolean Abstract) { + this.Abstract = Abstract; + } + + public void setEnum(final boolean Enum) { + this.Enum = Enum; + } + + public void setId(final int id) { + this.id = id; + } + + public void setMeta(final boolean Meta) { + this.Meta = Meta; + } + + public void setMultiplicity(final Multiplicity multiplicity) { + this.multiplicity = multiplicity; + } + + + public void setParent(final Relation parent) { + this.parent = parent; + } + + public void setPrivate(final boolean Private) { + this.Private = Private; + } + + @Override + public String toString() { + String ts = ""; + for (final Tuple tuple : this.tuples) { + ts += tuple.toString() + " "; + } + return this.name + "={" + ts + "};"; + } + + +} diff --git a/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/model/Tuple.java b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/model/Tuple.java new file mode 100644 index 00000000..37d34b64 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/model/Tuple.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.core.model; + +import java.util.ArrayList; + +public class Tuple { + private String text; + private final ArrayList atoms; + private int arity; + private boolean isLowerBound; + + public Tuple() { + this.atoms = new ArrayList(); + this.arity = 0; + } + + public Tuple(final String text) { + this.text = text; + this.atoms = new ArrayList(); + this.arity = 0; + } + + public void addAtom(final Atom newAtom) { + this.atoms.add(newAtom); + this.arity++; + } + + public boolean contains(final Atom atom) { + for (final Atom a : this.atoms) { + if (a.getText().equals(atom.getText())) { + return true; + } + } + return false; + } + + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + if (obj == this) { + return true; + } + + if (obj instanceof Tuple) { + final ArrayList otherAtoms = ((Tuple) obj).atoms; + final ArrayList atoms = this.atoms; + if (otherAtoms.size() != atoms.size()) { + return false; + } + for (int i = 0; i < atoms.size(); i++) { + if (!atoms.get(i).getText().equals(otherAtoms.get(i).getText())) { + return false; + } + } + } + return true; + } + + public int getArity() { + return this.arity; + } + + public Atom getAtom(final int index) { + return this.atoms.get(index); + } + + public int getAtomCount() { + return this.atoms.size(); + } + + public ArrayList getAtoms() { + return this.atoms; + } + + public String getText() { + return this.text; + } + + public boolean isLowerBound() { + return this.isLowerBound; + } + + public void setLowerBound(final boolean isLowerBound) { + this.isLowerBound = isLowerBound; + } + + @Override + public String toString() { + String result = "["; + for (int i = 0; i < this.atoms.size(); i++) { + if (i == 0) { + result += this.atoms.get(i).getText(); + } else { + result += "," + this.atoms.get(i).getText(); + } + } + result += "]"; + + return result; + } +} diff --git a/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/model/Universe.java b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/model/Universe.java new file mode 100644 index 00000000..e562e402 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/model/Universe.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.core.model; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class Universe { + private final ArrayList atoms; + private final ArrayList relations; + + public Universe() { + this.atoms = new ArrayList(); + this.relations = new ArrayList(); + } + + public void addAtom(final Atom newAtom) { + this.atoms.add(newAtom); + } + + public void addRelation(final Relation newRelation) { + this.relations.add(newRelation); + } + + public boolean contains(final Atom atom) { + for (final Atom a : this.atoms) { + if (a.getText().equals(atom.getText())) { + return true; + } + } + return false; + } + + public boolean contains(final Relation relation) { + for (final Relation r : this.relations) { + if (r.getName().equals(relation.getName())) { + return true; + } + } + return false; + } + + public boolean fullyEqual(final Relation rel1, final Relation rel2) { + if (!rel1.getName().equals(rel2.getName())) { + return false; + } + + final List tuples1 = rel1.getTuples(); + final List tuples2 = rel2.getTuples(); + if (tuples1.size() != tuples2.size()) { + return false; + } + for (int i = 0; i < tuples1.size(); i++) { + if (!tuples1.get(i).equals(tuples2.get(i))) { + return false; + } + } + + // final List> types1 = rel1.getTypes(); + // final List> types2 = rel2.getTypes(); + // if (types1.size() != types2.size()) { + // return false; + // } + // for (int i = 0; i < types1.size(); i++) { + // if (!types1.get(i).equals(types2.get(i))) { + // return false; + // } + // + // final List list1 = types1.get(i); + // final List list2 = types2.get(i); + // if (list1.size() != list2.size()) { + // return false; + // } + // for (int j = 0; j < list1.size(); j++) { + // if (!list1.get(i).equals(list2.get(i))) { + // return false; + // } + // } + // } + return true; + } + + public Atom getAtom(final String name) { + for (final Atom atom : this.getAtoms()) { + if (atom.getText().equals(name)) { + return atom; + } + } + return null; + } + + public ArrayList getAtoms() { + return this.atoms; + } + + public String getFirstAtomText() { + return this.atoms.get(0).getText(); + } + + public String getNextAtomText(final String current) { + for (int i = 0; i < this.atoms.size(); i++) { + if (this.atoms.get(i).getText().equals(current) && i + 1 < this.atoms.size()) { + return this.atoms.get(i + 1).getText(); + } + } + return null; + } + + public Relation getRelation(final String relationName) { + for (final Relation relation : this.relations) { + if (relation.getName().equals(relationName)) { + return relation; + } + } + return null; + } + + public ArrayList getRelations() { + return this.relations; + } + + public void removeRelation(final Relation relation) { + for (@SuppressWarnings("rawtypes") + final Iterator iterator = this.relations.iterator(); iterator.hasNext();) { + final Relation iterRel = (Relation) iterator.next(); + if (iterRel.equals(relation)) { + iterator.remove(); + } + } + } +} diff --git a/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/printer/NotifyPrinter.java b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/printer/NotifyPrinter.java new file mode 100644 index 00000000..f58c3cf1 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/printer/NotifyPrinter.java @@ -0,0 +1,308 @@ +package eu.modelwriter.kodkod.core.printer; + +import java.util.Iterator; +import java.util.List; + +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.CommonTokenStream; + +import eu.modelwriter.kodkod.core.recognizer.KodkodLexer; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.AtomContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.ProblemContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.RelationContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.RelationsContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.TupleContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.TupleSetContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.UniverseContext; + +public class NotifyPrinter extends PrettyPrinter { + enum PRINT_MODE { + PRINT_MODEL, ADD_TUPLE, REMOVE_TUPLE, MOVE_TO_UPPER, MOVE_TO_LOWER; + static String relationName = null; + static String inRelationName = null; + static List tuple = null; + static String bound = null; + } + + String problem = ""; + PRINT_MODE CURRENT_MODE = PRINT_MODE.PRINT_MODEL; + String currentRelationName; + String currentBound; + KodkodParser parser; + + public NotifyPrinter(final String kodkodString) { + this.parser = this.getParser(kodkodString); + } + + public String addTuple(final String relationName, final String inRelationName, + final List tuple, final String bound) { + this.print(PRINT_MODE.ADD_TUPLE, relationName, inRelationName, tuple, bound); + return this.problem; + } + + KodkodParser getParser(final String kodkodString) { + final ANTLRInputStream input = new ANTLRInputStream(kodkodString); + final KodkodLexer lexer = new KodkodLexer(input); + final CommonTokenStream tokens = new CommonTokenStream(lexer); + return new KodkodParser(tokens); + } + + String getStandartTupleSetString(final List tuples) { + String tupleSetString = ""; + if (tuples.size() > 0) { + TupleContext tupleContext = tuples.get(0); + if (tupleContext != null) { + tupleSetString += "\t\t" + this.visitTuple(tupleContext); + } + + for (int i = 1; i < tuples.size(); i++) { + tupleContext = tuples.get(i); + tupleSetString += ",\n\t\t" + this.visitTuple(tupleContext); + } + } + return tupleSetString; + } + + String makeTupleString(final List atoms) { + String tupleString = ""; + tupleString += "["; + + final String atom = atoms.get(0); + if (atom != null) { + tupleString += atom; + } + + for (int i = 1; i < atoms.size(); i++) { + tupleString += ", " + atoms.get(i); + } + + tupleString += "]"; + return tupleString; + } + + public String moveToLower(final String relationName, final String inRelationName, + final List tuple) { + this.print(PRINT_MODE.MOVE_TO_LOWER, relationName, inRelationName, tuple, null); + return this.problem; + } + + public String moveToUpper(final String relationName, final String inRelationName, + final List tuple) { + this.print(PRINT_MODE.MOVE_TO_UPPER, relationName, inRelationName, tuple, null); + return this.problem; + } + + private void print(final PRINT_MODE MODE, final String relationName, final String inRelationName, + final List tuple, final String bound) { + this.CURRENT_MODE = MODE; + PRINT_MODE.relationName = relationName; + PRINT_MODE.inRelationName = inRelationName; + PRINT_MODE.tuple = tuple; + PRINT_MODE.bound = bound; + this.visit(this.parser.problem()); // Buraya bir sey gelecek ?? + } + + public String removeTuple(final String relationName, final String inRelationName, + final List tuple, final String bound) { + this.print(PRINT_MODE.REMOVE_TUPLE, relationName, inRelationName, tuple, bound); + return this.problem; + } + + List removeTupleContextFromList(final List tuples) { + final Iterator iterator = tuples.iterator(); + TupleContext tupleContext; + + while (iterator.hasNext()) { + tupleContext = iterator.next(); + final List atoms = tupleContext.atom(); + boolean trueTuple = true; + for (int i = 0; i < atoms.size(); i++) { + final AtomContext atomContext = atoms.get(i); + final String atomContextString = atomContext.INT() == null + ? atomContext.IDENTIFIER().getText() : atomContext.INT().getText(); + if (!atomContextString.equals(PRINT_MODE.tuple.get(i))) { + trueTuple = false; + } + } + if (trueTuple) { + iterator.remove(); + break; + } + } + return tuples; + } + + @Override + public String visitProblem(final ProblemContext ctx) { + this.problem += "universe {\n"; + if (ctx.universe() != null) { + this.problem += this.visitUniverse(ctx.universe()); + } + this.problem += "\n}\n\n"; + + this.visitRelations(ctx.relations()); + + return this.problem; + } + + @Override + public String visitRelation(final RelationContext ctx) { + String relationsString = ""; + this.currentRelationName = ctx.relationId().getText(); + relationsString += "\t" + this.currentRelationName; + relationsString += " " + this.visitArity(ctx.arity()) + ": "; + relationsString += ctx.expression() == null ? "" : this.visit(ctx.expression()); + relationsString += "["; + + this.currentBound = "lower"; + TupleSetContext lowerBoundTupleSet = ctx.tupleSet(0); + if (lowerBoundTupleSet == null) { + lowerBoundTupleSet = new TupleSetContext(ctx, ctx.invokingState); + ctx.tupleSet().add(lowerBoundTupleSet); + } + relationsString += this.visitTupleSet(lowerBoundTupleSet); + + this.currentBound = "upper"; + TupleSetContext upperBoundTupleSet = ctx.tupleSet(1); + if (upperBoundTupleSet == null && (PRINT_MODE.relationName.equals(this.currentRelationName) + || PRINT_MODE.inRelationName != null + && PRINT_MODE.inRelationName.equals(this.currentRelationName))) { + switch (this.CURRENT_MODE) { + case MOVE_TO_UPPER: + upperBoundTupleSet = ctx.tupleSet(0); + break; + case ADD_TUPLE: + case REMOVE_TUPLE: + if (PRINT_MODE.bound.equals("upper")) { + upperBoundTupleSet = ctx.tupleSet(0); + } + break; + default: + break; + } + } + if (upperBoundTupleSet != null) { + relationsString += "," + this.visitTupleSet(upperBoundTupleSet); + } + + relationsString += "]"; + return relationsString; + + } + + @Override + public String visitRelations(final RelationsContext ctx) { + this.problem += "relations {\n"; + if (ctx.relation() != null) { + for (final RelationContext relation : ctx.relation()) { + this.problem += this.visitRelation(relation) + "\n"; + } + } + this.problem += "}"; + + return this.problem; + } + + @Override + public String visitTupleSet(final TupleSetContext ctx) { + String tupleSetString = ""; + tupleSetString += "{\n"; + + List tuples = ctx.tuple(); + + boolean OK = false; + switch (this.CURRENT_MODE) { + case ADD_TUPLE: + tupleSetString += this.getStandartTupleSetString(tuples); + + if (PRINT_MODE.relationName.equals(this.currentRelationName) + || PRINT_MODE.inRelationName != null + && PRINT_MODE.inRelationName.equals(this.currentRelationName)) { + final String tupleString = this.makeTupleString(PRINT_MODE.tuple); + if (PRINT_MODE.bound.equals("lower")) { + OK = true; + } else if (this.currentBound.equals("upper")) { + OK = true; + } + if (OK) { + if (tuples.size() < 1) { + tupleSetString += "\t\t" + tupleString; + } else { + tupleSetString += ",\n\t\t" + tupleString; + } + } + } + break; + case REMOVE_TUPLE: + if (PRINT_MODE.relationName.equals(this.currentRelationName) + || PRINT_MODE.inRelationName != null + && PRINT_MODE.inRelationName.equals(this.currentRelationName)) { + if (PRINT_MODE.bound.equals("lower")) { + OK = true; + } else if (this.currentBound.equals("upper")) { + OK = true; + } + if (OK) { + tuples = this.removeTupleContextFromList(tuples); + } + } + tupleSetString += this.getStandartTupleSetString(tuples); + break; + case MOVE_TO_LOWER: + tupleSetString += this.getStandartTupleSetString(tuples); + if (PRINT_MODE.relationName.equals(this.currentRelationName) + || PRINT_MODE.inRelationName != null + && PRINT_MODE.inRelationName.equals(this.currentRelationName)) { + if (this.currentBound.equals("lower")) { + final String tupleString = this.makeTupleString(PRINT_MODE.tuple); + if (tuples.size() < 1) { + tupleSetString += "\t\t" + tupleString; + } else { + tupleSetString += ",\n\t\t" + tupleString; + } + } + } + break; + case MOVE_TO_UPPER: + if (this.currentBound.equals("lower")) { + if (PRINT_MODE.relationName.equals(this.currentRelationName) + || PRINT_MODE.inRelationName != null + && PRINT_MODE.inRelationName.equals(this.currentRelationName)) { + tuples = this.removeTupleContextFromList(tuples); + } + tupleSetString += this.getStandartTupleSetString(tuples); + } else if (this.currentBound.equals("upper")) { + tupleSetString += this.getStandartTupleSetString(tuples); + } + break; + default: + tupleSetString += this.getStandartTupleSetString(tuples); + break; + } + + tupleSetString += "\n\t}"; + return tupleSetString; + } + + @Override + public String visitUniverse(final UniverseContext ctx) { + String universeString = ""; + AtomContext atomContext = ctx.atom(0); + if (atomContext != null) { + universeString += "\t" + this.visitAtom(atomContext); + } + for (int i = 1; i < ctx.atom().size(); i++) { + atomContext = ctx.atom(i); + universeString += ", " + this.visitAtom(atomContext); + } + if (this.CURRENT_MODE == PRINT_MODE.ADD_TUPLE && PRINT_MODE.tuple.size() == 1) { + if (ctx.atom().size() < 1) { + universeString += "\t" + PRINT_MODE.tuple.get(0); + } else { + universeString += ", " + PRINT_MODE.tuple.get(0); + } + } + return universeString; + } +} diff --git a/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/printer/PrettyPrinter.java b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/printer/PrettyPrinter.java new file mode 100644 index 00000000..354e375e --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/printer/PrettyPrinter.java @@ -0,0 +1,259 @@ +package eu.modelwriter.kodkod.core.printer; + +import java.util.List; + +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.RuleNode; +import org.antlr.v4.runtime.tree.TerminalNode; + +import eu.modelwriter.kodkod.core.recognizer.KodkodBaseVisitor; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.ArityContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.AtomContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.BitWidthContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.FormulaContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.IntegerContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.OptionContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.OptionsContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.ProblemContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.RelationContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.RelationIdContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.RelationsContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.SharingContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.SkolemDepthContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.SymmetryBreakingContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.TupleContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.TupleSetContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.UniverseContext; +import eu.modelwriter.kodkod.core.recognizer.KodkodParser.VariableIdContext; + +public class PrettyPrinter extends KodkodBaseVisitor { + private String problem; + + @Override + public String visitArity(final ArityContext ctx) { + return ctx != null ? ctx.INT().getText() : ""; + } + + @Override + public String visitAtom(final AtomContext ctx) { + return ctx.IDENTIFIER() == null ? ctx.INT().getText() : ctx.IDENTIFIER().getText(); + } + + @Override + public String visitChildren(final RuleNode arg0) { + String visitString = ""; + for (int i = 0; i < arg0.getChildCount(); i++) { + visitString += this.visit(arg0.getChild(i)); + } + return visitString; + } + + @Override + public String visitInteger(final IntegerContext ctx) { + return ctx != null ? ctx.INT().getText() : ""; + } + + @Override + public String visitOptions(final OptionsContext ctx) { + String optionsString = ""; + final List options = ctx.option(); + OptionContext optionContext = options.get(0); + if (optionContext != null) { + if (optionContext instanceof SymmetryBreakingContext) { + optionsString += "\t" + "symmetry_breaking: " + + ((SymmetryBreakingContext) optionContext).integer().getText(); + } else if (optionContext instanceof BitWidthContext) { + optionsString += + "\t" + "bit_width: " + ((BitWidthContext) optionContext).integer().getText(); + } else if (optionContext instanceof SkolemDepthContext) { + optionsString += + "\t" + "skolem_depth: " + ((SkolemDepthContext) optionContext).integer().getText(); + } else if (optionContext instanceof SharingContext) { + optionsString += "\t" + "sharing: " + ((SharingContext) optionContext).integer().getText(); + } + } + + for (int i = 1; i < options.size(); i++) { + optionContext = options.get(i); + if (optionContext instanceof SymmetryBreakingContext) { + optionsString += ",\n\t" + "symmetry_breaking: " + + ((SymmetryBreakingContext) optionContext).integer().getText(); + } else if (optionContext instanceof BitWidthContext) { + optionsString += + ",\n\t" + "bit_width: " + ((BitWidthContext) optionContext).integer().getText(); + } else if (optionContext instanceof SkolemDepthContext) { + optionsString += + ",\n\t" + "skolem_depth: " + ((SkolemDepthContext) optionContext).integer().getText(); + } else if (optionContext instanceof SharingContext) { + optionsString += + ",\n\t" + "sharing: " + ((SharingContext) optionContext).integer().getText(); + } + } + return optionsString; + } + + @Override + public String visitProblem(final ProblemContext ctx) { + if (ctx.options() != null) { + this.problem += "options {\n"; + this.problem += this.visitOptions(ctx.options()); + this.problem += "\n}\n\n"; + } + + this.problem += "universe {\n"; + if (ctx.universe() != null) { + this.problem += this.visitUniverse(ctx.universe()); + } + this.problem += "\n}\n\n"; + + this.visitRelations(ctx.relations()); + + if (ctx.formula() != null) { + for (final FormulaContext formula : ctx.formula()) { + this.problem += this.visit(formula) + "\n"; + } + } + return this.problem; + } + + @Override + public String visitRelation(final RelationContext ctx) { + String relationsString = ""; + relationsString += "\t" + ctx.relationId().getText(); + relationsString += " " + this.visitArity(ctx.arity()) + ": "; + relationsString += ctx.expression() == null ? "" : this.visit(ctx.expression()); + relationsString += "["; + + TupleSetContext lowerBoundTupleSet = ctx.tupleSet(0); + if (lowerBoundTupleSet == null) { + lowerBoundTupleSet = new TupleSetContext(ctx, ctx.invokingState); + ctx.tupleSet().add(lowerBoundTupleSet); + } + relationsString += this.visitTupleSet(lowerBoundTupleSet); + + final TupleSetContext upperBoundTupleSet = ctx.tupleSet(1); + if (upperBoundTupleSet != null) { + relationsString += "," + this.visitTupleSet(upperBoundTupleSet); + } + + relationsString += "]"; + return relationsString; + } + + @Override + public String visitRelationId(final RelationIdContext ctx) { + return ctx != null ? ctx.IDENTIFIER().getText() : ""; + } + + @Override + public String visitRelations(final RelationsContext ctx) { + this.problem += "relations {\n"; + if (ctx.relation() != null) { + for (final RelationContext relation : ctx.relation()) { + this.problem += this.visitRelation(relation) + "\n"; + } + } + this.problem += "}"; + + return this.problem; + } + + @Override + public String visitTerminal(final TerminalNode node) { + String nodeText = node == null ? "" : node.getText(); + switch (nodeText) { + case "[": + case "{": + case "(": + case "!": + case "~": + case "^": + case "*": + case ".": + case "]": + case "}": + case ")": + break; + case ",": + case ":": + case "|": + nodeText = nodeText + " "; + break; + case "#": + nodeText = " " + nodeText; + break; + default: + final ParseTree parent = node.getParent(); + for (int i = 0; i < parent.getChildCount(); i++) { + final ParseTree child = parent.getChild(i); + if (child.getText().equals(node.getText())) { + if (parent.getChild(i + 1) instanceof TerminalNode) { + nodeText = i == 0 ? "" + nodeText : " " + nodeText; + } else { + nodeText = i == 0 ? "" + nodeText + " " : " " + nodeText + " "; + } + break; + } + } + break; + } + return nodeText; + } + + @Override + public String visitTuple(final TupleContext ctx) { + String tupleString = ""; + tupleString += "["; + + AtomContext atomContext = ctx.atom(0); + if (atomContext != null) { + tupleString += this.visitAtom(atomContext); + } + + for (int i = 1; i < ctx.atom().size(); i++) { + atomContext = ctx.atom(i); + tupleString += ", " + this.visitAtom(atomContext); + } + + tupleString += "]"; + return tupleString; + } + + @Override + public String visitTupleSet(final TupleSetContext ctx) { + String tupleSetString = ""; + tupleSetString += "{\n"; + + TupleContext tupleContext = ctx.tuple(0); + if (tupleContext != null) { + tupleSetString += "\t\t" + this.visitTuple(tupleContext); + } + + for (int i = 1; i < ctx.tuple().size(); i++) { + tupleContext = ctx.tuple(i); + tupleSetString += ",\n\t\t" + this.visitTuple(tupleContext); + } + + tupleSetString += "\n\t}"; + return tupleSetString; + } + + @Override + public String visitUniverse(final UniverseContext ctx) { + String universeString = ""; + AtomContext atomContext = ctx.atom(0); + if (atomContext != null) { + universeString += "\t" + this.visitAtom(atomContext); + } + for (int i = 1; i < ctx.atom().size(); i++) { + atomContext = ctx.atom(i); + universeString += ", " + this.visitAtom(atomContext); + } + return universeString; + } + + @Override + public String visitVariableId(final VariableIdContext ctx) { + return ctx != null ? ctx.IDENTIFIER().getText() : ""; + } +} diff --git a/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/Kodkod.g4 b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/Kodkod.g4 new file mode 100644 index 00000000..9b04a0aa --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/Kodkod.g4 @@ -0,0 +1,300 @@ +grammar Kodkod; + +@parser::header {} + +@parser::members { + public java.util.Stack declarations = new java.util.Stack(); + public java.util.List atoms = new java.util.ArrayList(); + public java.util.List formulas = new java.util.ArrayList(); + public java.util.Map relations = new java.util.HashMap(); + public kodkod.instance.Universe universe = null; + public kodkod.instance.Bounds bounds = null; + + private boolean isRelation() { return this.relations.containsKey(getCurrentToken().getText()); } + private String getLocation() { return "["+ getCurrentToken().getLine()+ ","+ getCurrentToken().getCharPositionInLine()+ "]";} + private String context = null; + private int declareVariables(java.util.List vars, int var) { + System.out.println("Quantifier context: "); + for (VariableContext vc : vars) { + String s = vc.getText(); declarations.add(s); var++; System.out.println(s); + } + return var; + } +} + +problem: options? universe {System.out.println(universe);} 'Relations' '{' relations* {System.out.println(bounds);} '}' formulas+=formula* {} { + System.out.println("declarations= "+declarations); + declarations.clear(); +}; + +options: 'options' '{' option (',' option) '}'; + +option: 'symmetry_breaking' ':' integer #symmetryBreaking + | 'bit_width' ':' integer #bitWidth + | 'skolem_depth' ':' integer #skolemDepth + | 'sharing' ':' integer #sharing +; + +universe +@init{context="universe";} +:( 'universe' ('{' (atoms+=atom (',' atoms+=atom)*)'}') | ('[' (atoms+=atom (',' atoms+=atom)*) ']') ){ + System.out.println("universe:"); + for (AtomContext atom : $atoms) { + String s = atom.getText(); System.out.println(s); + if (atoms.contains(s)) {System.err.println("duplicated atom found: '"+ s + "' at "+ getLocation());} + else {atoms.add(s);} + } + this.universe = new kodkod.instance.Universe(this.atoms); + this.bounds = new kodkod.instance.Bounds(this.universe); + context = null; +}; + +relations +@init{context="relations";} +: (relation arity? ':' type? '[' (lowerBound = tupleSet (',' upperBound = tupleSet)?) ']') { + String name = $relation.text; + System.out.println("relation " + name); + if (relations.containsKey(name)) {System.err.println("duplicated relation found: '"+ name + "' at "+ getLocation());} + + kodkod.ast.Relation relation = null; + int arity = 0; + if ($arity.text != null && !$arity.text.isEmpty()) {arity = Integer.parseInt($arity.text);} + + kodkod.instance.TupleSet lowerBound = null; + java.util.List tuplesInLowerBound = new java.util.ArrayList(); + if ($lowerBound.ctx != null && !$lowerBound.ctx.tuples.isEmpty()){ + if (arity == 0) {arity = $lowerBound.ctx.tuples.get(0).atoms.size();} + for (TupleContext tuple : $lowerBound.ctx.tuples) { + java.util.List atoms = new java.util.ArrayList(); + for (AtomContext atom : tuple.atoms) { + atoms.add(atom.getText()); + } + tuplesInLowerBound.add(this.universe.factory().tuple(atoms)); + } + lowerBound = this.universe.factory().setOf(tuplesInLowerBound); + System.out.println("lb: " +lowerBound); + } + + kodkod.instance.TupleSet upperBound = null; + java.util.List tuplesInUpperBound = new java.util.ArrayList(); + if ($upperBound.ctx != null && !$upperBound.ctx.tuples.isEmpty()){ + if (lowerBound == null && arity == 0) {arity = $upperBound.ctx.tuples.get(0).atoms.size();} + for (TupleContext tuple : $upperBound.ctx.tuples) { + java.util.List atoms = new java.util.ArrayList(); + for (AtomContext atom : tuple.atoms) { + atoms.add(atom.getText()); + } + tuplesInUpperBound.add(this.universe.factory().tuple(atoms)); + } + upperBound = this.universe.factory().setOf(tuplesInUpperBound); + System.out.println("up: " +upperBound); + } + + if (lowerBound == null && upperBound == null && arity == 0) {arity = 1;} + + if (lowerBound == null) {lowerBound = this.universe.factory().noneOf(arity);} + + System.out.println(arity); + if (arity == 0) { + System.err.println("0 arity is detected on relation: '"+ name + "' at "+ getLocation()); + } else if (arity > 0) { + relation = kodkod.ast.Relation.nary(name, arity); + } + + if (upperBound == null) {this.bounds.boundExactly(relation, lowerBound);} + else {this.bounds.bound(relation, lowerBound, upperBound);} + this.relations.put(name, relation); +}; + +type: left=type leftMult=('set' | 'one' | 'lone' | 'some')? '->' rightMult=('set' | 'one' | 'lone' | 'some')? right=type #cartesianProduct + | left=type op=('+' | '&' | '-') right=type #setOperationsOnTypes + | '(' type ')' #nestedMultiplicity + | relation #set +; + +tupleSet: '{' (tuples+=tuple (',' tuples+=tuple)*)? '}' + | '[' (tuples+=tuple (',' tuples+=tuple)*)? ']' + | '{' left=tuple range='..' right=tuple '}' + | '[' left=tuple range='..' right=tuple ']' + | '{' left=relation range='->' right=relation '}' + | '[' left=relation range='->' right=relation ']' + ; + +tuple: '(' atoms+=atom (',' atoms+=atom)* ')' | '[' atoms+=atom (',' atoms+=atom)* ']'; +// The +, -, and & operators denote the union, difference, and intersection of two tuple sets, respectively. +// The -> operator denotes the Cartesian product of two tuple sets. car :2 [ none, { rel1a -> rel1b } ] +// Tuple sets can be specified exhaustively by listing all their tuples. 'none' is a synonym for '{}'. +// If all the tuples have consecutive indices, the range operator .. can be used. car :2 [ none, {(A1, A2) .. (A3, A4)} ] + +atom: id=IDENTIFIER { + if (context != null && !context.isEmpty() && !context.equals("universe")) { + System.out.print("atom found: " + $id.text + "-> "); + if ( atoms.contains($id.text) ) {System.out.println("defined");} + else {System.err.println("undefined atom found: '" +$id.text + "' at " + getLocation());} + } +} | INT ; +relation: IDENTIFIER; +variable: IDENTIFIER; +integer: INT; +arity: INT; //positive integer + +/* +All binary operators associate to the left, with the exception of implication, which associates to the right. +So, for example, p => q => r is parsed as p => (q => r), and a.b.c is parsed as (a.b).c. +*/ + +//Decls, Expression, Formula, IntExpression: kodkod.ast.Node +formula locals [int var = 0;]: + 'no' expression #no //Formula f = expr.no() --Returns the formula 'no expr'. + | 'lone' expression #lone //Formula f = expr.lone() --Returns the formula 'lone expr'. + | 'one' expression #one //Formula f = expr.one() --Returns the formula 'one expr'. + | 'some' expression #some //Formula f = expr.some() --Returns the formula 'some expr'. + + //Set Operators: These operators can be applied to any pair of relations so long as they have the same arity. + | left=expression not=('!' | 'not')? 'in' right=expression #in //Formula f = left.in(right) --Returns the formula 'left in right' (subset). + | left=expression not=('!' | 'not')? '=' right=expression #equal //Formula f = left.eq(right) --Returns the formula 'left = right' (equal). + + //Integer Comparison Operators + | left=intexpression not=('!' | 'not')? '=' right=intexpression #eq //Formula f= left.eq(right) --Returns a formula stating that the given int expression and left have the same value. + | left=intexpression not=('!' | 'not')? '<' right=intexpression #lt //Formula f= left.lt(right) --Returns a formula stating that the value of this int expression is less than the value of the given int expression. + | left=intexpression not=('!' | 'not')? '<=' right=intexpression #lte //Formula f= left.lte(right)--Returns a formula stating that the value of this int expression is less than or equal to the value of the given int expression. + | left=intexpression not=('!' | 'not')? '>' right=intexpression #gt //Formula f= left.qt(right) --Returns a formula stating that the value of this int expression is greater than the value of the given int expression. + | left=intexpression not=('!' | 'not')? '>=' right=intexpression #gte //Formula f= left.qte(right)--Returns a formula stating that the value of this int expression is greater than or equal to the value of the given int expression + + | {$formula::var = 0;}('sum' decls '|' intexpression) + {for (int i = 0; i < $formula::var; i++) declarations.pop();} #sumDeclaration //IntExpression iexpr = sum(Decls decls); + + | 'acyclic' '[' relation ']' #acyclic // + | 'function' '[' rel=relation ':' domain=expression '->' op=('one' | 'lone') range=expression ']' #function //Relation rel; Formula f = rel.function(domain, range); Formula f = rel.partialFunction(domain, range); --Returns a formula stating that this relation is a total function or partial function with the specified domain and range. + | 'ord' '[' rel=relation ',' ordered=relation ',' first=relation ',' last=relation ']' #totalOrder //Relation rel; Formula f = rel.totalOrder(Relation ordered, Relation first, Relation last) --Returns a formula stating that this relation imposes a total ordering over the atoms in the set ordered, and that thet first and last elements in the ordering are given by the relations first and last. + + //Logical Operators + //NotFormula + | op=('!' | 'not') formula #not //Formula f = formula.not() --Returns the negation of this formula. + + //BinaryFormula (AND, IFF, IMPLIES, OR) + | left=formula op=('&&' | 'and' ) right=formula #and //Formula f = left.and(right) --Returns the conjunction of left and the specified formula. + | left=formula op=('||' | 'or' ) right=formula #or //Formula f = left.or(right) --Returns the disjunction of left and the specified formula + | left=formula op=('=>' | 'if' ) right=formula #implies //Formula f = left.implies(right) --Returns the implication of the specified formula by left. + | left=formula op=('<=>' | 'iff') right=formula #iff //Formula f = left.iff(right) --Returns a formula that equates left and the specified formula. + + | {$formula::var = 0;}('all' decls ('|' (formula | '{' formula* '}' ) | '{' formula* '}')) + {for (int i = 0; i < $formula::var; i++) declarations.pop();} #forAll //Formula f = formula.forAll(decls) --Returns a formula that represents a universal quantification of this formula over the given declarations + | {$formula::var = 0;}('some' decls ('|' (formula | '{' formula* '}' ) | '{' formula* '}')) + {for (int i = 0; i < $formula::var; i++) declarations.pop();} #forSome //Formula f = formula.forSome(decls) --Returns a formula that represents an existential quantification of this formula over the given declarations. + | {$formula::var = 0;}('no' decls ('|' (formula | '{' formula* '}' ) | '{' formula* '}')) + {for (int i = 0; i < $formula::var; i++) declarations.pop();} #forNo //no x: e | F is true when F is true for no bindings of the variable x. + | {$formula::var = 0;}('one' decls ('|' (formula | '{' formula* '}' ) | '{' formula* '}')) + {for (int i = 0; i < $formula::var; i++) declarations.pop();} #forOne //one x: e | F is true when F is true for exactly one binding of the variable x. (unique existential quantification) + | {$formula::var = 0;}('lone' decls ('|' (formula | '{' formula* '}' ) | '{' formula* '}')) + {for (int i = 0; i < $formula::var; i++) declarations.pop();} #forLone //lone x: e | F is true when F is true for at most one binding of the variable x. + + | {$formula::var = 0;}('let' letDecls ('|' (formula | '{' formula* '}' ) | '{' formula* '}')) + {for (int i = 0; i < $formula::var; i++) declarations.pop();} #let + + //Constant Formulas + | 'true' #true //Formula f = Formula.FALSE --Constant formula false + | 'false' #false //Formula f = Formula.TRUE --Constant formula true + + | '(' formula ')' #f_paranthesis +; + +/* +**For the set theoretic operations (union, difference, and intersection) and for relational override, +the arguments are required to have the same arity. +*/ +expression: + {!isRelation()}? variable { + System.out.print("variable found: " + $variable.text + "-> "); + String s = $variable.text; + if ( declarations.contains(s) ) {System.out.println("defined");} + else {System.err.println("undefined variable found: '"+ s + "' at "+ getLocation());} + } #var //ConstantExpression, Relation, Variable + | {isRelation()}? relation #rel + + + // Relational Operators + // **These expressions are required to be binary + | '~' expression #transpose //Expression: expr.transpose() --Returns the transpose of expr. + | '^' expression #closure //Expression: expr.closure() --Returns the transitive closure of expr. + | '*' expression #reflexive //Expression: expr.reflexiveClosure()--Returns the reflexive transitive closure of expr. + + // Set theoretic operations: + // **These operators can be applied to any pair of relations so long as they have the same arity. + | left=expression '+' right=expression #union //Expression: left.union(right) --Returns the union of left and the specified expression. + | left=expression '&' right=expression #intersection //Expression: left.intersection(right) --Returns the intersection of left and the specified expression. + | left=expression '-' right=expression #difference //Expression: left.difference(right) --Returns the difference of left and the specified expression. + + //Relational Operators + | left=expression '.' right=expression #join //Expression expr = left.join(right) --Returns the join of left and the specified expression. + | right=expression '[' left=expression ']' #boxjoin //Expression expr = left.join(right) --e1[e2] = e2.e1 -- + | left=expression '->' right=expression #product //Expression expr = left.product(right) --Returns the product of left and the specified expression + | left=expression '++' right=expression #override //Expression expr = left.override(right) --Returns the relational override of left with the specified expression. + + //A comprehension expression, e.g. { a: A, b: B | a.r = b } + //Comprehensions make relations from properties + //{x1: e1, x2: e2, … | F} The relation obtained by taking all tuples x1 -> x2 -> … + // in which x1 is drawn from the set e1, x2 is drawn from the set e2, and so on, + // and for which the constraint F holds. The expressions e1, e2, and so on, must be unary, + // and may not be prefixed by (or contain) multiplicity keywords + //all d: decls.decls[int] | decl.variable.arity = 1 and decl.multiplicity = ONE + | {$formula::var = 0;}('{' comprehensionDecls '|' formula '}') + {for (int i = 0; i < $formula::var; i++) declarations.pop();} #comprehension //Expression f = formula.comprehension(Decls decls) //Returns the comprehension expression constructed from this formula and the given declarations. + + | op=('=>' | 'if') condition=formula 'then' thenExpr=expression 'else' elseExpr=expression #ifExpression + + //Constants + | 'iden' #iden //Expression expr = Expression.IDEN --The identity relation: maps all atoms in a universe of discourse to themselves. + | 'none' #none //Expression expr = Expression.NONE --The empty relation: contains no atoms. + | 'univ' #univ //Expression expr = Expression.UNIV --The universal relation: contains all atoms in a universe of discourse. + | 'ints' #ints //Expression expr = Expression.INTS --The integer relation: contains all atoms bound to integers + + | '(' expression ')' #e_paranthesis +; + +intexpression: + op=('=>' | 'if') condition=formula 'then' thenExpr=intexpression 'else' elseExpr=intexpression #ifIntExpression + | 'sum' expression #sum //IntExpression iexpr = exp.sum(); --Returns the sum of the integer atoms in this expression. + | '#' expression #count //IntExpression iexpr = exp.count(); --Returns the cardinality(the number of elements in the set) of this expression + | left=intexpression ('+' | 'plus') right=intexpression #plus //IntExpression iexpr = this.plus(intExpr); --Returns an IntExpression that represents the sum of this and the given int node + | left=intexpression ('-' | 'minus') right=intexpression #minus //IntExpression iexpr = this.minus(intExpr); --Returns an IntExpression that represents the difference between this and the given int node. + | left=intexpression ('*' | 'mul') right=intexpression #multiply //IntExpression iexpr = this.minus(intExpr); --Returns an IntExpression that represents the product of this and the given int node. + | left=intexpression ('/' | 'div') right=intexpression #divide //IntExpression iexpr = this.divide(intExpr); --Returns an IntExpression that represents the quotient of the division between this and the given int node. + | left=intexpression ('%' | 'modulo') right=intexpression #modulo //IntExpression iexpr = this.modulo(intExpr); --Returns an IntExpression that represents the remainder of the division between this and the given int node. + | sign='-'? integer #intConstant + | '(' intexpression ')' #i_paranthesis + ; + +//A variable declaration, such as 'x : lone X'. Declarations are used with quantified formulas and comprehension expressions. +decls: decl (',' decl)*; + +decl: disj='disj'? vars+=variable (',' vars+=variable)* ':' 'one'? expression + {$formula::var = declareVariables($vars, $formula::var);} #oneOf //Decl d = var.oneOf(expression) + | disj='disj'? vars+=variable (',' vars+=variable)* ':' 'lone' expression + {$formula::var = declareVariables($vars, $formula::var);} #loneOf //Decl d = var.loneOf(expression) + | disj='disj'? vars+=variable (',' vars+=variable)* ':' 'some' expression + {$formula::var = declareVariables($vars, $formula::var);} #someOf //Decl d = var.someOf(expression) + | disj='disj'? vars+=variable (',' vars+=variable)* ':' 'set' expression + {$formula::var = declareVariables($vars, $formula::var);} #setOf //Decl d = var.setOf(expression) +; + +letDecls: letDecl (',' letDecl)*; + +letDecl: (vars+=variable (',' vars+=variable)* '=' expression) + {$formula::var = declareVariables($vars, $formula::var);} ; + +comprehensionDecls: comprehensionDecl (',' comprehensionDecl)*; + +comprehensionDecl: disj='disj'? (vars+=variable (',' vars+=variable)* ':' 'one'? expression) + {$formula::var = declareVariables($vars, $formula::var);} +; + +INT : DIGIT+ ; +IDENTIFIER : LETTER (LETTER | APOSTROPHE | DIGIT)* ; +fragment +LETTER: [a-zA-Z]; +DIGIT: [0-9]; +APOSTROPHE: '\''; +MULTILINE_COMMENT : '/**' .*? '**/' -> skip; +SINGLELINE_COMMENT : '--' .*? '\r'? '\n' -> skip; +WS: [ \t\r\n]+ -> skip ; // toss out whitespace diff --git a/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/KodkodBaseListener.java b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/KodkodBaseListener.java new file mode 100644 index 00000000..4d3c288a --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/KodkodBaseListener.java @@ -0,0 +1,1035 @@ +// Generated from C:/Users/anil.ozturk/IdeaProjects/untitled1/src\Kodkod.g4 by ANTLR 4.5.1 +package eu.modelwriter.kodkod.core.recognizer; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.TerminalNode; + +/** + * This class provides an empty implementation of {@link KodkodListener}, + * which can be extended to create a listener which only needs to handle a subset + * of the available methods. + */ +public class KodkodBaseListener implements KodkodListener { + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterProblem(KodkodParser.ProblemContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitProblem(KodkodParser.ProblemContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterOptions(KodkodParser.OptionsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitOptions(KodkodParser.OptionsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterSymmetryBreaking(KodkodParser.SymmetryBreakingContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitSymmetryBreaking(KodkodParser.SymmetryBreakingContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterBitWidth(KodkodParser.BitWidthContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitBitWidth(KodkodParser.BitWidthContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterSkolemDepth(KodkodParser.SkolemDepthContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitSkolemDepth(KodkodParser.SkolemDepthContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterSharing(KodkodParser.SharingContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitSharing(KodkodParser.SharingContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterUniverse(KodkodParser.UniverseContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitUniverse(KodkodParser.UniverseContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterRelations(KodkodParser.RelationsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitRelations(KodkodParser.RelationsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterRelation(KodkodParser.RelationContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitRelation(KodkodParser.RelationContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterTupleSet(KodkodParser.TupleSetContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitTupleSet(KodkodParser.TupleSetContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterTuple(KodkodParser.TupleContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitTuple(KodkodParser.TupleContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterAtom(KodkodParser.AtomContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitAtom(KodkodParser.AtomContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterRelationId(KodkodParser.RelationIdContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitRelationId(KodkodParser.RelationIdContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterVariableId(KodkodParser.VariableIdContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitVariableId(KodkodParser.VariableIdContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterInteger(KodkodParser.IntegerContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitInteger(KodkodParser.IntegerContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterArity(KodkodParser.ArityContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitArity(KodkodParser.ArityContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterNo(KodkodParser.NoContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitNo(KodkodParser.NoContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterSome(KodkodParser.SomeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitSome(KodkodParser.SomeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterForOne(KodkodParser.ForOneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitForOne(KodkodParser.ForOneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterSumDeclaration(KodkodParser.SumDeclarationContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitSumDeclaration(KodkodParser.SumDeclarationContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterForAll(KodkodParser.ForAllContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitForAll(KodkodParser.ForAllContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterLone(KodkodParser.LoneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitLone(KodkodParser.LoneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterLt(KodkodParser.LtContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitLt(KodkodParser.LtContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterForSome(KodkodParser.ForSomeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitForSome(KodkodParser.ForSomeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterNot(KodkodParser.NotContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitNot(KodkodParser.NotContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterF_paranthesis(KodkodParser.F_paranthesisContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitF_paranthesis(KodkodParser.F_paranthesisContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterAnd(KodkodParser.AndContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitAnd(KodkodParser.AndContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterFunction(KodkodParser.FunctionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitFunction(KodkodParser.FunctionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterGte(KodkodParser.GteContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitGte(KodkodParser.GteContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterAcyclic(KodkodParser.AcyclicContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitAcyclic(KodkodParser.AcyclicContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterLet(KodkodParser.LetContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitLet(KodkodParser.LetContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterLte(KodkodParser.LteContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitLte(KodkodParser.LteContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterOr(KodkodParser.OrContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitOr(KodkodParser.OrContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIn(KodkodParser.InContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIn(KodkodParser.InContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterOne(KodkodParser.OneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitOne(KodkodParser.OneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterFalse(KodkodParser.FalseContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitFalse(KodkodParser.FalseContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIff(KodkodParser.IffContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIff(KodkodParser.IffContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEq(KodkodParser.EqContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEq(KodkodParser.EqContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterGt(KodkodParser.GtContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitGt(KodkodParser.GtContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEqual(KodkodParser.EqualContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEqual(KodkodParser.EqualContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterForLone(KodkodParser.ForLoneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitForLone(KodkodParser.ForLoneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterTotalOrder(KodkodParser.TotalOrderContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitTotalOrder(KodkodParser.TotalOrderContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterTrue(KodkodParser.TrueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitTrue(KodkodParser.TrueContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterForNo(KodkodParser.ForNoContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitForNo(KodkodParser.ForNoContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterImplies(KodkodParser.ImpliesContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitImplies(KodkodParser.ImpliesContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterProduct(KodkodParser.ProductContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitProduct(KodkodParser.ProductContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterVar(KodkodParser.VarContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitVar(KodkodParser.VarContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterNone(KodkodParser.NoneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitNone(KodkodParser.NoneContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterUnion(KodkodParser.UnionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitUnion(KodkodParser.UnionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterBoxjoin(KodkodParser.BoxjoinContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitBoxjoin(KodkodParser.BoxjoinContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterComprehension(KodkodParser.ComprehensionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitComprehension(KodkodParser.ComprehensionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterUniv(KodkodParser.UnivContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitUniv(KodkodParser.UnivContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterReflexive(KodkodParser.ReflexiveContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitReflexive(KodkodParser.ReflexiveContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterE_paranthesis(KodkodParser.E_paranthesisContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitE_paranthesis(KodkodParser.E_paranthesisContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIden(KodkodParser.IdenContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIden(KodkodParser.IdenContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterInts(KodkodParser.IntsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitInts(KodkodParser.IntsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIntersection(KodkodParser.IntersectionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIntersection(KodkodParser.IntersectionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterRel(KodkodParser.RelContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitRel(KodkodParser.RelContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterDifference(KodkodParser.DifferenceContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitDifference(KodkodParser.DifferenceContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterTranspose(KodkodParser.TransposeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitTranspose(KodkodParser.TransposeContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterJoin(KodkodParser.JoinContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitJoin(KodkodParser.JoinContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterOverride(KodkodParser.OverrideContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitOverride(KodkodParser.OverrideContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIfExpression(KodkodParser.IfExpressionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIfExpression(KodkodParser.IfExpressionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterClosure(KodkodParser.ClosureContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitClosure(KodkodParser.ClosureContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterMinus(KodkodParser.MinusContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitMinus(KodkodParser.MinusContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIntConstant(KodkodParser.IntConstantContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIntConstant(KodkodParser.IntConstantContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterI_paranthesis(KodkodParser.I_paranthesisContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitI_paranthesis(KodkodParser.I_paranthesisContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterIfIntExpression(KodkodParser.IfIntExpressionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitIfIntExpression(KodkodParser.IfIntExpressionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterCount(KodkodParser.CountContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitCount(KodkodParser.CountContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterSum(KodkodParser.SumContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitSum(KodkodParser.SumContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterDivide(KodkodParser.DivideContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitDivide(KodkodParser.DivideContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterMultiply(KodkodParser.MultiplyContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitMultiply(KodkodParser.MultiplyContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterModulo(KodkodParser.ModuloContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitModulo(KodkodParser.ModuloContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterPlus(KodkodParser.PlusContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitPlus(KodkodParser.PlusContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterDecls(KodkodParser.DeclsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitDecls(KodkodParser.DeclsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterOneOf(KodkodParser.OneOfContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitOneOf(KodkodParser.OneOfContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterLoneOf(KodkodParser.LoneOfContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitLoneOf(KodkodParser.LoneOfContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterSomeOf(KodkodParser.SomeOfContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitSomeOf(KodkodParser.SomeOfContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterSetOf(KodkodParser.SetOfContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitSetOf(KodkodParser.SetOfContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterLetDecls(KodkodParser.LetDeclsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitLetDecls(KodkodParser.LetDeclsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterLetDecl(KodkodParser.LetDeclContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitLetDecl(KodkodParser.LetDeclContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterComprehensionDecls(KodkodParser.ComprehensionDeclsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitComprehensionDecls(KodkodParser.ComprehensionDeclsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterComprehensionDecl(KodkodParser.ComprehensionDeclContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitComprehensionDecl(KodkodParser.ComprehensionDeclContext ctx) { } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEveryRule(ParserRuleContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEveryRule(ParserRuleContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void visitTerminal(TerminalNode node) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void visitErrorNode(ErrorNode node) { } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/KodkodBaseVisitor.java b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/KodkodBaseVisitor.java new file mode 100644 index 00000000..8e133bb6 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/KodkodBaseVisitor.java @@ -0,0 +1,595 @@ +// Generated from C:/Users/anil.ozturk/IdeaProjects/untitled1/src\Kodkod.g4 by ANTLR 4.5.1 +package eu.modelwriter.kodkod.core.recognizer; +import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; + +/** + * This class provides an empty implementation of {@link KodkodVisitor}, + * which can be extended to create a visitor which only needs to handle a subset + * of the available methods. + * + * @param The return type of the visit operation. Use {@link Void} for + * operations with no return type. + */ +public class KodkodBaseVisitor extends AbstractParseTreeVisitor implements KodkodVisitor { + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitProblem(KodkodParser.ProblemContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitOptions(KodkodParser.OptionsContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitSymmetryBreaking(KodkodParser.SymmetryBreakingContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitBitWidth(KodkodParser.BitWidthContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitSkolemDepth(KodkodParser.SkolemDepthContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitSharing(KodkodParser.SharingContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitUniverse(KodkodParser.UniverseContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitRelations(KodkodParser.RelationsContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitRelation(KodkodParser.RelationContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitTupleSet(KodkodParser.TupleSetContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitTuple(KodkodParser.TupleContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitAtom(KodkodParser.AtomContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitRelationId(KodkodParser.RelationIdContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitVariableId(KodkodParser.VariableIdContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitInteger(KodkodParser.IntegerContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitArity(KodkodParser.ArityContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitNo(KodkodParser.NoContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitSome(KodkodParser.SomeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitForOne(KodkodParser.ForOneContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitSumDeclaration(KodkodParser.SumDeclarationContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitForAll(KodkodParser.ForAllContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitLone(KodkodParser.LoneContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitLt(KodkodParser.LtContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitForSome(KodkodParser.ForSomeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitNot(KodkodParser.NotContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitF_paranthesis(KodkodParser.F_paranthesisContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitAnd(KodkodParser.AndContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitFunction(KodkodParser.FunctionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitGte(KodkodParser.GteContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitAcyclic(KodkodParser.AcyclicContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitLet(KodkodParser.LetContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitLte(KodkodParser.LteContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitOr(KodkodParser.OrContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIn(KodkodParser.InContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitOne(KodkodParser.OneContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitFalse(KodkodParser.FalseContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIff(KodkodParser.IffContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEq(KodkodParser.EqContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitGt(KodkodParser.GtContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitEqual(KodkodParser.EqualContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitForLone(KodkodParser.ForLoneContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitTotalOrder(KodkodParser.TotalOrderContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitTrue(KodkodParser.TrueContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitForNo(KodkodParser.ForNoContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitImplies(KodkodParser.ImpliesContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitProduct(KodkodParser.ProductContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitVar(KodkodParser.VarContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitNone(KodkodParser.NoneContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitUnion(KodkodParser.UnionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitBoxjoin(KodkodParser.BoxjoinContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitComprehension(KodkodParser.ComprehensionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitUniv(KodkodParser.UnivContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitReflexive(KodkodParser.ReflexiveContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitE_paranthesis(KodkodParser.E_paranthesisContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIden(KodkodParser.IdenContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitInts(KodkodParser.IntsContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIntersection(KodkodParser.IntersectionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitRel(KodkodParser.RelContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitDifference(KodkodParser.DifferenceContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitTranspose(KodkodParser.TransposeContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitJoin(KodkodParser.JoinContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitOverride(KodkodParser.OverrideContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIfExpression(KodkodParser.IfExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitClosure(KodkodParser.ClosureContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitMinus(KodkodParser.MinusContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIntConstant(KodkodParser.IntConstantContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitI_paranthesis(KodkodParser.I_paranthesisContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitIfIntExpression(KodkodParser.IfIntExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitCount(KodkodParser.CountContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitSum(KodkodParser.SumContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitDivide(KodkodParser.DivideContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitMultiply(KodkodParser.MultiplyContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitModulo(KodkodParser.ModuloContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitPlus(KodkodParser.PlusContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitDecls(KodkodParser.DeclsContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitOneOf(KodkodParser.OneOfContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitLoneOf(KodkodParser.LoneOfContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitSomeOf(KodkodParser.SomeOfContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitSetOf(KodkodParser.SetOfContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitLetDecls(KodkodParser.LetDeclsContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitLetDecl(KodkodParser.LetDeclContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitComprehensionDecls(KodkodParser.ComprehensionDeclsContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitComprehensionDecl(KodkodParser.ComprehensionDeclContext ctx) { return visitChildren(ctx); } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/KodkodLexer.java b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/KodkodLexer.java new file mode 100644 index 00000000..580926d3 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/KodkodLexer.java @@ -0,0 +1,297 @@ +// Generated from C:/Users/anil.ozturk/IdeaProjects/untitled1/src\Kodkod.g4 by ANTLR 4.5.1 +package eu.modelwriter.kodkod.core.recognizer; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.TokenStream; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.misc.*; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class KodkodLexer extends Lexer { + static { RuntimeMetaData.checkVersion("4.5.1", RuntimeMetaData.VERSION); } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, + T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, + T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, + T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, T__29=30, T__30=31, + T__31=32, T__32=33, T__33=34, T__34=35, T__35=36, T__36=37, T__37=38, + T__38=39, T__39=40, T__40=41, T__41=42, T__42=43, T__43=44, T__44=45, + T__45=46, T__46=47, T__47=48, T__48=49, T__49=50, T__50=51, T__51=52, + T__52=53, T__53=54, T__54=55, T__55=56, T__56=57, T__57=58, T__58=59, + T__59=60, T__60=61, T__61=62, T__62=63, T__63=64, T__64=65, T__65=66, + T__66=67, T__67=68, T__68=69, T__69=70, INT=71, IDENTIFIER=72, DIGIT=73, + APOSTROPHE=74, MULTILINE_COMMENT=75, SINGLELINE_COMMENT=76, WS=77; + public static String[] modeNames = { + "DEFAULT_MODE" + }; + + public static final String[] ruleNames = { + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", + "T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16", + "T__17", "T__18", "T__19", "T__20", "T__21", "T__22", "T__23", "T__24", + "T__25", "T__26", "T__27", "T__28", "T__29", "T__30", "T__31", "T__32", + "T__33", "T__34", "T__35", "T__36", "T__37", "T__38", "T__39", "T__40", + "T__41", "T__42", "T__43", "T__44", "T__45", "T__46", "T__47", "T__48", + "T__49", "T__50", "T__51", "T__52", "T__53", "T__54", "T__55", "T__56", + "T__57", "T__58", "T__59", "T__60", "T__61", "T__62", "T__63", "T__64", + "T__65", "T__66", "T__67", "T__68", "T__69", "INT", "IDENTIFIER", "LETTER", + "DIGIT", "APOSTROPHE", "MULTILINE_COMMENT", "SINGLELINE_COMMENT", "WS" + }; + + private static final String[] _LITERAL_NAMES = { + null, "'options'", "'{'", "','", "'}'", "'symmetry_breaking'", "':'", + "'bit_width'", "'skolem_depth'", "'sharing'", "'universe'", "'['", "']'", + "'relations'", "'..'", "'('", "')'", "'no'", "'lone'", "'one'", "'some'", + "'!'", "'not'", "'in'", "'='", "'<'", "'<='", "'>'", "'>='", "'sum'", + "'|'", "'acyclic'", "'function'", "'->'", "'ord'", "'&&'", "'and'", "'||'", + "'or'", "'=>'", "'if'", "'<=>'", "'iff'", "'all'", "'let'", "'true'", + "'false'", "'~'", "'^'", "'*'", "'+'", "'&'", "'-'", "'.'", "'set'", "'++'", + "'then'", "'else'", "'iden'", "'none'", "'univ'", "'ints'", "'#'", "'plus'", + "'minus'", "'mul'", "'/'", "'div'", "'%'", "'modulo'", "'disj'", null, + null, null, "'''" + }; + private static final String[] _SYMBOLIC_NAMES = { + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, "INT", + "IDENTIFIER", "DIGIT", "APOSTROPHE", "MULTILINE_COMMENT", "SINGLELINE_COMMENT", + "WS" + }; + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + + public KodkodLexer(CharStream input) { + super(input); + _interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); + } + + @Override + public String getGrammarFileName() { return "Kodkod.g4"; } + + @Override + public String[] getRuleNames() { return ruleNames; } + + @Override + public String getSerializedATN() { return _serializedATN; } + + @Override + public String[] getModeNames() { return modeNames; } + + @Override + public ATN getATN() { return _ATN; } + + public static final String _serializedATN = + "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2O\u0203\b\1\4\2\t"+ + "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ + "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ + "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ + "\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+ + "\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t+\4"+ + ",\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64\t"+ + "\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:\4;\t;\4<\t<\4=\t="+ + "\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4E\tE\4F\tF\4G\tG\4H\tH\4I"+ + "\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3"+ + "\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6"+ + "\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3"+ + "\b\3\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\n\3\n\3\n"+ + "\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\f"+ + "\3\f\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\17\3"+ + "\17\3\17\3\20\3\20\3\21\3\21\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3"+ + "\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\25\3\26\3\26\3\27\3\27\3\27\3"+ + "\27\3\30\3\30\3\30\3\31\3\31\3\32\3\32\3\33\3\33\3\33\3\34\3\34\3\35\3"+ + "\35\3\35\3\36\3\36\3\36\3\36\3\37\3\37\3 \3 \3 \3 \3 \3 \3 \3 \3!\3!\3"+ + "!\3!\3!\3!\3!\3!\3!\3\"\3\"\3\"\3#\3#\3#\3#\3$\3$\3$\3%\3%\3%\3%\3&\3"+ + "&\3&\3\'\3\'\3\'\3(\3(\3(\3)\3)\3)\3*\3*\3*\3*\3+\3+\3+\3+\3,\3,\3,\3"+ + ",\3-\3-\3-\3-\3.\3.\3.\3.\3.\3/\3/\3/\3/\3/\3/\3\60\3\60\3\61\3\61\3\62"+ + "\3\62\3\63\3\63\3\64\3\64\3\65\3\65\3\66\3\66\3\67\3\67\3\67\3\67\38\3"+ + "8\38\39\39\39\39\39\3:\3:\3:\3:\3:\3;\3;\3;\3;\3;\3<\3<\3<\3<\3<\3=\3"+ + "=\3=\3=\3=\3>\3>\3>\3>\3>\3?\3?\3@\3@\3@\3@\3@\3A\3A\3A\3A\3A\3A\3B\3"+ + "B\3B\3B\3C\3C\3D\3D\3D\3D\3E\3E\3F\3F\3F\3F\3F\3F\3F\3G\3G\3G\3G\3G\3"+ + "H\6H\u01ca\nH\rH\16H\u01cb\3I\3I\3I\3I\7I\u01d2\nI\fI\16I\u01d5\13I\3"+ + "J\3J\3K\3K\3L\3L\3M\3M\3M\3M\3M\7M\u01e2\nM\fM\16M\u01e5\13M\3M\3M\3M"+ + "\3M\3M\3M\3N\3N\3N\3N\7N\u01f1\nN\fN\16N\u01f4\13N\3N\5N\u01f7\nN\3N\3"+ + "N\3N\3N\3O\6O\u01fe\nO\rO\16O\u01ff\3O\3O\4\u01e3\u01f2\2P\3\3\5\4\7\5"+ + "\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23"+ + "%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G"+ + "%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o9q:s;u{"+ + "?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH\u008fI\u0091"+ + "J\u0093\2\u0095K\u0097L\u0099M\u009bN\u009dO\3\2\5\4\2C\\c|\3\2\62;\5"+ + "\2\13\f\17\17\"\"\u0209\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2"+ + "\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25"+ + "\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2"+ + "\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2"+ + "\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3"+ + "\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2"+ + "\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2"+ + "Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3"+ + "\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2"+ + "\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2"+ + "w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081\3\2\2"+ + "\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2\2\2\u008b"+ + "\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2\2\u0091\3\2\2\2\2\u0095\3\2\2"+ + "\2\2\u0097\3\2\2\2\2\u0099\3\2\2\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\3\u009f"+ + "\3\2\2\2\5\u00a7\3\2\2\2\7\u00a9\3\2\2\2\t\u00ab\3\2\2\2\13\u00ad\3\2"+ + "\2\2\r\u00bf\3\2\2\2\17\u00c1\3\2\2\2\21\u00cb\3\2\2\2\23\u00d8\3\2\2"+ + "\2\25\u00e0\3\2\2\2\27\u00e9\3\2\2\2\31\u00eb\3\2\2\2\33\u00ed\3\2\2\2"+ + "\35\u00f7\3\2\2\2\37\u00fa\3\2\2\2!\u00fc\3\2\2\2#\u00fe\3\2\2\2%\u0101"+ + "\3\2\2\2\'\u0106\3\2\2\2)\u010a\3\2\2\2+\u010f\3\2\2\2-\u0111\3\2\2\2"+ + "/\u0115\3\2\2\2\61\u0118\3\2\2\2\63\u011a\3\2\2\2\65\u011c\3\2\2\2\67"+ + "\u011f\3\2\2\29\u0121\3\2\2\2;\u0124\3\2\2\2=\u0128\3\2\2\2?\u012a\3\2"+ + "\2\2A\u0132\3\2\2\2C\u013b\3\2\2\2E\u013e\3\2\2\2G\u0142\3\2\2\2I\u0145"+ + "\3\2\2\2K\u0149\3\2\2\2M\u014c\3\2\2\2O\u014f\3\2\2\2Q\u0152\3\2\2\2S"+ + "\u0155\3\2\2\2U\u0159\3\2\2\2W\u015d\3\2\2\2Y\u0161\3\2\2\2[\u0165\3\2"+ + "\2\2]\u016a\3\2\2\2_\u0170\3\2\2\2a\u0172\3\2\2\2c\u0174\3\2\2\2e\u0176"+ + "\3\2\2\2g\u0178\3\2\2\2i\u017a\3\2\2\2k\u017c\3\2\2\2m\u017e\3\2\2\2o"+ + "\u0182\3\2\2\2q\u0185\3\2\2\2s\u018a\3\2\2\2u\u018f\3\2\2\2w\u0194\3\2"+ + "\2\2y\u0199\3\2\2\2{\u019e\3\2\2\2}\u01a3\3\2\2\2\177\u01a5\3\2\2\2\u0081"+ + "\u01aa\3\2\2\2\u0083\u01b0\3\2\2\2\u0085\u01b4\3\2\2\2\u0087\u01b6\3\2"+ + "\2\2\u0089\u01ba\3\2\2\2\u008b\u01bc\3\2\2\2\u008d\u01c3\3\2\2\2\u008f"+ + "\u01c9\3\2\2\2\u0091\u01cd\3\2\2\2\u0093\u01d6\3\2\2\2\u0095\u01d8\3\2"+ + "\2\2\u0097\u01da\3\2\2\2\u0099\u01dc\3\2\2\2\u009b\u01ec\3\2\2\2\u009d"+ + "\u01fd\3\2\2\2\u009f\u00a0\7q\2\2\u00a0\u00a1\7r\2\2\u00a1\u00a2\7v\2"+ + "\2\u00a2\u00a3\7k\2\2\u00a3\u00a4\7q\2\2\u00a4\u00a5\7p\2\2\u00a5\u00a6"+ + "\7u\2\2\u00a6\4\3\2\2\2\u00a7\u00a8\7}\2\2\u00a8\6\3\2\2\2\u00a9\u00aa"+ + "\7.\2\2\u00aa\b\3\2\2\2\u00ab\u00ac\7\177\2\2\u00ac\n\3\2\2\2\u00ad\u00ae"+ + "\7u\2\2\u00ae\u00af\7{\2\2\u00af\u00b0\7o\2\2\u00b0\u00b1\7o\2\2\u00b1"+ + "\u00b2\7g\2\2\u00b2\u00b3\7v\2\2\u00b3\u00b4\7t\2\2\u00b4\u00b5\7{\2\2"+ + "\u00b5\u00b6\7a\2\2\u00b6\u00b7\7d\2\2\u00b7\u00b8\7t\2\2\u00b8\u00b9"+ + "\7g\2\2\u00b9\u00ba\7c\2\2\u00ba\u00bb\7m\2\2\u00bb\u00bc\7k\2\2\u00bc"+ + "\u00bd\7p\2\2\u00bd\u00be\7i\2\2\u00be\f\3\2\2\2\u00bf\u00c0\7<\2\2\u00c0"+ + "\16\3\2\2\2\u00c1\u00c2\7d\2\2\u00c2\u00c3\7k\2\2\u00c3\u00c4\7v\2\2\u00c4"+ + "\u00c5\7a\2\2\u00c5\u00c6\7y\2\2\u00c6\u00c7\7k\2\2\u00c7\u00c8\7f\2\2"+ + "\u00c8\u00c9\7v\2\2\u00c9\u00ca\7j\2\2\u00ca\20\3\2\2\2\u00cb\u00cc\7"+ + "u\2\2\u00cc\u00cd\7m\2\2\u00cd\u00ce\7q\2\2\u00ce\u00cf\7n\2\2\u00cf\u00d0"+ + "\7g\2\2\u00d0\u00d1\7o\2\2\u00d1\u00d2\7a\2\2\u00d2\u00d3\7f\2\2\u00d3"+ + "\u00d4\7g\2\2\u00d4\u00d5\7r\2\2\u00d5\u00d6\7v\2\2\u00d6\u00d7\7j\2\2"+ + "\u00d7\22\3\2\2\2\u00d8\u00d9\7u\2\2\u00d9\u00da\7j\2\2\u00da\u00db\7"+ + "c\2\2\u00db\u00dc\7t\2\2\u00dc\u00dd\7k\2\2\u00dd\u00de\7p\2\2\u00de\u00df"+ + "\7i\2\2\u00df\24\3\2\2\2\u00e0\u00e1\7w\2\2\u00e1\u00e2\7p\2\2\u00e2\u00e3"+ + "\7k\2\2\u00e3\u00e4\7x\2\2\u00e4\u00e5\7g\2\2\u00e5\u00e6\7t\2\2\u00e6"+ + "\u00e7\7u\2\2\u00e7\u00e8\7g\2\2\u00e8\26\3\2\2\2\u00e9\u00ea\7]\2\2\u00ea"+ + "\30\3\2\2\2\u00eb\u00ec\7_\2\2\u00ec\32\3\2\2\2\u00ed\u00ee\7t\2\2\u00ee"+ + "\u00ef\7g\2\2\u00ef\u00f0\7n\2\2\u00f0\u00f1\7c\2\2\u00f1\u00f2\7v\2\2"+ + "\u00f2\u00f3\7k\2\2\u00f3\u00f4\7q\2\2\u00f4\u00f5\7p\2\2\u00f5\u00f6"+ + "\7u\2\2\u00f6\34\3\2\2\2\u00f7\u00f8\7\60\2\2\u00f8\u00f9\7\60\2\2\u00f9"+ + "\36\3\2\2\2\u00fa\u00fb\7*\2\2\u00fb \3\2\2\2\u00fc\u00fd\7+\2\2\u00fd"+ + "\"\3\2\2\2\u00fe\u00ff\7p\2\2\u00ff\u0100\7q\2\2\u0100$\3\2\2\2\u0101"+ + "\u0102\7n\2\2\u0102\u0103\7q\2\2\u0103\u0104\7p\2\2\u0104\u0105\7g\2\2"+ + "\u0105&\3\2\2\2\u0106\u0107\7q\2\2\u0107\u0108\7p\2\2\u0108\u0109\7g\2"+ + "\2\u0109(\3\2\2\2\u010a\u010b\7u\2\2\u010b\u010c\7q\2\2\u010c\u010d\7"+ + "o\2\2\u010d\u010e\7g\2\2\u010e*\3\2\2\2\u010f\u0110\7#\2\2\u0110,\3\2"+ + "\2\2\u0111\u0112\7p\2\2\u0112\u0113\7q\2\2\u0113\u0114\7v\2\2\u0114.\3"+ + "\2\2\2\u0115\u0116\7k\2\2\u0116\u0117\7p\2\2\u0117\60\3\2\2\2\u0118\u0119"+ + "\7?\2\2\u0119\62\3\2\2\2\u011a\u011b\7>\2\2\u011b\64\3\2\2\2\u011c\u011d"+ + "\7>\2\2\u011d\u011e\7?\2\2\u011e\66\3\2\2\2\u011f\u0120\7@\2\2\u01208"+ + "\3\2\2\2\u0121\u0122\7@\2\2\u0122\u0123\7?\2\2\u0123:\3\2\2\2\u0124\u0125"+ + "\7u\2\2\u0125\u0126\7w\2\2\u0126\u0127\7o\2\2\u0127<\3\2\2\2\u0128\u0129"+ + "\7~\2\2\u0129>\3\2\2\2\u012a\u012b\7c\2\2\u012b\u012c\7e\2\2\u012c\u012d"+ + "\7{\2\2\u012d\u012e\7e\2\2\u012e\u012f\7n\2\2\u012f\u0130\7k\2\2\u0130"+ + "\u0131\7e\2\2\u0131@\3\2\2\2\u0132\u0133\7h\2\2\u0133\u0134\7w\2\2\u0134"+ + "\u0135\7p\2\2\u0135\u0136\7e\2\2\u0136\u0137\7v\2\2\u0137\u0138\7k\2\2"+ + "\u0138\u0139\7q\2\2\u0139\u013a\7p\2\2\u013aB\3\2\2\2\u013b\u013c\7/\2"+ + "\2\u013c\u013d\7@\2\2\u013dD\3\2\2\2\u013e\u013f\7q\2\2\u013f\u0140\7"+ + "t\2\2\u0140\u0141\7f\2\2\u0141F\3\2\2\2\u0142\u0143\7(\2\2\u0143\u0144"+ + "\7(\2\2\u0144H\3\2\2\2\u0145\u0146\7c\2\2\u0146\u0147\7p\2\2\u0147\u0148"+ + "\7f\2\2\u0148J\3\2\2\2\u0149\u014a\7~\2\2\u014a\u014b\7~\2\2\u014bL\3"+ + "\2\2\2\u014c\u014d\7q\2\2\u014d\u014e\7t\2\2\u014eN\3\2\2\2\u014f\u0150"+ + "\7?\2\2\u0150\u0151\7@\2\2\u0151P\3\2\2\2\u0152\u0153\7k\2\2\u0153\u0154"+ + "\7h\2\2\u0154R\3\2\2\2\u0155\u0156\7>\2\2\u0156\u0157\7?\2\2\u0157\u0158"+ + "\7@\2\2\u0158T\3\2\2\2\u0159\u015a\7k\2\2\u015a\u015b\7h\2\2\u015b\u015c"+ + "\7h\2\2\u015cV\3\2\2\2\u015d\u015e\7c\2\2\u015e\u015f\7n\2\2\u015f\u0160"+ + "\7n\2\2\u0160X\3\2\2\2\u0161\u0162\7n\2\2\u0162\u0163\7g\2\2\u0163\u0164"+ + "\7v\2\2\u0164Z\3\2\2\2\u0165\u0166\7v\2\2\u0166\u0167\7t\2\2\u0167\u0168"+ + "\7w\2\2\u0168\u0169\7g\2\2\u0169\\\3\2\2\2\u016a\u016b\7h\2\2\u016b\u016c"+ + "\7c\2\2\u016c\u016d\7n\2\2\u016d\u016e\7u\2\2\u016e\u016f\7g\2\2\u016f"+ + "^\3\2\2\2\u0170\u0171\7\u0080\2\2\u0171`\3\2\2\2\u0172\u0173\7`\2\2\u0173"+ + "b\3\2\2\2\u0174\u0175\7,\2\2\u0175d\3\2\2\2\u0176\u0177\7-\2\2\u0177f"+ + "\3\2\2\2\u0178\u0179\7(\2\2\u0179h\3\2\2\2\u017a\u017b\7/\2\2\u017bj\3"+ + "\2\2\2\u017c\u017d\7\60\2\2\u017dl\3\2\2\2\u017e\u017f\7u\2\2\u017f\u0180"+ + "\7g\2\2\u0180\u0181\7v\2\2\u0181n\3\2\2\2\u0182\u0183\7-\2\2\u0183\u0184"+ + "\7-\2\2\u0184p\3\2\2\2\u0185\u0186\7v\2\2\u0186\u0187\7j\2\2\u0187\u0188"+ + "\7g\2\2\u0188\u0189\7p\2\2\u0189r\3\2\2\2\u018a\u018b\7g\2\2\u018b\u018c"+ + "\7n\2\2\u018c\u018d\7u\2\2\u018d\u018e\7g\2\2\u018et\3\2\2\2\u018f\u0190"+ + "\7k\2\2\u0190\u0191\7f\2\2\u0191\u0192\7g\2\2\u0192\u0193\7p\2\2\u0193"+ + "v\3\2\2\2\u0194\u0195\7p\2\2\u0195\u0196\7q\2\2\u0196\u0197\7p\2\2\u0197"+ + "\u0198\7g\2\2\u0198x\3\2\2\2\u0199\u019a\7w\2\2\u019a\u019b\7p\2\2\u019b"+ + "\u019c\7k\2\2\u019c\u019d\7x\2\2\u019dz\3\2\2\2\u019e\u019f\7k\2\2\u019f"+ + "\u01a0\7p\2\2\u01a0\u01a1\7v\2\2\u01a1\u01a2\7u\2\2\u01a2|\3\2\2\2\u01a3"+ + "\u01a4\7%\2\2\u01a4~\3\2\2\2\u01a5\u01a6\7r\2\2\u01a6\u01a7\7n\2\2\u01a7"+ + "\u01a8\7w\2\2\u01a8\u01a9\7u\2\2\u01a9\u0080\3\2\2\2\u01aa\u01ab\7o\2"+ + "\2\u01ab\u01ac\7k\2\2\u01ac\u01ad\7p\2\2\u01ad\u01ae\7w\2\2\u01ae\u01af"+ + "\7u\2\2\u01af\u0082\3\2\2\2\u01b0\u01b1\7o\2\2\u01b1\u01b2\7w\2\2\u01b2"+ + "\u01b3\7n\2\2\u01b3\u0084\3\2\2\2\u01b4\u01b5\7\61\2\2\u01b5\u0086\3\2"+ + "\2\2\u01b6\u01b7\7f\2\2\u01b7\u01b8\7k\2\2\u01b8\u01b9\7x\2\2\u01b9\u0088"+ + "\3\2\2\2\u01ba\u01bb\7\'\2\2\u01bb\u008a\3\2\2\2\u01bc\u01bd\7o\2\2\u01bd"+ + "\u01be\7q\2\2\u01be\u01bf\7f\2\2\u01bf\u01c0\7w\2\2\u01c0\u01c1\7n\2\2"+ + "\u01c1\u01c2\7q\2\2\u01c2\u008c\3\2\2\2\u01c3\u01c4\7f\2\2\u01c4\u01c5"+ + "\7k\2\2\u01c5\u01c6\7u\2\2\u01c6\u01c7\7l\2\2\u01c7\u008e\3\2\2\2\u01c8"+ + "\u01ca\5\u0095K\2\u01c9\u01c8\3\2\2\2\u01ca\u01cb\3\2\2\2\u01cb\u01c9"+ + "\3\2\2\2\u01cb\u01cc\3\2\2\2\u01cc\u0090\3\2\2\2\u01cd\u01d3\5\u0093J"+ + "\2\u01ce\u01d2\5\u0093J\2\u01cf\u01d2\5\u0097L\2\u01d0\u01d2\5\u0095K"+ + "\2\u01d1\u01ce\3\2\2\2\u01d1\u01cf\3\2\2\2\u01d1\u01d0\3\2\2\2\u01d2\u01d5"+ + "\3\2\2\2\u01d3\u01d1\3\2\2\2\u01d3\u01d4\3\2\2\2\u01d4\u0092\3\2\2\2\u01d5"+ + "\u01d3\3\2\2\2\u01d6\u01d7\t\2\2\2\u01d7\u0094\3\2\2\2\u01d8\u01d9\t\3"+ + "\2\2\u01d9\u0096\3\2\2\2\u01da\u01db\7)\2\2\u01db\u0098\3\2\2\2\u01dc"+ + "\u01dd\7\61\2\2\u01dd\u01de\7,\2\2\u01de\u01df\7,\2\2\u01df\u01e3\3\2"+ + "\2\2\u01e0\u01e2\13\2\2\2\u01e1\u01e0\3\2\2\2\u01e2\u01e5\3\2\2\2\u01e3"+ + "\u01e4\3\2\2\2\u01e3\u01e1\3\2\2\2\u01e4\u01e6\3\2\2\2\u01e5\u01e3\3\2"+ + "\2\2\u01e6\u01e7\7,\2\2\u01e7\u01e8\7,\2\2\u01e8\u01e9\7\61\2\2\u01e9"+ + "\u01ea\3\2\2\2\u01ea\u01eb\bM\2\2\u01eb\u009a\3\2\2\2\u01ec\u01ed\7/\2"+ + "\2\u01ed\u01ee\7/\2\2\u01ee\u01f2\3\2\2\2\u01ef\u01f1\13\2\2\2\u01f0\u01ef"+ + "\3\2\2\2\u01f1\u01f4\3\2\2\2\u01f2\u01f3\3\2\2\2\u01f2\u01f0\3\2\2\2\u01f3"+ + "\u01f6\3\2\2\2\u01f4\u01f2\3\2\2\2\u01f5\u01f7\7\17\2\2\u01f6\u01f5\3"+ + "\2\2\2\u01f6\u01f7\3\2\2\2\u01f7\u01f8\3\2\2\2\u01f8\u01f9\7\f\2\2\u01f9"+ + "\u01fa\3\2\2\2\u01fa\u01fb\bN\2\2\u01fb\u009c\3\2\2\2\u01fc\u01fe\t\4"+ + "\2\2\u01fd\u01fc\3\2\2\2\u01fe\u01ff\3\2\2\2\u01ff\u01fd\3\2\2\2\u01ff"+ + "\u0200\3\2\2\2\u0200\u0201\3\2\2\2\u0201\u0202\bO\2\2\u0202\u009e\3\2"+ + "\2\2\n\2\u01cb\u01d1\u01d3\u01e3\u01f2\u01f6\u01ff\3\b\2\2"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/KodkodListener.java b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/KodkodListener.java new file mode 100644 index 00000000..959bdba9 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/KodkodListener.java @@ -0,0 +1,972 @@ +// Generated from C:/Users/anil.ozturk/IdeaProjects/untitled1/src\Kodkod.g4 by ANTLR 4.5.1 +package eu.modelwriter.kodkod.core.recognizer; +import org.antlr.v4.runtime.tree.ParseTreeListener; + +/** + * This interface defines a complete listener for a parse tree produced by + * {@link KodkodParser}. + */ +public interface KodkodListener extends ParseTreeListener { + /** + * Enter a parse tree produced by {@link KodkodParser#problem}. + * @param ctx the parse tree + */ + void enterProblem(KodkodParser.ProblemContext ctx); + /** + * Exit a parse tree produced by {@link KodkodParser#problem}. + * @param ctx the parse tree + */ + void exitProblem(KodkodParser.ProblemContext ctx); + /** + * Enter a parse tree produced by {@link KodkodParser#options}. + * @param ctx the parse tree + */ + void enterOptions(KodkodParser.OptionsContext ctx); + /** + * Exit a parse tree produced by {@link KodkodParser#options}. + * @param ctx the parse tree + */ + void exitOptions(KodkodParser.OptionsContext ctx); + /** + * Enter a parse tree produced by the {@code symmetryBreaking} + * labeled alternative in {@link KodkodParser#option}. + * @param ctx the parse tree + */ + void enterSymmetryBreaking(KodkodParser.SymmetryBreakingContext ctx); + /** + * Exit a parse tree produced by the {@code symmetryBreaking} + * labeled alternative in {@link KodkodParser#option}. + * @param ctx the parse tree + */ + void exitSymmetryBreaking(KodkodParser.SymmetryBreakingContext ctx); + /** + * Enter a parse tree produced by the {@code bitWidth} + * labeled alternative in {@link KodkodParser#option}. + * @param ctx the parse tree + */ + void enterBitWidth(KodkodParser.BitWidthContext ctx); + /** + * Exit a parse tree produced by the {@code bitWidth} + * labeled alternative in {@link KodkodParser#option}. + * @param ctx the parse tree + */ + void exitBitWidth(KodkodParser.BitWidthContext ctx); + /** + * Enter a parse tree produced by the {@code skolemDepth} + * labeled alternative in {@link KodkodParser#option}. + * @param ctx the parse tree + */ + void enterSkolemDepth(KodkodParser.SkolemDepthContext ctx); + /** + * Exit a parse tree produced by the {@code skolemDepth} + * labeled alternative in {@link KodkodParser#option}. + * @param ctx the parse tree + */ + void exitSkolemDepth(KodkodParser.SkolemDepthContext ctx); + /** + * Enter a parse tree produced by the {@code sharing} + * labeled alternative in {@link KodkodParser#option}. + * @param ctx the parse tree + */ + void enterSharing(KodkodParser.SharingContext ctx); + /** + * Exit a parse tree produced by the {@code sharing} + * labeled alternative in {@link KodkodParser#option}. + * @param ctx the parse tree + */ + void exitSharing(KodkodParser.SharingContext ctx); + /** + * Enter a parse tree produced by {@link KodkodParser#universe}. + * @param ctx the parse tree + */ + void enterUniverse(KodkodParser.UniverseContext ctx); + /** + * Exit a parse tree produced by {@link KodkodParser#universe}. + * @param ctx the parse tree + */ + void exitUniverse(KodkodParser.UniverseContext ctx); + /** + * Enter a parse tree produced by {@link KodkodParser#relations}. + * @param ctx the parse tree + */ + void enterRelations(KodkodParser.RelationsContext ctx); + /** + * Exit a parse tree produced by {@link KodkodParser#relations}. + * @param ctx the parse tree + */ + void exitRelations(KodkodParser.RelationsContext ctx); + /** + * Enter a parse tree produced by {@link KodkodParser#relation}. + * @param ctx the parse tree + */ + void enterRelation(KodkodParser.RelationContext ctx); + /** + * Exit a parse tree produced by {@link KodkodParser#relation}. + * @param ctx the parse tree + */ + void exitRelation(KodkodParser.RelationContext ctx); + /** + * Enter a parse tree produced by {@link KodkodParser#tupleSet}. + * @param ctx the parse tree + */ + void enterTupleSet(KodkodParser.TupleSetContext ctx); + /** + * Exit a parse tree produced by {@link KodkodParser#tupleSet}. + * @param ctx the parse tree + */ + void exitTupleSet(KodkodParser.TupleSetContext ctx); + /** + * Enter a parse tree produced by {@link KodkodParser#tuple}. + * @param ctx the parse tree + */ + void enterTuple(KodkodParser.TupleContext ctx); + /** + * Exit a parse tree produced by {@link KodkodParser#tuple}. + * @param ctx the parse tree + */ + void exitTuple(KodkodParser.TupleContext ctx); + /** + * Enter a parse tree produced by {@link KodkodParser#atom}. + * @param ctx the parse tree + */ + void enterAtom(KodkodParser.AtomContext ctx); + /** + * Exit a parse tree produced by {@link KodkodParser#atom}. + * @param ctx the parse tree + */ + void exitAtom(KodkodParser.AtomContext ctx); + /** + * Enter a parse tree produced by {@link KodkodParser#relationId}. + * @param ctx the parse tree + */ + void enterRelationId(KodkodParser.RelationIdContext ctx); + /** + * Exit a parse tree produced by {@link KodkodParser#relationId}. + * @param ctx the parse tree + */ + void exitRelationId(KodkodParser.RelationIdContext ctx); + /** + * Enter a parse tree produced by {@link KodkodParser#variableId}. + * @param ctx the parse tree + */ + void enterVariableId(KodkodParser.VariableIdContext ctx); + /** + * Exit a parse tree produced by {@link KodkodParser#variableId}. + * @param ctx the parse tree + */ + void exitVariableId(KodkodParser.VariableIdContext ctx); + /** + * Enter a parse tree produced by {@link KodkodParser#integer}. + * @param ctx the parse tree + */ + void enterInteger(KodkodParser.IntegerContext ctx); + /** + * Exit a parse tree produced by {@link KodkodParser#integer}. + * @param ctx the parse tree + */ + void exitInteger(KodkodParser.IntegerContext ctx); + /** + * Enter a parse tree produced by {@link KodkodParser#arity}. + * @param ctx the parse tree + */ + void enterArity(KodkodParser.ArityContext ctx); + /** + * Exit a parse tree produced by {@link KodkodParser#arity}. + * @param ctx the parse tree + */ + void exitArity(KodkodParser.ArityContext ctx); + /** + * Enter a parse tree produced by the {@code no} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterNo(KodkodParser.NoContext ctx); + /** + * Exit a parse tree produced by the {@code no} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitNo(KodkodParser.NoContext ctx); + /** + * Enter a parse tree produced by the {@code some} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterSome(KodkodParser.SomeContext ctx); + /** + * Exit a parse tree produced by the {@code some} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitSome(KodkodParser.SomeContext ctx); + /** + * Enter a parse tree produced by the {@code forOne} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterForOne(KodkodParser.ForOneContext ctx); + /** + * Exit a parse tree produced by the {@code forOne} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitForOne(KodkodParser.ForOneContext ctx); + /** + * Enter a parse tree produced by the {@code sumDeclaration} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterSumDeclaration(KodkodParser.SumDeclarationContext ctx); + /** + * Exit a parse tree produced by the {@code sumDeclaration} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitSumDeclaration(KodkodParser.SumDeclarationContext ctx); + /** + * Enter a parse tree produced by the {@code forAll} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterForAll(KodkodParser.ForAllContext ctx); + /** + * Exit a parse tree produced by the {@code forAll} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitForAll(KodkodParser.ForAllContext ctx); + /** + * Enter a parse tree produced by the {@code lone} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterLone(KodkodParser.LoneContext ctx); + /** + * Exit a parse tree produced by the {@code lone} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitLone(KodkodParser.LoneContext ctx); + /** + * Enter a parse tree produced by the {@code lt} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterLt(KodkodParser.LtContext ctx); + /** + * Exit a parse tree produced by the {@code lt} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitLt(KodkodParser.LtContext ctx); + /** + * Enter a parse tree produced by the {@code forSome} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterForSome(KodkodParser.ForSomeContext ctx); + /** + * Exit a parse tree produced by the {@code forSome} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitForSome(KodkodParser.ForSomeContext ctx); + /** + * Enter a parse tree produced by the {@code not} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterNot(KodkodParser.NotContext ctx); + /** + * Exit a parse tree produced by the {@code not} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitNot(KodkodParser.NotContext ctx); + /** + * Enter a parse tree produced by the {@code f_paranthesis} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterF_paranthesis(KodkodParser.F_paranthesisContext ctx); + /** + * Exit a parse tree produced by the {@code f_paranthesis} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitF_paranthesis(KodkodParser.F_paranthesisContext ctx); + /** + * Enter a parse tree produced by the {@code and} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterAnd(KodkodParser.AndContext ctx); + /** + * Exit a parse tree produced by the {@code and} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitAnd(KodkodParser.AndContext ctx); + /** + * Enter a parse tree produced by the {@code function} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterFunction(KodkodParser.FunctionContext ctx); + /** + * Exit a parse tree produced by the {@code function} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitFunction(KodkodParser.FunctionContext ctx); + /** + * Enter a parse tree produced by the {@code gte} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterGte(KodkodParser.GteContext ctx); + /** + * Exit a parse tree produced by the {@code gte} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitGte(KodkodParser.GteContext ctx); + /** + * Enter a parse tree produced by the {@code acyclic} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterAcyclic(KodkodParser.AcyclicContext ctx); + /** + * Exit a parse tree produced by the {@code acyclic} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitAcyclic(KodkodParser.AcyclicContext ctx); + /** + * Enter a parse tree produced by the {@code let} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterLet(KodkodParser.LetContext ctx); + /** + * Exit a parse tree produced by the {@code let} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitLet(KodkodParser.LetContext ctx); + /** + * Enter a parse tree produced by the {@code lte} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterLte(KodkodParser.LteContext ctx); + /** + * Exit a parse tree produced by the {@code lte} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitLte(KodkodParser.LteContext ctx); + /** + * Enter a parse tree produced by the {@code or} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterOr(KodkodParser.OrContext ctx); + /** + * Exit a parse tree produced by the {@code or} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitOr(KodkodParser.OrContext ctx); + /** + * Enter a parse tree produced by the {@code in} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterIn(KodkodParser.InContext ctx); + /** + * Exit a parse tree produced by the {@code in} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitIn(KodkodParser.InContext ctx); + /** + * Enter a parse tree produced by the {@code one} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterOne(KodkodParser.OneContext ctx); + /** + * Exit a parse tree produced by the {@code one} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitOne(KodkodParser.OneContext ctx); + /** + * Enter a parse tree produced by the {@code false} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterFalse(KodkodParser.FalseContext ctx); + /** + * Exit a parse tree produced by the {@code false} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitFalse(KodkodParser.FalseContext ctx); + /** + * Enter a parse tree produced by the {@code iff} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterIff(KodkodParser.IffContext ctx); + /** + * Exit a parse tree produced by the {@code iff} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitIff(KodkodParser.IffContext ctx); + /** + * Enter a parse tree produced by the {@code eq} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterEq(KodkodParser.EqContext ctx); + /** + * Exit a parse tree produced by the {@code eq} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitEq(KodkodParser.EqContext ctx); + /** + * Enter a parse tree produced by the {@code gt} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterGt(KodkodParser.GtContext ctx); + /** + * Exit a parse tree produced by the {@code gt} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitGt(KodkodParser.GtContext ctx); + /** + * Enter a parse tree produced by the {@code equal} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterEqual(KodkodParser.EqualContext ctx); + /** + * Exit a parse tree produced by the {@code equal} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitEqual(KodkodParser.EqualContext ctx); + /** + * Enter a parse tree produced by the {@code forLone} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterForLone(KodkodParser.ForLoneContext ctx); + /** + * Exit a parse tree produced by the {@code forLone} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitForLone(KodkodParser.ForLoneContext ctx); + /** + * Enter a parse tree produced by the {@code totalOrder} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterTotalOrder(KodkodParser.TotalOrderContext ctx); + /** + * Exit a parse tree produced by the {@code totalOrder} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitTotalOrder(KodkodParser.TotalOrderContext ctx); + /** + * Enter a parse tree produced by the {@code true} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterTrue(KodkodParser.TrueContext ctx); + /** + * Exit a parse tree produced by the {@code true} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitTrue(KodkodParser.TrueContext ctx); + /** + * Enter a parse tree produced by the {@code forNo} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterForNo(KodkodParser.ForNoContext ctx); + /** + * Exit a parse tree produced by the {@code forNo} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitForNo(KodkodParser.ForNoContext ctx); + /** + * Enter a parse tree produced by the {@code implies} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void enterImplies(KodkodParser.ImpliesContext ctx); + /** + * Exit a parse tree produced by the {@code implies} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + */ + void exitImplies(KodkodParser.ImpliesContext ctx); + /** + * Enter a parse tree produced by the {@code product} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void enterProduct(KodkodParser.ProductContext ctx); + /** + * Exit a parse tree produced by the {@code product} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void exitProduct(KodkodParser.ProductContext ctx); + /** + * Enter a parse tree produced by the {@code var} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void enterVar(KodkodParser.VarContext ctx); + /** + * Exit a parse tree produced by the {@code var} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void exitVar(KodkodParser.VarContext ctx); + /** + * Enter a parse tree produced by the {@code none} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void enterNone(KodkodParser.NoneContext ctx); + /** + * Exit a parse tree produced by the {@code none} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void exitNone(KodkodParser.NoneContext ctx); + /** + * Enter a parse tree produced by the {@code union} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void enterUnion(KodkodParser.UnionContext ctx); + /** + * Exit a parse tree produced by the {@code union} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void exitUnion(KodkodParser.UnionContext ctx); + /** + * Enter a parse tree produced by the {@code boxjoin} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void enterBoxjoin(KodkodParser.BoxjoinContext ctx); + /** + * Exit a parse tree produced by the {@code boxjoin} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void exitBoxjoin(KodkodParser.BoxjoinContext ctx); + /** + * Enter a parse tree produced by the {@code comprehension} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void enterComprehension(KodkodParser.ComprehensionContext ctx); + /** + * Exit a parse tree produced by the {@code comprehension} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void exitComprehension(KodkodParser.ComprehensionContext ctx); + /** + * Enter a parse tree produced by the {@code univ} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void enterUniv(KodkodParser.UnivContext ctx); + /** + * Exit a parse tree produced by the {@code univ} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void exitUniv(KodkodParser.UnivContext ctx); + /** + * Enter a parse tree produced by the {@code reflexive} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void enterReflexive(KodkodParser.ReflexiveContext ctx); + /** + * Exit a parse tree produced by the {@code reflexive} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void exitReflexive(KodkodParser.ReflexiveContext ctx); + /** + * Enter a parse tree produced by the {@code e_paranthesis} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void enterE_paranthesis(KodkodParser.E_paranthesisContext ctx); + /** + * Exit a parse tree produced by the {@code e_paranthesis} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void exitE_paranthesis(KodkodParser.E_paranthesisContext ctx); + /** + * Enter a parse tree produced by the {@code iden} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void enterIden(KodkodParser.IdenContext ctx); + /** + * Exit a parse tree produced by the {@code iden} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void exitIden(KodkodParser.IdenContext ctx); + /** + * Enter a parse tree produced by the {@code ints} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void enterInts(KodkodParser.IntsContext ctx); + /** + * Exit a parse tree produced by the {@code ints} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void exitInts(KodkodParser.IntsContext ctx); + /** + * Enter a parse tree produced by the {@code intersection} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void enterIntersection(KodkodParser.IntersectionContext ctx); + /** + * Exit a parse tree produced by the {@code intersection} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void exitIntersection(KodkodParser.IntersectionContext ctx); + /** + * Enter a parse tree produced by the {@code rel} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void enterRel(KodkodParser.RelContext ctx); + /** + * Exit a parse tree produced by the {@code rel} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void exitRel(KodkodParser.RelContext ctx); + /** + * Enter a parse tree produced by the {@code difference} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void enterDifference(KodkodParser.DifferenceContext ctx); + /** + * Exit a parse tree produced by the {@code difference} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void exitDifference(KodkodParser.DifferenceContext ctx); + /** + * Enter a parse tree produced by the {@code transpose} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void enterTranspose(KodkodParser.TransposeContext ctx); + /** + * Exit a parse tree produced by the {@code transpose} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void exitTranspose(KodkodParser.TransposeContext ctx); + /** + * Enter a parse tree produced by the {@code join} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void enterJoin(KodkodParser.JoinContext ctx); + /** + * Exit a parse tree produced by the {@code join} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void exitJoin(KodkodParser.JoinContext ctx); + /** + * Enter a parse tree produced by the {@code override} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void enterOverride(KodkodParser.OverrideContext ctx); + /** + * Exit a parse tree produced by the {@code override} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void exitOverride(KodkodParser.OverrideContext ctx); + /** + * Enter a parse tree produced by the {@code ifExpression} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void enterIfExpression(KodkodParser.IfExpressionContext ctx); + /** + * Exit a parse tree produced by the {@code ifExpression} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void exitIfExpression(KodkodParser.IfExpressionContext ctx); + /** + * Enter a parse tree produced by the {@code closure} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void enterClosure(KodkodParser.ClosureContext ctx); + /** + * Exit a parse tree produced by the {@code closure} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + */ + void exitClosure(KodkodParser.ClosureContext ctx); + /** + * Enter a parse tree produced by the {@code minus} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void enterMinus(KodkodParser.MinusContext ctx); + /** + * Exit a parse tree produced by the {@code minus} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void exitMinus(KodkodParser.MinusContext ctx); + /** + * Enter a parse tree produced by the {@code intConstant} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void enterIntConstant(KodkodParser.IntConstantContext ctx); + /** + * Exit a parse tree produced by the {@code intConstant} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void exitIntConstant(KodkodParser.IntConstantContext ctx); + /** + * Enter a parse tree produced by the {@code i_paranthesis} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void enterI_paranthesis(KodkodParser.I_paranthesisContext ctx); + /** + * Exit a parse tree produced by the {@code i_paranthesis} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void exitI_paranthesis(KodkodParser.I_paranthesisContext ctx); + /** + * Enter a parse tree produced by the {@code ifIntExpression} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void enterIfIntExpression(KodkodParser.IfIntExpressionContext ctx); + /** + * Exit a parse tree produced by the {@code ifIntExpression} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void exitIfIntExpression(KodkodParser.IfIntExpressionContext ctx); + /** + * Enter a parse tree produced by the {@code count} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void enterCount(KodkodParser.CountContext ctx); + /** + * Exit a parse tree produced by the {@code count} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void exitCount(KodkodParser.CountContext ctx); + /** + * Enter a parse tree produced by the {@code sum} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void enterSum(KodkodParser.SumContext ctx); + /** + * Exit a parse tree produced by the {@code sum} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void exitSum(KodkodParser.SumContext ctx); + /** + * Enter a parse tree produced by the {@code divide} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void enterDivide(KodkodParser.DivideContext ctx); + /** + * Exit a parse tree produced by the {@code divide} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void exitDivide(KodkodParser.DivideContext ctx); + /** + * Enter a parse tree produced by the {@code multiply} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void enterMultiply(KodkodParser.MultiplyContext ctx); + /** + * Exit a parse tree produced by the {@code multiply} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void exitMultiply(KodkodParser.MultiplyContext ctx); + /** + * Enter a parse tree produced by the {@code modulo} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void enterModulo(KodkodParser.ModuloContext ctx); + /** + * Exit a parse tree produced by the {@code modulo} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void exitModulo(KodkodParser.ModuloContext ctx); + /** + * Enter a parse tree produced by the {@code plus} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void enterPlus(KodkodParser.PlusContext ctx); + /** + * Exit a parse tree produced by the {@code plus} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + */ + void exitPlus(KodkodParser.PlusContext ctx); + /** + * Enter a parse tree produced by {@link KodkodParser#decls}. + * @param ctx the parse tree + */ + void enterDecls(KodkodParser.DeclsContext ctx); + /** + * Exit a parse tree produced by {@link KodkodParser#decls}. + * @param ctx the parse tree + */ + void exitDecls(KodkodParser.DeclsContext ctx); + /** + * Enter a parse tree produced by the {@code oneOf} + * labeled alternative in {@link KodkodParser#decl}. + * @param ctx the parse tree + */ + void enterOneOf(KodkodParser.OneOfContext ctx); + /** + * Exit a parse tree produced by the {@code oneOf} + * labeled alternative in {@link KodkodParser#decl}. + * @param ctx the parse tree + */ + void exitOneOf(KodkodParser.OneOfContext ctx); + /** + * Enter a parse tree produced by the {@code loneOf} + * labeled alternative in {@link KodkodParser#decl}. + * @param ctx the parse tree + */ + void enterLoneOf(KodkodParser.LoneOfContext ctx); + /** + * Exit a parse tree produced by the {@code loneOf} + * labeled alternative in {@link KodkodParser#decl}. + * @param ctx the parse tree + */ + void exitLoneOf(KodkodParser.LoneOfContext ctx); + /** + * Enter a parse tree produced by the {@code someOf} + * labeled alternative in {@link KodkodParser#decl}. + * @param ctx the parse tree + */ + void enterSomeOf(KodkodParser.SomeOfContext ctx); + /** + * Exit a parse tree produced by the {@code someOf} + * labeled alternative in {@link KodkodParser#decl}. + * @param ctx the parse tree + */ + void exitSomeOf(KodkodParser.SomeOfContext ctx); + /** + * Enter a parse tree produced by the {@code setOf} + * labeled alternative in {@link KodkodParser#decl}. + * @param ctx the parse tree + */ + void enterSetOf(KodkodParser.SetOfContext ctx); + /** + * Exit a parse tree produced by the {@code setOf} + * labeled alternative in {@link KodkodParser#decl}. + * @param ctx the parse tree + */ + void exitSetOf(KodkodParser.SetOfContext ctx); + /** + * Enter a parse tree produced by {@link KodkodParser#letDecls}. + * @param ctx the parse tree + */ + void enterLetDecls(KodkodParser.LetDeclsContext ctx); + /** + * Exit a parse tree produced by {@link KodkodParser#letDecls}. + * @param ctx the parse tree + */ + void exitLetDecls(KodkodParser.LetDeclsContext ctx); + /** + * Enter a parse tree produced by {@link KodkodParser#letDecl}. + * @param ctx the parse tree + */ + void enterLetDecl(KodkodParser.LetDeclContext ctx); + /** + * Exit a parse tree produced by {@link KodkodParser#letDecl}. + * @param ctx the parse tree + */ + void exitLetDecl(KodkodParser.LetDeclContext ctx); + /** + * Enter a parse tree produced by {@link KodkodParser#comprehensionDecls}. + * @param ctx the parse tree + */ + void enterComprehensionDecls(KodkodParser.ComprehensionDeclsContext ctx); + /** + * Exit a parse tree produced by {@link KodkodParser#comprehensionDecls}. + * @param ctx the parse tree + */ + void exitComprehensionDecls(KodkodParser.ComprehensionDeclsContext ctx); + /** + * Enter a parse tree produced by {@link KodkodParser#comprehensionDecl}. + * @param ctx the parse tree + */ + void enterComprehensionDecl(KodkodParser.ComprehensionDeclContext ctx); + /** + * Exit a parse tree produced by {@link KodkodParser#comprehensionDecl}. + * @param ctx the parse tree + */ + void exitComprehensionDecl(KodkodParser.ComprehensionDeclContext ctx); +} \ No newline at end of file diff --git a/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/KodkodParser.java b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/KodkodParser.java new file mode 100644 index 00000000..bfc99e9f --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/KodkodParser.java @@ -0,0 +1,5240 @@ +// Generated from C:/Users/anil.ozturk/IdeaProjects/untitled1/src\Kodkod.g4 by ANTLR 4.5.1 +package eu.modelwriter.kodkod.core.recognizer; +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.misc.*; +import org.antlr.v4.runtime.tree.*; +import java.util.List; +import java.util.Iterator; +import java.util.ArrayList; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class KodkodParser extends Parser { + static { RuntimeMetaData.checkVersion("4.5.1", RuntimeMetaData.VERSION); } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, + T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, + T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, + T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, T__29=30, T__30=31, + T__31=32, T__32=33, T__33=34, T__34=35, T__35=36, T__36=37, T__37=38, + T__38=39, T__39=40, T__40=41, T__41=42, T__42=43, T__43=44, T__44=45, + T__45=46, T__46=47, T__47=48, T__48=49, T__49=50, T__50=51, T__51=52, + T__52=53, T__53=54, T__54=55, T__55=56, T__56=57, T__57=58, T__58=59, + T__59=60, T__60=61, T__61=62, T__62=63, T__63=64, T__64=65, T__65=66, + T__66=67, T__67=68, T__68=69, T__69=70, INT=71, IDENTIFIER=72, DIGIT=73, + APOSTROPHE=74, MULTILINE_COMMENT=75, SINGLELINE_COMMENT=76, WS=77; + public static final int + RULE_problem = 0, RULE_options = 1, RULE_option = 2, RULE_universe = 3, + RULE_relations = 4, RULE_relation = 5, RULE_tupleSet = 6, RULE_tuple = 7, + RULE_atom = 8, RULE_relationId = 9, RULE_variableId = 10, RULE_integer = 11, + RULE_arity = 12, RULE_formula = 13, RULE_expression = 14, RULE_intexpression = 15, + RULE_decls = 16, RULE_decl = 17, RULE_letDecls = 18, RULE_letDecl = 19, + RULE_comprehensionDecls = 20, RULE_comprehensionDecl = 21; + public static final String[] ruleNames = { + "problem", "options", "option", "universe", "relations", "relation", "tupleSet", + "tuple", "atom", "relationId", "variableId", "integer", "arity", "formula", + "expression", "intexpression", "decls", "decl", "letDecls", "letDecl", + "comprehensionDecls", "comprehensionDecl" + }; + + private static final String[] _LITERAL_NAMES = { + null, "'options'", "'{'", "','", "'}'", "'symmetry_breaking'", "':'", + "'bit_width'", "'skolem_depth'", "'sharing'", "'universe'", "'['", "']'", + "'relations'", "'..'", "'('", "')'", "'no'", "'lone'", "'one'", "'some'", + "'!'", "'not'", "'in'", "'='", "'<'", "'<='", "'>'", "'>='", "'sum'", + "'|'", "'acyclic'", "'function'", "'->'", "'ord'", "'&&'", "'and'", "'||'", + "'or'", "'=>'", "'if'", "'<=>'", "'iff'", "'all'", "'let'", "'true'", + "'false'", "'~'", "'^'", "'*'", "'+'", "'&'", "'-'", "'.'", "'set'", "'++'", + "'then'", "'else'", "'iden'", "'none'", "'univ'", "'ints'", "'#'", "'plus'", + "'minus'", "'mul'", "'/'", "'div'", "'%'", "'modulo'", "'disj'", null, + null, null, "'''" + }; + private static final String[] _SYMBOLIC_NAMES = { + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, "INT", + "IDENTIFIER", "DIGIT", "APOSTROPHE", "MULTILINE_COMMENT", "SINGLELINE_COMMENT", + "WS" + }; + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + @Override + public String getGrammarFileName() { return "Kodkod.g4"; } + + @Override + public String[] getRuleNames() { return ruleNames; } + + @Override + public String getSerializedATN() { return _serializedATN; } + + @Override + public ATN getATN() { return _ATN; } + + + public java.util.Stack declarations = new java.util.Stack(); + public java.util.List atoms = new java.util.ArrayList(); + public java.util.List formulas = new java.util.ArrayList(); + public java.util.Map relations = new java.util.HashMap(); + public kodkod.instance.Universe universe = null; + public kodkod.instance.Bounds bounds = null; + + private boolean isRelation() { return this.relations.containsKey(getCurrentToken().getText()); } + private String getLocation() { return "["+ getCurrentToken().getLine()+ ","+ getCurrentToken().getCharPositionInLine()+ "]";} + private String context = null; + private int declareVariables(java.util.List vars, int var) { + System.out.println("Quantifier context: "); + for (VariableIdContext vc : vars) { + String s = vc.getText(); declarations.add(s); var++; System.out.println(s); + } + return var; + } + + public KodkodParser(TokenStream input) { + super(input); + _interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); + } + public static class ProblemContext extends ParserRuleContext { + public FormulaContext formula; + public List formulas = new ArrayList(); + public UniverseContext universe() { + return getRuleContext(UniverseContext.class,0); + } + public RelationsContext relations() { + return getRuleContext(RelationsContext.class,0); + } + public OptionsContext options() { + return getRuleContext(OptionsContext.class,0); + } + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public ProblemContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_problem; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterProblem(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitProblem(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitProblem(this); + else return visitor.visitChildren(this); + } + } + + public final ProblemContext problem() throws RecognitionException { + ProblemContext _localctx = new ProblemContext(_ctx, getState()); + enterRule(_localctx, 0, RULE_problem); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(45); + _la = _input.LA(1); + if (_la==T__0) { + { + setState(44); + options(); + } + } + + setState(47); + universe(); + System.out.println(universe); + setState(49); + relations(); + System.out.println(bounds); + setState(54); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,1,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(51); + ((ProblemContext)_localctx).formula = formula(0); + ((ProblemContext)_localctx).formulas.add(((ProblemContext)_localctx).formula); + } + } + } + setState(56); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,1,_ctx); + } + + + System.out.println("declarations= "+declarations); + declarations.clear(); + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class OptionsContext extends ParserRuleContext { + public List option() { + return getRuleContexts(OptionContext.class); + } + public OptionContext option(int i) { + return getRuleContext(OptionContext.class,i); + } + public OptionsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_options; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterOptions(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitOptions(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitOptions(this); + else return visitor.visitChildren(this); + } + } + + public final OptionsContext options() throws RecognitionException { + OptionsContext _localctx = new OptionsContext(_ctx, getState()); + enterRule(_localctx, 2, RULE_options); + try { + enterOuterAlt(_localctx, 1); + { + setState(60); + match(T__0); + setState(61); + match(T__1); + setState(62); + option(); + { + setState(63); + match(T__2); + setState(64); + option(); + } + setState(66); + match(T__3); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class OptionContext extends ParserRuleContext { + public OptionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_option; } + + public OptionContext() { } + public void copyFrom(OptionContext ctx) { + super.copyFrom(ctx); + } + } + public static class SymmetryBreakingContext extends OptionContext { + public IntegerContext integer() { + return getRuleContext(IntegerContext.class,0); + } + public SymmetryBreakingContext(OptionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterSymmetryBreaking(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitSymmetryBreaking(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitSymmetryBreaking(this); + else return visitor.visitChildren(this); + } + } + public static class BitWidthContext extends OptionContext { + public IntegerContext integer() { + return getRuleContext(IntegerContext.class,0); + } + public BitWidthContext(OptionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterBitWidth(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitBitWidth(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitBitWidth(this); + else return visitor.visitChildren(this); + } + } + public static class SkolemDepthContext extends OptionContext { + public IntegerContext integer() { + return getRuleContext(IntegerContext.class,0); + } + public SkolemDepthContext(OptionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterSkolemDepth(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitSkolemDepth(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitSkolemDepth(this); + else return visitor.visitChildren(this); + } + } + public static class SharingContext extends OptionContext { + public IntegerContext integer() { + return getRuleContext(IntegerContext.class,0); + } + public SharingContext(OptionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterSharing(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitSharing(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitSharing(this); + else return visitor.visitChildren(this); + } + } + + public final OptionContext option() throws RecognitionException { + OptionContext _localctx = new OptionContext(_ctx, getState()); + enterRule(_localctx, 4, RULE_option); + try { + setState(80); + switch (_input.LA(1)) { + case T__4: + _localctx = new SymmetryBreakingContext(_localctx); + enterOuterAlt(_localctx, 1); + { + setState(68); + match(T__4); + setState(69); + match(T__5); + setState(70); + integer(); + } + break; + case T__6: + _localctx = new BitWidthContext(_localctx); + enterOuterAlt(_localctx, 2); + { + setState(71); + match(T__6); + setState(72); + match(T__5); + setState(73); + integer(); + } + break; + case T__7: + _localctx = new SkolemDepthContext(_localctx); + enterOuterAlt(_localctx, 3); + { + setState(74); + match(T__7); + setState(75); + match(T__5); + setState(76); + integer(); + } + break; + case T__8: + _localctx = new SharingContext(_localctx); + enterOuterAlt(_localctx, 4); + { + setState(77); + match(T__8); + setState(78); + match(T__5); + setState(79); + integer(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class UniverseContext extends ParserRuleContext { + public AtomContext atom; + public List atoms = new ArrayList(); + public List atom() { + return getRuleContexts(AtomContext.class); + } + public AtomContext atom(int i) { + return getRuleContext(AtomContext.class,i); + } + public UniverseContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_universe; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterUniverse(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitUniverse(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitUniverse(this); + else return visitor.visitChildren(this); + } + } + + public final UniverseContext universe() throws RecognitionException { + UniverseContext _localctx = new UniverseContext(_ctx, getState()); + enterRule(_localctx, 6, RULE_universe); + context="universe"; + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(82); + match(T__9); + setState(105); + switch (_input.LA(1)) { + case T__1: + { + { + setState(83); + match(T__1); + { + setState(84); + ((UniverseContext)_localctx).atom = atom(); + ((UniverseContext)_localctx).atoms.add(((UniverseContext)_localctx).atom); + setState(89); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(85); + match(T__2); + setState(86); + ((UniverseContext)_localctx).atom = atom(); + ((UniverseContext)_localctx).atoms.add(((UniverseContext)_localctx).atom); + } + } + setState(91); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + setState(92); + match(T__3); + } + } + break; + case T__10: + { + { + setState(94); + match(T__10); + { + setState(95); + ((UniverseContext)_localctx).atom = atom(); + ((UniverseContext)_localctx).atoms.add(((UniverseContext)_localctx).atom); + setState(100); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(96); + match(T__2); + setState(97); + ((UniverseContext)_localctx).atom = atom(); + ((UniverseContext)_localctx).atoms.add(((UniverseContext)_localctx).atom); + } + } + setState(102); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + setState(103); + match(T__11); + } + } + break; + default: + throw new NoViableAltException(this); + } + + System.out.println("universe:"); + for (AtomContext atom : ((UniverseContext)_localctx).atoms) { + String s = atom.getText(); System.out.println(s); + if (atoms.contains(s)) {System.err.println("duplicated atom found: '"+ s + "' at "+ getLocation());} + else {atoms.add(s);} + } + this.universe = new kodkod.instance.Universe(this.atoms); + this.bounds = new kodkod.instance.Bounds(this.universe); + context = null; + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class RelationsContext extends ParserRuleContext { + public List relation() { + return getRuleContexts(RelationContext.class); + } + public RelationContext relation(int i) { + return getRuleContext(RelationContext.class,i); + } + public RelationsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_relations; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterRelations(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitRelations(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitRelations(this); + else return visitor.visitChildren(this); + } + } + + public final RelationsContext relations() throws RecognitionException { + RelationsContext _localctx = new RelationsContext(_ctx, getState()); + enterRule(_localctx, 8, RULE_relations); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(109); + match(T__12); + setState(110); + match(T__1); + setState(114); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==IDENTIFIER) { + { + { + setState(111); + relation(); + } + } + setState(116); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(117); + match(T__3); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class RelationContext extends ParserRuleContext { + public RelationIdContext relationId; + public ArityContext arity; + public TupleSetContext lowerBound; + public TupleSetContext upperBound; + public RelationIdContext relationId() { + return getRuleContext(RelationIdContext.class,0); + } + public ArityContext arity() { + return getRuleContext(ArityContext.class,0); + } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public List tupleSet() { + return getRuleContexts(TupleSetContext.class); + } + public TupleSetContext tupleSet(int i) { + return getRuleContext(TupleSetContext.class,i); + } + public RelationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_relation; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterRelation(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitRelation(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitRelation(this); + else return visitor.visitChildren(this); + } + } + + public final RelationContext relation() throws RecognitionException { + RelationContext _localctx = new RelationContext(_ctx, getState()); + enterRule(_localctx, 10, RULE_relation); + context="relations"; + int _la; + try { + enterOuterAlt(_localctx, 1); + { + { + setState(119); + ((RelationContext)_localctx).relationId = relationId(); + setState(121); + _la = _input.LA(1); + if (_la==INT) { + { + setState(120); + ((RelationContext)_localctx).arity = arity(); + } + } + + setState(123); + match(T__5); + setState(125); + switch ( getInterpreter().adaptivePredict(_input,8,_ctx) ) { + case 1: + { + setState(124); + expression(0); + } + break; + } + setState(127); + match(T__10); + { + setState(128); + ((RelationContext)_localctx).lowerBound = tupleSet(); + setState(131); + _la = _input.LA(1); + if (_la==T__2) { + { + setState(129); + match(T__2); + setState(130); + ((RelationContext)_localctx).upperBound = tupleSet(); + } + } + + } + setState(133); + match(T__11); + } + + String name = (((RelationContext)_localctx).relationId!=null?_input.getText(((RelationContext)_localctx).relationId.start,((RelationContext)_localctx).relationId.stop):null); + System.out.println("relation " + name); + if (relations.containsKey(name)) {System.err.println("duplicated relation found: '"+ name + "' at "+ getLocation());} + + kodkod.ast.Relation relation = null; + int arity = 0; + if ((((RelationContext)_localctx).arity!=null?_input.getText(((RelationContext)_localctx).arity.start,((RelationContext)_localctx).arity.stop):null) != null && !(((RelationContext)_localctx).arity!=null?_input.getText(((RelationContext)_localctx).arity.start,((RelationContext)_localctx).arity.stop):null).isEmpty()) {arity = Integer.parseInt((((RelationContext)_localctx).arity!=null?_input.getText(((RelationContext)_localctx).arity.start,((RelationContext)_localctx).arity.stop):null));} + + kodkod.instance.TupleSet lowerBound = null; + java.util.List tuplesInLowerBound = new java.util.ArrayList(); + if (((RelationContext)_localctx).lowerBound != null && !((RelationContext)_localctx).lowerBound.tuples.isEmpty()){ + if (arity == 0) {arity = ((RelationContext)_localctx).lowerBound.tuples.get(0).atoms.size();} + for (TupleContext tuple : ((RelationContext)_localctx).lowerBound.tuples) { + java.util.List atoms = new java.util.ArrayList(); + for (AtomContext atom : tuple.atoms) { + if (atom.getText() == null || atom.getText().isEmpty()) continue; + atoms.add(atom.getText()); + } + if (!atoms.isEmpty()) tuplesInLowerBound.add(this.universe.factory().tuple(atoms)); + } + lowerBound = this.universe.factory().setOf(tuplesInLowerBound); + System.out.println("lb: " +lowerBound); + } + + kodkod.instance.TupleSet upperBound = null; + java.util.List tuplesInUpperBound = new java.util.ArrayList(); + if (((RelationContext)_localctx).upperBound != null && !((RelationContext)_localctx).upperBound.tuples.isEmpty()){ + if (lowerBound == null && arity == 0) {arity = ((RelationContext)_localctx).upperBound.tuples.get(0).atoms.size();} + for (TupleContext tuple : ((RelationContext)_localctx).upperBound.tuples) { + java.util.List atoms = new java.util.ArrayList(); + for (AtomContext atom : tuple.atoms) { + if (atom.getText() == null || atom.getText().isEmpty()) continue; + atoms.add(atom.getText()); + } + if (!atoms.isEmpty()) tuplesInUpperBound.add(this.universe.factory().tuple(atoms)); + } + upperBound = this.universe.factory().setOf(tuplesInUpperBound); + System.out.println("up: " +upperBound); + } + + if (lowerBound == null && upperBound == null && arity == 0) {arity = 1;} + + if (lowerBound == null) {lowerBound = this.universe.factory().noneOf(arity);} + + System.out.println(arity); + if (arity == 0) { + System.err.println("0 arity is detected on relation: '"+ name + "' at "+ getLocation()); + } else if (arity > 0) { + relation = kodkod.ast.Relation.nary(name, arity); + } + + if (upperBound == null) {this.bounds.boundExactly(relation, lowerBound);} + else {this.bounds.bound(relation, lowerBound, upperBound);} + this.relations.put(name, relation); + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class TupleSetContext extends ParserRuleContext { + public TupleContext tuple; + public List tuples = new ArrayList(); + public TupleContext left; + public Token range; + public TupleContext right; + public List tuple() { + return getRuleContexts(TupleContext.class); + } + public TupleContext tuple(int i) { + return getRuleContext(TupleContext.class,i); + } + public TupleSetContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_tupleSet; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterTupleSet(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitTupleSet(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitTupleSet(this); + else return visitor.visitChildren(this); + } + } + + public final TupleSetContext tupleSet() throws RecognitionException { + TupleSetContext _localctx = new TupleSetContext(_ctx, getState()); + enterRule(_localctx, 12, RULE_tupleSet); + int _la; + try { + setState(173); + switch ( getInterpreter().adaptivePredict(_input,14,_ctx) ) { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(137); + match(T__1); + setState(146); + _la = _input.LA(1); + if (_la==T__10 || _la==T__14) { + { + setState(138); + ((TupleSetContext)_localctx).tuple = tuple(); + ((TupleSetContext)_localctx).tuples.add(((TupleSetContext)_localctx).tuple); + setState(143); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(139); + match(T__2); + setState(140); + ((TupleSetContext)_localctx).tuple = tuple(); + ((TupleSetContext)_localctx).tuples.add(((TupleSetContext)_localctx).tuple); + } + } + setState(145); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + + setState(148); + match(T__3); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(149); + match(T__10); + setState(158); + _la = _input.LA(1); + if (_la==T__10 || _la==T__14) { + { + setState(150); + ((TupleSetContext)_localctx).tuple = tuple(); + ((TupleSetContext)_localctx).tuples.add(((TupleSetContext)_localctx).tuple); + setState(155); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(151); + match(T__2); + setState(152); + ((TupleSetContext)_localctx).tuple = tuple(); + ((TupleSetContext)_localctx).tuples.add(((TupleSetContext)_localctx).tuple); + } + } + setState(157); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + + setState(160); + match(T__11); + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(161); + match(T__1); + setState(162); + ((TupleSetContext)_localctx).left = tuple(); + setState(163); + ((TupleSetContext)_localctx).range = match(T__13); + setState(164); + ((TupleSetContext)_localctx).right = tuple(); + setState(165); + match(T__3); + } + break; + case 4: + enterOuterAlt(_localctx, 4); + { + setState(167); + match(T__10); + setState(168); + ((TupleSetContext)_localctx).left = tuple(); + setState(169); + ((TupleSetContext)_localctx).range = match(T__13); + setState(170); + ((TupleSetContext)_localctx).right = tuple(); + setState(171); + match(T__11); + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class TupleContext extends ParserRuleContext { + public AtomContext atom; + public List atoms = new ArrayList(); + public List atom() { + return getRuleContexts(AtomContext.class); + } + public AtomContext atom(int i) { + return getRuleContext(AtomContext.class,i); + } + public TupleContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_tuple; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterTuple(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitTuple(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitTuple(this); + else return visitor.visitChildren(this); + } + } + + public final TupleContext tuple() throws RecognitionException { + TupleContext _localctx = new TupleContext(_ctx, getState()); + enterRule(_localctx, 14, RULE_tuple); + int _la; + try { + setState(197); + switch (_input.LA(1)) { + case T__14: + enterOuterAlt(_localctx, 1); + { + setState(175); + match(T__14); + setState(176); + ((TupleContext)_localctx).atom = atom(); + ((TupleContext)_localctx).atoms.add(((TupleContext)_localctx).atom); + setState(181); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(177); + match(T__2); + setState(178); + ((TupleContext)_localctx).atom = atom(); + ((TupleContext)_localctx).atoms.add(((TupleContext)_localctx).atom); + } + } + setState(183); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(184); + match(T__15); + } + break; + case T__10: + enterOuterAlt(_localctx, 2); + { + setState(186); + match(T__10); + setState(187); + ((TupleContext)_localctx).atom = atom(); + ((TupleContext)_localctx).atoms.add(((TupleContext)_localctx).atom); + setState(192); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(188); + match(T__2); + setState(189); + ((TupleContext)_localctx).atom = atom(); + ((TupleContext)_localctx).atoms.add(((TupleContext)_localctx).atom); + } + } + setState(194); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(195); + match(T__11); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class AtomContext extends ParserRuleContext { + public Token id; + public TerminalNode IDENTIFIER() { return getToken(KodkodParser.IDENTIFIER, 0); } + public TerminalNode INT() { return getToken(KodkodParser.INT, 0); } + public AtomContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_atom; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterAtom(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitAtom(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitAtom(this); + else return visitor.visitChildren(this); + } + } + + public final AtomContext atom() throws RecognitionException { + AtomContext _localctx = new AtomContext(_ctx, getState()); + enterRule(_localctx, 16, RULE_atom); + try { + setState(202); + switch (_input.LA(1)) { + case IDENTIFIER: + enterOuterAlt(_localctx, 1); + { + setState(199); + ((AtomContext)_localctx).id = match(IDENTIFIER); + + if (context != null && !context.isEmpty() && !context.equals("universe")) { + System.out.print("atom found: " + (((AtomContext)_localctx).id!=null?((AtomContext)_localctx).id.getText():null) + "-> "); + if ( atoms.contains((((AtomContext)_localctx).id!=null?((AtomContext)_localctx).id.getText():null)) ) {System.out.println("defined");} + else {System.err.println("undefined atom found: '" +(((AtomContext)_localctx).id!=null?((AtomContext)_localctx).id.getText():null) + "' at " + getLocation());} + } + + } + break; + case INT: + enterOuterAlt(_localctx, 2); + { + setState(201); + match(INT); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class RelationIdContext extends ParserRuleContext { + public TerminalNode IDENTIFIER() { return getToken(KodkodParser.IDENTIFIER, 0); } + public RelationIdContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_relationId; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterRelationId(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitRelationId(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitRelationId(this); + else return visitor.visitChildren(this); + } + } + + public final RelationIdContext relationId() throws RecognitionException { + RelationIdContext _localctx = new RelationIdContext(_ctx, getState()); + enterRule(_localctx, 18, RULE_relationId); + try { + enterOuterAlt(_localctx, 1); + { + setState(204); + match(IDENTIFIER); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class VariableIdContext extends ParserRuleContext { + public TerminalNode IDENTIFIER() { return getToken(KodkodParser.IDENTIFIER, 0); } + public VariableIdContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_variableId; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterVariableId(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitVariableId(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitVariableId(this); + else return visitor.visitChildren(this); + } + } + + public final VariableIdContext variableId() throws RecognitionException { + VariableIdContext _localctx = new VariableIdContext(_ctx, getState()); + enterRule(_localctx, 20, RULE_variableId); + try { + enterOuterAlt(_localctx, 1); + { + setState(206); + match(IDENTIFIER); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class IntegerContext extends ParserRuleContext { + public TerminalNode INT() { return getToken(KodkodParser.INT, 0); } + public IntegerContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_integer; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterInteger(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitInteger(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitInteger(this); + else return visitor.visitChildren(this); + } + } + + public final IntegerContext integer() throws RecognitionException { + IntegerContext _localctx = new IntegerContext(_ctx, getState()); + enterRule(_localctx, 22, RULE_integer); + try { + enterOuterAlt(_localctx, 1); + { + setState(208); + match(INT); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ArityContext extends ParserRuleContext { + public TerminalNode INT() { return getToken(KodkodParser.INT, 0); } + public ArityContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_arity; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterArity(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitArity(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitArity(this); + else return visitor.visitChildren(this); + } + } + + public final ArityContext arity() throws RecognitionException { + ArityContext _localctx = new ArityContext(_ctx, getState()); + enterRule(_localctx, 24, RULE_arity); + try { + enterOuterAlt(_localctx, 1); + { + setState(210); + match(INT); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class FormulaContext extends ParserRuleContext { + public int var = 0;; + public FormulaContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_formula; } + + public FormulaContext() { } + public void copyFrom(FormulaContext ctx) { + super.copyFrom(ctx); + this.var = ctx.var; + } + } + public static class NoContext extends FormulaContext { + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public NoContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterNo(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitNo(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitNo(this); + else return visitor.visitChildren(this); + } + } + public static class SomeContext extends FormulaContext { + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public SomeContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterSome(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitSome(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitSome(this); + else return visitor.visitChildren(this); + } + } + public static class ForOneContext extends FormulaContext { + public DeclsContext decls() { + return getRuleContext(DeclsContext.class,0); + } + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public ForOneContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterForOne(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitForOne(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitForOne(this); + else return visitor.visitChildren(this); + } + } + public static class SumDeclarationContext extends FormulaContext { + public DeclsContext decls() { + return getRuleContext(DeclsContext.class,0); + } + public IntexpressionContext intexpression() { + return getRuleContext(IntexpressionContext.class,0); + } + public SumDeclarationContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterSumDeclaration(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitSumDeclaration(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitSumDeclaration(this); + else return visitor.visitChildren(this); + } + } + public static class ForAllContext extends FormulaContext { + public DeclsContext decls() { + return getRuleContext(DeclsContext.class,0); + } + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public ForAllContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterForAll(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitForAll(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitForAll(this); + else return visitor.visitChildren(this); + } + } + public static class LoneContext extends FormulaContext { + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public LoneContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterLone(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitLone(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitLone(this); + else return visitor.visitChildren(this); + } + } + public static class LtContext extends FormulaContext { + public IntexpressionContext left; + public Token not; + public IntexpressionContext right; + public List intexpression() { + return getRuleContexts(IntexpressionContext.class); + } + public IntexpressionContext intexpression(int i) { + return getRuleContext(IntexpressionContext.class,i); + } + public LtContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterLt(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitLt(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitLt(this); + else return visitor.visitChildren(this); + } + } + public static class ForSomeContext extends FormulaContext { + public DeclsContext decls() { + return getRuleContext(DeclsContext.class,0); + } + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public ForSomeContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterForSome(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitForSome(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitForSome(this); + else return visitor.visitChildren(this); + } + } + public static class NotContext extends FormulaContext { + public Token op; + public FormulaContext formula() { + return getRuleContext(FormulaContext.class,0); + } + public NotContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterNot(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitNot(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitNot(this); + else return visitor.visitChildren(this); + } + } + public static class F_paranthesisContext extends FormulaContext { + public FormulaContext formula() { + return getRuleContext(FormulaContext.class,0); + } + public F_paranthesisContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterF_paranthesis(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitF_paranthesis(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitF_paranthesis(this); + else return visitor.visitChildren(this); + } + } + public static class AndContext extends FormulaContext { + public FormulaContext left; + public Token op; + public FormulaContext right; + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public AndContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterAnd(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitAnd(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitAnd(this); + else return visitor.visitChildren(this); + } + } + public static class FunctionContext extends FormulaContext { + public RelationIdContext rel; + public ExpressionContext domain; + public Token op; + public ExpressionContext range; + public RelationIdContext relationId() { + return getRuleContext(RelationIdContext.class,0); + } + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public FunctionContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterFunction(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitFunction(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitFunction(this); + else return visitor.visitChildren(this); + } + } + public static class GteContext extends FormulaContext { + public IntexpressionContext left; + public Token not; + public IntexpressionContext right; + public List intexpression() { + return getRuleContexts(IntexpressionContext.class); + } + public IntexpressionContext intexpression(int i) { + return getRuleContext(IntexpressionContext.class,i); + } + public GteContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterGte(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitGte(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitGte(this); + else return visitor.visitChildren(this); + } + } + public static class AcyclicContext extends FormulaContext { + public RelationIdContext relationId() { + return getRuleContext(RelationIdContext.class,0); + } + public AcyclicContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterAcyclic(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitAcyclic(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitAcyclic(this); + else return visitor.visitChildren(this); + } + } + public static class LetContext extends FormulaContext { + public LetDeclsContext letDecls() { + return getRuleContext(LetDeclsContext.class,0); + } + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public LetContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterLet(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitLet(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitLet(this); + else return visitor.visitChildren(this); + } + } + public static class LteContext extends FormulaContext { + public IntexpressionContext left; + public Token not; + public IntexpressionContext right; + public List intexpression() { + return getRuleContexts(IntexpressionContext.class); + } + public IntexpressionContext intexpression(int i) { + return getRuleContext(IntexpressionContext.class,i); + } + public LteContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterLte(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitLte(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitLte(this); + else return visitor.visitChildren(this); + } + } + public static class OrContext extends FormulaContext { + public FormulaContext left; + public Token op; + public FormulaContext right; + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public OrContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterOr(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitOr(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitOr(this); + else return visitor.visitChildren(this); + } + } + public static class InContext extends FormulaContext { + public ExpressionContext left; + public Token not; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public InContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterIn(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitIn(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitIn(this); + else return visitor.visitChildren(this); + } + } + public static class OneContext extends FormulaContext { + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public OneContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterOne(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitOne(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitOne(this); + else return visitor.visitChildren(this); + } + } + public static class FalseContext extends FormulaContext { + public FalseContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterFalse(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitFalse(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitFalse(this); + else return visitor.visitChildren(this); + } + } + public static class IffContext extends FormulaContext { + public FormulaContext left; + public Token op; + public FormulaContext right; + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public IffContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterIff(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitIff(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitIff(this); + else return visitor.visitChildren(this); + } + } + public static class EqContext extends FormulaContext { + public IntexpressionContext left; + public Token not; + public IntexpressionContext right; + public List intexpression() { + return getRuleContexts(IntexpressionContext.class); + } + public IntexpressionContext intexpression(int i) { + return getRuleContext(IntexpressionContext.class,i); + } + public EqContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterEq(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitEq(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitEq(this); + else return visitor.visitChildren(this); + } + } + public static class GtContext extends FormulaContext { + public IntexpressionContext left; + public Token not; + public IntexpressionContext right; + public List intexpression() { + return getRuleContexts(IntexpressionContext.class); + } + public IntexpressionContext intexpression(int i) { + return getRuleContext(IntexpressionContext.class,i); + } + public GtContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterGt(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitGt(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitGt(this); + else return visitor.visitChildren(this); + } + } + public static class EqualContext extends FormulaContext { + public ExpressionContext left; + public Token not; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public EqualContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterEqual(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitEqual(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitEqual(this); + else return visitor.visitChildren(this); + } + } + public static class ForLoneContext extends FormulaContext { + public DeclsContext decls() { + return getRuleContext(DeclsContext.class,0); + } + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public ForLoneContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterForLone(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitForLone(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitForLone(this); + else return visitor.visitChildren(this); + } + } + public static class TotalOrderContext extends FormulaContext { + public RelationIdContext rel; + public RelationIdContext ordered; + public RelationIdContext first; + public RelationIdContext last; + public List relationId() { + return getRuleContexts(RelationIdContext.class); + } + public RelationIdContext relationId(int i) { + return getRuleContext(RelationIdContext.class,i); + } + public TotalOrderContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterTotalOrder(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitTotalOrder(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitTotalOrder(this); + else return visitor.visitChildren(this); + } + } + public static class TrueContext extends FormulaContext { + public TrueContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterTrue(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitTrue(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitTrue(this); + else return visitor.visitChildren(this); + } + } + public static class ForNoContext extends FormulaContext { + public DeclsContext decls() { + return getRuleContext(DeclsContext.class,0); + } + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public ForNoContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterForNo(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitForNo(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitForNo(this); + else return visitor.visitChildren(this); + } + } + public static class ImpliesContext extends FormulaContext { + public FormulaContext left; + public Token op; + public FormulaContext right; + public List formula() { + return getRuleContexts(FormulaContext.class); + } + public FormulaContext formula(int i) { + return getRuleContext(FormulaContext.class,i); + } + public ImpliesContext(FormulaContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterImplies(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitImplies(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitImplies(this); + else return visitor.visitChildren(this); + } + } + + public final FormulaContext formula() throws RecognitionException { + return formula(0); + } + + private FormulaContext formula(int _p) throws RecognitionException { + ParserRuleContext _parentctx = _ctx; + int _parentState = getState(); + FormulaContext _localctx = new FormulaContext(_ctx, _parentState); + FormulaContext _prevctx = _localctx; + int _startState = 26; + enterRecursionRule(_localctx, 26, RULE_formula, _p); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(474); + switch ( getInterpreter().adaptivePredict(_input,50,_ctx) ) { + case 1: + { + _localctx = new NotContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + + setState(213); + ((NotContext)_localctx).op = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__20 || _la==T__21) ) { + ((NotContext)_localctx).op = (Token)_errHandler.recoverInline(this); + } else { + consume(); + } + setState(214); + formula(14); + } + break; + case 2: + { + _localctx = new NoContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(215); + match(T__16); + setState(216); + expression(0); + } + break; + case 3: + { + _localctx = new LoneContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(217); + match(T__17); + setState(218); + expression(0); + } + break; + case 4: + { + _localctx = new OneContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(219); + match(T__18); + setState(220); + expression(0); + } + break; + case 5: + { + _localctx = new SomeContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(221); + match(T__19); + setState(222); + expression(0); + } + break; + case 6: + { + _localctx = new InContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(223); + ((InContext)_localctx).left = expression(0); + setState(225); + _la = _input.LA(1); + if (_la==T__20 || _la==T__21) { + { + setState(224); + ((InContext)_localctx).not = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__20 || _la==T__21) ) { + ((InContext)_localctx).not = (Token)_errHandler.recoverInline(this); + } else { + consume(); + } + } + } + + setState(227); + match(T__22); + setState(228); + ((InContext)_localctx).right = expression(0); + } + break; + case 7: + { + _localctx = new EqualContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(230); + ((EqualContext)_localctx).left = expression(0); + setState(232); + _la = _input.LA(1); + if (_la==T__20 || _la==T__21) { + { + setState(231); + ((EqualContext)_localctx).not = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__20 || _la==T__21) ) { + ((EqualContext)_localctx).not = (Token)_errHandler.recoverInline(this); + } else { + consume(); + } + } + } + + setState(234); + match(T__23); + setState(235); + ((EqualContext)_localctx).right = expression(0); + } + break; + case 8: + { + _localctx = new EqContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(237); + ((EqContext)_localctx).left = intexpression(0); + setState(239); + _la = _input.LA(1); + if (_la==T__20 || _la==T__21) { + { + setState(238); + ((EqContext)_localctx).not = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__20 || _la==T__21) ) { + ((EqContext)_localctx).not = (Token)_errHandler.recoverInline(this); + } else { + consume(); + } + } + } + + setState(241); + match(T__23); + setState(242); + ((EqContext)_localctx).right = intexpression(0); + } + break; + case 9: + { + _localctx = new LtContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(244); + ((LtContext)_localctx).left = intexpression(0); + setState(246); + _la = _input.LA(1); + if (_la==T__20 || _la==T__21) { + { + setState(245); + ((LtContext)_localctx).not = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__20 || _la==T__21) ) { + ((LtContext)_localctx).not = (Token)_errHandler.recoverInline(this); + } else { + consume(); + } + } + } + + setState(248); + match(T__24); + setState(249); + ((LtContext)_localctx).right = intexpression(0); + } + break; + case 10: + { + _localctx = new LteContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(251); + ((LteContext)_localctx).left = intexpression(0); + setState(253); + _la = _input.LA(1); + if (_la==T__20 || _la==T__21) { + { + setState(252); + ((LteContext)_localctx).not = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__20 || _la==T__21) ) { + ((LteContext)_localctx).not = (Token)_errHandler.recoverInline(this); + } else { + consume(); + } + } + } + + setState(255); + match(T__25); + setState(256); + ((LteContext)_localctx).right = intexpression(0); + } + break; + case 11: + { + _localctx = new GtContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(258); + ((GtContext)_localctx).left = intexpression(0); + setState(260); + _la = _input.LA(1); + if (_la==T__20 || _la==T__21) { + { + setState(259); + ((GtContext)_localctx).not = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__20 || _la==T__21) ) { + ((GtContext)_localctx).not = (Token)_errHandler.recoverInline(this); + } else { + consume(); + } + } + } + + setState(262); + match(T__26); + setState(263); + ((GtContext)_localctx).right = intexpression(0); + } + break; + case 12: + { + _localctx = new GteContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(265); + ((GteContext)_localctx).left = intexpression(0); + setState(267); + _la = _input.LA(1); + if (_la==T__20 || _la==T__21) { + { + setState(266); + ((GteContext)_localctx).not = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__20 || _la==T__21) ) { + ((GteContext)_localctx).not = (Token)_errHandler.recoverInline(this); + } else { + consume(); + } + } + } + + setState(269); + match(T__27); + setState(270); + ((GteContext)_localctx).right = intexpression(0); + } + break; + case 13: + { + _localctx = new SumDeclarationContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + ((FormulaContext)getInvokingContext(13)).var = 0; + { + setState(273); + match(T__28); + setState(274); + decls(); + setState(275); + match(T__29); + setState(276); + intexpression(0); + } + for (int i = 0; i < ((FormulaContext)getInvokingContext(13)).var; i++) declarations.pop(); + } + break; + case 14: + { + _localctx = new AcyclicContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(280); + match(T__30); + setState(281); + match(T__10); + setState(282); + relationId(); + setState(283); + match(T__11); + } + break; + case 15: + { + _localctx = new FunctionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(285); + match(T__31); + setState(286); + match(T__10); + setState(287); + ((FunctionContext)_localctx).rel = relationId(); + setState(288); + match(T__5); + setState(289); + ((FunctionContext)_localctx).domain = expression(0); + setState(290); + match(T__32); + setState(291); + ((FunctionContext)_localctx).op = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__17 || _la==T__18) ) { + ((FunctionContext)_localctx).op = (Token)_errHandler.recoverInline(this); + } else { + consume(); + } + setState(292); + ((FunctionContext)_localctx).range = expression(0); + setState(293); + match(T__11); + } + break; + case 16: + { + _localctx = new TotalOrderContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(295); + match(T__33); + setState(296); + match(T__10); + setState(297); + ((TotalOrderContext)_localctx).rel = relationId(); + setState(298); + match(T__2); + setState(299); + ((TotalOrderContext)_localctx).ordered = relationId(); + setState(300); + match(T__2); + setState(301); + ((TotalOrderContext)_localctx).first = relationId(); + setState(302); + match(T__2); + setState(303); + ((TotalOrderContext)_localctx).last = relationId(); + setState(304); + match(T__11); + } + break; + case 17: + { + _localctx = new ForAllContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + ((FormulaContext)getInvokingContext(13)).var = 0; + { + setState(307); + match(T__42); + setState(308); + decls(); + setState(329); + switch (_input.LA(1)) { + case T__29: + { + setState(309); + match(T__29); + setState(319); + switch ( getInterpreter().adaptivePredict(_input,27,_ctx) ) { + case 1: + { + setState(310); + formula(0); + } + break; + case 2: + { + setState(311); + match(T__1); + setState(315); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,26,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(312); + formula(0); + } + } + } + setState(317); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,26,_ctx); + } + setState(318); + match(T__3); + } + break; + } + } + break; + case T__1: + { + setState(321); + match(T__1); + setState(325); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,28,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(322); + formula(0); + } + } + } + setState(327); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,28,_ctx); + } + setState(328); + match(T__3); + } + break; + default: + throw new NoViableAltException(this); + } + } + for (int i = 0; i < ((FormulaContext)getInvokingContext(13)).var; i++) declarations.pop(); + } + break; + case 18: + { + _localctx = new ForSomeContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + ((FormulaContext)getInvokingContext(13)).var = 0; + { + setState(334); + match(T__19); + setState(335); + decls(); + setState(356); + switch (_input.LA(1)) { + case T__29: + { + setState(336); + match(T__29); + setState(346); + switch ( getInterpreter().adaptivePredict(_input,31,_ctx) ) { + case 1: + { + setState(337); + formula(0); + } + break; + case 2: + { + setState(338); + match(T__1); + setState(342); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,30,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(339); + formula(0); + } + } + } + setState(344); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,30,_ctx); + } + setState(345); + match(T__3); + } + break; + } + } + break; + case T__1: + { + setState(348); + match(T__1); + setState(352); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,32,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(349); + formula(0); + } + } + } + setState(354); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,32,_ctx); + } + setState(355); + match(T__3); + } + break; + default: + throw new NoViableAltException(this); + } + } + for (int i = 0; i < ((FormulaContext)getInvokingContext(13)).var; i++) declarations.pop(); + } + break; + case 19: + { + _localctx = new ForNoContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + ((FormulaContext)getInvokingContext(13)).var = 0; + { + setState(361); + match(T__16); + setState(362); + decls(); + setState(383); + switch (_input.LA(1)) { + case T__29: + { + setState(363); + match(T__29); + setState(373); + switch ( getInterpreter().adaptivePredict(_input,35,_ctx) ) { + case 1: + { + setState(364); + formula(0); + } + break; + case 2: + { + setState(365); + match(T__1); + setState(369); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,34,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(366); + formula(0); + } + } + } + setState(371); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,34,_ctx); + } + setState(372); + match(T__3); + } + break; + } + } + break; + case T__1: + { + setState(375); + match(T__1); + setState(379); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,36,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(376); + formula(0); + } + } + } + setState(381); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,36,_ctx); + } + setState(382); + match(T__3); + } + break; + default: + throw new NoViableAltException(this); + } + } + for (int i = 0; i < ((FormulaContext)getInvokingContext(13)).var; i++) declarations.pop(); + } + break; + case 20: + { + _localctx = new ForOneContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + ((FormulaContext)getInvokingContext(13)).var = 0; + { + setState(388); + match(T__18); + setState(389); + decls(); + setState(410); + switch (_input.LA(1)) { + case T__29: + { + setState(390); + match(T__29); + setState(400); + switch ( getInterpreter().adaptivePredict(_input,39,_ctx) ) { + case 1: + { + setState(391); + formula(0); + } + break; + case 2: + { + setState(392); + match(T__1); + setState(396); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,38,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(393); + formula(0); + } + } + } + setState(398); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,38,_ctx); + } + setState(399); + match(T__3); + } + break; + } + } + break; + case T__1: + { + setState(402); + match(T__1); + setState(406); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,40,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(403); + formula(0); + } + } + } + setState(408); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,40,_ctx); + } + setState(409); + match(T__3); + } + break; + default: + throw new NoViableAltException(this); + } + } + for (int i = 0; i < ((FormulaContext)getInvokingContext(13)).var; i++) declarations.pop(); + } + break; + case 21: + { + _localctx = new ForLoneContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + ((FormulaContext)getInvokingContext(13)).var = 0; + { + setState(415); + match(T__17); + setState(416); + decls(); + setState(437); + switch (_input.LA(1)) { + case T__29: + { + setState(417); + match(T__29); + setState(427); + switch ( getInterpreter().adaptivePredict(_input,43,_ctx) ) { + case 1: + { + setState(418); + formula(0); + } + break; + case 2: + { + setState(419); + match(T__1); + setState(423); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,42,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(420); + formula(0); + } + } + } + setState(425); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,42,_ctx); + } + setState(426); + match(T__3); + } + break; + } + } + break; + case T__1: + { + setState(429); + match(T__1); + setState(433); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,44,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(430); + formula(0); + } + } + } + setState(435); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,44,_ctx); + } + setState(436); + match(T__3); + } + break; + default: + throw new NoViableAltException(this); + } + } + for (int i = 0; i < ((FormulaContext)getInvokingContext(13)).var; i++) declarations.pop(); + } + break; + case 22: + { + _localctx = new LetContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + ((FormulaContext)getInvokingContext(13)).var = 0; + { + setState(442); + match(T__43); + setState(443); + letDecls(); + setState(464); + switch (_input.LA(1)) { + case T__29: + { + setState(444); + match(T__29); + setState(454); + switch ( getInterpreter().adaptivePredict(_input,47,_ctx) ) { + case 1: + { + setState(445); + formula(0); + } + break; + case 2: + { + setState(446); + match(T__1); + setState(450); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,46,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(447); + formula(0); + } + } + } + setState(452); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,46,_ctx); + } + setState(453); + match(T__3); + } + break; + } + } + break; + case T__1: + { + setState(456); + match(T__1); + setState(460); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,48,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + setState(457); + formula(0); + } + } + } + setState(462); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,48,_ctx); + } + setState(463); + match(T__3); + } + break; + default: + throw new NoViableAltException(this); + } + } + for (int i = 0; i < ((FormulaContext)getInvokingContext(13)).var; i++) declarations.pop(); + } + break; + case 23: + { + _localctx = new TrueContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(468); + match(T__44); + } + break; + case 24: + { + _localctx = new FalseContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(469); + match(T__45); + } + break; + case 25: + { + _localctx = new F_paranthesisContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(470); + match(T__14); + setState(471); + formula(0); + setState(472); + match(T__15); + } + break; + } + _ctx.stop = _input.LT(-1); + setState(490); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,52,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + if ( _parseListeners!=null ) triggerExitRuleEvent(); + _prevctx = _localctx; + { + setState(488); + switch ( getInterpreter().adaptivePredict(_input,51,_ctx) ) { + case 1: + { + _localctx = new AndContext(new FormulaContext(_parentctx, _parentState)); + ((AndContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_formula); + setState(476); + if (!(precpred(_ctx, 13))) throw new FailedPredicateException(this, "precpred(_ctx, 13)"); + setState(477); + ((AndContext)_localctx).op = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__34 || _la==T__35) ) { + ((AndContext)_localctx).op = (Token)_errHandler.recoverInline(this); + } else { + consume(); + } + setState(478); + ((AndContext)_localctx).right = formula(13); + } + break; + case 2: + { + _localctx = new OrContext(new FormulaContext(_parentctx, _parentState)); + ((OrContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_formula); + setState(479); + if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)"); + setState(480); + ((OrContext)_localctx).op = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__36 || _la==T__37) ) { + ((OrContext)_localctx).op = (Token)_errHandler.recoverInline(this); + } else { + consume(); + } + setState(481); + ((OrContext)_localctx).right = formula(12); + } + break; + case 3: + { + _localctx = new ImpliesContext(new FormulaContext(_parentctx, _parentState)); + ((ImpliesContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_formula); + setState(482); + if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)"); + setState(483); + ((ImpliesContext)_localctx).op = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__38 || _la==T__39) ) { + ((ImpliesContext)_localctx).op = (Token)_errHandler.recoverInline(this); + } else { + consume(); + } + setState(484); + ((ImpliesContext)_localctx).right = formula(11); + } + break; + case 4: + { + _localctx = new IffContext(new FormulaContext(_parentctx, _parentState)); + ((IffContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_formula); + setState(485); + if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); + setState(486); + ((IffContext)_localctx).op = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__40 || _la==T__41) ) { + ((IffContext)_localctx).op = (Token)_errHandler.recoverInline(this); + } else { + consume(); + } + setState(487); + ((IffContext)_localctx).right = formula(10); + } + break; + } + } + } + setState(492); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,52,_ctx); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + unrollRecursionContexts(_parentctx); + } + return _localctx; + } + + public static class ExpressionContext extends ParserRuleContext { + public ExpressionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_expression; } + + public ExpressionContext() { } + public void copyFrom(ExpressionContext ctx) { + super.copyFrom(ctx); + } + } + public static class ProductContext extends ExpressionContext { + public ExpressionContext left; + public Token leftMult; + public Token rightMult; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public ProductContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterProduct(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitProduct(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitProduct(this); + else return visitor.visitChildren(this); + } + } + public static class VarContext extends ExpressionContext { + public VariableIdContext variableId; + public VariableIdContext variableId() { + return getRuleContext(VariableIdContext.class,0); + } + public VarContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterVar(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitVar(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitVar(this); + else return visitor.visitChildren(this); + } + } + public static class NoneContext extends ExpressionContext { + public NoneContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterNone(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitNone(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitNone(this); + else return visitor.visitChildren(this); + } + } + public static class UnionContext extends ExpressionContext { + public ExpressionContext left; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public UnionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterUnion(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitUnion(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitUnion(this); + else return visitor.visitChildren(this); + } + } + public static class BoxjoinContext extends ExpressionContext { + public ExpressionContext right; + public ExpressionContext left; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public BoxjoinContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterBoxjoin(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitBoxjoin(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitBoxjoin(this); + else return visitor.visitChildren(this); + } + } + public static class ComprehensionContext extends ExpressionContext { + public ComprehensionDeclsContext comprehensionDecls() { + return getRuleContext(ComprehensionDeclsContext.class,0); + } + public FormulaContext formula() { + return getRuleContext(FormulaContext.class,0); + } + public ComprehensionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterComprehension(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitComprehension(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitComprehension(this); + else return visitor.visitChildren(this); + } + } + public static class UnivContext extends ExpressionContext { + public UnivContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterUniv(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitUniv(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitUniv(this); + else return visitor.visitChildren(this); + } + } + public static class ReflexiveContext extends ExpressionContext { + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public ReflexiveContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterReflexive(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitReflexive(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitReflexive(this); + else return visitor.visitChildren(this); + } + } + public static class E_paranthesisContext extends ExpressionContext { + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public E_paranthesisContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterE_paranthesis(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitE_paranthesis(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitE_paranthesis(this); + else return visitor.visitChildren(this); + } + } + public static class IdenContext extends ExpressionContext { + public IdenContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterIden(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitIden(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitIden(this); + else return visitor.visitChildren(this); + } + } + public static class IntsContext extends ExpressionContext { + public IntsContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterInts(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitInts(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitInts(this); + else return visitor.visitChildren(this); + } + } + public static class IntersectionContext extends ExpressionContext { + public ExpressionContext left; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public IntersectionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterIntersection(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitIntersection(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitIntersection(this); + else return visitor.visitChildren(this); + } + } + public static class RelContext extends ExpressionContext { + public RelationIdContext relationId() { + return getRuleContext(RelationIdContext.class,0); + } + public RelContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterRel(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitRel(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitRel(this); + else return visitor.visitChildren(this); + } + } + public static class DifferenceContext extends ExpressionContext { + public ExpressionContext left; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public DifferenceContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterDifference(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitDifference(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitDifference(this); + else return visitor.visitChildren(this); + } + } + public static class TransposeContext extends ExpressionContext { + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public TransposeContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterTranspose(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitTranspose(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitTranspose(this); + else return visitor.visitChildren(this); + } + } + public static class JoinContext extends ExpressionContext { + public ExpressionContext left; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public JoinContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterJoin(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitJoin(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitJoin(this); + else return visitor.visitChildren(this); + } + } + public static class OverrideContext extends ExpressionContext { + public ExpressionContext left; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public OverrideContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterOverride(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitOverride(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitOverride(this); + else return visitor.visitChildren(this); + } + } + public static class IfExpressionContext extends ExpressionContext { + public Token op; + public FormulaContext condition; + public ExpressionContext thenExpr; + public ExpressionContext elseExpr; + public FormulaContext formula() { + return getRuleContext(FormulaContext.class,0); + } + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public IfExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterIfExpression(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitIfExpression(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitIfExpression(this); + else return visitor.visitChildren(this); + } + } + public static class ClosureContext extends ExpressionContext { + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public ClosureContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterClosure(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitClosure(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitClosure(this); + else return visitor.visitChildren(this); + } + } + + public final ExpressionContext expression() throws RecognitionException { + return expression(0); + } + + private ExpressionContext expression(int _p) throws RecognitionException { + ParserRuleContext _parentctx = _ctx; + int _parentState = getState(); + ExpressionContext _localctx = new ExpressionContext(_ctx, _parentState); + ExpressionContext _prevctx = _localctx; + int _startState = 28; + enterRecursionRule(_localctx, 28, RULE_expression, _p); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(530); + switch ( getInterpreter().adaptivePredict(_input,53,_ctx) ) { + case 1: + { + _localctx = new TransposeContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + + setState(494); + match(T__46); + setState(495); + expression(17); + } + break; + case 2: + { + _localctx = new ClosureContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(496); + match(T__47); + setState(497); + expression(16); + } + break; + case 3: + { + _localctx = new ReflexiveContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(498); + match(T__48); + setState(499); + expression(15); + } + break; + case 4: + { + _localctx = new IfExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(500); + ((IfExpressionContext)_localctx).op = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__38 || _la==T__39) ) { + ((IfExpressionContext)_localctx).op = (Token)_errHandler.recoverInline(this); + } else { + consume(); + } + setState(501); + ((IfExpressionContext)_localctx).condition = formula(0); + setState(502); + match(T__55); + setState(503); + ((IfExpressionContext)_localctx).thenExpr = expression(0); + setState(504); + match(T__56); + setState(505); + ((IfExpressionContext)_localctx).elseExpr = expression(6); + } + break; + case 5: + { + _localctx = new VarContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(507); + if (!(!isRelation())) throw new FailedPredicateException(this, "!isRelation()"); + setState(508); + ((VarContext)_localctx).variableId = variableId(); + + System.out.print("variable found: " + (((VarContext)_localctx).variableId!=null?_input.getText(((VarContext)_localctx).variableId.start,((VarContext)_localctx).variableId.stop):null) + "-> "); + String s = (((VarContext)_localctx).variableId!=null?_input.getText(((VarContext)_localctx).variableId.start,((VarContext)_localctx).variableId.stop):null); + if ( declarations.contains(s) ) {System.out.println("defined");} + else {System.err.println("undefined variable found: '"+ s + "' at "+ getLocation());} + + } + break; + case 6: + { + _localctx = new RelContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(511); + if (!(isRelation())) throw new FailedPredicateException(this, "isRelation()"); + setState(512); + relationId(); + } + break; + case 7: + { + _localctx = new ComprehensionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + ((FormulaContext)getInvokingContext(13)).var = 0; + { + setState(514); + match(T__1); + setState(515); + comprehensionDecls(); + setState(516); + match(T__29); + setState(517); + formula(0); + setState(518); + match(T__3); + } + for (int i = 0; i < ((FormulaContext)getInvokingContext(13)).var; i++) declarations.pop(); + } + break; + case 8: + { + _localctx = new IdenContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(522); + match(T__57); + } + break; + case 9: + { + _localctx = new NoneContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(523); + match(T__58); + } + break; + case 10: + { + _localctx = new UnivContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(524); + match(T__59); + } + break; + case 11: + { + _localctx = new IntsContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(525); + match(T__60); + } + break; + case 12: + { + _localctx = new E_paranthesisContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(526); + match(T__14); + setState(527); + expression(0); + setState(528); + match(T__15); + } + break; + } + _ctx.stop = _input.LT(-1); + setState(563); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,57,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + if ( _parseListeners!=null ) triggerExitRuleEvent(); + _prevctx = _localctx; + { + setState(561); + switch ( getInterpreter().adaptivePredict(_input,56,_ctx) ) { + case 1: + { + _localctx = new UnionContext(new ExpressionContext(_parentctx, _parentState)); + ((UnionContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(532); + if (!(precpred(_ctx, 14))) throw new FailedPredicateException(this, "precpred(_ctx, 14)"); + setState(533); + match(T__49); + setState(534); + ((UnionContext)_localctx).right = expression(15); + } + break; + case 2: + { + _localctx = new IntersectionContext(new ExpressionContext(_parentctx, _parentState)); + ((IntersectionContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(535); + if (!(precpred(_ctx, 13))) throw new FailedPredicateException(this, "precpred(_ctx, 13)"); + setState(536); + match(T__50); + setState(537); + ((IntersectionContext)_localctx).right = expression(14); + } + break; + case 3: + { + _localctx = new DifferenceContext(new ExpressionContext(_parentctx, _parentState)); + ((DifferenceContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(538); + if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)"); + setState(539); + match(T__51); + setState(540); + ((DifferenceContext)_localctx).right = expression(13); + } + break; + case 4: + { + _localctx = new JoinContext(new ExpressionContext(_parentctx, _parentState)); + ((JoinContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(541); + if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)"); + setState(542); + match(T__52); + setState(543); + ((JoinContext)_localctx).right = expression(12); + } + break; + case 5: + { + _localctx = new ProductContext(new ExpressionContext(_parentctx, _parentState)); + ((ProductContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(544); + if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); + setState(546); + _la = _input.LA(1); + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__53))) != 0)) { + { + setState(545); + ((ProductContext)_localctx).leftMult = _input.LT(1); + _la = _input.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__53))) != 0)) ) { + ((ProductContext)_localctx).leftMult = (Token)_errHandler.recoverInline(this); + } else { + consume(); + } + } + } + + setState(548); + match(T__32); + setState(550); + switch ( getInterpreter().adaptivePredict(_input,55,_ctx) ) { + case 1: + { + setState(549); + ((ProductContext)_localctx).rightMult = _input.LT(1); + _la = _input.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__53))) != 0)) ) { + ((ProductContext)_localctx).rightMult = (Token)_errHandler.recoverInline(this); + } else { + consume(); + } + } + break; + } + setState(552); + ((ProductContext)_localctx).right = expression(9); + } + break; + case 6: + { + _localctx = new OverrideContext(new ExpressionContext(_parentctx, _parentState)); + ((OverrideContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(553); + if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)"); + setState(554); + match(T__54); + setState(555); + ((OverrideContext)_localctx).right = expression(9); + } + break; + case 7: + { + _localctx = new BoxjoinContext(new ExpressionContext(_parentctx, _parentState)); + ((BoxjoinContext)_localctx).right = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(556); + if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); + setState(557); + match(T__10); + setState(558); + ((BoxjoinContext)_localctx).left = expression(0); + setState(559); + match(T__11); + } + break; + } + } + } + setState(565); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,57,_ctx); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + unrollRecursionContexts(_parentctx); + } + return _localctx; + } + + public static class IntexpressionContext extends ParserRuleContext { + public IntexpressionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_intexpression; } + + public IntexpressionContext() { } + public void copyFrom(IntexpressionContext ctx) { + super.copyFrom(ctx); + } + } + public static class MinusContext extends IntexpressionContext { + public IntexpressionContext left; + public IntexpressionContext right; + public List intexpression() { + return getRuleContexts(IntexpressionContext.class); + } + public IntexpressionContext intexpression(int i) { + return getRuleContext(IntexpressionContext.class,i); + } + public MinusContext(IntexpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterMinus(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitMinus(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitMinus(this); + else return visitor.visitChildren(this); + } + } + public static class IntConstantContext extends IntexpressionContext { + public Token sign; + public IntegerContext integer() { + return getRuleContext(IntegerContext.class,0); + } + public IntConstantContext(IntexpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterIntConstant(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitIntConstant(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitIntConstant(this); + else return visitor.visitChildren(this); + } + } + public static class I_paranthesisContext extends IntexpressionContext { + public IntexpressionContext intexpression() { + return getRuleContext(IntexpressionContext.class,0); + } + public I_paranthesisContext(IntexpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterI_paranthesis(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitI_paranthesis(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitI_paranthesis(this); + else return visitor.visitChildren(this); + } + } + public static class IfIntExpressionContext extends IntexpressionContext { + public Token op; + public FormulaContext condition; + public IntexpressionContext thenExpr; + public IntexpressionContext elseExpr; + public FormulaContext formula() { + return getRuleContext(FormulaContext.class,0); + } + public List intexpression() { + return getRuleContexts(IntexpressionContext.class); + } + public IntexpressionContext intexpression(int i) { + return getRuleContext(IntexpressionContext.class,i); + } + public IfIntExpressionContext(IntexpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterIfIntExpression(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitIfIntExpression(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitIfIntExpression(this); + else return visitor.visitChildren(this); + } + } + public static class CountContext extends IntexpressionContext { + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public CountContext(IntexpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterCount(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitCount(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitCount(this); + else return visitor.visitChildren(this); + } + } + public static class SumContext extends IntexpressionContext { + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public SumContext(IntexpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterSum(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitSum(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitSum(this); + else return visitor.visitChildren(this); + } + } + public static class DivideContext extends IntexpressionContext { + public IntexpressionContext left; + public IntexpressionContext right; + public List intexpression() { + return getRuleContexts(IntexpressionContext.class); + } + public IntexpressionContext intexpression(int i) { + return getRuleContext(IntexpressionContext.class,i); + } + public DivideContext(IntexpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterDivide(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitDivide(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitDivide(this); + else return visitor.visitChildren(this); + } + } + public static class MultiplyContext extends IntexpressionContext { + public IntexpressionContext left; + public IntexpressionContext right; + public List intexpression() { + return getRuleContexts(IntexpressionContext.class); + } + public IntexpressionContext intexpression(int i) { + return getRuleContext(IntexpressionContext.class,i); + } + public MultiplyContext(IntexpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterMultiply(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitMultiply(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitMultiply(this); + else return visitor.visitChildren(this); + } + } + public static class ModuloContext extends IntexpressionContext { + public IntexpressionContext left; + public IntexpressionContext right; + public List intexpression() { + return getRuleContexts(IntexpressionContext.class); + } + public IntexpressionContext intexpression(int i) { + return getRuleContext(IntexpressionContext.class,i); + } + public ModuloContext(IntexpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterModulo(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitModulo(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitModulo(this); + else return visitor.visitChildren(this); + } + } + public static class PlusContext extends IntexpressionContext { + public IntexpressionContext left; + public IntexpressionContext right; + public List intexpression() { + return getRuleContexts(IntexpressionContext.class); + } + public IntexpressionContext intexpression(int i) { + return getRuleContext(IntexpressionContext.class,i); + } + public PlusContext(IntexpressionContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterPlus(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitPlus(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitPlus(this); + else return visitor.visitChildren(this); + } + } + + public final IntexpressionContext intexpression() throws RecognitionException { + return intexpression(0); + } + + private IntexpressionContext intexpression(int _p) throws RecognitionException { + ParserRuleContext _parentctx = _ctx; + int _parentState = getState(); + IntexpressionContext _localctx = new IntexpressionContext(_ctx, _parentState); + IntexpressionContext _prevctx = _localctx; + int _startState = 30; + enterRecursionRule(_localctx, 30, RULE_intexpression, _p); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(586); + switch (_input.LA(1)) { + case T__38: + case T__39: + { + _localctx = new IfIntExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + + setState(567); + ((IfIntExpressionContext)_localctx).op = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==T__38 || _la==T__39) ) { + ((IfIntExpressionContext)_localctx).op = (Token)_errHandler.recoverInline(this); + } else { + consume(); + } + setState(568); + ((IfIntExpressionContext)_localctx).condition = formula(0); + setState(569); + match(T__55); + setState(570); + ((IfIntExpressionContext)_localctx).thenExpr = intexpression(0); + setState(571); + match(T__56); + setState(572); + ((IfIntExpressionContext)_localctx).elseExpr = intexpression(10); + } + break; + case T__28: + { + _localctx = new SumContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(574); + match(T__28); + setState(575); + expression(0); + } + break; + case T__61: + { + _localctx = new CountContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(576); + match(T__61); + setState(577); + expression(0); + } + break; + case T__51: + case INT: + { + _localctx = new IntConstantContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(579); + _la = _input.LA(1); + if (_la==T__51) { + { + setState(578); + ((IntConstantContext)_localctx).sign = match(T__51); + } + } + + setState(581); + integer(); + } + break; + case T__14: + { + _localctx = new I_paranthesisContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(582); + match(T__14); + setState(583); + intexpression(0); + setState(584); + match(T__15); + } + break; + default: + throw new NoViableAltException(this); + } + _ctx.stop = _input.LT(-1); + setState(605); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,61,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + if ( _parseListeners!=null ) triggerExitRuleEvent(); + _prevctx = _localctx; + { + setState(603); + switch ( getInterpreter().adaptivePredict(_input,60,_ctx) ) { + case 1: + { + _localctx = new PlusContext(new IntexpressionContext(_parentctx, _parentState)); + ((PlusContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_intexpression); + setState(588); + if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); + setState(589); + _la = _input.LA(1); + if ( !(_la==T__49 || _la==T__62) ) { + _errHandler.recoverInline(this); + } else { + consume(); + } + setState(590); + ((PlusContext)_localctx).right = intexpression(8); + } + break; + case 2: + { + _localctx = new MinusContext(new IntexpressionContext(_parentctx, _parentState)); + ((MinusContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_intexpression); + setState(591); + if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)"); + setState(592); + _la = _input.LA(1); + if ( !(_la==T__51 || _la==T__63) ) { + _errHandler.recoverInline(this); + } else { + consume(); + } + setState(593); + ((MinusContext)_localctx).right = intexpression(7); + } + break; + case 3: + { + _localctx = new MultiplyContext(new IntexpressionContext(_parentctx, _parentState)); + ((MultiplyContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_intexpression); + setState(594); + if (!(precpred(_ctx, 5))) throw new FailedPredicateException(this, "precpred(_ctx, 5)"); + setState(595); + _la = _input.LA(1); + if ( !(_la==T__48 || _la==T__64) ) { + _errHandler.recoverInline(this); + } else { + consume(); + } + setState(596); + ((MultiplyContext)_localctx).right = intexpression(6); + } + break; + case 4: + { + _localctx = new DivideContext(new IntexpressionContext(_parentctx, _parentState)); + ((DivideContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_intexpression); + setState(597); + if (!(precpred(_ctx, 4))) throw new FailedPredicateException(this, "precpred(_ctx, 4)"); + setState(598); + _la = _input.LA(1); + if ( !(_la==T__65 || _la==T__66) ) { + _errHandler.recoverInline(this); + } else { + consume(); + } + setState(599); + ((DivideContext)_localctx).right = intexpression(5); + } + break; + case 5: + { + _localctx = new ModuloContext(new IntexpressionContext(_parentctx, _parentState)); + ((ModuloContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_intexpression); + setState(600); + if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)"); + setState(601); + _la = _input.LA(1); + if ( !(_la==T__67 || _la==T__68) ) { + _errHandler.recoverInline(this); + } else { + consume(); + } + setState(602); + ((ModuloContext)_localctx).right = intexpression(4); + } + break; + } + } + } + setState(607); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,61,_ctx); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + unrollRecursionContexts(_parentctx); + } + return _localctx; + } + + public static class DeclsContext extends ParserRuleContext { + public List decl() { + return getRuleContexts(DeclContext.class); + } + public DeclContext decl(int i) { + return getRuleContext(DeclContext.class,i); + } + public DeclsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_decls; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterDecls(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitDecls(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitDecls(this); + else return visitor.visitChildren(this); + } + } + + public final DeclsContext decls() throws RecognitionException { + DeclsContext _localctx = new DeclsContext(_ctx, getState()); + enterRule(_localctx, 32, RULE_decls); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(608); + decl(); + setState(613); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(609); + match(T__2); + setState(610); + decl(); + } + } + setState(615); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class DeclContext extends ParserRuleContext { + public DeclContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_decl; } + + public DeclContext() { } + public void copyFrom(DeclContext ctx) { + super.copyFrom(ctx); + } + } + public static class OneOfContext extends DeclContext { + public Token disj; + public VariableIdContext variableId; + public List vars = new ArrayList(); + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public List variableId() { + return getRuleContexts(VariableIdContext.class); + } + public VariableIdContext variableId(int i) { + return getRuleContext(VariableIdContext.class,i); + } + public OneOfContext(DeclContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterOneOf(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitOneOf(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitOneOf(this); + else return visitor.visitChildren(this); + } + } + public static class SomeOfContext extends DeclContext { + public Token disj; + public VariableIdContext variableId; + public List vars = new ArrayList(); + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public List variableId() { + return getRuleContexts(VariableIdContext.class); + } + public VariableIdContext variableId(int i) { + return getRuleContext(VariableIdContext.class,i); + } + public SomeOfContext(DeclContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterSomeOf(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitSomeOf(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitSomeOf(this); + else return visitor.visitChildren(this); + } + } + public static class LoneOfContext extends DeclContext { + public Token disj; + public VariableIdContext variableId; + public List vars = new ArrayList(); + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public List variableId() { + return getRuleContexts(VariableIdContext.class); + } + public VariableIdContext variableId(int i) { + return getRuleContext(VariableIdContext.class,i); + } + public LoneOfContext(DeclContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterLoneOf(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitLoneOf(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitLoneOf(this); + else return visitor.visitChildren(this); + } + } + public static class SetOfContext extends DeclContext { + public Token disj; + public VariableIdContext variableId; + public List vars = new ArrayList(); + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public List variableId() { + return getRuleContexts(VariableIdContext.class); + } + public VariableIdContext variableId(int i) { + return getRuleContext(VariableIdContext.class,i); + } + public SetOfContext(DeclContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterSetOf(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitSetOf(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitSetOf(this); + else return visitor.visitChildren(this); + } + } + + public final DeclContext decl() throws RecognitionException { + DeclContext _localctx = new DeclContext(_ctx, getState()); + enterRule(_localctx, 34, RULE_decl); + int _la; + try { + setState(682); + switch ( getInterpreter().adaptivePredict(_input,72,_ctx) ) { + case 1: + _localctx = new OneOfContext(_localctx); + enterOuterAlt(_localctx, 1); + { + setState(617); + _la = _input.LA(1); + if (_la==T__69) { + { + setState(616); + ((OneOfContext)_localctx).disj = match(T__69); + } + } + + setState(619); + ((OneOfContext)_localctx).variableId = variableId(); + ((OneOfContext)_localctx).vars.add(((OneOfContext)_localctx).variableId); + setState(624); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(620); + match(T__2); + setState(621); + ((OneOfContext)_localctx).variableId = variableId(); + ((OneOfContext)_localctx).vars.add(((OneOfContext)_localctx).variableId); + } + } + setState(626); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(627); + match(T__5); + setState(629); + switch ( getInterpreter().adaptivePredict(_input,65,_ctx) ) { + case 1: + { + setState(628); + match(T__18); + } + break; + } + setState(631); + expression(0); + ((FormulaContext)getInvokingContext(13)).var = declareVariables(((OneOfContext)_localctx).vars, ((FormulaContext)getInvokingContext(13)).var); + } + break; + case 2: + _localctx = new LoneOfContext(_localctx); + enterOuterAlt(_localctx, 2); + { + setState(635); + _la = _input.LA(1); + if (_la==T__69) { + { + setState(634); + ((LoneOfContext)_localctx).disj = match(T__69); + } + } + + setState(637); + ((LoneOfContext)_localctx).variableId = variableId(); + ((LoneOfContext)_localctx).vars.add(((LoneOfContext)_localctx).variableId); + setState(642); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(638); + match(T__2); + setState(639); + ((LoneOfContext)_localctx).variableId = variableId(); + ((LoneOfContext)_localctx).vars.add(((LoneOfContext)_localctx).variableId); + } + } + setState(644); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(645); + match(T__5); + setState(646); + match(T__17); + setState(647); + expression(0); + ((FormulaContext)getInvokingContext(13)).var = declareVariables(((LoneOfContext)_localctx).vars, ((FormulaContext)getInvokingContext(13)).var); + } + break; + case 3: + _localctx = new SomeOfContext(_localctx); + enterOuterAlt(_localctx, 3); + { + setState(651); + _la = _input.LA(1); + if (_la==T__69) { + { + setState(650); + ((SomeOfContext)_localctx).disj = match(T__69); + } + } + + setState(653); + ((SomeOfContext)_localctx).variableId = variableId(); + ((SomeOfContext)_localctx).vars.add(((SomeOfContext)_localctx).variableId); + setState(658); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(654); + match(T__2); + setState(655); + ((SomeOfContext)_localctx).variableId = variableId(); + ((SomeOfContext)_localctx).vars.add(((SomeOfContext)_localctx).variableId); + } + } + setState(660); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(661); + match(T__5); + setState(662); + match(T__19); + setState(663); + expression(0); + ((FormulaContext)getInvokingContext(13)).var = declareVariables(((SomeOfContext)_localctx).vars, ((FormulaContext)getInvokingContext(13)).var); + } + break; + case 4: + _localctx = new SetOfContext(_localctx); + enterOuterAlt(_localctx, 4); + { + setState(667); + _la = _input.LA(1); + if (_la==T__69) { + { + setState(666); + ((SetOfContext)_localctx).disj = match(T__69); + } + } + + setState(669); + ((SetOfContext)_localctx).variableId = variableId(); + ((SetOfContext)_localctx).vars.add(((SetOfContext)_localctx).variableId); + setState(674); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(670); + match(T__2); + setState(671); + ((SetOfContext)_localctx).variableId = variableId(); + ((SetOfContext)_localctx).vars.add(((SetOfContext)_localctx).variableId); + } + } + setState(676); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(677); + match(T__5); + setState(678); + match(T__53); + setState(679); + expression(0); + ((FormulaContext)getInvokingContext(13)).var = declareVariables(((SetOfContext)_localctx).vars, ((FormulaContext)getInvokingContext(13)).var); + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class LetDeclsContext extends ParserRuleContext { + public List letDecl() { + return getRuleContexts(LetDeclContext.class); + } + public LetDeclContext letDecl(int i) { + return getRuleContext(LetDeclContext.class,i); + } + public LetDeclsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_letDecls; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterLetDecls(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitLetDecls(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitLetDecls(this); + else return visitor.visitChildren(this); + } + } + + public final LetDeclsContext letDecls() throws RecognitionException { + LetDeclsContext _localctx = new LetDeclsContext(_ctx, getState()); + enterRule(_localctx, 36, RULE_letDecls); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(684); + letDecl(); + setState(689); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(685); + match(T__2); + setState(686); + letDecl(); + } + } + setState(691); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class LetDeclContext extends ParserRuleContext { + public VariableIdContext variableId; + public List vars = new ArrayList(); + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public List variableId() { + return getRuleContexts(VariableIdContext.class); + } + public VariableIdContext variableId(int i) { + return getRuleContext(VariableIdContext.class,i); + } + public LetDeclContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_letDecl; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterLetDecl(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitLetDecl(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitLetDecl(this); + else return visitor.visitChildren(this); + } + } + + public final LetDeclContext letDecl() throws RecognitionException { + LetDeclContext _localctx = new LetDeclContext(_ctx, getState()); + enterRule(_localctx, 38, RULE_letDecl); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + { + setState(692); + ((LetDeclContext)_localctx).variableId = variableId(); + ((LetDeclContext)_localctx).vars.add(((LetDeclContext)_localctx).variableId); + setState(697); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(693); + match(T__2); + setState(694); + ((LetDeclContext)_localctx).variableId = variableId(); + ((LetDeclContext)_localctx).vars.add(((LetDeclContext)_localctx).variableId); + } + } + setState(699); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(700); + match(T__23); + setState(701); + expression(0); + } + ((FormulaContext)getInvokingContext(13)).var = declareVariables(((LetDeclContext)_localctx).vars, ((FormulaContext)getInvokingContext(13)).var); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ComprehensionDeclsContext extends ParserRuleContext { + public List comprehensionDecl() { + return getRuleContexts(ComprehensionDeclContext.class); + } + public ComprehensionDeclContext comprehensionDecl(int i) { + return getRuleContext(ComprehensionDeclContext.class,i); + } + public ComprehensionDeclsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_comprehensionDecls; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterComprehensionDecls(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitComprehensionDecls(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitComprehensionDecls(this); + else return visitor.visitChildren(this); + } + } + + public final ComprehensionDeclsContext comprehensionDecls() throws RecognitionException { + ComprehensionDeclsContext _localctx = new ComprehensionDeclsContext(_ctx, getState()); + enterRule(_localctx, 40, RULE_comprehensionDecls); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(705); + comprehensionDecl(); + setState(710); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(706); + match(T__2); + setState(707); + comprehensionDecl(); + } + } + setState(712); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ComprehensionDeclContext extends ParserRuleContext { + public Token disj; + public VariableIdContext variableId; + public List vars = new ArrayList(); + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public List variableId() { + return getRuleContexts(VariableIdContext.class); + } + public VariableIdContext variableId(int i) { + return getRuleContext(VariableIdContext.class,i); + } + public ComprehensionDeclContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_comprehensionDecl; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).enterComprehensionDecl(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof KodkodListener ) ((KodkodListener)listener).exitComprehensionDecl(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof KodkodVisitor ) return ((KodkodVisitor)visitor).visitComprehensionDecl(this); + else return visitor.visitChildren(this); + } + } + + public final ComprehensionDeclContext comprehensionDecl() throws RecognitionException { + ComprehensionDeclContext _localctx = new ComprehensionDeclContext(_ctx, getState()); + enterRule(_localctx, 42, RULE_comprehensionDecl); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(714); + _la = _input.LA(1); + if (_la==T__69) { + { + setState(713); + ((ComprehensionDeclContext)_localctx).disj = match(T__69); + } + } + + { + setState(716); + ((ComprehensionDeclContext)_localctx).variableId = variableId(); + ((ComprehensionDeclContext)_localctx).vars.add(((ComprehensionDeclContext)_localctx).variableId); + setState(721); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__2) { + { + { + setState(717); + match(T__2); + setState(718); + ((ComprehensionDeclContext)_localctx).variableId = variableId(); + ((ComprehensionDeclContext)_localctx).vars.add(((ComprehensionDeclContext)_localctx).variableId); + } + } + setState(723); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(724); + match(T__5); + setState(726); + switch ( getInterpreter().adaptivePredict(_input,78,_ctx) ) { + case 1: + { + setState(725); + match(T__18); + } + break; + } + setState(728); + expression(0); + } + ((FormulaContext)getInvokingContext(13)).var = declareVariables(((ComprehensionDeclContext)_localctx).vars, ((FormulaContext)getInvokingContext(13)).var); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) { + switch (ruleIndex) { + case 13: + return formula_sempred((FormulaContext)_localctx, predIndex); + case 14: + return expression_sempred((ExpressionContext)_localctx, predIndex); + case 15: + return intexpression_sempred((IntexpressionContext)_localctx, predIndex); + } + return true; + } + private boolean formula_sempred(FormulaContext _localctx, int predIndex) { + switch (predIndex) { + case 0: + return precpred(_ctx, 13); + case 1: + return precpred(_ctx, 12); + case 2: + return precpred(_ctx, 11); + case 3: + return precpred(_ctx, 10); + } + return true; + } + private boolean expression_sempred(ExpressionContext _localctx, int predIndex) { + switch (predIndex) { + case 4: + return !isRelation(); + case 5: + return isRelation(); + case 6: + return precpred(_ctx, 14); + case 7: + return precpred(_ctx, 13); + case 8: + return precpred(_ctx, 12); + case 9: + return precpred(_ctx, 11); + case 10: + return precpred(_ctx, 9); + case 11: + return precpred(_ctx, 8); + case 12: + return precpred(_ctx, 10); + } + return true; + } + private boolean intexpression_sempred(IntexpressionContext _localctx, int predIndex) { + switch (predIndex) { + case 13: + return precpred(_ctx, 7); + case 14: + return precpred(_ctx, 6); + case 15: + return precpred(_ctx, 5); + case 16: + return precpred(_ctx, 4); + case 17: + return precpred(_ctx, 3); + } + return true; + } + + public static final String _serializedATN = + "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3O\u02df\4\2\t\2\4"+ + "\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"+ + "\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ + "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\3\2\5\2\60\n\2\3\2"+ + "\3\2\3\2\3\2\3\2\7\2\67\n\2\f\2\16\2:\13\2\3\2\3\2\3\2\3\3\3\3\3\3\3\3"+ + "\3\3\3\3\3\3\3\3\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\5\4S"+ + "\n\4\3\5\3\5\3\5\3\5\3\5\7\5Z\n\5\f\5\16\5]\13\5\3\5\3\5\3\5\3\5\3\5\3"+ + "\5\7\5e\n\5\f\5\16\5h\13\5\3\5\3\5\5\5l\n\5\3\5\3\5\3\6\3\6\3\6\7\6s\n"+ + "\6\f\6\16\6v\13\6\3\6\3\6\3\7\3\7\5\7|\n\7\3\7\3\7\5\7\u0080\n\7\3\7\3"+ + "\7\3\7\3\7\5\7\u0086\n\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\7\b\u0090\n\b"+ + "\f\b\16\b\u0093\13\b\5\b\u0095\n\b\3\b\3\b\3\b\3\b\3\b\7\b\u009c\n\b\f"+ + "\b\16\b\u009f\13\b\5\b\u00a1\n\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3"+ + "\b\3\b\3\b\3\b\5\b\u00b0\n\b\3\t\3\t\3\t\3\t\7\t\u00b6\n\t\f\t\16\t\u00b9"+ + "\13\t\3\t\3\t\3\t\3\t\3\t\3\t\7\t\u00c1\n\t\f\t\16\t\u00c4\13\t\3\t\3"+ + "\t\5\t\u00c8\n\t\3\n\3\n\3\n\5\n\u00cd\n\n\3\13\3\13\3\f\3\f\3\r\3\r\3"+ + "\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3"+ + "\17\5\17\u00e4\n\17\3\17\3\17\3\17\3\17\3\17\5\17\u00eb\n\17\3\17\3\17"+ + "\3\17\3\17\3\17\5\17\u00f2\n\17\3\17\3\17\3\17\3\17\3\17\5\17\u00f9\n"+ + "\17\3\17\3\17\3\17\3\17\3\17\5\17\u0100\n\17\3\17\3\17\3\17\3\17\3\17"+ + "\5\17\u0107\n\17\3\17\3\17\3\17\3\17\3\17\5\17\u010e\n\17\3\17\3\17\3"+ + "\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3"+ + "\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3"+ + "\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\7"+ + "\17\u013c\n\17\f\17\16\17\u013f\13\17\3\17\5\17\u0142\n\17\3\17\3\17\7"+ + "\17\u0146\n\17\f\17\16\17\u0149\13\17\3\17\5\17\u014c\n\17\3\17\3\17\3"+ + "\17\3\17\3\17\3\17\3\17\3\17\3\17\7\17\u0157\n\17\f\17\16\17\u015a\13"+ + "\17\3\17\5\17\u015d\n\17\3\17\3\17\7\17\u0161\n\17\f\17\16\17\u0164\13"+ + "\17\3\17\5\17\u0167\n\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17"+ + "\7\17\u0172\n\17\f\17\16\17\u0175\13\17\3\17\5\17\u0178\n\17\3\17\3\17"+ + "\7\17\u017c\n\17\f\17\16\17\u017f\13\17\3\17\5\17\u0182\n\17\3\17\3\17"+ + "\3\17\3\17\3\17\3\17\3\17\3\17\3\17\7\17\u018d\n\17\f\17\16\17\u0190\13"+ + "\17\3\17\5\17\u0193\n\17\3\17\3\17\7\17\u0197\n\17\f\17\16\17\u019a\13"+ + "\17\3\17\5\17\u019d\n\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17"+ + "\7\17\u01a8\n\17\f\17\16\17\u01ab\13\17\3\17\5\17\u01ae\n\17\3\17\3\17"+ + "\7\17\u01b2\n\17\f\17\16\17\u01b5\13\17\3\17\5\17\u01b8\n\17\3\17\3\17"+ + "\3\17\3\17\3\17\3\17\3\17\3\17\3\17\7\17\u01c3\n\17\f\17\16\17\u01c6\13"+ + "\17\3\17\5\17\u01c9\n\17\3\17\3\17\7\17\u01cd\n\17\f\17\16\17\u01d0\13"+ + "\17\3\17\5\17\u01d3\n\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\5\17"+ + "\u01dd\n\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17"+ + "\7\17\u01eb\n\17\f\17\16\17\u01ee\13\17\3\20\3\20\3\20\3\20\3\20\3\20"+ + "\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20"+ + "\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20"+ + "\3\20\3\20\3\20\5\20\u0215\n\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20"+ + "\3\20\3\20\3\20\3\20\3\20\3\20\5\20\u0225\n\20\3\20\3\20\5\20\u0229\n"+ + "\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\7\20\u0234\n\20\f\20"+ + "\16\20\u0237\13\20\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3"+ + "\21\3\21\3\21\5\21\u0246\n\21\3\21\3\21\3\21\3\21\3\21\5\21\u024d\n\21"+ + "\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21"+ + "\3\21\7\21\u025e\n\21\f\21\16\21\u0261\13\21\3\22\3\22\3\22\7\22\u0266"+ + "\n\22\f\22\16\22\u0269\13\22\3\23\5\23\u026c\n\23\3\23\3\23\3\23\7\23"+ + "\u0271\n\23\f\23\16\23\u0274\13\23\3\23\3\23\5\23\u0278\n\23\3\23\3\23"+ + "\3\23\3\23\5\23\u027e\n\23\3\23\3\23\3\23\7\23\u0283\n\23\f\23\16\23\u0286"+ + "\13\23\3\23\3\23\3\23\3\23\3\23\3\23\5\23\u028e\n\23\3\23\3\23\3\23\7"+ + "\23\u0293\n\23\f\23\16\23\u0296\13\23\3\23\3\23\3\23\3\23\3\23\3\23\5"+ + "\23\u029e\n\23\3\23\3\23\3\23\7\23\u02a3\n\23\f\23\16\23\u02a6\13\23\3"+ + "\23\3\23\3\23\3\23\3\23\5\23\u02ad\n\23\3\24\3\24\3\24\7\24\u02b2\n\24"+ + "\f\24\16\24\u02b5\13\24\3\25\3\25\3\25\7\25\u02ba\n\25\f\25\16\25\u02bd"+ + "\13\25\3\25\3\25\3\25\3\25\3\25\3\26\3\26\3\26\7\26\u02c7\n\26\f\26\16"+ + "\26\u02ca\13\26\3\27\5\27\u02cd\n\27\3\27\3\27\3\27\7\27\u02d2\n\27\f"+ + "\27\16\27\u02d5\13\27\3\27\3\27\5\27\u02d9\n\27\3\27\3\27\3\27\3\27\3"+ + "\27\2\5\34\36 \30\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,\2\16"+ + "\3\2\27\30\3\2\24\25\3\2%&\3\2\'(\3\2)*\3\2+,\4\2\24\2688\4\2\64\64AA"+ + "\4\2\66\66BB\4\2\63\63CC\3\2DE\3\2FG\u034b\2/\3\2\2\2\4>\3\2\2\2\6R\3"+ + "\2\2\2\bT\3\2\2\2\no\3\2\2\2\fy\3\2\2\2\16\u00af\3\2\2\2\20\u00c7\3\2"+ + "\2\2\22\u00cc\3\2\2\2\24\u00ce\3\2\2\2\26\u00d0\3\2\2\2\30\u00d2\3\2\2"+ + "\2\32\u00d4\3\2\2\2\34\u01dc\3\2\2\2\36\u0214\3\2\2\2 \u024c\3\2\2\2\""+ + "\u0262\3\2\2\2$\u02ac\3\2\2\2&\u02ae\3\2\2\2(\u02b6\3\2\2\2*\u02c3\3\2"+ + "\2\2,\u02cc\3\2\2\2.\60\5\4\3\2/.\3\2\2\2/\60\3\2\2\2\60\61\3\2\2\2\61"+ + "\62\5\b\5\2\62\63\b\2\1\2\63\64\5\n\6\2\648\b\2\1\2\65\67\5\34\17\2\66"+ + "\65\3\2\2\2\67:\3\2\2\28\66\3\2\2\289\3\2\2\29;\3\2\2\2:8\3\2\2\2;<\b"+ + "\2\1\2<=\b\2\1\2=\3\3\2\2\2>?\7\3\2\2?@\7\4\2\2@A\5\6\4\2AB\7\5\2\2BC"+ + "\5\6\4\2CD\3\2\2\2DE\7\6\2\2E\5\3\2\2\2FG\7\7\2\2GH\7\b\2\2HS\5\30\r\2"+ + "IJ\7\t\2\2JK\7\b\2\2KS\5\30\r\2LM\7\n\2\2MN\7\b\2\2NS\5\30\r\2OP\7\13"+ + "\2\2PQ\7\b\2\2QS\5\30\r\2RF\3\2\2\2RI\3\2\2\2RL\3\2\2\2RO\3\2\2\2S\7\3"+ + "\2\2\2Tk\7\f\2\2UV\7\4\2\2V[\5\22\n\2WX\7\5\2\2XZ\5\22\n\2YW\3\2\2\2Z"+ + "]\3\2\2\2[Y\3\2\2\2[\\\3\2\2\2\\^\3\2\2\2][\3\2\2\2^_\7\6\2\2_l\3\2\2"+ + "\2`a\7\r\2\2af\5\22\n\2bc\7\5\2\2ce\5\22\n\2db\3\2\2\2eh\3\2\2\2fd\3\2"+ + "\2\2fg\3\2\2\2gi\3\2\2\2hf\3\2\2\2ij\7\16\2\2jl\3\2\2\2kU\3\2\2\2k`\3"+ + "\2\2\2lm\3\2\2\2mn\b\5\1\2n\t\3\2\2\2op\7\17\2\2pt\7\4\2\2qs\5\f\7\2r"+ + "q\3\2\2\2sv\3\2\2\2tr\3\2\2\2tu\3\2\2\2uw\3\2\2\2vt\3\2\2\2wx\7\6\2\2"+ + "x\13\3\2\2\2y{\5\24\13\2z|\5\32\16\2{z\3\2\2\2{|\3\2\2\2|}\3\2\2\2}\177"+ + "\7\b\2\2~\u0080\5\36\20\2\177~\3\2\2\2\177\u0080\3\2\2\2\u0080\u0081\3"+ + "\2\2\2\u0081\u0082\7\r\2\2\u0082\u0085\5\16\b\2\u0083\u0084\7\5\2\2\u0084"+ + "\u0086\5\16\b\2\u0085\u0083\3\2\2\2\u0085\u0086\3\2\2\2\u0086\u0087\3"+ + "\2\2\2\u0087\u0088\7\16\2\2\u0088\u0089\3\2\2\2\u0089\u008a\b\7\1\2\u008a"+ + "\r\3\2\2\2\u008b\u0094\7\4\2\2\u008c\u0091\5\20\t\2\u008d\u008e\7\5\2"+ + "\2\u008e\u0090\5\20\t\2\u008f\u008d\3\2\2\2\u0090\u0093\3\2\2\2\u0091"+ + "\u008f\3\2\2\2\u0091\u0092\3\2\2\2\u0092\u0095\3\2\2\2\u0093\u0091\3\2"+ + "\2\2\u0094\u008c\3\2\2\2\u0094\u0095\3\2\2\2\u0095\u0096\3\2\2\2\u0096"+ + "\u00b0\7\6\2\2\u0097\u00a0\7\r\2\2\u0098\u009d\5\20\t\2\u0099\u009a\7"+ + "\5\2\2\u009a\u009c\5\20\t\2\u009b\u0099\3\2\2\2\u009c\u009f\3\2\2\2\u009d"+ + "\u009b\3\2\2\2\u009d\u009e\3\2\2\2\u009e\u00a1\3\2\2\2\u009f\u009d\3\2"+ + "\2\2\u00a0\u0098\3\2\2\2\u00a0\u00a1\3\2\2\2\u00a1\u00a2\3\2\2\2\u00a2"+ + "\u00b0\7\16\2\2\u00a3\u00a4\7\4\2\2\u00a4\u00a5\5\20\t\2\u00a5\u00a6\7"+ + "\20\2\2\u00a6\u00a7\5\20\t\2\u00a7\u00a8\7\6\2\2\u00a8\u00b0\3\2\2\2\u00a9"+ + "\u00aa\7\r\2\2\u00aa\u00ab\5\20\t\2\u00ab\u00ac\7\20\2\2\u00ac\u00ad\5"+ + "\20\t\2\u00ad\u00ae\7\16\2\2\u00ae\u00b0\3\2\2\2\u00af\u008b\3\2\2\2\u00af"+ + "\u0097\3\2\2\2\u00af\u00a3\3\2\2\2\u00af\u00a9\3\2\2\2\u00b0\17\3\2\2"+ + "\2\u00b1\u00b2\7\21\2\2\u00b2\u00b7\5\22\n\2\u00b3\u00b4\7\5\2\2\u00b4"+ + "\u00b6\5\22\n\2\u00b5\u00b3\3\2\2\2\u00b6\u00b9\3\2\2\2\u00b7\u00b5\3"+ + "\2\2\2\u00b7\u00b8\3\2\2\2\u00b8\u00ba\3\2\2\2\u00b9\u00b7\3\2\2\2\u00ba"+ + "\u00bb\7\22\2\2\u00bb\u00c8\3\2\2\2\u00bc\u00bd\7\r\2\2\u00bd\u00c2\5"+ + "\22\n\2\u00be\u00bf\7\5\2\2\u00bf\u00c1\5\22\n\2\u00c0\u00be\3\2\2\2\u00c1"+ + "\u00c4\3\2\2\2\u00c2\u00c0\3\2\2\2\u00c2\u00c3\3\2\2\2\u00c3\u00c5\3\2"+ + "\2\2\u00c4\u00c2\3\2\2\2\u00c5\u00c6\7\16\2\2\u00c6\u00c8\3\2\2\2\u00c7"+ + "\u00b1\3\2\2\2\u00c7\u00bc\3\2\2\2\u00c8\21\3\2\2\2\u00c9\u00ca\7J\2\2"+ + "\u00ca\u00cd\b\n\1\2\u00cb\u00cd\7I\2\2\u00cc\u00c9\3\2\2\2\u00cc\u00cb"+ + "\3\2\2\2\u00cd\23\3\2\2\2\u00ce\u00cf\7J\2\2\u00cf\25\3\2\2\2\u00d0\u00d1"+ + "\7J\2\2\u00d1\27\3\2\2\2\u00d2\u00d3\7I\2\2\u00d3\31\3\2\2\2\u00d4\u00d5"+ + "\7I\2\2\u00d5\33\3\2\2\2\u00d6\u00d7\b\17\1\2\u00d7\u00d8\t\2\2\2\u00d8"+ + "\u01dd\5\34\17\20\u00d9\u00da\7\23\2\2\u00da\u01dd\5\36\20\2\u00db\u00dc"+ + "\7\24\2\2\u00dc\u01dd\5\36\20\2\u00dd\u00de\7\25\2\2\u00de\u01dd\5\36"+ + "\20\2\u00df\u00e0\7\26\2\2\u00e0\u01dd\5\36\20\2\u00e1\u00e3\5\36\20\2"+ + "\u00e2\u00e4\t\2\2\2\u00e3\u00e2\3\2\2\2\u00e3\u00e4\3\2\2\2\u00e4\u00e5"+ + "\3\2\2\2\u00e5\u00e6\7\31\2\2\u00e6\u00e7\5\36\20\2\u00e7\u01dd\3\2\2"+ + "\2\u00e8\u00ea\5\36\20\2\u00e9\u00eb\t\2\2\2\u00ea\u00e9\3\2\2\2\u00ea"+ + "\u00eb\3\2\2\2\u00eb\u00ec\3\2\2\2\u00ec\u00ed\7\32\2\2\u00ed\u00ee\5"+ + "\36\20\2\u00ee\u01dd\3\2\2\2\u00ef\u00f1\5 \21\2\u00f0\u00f2\t\2\2\2\u00f1"+ + "\u00f0\3\2\2\2\u00f1\u00f2\3\2\2\2\u00f2\u00f3\3\2\2\2\u00f3\u00f4\7\32"+ + "\2\2\u00f4\u00f5\5 \21\2\u00f5\u01dd\3\2\2\2\u00f6\u00f8\5 \21\2\u00f7"+ + "\u00f9\t\2\2\2\u00f8\u00f7\3\2\2\2\u00f8\u00f9\3\2\2\2\u00f9\u00fa\3\2"+ + "\2\2\u00fa\u00fb\7\33\2\2\u00fb\u00fc\5 \21\2\u00fc\u01dd\3\2\2\2\u00fd"+ + "\u00ff\5 \21\2\u00fe\u0100\t\2\2\2\u00ff\u00fe\3\2\2\2\u00ff\u0100\3\2"+ + "\2\2\u0100\u0101\3\2\2\2\u0101\u0102\7\34\2\2\u0102\u0103\5 \21\2\u0103"+ + "\u01dd\3\2\2\2\u0104\u0106\5 \21\2\u0105\u0107\t\2\2\2\u0106\u0105\3\2"+ + "\2\2\u0106\u0107\3\2\2\2\u0107\u0108\3\2\2\2\u0108\u0109\7\35\2\2\u0109"+ + "\u010a\5 \21\2\u010a\u01dd\3\2\2\2\u010b\u010d\5 \21\2\u010c\u010e\t\2"+ + "\2\2\u010d\u010c\3\2\2\2\u010d\u010e\3\2\2\2\u010e\u010f\3\2\2\2\u010f"+ + "\u0110\7\36\2\2\u0110\u0111\5 \21\2\u0111\u01dd\3\2\2\2\u0112\u0113\b"+ + "\17\1\2\u0113\u0114\7\37\2\2\u0114\u0115\5\"\22\2\u0115\u0116\7 \2\2\u0116"+ + "\u0117\5 \21\2\u0117\u0118\3\2\2\2\u0118\u0119\b\17\1\2\u0119\u01dd\3"+ + "\2\2\2\u011a\u011b\7!\2\2\u011b\u011c\7\r\2\2\u011c\u011d\5\24\13\2\u011d"+ + "\u011e\7\16\2\2\u011e\u01dd\3\2\2\2\u011f\u0120\7\"\2\2\u0120\u0121\7"+ + "\r\2\2\u0121\u0122\5\24\13\2\u0122\u0123\7\b\2\2\u0123\u0124\5\36\20\2"+ + "\u0124\u0125\7#\2\2\u0125\u0126\t\3\2\2\u0126\u0127\5\36\20\2\u0127\u0128"+ + "\7\16\2\2\u0128\u01dd\3\2\2\2\u0129\u012a\7$\2\2\u012a\u012b\7\r\2\2\u012b"+ + "\u012c\5\24\13\2\u012c\u012d\7\5\2\2\u012d\u012e\5\24\13\2\u012e\u012f"+ + "\7\5\2\2\u012f\u0130\5\24\13\2\u0130\u0131\7\5\2\2\u0131\u0132\5\24\13"+ + "\2\u0132\u0133\7\16\2\2\u0133\u01dd\3\2\2\2\u0134\u0135\b\17\1\2\u0135"+ + "\u0136\7-\2\2\u0136\u014b\5\"\22\2\u0137\u0141\7 \2\2\u0138\u0142\5\34"+ + "\17\2\u0139\u013d\7\4\2\2\u013a\u013c\5\34\17\2\u013b\u013a\3\2\2\2\u013c"+ + "\u013f\3\2\2\2\u013d\u013b\3\2\2\2\u013d\u013e\3\2\2\2\u013e\u0140\3\2"+ + "\2\2\u013f\u013d\3\2\2\2\u0140\u0142\7\6\2\2\u0141\u0138\3\2\2\2\u0141"+ + "\u0139\3\2\2\2\u0142\u014c\3\2\2\2\u0143\u0147\7\4\2\2\u0144\u0146\5\34"+ + "\17\2\u0145\u0144\3\2\2\2\u0146\u0149\3\2\2\2\u0147\u0145\3\2\2\2\u0147"+ + "\u0148\3\2\2\2\u0148\u014a\3\2\2\2\u0149\u0147\3\2\2\2\u014a\u014c\7\6"+ + "\2\2\u014b\u0137\3\2\2\2\u014b\u0143\3\2\2\2\u014c\u014d\3\2\2\2\u014d"+ + "\u014e\b\17\1\2\u014e\u01dd\3\2\2\2\u014f\u0150\b\17\1\2\u0150\u0151\7"+ + "\26\2\2\u0151\u0166\5\"\22\2\u0152\u015c\7 \2\2\u0153\u015d\5\34\17\2"+ + "\u0154\u0158\7\4\2\2\u0155\u0157\5\34\17\2\u0156\u0155\3\2\2\2\u0157\u015a"+ + "\3\2\2\2\u0158\u0156\3\2\2\2\u0158\u0159\3\2\2\2\u0159\u015b\3\2\2\2\u015a"+ + "\u0158\3\2\2\2\u015b\u015d\7\6\2\2\u015c\u0153\3\2\2\2\u015c\u0154\3\2"+ + "\2\2\u015d\u0167\3\2\2\2\u015e\u0162\7\4\2\2\u015f\u0161\5\34\17\2\u0160"+ + "\u015f\3\2\2\2\u0161\u0164\3\2\2\2\u0162\u0160\3\2\2\2\u0162\u0163\3\2"+ + "\2\2\u0163\u0165\3\2\2\2\u0164\u0162\3\2\2\2\u0165\u0167\7\6\2\2\u0166"+ + "\u0152\3\2\2\2\u0166\u015e\3\2\2\2\u0167\u0168\3\2\2\2\u0168\u0169\b\17"+ + "\1\2\u0169\u01dd\3\2\2\2\u016a\u016b\b\17\1\2\u016b\u016c\7\23\2\2\u016c"+ + "\u0181\5\"\22\2\u016d\u0177\7 \2\2\u016e\u0178\5\34\17\2\u016f\u0173\7"+ + "\4\2\2\u0170\u0172\5\34\17\2\u0171\u0170\3\2\2\2\u0172\u0175\3\2\2\2\u0173"+ + "\u0171\3\2\2\2\u0173\u0174\3\2\2\2\u0174\u0176\3\2\2\2\u0175\u0173\3\2"+ + "\2\2\u0176\u0178\7\6\2\2\u0177\u016e\3\2\2\2\u0177\u016f\3\2\2\2\u0178"+ + "\u0182\3\2\2\2\u0179\u017d\7\4\2\2\u017a\u017c\5\34\17\2\u017b\u017a\3"+ + "\2\2\2\u017c\u017f\3\2\2\2\u017d\u017b\3\2\2\2\u017d\u017e\3\2\2\2\u017e"+ + "\u0180\3\2\2\2\u017f\u017d\3\2\2\2\u0180\u0182\7\6\2\2\u0181\u016d\3\2"+ + "\2\2\u0181\u0179\3\2\2\2\u0182\u0183\3\2\2\2\u0183\u0184\b\17\1\2\u0184"+ + "\u01dd\3\2\2\2\u0185\u0186\b\17\1\2\u0186\u0187\7\25\2\2\u0187\u019c\5"+ + "\"\22\2\u0188\u0192\7 \2\2\u0189\u0193\5\34\17\2\u018a\u018e\7\4\2\2\u018b"+ + "\u018d\5\34\17\2\u018c\u018b\3\2\2\2\u018d\u0190\3\2\2\2\u018e\u018c\3"+ + "\2\2\2\u018e\u018f\3\2\2\2\u018f\u0191\3\2\2\2\u0190\u018e\3\2\2\2\u0191"+ + "\u0193\7\6\2\2\u0192\u0189\3\2\2\2\u0192\u018a\3\2\2\2\u0193\u019d\3\2"+ + "\2\2\u0194\u0198\7\4\2\2\u0195\u0197\5\34\17\2\u0196\u0195\3\2\2\2\u0197"+ + "\u019a\3\2\2\2\u0198\u0196\3\2\2\2\u0198\u0199\3\2\2\2\u0199\u019b\3\2"+ + "\2\2\u019a\u0198\3\2\2\2\u019b\u019d\7\6\2\2\u019c\u0188\3\2\2\2\u019c"+ + "\u0194\3\2\2\2\u019d\u019e\3\2\2\2\u019e\u019f\b\17\1\2\u019f\u01dd\3"+ + "\2\2\2\u01a0\u01a1\b\17\1\2\u01a1\u01a2\7\24\2\2\u01a2\u01b7\5\"\22\2"+ + "\u01a3\u01ad\7 \2\2\u01a4\u01ae\5\34\17\2\u01a5\u01a9\7\4\2\2\u01a6\u01a8"+ + "\5\34\17\2\u01a7\u01a6\3\2\2\2\u01a8\u01ab\3\2\2\2\u01a9\u01a7\3\2\2\2"+ + "\u01a9\u01aa\3\2\2\2\u01aa\u01ac\3\2\2\2\u01ab\u01a9\3\2\2\2\u01ac\u01ae"+ + "\7\6\2\2\u01ad\u01a4\3\2\2\2\u01ad\u01a5\3\2\2\2\u01ae\u01b8\3\2\2\2\u01af"+ + "\u01b3\7\4\2\2\u01b0\u01b2\5\34\17\2\u01b1\u01b0\3\2\2\2\u01b2\u01b5\3"+ + "\2\2\2\u01b3\u01b1\3\2\2\2\u01b3\u01b4\3\2\2\2\u01b4\u01b6\3\2\2\2\u01b5"+ + "\u01b3\3\2\2\2\u01b6\u01b8\7\6\2\2\u01b7\u01a3\3\2\2\2\u01b7\u01af\3\2"+ + "\2\2\u01b8\u01b9\3\2\2\2\u01b9\u01ba\b\17\1\2\u01ba\u01dd\3\2\2\2\u01bb"+ + "\u01bc\b\17\1\2\u01bc\u01bd\7.\2\2\u01bd\u01d2\5&\24\2\u01be\u01c8\7 "+ + "\2\2\u01bf\u01c9\5\34\17\2\u01c0\u01c4\7\4\2\2\u01c1\u01c3\5\34\17\2\u01c2"+ + "\u01c1\3\2\2\2\u01c3\u01c6\3\2\2\2\u01c4\u01c2\3\2\2\2\u01c4\u01c5\3\2"+ + "\2\2\u01c5\u01c7\3\2\2\2\u01c6\u01c4\3\2\2\2\u01c7\u01c9\7\6\2\2\u01c8"+ + "\u01bf\3\2\2\2\u01c8\u01c0\3\2\2\2\u01c9\u01d3\3\2\2\2\u01ca\u01ce\7\4"+ + "\2\2\u01cb\u01cd\5\34\17\2\u01cc\u01cb\3\2\2\2\u01cd\u01d0\3\2\2\2\u01ce"+ + "\u01cc\3\2\2\2\u01ce\u01cf\3\2\2\2\u01cf\u01d1\3\2\2\2\u01d0\u01ce\3\2"+ + "\2\2\u01d1\u01d3\7\6\2\2\u01d2\u01be\3\2\2\2\u01d2\u01ca\3\2\2\2\u01d3"+ + "\u01d4\3\2\2\2\u01d4\u01d5\b\17\1\2\u01d5\u01dd\3\2\2\2\u01d6\u01dd\7"+ + "/\2\2\u01d7\u01dd\7\60\2\2\u01d8\u01d9\7\21\2\2\u01d9\u01da\5\34\17\2"+ + "\u01da\u01db\7\22\2\2\u01db\u01dd\3\2\2\2\u01dc\u00d6\3\2\2\2\u01dc\u00d9"+ + "\3\2\2\2\u01dc\u00db\3\2\2\2\u01dc\u00dd\3\2\2\2\u01dc\u00df\3\2\2\2\u01dc"+ + "\u00e1\3\2\2\2\u01dc\u00e8\3\2\2\2\u01dc\u00ef\3\2\2\2\u01dc\u00f6\3\2"+ + "\2\2\u01dc\u00fd\3\2\2\2\u01dc\u0104\3\2\2\2\u01dc\u010b\3\2\2\2\u01dc"+ + "\u0112\3\2\2\2\u01dc\u011a\3\2\2\2\u01dc\u011f\3\2\2\2\u01dc\u0129\3\2"+ + "\2\2\u01dc\u0134\3\2\2\2\u01dc\u014f\3\2\2\2\u01dc\u016a\3\2\2\2\u01dc"+ + "\u0185\3\2\2\2\u01dc\u01a0\3\2\2\2\u01dc\u01bb\3\2\2\2\u01dc\u01d6\3\2"+ + "\2\2\u01dc\u01d7\3\2\2\2\u01dc\u01d8\3\2\2\2\u01dd\u01ec\3\2\2\2\u01de"+ + "\u01df\f\17\2\2\u01df\u01e0\t\4\2\2\u01e0\u01eb\5\34\17\17\u01e1\u01e2"+ + "\f\16\2\2\u01e2\u01e3\t\5\2\2\u01e3\u01eb\5\34\17\16\u01e4\u01e5\f\r\2"+ + "\2\u01e5\u01e6\t\6\2\2\u01e6\u01eb\5\34\17\r\u01e7\u01e8\f\f\2\2\u01e8"+ + "\u01e9\t\7\2\2\u01e9\u01eb\5\34\17\f\u01ea\u01de\3\2\2\2\u01ea\u01e1\3"+ + "\2\2\2\u01ea\u01e4\3\2\2\2\u01ea\u01e7\3\2\2\2\u01eb\u01ee\3\2\2\2\u01ec"+ + "\u01ea\3\2\2\2\u01ec\u01ed\3\2\2\2\u01ed\35\3\2\2\2\u01ee\u01ec\3\2\2"+ + "\2\u01ef\u01f0\b\20\1\2\u01f0\u01f1\7\61\2\2\u01f1\u0215\5\36\20\23\u01f2"+ + "\u01f3\7\62\2\2\u01f3\u0215\5\36\20\22\u01f4\u01f5\7\63\2\2\u01f5\u0215"+ + "\5\36\20\21\u01f6\u01f7\t\6\2\2\u01f7\u01f8\5\34\17\2\u01f8\u01f9\7:\2"+ + "\2\u01f9\u01fa\5\36\20\2\u01fa\u01fb\7;\2\2\u01fb\u01fc\5\36\20\b\u01fc"+ + "\u0215\3\2\2\2\u01fd\u01fe\6\20\6\2\u01fe\u01ff\5\26\f\2\u01ff\u0200\b"+ + "\20\1\2\u0200\u0215\3\2\2\2\u0201\u0202\6\20\7\2\u0202\u0215\5\24\13\2"+ + "\u0203\u0204\b\20\1\2\u0204\u0205\7\4\2\2\u0205\u0206\5*\26\2\u0206\u0207"+ + "\7 \2\2\u0207\u0208\5\34\17\2\u0208\u0209\7\6\2\2\u0209\u020a\3\2\2\2"+ + "\u020a\u020b\b\20\1\2\u020b\u0215\3\2\2\2\u020c\u0215\7<\2\2\u020d\u0215"+ + "\7=\2\2\u020e\u0215\7>\2\2\u020f\u0215\7?\2\2\u0210\u0211\7\21\2\2\u0211"+ + "\u0212\5\36\20\2\u0212\u0213\7\22\2\2\u0213\u0215\3\2\2\2\u0214\u01ef"+ + "\3\2\2\2\u0214\u01f2\3\2\2\2\u0214\u01f4\3\2\2\2\u0214\u01f6\3\2\2\2\u0214"+ + "\u01fd\3\2\2\2\u0214\u0201\3\2\2\2\u0214\u0203\3\2\2\2\u0214\u020c\3\2"+ + "\2\2\u0214\u020d\3\2\2\2\u0214\u020e\3\2\2\2\u0214\u020f\3\2\2\2\u0214"+ + "\u0210\3\2\2\2\u0215\u0235\3\2\2\2\u0216\u0217\f\20\2\2\u0217\u0218\7"+ + "\64\2\2\u0218\u0234\5\36\20\21\u0219\u021a\f\17\2\2\u021a\u021b\7\65\2"+ + "\2\u021b\u0234\5\36\20\20\u021c\u021d\f\16\2\2\u021d\u021e\7\66\2\2\u021e"+ + "\u0234\5\36\20\17\u021f\u0220\f\r\2\2\u0220\u0221\7\67\2\2\u0221\u0234"+ + "\5\36\20\16\u0222\u0224\f\13\2\2\u0223\u0225\t\b\2\2\u0224\u0223\3\2\2"+ + "\2\u0224\u0225\3\2\2\2\u0225\u0226\3\2\2\2\u0226\u0228\7#\2\2\u0227\u0229"+ + "\t\b\2\2\u0228\u0227\3\2\2\2\u0228\u0229\3\2\2\2\u0229\u022a\3\2\2\2\u022a"+ + "\u0234\5\36\20\13\u022b\u022c\f\n\2\2\u022c\u022d\79\2\2\u022d\u0234\5"+ + "\36\20\13\u022e\u022f\f\f\2\2\u022f\u0230\7\r\2\2\u0230\u0231\5\36\20"+ + "\2\u0231\u0232\7\16\2\2\u0232\u0234\3\2\2\2\u0233\u0216\3\2\2\2\u0233"+ + "\u0219\3\2\2\2\u0233\u021c\3\2\2\2\u0233\u021f\3\2\2\2\u0233\u0222\3\2"+ + "\2\2\u0233\u022b\3\2\2\2\u0233\u022e\3\2\2\2\u0234\u0237\3\2\2\2\u0235"+ + "\u0233\3\2\2\2\u0235\u0236\3\2\2\2\u0236\37\3\2\2\2\u0237\u0235\3\2\2"+ + "\2\u0238\u0239\b\21\1\2\u0239\u023a\t\6\2\2\u023a\u023b\5\34\17\2\u023b"+ + "\u023c\7:\2\2\u023c\u023d\5 \21\2\u023d\u023e\7;\2\2\u023e\u023f\5 \21"+ + "\f\u023f\u024d\3\2\2\2\u0240\u0241\7\37\2\2\u0241\u024d\5\36\20\2\u0242"+ + "\u0243\7@\2\2\u0243\u024d\5\36\20\2\u0244\u0246\7\66\2\2\u0245\u0244\3"+ + "\2\2\2\u0245\u0246\3\2\2\2\u0246\u0247\3\2\2\2\u0247\u024d\5\30\r\2\u0248"+ + "\u0249\7\21\2\2\u0249\u024a\5 \21\2\u024a\u024b\7\22\2\2\u024b\u024d\3"+ + "\2\2\2\u024c\u0238\3\2\2\2\u024c\u0240\3\2\2\2\u024c\u0242\3\2\2\2\u024c"+ + "\u0245\3\2\2\2\u024c\u0248\3\2\2\2\u024d\u025f\3\2\2\2\u024e\u024f\f\t"+ + "\2\2\u024f\u0250\t\t\2\2\u0250\u025e\5 \21\n\u0251\u0252\f\b\2\2\u0252"+ + "\u0253\t\n\2\2\u0253\u025e\5 \21\t\u0254\u0255\f\7\2\2\u0255\u0256\t\13"+ + "\2\2\u0256\u025e\5 \21\b\u0257\u0258\f\6\2\2\u0258\u0259\t\f\2\2\u0259"+ + "\u025e\5 \21\7\u025a\u025b\f\5\2\2\u025b\u025c\t\r\2\2\u025c\u025e\5 "+ + "\21\6\u025d\u024e\3\2\2\2\u025d\u0251\3\2\2\2\u025d\u0254\3\2\2\2\u025d"+ + "\u0257\3\2\2\2\u025d\u025a\3\2\2\2\u025e\u0261\3\2\2\2\u025f\u025d\3\2"+ + "\2\2\u025f\u0260\3\2\2\2\u0260!\3\2\2\2\u0261\u025f\3\2\2\2\u0262\u0267"+ + "\5$\23\2\u0263\u0264\7\5\2\2\u0264\u0266\5$\23\2\u0265\u0263\3\2\2\2\u0266"+ + "\u0269\3\2\2\2\u0267\u0265\3\2\2\2\u0267\u0268\3\2\2\2\u0268#\3\2\2\2"+ + "\u0269\u0267\3\2\2\2\u026a\u026c\7H\2\2\u026b\u026a\3\2\2\2\u026b\u026c"+ + "\3\2\2\2\u026c\u026d\3\2\2\2\u026d\u0272\5\26\f\2\u026e\u026f\7\5\2\2"+ + "\u026f\u0271\5\26\f\2\u0270\u026e\3\2\2\2\u0271\u0274\3\2\2\2\u0272\u0270"+ + "\3\2\2\2\u0272\u0273\3\2\2\2\u0273\u0275\3\2\2\2\u0274\u0272\3\2\2\2\u0275"+ + "\u0277\7\b\2\2\u0276\u0278\7\25\2\2\u0277\u0276\3\2\2\2\u0277\u0278\3"+ + "\2\2\2\u0278\u0279\3\2\2\2\u0279\u027a\5\36\20\2\u027a\u027b\b\23\1\2"+ + "\u027b\u02ad\3\2\2\2\u027c\u027e\7H\2\2\u027d\u027c\3\2\2\2\u027d\u027e"+ + "\3\2\2\2\u027e\u027f\3\2\2\2\u027f\u0284\5\26\f\2\u0280\u0281\7\5\2\2"+ + "\u0281\u0283\5\26\f\2\u0282\u0280\3\2\2\2\u0283\u0286\3\2\2\2\u0284\u0282"+ + "\3\2\2\2\u0284\u0285\3\2\2\2\u0285\u0287\3\2\2\2\u0286\u0284\3\2\2\2\u0287"+ + "\u0288\7\b\2\2\u0288\u0289\7\24\2\2\u0289\u028a\5\36\20\2\u028a\u028b"+ + "\b\23\1\2\u028b\u02ad\3\2\2\2\u028c\u028e\7H\2\2\u028d\u028c\3\2\2\2\u028d"+ + "\u028e\3\2\2\2\u028e\u028f\3\2\2\2\u028f\u0294\5\26\f\2\u0290\u0291\7"+ + "\5\2\2\u0291\u0293\5\26\f\2\u0292\u0290\3\2\2\2\u0293\u0296\3\2\2\2\u0294"+ + "\u0292\3\2\2\2\u0294\u0295\3\2\2\2\u0295\u0297\3\2\2\2\u0296\u0294\3\2"+ + "\2\2\u0297\u0298\7\b\2\2\u0298\u0299\7\26\2\2\u0299\u029a\5\36\20\2\u029a"+ + "\u029b\b\23\1\2\u029b\u02ad\3\2\2\2\u029c\u029e\7H\2\2\u029d\u029c\3\2"+ + "\2\2\u029d\u029e\3\2\2\2\u029e\u029f\3\2\2\2\u029f\u02a4\5\26\f\2\u02a0"+ + "\u02a1\7\5\2\2\u02a1\u02a3\5\26\f\2\u02a2\u02a0\3\2\2\2\u02a3\u02a6\3"+ + "\2\2\2\u02a4\u02a2\3\2\2\2\u02a4\u02a5\3\2\2\2\u02a5\u02a7\3\2\2\2\u02a6"+ + "\u02a4\3\2\2\2\u02a7\u02a8\7\b\2\2\u02a8\u02a9\78\2\2\u02a9\u02aa\5\36"+ + "\20\2\u02aa\u02ab\b\23\1\2\u02ab\u02ad\3\2\2\2\u02ac\u026b\3\2\2\2\u02ac"+ + "\u027d\3\2\2\2\u02ac\u028d\3\2\2\2\u02ac\u029d\3\2\2\2\u02ad%\3\2\2\2"+ + "\u02ae\u02b3\5(\25\2\u02af\u02b0\7\5\2\2\u02b0\u02b2\5(\25\2\u02b1\u02af"+ + "\3\2\2\2\u02b2\u02b5\3\2\2\2\u02b3\u02b1\3\2\2\2\u02b3\u02b4\3\2\2\2\u02b4"+ + "\'\3\2\2\2\u02b5\u02b3\3\2\2\2\u02b6\u02bb\5\26\f\2\u02b7\u02b8\7\5\2"+ + "\2\u02b8\u02ba\5\26\f\2\u02b9\u02b7\3\2\2\2\u02ba\u02bd\3\2\2\2\u02bb"+ + "\u02b9\3\2\2\2\u02bb\u02bc\3\2\2\2\u02bc\u02be\3\2\2\2\u02bd\u02bb\3\2"+ + "\2\2\u02be\u02bf\7\32\2\2\u02bf\u02c0\5\36\20\2\u02c0\u02c1\3\2\2\2\u02c1"+ + "\u02c2\b\25\1\2\u02c2)\3\2\2\2\u02c3\u02c8\5,\27\2\u02c4\u02c5\7\5\2\2"+ + "\u02c5\u02c7\5,\27\2\u02c6\u02c4\3\2\2\2\u02c7\u02ca\3\2\2\2\u02c8\u02c6"+ + "\3\2\2\2\u02c8\u02c9\3\2\2\2\u02c9+\3\2\2\2\u02ca\u02c8\3\2\2\2\u02cb"+ + "\u02cd\7H\2\2\u02cc\u02cb\3\2\2\2\u02cc\u02cd\3\2\2\2\u02cd\u02ce\3\2"+ + "\2\2\u02ce\u02d3\5\26\f\2\u02cf\u02d0\7\5\2\2\u02d0\u02d2\5\26\f\2\u02d1"+ + "\u02cf\3\2\2\2\u02d2\u02d5\3\2\2\2\u02d3\u02d1\3\2\2\2\u02d3\u02d4\3\2"+ + "\2\2\u02d4\u02d6\3\2\2\2\u02d5\u02d3\3\2\2\2\u02d6\u02d8\7\b\2\2\u02d7"+ + "\u02d9\7\25\2\2\u02d8\u02d7\3\2\2\2\u02d8\u02d9\3\2\2\2\u02d9\u02da\3"+ + "\2\2\2\u02da\u02db\5\36\20\2\u02db\u02dc\3\2\2\2\u02dc\u02dd\b\27\1\2"+ + "\u02dd-\3\2\2\2Q/8R[fkt{\177\u0085\u0091\u0094\u009d\u00a0\u00af\u00b7"+ + "\u00c2\u00c7\u00cc\u00e3\u00ea\u00f1\u00f8\u00ff\u0106\u010d\u013d\u0141"+ + "\u0147\u014b\u0158\u015c\u0162\u0166\u0173\u0177\u017d\u0181\u018e\u0192"+ + "\u0198\u019c\u01a9\u01ad\u01b3\u01b7\u01c4\u01c8\u01ce\u01d2\u01dc\u01ea"+ + "\u01ec\u0214\u0224\u0228\u0233\u0235\u0245\u024c\u025d\u025f\u0267\u026b"+ + "\u0272\u0277\u027d\u0284\u028d\u0294\u029d\u02a4\u02ac\u02b3\u02bb\u02c8"+ + "\u02cc\u02d3\u02d8"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/KodkodVisitor.java b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/KodkodVisitor.java new file mode 100644 index 00000000..9c618099 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.core/src/eu/modelwriter/kodkod/core/recognizer/KodkodVisitor.java @@ -0,0 +1,577 @@ +// Generated from C:/Users/anil.ozturk/IdeaProjects/untitled1/src\Kodkod.g4 by ANTLR 4.5.1 +package eu.modelwriter.kodkod.core.recognizer; +import org.antlr.v4.runtime.tree.ParseTreeVisitor; + +/** + * This interface defines a complete generic visitor for a parse tree produced + * by {@link KodkodParser}. + * + * @param The return type of the visit operation. Use {@link Void} for + * operations with no return type. + */ +public interface KodkodVisitor extends ParseTreeVisitor { + /** + * Visit a parse tree produced by {@link KodkodParser#problem}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitProblem(KodkodParser.ProblemContext ctx); + /** + * Visit a parse tree produced by {@link KodkodParser#options}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitOptions(KodkodParser.OptionsContext ctx); + /** + * Visit a parse tree produced by the {@code symmetryBreaking} + * labeled alternative in {@link KodkodParser#option}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSymmetryBreaking(KodkodParser.SymmetryBreakingContext ctx); + /** + * Visit a parse tree produced by the {@code bitWidth} + * labeled alternative in {@link KodkodParser#option}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitBitWidth(KodkodParser.BitWidthContext ctx); + /** + * Visit a parse tree produced by the {@code skolemDepth} + * labeled alternative in {@link KodkodParser#option}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSkolemDepth(KodkodParser.SkolemDepthContext ctx); + /** + * Visit a parse tree produced by the {@code sharing} + * labeled alternative in {@link KodkodParser#option}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSharing(KodkodParser.SharingContext ctx); + /** + * Visit a parse tree produced by {@link KodkodParser#universe}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitUniverse(KodkodParser.UniverseContext ctx); + /** + * Visit a parse tree produced by {@link KodkodParser#relations}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitRelations(KodkodParser.RelationsContext ctx); + /** + * Visit a parse tree produced by {@link KodkodParser#relation}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitRelation(KodkodParser.RelationContext ctx); + /** + * Visit a parse tree produced by {@link KodkodParser#tupleSet}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitTupleSet(KodkodParser.TupleSetContext ctx); + /** + * Visit a parse tree produced by {@link KodkodParser#tuple}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitTuple(KodkodParser.TupleContext ctx); + /** + * Visit a parse tree produced by {@link KodkodParser#atom}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitAtom(KodkodParser.AtomContext ctx); + /** + * Visit a parse tree produced by {@link KodkodParser#relationId}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitRelationId(KodkodParser.RelationIdContext ctx); + /** + * Visit a parse tree produced by {@link KodkodParser#variableId}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitVariableId(KodkodParser.VariableIdContext ctx); + /** + * Visit a parse tree produced by {@link KodkodParser#integer}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitInteger(KodkodParser.IntegerContext ctx); + /** + * Visit a parse tree produced by {@link KodkodParser#arity}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitArity(KodkodParser.ArityContext ctx); + /** + * Visit a parse tree produced by the {@code no} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitNo(KodkodParser.NoContext ctx); + /** + * Visit a parse tree produced by the {@code some} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSome(KodkodParser.SomeContext ctx); + /** + * Visit a parse tree produced by the {@code forOne} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitForOne(KodkodParser.ForOneContext ctx); + /** + * Visit a parse tree produced by the {@code sumDeclaration} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSumDeclaration(KodkodParser.SumDeclarationContext ctx); + /** + * Visit a parse tree produced by the {@code forAll} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitForAll(KodkodParser.ForAllContext ctx); + /** + * Visit a parse tree produced by the {@code lone} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitLone(KodkodParser.LoneContext ctx); + /** + * Visit a parse tree produced by the {@code lt} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitLt(KodkodParser.LtContext ctx); + /** + * Visit a parse tree produced by the {@code forSome} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitForSome(KodkodParser.ForSomeContext ctx); + /** + * Visit a parse tree produced by the {@code not} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitNot(KodkodParser.NotContext ctx); + /** + * Visit a parse tree produced by the {@code f_paranthesis} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitF_paranthesis(KodkodParser.F_paranthesisContext ctx); + /** + * Visit a parse tree produced by the {@code and} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitAnd(KodkodParser.AndContext ctx); + /** + * Visit a parse tree produced by the {@code function} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitFunction(KodkodParser.FunctionContext ctx); + /** + * Visit a parse tree produced by the {@code gte} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitGte(KodkodParser.GteContext ctx); + /** + * Visit a parse tree produced by the {@code acyclic} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitAcyclic(KodkodParser.AcyclicContext ctx); + /** + * Visit a parse tree produced by the {@code let} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitLet(KodkodParser.LetContext ctx); + /** + * Visit a parse tree produced by the {@code lte} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitLte(KodkodParser.LteContext ctx); + /** + * Visit a parse tree produced by the {@code or} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitOr(KodkodParser.OrContext ctx); + /** + * Visit a parse tree produced by the {@code in} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIn(KodkodParser.InContext ctx); + /** + * Visit a parse tree produced by the {@code one} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitOne(KodkodParser.OneContext ctx); + /** + * Visit a parse tree produced by the {@code false} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitFalse(KodkodParser.FalseContext ctx); + /** + * Visit a parse tree produced by the {@code iff} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIff(KodkodParser.IffContext ctx); + /** + * Visit a parse tree produced by the {@code eq} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEq(KodkodParser.EqContext ctx); + /** + * Visit a parse tree produced by the {@code gt} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitGt(KodkodParser.GtContext ctx); + /** + * Visit a parse tree produced by the {@code equal} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEqual(KodkodParser.EqualContext ctx); + /** + * Visit a parse tree produced by the {@code forLone} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitForLone(KodkodParser.ForLoneContext ctx); + /** + * Visit a parse tree produced by the {@code totalOrder} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitTotalOrder(KodkodParser.TotalOrderContext ctx); + /** + * Visit a parse tree produced by the {@code true} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitTrue(KodkodParser.TrueContext ctx); + /** + * Visit a parse tree produced by the {@code forNo} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitForNo(KodkodParser.ForNoContext ctx); + /** + * Visit a parse tree produced by the {@code implies} + * labeled alternative in {@link KodkodParser#formula}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitImplies(KodkodParser.ImpliesContext ctx); + /** + * Visit a parse tree produced by the {@code product} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitProduct(KodkodParser.ProductContext ctx); + /** + * Visit a parse tree produced by the {@code var} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitVar(KodkodParser.VarContext ctx); + /** + * Visit a parse tree produced by the {@code none} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitNone(KodkodParser.NoneContext ctx); + /** + * Visit a parse tree produced by the {@code union} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitUnion(KodkodParser.UnionContext ctx); + /** + * Visit a parse tree produced by the {@code boxjoin} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitBoxjoin(KodkodParser.BoxjoinContext ctx); + /** + * Visit a parse tree produced by the {@code comprehension} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitComprehension(KodkodParser.ComprehensionContext ctx); + /** + * Visit a parse tree produced by the {@code univ} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitUniv(KodkodParser.UnivContext ctx); + /** + * Visit a parse tree produced by the {@code reflexive} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitReflexive(KodkodParser.ReflexiveContext ctx); + /** + * Visit a parse tree produced by the {@code e_paranthesis} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitE_paranthesis(KodkodParser.E_paranthesisContext ctx); + /** + * Visit a parse tree produced by the {@code iden} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIden(KodkodParser.IdenContext ctx); + /** + * Visit a parse tree produced by the {@code ints} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitInts(KodkodParser.IntsContext ctx); + /** + * Visit a parse tree produced by the {@code intersection} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIntersection(KodkodParser.IntersectionContext ctx); + /** + * Visit a parse tree produced by the {@code rel} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitRel(KodkodParser.RelContext ctx); + /** + * Visit a parse tree produced by the {@code difference} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitDifference(KodkodParser.DifferenceContext ctx); + /** + * Visit a parse tree produced by the {@code transpose} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitTranspose(KodkodParser.TransposeContext ctx); + /** + * Visit a parse tree produced by the {@code join} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitJoin(KodkodParser.JoinContext ctx); + /** + * Visit a parse tree produced by the {@code override} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitOverride(KodkodParser.OverrideContext ctx); + /** + * Visit a parse tree produced by the {@code ifExpression} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIfExpression(KodkodParser.IfExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code closure} + * labeled alternative in {@link KodkodParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitClosure(KodkodParser.ClosureContext ctx); + /** + * Visit a parse tree produced by the {@code minus} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitMinus(KodkodParser.MinusContext ctx); + /** + * Visit a parse tree produced by the {@code intConstant} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIntConstant(KodkodParser.IntConstantContext ctx); + /** + * Visit a parse tree produced by the {@code i_paranthesis} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitI_paranthesis(KodkodParser.I_paranthesisContext ctx); + /** + * Visit a parse tree produced by the {@code ifIntExpression} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIfIntExpression(KodkodParser.IfIntExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code count} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitCount(KodkodParser.CountContext ctx); + /** + * Visit a parse tree produced by the {@code sum} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSum(KodkodParser.SumContext ctx); + /** + * Visit a parse tree produced by the {@code divide} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitDivide(KodkodParser.DivideContext ctx); + /** + * Visit a parse tree produced by the {@code multiply} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitMultiply(KodkodParser.MultiplyContext ctx); + /** + * Visit a parse tree produced by the {@code modulo} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitModulo(KodkodParser.ModuloContext ctx); + /** + * Visit a parse tree produced by the {@code plus} + * labeled alternative in {@link KodkodParser#intexpression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitPlus(KodkodParser.PlusContext ctx); + /** + * Visit a parse tree produced by {@link KodkodParser#decls}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitDecls(KodkodParser.DeclsContext ctx); + /** + * Visit a parse tree produced by the {@code oneOf} + * labeled alternative in {@link KodkodParser#decl}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitOneOf(KodkodParser.OneOfContext ctx); + /** + * Visit a parse tree produced by the {@code loneOf} + * labeled alternative in {@link KodkodParser#decl}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitLoneOf(KodkodParser.LoneOfContext ctx); + /** + * Visit a parse tree produced by the {@code someOf} + * labeled alternative in {@link KodkodParser#decl}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSomeOf(KodkodParser.SomeOfContext ctx); + /** + * Visit a parse tree produced by the {@code setOf} + * labeled alternative in {@link KodkodParser#decl}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSetOf(KodkodParser.SetOfContext ctx); + /** + * Visit a parse tree produced by {@link KodkodParser#letDecls}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitLetDecls(KodkodParser.LetDeclsContext ctx); + /** + * Visit a parse tree produced by {@link KodkodParser#letDecl}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitLetDecl(KodkodParser.LetDeclContext ctx); + /** + * Visit a parse tree produced by {@link KodkodParser#comprehensionDecls}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitComprehensionDecls(KodkodParser.ComprehensionDeclsContext ctx); + /** + * Visit a parse tree produced by {@link KodkodParser#comprehensionDecl}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitComprehensionDecl(KodkodParser.ComprehensionDeclContext ctx); +} \ No newline at end of file diff --git a/Source/eu.modelwriter.kodkod.editor/.classpath b/Source/eu.modelwriter.kodkod.editor/.classpath new file mode 100644 index 00000000..eca7bdba --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Source/eu.modelwriter.kodkod.editor/.gitignore b/Source/eu.modelwriter.kodkod.editor/.gitignore new file mode 100644 index 00000000..ae3c1726 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/Source/eu.modelwriter.kodkod.editor/.project b/Source/eu.modelwriter.kodkod.editor/.project new file mode 100644 index 00000000..c6bb1287 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/.project @@ -0,0 +1,28 @@ + + + eu.modelwriter.kodkod.editor + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/Source/eu.modelwriter.kodkod.editor/.settings/org.eclipse.jdt.core.prefs b/Source/eu.modelwriter.kodkod.editor/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..0c68a61d --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/Source/eu.modelwriter.kodkod.editor/META-INF/MANIFEST.MF b/Source/eu.modelwriter.kodkod.editor/META-INF/MANIFEST.MF new file mode 100644 index 00000000..823dc160 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/META-INF/MANIFEST.MF @@ -0,0 +1,15 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Editor +Bundle-SymbolicName: eu.modelwriter.kodkod.editor;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: eu.modelwriter.kodkod.editor.Activator +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.jface.text, + org.eclipse.ui.editors, + eu.modelwriter.kodkod.core, + eu.modelwriter.kodkod.visualization;bundle-version="1.0.0" +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ActivationPolicy: lazy +Bundle-ClassPath: . diff --git a/Source/eu.modelwriter.kodkod.editor/build.properties b/Source/eu.modelwriter.kodkod.editor/build.properties new file mode 100644 index 00000000..e9863e28 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/build.properties @@ -0,0 +1,5 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml diff --git a/Source/eu.modelwriter.kodkod.editor/plugin.xml b/Source/eu.modelwriter.kodkod.editor/plugin.xml new file mode 100644 index 00000000..198ad9e4 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/plugin.xml @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/Activator.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/Activator.java new file mode 100644 index 00000000..796f6877 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/Activator.java @@ -0,0 +1,50 @@ +package eu.modelwriter.kodkod.editor; + +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "eu.modelwriter.kodkod.editor"; //$NON-NLS-1$ + + // The shared instance + private static Activator plugin; + + /** + * The constructor + */ + public Activator() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/CodeCompletionProcessor.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/CodeCompletionProcessor.java new file mode 100644 index 00000000..9779520b --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/CodeCompletionProcessor.java @@ -0,0 +1,91 @@ +package eu.modelwriter.kodkod.editor; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.contentassist.CompletionProposal; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.IContentAssistProcessor; +import org.eclipse.jface.text.contentassist.IContextInformation; +import org.eclipse.jface.text.contentassist.IContextInformationValidator; + +import eu.modelwriter.kodkod.editor.scanners.FormulasScanner; + +public class CodeCompletionProcessor implements IContentAssistProcessor { + + private final IContextInformation[] NO_CONTEXTS = {}; + // private final char[] activationChars = new char[] { '[', '(' }; + + @Override + public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) { + final List proposals = new ArrayList(); + try { + final IDocument document = viewer.getDocument(); + Character c = document.getChar(offset - 1); + int temp = offset - 1; + String s = ""; + + if (Character.isAlphabetic(c)) { + while (Character.isAlphabetic(c)) { + s += c; + temp--; + c = document.getChar(temp); + } + s = new StringBuilder(s).reverse().toString(); + + for (int i = 0; i < FormulasScanner.formulasKeywords.length; i++) { + if (FormulasScanner.formulasKeywords[i].startsWith(s)) { + proposals.add(new CompletionProposal(FormulasScanner.formulasKeywords[i], temp + 1, s.length(), + FormulasScanner.formulasKeywords[i].length())); + } + } + } else if (c == '(') { + document.replace(temp, 1, "()"); + } else if (c == '[') { + document.replace(temp, 1, "[]"); + } + + if (proposals.isEmpty() && s == "") { + for (int i = 0; i < FormulasScanner.formulasKeywords.length; i++) { + proposals.add(new CompletionProposal(FormulasScanner.formulasKeywords[i], temp + 1, s.length(), + FormulasScanner.formulasKeywords[i].length())); + } + } + + } catch (final BadLocationException e) { + e.printStackTrace(); + } + final ICompletionProposal[] result = new ICompletionProposal[proposals.size()]; + proposals.toArray(result); + return result; + } + + @Override + public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) { + return this.NO_CONTEXTS; + } + + @Override + public char[] getCompletionProposalAutoActivationCharacters() { + // return this.activationChars; + return null; + } + + @Override + public char[] getContextInformationAutoActivationCharacters() { + return null; + } + + @Override + public String getErrorMessage() { + return "No completions available."; + } + + @Override + public IContextInformationValidator getContextInformationValidator() { + return null; + } +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/ColorManager.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/ColorManager.java new file mode 100644 index 00000000..973c20b2 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/ColorManager.java @@ -0,0 +1,31 @@ +package eu.modelwriter.kodkod.editor; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Display; + +public class ColorManager { + @SuppressWarnings("rawtypes") + protected Map fColorTable = new HashMap(10); + + public void dispose() { + @SuppressWarnings("rawtypes") + Iterator e = fColorTable.values().iterator(); + while (e.hasNext()) + ((Color) e.next()).dispose(); + } + + @SuppressWarnings("unchecked") + public Color getColor(RGB rgb) { + Color color = (Color) fColorTable.get(rgb); + if (color == null) { + color = new Color(Display.getCurrent(), rgb); + fColorTable.put(rgb, color); + } + return color; + } +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/IColorConstants.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/IColorConstants.java new file mode 100644 index 00000000..750eac90 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/IColorConstants.java @@ -0,0 +1,15 @@ +package eu.modelwriter.kodkod.editor; + +import org.eclipse.swt.graphics.RGB; + +public interface IColorConstants { + RGB COMMENT = new RGB(102, 0, 0); + RGB OPTIONS_KEYWORD = new RGB(102, 51, 0); + RGB OPTIONS_DEFAULT = new RGB(102, 102, 0); + RGB UNIVERSE = new RGB(51, 102, 0); + RGB REL_BOUND = new RGB(0, 102, 102); + RGB REL_BOUND_BRACKETS = new RGB(102, 0, 204); + RGB FORMULAS_KEYWORD = new RGB(0, 0, 255); + RGB FORMULAS_SPECCHARS = new RGB(153, 0, 76); + RGB DEFAULT = new RGB(25, 25, 25); +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/RelationModelDocumentProvider.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/RelationModelDocumentProvider.java new file mode 100644 index 00000000..65ee6bdd --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/RelationModelDocumentProvider.java @@ -0,0 +1,31 @@ +package eu.modelwriter.kodkod.editor; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentPartitioner; +import org.eclipse.jface.text.rules.FastPartitioner; +import org.eclipse.ui.editors.text.FileDocumentProvider; + +import eu.modelwriter.kodkod.editor.scanners.RelationModelPartitionScanner; + +/** + * Document provider is needed for document partitioning. In our editor, they are just Comment + * Partition and Default Partition (for codes). + * + * @author anil.ozturk + * + */ +public class RelationModelDocumentProvider extends FileDocumentProvider { + + @Override + protected IDocument createDocument(final Object element) throws CoreException { + final IDocument document = super.createDocument(element); + if (document != null) { + final IDocumentPartitioner partitioner = new FastPartitioner( + new RelationModelPartitionScanner(), RelationModelPartitionScanner.PARTITION_TYPES); + partitioner.connect(document); + document.setDocumentPartitioner(partitioner); + } + return document; + } +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/RelationModelEditStrategy.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/RelationModelEditStrategy.java new file mode 100644 index 00000000..b069e382 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/RelationModelEditStrategy.java @@ -0,0 +1,27 @@ +package eu.modelwriter.kodkod.editor; + +import org.eclipse.jface.text.DocumentCommand; +import org.eclipse.jface.text.IAutoEditStrategy; +import org.eclipse.jface.text.IDocument; + +public class RelationModelEditStrategy implements IAutoEditStrategy { + + private void configureCaret(final DocumentCommand command) { + command.caretOffset = command.offset + 1; + command.shiftsCaret = false; + } + + @Override + public void customizeDocumentCommand(final IDocument document, final DocumentCommand command) { + if (command.text.equals("(")) { + command.text = "()"; + this.configureCaret(command); + } else if (command.text.equals("[")) { + command.text = "[]"; + this.configureCaret(command); + } else if (command.text.equals("{")) { + command.text = "{}"; + this.configureCaret(command); + } + } +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/RelationModelEditor.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/RelationModelEditor.java new file mode 100644 index 00000000..c4d48796 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/RelationModelEditor.java @@ -0,0 +1,87 @@ +package eu.modelwriter.kodkod.editor; + +import java.awt.Frame; + +import javax.swing.JPanel; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.awt.SWT_AWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.editors.text.TextEditor; +import org.eclipse.ui.part.MultiPageEditorPart; + +public class RelationModelEditor extends MultiPageEditorPart { + private class KodKodEditor extends TextEditor { + private final ColorManager colorManager; + + public KodKodEditor() { + super(); + this.colorManager = new ColorManager(); + this.setSourceViewerConfiguration( + new RelationModelEditorSourceViewerConfiguration(this.colorManager)); + this.setDocumentProvider(new RelationModelDocumentProvider()); + } + + @Override + public void dispose() { + this.colorManager.dispose(); + super.dispose(); + } + } + + private static Frame frame; + private static Composite animationEditor; + + public static void addGraphToFrame(final JPanel graph) { + if (RelationModelEditor.frame == null) { + RelationModelEditor.frame = SWT_AWT.new_Frame(RelationModelEditor.animationEditor); + } + if (RelationModelEditor.frame.getComponents().length > 0) { + RelationModelEditor.frame.remove(0); + } + RelationModelEditor.frame.revalidate(); + graph.revalidate(); + RelationModelEditor.frame.add(graph); + } + + KodKodEditor kodKodEditor; + + @Override + protected void createPages() { + this.kodKodEditor = new KodKodEditor(); + RelationModelEditor.animationEditor = new Composite(this.getContainer(), SWT.EMBEDDED); + RelationModelEditor.frame = null; + + try { + int pageIndex = this.addPage(this.kodKodEditor, this.getEditorInput()); + this.setPageText(pageIndex, "Specification"); + pageIndex = this.addPage(RelationModelEditor.animationEditor); + this.setPageText(pageIndex, "Manager"); + } catch (final PartInitException e) { + e.printStackTrace(); + } + } + + @Override + public void doSave(final IProgressMonitor monitor) { + final IEditorPart editor = this.getActiveEditor(); + if (editor instanceof KodKodEditor) { + editor.doSave(monitor); + } else { + // do nothing + } + } + + @Override + public void doSaveAs() { + // do nothing + } + + @Override + public boolean isSaveAsAllowed() { + return false; + } +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/RelationModelEditorSourceViewerConfiguration.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/RelationModelEditorSourceViewerConfiguration.java new file mode 100644 index 00000000..cb783847 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/RelationModelEditorSourceViewerConfiguration.java @@ -0,0 +1,118 @@ +package eu.modelwriter.kodkod.editor; + +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.jface.text.IAutoEditStrategy; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.contentassist.ContentAssistant; +import org.eclipse.jface.text.contentassist.IContentAssistant; +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.presentation.PresentationReconciler; +import org.eclipse.jface.text.reconciler.IReconciler; +import org.eclipse.jface.text.reconciler.MonoReconciler; +import org.eclipse.jface.text.rules.DefaultDamagerRepairer; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.ui.editors.text.TextSourceViewerConfiguration; + +import eu.modelwriter.kodkod.editor.scanners.CommentScanner; +import eu.modelwriter.kodkod.editor.scanners.FormulasScanner; +import eu.modelwriter.kodkod.editor.scanners.OptionScanner; +import eu.modelwriter.kodkod.editor.scanners.RelBoundScanner; +import eu.modelwriter.kodkod.editor.scanners.RelationModelPartitionScanner; +import eu.modelwriter.kodkod.editor.scanners.UniverseScanner; + +public class RelationModelEditorSourceViewerConfiguration extends TextSourceViewerConfiguration { + private final ColorManager manager; + + public RelationModelEditorSourceViewerConfiguration(final ColorManager manager) { + this.manager = manager; + } + + @Override + public IAutoEditStrategy[] getAutoEditStrategies(final ISourceViewer sourceViewer, + final String contentType) { + final IAutoEditStrategy strategy = new RelationModelEditStrategy(); + return new IAutoEditStrategy[] {strategy}; + } + + @Override + public String[] getConfiguredContentTypes(final ISourceViewer sourceViewer) { + return RelationModelPartitionScanner.PARTITION_TYPES; + } + + @Override + public String getConfiguredDocumentPartitioning(final ISourceViewer sourceViewer) { + return super.getConfiguredDocumentPartitioning(sourceViewer); + } + + /** + * Create and set some specifications of content assistant. We define our completion processor + * as @CodeCompletionProcessor. + */ + @Override + public IContentAssistant getContentAssistant(final ISourceViewer sourceViewer) { + final ContentAssistant assistant = new ContentAssistant(); + assistant.setContentAssistProcessor(new CodeCompletionProcessor(), + IDocument.DEFAULT_CONTENT_TYPE); + assistant.setAutoActivationDelay(500); + assistant.enableAutoActivation(true); + assistant.enableAutoInsert(true); + assistant.setProposalPopupOrientation(IContentAssistant.PROPOSAL_OVERLAY); + assistant.setContextInformationPopupOrientation(IContentAssistant.CONTEXT_INFO_ABOVE); + + return assistant; + } + + /** + * We set presentation reconciler and it's damagers and repairers. This requires for syntax + * highlighting that used partition scanner. + */ + @Override + public IPresentationReconciler getPresentationReconciler(final ISourceViewer sourceViewer) { + final PresentationReconciler reconciler = new PresentationReconciler(); + + // Comment Partition + DefaultDamagerRepairer dr = new DefaultDamagerRepairer(new CommentScanner(this.manager)); + reconciler.setDamager(dr, RelationModelPartitionScanner.RELATION_MODEL_COMMENT); + reconciler.setRepairer(dr, RelationModelPartitionScanner.RELATION_MODEL_COMMENT); + + // Options Partition + dr = new DefaultDamagerRepairer(new OptionScanner(this.manager)); + reconciler.setDamager(dr, RelationModelPartitionScanner.RELATION_MODEL_OPTION); + reconciler.setRepairer(dr, RelationModelPartitionScanner.RELATION_MODEL_OPTION); + + // Universe Partition + dr = new DefaultDamagerRepairer(new UniverseScanner(this.manager)); + reconciler.setDamager(dr, RelationModelPartitionScanner.RELATION_MODEL_UNIVERSE); + reconciler.setRepairer(dr, RelationModelPartitionScanner.RELATION_MODEL_UNIVERSE); + + // Relations Partition + dr = new DefaultDamagerRepairer(new RelBoundScanner(this.manager)); + reconciler.setDamager(dr, RelationModelPartitionScanner.RELATION_MODEL_REL_BOUND); + reconciler.setRepairer(dr, RelationModelPartitionScanner.RELATION_MODEL_REL_BOUND); + + // Default Partition(Formulas Partition) + dr = new DefaultDamagerRepairer(new FormulasScanner(this.manager)); + reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE); + reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE); + + return reconciler; + } + + /** + * We set reconciler and it's strategy for reconciling. + * + * @MetaModelValidationReconcilingStrategy we set our strategy while editing. It may be both + * incremental and full. + */ + @Override + public IReconciler getReconciler(final ISourceViewer sourceViewer) { + MonoReconciler reconciler = null; + if (sourceViewer != null) { + reconciler = new MonoReconciler( + new RelationModelReconcilingStrategy(sourceViewer.getDocument()), true); + reconciler.setDelay(1000); + reconciler.setProgressMonitor(new NullProgressMonitor()); + } + return reconciler; + } +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/RelationModelReconcilingStrategy.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/RelationModelReconcilingStrategy.java new file mode 100644 index 00000000..35a684f0 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/RelationModelReconcilingStrategy.java @@ -0,0 +1,71 @@ +package eu.modelwriter.kodkod.editor; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.reconciler.DirtyRegion; +import org.eclipse.jface.text.reconciler.IReconcilingStrategy; +import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension; +import org.eclipse.swt.widgets.Display; + +import eu.modelwriter.kodkod.editor.manager.SynchronizationManager; + +public class RelationModelReconcilingStrategy + implements IReconcilingStrategy, IReconcilingStrategyExtension { + + private IDocument document; + private SynchronizationManager manager; + + public RelationModelReconcilingStrategy(final IDocument document) { + this.document = document; + } + + @Override + public void initialReconcile() { + if (this.document == null) { + return; + } + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + try { + RelationModelReconcilingStrategy.this.manager = + new SynchronizationManager(RelationModelReconcilingStrategy.this.document); + } catch (final BadLocationException e) { + e.printStackTrace(); + } + } + }); + } + + @Override + public void reconcile(final DirtyRegion dirtyRegion, final IRegion subRegion) { + this.reconcile(dirtyRegion); + } + + @Override + public void reconcile(final IRegion partition) { + if (this.document == null) { + return; + } + + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + RelationModelReconcilingStrategy.this.manager + .evaluate(RelationModelReconcilingStrategy.this.document, partition); + } + }); + } + + @Override + public void setDocument(final IDocument document) { + this.document = document; + } + + @Override + public void setProgressMonitor(final IProgressMonitor monitor) { + // do nothing + } +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/manager/RelationParser.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/manager/RelationParser.java new file mode 100644 index 00000000..44c216db --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/manager/RelationParser.java @@ -0,0 +1,171 @@ +package eu.modelwriter.kodkod.editor.manager; + +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; + +public class RelationParser { + + private class TupleSet { + private final ArrayList tuples; + + public TupleSet() { + this.tuples = new ArrayList(); + } + + public void addTuple(final String tuple) { + this.tuples.add(tuple); + } + + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + if (obj == this) { + return true; + } + + for (final String tuple : ((TupleSet) obj).tuples) { + if (!this.tuples.contains(tuple)) { + return false; + } + } + + return true; + } + + public void removeTuple(final String tuple) { + this.tuples.remove(tuple); + } + + @Override + public String toString() { + String result = "["; + for (int i = 0; i < this.tuples.size(); i++) { + if (i == 0) { + result += this.tuples.get(i); + } else { + result += "," + this.tuples.get(i); + } + } + result += "]"; + + return result; + } + } + + private final String relationData; + private String lowerBoundData; + private String upperBoundData; + private final TupleSet lowerTupleSet; + private final TupleSet upperTupleSet; + + public RelationParser(final String relation) { + this.relationData = relation; + this.lowerTupleSet = new TupleSet(); + this.upperTupleSet = new TupleSet(); + + try { + this.init(); + } catch (final IOException e) { + e.printStackTrace(); + } + } + + public void init() throws IOException { + final StringReader reader = new StringReader(this.relationData); + + int open = 0; + int offset = 1; + int c = reader.read(); + while (c != -1) { + if (c == '[' || c == '{') { + open++; + } else if (c == ']' || c == '}') { + open--; + } + + if (open == 1 && c == ',') { + reader.close(); + break; + } + + offset++; + c = reader.read(); + } + reader.close(); + + if (offset > this.relationData.length()) { + this.lowerBoundData = + this.relationData.substring(this.relationData.indexOf("[") + 1, offset - 2); + this.upperBoundData = this.relationData.substring(offset - 2, this.relationData.length() - 1); + } else { + this.lowerBoundData = + this.relationData.substring(this.relationData.indexOf("[") + 1, offset - 1); + this.upperBoundData = this.relationData.substring(offset, this.relationData.length() - 1); + } + + this.parse2Tuples(); + } + + public void move2Lower(final String tuple) { + this.lowerTupleSet.addTuple(tuple); + if (this.lowerTupleSet.equals(this.upperTupleSet)) { + this.upperTupleSet.tuples.clear(); + } + } + + public void move2Upper(final String tuple) { + if (this.upperTupleSet.tuples.isEmpty()) { + this.upperTupleSet.tuples.addAll(this.lowerTupleSet.tuples); + this.lowerTupleSet.removeTuple(tuple); + } else { + this.upperTupleSet.addTuple(tuple); + this.lowerTupleSet.removeTuple(tuple); + } + } + + private void parse2Tuples() { + if (!this.lowerBoundData.isEmpty()) { + this.lowerBoundData = this.lowerBoundData.substring(this.lowerBoundData.indexOf("[") + 1, + this.lowerBoundData.lastIndexOf("]")); + + final String ltuples[] = this.lowerBoundData.split(","); + for (final String tuple : ltuples) { + if (!tuple.isEmpty()) { + this.lowerTupleSet.addTuple(tuple.trim()); + } + } + } + + if (!this.upperBoundData.isEmpty()) { + this.upperBoundData = this.upperBoundData.substring(this.upperBoundData.indexOf("[") + 1, + this.upperBoundData.lastIndexOf("]")); + + final String utuples[] = this.upperBoundData.split(","); + for (final String tuple : utuples) { + if (!tuple.isEmpty()) { + this.upperTupleSet.addTuple(tuple.trim()); + } + } + } + } + + public void removeTuples(final ArrayList relatedTuples) { + for (final String tuple : relatedTuples) { + this.lowerTupleSet.removeTuple(tuple); + this.upperTupleSet.removeTuple(tuple); + } + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(this.relationData); + builder.delete(builder.indexOf("[") + 1, builder.lastIndexOf("]")); + builder.insert(builder.indexOf("[") + 1, + this.lowerTupleSet.toString() + "," + this.upperTupleSet.toString()); + + return builder.toString(); + } +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/manager/SynchronizationManager.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/manager/SynchronizationManager.java new file mode 100644 index 00000000..4564529f --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/manager/SynchronizationManager.java @@ -0,0 +1,139 @@ +package eu.modelwriter.kodkod.editor.manager; + +import javax.swing.JPanel; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.BadPartitioningException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentExtension3; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITypedRegion; + +import eu.modelwriter.kodkod.core.KodkodAnalyzer; +import eu.modelwriter.kodkod.core.KodkodAnalyzer.PARSE_AREA; +import eu.modelwriter.kodkod.core.model.Universe; +import eu.modelwriter.kodkod.editor.RelationModelEditor; +import eu.modelwriter.kodkod.editor.manager.transformer.UniverseTransformer; +import eu.modelwriter.kodkod.editor.scanners.RelationModelPartitionScanner; +import eu.modelwriter.kodkod.visualization.Visualization; + +public class SynchronizationManager { + private Visualization instance; + private Universe kodkodUniverse; + private eu.modelwriter.kodkod.visualization.model.Universe visUniverse; + private final KodkodAnalyzer kodkodAnalyzer; + private IDocument document; + + public SynchronizationManager(final IDocument document) throws BadLocationException { + this.kodkodAnalyzer = new KodkodAnalyzer(); + this.document = document; + this.evaluate(document, null); + this.subscribeToVis(); + } + + public void evaluate(final IDocument document, final IRegion dirtyRegion) { + this.document = document; + try { + final ITypedRegion changedPartition = + dirtyRegion == null ? null : document.getPartition(dirtyRegion.getOffset()); + this.parseRequiredPartitions(changedPartition); + if (this.kodkodUniverse != null) { + this.runVisualization(this.visUniverse); + } + } catch (final BadLocationException e) { + e.printStackTrace(); + } + } + + private ITypedRegion getPartition(final String partitionContentType) { + final IDocumentExtension3 extension = (IDocumentExtension3) this.document; + ITypedRegion[] computePartitioning = null; + try { + computePartitioning = extension.computePartitioning(IDocumentExtension3.DEFAULT_PARTITIONING, + 0, this.document.getLength(), false); + } catch (BadLocationException | BadPartitioningException e) { + e.printStackTrace(); + } + + for (final ITypedRegion iTypedRegion : computePartitioning) { + if (iTypedRegion.getType().equals(partitionContentType)) { + return iTypedRegion; + } + } + return null; + } + + private String getPartitionString(final ITypedRegion partition) { + String partitionString = null; + try { + partitionString = this.document.get(partition.getOffset(), partition.getLength()); + } catch (final BadLocationException e) { + e.printStackTrace(); + } + return partitionString; + } + + private void parseRequiredPartitions(final ITypedRegion changedPartition) + throws BadLocationException { + PARSE_AREA changedArea = null; + String changedPartitionString; + + if (changedPartition != null) { + switch (changedPartition.getType()) { + case RelationModelPartitionScanner.RELATION_MODEL_OPTION: + changedArea = KodkodAnalyzer.PARSE_AREA.OPTIONS; + changedPartitionString = this.getPartitionString( + this.getPartition(RelationModelPartitionScanner.RELATION_MODEL_OPTION)); + break; + case RelationModelPartitionScanner.RELATION_MODEL_UNIVERSE: + changedArea = KodkodAnalyzer.PARSE_AREA.UNIVERSE; + changedPartitionString = this.getPartitionString( + this.getPartition(RelationModelPartitionScanner.RELATION_MODEL_UNIVERSE)); + this.runParser(changedPartitionString, changedArea); + break; + case RelationModelPartitionScanner.RELATION_MODEL_REL_BOUND: + changedArea = KodkodAnalyzer.PARSE_AREA.RELATION; + changedPartitionString = this.getPartitionString( + this.getPartition(RelationModelPartitionScanner.RELATION_MODEL_UNIVERSE)); + final String relBoundString = this.getPartitionString( + this.getPartition(RelationModelPartitionScanner.RELATION_MODEL_REL_BOUND)); + changedPartitionString += relBoundString; + this.runParser(changedPartitionString, changedArea); + break; + case RelationModelPartitionScanner.DEFAULT_CONTENT_TYPE: + changedArea = KodkodAnalyzer.PARSE_AREA.FORMULAS; + changedPartitionString = this.document.get(); + this.runParser(changedPartitionString, changedArea); + break; + default: + break; + } + } else { + changedPartitionString = this.document.get(); + changedArea = KodkodAnalyzer.PARSE_AREA.FULL_DOCUMENT; + this.runParser(changedPartitionString, changedArea); + } + } + + private void runParser(final String changedPartitionString, final PARSE_AREA changedArea) + throws BadLocationException { + this.kodkodUniverse = this.kodkodAnalyzer.parseKodkod(changedPartitionString, changedArea); + if (this.kodkodUniverse == null) { + return; + } + this.visUniverse = UniverseTransformer.getInstance().transformKodkod2Vis(this.kodkodUniverse); + } + + private void runVisualization(final eu.modelwriter.kodkod.visualization.model.Universe visUniverse) { + this.instance = Visualization.getInstance(visUniverse, "kodkodUniv"); + final JPanel graph = this.instance.getGraph(); + RelationModelEditor.addGraphToFrame(graph); + } + + private void subscribeToVis() { + if (this.instance != null) { + final VisualizationSubscriber vs = new VisualizationSubscriber(this.document); + this.instance.getNotifierList().add(vs); + } + } +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/manager/VisualizationSubscriber.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/manager/VisualizationSubscriber.java new file mode 100644 index 00000000..04106cb6 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/manager/VisualizationSubscriber.java @@ -0,0 +1,506 @@ +package eu.modelwriter.kodkod.editor.manager; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.BadPartitioningException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentExtension3; +import org.eclipse.jface.text.ITypedRegion; +import org.eclipse.swt.widgets.Display; + +import eu.modelwriter.kodkod.core.ModelBuildVisitor; +import eu.modelwriter.kodkod.core.model.Atom; +import eu.modelwriter.kodkod.core.model.Relation; +import eu.modelwriter.kodkod.core.model.Tuple; +import eu.modelwriter.kodkod.editor.scanners.RelationModelPartitionScanner; +import eu.modelwriter.kodkod.visualization.Notifier; + +public class VisualizationSubscriber implements Notifier { + IDocument document; + + public VisualizationSubscriber(final IDocument document) { + this.document = document; + } + + @Override + public void addTupleNotify(final String arg0, final List arg1, final String arg2) { + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + try { + final String relationName = arg0; + final List tuple = arg1; + final String bound = arg2; + + final ModelBuildVisitor v = new ModelBuildVisitor(); + final Atom atomsOfTuple[] = new Atom[tuple.size()]; + for (int i = 0; i < atomsOfTuple.length; i++) { + atomsOfTuple[i] = new Atom(tuple.get(i)); + } + + v.getUniverse().getRelation(relationName) + .addAtomWithTuple(bound.equals("lower") ? true : false, atomsOfTuple); + + final String relationLine = VisualizationSubscriber.this.getRelationLine(relationName); + final int startOfRelationLine = + VisualizationSubscriber.this.document.get().indexOf(relationLine); + final int endOfRelationLine = startOfRelationLine + relationLine.length(); + final String newRelationLineOfRelation = VisualizationSubscriber.this + .getNewRelationLine4AddedTuple(relationLine, tuple, bound); + VisualizationSubscriber.this.document.replace(startOfRelationLine, endOfRelationLine, + newRelationLineOfRelation); + + if (tuple.size() == 1) { + final String universeString = + VisualizationSubscriber.this.getPartitionString(VisualizationSubscriber.this + .getPartition(RelationModelPartitionScanner.RELATION_MODEL_UNIVERSE)); + final String afterNewAtom = universeString.substring(universeString.indexOf("}")); + final String newUniverseString = + universeString.replace(afterNewAtom, ", " + tuple.get(0) + afterNewAtom); + final int startOfUniverse = + VisualizationSubscriber.this.document.get().indexOf(universeString); + final int endOfUniverse = startOfUniverse + universeString.length(); + VisualizationSubscriber.this.document.replace(startOfUniverse, endOfUniverse, + newUniverseString); + } + } catch (final BadLocationException e) { + e.printStackTrace(); + } + } + }); + } + + @Override + public void addTupleNotify(final String arg0, final String arg1, final List arg2, + final String arg3) { + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + try { + final String relationName = arg0; + final String inRelationName = arg1; + final List tuple = arg2; + final String bound = arg3; + + final ModelBuildVisitor v = new ModelBuildVisitor(); + final Atom atomsOfTuple[] = new Atom[tuple.size()]; + for (int i = 0; i < atomsOfTuple.length; i++) { + atomsOfTuple[i] = new Atom(tuple.get(i)); + } + + v.getUniverse().getRelation(relationName) + .addAtomWithTuple(bound.equals("lower") ? true : false, atomsOfTuple); + v.getUniverse().getRelation(inRelationName) + .addAtomWithTuple(bound.equals("lower") ? true : false, atomsOfTuple); + + final String relationLine = VisualizationSubscriber.this.getRelationLine(relationName); + final int startOfRelationLine = + VisualizationSubscriber.this.document.get().indexOf(relationLine); + final int endOfRelationLine = startOfRelationLine + relationLine.length(); + final String newRelationLineOfRelation = VisualizationSubscriber.this + .getNewRelationLine4AddedTuple(relationLine, tuple, bound); + VisualizationSubscriber.this.document.replace(startOfRelationLine, endOfRelationLine, + newRelationLineOfRelation); + + if (tuple.size() == 1) { + final String universeString = + VisualizationSubscriber.this.getPartitionString(VisualizationSubscriber.this + .getPartition(RelationModelPartitionScanner.RELATION_MODEL_UNIVERSE)); + final String afterNewAtom = universeString.substring(universeString.indexOf("}")); + final String newUniverseString = + universeString.replace(afterNewAtom, ", " + tuple.get(0) + afterNewAtom); + final int startOfUniverse = + VisualizationSubscriber.this.document.get().indexOf(universeString); + final int endOfUniverse = startOfUniverse + universeString.length(); + VisualizationSubscriber.this.document.replace(startOfUniverse, endOfUniverse, + newUniverseString); + } + + final String inRelationLine = + VisualizationSubscriber.this.getRelationLine(inRelationName); + final int startOfInRelationLine = + VisualizationSubscriber.this.document.get().indexOf(relationLine); + final int endOfInRelationLine = startOfInRelationLine + inRelationLine.length(); + final String newRelationLineOfInRelation = VisualizationSubscriber.this + .getNewRelationLine4AddedTuple(inRelationLine, tuple, bound); + VisualizationSubscriber.this.document.replace(startOfInRelationLine, endOfInRelationLine, + newRelationLineOfInRelation); + + } catch (final BadLocationException e) { + e.printStackTrace(); + } + } + }); + } + + private String getNewRelationLine4AddedTuple(final String relationLine, final List tuple, + final String bound) { + final String tupleString = this.makeTupleString(tuple); + String newRelationLine = relationLine; + String beforeNewTuple; + newRelationLine = newRelationLine.replaceAll("\\{", "["); + newRelationLine = newRelationLine.replaceAll("\\}", "]"); + int index; + if (bound.toLowerCase().equals("lower")) { + index = newRelationLine.indexOf(":") + 1; + newRelationLine = newRelationLine.substring(index); + index += newRelationLine.indexOf("[") + 1; + newRelationLine = newRelationLine.substring(newRelationLine.indexOf("[") + 1); + index += newRelationLine.indexOf("[") + 1; // second '[' is found. + beforeNewTuple = relationLine.substring(0, index); + newRelationLine = relationLine.replace(beforeNewTuple, beforeNewTuple + tupleString + ","); + } else if (bound.toLowerCase().equals("upper")) { + index = newRelationLine.lastIndexOf("]"); + newRelationLine = newRelationLine.substring(0, index); + index = newRelationLine.lastIndexOf("]"); + beforeNewTuple = relationLine.substring(0, index); + newRelationLine = relationLine.replace(beforeNewTuple, beforeNewTuple + "," + tupleString); + } + return newRelationLine; + } + + protected String getNewRelationLine4MovedLowerTuple(final String relationLine, + final List tuple) { + final RelationParser parser = new RelationParser(relationLine); + parser.move2Lower(tuple.toString()); + + return parser.toString(); + } + + protected String getNewRelationLine4MovedUpperTuple(final String relationLine, + final List tuple) { + final RelationParser parser = new RelationParser(relationLine); + parser.move2Upper(tuple.toString()); + + return parser.toString(); + } + + protected String getNewRelationLine4RemovedTuple(final String relationLine, + final ArrayList relatedTuplesWith, final String bound) { + final ArrayList relatedTuples = new ArrayList(); + for (final Tuple tuple : relatedTuplesWith) { + relatedTuples.add(tuple.toString()); + } + + final RelationParser parser = new RelationParser(relationLine); + parser.removeTuples(relatedTuples); + + return parser.toString(); + } + + private ITypedRegion getPartition(final String partitionContentType) { + final IDocumentExtension3 extension = (IDocumentExtension3) this.document; + ITypedRegion[] computePartitioning = null; + try { + computePartitioning = extension.computePartitioning(IDocumentExtension3.DEFAULT_PARTITIONING, + 0, this.document.getLength(), false); + } catch (BadLocationException | BadPartitioningException e) { + e.printStackTrace(); + } + + for (final ITypedRegion iTypedRegion : computePartitioning) { + if (iTypedRegion.getType().equals(partitionContentType)) { + return iTypedRegion; + } + } + return null; + } + + private String getPartitionString(final ITypedRegion partition) { + String partitionString = null; + try { + partitionString = this.document.get(partition.getOffset(), partition.getLength()); + } catch (final BadLocationException e) { + e.printStackTrace(); + } + return partitionString; + } + + private String getRelationLine(final String relationName) { + String relBoundString = this.getPartitionString( + this.getPartition(RelationModelPartitionScanner.RELATION_MODEL_REL_BOUND)); + + String relationLine = ""; + relBoundString = relBoundString.replaceAll("\r", "\n"); + final String[] split = relBoundString.split("\n"); + for (final String line : split) { + if (line.contains(":")) { + final String leftSideOfLine = line.substring(0, line.indexOf(':')); + if (leftSideOfLine.contains(relationName)) { + relationLine = line; + break; + } + } + } + return relationLine; + } + + String makeTupleString(final List atoms) { + String tupleString = ""; + tupleString += "["; + + final String atom = atoms.get(0); + if (atom != null) { + tupleString += atom; + } + + for (int i = 1; i < atoms.size(); i++) { + tupleString += ", " + atoms.get(i); + } + + tupleString += "]"; + return tupleString; + } + + @Override + public void moveToLower(final String arg0, final List arg1) { + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + try { + final String relationName = arg0; + final List tuple = arg1; + + final ModelBuildVisitor v = new ModelBuildVisitor(); + final Atom atomsOfTuple[] = new Atom[tuple.size()]; + for (int i = 0; i < atomsOfTuple.length; i++) { + atomsOfTuple[i] = new Atom(tuple.get(i)); + } + + v.getUniverse().getRelation(relationName).getTuple(atomsOfTuple).setLowerBound(true); + + final String relationLine = VisualizationSubscriber.this.getRelationLine(relationName); + final int startOfRelationLine = + VisualizationSubscriber.this.document.get().indexOf(relationLine); + final String newRelationLineOfRelation = + VisualizationSubscriber.this.getNewRelationLine4MovedLowerTuple(relationLine, tuple); + VisualizationSubscriber.this.document.replace(startOfRelationLine, relationLine.length(), + newRelationLineOfRelation); + } catch (final BadLocationException e) { + e.printStackTrace(); + } + } + }); + } + + @Override + public void moveToLower(final String arg0, final String arg1, final List arg2) { + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + try { + final String relationName = arg0; + final String inRelationName = arg1; + final List tuple = arg2; + + final ModelBuildVisitor v = new ModelBuildVisitor(); + final Atom atomsOfTuple[] = new Atom[tuple.size()]; + for (int i = 0; i < atomsOfTuple.length; i++) { + atomsOfTuple[i] = new Atom(tuple.get(i)); + } + + v.getUniverse().getRelation(relationName).getTuple(atomsOfTuple).setLowerBound(true); + v.getUniverse().getRelation(inRelationName).getTuple(atomsOfTuple).setLowerBound(true); + + final String relationLine = VisualizationSubscriber.this.getRelationLine(relationName); + final int startOfRelationLine = + VisualizationSubscriber.this.document.get().indexOf(relationLine); + final String newRelationLineOfRelation = + VisualizationSubscriber.this.getNewRelationLine4MovedLowerTuple(relationLine, tuple); + + final String inRelationLine = + VisualizationSubscriber.this.getRelationLine(inRelationName); + final int startOfInRelationLine = + VisualizationSubscriber.this.document.get().indexOf(inRelationLine); + final String newRelationLineOfInRelation = VisualizationSubscriber.this + .getNewRelationLine4MovedLowerTuple(inRelationLine, tuple); + + VisualizationSubscriber.this.document.replace(startOfRelationLine, relationLine.length(), + newRelationLineOfRelation); + VisualizationSubscriber.this.document.replace(startOfInRelationLine, + inRelationLine.length(), newRelationLineOfInRelation); + } catch (final BadLocationException e) { + e.printStackTrace(); + } + } + }); + } + + @Override + public void moveToUpper(final String arg0, final List arg1) { + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + try { + final String relationName = arg0; + final List tuple = arg1; + + final ModelBuildVisitor v = new ModelBuildVisitor(); + final Atom atomsOfTuple[] = new Atom[tuple.size()]; + for (int i = 0; i < atomsOfTuple.length; i++) { + atomsOfTuple[i] = new Atom(tuple.get(i)); + } + v.getUniverse().getRelation(relationName).getTuple(atomsOfTuple).setLowerBound(false); + + final String relationLine = VisualizationSubscriber.this.getRelationLine(relationName); + final int startOfRelationLine = + VisualizationSubscriber.this.document.get().indexOf(relationLine); + final String newRelationLineOfRelation = + VisualizationSubscriber.this.getNewRelationLine4MovedUpperTuple(relationLine, tuple); + VisualizationSubscriber.this.document.replace(startOfRelationLine, relationLine.length(), + newRelationLineOfRelation); + } catch (final BadLocationException e) { + e.printStackTrace(); + } + } + }); + } + + @Override + public void moveToUpper(final String arg0, final String arg1, final List arg2) { + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + try { + final String relationName = arg0; + final String inRelationName = arg1; + final List tuple = arg2; + + final ModelBuildVisitor v = new ModelBuildVisitor(); + final Atom atomsOfTuple[] = new Atom[tuple.size()]; + for (int i = 0; i < atomsOfTuple.length; i++) { + atomsOfTuple[i] = new Atom(tuple.get(i)); + } + v.getUniverse().getRelation(relationName).getTuple(atomsOfTuple).setLowerBound(false); + v.getUniverse().getRelation(inRelationName).getTuple(atomsOfTuple).setLowerBound(false); + + final String relationLine = VisualizationSubscriber.this.getRelationLine(relationName); + final int startOfRelationLine = + VisualizationSubscriber.this.document.get().indexOf(relationLine); + final String newRelationLineOfRelation = + VisualizationSubscriber.this.getNewRelationLine4MovedUpperTuple(relationLine, tuple); + + final String inRelationLine = + VisualizationSubscriber.this.getRelationLine(inRelationName); + final int startOfInRelationLine = + VisualizationSubscriber.this.document.get().indexOf(inRelationLine); + final String newRelationLineOfInRelation = VisualizationSubscriber.this + .getNewRelationLine4MovedUpperTuple(inRelationLine, tuple); + + VisualizationSubscriber.this.document.replace(startOfRelationLine, relationLine.length(), + newRelationLineOfRelation); + VisualizationSubscriber.this.document.replace(startOfInRelationLine, + inRelationLine.length(), newRelationLineOfInRelation); + } catch (final BadLocationException e) { + e.printStackTrace(); + } + } + }); + } + + @Override + public void notify(final Serializable arg0) {} + + @Override + public void removeTupleNotify(final String arg0, final List arg1, final String arg2) { + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + final String relationName = arg0; + final List tuple = arg1; + final String bound = arg2; + + final ModelBuildVisitor v = new ModelBuildVisitor(); + final Atom atomsOfTuple[] = new Atom[tuple.size()]; + for (int i = 0; i < atomsOfTuple.length; i++) { + atomsOfTuple[i] = new Atom(tuple.get(i)); + } + + // modify the universe + v.getUniverse().getRelation(relationName).removeTuple(atomsOfTuple); + final ArrayList relations = v.getUniverse().getRelations(); + for (final Relation relation : relations) { + ArrayList relatedTuplesWith; + for (final Atom atom : atomsOfTuple) { + relatedTuplesWith = relation.getRelatedTuplesWith(atom); + for (final Tuple tuple2 : relatedTuplesWith) { + relation.removeTuple(tuple2); + } + } + final List relatedTuples; + + final String relationLine = + VisualizationSubscriber.this.getRelationLine(relation.getName()); + final int startOfRelationLine = + VisualizationSubscriber.this.document.get().indexOf(relationLine); + // final String newRelationLineOfRelation = VisualizationSubscriber.this + // .getNewRelationLine4RemovedTuple(relationLine, relatedTuplesWith, bound); + // VisualizationSubscriber.this.document.replace(startOfRelationLine, + // relationLine.length(), newRelationLineOfRelation); + } + + final String relationLine = VisualizationSubscriber.this.getRelationLine(relationName); + final int startOfRelationLine = + VisualizationSubscriber.this.document.get().indexOf(relationLine); + // final String newRelationLineOfRelation = VisualizationSubscriber.this + // .getNewRelationLine4RemovedTuple(relationLine, tuple, bound); + // VisualizationSubscriber.this.document.replace(startOfRelationLine, relationLine.length(), + // newRelationLineOfRelation); + } + }); + } + + @Override + public void removeTupleNotify(final String arg0, final String arg1, final List arg2, + final String arg3) { + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + final String relationName = arg0; + final String inRelationName = arg1; + final List tuple = arg2; + final String bound = arg3; + + final ModelBuildVisitor v = new ModelBuildVisitor(); + final Atom atomsOfTuple[] = new Atom[tuple.size()]; + for (int i = 0; i < atomsOfTuple.length; i++) { + atomsOfTuple[i] = new Atom(tuple.get(i)); + } + v.getUniverse().getRelation(relationName).removeTuple(atomsOfTuple); + v.getUniverse().getRelation(inRelationName).removeTuple(atomsOfTuple); + + final String relationLine = VisualizationSubscriber.this.getRelationLine(relationName); + final int startOfRelationLine = + VisualizationSubscriber.this.document.get().indexOf(relationLine); + // final String newRelationLineOfRelation = VisualizationSubscriber.this + // .getNewRelationLine4RemovedTuple(relationLine, tuple, bound); + // VisualizationSubscriber.this.document.replace(startOfRelationLine, + // relationLine.length(), + // newRelationLineOfRelation); + + // if (tuple.size() == 1) { + // final String universeString = + // VisualizationSubscriber.this.getPartitionString(VisualizationSubscriber.this + // .getPartition(RelationModelPartitionScanner.RELATION_MODEL_UNIVERSE)); + // final String newUniverseString = ""; + // final int startOfUniverse = + // VisualizationSubscriber.this.document.get().indexOf(universeString); + // VisualizationSubscriber.this.document.replace(startOfUniverse, universeString.length(), + // newUniverseString); + // } + + final String inRelationLine = + VisualizationSubscriber.this.getRelationLine(inRelationName); + final int startOfInRelationLine = + VisualizationSubscriber.this.document.get().indexOf(relationLine); + // final String newRelationLineOfInRelation = VisualizationSubscriber.this + // .getNewRelationLine4RemovedTuple(inRelationLine, tuple, bound); + // VisualizationSubscriber.this.document.replace(startOfInRelationLine, + // inRelationLine.length(), newRelationLineOfInRelation); + } + }); + } +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/manager/transformer/UniverseTransformer.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/manager/transformer/UniverseTransformer.java new file mode 100644 index 00000000..dbd71fb7 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/manager/transformer/UniverseTransformer.java @@ -0,0 +1,119 @@ +package eu.modelwriter.kodkod.editor.manager.transformer; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map.Entry; + +import eu.modelwriter.kodkod.core.model.Atom; +import eu.modelwriter.kodkod.core.model.Relation; +import eu.modelwriter.kodkod.core.model.Tuple; +import eu.modelwriter.kodkod.core.model.Universe; + +public class UniverseTransformer { + private static UniverseTransformer transformer; + + public static UniverseTransformer getInstance() { + if (UniverseTransformer.transformer == null) { + UniverseTransformer.transformer = new UniverseTransformer(); + } + + return UniverseTransformer.transformer; + } + + private final HashMap relwithParent = new HashMap<>(); + private final HashMap>> relwithTypes = new HashMap<>(); + + UniverseTransformer() {} + + public eu.modelwriter.kodkod.visualization.model.Universe transformKodkod2Vis( + final Universe kodkodUniverse) { + final eu.modelwriter.kodkod.visualization.model.Universe visUniverse = + new eu.modelwriter.kodkod.visualization.model.Universe(); + + for (final Relation kodkodRelation : kodkodUniverse.getRelations()) { + eu.modelwriter.kodkod.visualization.model.Relation visRelation = + new eu.modelwriter.kodkod.visualization.model.Relation(kodkodRelation.getName()); + visUniverse.addRelation(visRelation); + visRelation = this.transformKodkodRel2VisRel(visRelation, kodkodRelation); + for (final Tuple kodkodTuple : kodkodRelation.getTuples()) { + final eu.modelwriter.kodkod.visualization.model.Tuple visTuple = + new eu.modelwriter.kodkod.visualization.model.Tuple(kodkodTuple.getText()); + visTuple.setBound(kodkodTuple.isLowerBound() ? "lower" : "upper"); + visRelation.addTuple(visTuple); + for (final Atom kodkodAtom : kodkodTuple.getAtoms()) { + final eu.modelwriter.kodkod.visualization.model.Atom visAtom = + new eu.modelwriter.kodkod.visualization.model.Atom(kodkodAtom.getText()); + visTuple.addAtom(visAtom); + visAtom.setData(kodkodAtom.getData()); + visAtom.setId(kodkodAtom.getId()); + } + } + } + + for (final Entry entry : this.relwithParent.entrySet()) { + final eu.modelwriter.kodkod.visualization.model.Relation parent = + visUniverse.getRelation(entry.getValue()); + final eu.modelwriter.kodkod.visualization.model.Relation relation = + visUniverse.getRelation(entry.getKey()); + relation.setParent(parent); + } + + for (final Entry>> entry : this.relwithTypes.entrySet()) { + final eu.modelwriter.kodkod.visualization.model.Relation relation = + visUniverse.getRelation(entry.getKey()); + for (final List types : entry.getValue()) { + final eu.modelwriter.kodkod.visualization.model.Relation[] typesArray = + new eu.modelwriter.kodkod.visualization.model.Relation[types.size()]; + for (int i = 0; i < typesArray.length; i++) { + typesArray[i] = visUniverse.getRelation(types.get(i)); + } + relation.addTypes(typesArray); + } + } + + return visUniverse; + } + + private eu.modelwriter.kodkod.visualization.model.Relation transformKodkodRel2VisRel( + final eu.modelwriter.kodkod.visualization.model.Relation visRel, final Relation kodkodRel) { + + if (kodkodRel.getParent() != null) { + this.relwithParent.put(visRel.getName(), kodkodRel.getParent().getName()); + } + + final List> visRelTypes = new ArrayList<>(); + final List> types = kodkodRel.getTypes(); + for (final List list : types) { + final ArrayList visRelType = new ArrayList<>(); + visRelTypes.add(visRelType); + for (final Relation relation : list) { + visRelType.add(relation.getName()); + } + } + this.relwithTypes.put(visRel.getName(), visRelTypes); + + visRel.setId(kodkodRel.getId()); + visRel.setAbstract(kodkodRel.isAbstract()); + visRel.setEnum(kodkodRel.isEnum()); + visRel.setMeta(kodkodRel.isMeta()); + visRel.setPrivate(kodkodRel.isPrivate()); + if (kodkodRel.getMultiplicity() != null) { + switch (kodkodRel.getMultiplicity()) { + case LONE: + visRel.setMultiplicity(eu.modelwriter.kodkod.visualization.model.Relation.Multiplicity.LONE); + break; + case ONE: + visRel.setMultiplicity(eu.modelwriter.kodkod.visualization.model.Relation.Multiplicity.ONE); + break; + case SOME: + visRel.setMultiplicity(eu.modelwriter.kodkod.visualization.model.Relation.Multiplicity.SOME); + break; + default: + break; + } + } + return visRel; + } + +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/rules/BracketsRule.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/rules/BracketsRule.java new file mode 100644 index 00000000..7db8777f --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/rules/BracketsRule.java @@ -0,0 +1,24 @@ +package eu.modelwriter.kodkod.editor.rules; + +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.Token; + +public class BracketsRule implements IRule { + private final IToken token; + + public BracketsRule(final IToken token) { + this.token = token; + } + + @Override + public IToken evaluate(final ICharacterScanner scanner) { + final int c = scanner.read(); + if (c == '[' || c == ']') { + return this.token; + } + scanner.unread(); + return Token.UNDEFINED; + } +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/rules/RelationBoundsRule.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/rules/RelationBoundsRule.java new file mode 100644 index 00000000..012a485b --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/rules/RelationBoundsRule.java @@ -0,0 +1,65 @@ +package eu.modelwriter.kodkod.editor.rules; + +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.MultiLineRule; +import org.eclipse.jface.text.rules.Token; + +public class RelationBoundsRule extends MultiLineRule { + + public RelationBoundsRule(final String startSequence, final String endSequence, + final IToken token) { + super(startSequence, endSequence, token); + } + + @Override + protected IToken doEvaluate(final ICharacterScanner scanner, final boolean resume) { + + if (resume) { + if (this.endSequenceDetected(scanner)) { + return this.fToken; + } + } else { + final int c = scanner.read(); + if (c == this.fStartSequence[0]) { + if (this.sequenceDetected(scanner, this.fStartSequence, false)) { + if (this.endSequenceDetected(scanner)) { + return this.fToken; + } + } + } + } + + scanner.unread(); + return Token.UNDEFINED; + } + + @Override + protected boolean endSequenceDetected(final ICharacterScanner scanner) { + + int readCount = 1; + int c; + int open = 0; + while ((c = scanner.read()) != ICharacterScanner.EOF) { + + if (c == '{') { + open++; + } else if (c == '}') { + open--; + if (open == 0) { + if (this.sequenceDetected(scanner, this.fEndSequence, this.fBreaksOnEOF)) { + return true; + } + } + } + + readCount++; + } + + for (; readCount > 0; readCount--) { + scanner.unread(); + } + + return false; + } +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/scanners/CommentScanner.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/scanners/CommentScanner.java new file mode 100644 index 00000000..e3a26c7e --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/scanners/CommentScanner.java @@ -0,0 +1,24 @@ +package eu.modelwriter.kodkod.editor.scanners; + +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.RuleBasedScanner; +import org.eclipse.jface.text.rules.Token; + +import eu.modelwriter.kodkod.editor.ColorManager; +import eu.modelwriter.kodkod.editor.IColorConstants; + +/** + * We already define the comment rules in @MetaModelPartitionScanner In this class just provide + * token for that rules + * + * @author anil.ozturk + * + */ +public class CommentScanner extends RuleBasedScanner { + public CommentScanner(final ColorManager manager) { + final IToken commentToken = + new Token(new TextAttribute(manager.getColor(IColorConstants.COMMENT))); + this.setDefaultReturnToken(commentToken); + } +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/scanners/FormulasScanner.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/scanners/FormulasScanner.java new file mode 100644 index 00000000..2abcf28b --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/scanners/FormulasScanner.java @@ -0,0 +1,88 @@ +package eu.modelwriter.kodkod.editor.scanners; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWhitespaceDetector; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.RuleBasedScanner; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WhitespaceRule; +import org.eclipse.jface.text.rules.WordRule; + +import eu.modelwriter.kodkod.editor.ColorManager; +import eu.modelwriter.kodkod.editor.IColorConstants; + +public class FormulasScanner extends RuleBasedScanner { + public static final String[] formulasKeywords = + new String[] {"no", "lone", "one", "some", "not", "in", "sum", "acyclic", "function", "ord", + "and", "or", "if", "iff", "all", "let", "true", "false", "then", "else", "iden", "none", + "univ", "ints", "plus", "minus", "mul", "div", "modulo", "disj", "set"}; + + public static final ArrayList formulasSpecChars = + new ArrayList(Arrays.asList("!", "=", "<", "<=", ">", ">=", "->", "&&", "||", "=>", + "<=>", "~", "^", "*", "+", "&", "-", ".", ".*", ".^", "++", "#", "/", "%")); + + public FormulasScanner(final ColorManager manager) { + final IToken keywordToken = + new Token(new TextAttribute(manager.getColor(IColorConstants.FORMULAS_KEYWORD))); + final IToken specCharsToken = + new Token(new TextAttribute(manager.getColor(IColorConstants.FORMULAS_SPECCHARS))); + final IToken defaultToken = + new Token(new TextAttribute(manager.getColor(IColorConstants.DEFAULT))); + + final List rules = new ArrayList(); + + rules.add(new WhitespaceRule(new IWhitespaceDetector() { + + @Override + public boolean isWhitespace(final char c) { + return Character.isWhitespace(c); + } + })); + + final WordRule specCharsRule = new WordRule(new IWordDetector() { + + @Override + public boolean isWordPart(final char c) { + return FormulasScanner.formulasSpecChars.contains(String.valueOf(c)); + } + + @Override + public boolean isWordStart(final char c) { + return FormulasScanner.formulasSpecChars.contains(String.valueOf(c)); + } + }, defaultToken); + + for (final String chars : FormulasScanner.formulasSpecChars) { + specCharsRule.addWord(chars, specCharsToken); + } + rules.add(specCharsRule); + + final WordRule keywordRule = new WordRule(new IWordDetector() { + + @Override + public boolean isWordPart(final char c) { + return Character.isAlphabetic(c); + } + + @Override + public boolean isWordStart(final char c) { + return Character.isAlphabetic(c); + } + }, defaultToken); + + for (int i = 0; i < FormulasScanner.formulasKeywords.length; i++) { + keywordRule.addWord(FormulasScanner.formulasKeywords[i], keywordToken); + } + rules.add(keywordRule); + + final IRule[] result = new IRule[rules.size()]; + rules.toArray(result); + this.setRules(result); + } +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/scanners/OptionScanner.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/scanners/OptionScanner.java new file mode 100644 index 00000000..bec67013 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/scanners/OptionScanner.java @@ -0,0 +1,63 @@ +package eu.modelwriter.kodkod.editor.scanners; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWhitespaceDetector; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.RuleBasedScanner; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WhitespaceRule; +import org.eclipse.jface.text.rules.WordRule; + +import eu.modelwriter.kodkod.editor.ColorManager; +import eu.modelwriter.kodkod.editor.IColorConstants; + +public class OptionScanner extends RuleBasedScanner { + private static final String[] optionKeywords = + new String[] {"symmetry_breaking", "bit_width", "skolem_depth", "sharing"}; + + public OptionScanner(final ColorManager manager) { + final IToken keywordToken = + new Token(new TextAttribute(manager.getColor(IColorConstants.OPTIONS_KEYWORD))); + final IToken defaultToken = + new Token(new TextAttribute(manager.getColor(IColorConstants.OPTIONS_DEFAULT))); + + final List rules = new ArrayList(); + + rules.add(new WhitespaceRule(new IWhitespaceDetector() { + + @Override + public boolean isWhitespace(final char c) { + return Character.isWhitespace(c); + } + })); + + final WordRule keywordRule = new WordRule(new IWordDetector() { + + @Override + public boolean isWordPart(final char c) { + return Character.isLetter(c) | c == '_'; + } + + @Override + public boolean isWordStart(final char c) { + return Character.isLetter(c); + } + }, defaultToken); + + for (int i = 0; i < OptionScanner.optionKeywords.length; i++) { + keywordRule.addWord(OptionScanner.optionKeywords[i], keywordToken); + } + rules.add(keywordRule); + + this.setDefaultReturnToken(defaultToken); + + final IRule[] result = new IRule[rules.size()]; + rules.toArray(result); + this.setRules(result); + } +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/scanners/RelBoundScanner.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/scanners/RelBoundScanner.java new file mode 100644 index 00000000..cad8e572 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/scanners/RelBoundScanner.java @@ -0,0 +1,48 @@ +package eu.modelwriter.kodkod.editor.scanners; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.rules.EndOfLineRule; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWhitespaceDetector; +import org.eclipse.jface.text.rules.MultiLineRule; +import org.eclipse.jface.text.rules.RuleBasedScanner; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WhitespaceRule; + +import eu.modelwriter.kodkod.editor.ColorManager; +import eu.modelwriter.kodkod.editor.IColorConstants; +import eu.modelwriter.kodkod.editor.rules.BracketsRule; + +public class RelBoundScanner extends RuleBasedScanner { + public RelBoundScanner(final ColorManager manager) { + final IToken token = new Token(new TextAttribute(manager.getColor(IColorConstants.REL_BOUND))); + final IToken bracketsToken = + new Token(new TextAttribute(manager.getColor(IColorConstants.REL_BOUND_BRACKETS))); + final IToken commentToken = + new Token(new TextAttribute(manager.getColor(IColorConstants.COMMENT))); + + final List rules = new ArrayList(); + + rules.add(new MultiLineRule("/**", "**/", commentToken)); + rules.add(new EndOfLineRule("--", commentToken)); + // rules.add(new EndOfLineRule("//", commentToken)); + rules.add(new BracketsRule(bracketsToken)); + + rules.add(new WhitespaceRule(new IWhitespaceDetector() { + + @Override + public boolean isWhitespace(final char c) { + return Character.isWhitespace(c); + } + })); + this.setDefaultReturnToken(token); + + final IRule[] result = new IRule[rules.size()]; + rules.toArray(result); + this.setRules(result); + } +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/scanners/RelationModelPartitionScanner.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/scanners/RelationModelPartitionScanner.java new file mode 100644 index 00000000..6b5b2881 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/scanners/RelationModelPartitionScanner.java @@ -0,0 +1,61 @@ +package eu.modelwriter.kodkod.editor.scanners; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.rules.EndOfLineRule; +import org.eclipse.jface.text.rules.IPredicateRule; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.MultiLineRule; +import org.eclipse.jface.text.rules.RuleBasedPartitionScanner; +import org.eclipse.jface.text.rules.Token; + +import eu.modelwriter.kodkod.editor.rules.RelationBoundsRule; + +public class RelationModelPartitionScanner extends RuleBasedPartitionScanner { + public final static String RELATION_MODEL_COMMENT = "__RELATION_MODEL_COMMENT"; + public final static String RELATION_MODEL_OPTION = "__RELATION_MODEL_OPTION"; + public final static String RELATION_MODEL_UNIVERSE = "__RELATION_MODEL_UNIVERSE"; + public final static String RELATION_MODEL_REL_BOUND = "__RELATION_MODEL_REL_BOUND"; + public final static String DEFAULT_CONTENT_TYPE = "__dftl_partition_content_type"; + + public final static String[] PARTITION_TYPES = new String[] {IDocument.DEFAULT_CONTENT_TYPE, + RelationModelPartitionScanner.RELATION_MODEL_COMMENT, + RelationModelPartitionScanner.RELATION_MODEL_OPTION, + RelationModelPartitionScanner.RELATION_MODEL_UNIVERSE, + RelationModelPartitionScanner.RELATION_MODEL_REL_BOUND}; + + public RelationModelPartitionScanner() { + final IToken commentPartition = new Token(RelationModelPartitionScanner.RELATION_MODEL_COMMENT); + final IToken optionPartition = new Token(RelationModelPartitionScanner.RELATION_MODEL_OPTION); + final IToken universePartition = + new Token(RelationModelPartitionScanner.RELATION_MODEL_UNIVERSE); + final IToken relBoundPartition = + new Token(RelationModelPartitionScanner.RELATION_MODEL_REL_BOUND); + + final List rules = new ArrayList(); + rules.add(new MultiLineRule("/**", "**/", commentPartition)); + rules.add(new EndOfLineRule("--", commentPartition)); + // rules.add(new EndOfLineRule("//", commentPartition)); + rules.add(new MultiLineRule("options {", "}", optionPartition)); + rules.add(new MultiLineRule("universe {", "}", universePartition)); + rules.add(new MultiLineRule("universe [", "]", universePartition)); + rules.add(new RelationBoundsRule("relations", "}", relBoundPartition)); + + final IPredicateRule[] result = new IPredicateRule[rules.size()]; + rules.toArray(result); + this.setPredicateRules(result); + } + + @Override + public void setPartialRange(final IDocument document, int offset, final int length, + final String contentType, final int partitionOffset) { + if (contentType != null + && contentType.equals(RelationModelPartitionScanner.RELATION_MODEL_REL_BOUND)) { + offset = partitionOffset; + } + super.setPartialRange(document, offset, length, contentType, partitionOffset); + } +} diff --git a/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/scanners/UniverseScanner.java b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/scanners/UniverseScanner.java new file mode 100644 index 00000000..87119aa4 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.editor/src/eu/modelwriter/kodkod/editor/scanners/UniverseScanner.java @@ -0,0 +1,16 @@ +package eu.modelwriter.kodkod.editor.scanners; + +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.RuleBasedScanner; +import org.eclipse.jface.text.rules.Token; + +import eu.modelwriter.kodkod.editor.ColorManager; +import eu.modelwriter.kodkod.editor.IColorConstants; + +public class UniverseScanner extends RuleBasedScanner { + public UniverseScanner(final ColorManager manager) { + final IToken token = new Token(new TextAttribute(manager.getColor(IColorConstants.UNIVERSE))); + this.setDefaultReturnToken(token); + } +} diff --git a/Source/eu.modelwriter.kodkod.visualization/.classpath b/Source/eu.modelwriter.kodkod.visualization/.classpath new file mode 100644 index 00000000..eca7bdba --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Source/eu.modelwriter.kodkod.visualization/.gitignore b/Source/eu.modelwriter.kodkod.visualization/.gitignore new file mode 100644 index 00000000..ae3c1726 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/Source/eu.modelwriter.kodkod.visualization/.project b/Source/eu.modelwriter.kodkod.visualization/.project new file mode 100644 index 00000000..a4f700d4 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/.project @@ -0,0 +1,28 @@ + + + eu.modelwriter.kodkod.visualization + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/Source/eu.modelwriter.kodkod.visualization/.settings/org.eclipse.jdt.core.prefs b/Source/eu.modelwriter.kodkod.visualization/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..0c68a61d --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/Source/eu.modelwriter.kodkod.visualization/META-INF/MANIFEST.MF b/Source/eu.modelwriter.kodkod.visualization/META-INF/MANIFEST.MF new file mode 100644 index 00000000..cd5884b6 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/META-INF/MANIFEST.MF @@ -0,0 +1,14 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Visualization +Bundle-SymbolicName: eu.modelwriter.kodkod.visualization +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: eu.modelwriter.kodkod.visualization.Activator +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + eu.modelwriter.alloyanalyzer, + eu.modelwriter.traceability.core.persistence +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ActivationPolicy: lazy +Export-Package: eu.modelwriter.kodkod.visualization, + eu.modelwriter.kodkod.visualization.model diff --git a/Source/eu.modelwriter.kodkod.visualization/build.properties b/Source/eu.modelwriter.kodkod.visualization/build.properties new file mode 100644 index 00000000..34d2e4d2 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/Source/eu.modelwriter.kodkod.visualization/icon/atom.png b/Source/eu.modelwriter.kodkod.visualization/icon/atom.png new file mode 100644 index 00000000..fa0ebb42 Binary files /dev/null and b/Source/eu.modelwriter.kodkod.visualization/icon/atom.png differ diff --git a/Source/eu.modelwriter.kodkod.visualization/icon/relation.png b/Source/eu.modelwriter.kodkod.visualization/icon/relation.png new file mode 100644 index 00000000..dbddee88 Binary files /dev/null and b/Source/eu.modelwriter.kodkod.visualization/icon/relation.png differ diff --git a/Source/eu.modelwriter.kodkod.visualization/icon/sig.png b/Source/eu.modelwriter.kodkod.visualization/icon/sig.png new file mode 100644 index 00000000..5e343d63 Binary files /dev/null and b/Source/eu.modelwriter.kodkod.visualization/icon/sig.png differ diff --git a/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/Activator.java b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/Activator.java new file mode 100644 index 00000000..8ee31d46 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/Activator.java @@ -0,0 +1,50 @@ +package eu.modelwriter.kodkod.visualization; + +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "eu.modelwriter.kodkod.visualization"; //$NON-NLS-1$ + + // The shared instance + private static Activator plugin; + + /** + * The constructor + */ + public Activator() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + +} diff --git a/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/Notifier.java b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/Notifier.java new file mode 100644 index 00000000..6b1d911d --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/Notifier.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.visualization; + +import java.io.Serializable; +import java.util.List; + +public interface Notifier { + + public void addTupleNotify(String relationName, List tuple, String bound); + + public void addTupleNotify(String relationName, String inRelationName, List tuple, + String bound); + + public void moveToLower(String relationName, List tuple); + + public void moveToLower(String relationName, String inRelationName, List tuple); + + public void moveToUpper(String relationName, List tuple); + + public void moveToUpper(String relationName, String inRelationName, List tuple); + + public void notify(Serializable data); + + /** + * + * @param relationName + * @param tuple : Atoms Name in removed tuple + */ + public void removeTupleNotify(String relationName, List tuple, String bound); + + public void removeTupleNotify(String relationName, String inRelationName, List tuple, + String bound); + +} + diff --git a/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/Serialization.java b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/Serialization.java new file mode 100644 index 00000000..ad7e7277 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/Serialization.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.visualization; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Base64; + +public class Serialization { + + private static Serialization instance = null; + + protected Serialization() { + // Exists only to defeat instantiation. + } + + public static Serialization getInstance() { + if (instance == null) { + instance = new Serialization(); + } + return instance; + } + + /** Read the object from Base64 string. */ + @SuppressWarnings({"unchecked"}) + public T fromString(String string) throws IOException, ClassNotFoundException { + byte[] data = Base64.getDecoder().decode(string); + ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data)); + T object = (T) ois.readObject(); + ois.close(); + return object; + } + + /** Write the object to a Base64 string. */ + public String toString(T object) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(object); + oos.close(); + return Base64.getEncoder().encodeToString(baos.toByteArray()); + } +} diff --git a/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/Utility.java b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/Utility.java new file mode 100644 index 00000000..5d300a69 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/Utility.java @@ -0,0 +1,922 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.visualization; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.MutableTreeNode; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.URI; + +import edu.mit.csail.sdg.alloy4viz.AlloyAtom; +import edu.mit.csail.sdg.alloy4viz.AlloyTuple; +import eu.modelwriter.kodkod.visualization.wizards.createatom.TypeElement; +import eu.modelwriter.traceability.core.persistence.AtomType; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; +import eu.modelwriter.traceability.core.persistence.EntryType; +import eu.modelwriter.traceability.core.persistence.FieldType; +import eu.modelwriter.traceability.core.persistence.ItemType; +import eu.modelwriter.traceability.core.persistence.SigType; +import eu.modelwriter.traceability.core.persistence.TupleType; +import eu.modelwriter.traceability.core.persistence.TypesType; +import eu.modelwriter.traceability.core.persistence.persistenceFactory; +import eu.modelwriter.traceability.core.persistence.internal.ModelIO; + +public class Utility { + + private static Map atomNameIndexMap = new HashMap<>(); + + public static void addAtomToSigType(final String type, final String name) { + final DocumentRoot documentRoot = Utility.getDocumentRoot(); + final EList sigs = documentRoot.getAlloy().getInstance().getSig(); + String index = null; + + for (final SigType sigType : sigs) { + if (sigType.getLabel().equals(type)) { + final AtomType atomType = persistenceFactory.eINSTANCE.createAtomType(); + index = Utility.atomNameIndexMap.get(name); + if (index == null) { + index = Utility.generateId(documentRoot, false); + Utility.atomNameIndexMap.put(name, index); + + final ItemType itemType = persistenceFactory.eINSTANCE.createItemType(); + itemType.setId(index); + + if (name != null) { + final EntryType entryType = persistenceFactory.eINSTANCE.createEntryType(); + itemType.getEntry().add(entryType); + entryType.setKey("Name"); + entryType.setValue(name); + } + + documentRoot.getAlloy().getRepository().getItem().add(itemType); + } + atomType.setLabel(index); + + atomType.setBound(Visualization.getInstance().isLower() ? "lower" : "upper"); + sigType.getAtom().add(atomType); + break; + } + } + + Utility.writeDocumentRoot(documentRoot); + } + + protected static void addAtomToSigTypeWithData(final String type, final String name, + final String data) { + final DocumentRoot documentRoot = Utility.getDocumentRoot(); + final EList sigs = documentRoot.getAlloy().getInstance().getSig(); + final String generatedId = Utility.generateId(documentRoot, false); + + for (final SigType sigType : sigs) { + if (sigType.getLabel().equals(type)) { + final AtomType atomType = persistenceFactory.eINSTANCE.createAtomType(); + atomType.setLabel(generatedId); + sigType.getAtom().add(atomType); + break; + } + } + + final ItemType itemType = persistenceFactory.eINSTANCE.createItemType(); + final EntryType entryTypeName = persistenceFactory.eINSTANCE.createEntryType(); + final EntryType entryTypeData = persistenceFactory.eINSTANCE.createEntryType(); + + itemType.getEntry().add(entryTypeName); + itemType.getEntry().add(entryTypeData); + itemType.setId(generatedId); + entryTypeName.setKey("Name"); + entryTypeName.setValue(name); + entryTypeData.setKey("Data"); + entryTypeData.setValue(data); + + documentRoot.getAlloy().getRepository().getItem().add(itemType); + + Utility.writeDocumentRoot(documentRoot); + } + + protected static void addDataToRepository(final String atomId, final String data) { + final DocumentRoot documentRoot = Utility.getDocumentRoot(); + + final ItemType itemType = Utility.getItemById(atomId); + final EntryType entryType = persistenceFactory.eINSTANCE.createEntryType(); + + itemType.getEntry().add(entryType); + + entryType.setKey("Data"); + entryType.setValue(data); + + documentRoot.getAlloy().getRepository().getItem().add(itemType); + + Utility.writeDocumentRoot(documentRoot); + } + + public static void addRelation2Atoms(final String fromId, final String toId, + final String relation) { + final DocumentRoot documentRoot = Utility.getDocumentRoot(); + + final AtomType fromAtom = persistenceFactory.eINSTANCE.createAtomType(); + fromAtom.setLabel(fromId); + + final AtomType toAtom = persistenceFactory.eINSTANCE.createAtomType(); + toAtom.setLabel(toId); + + final TupleType tuple = persistenceFactory.eINSTANCE.createTupleType(); + tuple.getAtom().add(fromAtom); + tuple.getAtom().add(toAtom); + + final EList fields = documentRoot.getAlloy().getInstance().getField(); + + for (final FieldType fieldType : fields) { + if (relation.equals(fieldType.getLabel())) { + fieldType.getTuple().add(tuple); + break; + } + } + + Utility.writeDocumentRoot(documentRoot); + } + + public static void changeAtomType(final AlloyAtom alloyAtom, final String newType) { + final String id = Utility.itemIdByAlloyAtom(alloyAtom); + Utility.removeRelationFromFieldType(id); + Utility.removeAtomTypeFromSigType(id); + + final DocumentRoot documentRoot = Utility.getDocumentRoot(); + final EList sigs = documentRoot.getAlloy().getInstance().getSig(); + + for (final SigType sigType : sigs) { + if (sigType.getLabel().equals(newType)) { + final AtomType atomType = persistenceFactory.eINSTANCE.createAtomType(); + atomType.setLabel(id); + int i = 0; + for (i = 0; i < sigType.getAtom().size(); i++) { + if (sigType.getAtom().get(i).getLabel().compareTo(atomType.getLabel()) > 0) { + break; + } + } + sigType.getAtom().add(i == 0 ? 0 : i - 1, atomType); + break; + } + } + + Utility.writeDocumentRoot(documentRoot); + } + + protected static String generateId(final DocumentRoot documentRoot, final boolean isWrite) { + final String base = "0000"; + int nextId = documentRoot.getAlloy().getRepository().getNextId(); + + String id = base + nextId; + id = id.substring(id.length() - 5); + + documentRoot.getAlloy().getRepository().setNextId(++nextId); + if (isWrite) { + Utility.writeDocumentRoot(documentRoot); + } + + return id; + } + + public static ArrayList getAllChildIds(final int id) { + final ArrayList ids = new ArrayList<>(); + + final ArrayList sigTypes = Utility.getSigTypeListByParentId(id); + + for (final SigType sigType : sigTypes) { + ids.addAll(Utility.getAllChildIds(sigType.getID())); + } + + ids.add(id); + + return ids; + } + + private static ArrayList getAllParentIds(int id) { + final ArrayList ids = new ArrayList<>(); + do { + ids.add(id); + final SigType sigType = Utility.getSigTypeById(id); + if (sigType.getType().size() == 0) { + id = sigType.getParentID(); + } else { + id = sigType.getType().get(0).getID(); + } + } while (id != 0); + + return ids; + } + + public static String getAtomNameById(final String id) { + final ItemType itemType = Utility.getItemById(id); + final EList entries = itemType.getEntry(); + + for (final EntryType entryType : entries) { + if (entryType.getKey().equals("Name")) { + return entryType.getValue(); + } + } + + return null; + } + + public static AtomType getAtomTypeById(final String id, final String type) { + final EList sigList = Utility.getDocumentRoot().getAlloy().getInstance().getSig(); + + for (final SigType sigType : sigList) { + if (sigType.getLabel().equals(type)) { + final EList atomList = sigType.getAtom(); + for (final AtomType atomType : atomList) { + if (atomType.getLabel().equals(id)) { + return atomType; + } + } + } + } + return null; + } + + public static String getBoundOfAtomType(final AlloyAtom alloyAtom) { + final String id = Utility.itemIdByAlloyAtom(alloyAtom); + final String type = alloyAtom.getType().getName(); + + final DocumentRoot documentRoot = Utility.getDocumentRoot(); + final EList sigList = documentRoot.getAlloy().getInstance().getSig(); + + for (final SigType sigType : sigList) { + if (sigType.getLabel().equals(type)) { + final EList atomList = sigType.getAtom(); + for (final AtomType atomType : atomList) { + if (atomType.getLabel().equals(id)) { + return atomType.getBound(); + } + } + } + } + return null; + } + + public static String getBoundOfTupleType(final AlloyTuple alloyTuple, final String relation) { + final AlloyAtom fromAtom = alloyTuple.getStart(); + final AlloyAtom toAtom = alloyTuple.getEnd(); + + final String fromAtomId = Utility.itemIdByAlloyAtom(fromAtom); + final String toAtomId = Utility.itemIdByAlloyAtom(toAtom); + + final String fromAtomName = Utility.getAtomNameById(fromAtomId); + final String toAtomName = Utility.getAtomNameById(toAtomId); + + final List tupleList = new ArrayList<>(); + tupleList.add(fromAtomName); + tupleList.add(toAtomName); + + final DocumentRoot documentRoot = Utility.getDocumentRoot(); + + final EList fieldList = documentRoot.getAlloy().getInstance().getField(); + + for (final FieldType fieldType : fieldList) { + if (fieldType.getLabel().equals(relation)) { + final EList tupleTypeList = fieldType.getTuple(); + for (final TupleType tupleType : tupleTypeList) { + if (fromAtomId.equals(tupleType.getAtom().get(0).getLabel()) + && toAtomId.equals(tupleType.getAtom().get(1).getLabel())) { + return tupleType.getBound(); + } + } + } + } + return null; + } + + protected static String getDataOfAtom(final String type, final int index) { + final String atomId = Utility.itemIdByIndex(type, index); + + final ItemType itemType = Utility.getItemById(atomId); + + for (final EntryType entryType : itemType.getEntry()) { + if (entryType.getKey().equals("Data")) { + return entryType.getValue(); + } + } + + return null; + } + + protected static DocumentRoot getDocumentRoot() { + @SuppressWarnings("rawtypes") + final ModelIO modelIO = new ModelIO<>(); + @SuppressWarnings("rawtypes") + List list; + try { + list = modelIO.read(URI.createFileURI(XmlCreator.xmlfile)); + if (list.isEmpty()) { + return null; + } + final DocumentRoot documentRoot = (DocumentRoot) list.get(0); + return documentRoot; + } catch (final IOException e) { + e.printStackTrace(); + } + return null; + } + + protected static ItemType getItemById(final String id) { + final EList itemTypes = + Utility.getDocumentRoot().getAlloy().getRepository().getItem(); + + for (final ItemType itemType : itemTypes) { + if (id.equals(itemType.getId())) { + return itemType; + } + } + + return null; + } + + /** + * For example atom is in EmptyList, also it is in List.
+ * So that if we know only relationName which is "List",
+ * we can find EmptyList with this method. + * + * @param atomLabel + * @param relationName + * @return + */ + public static String getRealTypeOfAtom(final String atomLabel, final String relationName) { + final EList sigTypeList = Utility.getDocumentRoot().getAlloy().getInstance().getSig(); + final Map sigIdNameMap = new HashMap<>(); + + for (final SigType sigType : sigTypeList) { + sigIdNameMap.put(sigType.getID(), sigType.getLabel()); + } + + for (final SigType sigType : sigTypeList) { + if (!sigType.getType().isEmpty()) { + final String typeName = sigIdNameMap.get(sigType.getType().get(0).getID()); + if (typeName.equals(relationName)) { + final EList atomTypes = sigType.getAtom(); + for (final AtomType atomType : atomTypes) { + if (atomType.getLabel().equals(atomLabel)) { + return sigType.getLabel(); + } + } + } + } + } + return null; + } + + private static ArrayList getRelationTypesForFirstSide(final String typeName) { + final ArrayList relationTypeNames = new ArrayList<>(); + + int TypeId = -1; + + final EList sigTypes = Utility.getDocumentRoot().getAlloy().getInstance().getSig(); + for (final SigType sigType : sigTypes) { + if (sigType.getLabel().equals(typeName)) { + TypeId = sigType.getID(); + break; + } + } + + final ArrayList parentIds = Utility.getAllParentIds(TypeId); + + final EList fieldTypes = + Utility.getDocumentRoot().getAlloy().getInstance().getField(); + + for (final FieldType fieldType : fieldTypes) { + for (final Integer parentId : parentIds) { + if (fieldType.getParentID() == parentId) { + relationTypeNames.add(fieldType.getLabel()); + break; + } + } + } + + return relationTypeNames; + } + + private static SigType getSigTypeById(final int id) { + final EList sigTypes = Utility.getDocumentRoot().getAlloy().getInstance().getSig(); + + for (final SigType sigType : sigTypes) { + if (id == sigType.getID()) { + return sigType; + } + } + return null; + } + + public static int getSigTypeIdByName(final String typeName) { + int id = -1; + + final EList sigTypes = Utility.getDocumentRoot().getAlloy().getInstance().getSig(); + + for (final SigType sigType : sigTypes) { + if (typeName.equals(sigType.getLabel().substring(sigType.getLabel().indexOf("/") + 1))) { + id = sigType.getID(); + } + } + + return id; + } + + public static ArrayList getSigTypeListByParentId(final int id) { + final ArrayList suitableSigTypes = new ArrayList<>(); + + final EList sigTypes = Utility.getDocumentRoot().getAlloy().getInstance().getSig(); + + for (final SigType sigType : sigTypes) { + if (sigType.getParentID() == id) { + suitableSigTypes.add(sigType); + } + } + + return suitableSigTypes; + } + + private static String getSigTypeName(final String id) { + final ItemType itemType = Utility.getItemById(id); + + final EList entries = itemType.getEntry(); + + for (final EntryType entryType : entries) { + if (entryType.getKey().equals("Name")) { + return entryType.getValue(); + } + } + return null; + } + + public static ArrayList getSuitableRelations(final String typeName) { + final ArrayList suitableRelationNames = Utility.getRelationTypesForFirstSide(typeName); + + final EList fieldList = + Utility.getDocumentRoot().getAlloy().getInstance().getField(); + final ArrayList relations = new ArrayList<>(); + + for (final String relationName : suitableRelationNames) { + for (final FieldType fieldType : fieldList) { + if (relationName.equals(fieldType.getLabel())) { + final EList types = fieldType.getTypes(); + for (final TypesType typesType : types) { + final String first = + Utility.getSigTypeById(typesType.getType().get(0).getID()).getLabel(); + final String second = + Utility.getSigTypeById(typesType.getType().get(1).getID()).getLabel(); + relations.add(relationName + " : " + first + " -> " + second); + } + break; + } + } + } + + return relations; + } + + public static ArrayList> getSuitableSecondSideTypesOfRelation( + final String relationName, final String firstSideType, final String firstSideId) { + final EList fields = Utility.getDocumentRoot().getAlloy().getInstance().getField(); + + final int firstSideTypeId = Utility.getSigTypeIdByName(firstSideType); + + int id = -1; + FieldType foundFieldType = null; + for (final FieldType fieldType : fields) { + if (fieldType.getLabel().equals(relationName) + && fieldType.getTypes().get(0).getType().get(0).getID() == firstSideTypeId) { + id = fieldType.getTypes().get(0).getType().get(1).getID(); + foundFieldType = fieldType; + break; + } + } + + final ArrayList suitableIds = Utility.getAllChildIds(id); + + final EList sigList = Utility.getDocumentRoot().getAlloy().getInstance().getSig(); + final ArrayList> suitableAtoms = new ArrayList<>(); + + for (final SigType sigType : sigList) { + if (suitableIds.contains(sigType.getID())) { + final EList atomList = sigType.getAtom(); + final String sigName = sigType.getLabel(); + int index = 0; + for (final AtomType atomType : atomList) { + final EList tuples = foundFieldType.getTuple(); + String isCheck = "false"; + for (final TupleType tupleType : tuples) { + if (tupleType.getAtom().get(0).getLabel().equals(firstSideId) + && tupleType.getAtom().get(1).getLabel().equals(atomType.getLabel())) { + isCheck = "true"; + } + + } + + final ArrayList suitable = new ArrayList<>(); + suitable.add(sigName); + suitable.add(sigName + Integer.toString(index)); + suitable.add(Utility.getSigTypeName(atomType.getLabel())); + suitable.add(isCheck); + suitableAtoms.add(suitable); + index++; + } + } + } + + + return suitableAtoms; + } + + public static TupleType getTupleTypeByAtoms(final AlloyAtom fromAlloyAtom, + final AlloyAtom toAlloyAtom, final String relation) { + final String fromAtomId = Utility.itemIdByAlloyAtom(fromAlloyAtom); + final String toAtomId = Utility.itemIdByAlloyAtom(toAlloyAtom); + + final String fromAtomName = Utility.getAtomNameById(fromAtomId); + final String toAtomName = Utility.getAtomNameById(toAtomId); + + final List tupleList = new ArrayList<>(); + tupleList.add(fromAtomName); + tupleList.add(toAtomName); + + final DocumentRoot documentRoot = Utility.getDocumentRoot(); + + final EList fieldList = documentRoot.getAlloy().getInstance().getField(); + + for (final FieldType fieldType : fieldList) { + if (fieldType.getLabel().equals(relation)) { + final EList tupleTypeList = fieldType.getTuple(); + for (final TupleType tupleType : tupleTypeList) { + if (fromAtomId.equals(tupleType.getAtom().get(0).getLabel()) + && toAtomId.equals(tupleType.getAtom().get(1).getLabel())) { + return tupleType; + } + } + } + } + return null; + } + + /** + * + * @param relationName is relation name + * @return if type is in the other type, return other type, else return null + */ + public static String getType(final String relationName) { + final EList sigTypeList = Utility.getDocumentRoot().getAlloy().getInstance().getSig(); + final Map sigIdNameMap = new HashMap<>(); + + for (final SigType sigType : sigTypeList) { + sigIdNameMap.put(sigType.getID(), sigType.getLabel()); + } + + for (final SigType sigType : sigTypeList) { + if (sigType.getLabel().equals(relationName)) { + if (!sigType.getType().isEmpty()) { + return sigIdNameMap.get(sigType.getType().get(0).getID()); + } + } + } + return null; + } + + public static List getTypeHierarchy() { + final EList sigTypeList = Utility.getDocumentRoot().getAlloy().getInstance().getSig(); + final Map sigIdNameMap = new HashMap<>(); + final Map sigIdParentIdMap = new HashMap<>(); + final List topTypeElements = new ArrayList<>(); + + for (final SigType sigType : sigTypeList) { + if (sigType.getID() > 3) { + String type = sigType.getLabel(); + if (sigType.getAbstract() != null && sigType.getAbstract().equals("yes")) { + type += " {abs}"; + } + if (sigType.getParentID() == 2) { + sigIdNameMap.put(sigType.getID(), new TypeElement(type, true)); + } else { + sigIdNameMap.put(sigType.getID(), new TypeElement(type)); + } + + sigIdParentIdMap.put(sigType.getID(), sigType.getParentID()); + } + } + + final Iterator> iter = sigIdParentIdMap.entrySet().iterator(); + + while (iter.hasNext()) { + final Entry entry = iter.next(); + + final TypeElement currentTypeElement = sigIdNameMap.get(entry.getKey()); + final TypeElement parentTypeElement = sigIdNameMap.get(entry.getValue()); + + if (parentTypeElement != null) { + parentTypeElement.getChildren().add(currentTypeElement); + } + + if (currentTypeElement.isTop()) { + topTypeElements.add(currentTypeElement); + } + } + + return topTypeElements; + } + + + public static List getTypeHierarchyForTree() { + final EList sigTypeList = Utility.getDocumentRoot().getAlloy().getInstance().getSig(); + final Map sigIdNameMap = new HashMap<>(); + final Map sigIdParentIdMap = new HashMap<>(); + final List topTypeElements = new ArrayList<>(); + final List topElements = new ArrayList<>(); + + for (final SigType sigType : sigTypeList) { + if (sigType.getID() > 3) { + String type = sigType.getLabel(); + if (sigType.getAbstract() != null && sigType.getAbstract().equals("yes")) { + type += " {abs}"; + } + if (sigType.getParentID() == 2) { + final DefaultMutableTreeNode node = new DefaultMutableTreeNode(type); + sigIdNameMap.put(sigType.getID(), node); + topElements.add(node); + } else { + sigIdNameMap.put(sigType.getID(), new DefaultMutableTreeNode(type)); + } + if (sigType.getParentID() == 0) { + final Integer parentID = sigIdParentIdMap.get(sigType.getType().get(0).getID()); + if (parentID == 2) { + final MutableTreeNode node = sigIdNameMap.get(sigType.getID()); + topElements.add(node); + } + sigIdParentIdMap.put(sigType.getID(), parentID); + } else { + sigIdParentIdMap.put(sigType.getID(), sigType.getParentID()); + } + } + } + + final Iterator> iter = sigIdParentIdMap.entrySet().iterator(); + + while (iter.hasNext()) { + final Entry entry = iter.next(); + + final MutableTreeNode currentTypeElement = sigIdNameMap.get(entry.getKey()); + final MutableTreeNode parentTypeElement = sigIdNameMap.get(entry.getValue()); + + if (parentTypeElement != null) { + parentTypeElement.insert(currentTypeElement, parentTypeElement.getChildCount()); + } + + if (currentTypeElement.toString().contains("{abs}") + || topElements.contains(currentTypeElement)) { + topTypeElements.add(currentTypeElement); + } + } + + return topTypeElements; + } + + public static String itemIdByAlloyAtom(final AlloyAtom atom) { + final String stringIndex = atom.toString().substring(atom.getType().getName().length()); + int index = 0; + if (!stringIndex.isEmpty()) { + index = Integer.parseInt(stringIndex); + } + + return Utility.itemIdByIndex(atom.getType().getName(), index); + } + + public static String itemIdByIndex(final String type, final int index) { + final DocumentRoot documentRoot = Utility.getDocumentRoot(); + final EList sigs = documentRoot.getAlloy().getInstance().getSig(); + + for (final SigType sigType : sigs) { + if (sigType.getLabel().equals(type)) { + return sigType.getAtom().get(index).getLabel(); + } + } + + return null; + } + + public static void removeAllRelationsOfAtom(final String id) { + Utility.removeRelationFromFieldType(id); + Utility.removeAtomTypeFromSigType(id); + Utility.removeItemIdFromRepository(id); + } + + public static void removeAtomTypeFromSigType(final String id) { + final DocumentRoot documentRoot = Utility.getDocumentRoot(); + + final EList sigs = documentRoot.getAlloy().getInstance().getSig(); + + for (final SigType sigType : sigs) { + final Iterator atomsIter = sigType.getAtom().iterator(); + while (atomsIter.hasNext()) { + final AtomType atomType = atomsIter.next(); + if (atomType.getLabel().equals(id)) { + atomsIter.remove(); + break; + } + } + } + + Utility.writeDocumentRoot(documentRoot); + } + + public static void removeItemIdFromRepository(final String id) { + final DocumentRoot documentRoot = Utility.getDocumentRoot(); + final Iterator itemsIter = + documentRoot.getAlloy().getRepository().getItem().iterator(); + + while (itemsIter.hasNext()) { + final ItemType itemType = itemsIter.next(); + if (itemType.getId().equals(id)) { + itemsIter.remove(); + break; + } + } + + Utility.writeDocumentRoot(documentRoot); + } + + public static void removeRelation(final String fromId, final String toId, final String relation) { + if (fromId == null || toId == null || relation == null) { + return; + } + + final DocumentRoot documentRoot = Utility.getDocumentRoot(); + final EList fields = documentRoot.getAlloy().getInstance().getField(); + + for (final FieldType fieldType : fields) { + if (fieldType.getLabel().equals(relation)) { + final Iterator iterTuples = fieldType.getTuple().iterator(); + while (iterTuples.hasNext()) { + final TupleType tupleType = iterTuples.next(); + if (fromId.equals(tupleType.getAtom().get(0).getLabel()) + && toId.equals(tupleType.getAtom().get(1).getLabel())) { + iterTuples.remove(); + break; + } + } + } + } + + Utility.writeDocumentRoot(documentRoot); + } + + public static void removeRelationFromFieldType(final String id) { + final DocumentRoot documentRoot = Utility.getDocumentRoot(); + final EList fields = documentRoot.getAlloy().getInstance().getField(); + final List notifierList = Visualization.getInstance().getNotifierList(); + + for (final FieldType fieldType : fields) { + final Iterator tuplesIter = fieldType.getTuple().iterator(); + while (tuplesIter.hasNext()) { + final TupleType tupleType = tuplesIter.next(); + if (tupleType.getAtom().get(0).getLabel().equals(id) + || tupleType.getAtom().get(1).getLabel().equals(id)) { + tuplesIter.remove(); + + final String fromAtomName = Utility.getAtomNameById(tupleType.getAtom().get(0).getLabel()); + final String toAtomName = Utility.getAtomNameById(tupleType.getAtom().get(1).getLabel()); + + final List tupleList = new ArrayList<>(); + + tupleList.add(fromAtomName); + tupleList.add(toAtomName); + + for (final Notifier notifier : notifierList) { + notifier.removeTupleNotify(fieldType.getLabel(), tupleList, + Visualization.getInstance().isLower() ? "lower" : "upper"); + } + } + } + } + Utility.writeDocumentRoot(documentRoot); + } + + public static void setBoundOfAtomType(final AlloyAtom alloyAtom, final boolean isLower) { + final String id = Utility.itemIdByAlloyAtom(alloyAtom); + final String type = alloyAtom.getType().getName(); + + final DocumentRoot documentRoot = Utility.getDocumentRoot(); + final EList sigList = documentRoot.getAlloy().getInstance().getSig(); + + for (final SigType sigType : sigList) { + if (sigType.getLabel().equals(type)) { + boolean flag = false; + final EList atomList = sigType.getAtom(); + for (final AtomType atomType : atomList) { + if (atomType.getLabel().equals(id)) { + final String realTypeOfAtom = Utility.getRealTypeOfAtom(atomType.getLabel(), type); + flag = true; + final List notifierList = Visualization.getInstance().getNotifierList(); + final List tupleList = new ArrayList<>(); + tupleList.add(Utility.getAtomNameById(id)); + if (isLower) { + atomType.setBound("lower"); + for (final Notifier notifier : notifierList) { + if (realTypeOfAtom != null) { + notifier.moveToLower(realTypeOfAtom, type, tupleList); + } else { + notifier.moveToLower(type, tupleList); + } + } + } else { + atomType.setBound("upper"); + for (final Notifier notifier : notifierList) { + if (realTypeOfAtom != null) { + notifier.moveToUpper(realTypeOfAtom, type, tupleList); + } else { + notifier.moveToUpper(type, tupleList); + } + } + } + break; + } + } + if (flag) { + break; + } + } + } + + Utility.writeDocumentRoot(documentRoot); + } + + public static void setBoundOfTupleType(final AlloyTuple alloyTuple, final String relation, + final boolean isLower) { + final AlloyAtom fromAtom = alloyTuple.getStart(); + final AlloyAtom toAtom = alloyTuple.getEnd(); + + final String fromAtomId = Utility.itemIdByAlloyAtom(fromAtom); + final String toAtomId = Utility.itemIdByAlloyAtom(toAtom); + + final String fromAtomName = Utility.getAtomNameById(fromAtomId); + final String toAtomName = Utility.getAtomNameById(toAtomId); + + final List tupleList = new ArrayList<>(); + tupleList.add(fromAtomName); + tupleList.add(toAtomName); + + final List notifierList = Visualization.getInstance().getNotifierList(); + + final DocumentRoot documentRoot = Utility.getDocumentRoot(); + + final EList fieldList = documentRoot.getAlloy().getInstance().getField(); + + for (final FieldType fieldType : fieldList) { + if (fieldType.getLabel().equals(relation)) { + boolean flag = false; + final EList tupleTypeList = fieldType.getTuple(); + for (final TupleType tupleType : tupleTypeList) { + if (fromAtomId.equals(tupleType.getAtom().get(0).getLabel()) + && toAtomId.equals(tupleType.getAtom().get(1).getLabel())) { + flag = true; + if (isLower) { + tupleType.setBound("lower"); + for (final Notifier notifier : notifierList) { + notifier.moveToLower(relation, tupleList); + } + } else { + tupleType.setBound("upper"); + for (final Notifier notifier : notifierList) { + notifier.moveToUpper(relation, tupleList); + } + } + break; + } + } + if (flag) { + break; + } + } + } + + Utility.writeDocumentRoot(documentRoot); + } + + @SuppressWarnings("unchecked") + protected static void writeDocumentRoot(final DocumentRoot documentRoot) { + @SuppressWarnings("rawtypes") + final ModelIO modelIO = new ModelIO<>(); + modelIO.write(URI.createFileURI(XmlCreator.xmlfile), documentRoot); + } +} diff --git a/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/Visualization.java b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/Visualization.java new file mode 100644 index 00000000..40ed1bea --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/Visualization.java @@ -0,0 +1,655 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.visualization; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Cursor; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter; +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.AbstractButton; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JToggleButton; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.WindowConstants; + +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4graph.Graph; +import edu.mit.csail.sdg.alloy4graph.GraphEdge; +import edu.mit.csail.sdg.alloy4graph.GraphNode; +import edu.mit.csail.sdg.alloy4graph.GraphViewer; +import edu.mit.csail.sdg.alloy4viz.AlloyAtom; +import edu.mit.csail.sdg.alloy4viz.AlloyInstance; +import edu.mit.csail.sdg.alloy4viz.AlloyRelation; +import edu.mit.csail.sdg.alloy4viz.AlloyTuple; +import edu.mit.csail.sdg.alloy4viz.StaticInstanceReader; +import edu.mit.csail.sdg.alloy4viz.VizGraphPanel; +import edu.mit.csail.sdg.alloy4viz.VizState; +import eu.modelwriter.kodkod.visualization.model.Universe; +import eu.modelwriter.kodkod.visualization.wizards.createatom.CreateAtom; +import eu.modelwriter.kodkod.visualization.wizards.mapping.MappingWizard; + +public class Visualization { + + private static Visualization visualization; + + public static Visualization getInstance() { + if (Visualization.visualization == null) { + Visualization.visualization = new Visualization(null, XmlCreator.xmlfile); + } + + return Visualization.visualization; + } + + public static Visualization getInstance(final String xmlFile) { + if (Visualization.visualization == null) { + Visualization.visualization = new Visualization(null, xmlFile); + } else if (xmlFile != null) { + Visualization.visualization.setUniverse(null, xmlFile); + } + + return Visualization.visualization; + } + + public static Visualization getInstance(final Universe universe, final String xmlFile) { + if (Visualization.visualization == null) { + Visualization.visualization = new Visualization(universe, xmlFile); + } else if (universe != null) { + Visualization.visualization.setUniverse(universe, xmlFile); + } + + return Visualization.visualization; + } + + private String xmlfile; + private Universe universe; + private XmlCreator xmlCreator; + private List notifierList; + private VizGraphPanel graph; + private JFrame frame; + private JMenu universeMenu; + private Object rightClickedAnnotation; + private String relation; + private final JPanel graphInPanel; + private final JMenuBar menuBar; + + private final JToggleButton lowerButton; + + private final JToggleButton upperButton; + + private boolean isLower; + + private Visualization(final Universe universe, final String xmlFile) { + notifierList = new ArrayList<>(); + graphInPanel = new JPanel(); + graphInPanel.setLayout(new BorderLayout()); + + menuBar = new JMenuBar(); + lowerButton = new JToggleButton("Lower Edit Mode"); + lowerButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent e) { + final AbstractButton abstractButton = (AbstractButton) e.getSource(); + final boolean selected = abstractButton.getModel().isSelected(); + upperButton.setSelected(!selected); + isLower = selected; + } + }); + upperButton = new JToggleButton("Upper Edit Mode"); + upperButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent e) { + final AbstractButton abstractButton = (AbstractButton) e.getSource(); + final boolean selected = abstractButton.getModel().isSelected(); + lowerButton.setSelected(!selected); + isLower = !selected; + } + }); + menuBar.add(lowerButton); + menuBar.add(upperButton); + graphInPanel.add(menuBar, BorderLayout.SOUTH); + + upperButton.setSelected(true); + isLower = false; + + setUniverse(universe, xmlFile); + } + + private void addMouseListener() { + graph.alloyGetViewer().addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(final MouseEvent e) { + super.mouseClicked(e); + final Object annotation = + graph.alloyGetViewer().alloyGetAnnotationAtXY(e.getX(), e.getY()); + if (annotation instanceof AlloyAtom) { + final AlloyAtom alloyAtom = (AlloyAtom) annotation; + + final String atomType = alloyAtom.getType().getName(); + final String stringIndex = alloyAtom.toString().substring(atomType.length()); + int index = 0; + if (!stringIndex.isEmpty()) { + index = Integer.parseInt(stringIndex); + } + final String serilizatedData = Utility.getDataOfAtom(atomType, index); + if (serilizatedData == null) { + return; + } + Serializable deSerilizatedData = null; + try { + deSerilizatedData = Serialization.getInstance().fromString(serilizatedData); + } catch (ClassNotFoundException | IOException e1) { + e1.printStackTrace(); + } + for (final Notifier notifier : notifierList) { + notifier.notify(deSerilizatedData); + } + } + } + + @Override + public void mousePressed(final MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON3) { + rightClickedAnnotation = + graph.alloyGetViewer().alloyGetAnnotationAtXY(e.getX(), e.getY()); + + Field field; + try { + field = GraphViewer.class.getDeclaredField("selected"); + field.setAccessible(true); + if (field.get(graph.alloyGetViewer()) instanceof GraphEdge) { + final GraphEdge edge = + (GraphEdge) field.get(graph.alloyGetViewer()); + relation = + edge.group.toString().substring(0, edge.group.toString().indexOf(":") - 1); + } + } catch (NoSuchFieldException | SecurityException | IllegalArgumentException + | IllegalAccessException e1) { + e1.printStackTrace(); + } + + if (rightClickedAnnotation == null) { + universeMenu.setVisible(true); + universeMenu.getItem(0).setVisible(true); + universeMenu.getItem(1).setVisible(false); + universeMenu.getItem(2).setVisible(false); + universeMenu.getItem(3).setVisible(false); + universeMenu.getItem(4).setVisible(false); + universeMenu.getItem(5).setVisible(false); + universeMenu.getItem(6).setVisible(false); + } else { + universeMenu.setVisible(true); + if (rightClickedAnnotation instanceof AlloyAtom) { + universeMenu.getItem(0).setVisible(false); + universeMenu.getItem(1).setVisible(true); + universeMenu.getItem(3).setVisible(false); + universeMenu.getItem(4).setVisible(true); + + final AlloyAtom alloyAtom = (AlloyAtom) rightClickedAnnotation; + final String bound = Utility.getBoundOfAtomType(alloyAtom); + + if (bound != null) { + if (bound.equals("lower")) { + universeMenu.getItem(5).setVisible(false); + universeMenu.getItem(6).setVisible(true); + if (!isLower) { + universeMenu.getItem(2).setVisible(false); + } else { + universeMenu.getItem(2).setVisible(true); + } + } else if (bound.equals("upper")) { + universeMenu.getItem(5).setVisible(true); + universeMenu.getItem(6).setVisible(false); + } + } + } else if (rightClickedAnnotation instanceof AlloyTuple) { + universeMenu.getItem(0).setVisible(false); + universeMenu.getItem(1).setVisible(false); + universeMenu.getItem(2).setVisible(false); + universeMenu.getItem(4).setVisible(false); + + final AlloyTuple alloyTuple = (AlloyTuple) rightClickedAnnotation; + final String bound = + Utility.getBoundOfTupleType(alloyTuple, relation); + + if (bound != null) { + if (bound.equals("lower")) { + universeMenu.getItem(5).setVisible(false); + universeMenu.getItem(6).setVisible(true); + if (!isLower) { + universeMenu.getItem(3).setVisible(false); + } else { + universeMenu.getItem(3).setVisible(true); + } + } else if (bound.equals("upper")) { + universeMenu.getItem(5).setVisible(true); + universeMenu.getItem(6).setVisible(false); + } + } + } + } + } + } + }); + + Field field; + try { + field = VizGraphPanel.class.getDeclaredField("graphPanel"); + field.setAccessible(true); + if (field.get(graph) instanceof JPanel) { + final JPanel graphPanel = (JPanel) field.get(graph); + + graphPanel.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(final MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON3) { + + rightClickedAnnotation = null; + + universeMenu.setVisible(true); + universeMenu.getItem(0).setVisible(true); + universeMenu.getItem(1).setVisible(false); + universeMenu.getItem(2).setVisible(false); + universeMenu.getItem(3).setVisible(false); + universeMenu.getItem(4).setVisible(false); + + } + } + }); + + } + } catch (NoSuchFieldException | SecurityException | IllegalArgumentException + | IllegalAccessException e1) { + e1.printStackTrace(); + } + } + + private void addMouseMotionAdaper() { + final MouseMotionAdapter adapter = new MouseMotionAdapter() { + + @Override + public void mouseMoved(final MouseEvent e) { + final Object annotation = + graph.alloyGetViewer().alloyGetAnnotationAtXY(e.getX(), e.getY()); + final JComponent cmpnt = (JComponent) e.getComponent(); + String tooltip = null; + + if (annotation instanceof AlloyAtom) { + graphInPanel.setCursor(new Cursor(Cursor.HAND_CURSOR)); + + final String id = Utility.itemIdByAlloyAtom((AlloyAtom) annotation); + final String atomName = Utility.getAtomNameById(id); + + tooltip = atomName; + } else if (annotation instanceof AlloyTuple) { + final AlloyTuple tuple = (AlloyTuple) annotation; + + final AlloyAtom highLightedAtomStart = tuple.getStart(); + final AlloyAtom highLightedAtomEnd = tuple.getEnd(); + + final String fromId = Utility.itemIdByAlloyAtom(highLightedAtomStart); + final String toId = Utility.itemIdByAlloyAtom(highLightedAtomEnd); + if (fromId == null || toId == null) { + return; + } + final String fromAtomName = Utility.getAtomNameById(fromId); + final String toAtomName = Utility.getAtomNameById(toId); + + tooltip = fromAtomName + " --> " + toAtomName; + + graphInPanel.setCursor(new Cursor(Cursor.HAND_CURSOR)); + } else { + graphInPanel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + + cmpnt.setToolTipText(tooltip); + + } + }; + graph.alloyGetViewer().addMouseMotionListener(adapter); + graphInPanel.addMouseMotionListener(adapter); + + } + + public void addNewAtom(final String type, final String name) { + Utility.addAtomToSigType(type, name); + } + + public void addNewAtom(final String type, final String name, final Serializable data) { + String sData = null; + try { + sData = Serialization.getInstance().toString(data); + } catch (final IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + Utility.addAtomToSigTypeWithData(type, name, sData); + } + + public JPanel getGraph() { + try { + /* + * TODO BUG + * + * A Fatal Error occurs while setting GTK look and feel on Ubuntu 16.04 + * (com.sun.java.swing.plaf.gtk.GTKLookAndFeel). + * + */ + final String LaF = UIManager.getSystemLookAndFeelClassName(); + if ("com.sun.java.swing.plaf.gtk.GTKLookAndFeel".equals(LaF)) { + UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); + } else { + UIManager.setLookAndFeel(LaF); + } + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException + | UnsupportedLookAndFeelException e1) { + + e1.printStackTrace(); + } + final File f = new File(xmlfile); + try { + if (!f.exists()) { + throw new IOException("File " + xmlfile + " does not exist."); + } + + final AlloyInstance instance = StaticInstanceReader.parseInstance(f); + final VizState myState = new VizState(instance); + + if (graphInPanel.getComponentCount() > 1) { + graphInPanel.remove(graph); + } + + graph = new VizGraphPanel(myState, false); + + setColorOfNodes(); + + graph.alloyGetViewer().alloyRepaint(); + + universeMenu = new JMenu("Universe"); + final JMenuItem createAtomMenuItem = new JMenuItem("Create Atom"); + final JMenuItem createMappingMenuItem = new JMenuItem("Create Mapping"); + final JMenuItem removeAtomMenuItem = new JMenuItem("Remove Atom"); + final JMenuItem removeRelationMenuItem = new JMenuItem("Remove Relation"); + final JMenuItem changeAtomTypeMenuItem = new JMenuItem("Change Atom Type"); + final JMenuItem moveToLowerMenuItem = new JMenuItem("Move To Lower"); + final JMenuItem moveToUpperMenuItem = new JMenuItem("Move To Upper"); + final JMenuItem refreshMenuItem = new JMenuItem("Refresh"); + + graph.alloyGetViewer().pop.add(universeMenu, 0); + + universeMenu.add(createAtomMenuItem, 0); + universeMenu.add(createMappingMenuItem, 1); + universeMenu.add(removeAtomMenuItem, 2); + universeMenu.add(removeRelationMenuItem, 3); + universeMenu.add(changeAtomTypeMenuItem, 4); + universeMenu.add(moveToLowerMenuItem, 5); + universeMenu.add(moveToUpperMenuItem, 6); + universeMenu.add(refreshMenuItem, 7); + + createAtomMenuItem.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent e) { + final CreateAtom wiz = new CreateAtom(null); + wiz.setVisible(true); + } + }); + + createMappingMenuItem.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent e) { + final String stringIndex = ((AlloyAtom) rightClickedAnnotation) + .toString().substring(((AlloyAtom) rightClickedAnnotation) + .getType().getName().length()); + int index = 0; + if (!stringIndex.isEmpty()) { + index = Integer.parseInt(stringIndex); + } + + final MappingWizard relationPage = new MappingWizard( + ((AlloyAtom) rightClickedAnnotation).getType().getName(), index); + relationPage.setVisible(true); + } + }); + + removeAtomMenuItem.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent e) { + final AlloyAtom alloyAtom = (AlloyAtom) rightClickedAnnotation; + final String atomLabel = Utility.itemIdByAlloyAtom(alloyAtom); + final String atomName = Utility.getAtomNameById(atomLabel); + final String relationName = + ((AlloyAtom) rightClickedAnnotation).getType().getName(); + final String realTypeOfAtom = Utility.getRealTypeOfAtom(atomLabel, relationName); + final List tuple = new ArrayList<>(); + tuple.add(atomName); + for (final Notifier notifier : notifierList) { + if (realTypeOfAtom != null) { + notifier.removeTupleNotify(realTypeOfAtom, relationName, tuple, + Visualization.getInstance().isLower() ? "lower" : "upper"); + } else { + notifier.removeTupleNotify(relationName, tuple, + Visualization.getInstance().isLower() ? "lower" : "upper"); + } + } + Utility.removeAllRelationsOfAtom(atomLabel); + Visualization.this.revalidate(); + } + }); + + removeRelationMenuItem.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent e) { + final AlloyTuple tuple = (AlloyTuple) rightClickedAnnotation; + final AlloyAtom fromAtom = tuple.getStart(); + final AlloyAtom toAtom = tuple.getEnd(); + + final String fromAtomId = Utility.itemIdByAlloyAtom(fromAtom); + final String toAtomId = Utility.itemIdByAlloyAtom(toAtom); + + final String fromAtomName = Utility.getAtomNameById(fromAtomId); + final String toAtomName = Utility.getAtomNameById(toAtomId); + + final List tupleList = new ArrayList<>(); + tupleList.add(fromAtomName); + tupleList.add(toAtomName); + + for (final Notifier notifier : notifierList) { + notifier.removeTupleNotify(relation, tupleList, + Visualization.getInstance().isLower() ? "lower" : "upper"); + } + + Utility.removeRelation(fromAtomId, toAtomId, relation); + Visualization.this.revalidate(); + } + }); + + changeAtomTypeMenuItem.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent e) { + final CreateAtom wiz = + new CreateAtom((AlloyAtom) rightClickedAnnotation); + wiz.setVisible(true); + } + }); + + moveToLowerMenuItem.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent e) { + if (rightClickedAnnotation instanceof AlloyAtom) { + Utility.setBoundOfAtomType((AlloyAtom) rightClickedAnnotation, true); + } else if (rightClickedAnnotation instanceof AlloyTuple) { + Utility.setBoundOfTupleType((AlloyTuple) rightClickedAnnotation, + relation, true); + } + Visualization.this.revalidate(); + } + }); + + moveToUpperMenuItem.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent e) { + if (rightClickedAnnotation instanceof AlloyAtom) { + Utility.setBoundOfAtomType((AlloyAtom) rightClickedAnnotation, + false); + } else if (rightClickedAnnotation instanceof AlloyTuple) { + Utility.setBoundOfTupleType((AlloyTuple) rightClickedAnnotation, + relation, false); + } + Visualization.this.revalidate(); + } + }); + + refreshMenuItem.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent e) { + Visualization.this.revalidate(); + } + }); + + + addMouseListener(); + addMouseMotionAdaper(); + + + graphInPanel.add(graph, BorderLayout.CENTER); + graphInPanel.revalidate(); + + return graphInPanel; + } catch (IOException | Err e) { + e.printStackTrace(); + } + return null; + } + + public Universe getLastUniverse() { + final XmlToUniverse xmlToUniverse = new XmlToUniverse(); + return xmlToUniverse.getUniverse(); + } + + public List getNotifierList() { + return notifierList; + } + + public Universe getUniverse() { + return universe; + } + + public boolean isLower() { + return isLower; + } + + public void revalidate() { + // frame.remove(graph); + getGraph(); + // frame.add(graph); + // frame.revalidate(); + } + + private void setColorOfNodes() { + Field field; + try { + field = GraphViewer.class.getDeclaredField("graph"); + field.setAccessible(true); + if (field.get(graph.alloyGetViewer()) instanceof Graph) { + final Graph refGraph = (Graph) field.get(graph.alloyGetViewer()); + + for (final GraphNode graphNode : refGraph.nodes) { + if (graphNode.uuid instanceof AlloyAtom) { + final AlloyAtom alloyAtom = (AlloyAtom) graphNode.uuid; + final String bound = Utility.getBoundOfAtomType(alloyAtom); + if (bound != null) { + if (bound.equals("lower")) { + graphNode.set(new Color(255, 255, 180)); + } + } + } + } + + for (final GraphEdge graphEdge : refGraph.edges) { + if (graphEdge.uuid instanceof AlloyTuple) { + final AlloyTuple alloyTuple = (AlloyTuple) graphEdge.uuid; + final AlloyRelation relation = (AlloyRelation) graphEdge.group; + final String relationName = relation.getName(); + final String bound = Utility.getBoundOfTupleType(alloyTuple, relationName); + if (bound != null) { + if (bound.equals("lower")) { + final int red = graphEdge.color().getRed() + 70; + final int green = graphEdge.color().getGreen() + 70; + final int blue = graphEdge.color().getBlue() + 70; + graphEdge.set(new Color(red > 255 ? 255 : red, green > 255 ? 255 : green, + blue > 255 ? 255 : blue)); + } + } + } + } + } + } catch (NoSuchFieldException | SecurityException | IllegalArgumentException + | IllegalAccessException e1) { + e1.printStackTrace(); + } + } + + public void setNotifierList(final List notifierList) { + this.notifierList = notifierList; + } + + public void setUniverse(final Universe universe, final String xmlFile) { + this.universe = universe; + xmlfile = "temp" + System.getProperty("file.separator") + xmlFile + ".xml"; + xmlCreator = new XmlCreator(universe, xmlfile); + } + + public void showMetamodel() { + xmlCreator.setMetamodel(true); + frame = new JFrame("Visualization"); + frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + frame.add(getGraph(), BorderLayout.CENTER); + frame.setVisible(true); + frame.setSize(500, 500); + } + + + public void showModel() { + xmlCreator.setMetamodel(false); + frame = new JFrame("Visualization"); + frame.setLayout(new BorderLayout()); + frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + frame.add(getGraph(), BorderLayout.CENTER); + frame.setVisible(true); + frame.setSize(500, 500); + } +} diff --git a/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/XmlCreator.java b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/XmlCreator.java new file mode 100644 index 00000000..3d3b57b9 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/XmlCreator.java @@ -0,0 +1,307 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.visualization; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.emf.ecore.EObject; + +import eu.modelwriter.kodkod.visualization.model.Atom; +import eu.modelwriter.kodkod.visualization.model.Relation; +import eu.modelwriter.kodkod.visualization.model.Tuple; +import eu.modelwriter.kodkod.visualization.model.Universe; +import eu.modelwriter.traceability.core.persistence.AlloyType; +import eu.modelwriter.traceability.core.persistence.AtomType; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; +import eu.modelwriter.traceability.core.persistence.EntryType; +import eu.modelwriter.traceability.core.persistence.FieldType; +import eu.modelwriter.traceability.core.persistence.InstanceType; +import eu.modelwriter.traceability.core.persistence.ItemType; +import eu.modelwriter.traceability.core.persistence.RepositoryType; +import eu.modelwriter.traceability.core.persistence.SigType; +import eu.modelwriter.traceability.core.persistence.TupleType; +import eu.modelwriter.traceability.core.persistence.TypeType; +import eu.modelwriter.traceability.core.persistence.TypesType; +import eu.modelwriter.traceability.core.persistence.persistenceFactory; + +public class XmlCreator { + + protected static String xmlfile; + protected static DocumentRoot documentRoot; + private Universe universe; + private int id; + private HashMap mapForParent; + private HashMap mapForTypes; + + public XmlCreator(final Universe universe, final String xmlfile) { + XmlCreator.xmlfile = xmlfile; + final DocumentRoot oldDocumentRoot = Utility.getDocumentRoot(); + if (oldDocumentRoot != null && universe == null) { + XmlCreator.documentRoot = oldDocumentRoot; + } else { + this.universe = universe; + this.id = 4; + this.mapForParent = new HashMap(); + this.mapForTypes = new HashMap(); + + this.createBaseXml(); + this.addRelations(); + this.setTypes(); + this.setParents(); + + Utility.writeDocumentRoot(XmlCreator.documentRoot); + } + } + + private void addRelations() { + final Map atomNameIndexMap = new HashMap<>(); + if (this.universe == null) { + return; + } + for (final Relation relation : this.universe.getRelations()) { + if (relation.getArity() < 2) { + final SigType sigType = persistenceFactory.eINSTANCE.createSigType(); + sigType.setID(this.id); + relation.setId(this.id); + this.mapForParent.put(sigType, relation.getParent()); + if (!relation.getTypes().isEmpty()) { + this.mapForTypes.put(sigType, relation); + } + this.id++; + sigType.setLabel(relation.getName()); + this.setStatueOfRelation(relation, sigType); + XmlCreator.documentRoot.getAlloy().getInstance().getSig().add(sigType); + for (final Tuple tuple : relation.getTuples()) { + if (atomNameIndexMap.get(tuple.getAtoms().get(0).getText()) == null) { + final String index = Utility.generateId(XmlCreator.documentRoot, false); + final AtomType atomType = persistenceFactory.eINSTANCE.createAtomType(); + + atomType.setLabel(index); + if (tuple.getBound() != null) { + atomType.setBound(tuple.getBound().toLowerCase()); + } + sigType.getAtom().add(atomType); + + final ItemType itemType = persistenceFactory.eINSTANCE.createItemType(); + final EntryType entryType = persistenceFactory.eINSTANCE.createEntryType(); + itemType.getEntry().add(entryType); + + itemType.setId(index); + entryType.setKey("Name"); + entryType.setValue(tuple.getAtoms().get(0).getText()); + XmlCreator.documentRoot.getAlloy().getRepository().getItem().add(itemType); + atomNameIndexMap.put(tuple.getAtoms().get(0).getText(), index); + } else { + if (!relation.getTypes().isEmpty()) { + final String index = atomNameIndexMap.get(tuple.getAtom(0).getText()); + final AtomType atomType = persistenceFactory.eINSTANCE.createAtomType(); + + atomType.setLabel(index); + if (tuple.getBound() != null) { + atomType.setBound(tuple.getBound().toLowerCase()); + } + sigType.getAtom().add(atomType); + } + } + } + } else if (relation.getArity() > 1) { + final FieldType fieldType = persistenceFactory.eINSTANCE.createFieldType(); + fieldType.setID(this.id); + relation.setId(this.id); + this.mapForParent.put(fieldType, relation.getParent()); + this.mapForTypes.put(fieldType, relation); + this.id++; + fieldType.setLabel(relation.getName()); + XmlCreator.documentRoot.getAlloy().getInstance().getField().add(fieldType); + for (final Tuple tuple : relation.getTuples()) { + final TupleType tupleType = persistenceFactory.eINSTANCE.createTupleType(); + fieldType.getTuple().add(tupleType); + if (tuple.getBound() != null) { + tupleType.setBound(tuple.getBound().toLowerCase()); + } + for (final Atom atom : tuple.getAtoms()) { + final AtomType atomType = persistenceFactory.eINSTANCE.createAtomType(); + atomType.setLabel(atomNameIndexMap.get(atom.getText())); + tupleType.getAtom().add(atomType); + } + } + } + } + } + + private void createBaseXml() { + XmlCreator.documentRoot = persistenceFactory.eINSTANCE.createDocumentRoot(); + + final AlloyType alloyType = persistenceFactory.eINSTANCE.createAlloyType(); + XmlCreator.documentRoot.setAlloy(alloyType); + alloyType.setBuilddate(""); + + final RepositoryType repositoryType = persistenceFactory.eINSTANCE.createRepositoryType(); + repositoryType.setNextId(0); + alloyType.setRepository(repositoryType); + + final InstanceType instanceType = persistenceFactory.eINSTANCE.createInstanceType(); + alloyType.setInstance(instanceType); + instanceType.setBitwidth(0); + instanceType.setFilename(""); + instanceType.setMaxseq(0); + + final SigType sigSegInt = persistenceFactory.eINSTANCE.createSigType(); + instanceType.getSig().add(sigSegInt); + sigSegInt.setID(0); + sigSegInt.setLabel("seq/Int"); + sigSegInt.setParentID(1); + sigSegInt.setBuiltin("yes"); + + final SigType sigInt = persistenceFactory.eINSTANCE.createSigType(); + instanceType.getSig().add(sigInt); + sigInt.setID(1); + sigInt.setLabel("Int"); + sigInt.setParentID(2); + sigInt.setBuiltin("yes"); + + final SigType sigUniv = persistenceFactory.eINSTANCE.createSigType(); + instanceType.getSig().add(sigUniv); + sigUniv.setID(2); + sigUniv.setLabel("univ"); + sigUniv.setBuiltin("yes"); + + final SigType sigString = persistenceFactory.eINSTANCE.createSigType(); + instanceType.getSig().add(sigString); + sigString.setID(3); + sigString.setLabel("String"); + sigString.setParentID(2); + sigString.setBuiltin("yes"); + + } + + public void setMetamodel(final boolean isMetamodel) { + final DocumentRoot documentRoot = Utility.getDocumentRoot(); + if (isMetamodel) { + documentRoot.getAlloy().getInstance().setMetamodel("yes"); + } else { + documentRoot.getAlloy().getInstance().setMetamodel(null); + } + + Utility.writeDocumentRoot(documentRoot); + } + + private void setParents() { + final Iterator> iter = this.mapForParent.entrySet().iterator(); + int countForParentless = 0; + + while (iter.hasNext()) { + final Entry object = iter.next(); + if (object.getKey() instanceof SigType) { + final SigType sigType = (SigType) object.getKey(); + if (object.getValue() != null) { + final Relation parent = this.universe.getRelation(object.getValue().getName()); + + if (parent.getId() == -1) { + countForParentless++; + } + + sigType.setParentID(parent.getId()); + + } else { + if (sigType.getType().isEmpty()) { + sigType.setParentID(2); + } + } + } else if (object.getKey() instanceof FieldType) { + final FieldType fieldType = (FieldType) object.getKey(); + if (object.getValue() != null) { + final Relation parent = this.universe.getRelation(object.getValue().getName()); + + if (parent.getId() == -1) { + countForParentless++; + } + + fieldType.setParentID(parent.getId()); + + } else { + fieldType.setParentID(2); + } + } + } + if (countForParentless != 0) { + this.setParents(); + } + } + + private void setStatueOfRelation(final Relation relation, final SigType sigType) { + if (relation.getMultiplicity() != null) { + switch (relation.getMultiplicity()) { + case LONE: + sigType.setLone("yes"); + break; + case ONE: + sigType.setOne("yes"); + break; + case SOME: + sigType.setSome("yes"); + break; + default: + break; + } + } + if (relation.isAbstract()) { + sigType.setAbstract("yes"); + } + if (relation.isEnum()) { + sigType.setEnum("yes"); + } + if (relation.isMeta()) { + sigType.setMeta("yes"); + } + if (relation.isPrivate()) { + sigType.setPrivate("yes"); + } + } + + private void setTypes() { + final Iterator> iter = this.mapForTypes.entrySet().iterator(); + + while (iter.hasNext()) { + final Entry object = iter.next(); + if (object.getKey() instanceof SigType) { + final SigType sigType = (SigType) object.getKey(); + for (final List types : object.getValue().getTypes()) { + for (final Relation relation : types) { + final Relation relationInUniverse = this.universe.getRelation(relation.getName()); + final TypeType typeType = persistenceFactory.eINSTANCE.createTypeType(); + typeType.setID(relationInUniverse.getId()); + sigType.getType().add(typeType); + } + } + } else if (object.getKey() instanceof FieldType) { + final FieldType fieldType = (FieldType) object.getKey(); + for (final List types : object.getValue().getTypes()) { + final TypesType typesType = persistenceFactory.eINSTANCE.createTypesType(); + for (final Relation relation : types) { + final Relation relationInUniverse = this.universe.getRelation(relation.getName()); + final TypeType typeType = persistenceFactory.eINSTANCE.createTypeType(); + typeType.setID(relationInUniverse.getId()); + typesType.getType().add(typeType); + } + fieldType.getTypes().add(typesType); + } + } + } + + } + + +} diff --git a/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/XmlToUniverse.java b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/XmlToUniverse.java new file mode 100644 index 00000000..6d364baf --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/XmlToUniverse.java @@ -0,0 +1,206 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.visualization; + +import java.io.IOException; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.emf.common.util.EList; + +import eu.modelwriter.kodkod.visualization.model.Atom; +import eu.modelwriter.kodkod.visualization.model.Relation; +import eu.modelwriter.kodkod.visualization.model.Universe; +import eu.modelwriter.kodkod.visualization.model.Relation.Multiplicity; +import eu.modelwriter.traceability.core.persistence.AtomType; +import eu.modelwriter.traceability.core.persistence.EntryType; +import eu.modelwriter.traceability.core.persistence.FieldType; +import eu.modelwriter.traceability.core.persistence.ItemType; +import eu.modelwriter.traceability.core.persistence.SigType; +import eu.modelwriter.traceability.core.persistence.TupleType; +import eu.modelwriter.traceability.core.persistence.TypeType; +import eu.modelwriter.traceability.core.persistence.TypesType; + +public class XmlToUniverse { + + Universe universe; + Map idRelationMap; + Map relationParentMap; + Map idAtomMap; + + public XmlToUniverse() { + universe = new Universe(); + idRelationMap = new HashMap<>(); + relationParentMap = new HashMap<>(); + idAtomMap = new HashMap<>(); + } + + + public Universe getUniverse() { + EList sigList = Utility.getDocumentRoot().getAlloy().getInstance().getSig(); + + for (SigType sigType : sigList) { + if (sigType.getID() > 3) + universe.addRelation(createRelationFromSigType(sigType)); + } + + EList fieldList = Utility.getDocumentRoot().getAlloy().getInstance().getField(); + + for (FieldType fieldType : fieldList) { + universe.addRelation(createRelationFromFieldType(fieldType)); + } + + setParents(); + + return universe; + } + + private Relation createRelationFromSigType(SigType sigType) { + Relation relation = new Relation(sigType.getLabel()); + + relation.setId(sigType.getID()); + checkSigTypeProperties(sigType, relation); + relationParentMap.put(sigType.getID(), sigType.getParentID()); + + EList atomList = sigType.getAtom(); + + for (AtomType atomType : atomList) { + relation.addAtomWithTuple(createAtomFromAtomType(atomType)); + } + + EList typeList = sigType.getType(); + + for (TypeType typeType : typeList) { + relation.addTypes(idRelationMap.get(typeType.getID())); + } + + idRelationMap.put(sigType.getID(), relation); + + return relation; + } + + private void checkSigTypeProperties(SigType sigType, Relation relation) { + if (sigType.getAbstract() != null && sigType.getAbstract().equals("yes")) { + relation.setAbstract(true); + } + if (sigType.getPrivate() != null && sigType.getPrivate().equals("yes")) { + relation.setPrivate(true); + } + if (sigType.getMeta() != null && sigType.getMeta().equals("yes")) { + relation.setMeta(true); + } + if (sigType.getEnum() != null && sigType.getEnum().equals("yes")) { + relation.setEnum(true); + } + if (sigType.getOne() != null && sigType.getOne().equals("yes")) { + relation.setMultiplicity(Multiplicity.ONE); + } else if (sigType.getSome() != null && sigType.getSome().equals("yes")) { + relation.setMultiplicity(Multiplicity.SOME); + } else if (sigType.getLone() != null && sigType.getLone().equals("yes")) { + relation.setMultiplicity(Multiplicity.LONE); + } + } + + private Atom createAtomFromAtomType(AtomType atomType) { + ItemType itemType = Utility.getItemById(atomType.getLabel()); + + String atomName = ""; + Serializable data = null; + + EList entries = itemType.getEntry(); + + for (EntryType entryType : entries) { + if (entryType.getKey().equals("Name")) { + atomName = entryType.getValue(); + } else if (entryType.getKey().equals("Data")) { + try { + data = Serialization.getInstance().fromString(entryType.getValue()); + } catch (ClassNotFoundException | IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + Atom atom = new Atom(atomName); + if (data != null) + atom.setData(data); + + atom.setId(atomType.getLabel()); + + idAtomMap.put(atom.getId(), atom); + + return atom; + } + + private Relation createRelationFromFieldType(FieldType fieldType) { + Relation relation = new Relation(fieldType.getLabel()); + + relation.setId(fieldType.getID()); + relationParentMap.put(fieldType.getID(), fieldType.getParentID()); + + EList tupleList = fieldType.getTuple(); + + for (TupleType tupleType : tupleList) { + relation.addAtomWithTuple(createAtomsFromTupleType(tupleType)); + } + + EList typesList = fieldType.getTypes(); + + for (TypesType typesType : typesList) { + relation.addTypes(createTypesFromTypesType(typesType)); + } + + idRelationMap.put(relation.getId(), relation); + + return relation; + } + + private Atom[] createAtomsFromTupleType(TupleType tupleType) { + EList atomList = tupleType.getAtom(); + Atom[] atoms = new Atom[atomList.size()]; + for (int i = 0; i < atomList.size(); i++) { + atoms[i] = idAtomMap.get(atomList.get(i).getLabel()); + } + + return atoms; + } + + private Relation[] createTypesFromTypesType(TypesType typesType) { + EList typeList = typesType.getType(); + Relation[] types = new Relation[typeList.size()]; + for (int i = 0; i < typeList.size(); i++) { + types[i] = idRelationMap.get(typeList.get(i).getID()); + } + + return types; + } + + private void setParents() { + Iterator> relationParentIter = relationParentMap.entrySet().iterator(); + + while (relationParentIter.hasNext()) { + Entry entry = (Entry) relationParentIter.next(); + + Relation relation = idRelationMap.get(entry.getKey()); + Relation parentRelation = idRelationMap.get(entry.getValue()); + + relation.setParent(parentRelation); + } + } + +} diff --git a/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/model/Atom.java b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/model/Atom.java new file mode 100644 index 00000000..b0d2af96 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/model/Atom.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.visualization.model; + +import java.io.Serializable; + +public class Atom { + private String text; + private Serializable data; + private String id; + + public Atom(String text) { + this.text = text; + } + + public String getText() { + return this.text; + } + + public Serializable getData() { + return data; + } + + public void setData(Serializable data) { + this.data = data; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + +} diff --git a/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/model/Relation.java b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/model/Relation.java new file mode 100644 index 00000000..7f7ce3a7 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/model/Relation.java @@ -0,0 +1,177 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.visualization.model; + +import java.util.ArrayList; +import java.util.List; + +public class Relation { + private final String name; + private final List tuples; + private final List> types; + private int id; + private Relation parent; + private Multiplicity multiplicity; + private boolean Abstract; + private boolean Private; + private boolean Meta; + private boolean Enum; + + public enum Multiplicity { + ONE, LONE, SOME + } + + public Relation(String name) { + this.name = name; + tuples = new ArrayList(); + types = new ArrayList>(); + id = -1; + } + + public void addTuple(Tuple newTuple) { + tuples.add(newTuple); + } + + public boolean contains(Tuple tuple) { + for (final Tuple t : tuples) { + if (t.getText().equals(tuple.getText())) { + return true; + } + } + return false; + } + + public int getArity() { + if (tuples != null && tuples.size() != 0) { + return tuples.get(0).getArity(); + } + return 0; + } + + public String getName() { + return name; + } + + public Tuple getTuple(int index) { + return tuples.get(index); + } + + public int getTupleCount() { + return tuples.size(); + } + + public List getTuples() { + return tuples; + } + + public List> getTypes() { + return types; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Relation getParent() { + return parent; + } + + public void setParent(Relation parent) { + this.parent = parent; + } + + public Multiplicity getMultiplicity() { + return multiplicity; + } + + public void setMultiplicity(Multiplicity multiplicity) { + this.multiplicity = multiplicity; + } + + public boolean isAbstract() { + return Abstract; + } + + public void setAbstract(boolean Abstract) { + this.Abstract = Abstract; + } + + public boolean isPrivate() { + return Private; + } + + public void setPrivate(boolean Private) { + this.Private = Private; + } + + public boolean isMeta() { + return Meta; + } + + public void setMeta(boolean Meta) { + this.Meta = Meta; + } + + public boolean isEnum() { + return Enum; + } + + public void setEnum(boolean Enum) { + this.Enum = Enum; + } + + public void addAtomWithTuple(Atom... atoms) { + Tuple tuple = new Tuple(); + for (Atom atom : atoms) { + tuple.addAtom(atom); + } + this.addTuple(tuple); + } + + + public void addTypes(Relation... relations) { + List type = new ArrayList<>(); + + for (Relation relation : relations) { + type.add(relation); + } + + types.add(type); + } + + @Override + public String toString() { + String ts = ""; + for (final Tuple tuple : tuples) { + ts += tuple.toString() + " "; + } + return name + "={" + ts + "};"; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + if (obj == this) + return true; + + return this.getName().equals(((Relation) obj).getName()); + } + + +} diff --git a/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/model/Tuple.java b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/model/Tuple.java new file mode 100644 index 00000000..378ef1d4 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/model/Tuple.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.visualization.model; + +import java.util.ArrayList; + +public class Tuple { + private String text; + private ArrayList atoms; + private int arity; + private String bound; + + + public Tuple() { + this.atoms = new ArrayList(); + this.arity = 0; + } + + public Tuple(String text) { + this.text = text; + this.atoms = new ArrayList(); + this.arity = 0; + } + + public void addAtom(Atom newAtom) { + this.atoms.add(newAtom); + this.arity++; + } + + public boolean contains(Atom atom) { + for (Atom a : this.atoms) { + if (a.getText().equals(atom.getText())) { + return true; + } + } + return false; + } + + public int getArity() { + return this.arity; + } + + public Atom getAtom(int index) { + return this.atoms.get(index); + } + + public int getAtomCount() { + return this.atoms.size(); + } + + public ArrayList getAtoms() { + return this.atoms; + } + + public String getText() { + return this.text; + } + + public String getBound() { + return bound; + } + + public void setBound(String bound) { + this.bound = bound; + } + + @Override + public String toString() { + String as = ""; + for (Atom atom : this.atoms) { + as += atom.getText() + " "; + } + return "(" + as + ")"; + } +} diff --git a/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/model/Universe.java b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/model/Universe.java new file mode 100644 index 00000000..309cb556 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/model/Universe.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.visualization.model; + +import java.util.ArrayList; + +public class Universe { + private ArrayList atoms; + private ArrayList relations; + + public Universe() { + this.atoms = new ArrayList(); + this.relations = new ArrayList(); + } + + public void addAtom(Atom newAtom) { + this.atoms.add(newAtom); + } + + public void addRelation(Relation newRelation) { + this.relations.add(newRelation); + } + + public boolean contains(Atom atom) { + for (Atom a : this.atoms) { + if (a.getText().equals(atom.getText())) { + return true; + } + } + return false; + } + + public boolean contains(Relation relation) { + for (Relation r : this.relations) { + if (r.getName().equals(relation.getName())) { + return true; + } + } + return false; + } + + public ArrayList getAtoms() { + return this.atoms; + } + + public String getFirstAtomText() { + return this.atoms.get(0).getText(); + } + + public String getNextAtomText(String current) { + for (int i = 0; i < this.atoms.size(); i++) { + if (this.atoms.get(i).getText().equals(current) && i + 1 < this.atoms.size()) { + return this.atoms.get(i + 1).getText(); + } + } + return null; + } + + public Relation getRelation(String relationName) { + for (Relation relation : this.relations) { + if (relation.getName().equals(relationName)) { + return relation; + } + } + return null; + } + + public ArrayList getRelations() { + return this.relations; + } +} diff --git a/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/test/Test.java b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/test/Test.java new file mode 100644 index 00000000..765a2201 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/test/Test.java @@ -0,0 +1,259 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.visualization.test; + +import java.util.ArrayList; +import java.util.List; + +import eu.modelwriter.kodkod.visualization.Notifier; +import eu.modelwriter.kodkod.visualization.Visualization; +import eu.modelwriter.kodkod.visualization.model.Atom; +import eu.modelwriter.kodkod.visualization.model.Relation; +import eu.modelwriter.kodkod.visualization.model.Tuple; +import eu.modelwriter.kodkod.visualization.model.Universe; +import eu.modelwriter.kodkod.visualization.model.Relation.Multiplicity; + +public class Test { + + public static void main(final String[] args) { + final Test test = new Test(); + final Universe universe = test.createFileSystemExample(); + + final Visualization visualization = Visualization.getInstance(universe, "test"); + final List notifiers = new ArrayList<>(); + notifiers.add(new TestNotifier()); + visualization.setNotifierList(notifiers); + // test.addTestAtoms(visualization); + + visualization.showModel(); + + // Universe lastUniverse = visualization.getLastUniverse(); + } + + public void addTestAtoms(final Visualization visualization) { + + visualization.addNewAtom("File", "Deneme", new TestObject("XXX")); + } + + public Universe createFileSystemExample() { + final Universe universe = new Universe(); + + /* Sigs definitions */ + final Relation Object = new Relation("Object"); + final Relation Directory = new Relation("Directory"); + final Relation Root = new Relation("Root"); + final Relation File = new Relation("File"); + final Relation Word = new Relation("Word"); + final Relation Alias = new Relation("Alias"); + + Directory.setParent(Object); + Root.setParent(Directory); + File.setParent(Object); + Word.setParent(File); + Alias.setParent(Object); + + Object.setAbstract(true); + Root.setMultiplicity(Multiplicity.ONE); + + final Atom Root$0 = new Atom("Root$0"); + + final Atom Directory$0 = new Atom("Directory$0"); + final Atom Directory$1 = new Atom("Directory$1"); + + final Atom Alias$0 = new Atom("Alias$0"); + final Atom Alias$1 = new Atom("Alias$1"); + final Atom Alias$2 = new Atom("Alias$2"); + + final Atom Word$0 = new Atom("Word$0"); + final Atom Word$1 = new Atom("Word$1"); + final Atom Word$2 = new Atom("Word$2"); + final Atom Word$3 = new Atom("Word$3"); + + Root.addTuple(this.wrapTupleWithBound("lower", Root$0)); + + Directory.addTuple(this.wrapTupleWithBound("lower", Directory$0)); + Directory.addTuple(this.wrapTupleWithBound("lower", Directory$1)); + + Word.addTuple(this.wrapTupleWithBound("lower", Word$0)); + Word.addTuple(this.wrapTupleWithBound("lower", Word$1)); + Word.addTuple(this.wrapTupleWithBound("lower", Word$2)); + Word.addTuple(this.wrapTupleWithBound("lower", Word$3)); + + Alias.addTuple(this.wrapTupleWithBound("lower", Alias$0)); + Alias.addTuple(this.wrapTupleWithBound("lower", Alias$1)); + Alias.addTuple(this.wrapTupleWithBound("lower", Alias$2)); + + /* Sigs definitions end */ + + /* Fields definitions */ + final Relation contents = new Relation("contents"); + final Relation refs = new Relation("refs"); + + contents.setParent(Directory); + refs.setParent(Alias); + + contents.addTypes(Directory, Object); + refs.addTypes(Alias, Word); + + contents.addTuple(this.wrapTupleWithBound("lower", Root$0, Alias$0)); + contents.addTuple(this.wrapTupleWithBound("lower", Root$0, Directory$0)); + contents.addTuple(this.wrapTupleWithBound("lower", Root$0, Alias$1)); + contents.addTuple(this.wrapTupleWithBound("lower", Directory$0, Word$0)); + contents.addTuple(this.wrapTupleWithBound("lower", Directory$0, Directory$1)); + contents.addTuple(this.wrapTupleWithBound("lower", Directory$1, Word$1)); + contents.addTuple(this.wrapTupleWithBound("lower", Directory$1, Word$2)); + contents.addTuple(this.wrapTupleWithBound("lower", Directory$1, Word$3)); + contents.addTuple(this.wrapTupleWithBound("lower", Directory$1, Alias$2)); + + refs.addTuple(this.wrapTupleWithBound("lower", Alias$2, Word$0)); + refs.addTuple(this.wrapTupleWithBound("lower", Alias$2, Word$1)); + refs.addTuple(this.wrapTupleWithBound("lower", Alias$2, Word$2)); + refs.addTuple(this.wrapTupleWithBound("lower", Alias$2, Word$3)); + + /* Fields definitions end */ + + universe.addRelation(Object); + universe.addRelation(Directory); + universe.addRelation(Root); + universe.addRelation(File); + universe.addRelation(Word); + universe.addRelation(Alias); + + universe.addRelation(contents); + universe.addRelation(refs); + + return universe; + } + + public Universe createInExample() { + + + final Universe universe = new Universe(); + + final Relation Ferhat = new Relation("Ferhat"); + final Relation Anil = new Relation("Anil"); + final Relation Serhat = new Relation("Serhat"); + + final Atom Ferhat$0 = new Atom("Ferhat$0"); + final Atom Ferhat$1 = new Atom("Ferhat$1"); + final Atom Ferhat$2 = new Atom("Ferhat$2"); + + final Atom Anil$0 = new Atom("Anil$0"); + + final Atom Serhat$0 = new Atom("Serhat$0"); + final Atom Serhat$1 = new Atom("Serhat$1"); + final Atom Serhat$2 = new Atom("Serhat$2"); + final Atom Serhat$3 = new Atom("Serhat$3"); + final Atom Serhat$4 = new Atom("Serhat$4"); + final Atom Serhat$5 = new Atom("Serhat$5"); + final Atom Serhat$6 = new Atom("Serhat$6"); + + + Ferhat.addAtomWithTuple(Ferhat$0); + Ferhat.addAtomWithTuple(Ferhat$1); + Ferhat.addAtomWithTuple(Ferhat$2); + + Anil.addAtomWithTuple(Anil$0); + + Serhat.addAtomWithTuple(Serhat$0); + Serhat.addAtomWithTuple(Serhat$1); + Serhat.addAtomWithTuple(Serhat$2); + Serhat.addAtomWithTuple(Serhat$3); + Serhat.addAtomWithTuple(Serhat$4); + Serhat.addAtomWithTuple(Serhat$5); + Serhat.addAtomWithTuple(Serhat$6); + + + final Relation emre = new Relation("emre"); + + emre.setParent(Ferhat); + + emre.addTypes(Ferhat, Serhat); + emre.addTypes(Ferhat, Anil); + + emre.addAtomWithTuple(Ferhat$0, Serhat$6); + emre.addAtomWithTuple(Ferhat$1, Serhat$5); + emre.addAtomWithTuple(Ferhat$2, Serhat$4); + emre.addAtomWithTuple(Ferhat$0, Anil$0); + + universe.addRelation(Ferhat); + universe.addRelation(Anil); + universe.addRelation(Serhat); + universe.addRelation(emre); + + return universe; + } + + public Universe createTestExample() { + + + final Universe universe = new Universe(); + + final Relation sig1 = new Relation("A"); + final Relation sig2 = new Relation("B"); + final Relation sig3 = new Relation("C"); + final Relation field1 = new Relation("X"); + + final Tuple tuple1 = new Tuple("tuple1"); + final Tuple tuple2 = new Tuple("tuple2"); + final Tuple tuple3 = new Tuple("tuple3"); + final Tuple tuple4 = new Tuple("tuple4"); + final Tuple tuple5 = new Tuple("tuple5"); + + final Atom atom1 = new Atom("atom1"); + final Atom atom2 = new Atom("atom2"); + final Atom atom3 = new Atom("atom3"); + + tuple1.addAtom(atom1); + sig1.addTuple(tuple1); + + tuple2.addAtom(atom2); + sig2.addTuple(tuple2); + + tuple4.addAtom(atom3); + sig2.addTuple(tuple4); + + tuple3.addAtom(atom1); + tuple3.addAtom(atom2); + + tuple5.addAtom(atom1); + tuple5.addAtom(atom3); + + field1.setParent(sig1); + field1.addTuple(tuple3); + field1.addTuple(tuple5); + field1.addTypes(sig1, sig2); + + sig1.setParent(sig3); + sig2.setParent(sig3); + + sig3.setAbstract(true); + + universe.addRelation(sig1); + universe.addRelation(sig2); + universe.addRelation(sig3); + universe.addRelation(field1); + + return universe; + } + + private Tuple wrapTupleWithBound(final String bound, final Atom... atoms) { + final Tuple tuple = new Tuple(); + for (final Atom atom : atoms) { + tuple.addAtom(atom); + } + tuple.setBound(bound.toLowerCase()); + return tuple; + } + +} + + diff --git a/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/test/TestNotifier.java b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/test/TestNotifier.java new file mode 100644 index 00000000..a3e547c0 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/test/TestNotifier.java @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.visualization.test; + +import java.io.Serializable; +import java.util.List; + +import eu.modelwriter.kodkod.visualization.Notifier; + +public class TestNotifier implements Notifier { + + @Override + public void addTupleNotify(final String relationName, final List tuple, + final String bound) { + System.out.println("Added Relation " + relationName); + + for (final String string : tuple) { + System.out.println("Atom : " + string); + } + + System.out.println("Bound : " + bound); + } + + @Override + public void addTupleNotify(final String relationName, final String inRelationName, + final List tuple, final String bound) { + System.out.println("Added Relation " + relationName + " in " + inRelationName); + + for (final String string : tuple) { + System.out.println("Atom : " + string); + } + + System.out.println("Bound : " + bound); + } + + @Override + public void moveToLower(final String relationName, final List tuple) { + System.out.println("Relation " + relationName); + + for (final String string : tuple) { + System.out.println("Atom : " + string); + } + + System.out.println("Moved to Lower."); + } + + @Override + public void moveToLower(final String relationName, final String inRelationName, + final List tuple) { + System.out.println("Relation " + relationName + " in " + inRelationName); + + for (final String string : tuple) { + System.out.println("Atom : " + string); + } + + System.out.println("Moved to Lower."); + } + + @Override + public void moveToUpper(final String relationName, final List tuple) { + System.out.println("Relation " + relationName); + + for (final String string : tuple) { + System.out.println("Atom : " + string); + } + + System.out.println("Moved to Upper."); + } + + @Override + public void moveToUpper(final String relationName, final String inRelationName, + final List tuple) { + System.out.println("Relation " + relationName + " in " + inRelationName); + + for (final String string : tuple) { + System.out.println("Atom : " + string); + } + + System.out.println("Moved to Upper."); + } + + @Override + public void notify(final Serializable data) { + final TestObject testObject = (TestObject) data; + + System.out.println(testObject.name); + } + + @Override + public void removeTupleNotify(final String relationName, final List tuple, + final String bound) { + System.out.println("Removed Relation " + relationName); + + for (final String string : tuple) { + System.out.println("Atom : " + string); + } + + System.out.println("Bound : " + bound); + } + + @Override + public void removeTupleNotify(final String relationName, final String inRelationName, + final List tuple, final String bound) { + System.out.println("Removed Relation " + relationName + " in " + inRelationName); + + for (final String string : tuple) { + System.out.println("Atom : " + string); + } + + System.out.println("Bound : " + bound); + } +} diff --git a/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/test/TestObject.java b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/test/TestObject.java new file mode 100644 index 00000000..0c4b7a57 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/test/TestObject.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.visualization.test; + +import java.io.Serializable; + +@SuppressWarnings("serial") +public class TestObject implements Serializable { + + String name; + + public TestObject(String name) { + this.name = name; + } + +} diff --git a/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/wizards/createatom/CreateAtom.java b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/wizards/createatom/CreateAtom.java new file mode 100644 index 00000000..153168f7 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/wizards/createatom/CreateAtom.java @@ -0,0 +1,229 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.visualization.wizards.createatom; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.JTree; +import javax.swing.border.EmptyBorder; +import javax.swing.border.MatteBorder; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.MutableTreeNode; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; + +import edu.mit.csail.sdg.alloy4viz.AlloyAtom; +import eu.modelwriter.kodkod.visualization.Notifier; +import eu.modelwriter.kodkod.visualization.Utility; +import eu.modelwriter.kodkod.visualization.Visualization; + +@SuppressWarnings("serial") +public class CreateAtom extends JFrame { + + + class CellRenderer implements TreeCellRenderer { + private final JLabel label; + + public CellRenderer() { + this.label = new JLabel(); + } + + @Override + public Component getTreeCellRendererComponent(final JTree tree, final Object value, + final boolean selected, final boolean expanded, final boolean leaf, final int row, + final boolean hasFocus) { + + final Object object = ((DefaultMutableTreeNode) value).getUserObject(); + if (object instanceof String) { + final URL imageUrl = this.getClass().getClassLoader().getResource("sig.png"); + this.label.setText((String) object); + this.label.setIcon(new ImageIcon(imageUrl)); + } + + if (selected && hasFocus) { + this.label.setOpaque(true); + this.label.setBackground(new Color(199, 229, 255)); + this.label.setBorder(BorderFactory.createLineBorder(new Color(144, 204, 255))); + } else { + this.label.setOpaque(false); + this.label.setBorder(BorderFactory.createLineBorder(Color.WHITE)); + } + + return this.label; + } + } + + private final JPanel contentPanel = new JPanel(); + private JTextField textField; + private JTree tree; + + // /** + // * Launch the application. + // */ + // public static void main(String[] args) { + // EventQueue.invokeLater(new Runnable() { + // public void run() { + // try { + // CreateAtom frame = new CreateAtom(); + // frame.setVisible(true); + // } catch (Exception e) { + // e.printStackTrace(); + // } + // } + // }); + // } + + private final AlloyAtom beforeAtom; + + /** + * Create the frame. + */ + public CreateAtom(final AlloyAtom beforeAtom) { + this.beforeAtom = beforeAtom; + this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + this.setTitle("Create Atom"); + this.setBounds(100, 100, 450, 300); + this.getContentPane().setLayout(new BorderLayout()); + this.contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5)); + this.getContentPane().add(this.contentPanel, BorderLayout.CENTER); + this.contentPanel.setLayout(new BorderLayout(0, 0)); + { + final MutableTreeNode univ = new DefaultMutableTreeNode("Univ"); + this.tree = new JTree(univ); + this.tree.setBorder(new MatteBorder(1, 1, 1, 1, new Color(0, 0, 0))); + this.contentPanel.add(this.tree, BorderLayout.CENTER); + this.tree.setCellRenderer(new CellRenderer()); + + final List topElement = Utility.getTypeHierarchyForTree(); + + for (final MutableTreeNode mutableTreeNode : topElement) { + univ.insert(mutableTreeNode, univ.getChildCount()); + } + final TreeNode root = (TreeNode) this.tree.getModel().getRoot(); + this.expandAll(this.tree, new TreePath(root)); + } + if (this.beforeAtom == null) { + final JPanel panel = new JPanel(); + this.contentPanel.add(panel, BorderLayout.NORTH); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5)); + { + final JLabel lblNewLabel = new JLabel("Atom Name : "); + panel.add(lblNewLabel); + } + { + this.textField = new JTextField(); + panel.add(this.textField); + this.textField.setColumns(30); + } + } + { + final JPanel buttonPane = new JPanel(); + buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT)); + this.getContentPane().add(buttonPane, BorderLayout.SOUTH); + { + final JButton okButton = new JButton("OK"); + okButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent arg0) { + if (CreateAtom.this.performFinish()) { + Visualization.getInstance(null).revalidate(); + CreateAtom.this.disposeThis(); + } + } + }); + okButton.setActionCommand("OK"); + buttonPane.add(okButton); + this.getRootPane().setDefaultButton(okButton); + } + { + final JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + CreateAtom.this.disposeThis(); + } + }); + cancelButton.setActionCommand("Cancel"); + buttonPane.add(cancelButton); + } + } + } + + private void disposeThis() { + this.dispose(); + } + + private void expandAll(final JTree tree, final TreePath parent) { + final TreeNode node = (TreeNode) parent.getLastPathComponent(); + if (node.getChildCount() >= 0) { + for (@SuppressWarnings("rawtypes") + final Enumeration e = node.children(); e.hasMoreElements();) { + final TreeNode n = (TreeNode) e.nextElement(); + final TreePath path = parent.pathByAddingChild(n); + this.expandAll(tree, path); + } + } + tree.expandPath(parent); + // tree.collapsePath(parent); + } + + private boolean performFinish() { + final TreePath path = this.tree.getSelectionModel().getSelectionPath(); + if (path == null || path.getLastPathComponent() == null) { + return false; + } + + final String relationName = path.getLastPathComponent().toString(); + final String inRelationName = Utility.getType(relationName); + + if (this.beforeAtom == null) { + final String name = this.textField.getText(); + if (inRelationName != null) { + Utility.addAtomToSigType(inRelationName, name); + } + Utility.addAtomToSigType(relationName, name); + final List notifierList = Visualization.getInstance().getNotifierList(); + final List tupleList = new ArrayList<>(); + tupleList.add(name); + for (final Notifier notifier : notifierList) { + if (inRelationName != null) { + notifier.addTupleNotify(relationName, inRelationName, tupleList, + Visualization.getInstance().isLower() ? "lower" : "upper"); + } else { + notifier.addTupleNotify(relationName, tupleList, + Visualization.getInstance().isLower() ? "lower" : "upper"); + } + } + } else { + Utility.changeAtomType(this.beforeAtom, !relationName.equals(inRelationName) ? inRelationName : relationName); + } + + return true; + } + +} diff --git a/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/wizards/createatom/TypeElement.java b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/wizards/createatom/TypeElement.java new file mode 100644 index 00000000..68b0e712 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/wizards/createatom/TypeElement.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.visualization.wizards.createatom; + +import java.io.Serializable; +import java.util.ArrayList; + +@SuppressWarnings("serial") +public class TypeElement implements Serializable { + + private String type; + private ArrayList children = new ArrayList(); + private boolean isTop = false; + + public TypeElement(String type) { + this.type = type; + } + + public TypeElement(String type, boolean isTop) { + this.type = type; + this.setTop(isTop); + } + + public TypeElement(String type, ArrayList children) { + super(); + this.type = type; + this.children = children; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public ArrayList getChildren() { + return children; + } + + public void setChildren(ArrayList children) { + this.children = children; + } + + + @Override + public String toString() { + + return type; + } + + public boolean isTop() { + return isTop; + } + + public void setTop(boolean isTop) { + this.isTop = isTop; + } + +} diff --git a/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/wizards/mapping/MappingWizard.java b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/wizards/mapping/MappingWizard.java new file mode 100644 index 00000000..3b7c5ff2 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/src/eu/modelwriter/kodkod/visualization/wizards/mapping/MappingWizard.java @@ -0,0 +1,371 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.kodkod.visualization.wizards.mapping; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.DefaultListModel; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.ListCellRenderer; +import javax.swing.border.EmptyBorder; +import javax.swing.border.LineBorder; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.MutableTreeNode; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; + +import eu.modelwriter.kodkod.visualization.Notifier; +import eu.modelwriter.kodkod.visualization.Utility; +import eu.modelwriter.kodkod.visualization.Visualization; + +@SuppressWarnings("serial") +public class MappingWizard extends JFrame { + + @SuppressWarnings("rawtypes") + class ListCellRender implements ListCellRenderer { + private final JLabel label; + + public ListCellRender() { + this.label = new JLabel(); + } + + + @Override + public Component getListCellRendererComponent(final JList arg0, final Object arg1, + final int arg2, final boolean arg3, final boolean arg4) { + + final Object object = arg1; + if (object instanceof String) { + final URL imageUrl = this.getClass().getClassLoader().getResource("relation.png"); + this.label.setText((String) object); + this.label.setIcon(new ImageIcon(imageUrl)); + } + + if (arg3 && arg4) { + this.label.setOpaque(true); + this.label.setBackground(new Color(199, 229, 255)); + this.label.setBorder(BorderFactory.createLineBorder(new Color(144, 204, 255))); + } else { + this.label.setOpaque(false); + this.label.setBorder(BorderFactory.createLineBorder(Color.WHITE)); + } + + return this.label; + } + } + class TreeCellRender implements TreeCellRenderer { + private final JCheckBox label; + + public TreeCellRender() { + this.label = new JCheckBox(); + } + + @SuppressWarnings("unchecked") + @Override + public Component getTreeCellRendererComponent(final JTree tree, final Object value, + final boolean selected, final boolean expanded, final boolean leaf, final int row, + final boolean hasFocus) { + + final Object object = ((DefaultMutableTreeNode) value).getUserObject(); + ArrayList listObject = null; + if (object instanceof ArrayList) { + listObject = (ArrayList) object; + this.label.setIcon(null); + this.label.setText(listObject.get(4)); + if (listObject.get(5).equals("true")) { + this.label.setSelected(true); + } else { + this.label.setSelected(false); + } + + } else { + final URL imageUrl = this.getClass().getClassLoader().getResource("atom.png"); + this.label.setIcon(new ImageIcon(imageUrl)); + this.label.setText((String) object); + this.label.setSelected(false); + } + + if (selected && hasFocus) { + this.label.setOpaque(true); + this.label.setBackground(new Color(199, 229, 255)); + this.label.setBorder(BorderFactory.createLineBorder(new Color(144, 204, 255))); + + if (listObject != null) { + if (listObject.get(5).equals("true")) { + listObject.set(5, "false"); + this.label.setSelected(false); + } else { + listObject.set(5, "true"); + this.label.setSelected(true); + } + } + } else { + this.label.setOpaque(false); + this.label.setBorder(BorderFactory.createLineBorder(Color.WHITE)); + } + + return this.label; + } + } + + private JPanel relationContentPane; + private JPanel atomContentPane; + String type; + int index; + @SuppressWarnings("rawtypes") + private JList list; + private JTree tree; + + /** + * Launch the application. + */ + // public static void main(String[] args) { + // EventQueue.invokeLater(new Runnable() { + // public void run() { + // try { + // RelationPage frame = new RelationPage(); + // frame.setVisible(true); + // } catch (Exception e) { + // e.printStackTrace(); + // } + // } + // }); + // } + + private String relation; + + private final String id; + + /** + * Create the frame. + */ + public MappingWizard(final String type, final int index) { + this.type = type; + this.index = index; + this.id = Utility.itemIdByIndex(type, index); + this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + this.setBounds(100, 100, 450, 300); + this.createRelationContent(); + this.setContentPane(this.relationContentPane); + } + + private void createAtomContent() { + this.setTitle("Atoms"); + + this.atomContentPane = new JPanel(); + this.atomContentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); + this.atomContentPane.setLayout(new BorderLayout(0, 0)); + + final MutableTreeNode atoms = new DefaultMutableTreeNode("Atoms"); + this.tree = new JTree(atoms); + this.tree.setBorder(new LineBorder(new Color(0, 0, 0))); + final JScrollPane scrollPane = new JScrollPane(this.tree, + JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + scrollPane.setBorder(new EmptyBorder(5, 5, 5, 5)); + this.atomContentPane.add(scrollPane, BorderLayout.CENTER); + this.tree.setCellRenderer(new TreeCellRender()); + + final String selectedValueOfList = (String) this.list.getSelectedValue(); + this.relation = selectedValueOfList.substring(0, selectedValueOfList.indexOf(" ")); + final String selectedType = selectedValueOfList.substring(selectedValueOfList.indexOf(": ") + 2, + selectedValueOfList.indexOf(" ->")); + final ArrayList> suitableAtoms = + Utility.getSuitableSecondSideTypesOfRelation(this.relation, selectedType, this.id); + + String atomType = ""; + MutableTreeNode typeNode = null; + + for (final ArrayList suitable : suitableAtoms) { + if (!atomType.equals(suitable.get(0))) { + typeNode = new DefaultMutableTreeNode(suitable.get(0)); + atomType = suitable.get(0); + atoms.insert(typeNode, atoms.getChildCount()); + } + suitable.add(suitable.get(1) + " { " + suitable.get(2) + " }"); + suitable.add(suitable.get(3)); + final MutableTreeNode atomNode = new DefaultMutableTreeNode(suitable); + typeNode.insert(atomNode, typeNode.getChildCount()); + } + + final TreeNode root = (TreeNode) this.tree.getModel().getRoot(); + this.expandAll(this.tree, new TreePath(root)); + + final JPanel panel = new JPanel(); + final FlowLayout flowLayout = (FlowLayout) panel.getLayout(); + flowLayout.setAlignment(FlowLayout.RIGHT); + this.atomContentPane.add(panel, BorderLayout.SOUTH); + + final JButton btnNewButton = new JButton("Back"); + btnNewButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + MappingWizard.this.createRelationContent(); + MappingWizard.this.setContentPane(MappingWizard.this.relationContentPane); + MappingWizard.this.revalidate(); + } + }); + panel.add(btnNewButton); + + final JButton btnNewButton_1 = new JButton("Finish"); + btnNewButton_1.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + final List notifierList = Visualization.getInstance().getNotifierList(); + + for (final ArrayList suitable : suitableAtoms) { + if (!suitable.get(3).equals(suitable.get(5))) { + final String toIndex = suitable.get(1).substring(suitable.get(0).length()); + final String toItemId = + Utility.itemIdByIndex(suitable.get(0), Integer.parseInt(toIndex)); + final String toAtomName = Utility.getAtomNameById(toItemId); + final String fromAtomName = Utility.getAtomNameById(MappingWizard.this.id); + final List tupleList = new ArrayList<>(); + tupleList.add(fromAtomName); + tupleList.add(toAtomName); + if (suitable.get(5).equals("false")) { + Utility.removeRelation(MappingWizard.this.id, toItemId, MappingWizard.this.relation); + for (final Notifier notifier : notifierList) { + notifier.removeTupleNotify(MappingWizard.this.relation, tupleList, + Visualization.getInstance().isLower() ? "lower" : "upper"); + } + } else { + Utility.addRelation2Atoms(MappingWizard.this.id, toItemId, + MappingWizard.this.relation); + for (final Notifier notifier : notifierList) { + notifier.addTupleNotify(MappingWizard.this.relation, tupleList, + Visualization.getInstance().isLower() ? "lower" : "upper"); + } + } + } + } + + // TreePath path = tree.getSelectionModel().getSelectionPath(); + // if (path == null || path.getLastPathComponent() == null) + // return; + // String selectedOnTree = path.getLastPathComponent().toString(); + // String selectedItemType = path.getParentPath().getLastPathComponent().toString(); + // String strIndexOfSelected = + // selectedOnTree.substring(selectedItemType.length(), selectedOnTree.indexOf(" ")); + // int indexOfSelected = 0; + // if (!strIndexOfSelected.isEmpty()) { + // try { + // indexOfSelected = Integer.parseInt(strIndexOfSelected); + // } catch (NumberFormatException e1) { + // } + // } + // Utility.addRelation2Atoms(Utility.itemIdByIndex(type, index), + // Utility.itemIdByIndex(selectedItemType, indexOfSelected), relation); + Visualization.getInstance(null).revalidate(); + MappingWizard.this.disposeThis(); + } + }); + panel.add(btnNewButton_1); + + final JButton btnCancel = new JButton("Cancel"); + btnCancel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + MappingWizard.this.disposeThis(); + } + }); + panel.add(btnCancel); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private void createRelationContent() { + this.setTitle("Relations"); + this.relationContentPane = new JPanel(); + this.relationContentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); + this.relationContentPane.setLayout(new BorderLayout(0, 0)); + + this.list = new JList(); + this.list.setBorder(new LineBorder(new Color(0, 0, 0))); + final JScrollPane scrollPane = new JScrollPane(this.list, + JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + scrollPane.setBorder(new EmptyBorder(5, 5, 5, 5)); + this.relationContentPane.add(scrollPane, BorderLayout.CENTER); + + final ArrayList relations = Utility.getSuitableRelations(this.type); + final DefaultListModel model = new DefaultListModel<>(); + this.list.setModel(model); + this.list.setCellRenderer(new ListCellRender()); + + for (final String rel : relations) { + model.addElement(rel); + } + + final JPanel panel = new JPanel(); + final FlowLayout flowLayout = (FlowLayout) panel.getLayout(); + flowLayout.setAlignment(FlowLayout.RIGHT); + this.relationContentPane.add(panel, BorderLayout.SOUTH); + + final JButton btnNewButton = new JButton("Next"); + btnNewButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + if (!MappingWizard.this.list.isSelectionEmpty()) { + MappingWizard.this.createAtomContent(); + MappingWizard.this.setContentPane(MappingWizard.this.atomContentPane); + MappingWizard.this.revalidate(); + } + } + }); + panel.add(btnNewButton); + + final JButton btnNewButton_1 = new JButton("Cancel"); + btnNewButton_1.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent arg0) { + MappingWizard.this.disposeThis(); + } + }); + panel.add(btnNewButton_1); + } + + + private void disposeThis() { + this.dispose(); + } + + private void expandAll(final JTree tree, final TreePath parent) { + final TreeNode node = (TreeNode) parent.getLastPathComponent(); + if (node.getChildCount() >= 0) { + for (@SuppressWarnings("rawtypes") + final Enumeration e = node.children(); e.hasMoreElements();) { + final TreeNode n = (TreeNode) e.nextElement(); + final TreePath path = parent.pathByAddingChild(n); + this.expandAll(tree, path); + } + } + tree.expandPath(parent); + // tree.collapsePath(parent); + } + +} diff --git a/Source/eu.modelwriter.kodkod.visualization/temp/test.xml b/Source/eu.modelwriter.kodkod.visualization/temp/test.xml new file mode 100644 index 00000000..a62a0bc5 --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/temp/test.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Directory$0 + + + Directory$1 + + + Root$0 + + + Word$0 + + + Word$1 + + + Word$2 + + + Word$3 + + + Alias$0 + + + Alias$1 + + + Alias$2 + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.kodkod.visualization/temp/universeTest.xml b/Source/eu.modelwriter.kodkod.visualization/temp/universeTest.xml new file mode 100644 index 00000000..df4d968d --- /dev/null +++ b/Source/eu.modelwriter.kodkod.visualization/temp/universeTest.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Directory$0 + + + Directory$1 + + + Root$0 + + + Word$0 + + + Word$1 + + + Word$2 + + + Word$3 + + + Alias$0 + + + Alias$1 + + + Alias$2 + + + asdasd + + + asdasd + + + asdasd + + + asdasd + + + asdasd + + + asdsd + + + werwer + + + rwwerwerq + + + asdad + + + + + + asdasd + + + sdfdf + + + dasdasd + + + czxc + + + asd + + + \ No newline at end of file diff --git a/Source/eu.modelwriter.marker.command/.classpath b/Source/eu.modelwriter.marker.command/.classpath new file mode 100644 index 00000000..eca7bdba --- /dev/null +++ b/Source/eu.modelwriter.marker.command/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Source/eu.modelwriter.marker.command/.gitignore b/Source/eu.modelwriter.marker.command/.gitignore new file mode 100644 index 00000000..ae3c1726 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/Source/eu.modelwriter.marker.command/.project b/Source/eu.modelwriter.marker.command/.project new file mode 100644 index 00000000..20e7e6ce --- /dev/null +++ b/Source/eu.modelwriter.marker.command/.project @@ -0,0 +1,28 @@ + + + eu.modelwriter.marker.command + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/Source/eu.modelwriter.marker.command/.settings/org.eclipse.jdt.core.prefs b/Source/eu.modelwriter.marker.command/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..0c68a61d --- /dev/null +++ b/Source/eu.modelwriter.marker.command/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/Source/eu.modelwriter.marker.command/.settings/org.eclipse.pde.core.prefs b/Source/eu.modelwriter.marker.command/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 00000000..923c37fb --- /dev/null +++ b/Source/eu.modelwriter.marker.command/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +resolve.requirebundle=false diff --git a/Source/eu.modelwriter.marker.command/META-INF/MANIFEST.MF b/Source/eu.modelwriter.marker.command/META-INF/MANIFEST.MF new file mode 100644 index 00000000..e68b8472 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/META-INF/MANIFEST.MF @@ -0,0 +1,29 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: eu.modelwriter.marker.action +Bundle-SymbolicName: eu.modelwriter.marker.command;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: eu.modelwriter.marker.command.Activator +Require-Bundle: org.eclipse.core.runtime, + eu.modelwriter.marker, + org.eclipse.jface.text, + org.eclipse.jdt.core, + org.eclipse.emf.ecore.editor, + org.eclipse.ui.editors, + eu.modelwriter.marker.ui, + eu.modelwriter.configuration;bundle-version="1.0.0", + org.eclipse.ui.console, + eu.modelwriter.alloyanalyzer;bundle-version="1.0.0", + org.eclipse.core.resources, + org.eclipse.jdt.ui +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ActivationPolicy: lazy +Export-Package: eu.modelwriter.marker.command; + uses:="org.osgi.framework, + org.eclipse.ui, + org.eclipse.ui.menus, + org.eclipse.ui.commands, + org.eclipse.core.resources, + org.eclipse.core.commands, + org.eclipse.jface.viewers, + org.eclipse.ui.plugin" diff --git a/Source/eu.modelwriter.marker.command/build.properties b/Source/eu.modelwriter.marker.command/build.properties new file mode 100644 index 00000000..6a856854 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/build.properties @@ -0,0 +1,24 @@ +############################################################################### +# Copyright (c) 2015 UNIT Information Technologies R&D Ltd +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Ferhat Erata - initial API and implementation +# H. Emre Kirmizi - initial API and implementation +# Serhat Celik - initial API and implementation +# U. Anil Ozturk - initial API and implementation +############################################################################### +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + build.properties,\ + bin/,\ + .settings/,\ + .project,\ + .classpath +additional.bundles = org.eclipse.core.expressions diff --git a/Source/eu.modelwriter.marker.command/plugin.xml b/Source/eu.modelwriter.marker.command/plugin.xml new file mode 100644 index 00000000..3ed3f978 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/plugin.xml @@ -0,0 +1,1124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/Activator.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/Activator.java new file mode 100644 index 00000000..487c36dd --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/Activator.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.command; + +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "eu.modelwriter.marker.action"; //$NON-NLS-1$ + + // The shared instance + private static Activator plugin; + + /** + * The constructor + */ + public Activator() {} + + public static Shell getShell() { + return getActiveWorkbenchWindow().getShell(); + } + + public static IWorkbenchWindow getActiveWorkbenchWindow() { + return PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/AddRemoveTypeHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/AddRemoveTypeHandler.java new file mode 100644 index 00000000..e9bc1664 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/AddRemoveTypeHandler.java @@ -0,0 +1,229 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.command; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.presentation.EcoreEditor; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ITreeSelection; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.PlatformUI; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; +import eu.modelwriter.marker.ui.internal.wizards.mappingwizard.ActionSelectionDialog; +import eu.modelwriter.marker.ui.internal.wizards.markerwizard.MarkerPage; +import eu.modelwriter.marker.ui.internal.wizards.markerwizard.MarkerWizard; +import eu.modelwriter.marker.ui.internal.wizards.selectionwizard.SelectionWizard; + +@SuppressWarnings("restriction") +public class AddRemoveTypeHandler extends AbstractHandler { + public static String COMMAND_ID = "eu.modelwriter.marker.command.addremovetype"; + IEditorPart editor; + IFile file; + ISelection selection; + IMarker selectedMarker; + private ArrayList candidateToTypeChanging; + + private void addRemoveType() { + if (!MarkerPage.isParsed()) { + final MessageDialog parseCtrlDialog = + new MessageDialog(MarkerActivator.getShell(), "Type Information", null, + "You dont have any marker type registered to system! \n" + + "Please parse an alloy file first", + MessageDialog.INFORMATION, new String[] {"OK"}, 0); + parseCtrlDialog.open(); + return; + } + + final ActionSelectionDialog actionSelectionDialog = + new ActionSelectionDialog(MarkerActivator.getShell()); + actionSelectionDialog.open(); + if (actionSelectionDialog.getReturnCode() == IDialogConstants.CANCEL_ID) { + return; + } + + if (selectedMarker != null && selectedMarker.exists()) { + findCandidateToTypeChangingMarkers(selectedMarker); + if (actionSelectionDialog.getReturnCode() == IDialogConstants.YES_ID) { + addType(selectedMarker); + } else if (actionSelectionDialog.getReturnCode() == IDialogConstants.NO_ID) { + final MessageDialog warningDialog = + new MessageDialog(MarkerActivator.getShell(), "Warning!", null, + "If you remove marker's type, all relations of this marker has been removed! Do you want to continue to remove marker's type?", + MessageDialog.WARNING, new String[] {"Yes", "No"}, 0); + final int returnCode = warningDialog.open(); + if (returnCode != 0) { + return; + } + removeType(selectedMarker); + } + // MarkerUpdater.updateTargets(selectedMarker); + // MarkerUpdater.updateSources(selectedMarker); + } else { + final MessageDialog dialog = + new MessageDialog(MarkerActivator.getShell(), "There is no marker in this position", null, + "Please select valid marker", MessageDialog.INFORMATION, new String[] {"Ok"}, 0); + dialog.open(); + return; + } + } + + private void addType(final IMarker selectedMarker) { + final MarkerWizard markerTypeWizard = new MarkerWizard(selectedMarker); + + final WizardDialog dialog = new WizardDialog(MarkerActivator.getShell(), markerTypeWizard); + dialog.open(); + } + + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + if (AlloyUtilities.isExists()) { + candidateToTypeChanging = new ArrayList(); + file = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor() + .getEditorInput().getAdapter(IFile.class); + selection = + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection(); + editor = + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + selectedMarker = MarkUtilities.getLeaderOfMarker(getMarker()); + + addRemoveType(); + if (Activator.getDefault().getWorkbench().getWorkbenchWindows()[0].getActivePage() + .findView(Visualization.ID) != null) { + Visualization.showViz(); + } + } else { + final MessageDialog infoDialog = new MessageDialog(MarkerActivator.getShell(), + "System Information", null, "You dont have any registered alloy file to system.", + MessageDialog.INFORMATION, new String[] {"Ok"}, 0); + infoDialog.open(); + } + return null; + } + + /** + * @param selectedMarker from text + */ + private void findCandidateToTypeChangingMarkers(final IMarker selectedMarker) { + candidateToTypeChanging.add(selectedMarker); + + final Map fieldsSources = + AlloyUtilities.getRelationsOfSecondSideMarker(selectedMarker); + final ArrayList relationsSources = + AlloyUtilities.getSourcesOfMarkerAtRelations(selectedMarker); + + for (final IMarker iMarker : fieldsSources.keySet()) { + candidateToTypeChanging.add(iMarker); + } + + for (final IMarker iMarker : relationsSources) { + candidateToTypeChanging.add(iMarker); + } + } + + private IMarker getMarker() { + IMarker selectedMarker = null; + if (selection != null) { + if (selection instanceof ITextSelection) { + final ITextSelection textSelection = (ITextSelection) selection; + + final ArrayList markerList = + MarkerFactory.findMarkersInSelection(file, textSelection); + if (markerList != null) { + if (markerList.size() == 1) { + selectedMarker = markerList.get(0); + } else if (markerList.size() > 1) { + final SelectionWizard selectionWizard = new SelectionWizard(markerList); + final WizardDialog selectionDialog = + new WizardDialog(MarkerActivator.getShell(), selectionWizard); + if (selectionDialog.open() == 1) { + return null; + } + selectedMarker = selectionWizard.getSelectedMarker(); + } + } + } else if (selection instanceof ITreeSelection) { + final ITreeSelection treeSelection = (ITreeSelection) selection; + if (((ITreeSelection) selection).getFirstElement() instanceof IMarker) { + selectedMarker = (IMarker) ((ITreeSelection) selection).getFirstElement(); + } else if (editor instanceof EcoreEditor) { + if (treeSelection.getFirstElement() instanceof ENamedElement + && ((ENamedElement) treeSelection.getFirstElement()).getName() != null + && !((ENamedElement) treeSelection.getFirstElement()).getName().isEmpty()) { + + final URI uri = EcoreUtil.getURI((ENamedElement) treeSelection.getFirstElement()); + + selectedMarker = MarkerFactory.findMarkersByUri(file, uri.toString()); + } else if (!((EObject) treeSelection.getFirstElement() instanceof EModelElement)) { + final URI uri = EcoreUtil.getURI((EObject) treeSelection.getFirstElement()); + selectedMarker = MarkerFactory.findMarkersByUri(file, uri.toString()); + } + } else if (editor instanceof CompilationUnitEditor) { + selectedMarker = MarkerFactory.findMarkerByOutlineTreeSelection(treeSelection, file); + } + } + } + return selectedMarker; + } + + private void removeType(IMarker selectedMarker) { + selectedMarker = AnnotationFactory.convertAnnotationType(selectedMarker, true, true, + AlloyUtilities.getTotalTargetCount(selectedMarker)); + + IMarker marker = null; + for (int i = 1; i < candidateToTypeChanging.size(); i++) { + marker = candidateToTypeChanging.get(i); + AnnotationFactory.convertAnnotationType(marker, true, + MarkUtilities.compare(marker, selectedMarker), + AlloyUtilities.getTotalTargetCount(marker)); + } + AlloyUtilities.removeAllRelationsOfMarker(selectedMarker); + AlloyUtilities.removeRelationOfMarker(selectedMarker); + if (MarkUtilities.getGroupId(selectedMarker) != null) { + final List group = MarkerFactory.findMarkersByGroupId(selectedMarker.getResource(), + MarkUtilities.getGroupId(selectedMarker)); + for (final IMarker iMarker : group) { + AlloyUtilities.removeTypeFromMarker(iMarker); + MarkUtilities.setType(iMarker, null); + } + } else { + AlloyUtilities.removeTypeFromMarker(selectedMarker); + MarkUtilities.setType(selectedMarker, null); + } + final MessageDialog removeSuccessDialog = new MessageDialog(MarkerActivator.getShell(), + "Removing Type Action", null, "Selected marker's type has been removed.", + MessageDialog.INFORMATION, new String[] {"OK"}, 0); + removeSuccessDialog.open(); + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/AlloyParseUtil.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/AlloyParseUtil.java new file mode 100644 index 00000000..deb94e94 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/AlloyParseUtil.java @@ -0,0 +1,90 @@ +package eu.modelwriter.marker.command; + +import java.io.IOException; +import java.util.ArrayList; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.ui.PlatformUI; + +import eu.modelwriter.configuration.alloy.AlloyParser; +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.Serialization; +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.marker.internal.MarkerTypeElement; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; +import eu.modelwriter.marker.ui.internal.wizards.markerwizard.MarkerPage; + +public class AlloyParseUtil { + public static void parse(final String filePath) { + AlloyParseUtil.removeTypesFromMarkers(); + + final AlloyParser parser = new AlloyParser(filePath); + final ArrayList roots = parser.getTypes(); + final ArrayList rels = parser.getRels(); + + MarkerPage.settings.put("alloyFile", filePath); + final MarkerTypeElement systemRoot = new MarkerTypeElement("universe"); + for (final MarkerTypeElement root : roots) { + systemRoot.getChildren().add(root); + } + + try { + MarkerPage.settings.put("universe", Serialization.getInstance().toString(systemRoot)); + MarkerPage.settings.put("rels", Serialization.getInstance().toString(rels)); + } catch (final IOException e1) { + e1.printStackTrace(); + } + if (Activator.getDefault().getWorkbench().getWorkbenchWindows()[0].getActivePage() + .findView(Visualization.ID) != null) { + Visualization.showViz(); + } + } + + private static void removeTypesFromMarkers() { + for (final IResource iResource : ResourcesPlugin.getWorkspace().getRoot().getProjects()) { + boolean isClosed = false; + try { + if (!((IProject) iResource).isOpen()) { + isClosed = true; + ((IProject) iResource).open(new NullProgressMonitor()); + } + for (IMarker iMarker : MarkerFactory.findMarkersAsArrayList(iResource)) { + if (MarkUtilities.getType(iMarker) != null) { + if (AlloyUtilities.getTotalTargetCount(iMarker) != 0) { + iMarker = AnnotationFactory.convertAnnotationType(iMarker, false, true, + AlloyUtilities.getTotalTargetCount(iMarker)); + } + MarkUtilities.setType(iMarker, null); + AlloyUtilities.removeTypeFromMarker(iMarker); + } + } + if (isClosed == true) { + ((IProject) iResource).close(new NullProgressMonitor()); + } + } catch (final CoreException e) { + e.printStackTrace(); + } + } + } + + public static IFile getSelectedFile() { + IFile file = null; + final ISelection selection = + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection(); + if (selection != null && selection instanceof TreeSelection) { + final TreeSelection treeSelection = (TreeSelection) selection; + file = (IFile) treeSelection.getFirstElement(); + } + return file; + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/AlloyToEMFHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/AlloyToEMFHandler.java new file mode 100644 index 00000000..97ed9a6b --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/AlloyToEMFHandler.java @@ -0,0 +1,41 @@ +package eu.modelwriter.marker.command; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.widgets.Display; + +import eu.modelwriter.configuration.alloy.trace.TraceException; +import eu.modelwriter.configuration.alloy.trace.TraceManager; +import eu.modelwriter.configuration.alloy2emf.AlloyToEMF; +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; +import eu.modelwriter.marker.ui.internal.wizards.markerwizard.MarkerPage; + +public class AlloyToEMFHandler extends AbstractHandler { + + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + final String alloyFilePath = MarkerPage.settings.get("alloyFile"); + try { + TraceManager.get().loadSpec(alloyFilePath); + final AlloyToEMF alloy2emf = new AlloyToEMF(alloyFilePath); + alloy2emf.start(); + Display.getDefault().syncExec(new Runnable() { + + @Override + public void run() { + Visualization.showViz(); + } + }); + } catch (final TraceException e) { + final MessageDialog warningdialog = new MessageDialog(MarkerActivator.getShell(), + "Alloy To EMF", null, e.getMessage(), MessageDialog.WARNING, new String[] {"OK"}, 0); + if (warningdialog.open() != 0) { + return null; + } + } + return null; + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/AutomatedTraceCreationHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/AutomatedTraceCreationHandler.java new file mode 100644 index 00000000..2bed1ede --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/AutomatedTraceCreationHandler.java @@ -0,0 +1,47 @@ +package eu.modelwriter.marker.command; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.JobChangeAdapter; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.widgets.Display; + +import eu.modelwriter.configuration.synthesis.AutomatedTraceCreator; +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; +import eu.modelwriter.marker.ui.internal.wizards.markerwizard.MarkerPage; + +public class AutomatedTraceCreationHandler extends AbstractHandler { + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + final AutomatedTraceCreator creator = new AutomatedTraceCreator(); + + // Check if specification is loaded + if (MarkerPage.settings.get("alloyFile") == null) { + new MessageDialog(MarkerActivator.getShell(), "Automated Trace Creation", null, + "Load the specification first.", MessageDialog.WARNING, new String[] {"OK"}, 0); + } else { + creator.setUser(true); + creator.schedule(); + creator.addJobChangeListener(new JobChangeAdapter() { + @Override + public void done(final IJobChangeEvent event) { + if (event.getResult() == Status.OK_STATUS) { + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + Visualization.showViz(); + } + }); + } + } + }); + } + return null; + } + +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/ContextualViewRefreshHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/ContextualViewRefreshHandler.java new file mode 100644 index 00000000..f09b7f30 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/ContextualViewRefreshHandler.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.command; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; + +import eu.modelwriter.marker.ui.internal.views.contextualview.ContextualView; + +public class ContextualViewRefreshHandler extends AbstractHandler { + public static String COMMAND_ID = "eu.modelwriter.marker.command.contextualviewrefresh"; + + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + ContextualView.refreshTree(); + return true; + } + +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/CountMarkersInFileHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/CountMarkersInFileHandler.java new file mode 100644 index 00000000..24f3c4e5 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/CountMarkersInFileHandler.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.command; + +import java.util.List; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ITreeSelection; + +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class CountMarkersInFileHandler extends AbstractHandler { + public static String COMMAND_ID = "eu.modelwriter.marker.command.countforfile"; + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + ISelection sel = Activator.getDefault().getWorkbench().getActiveWorkbenchWindow() + .getSelectionService().getSelection(); + if (sel instanceof ITreeSelection) { + ITreeSelection treeSel = (ITreeSelection) sel; + if (treeSel.getFirstElement() instanceof IFile) { + IFile file = (IFile) treeSel.getFirstElement(); + List markers = MarkerFactory.findMarkers(file); + MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), "Marker Count", null, + markers.size() + " marker(s)", MessageDialog.INFORMATION, new String[] {"OK"}, 0); + dialog.open(); + } + } + return null; + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/CountMarkersInResourceHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/CountMarkersInResourceHandler.java new file mode 100644 index 00000000..c7efbe51 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/CountMarkersInResourceHandler.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.command; + +import java.util.List; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.jdt.core.IOpenable; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ITreeSelection; + +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class CountMarkersInResourceHandler extends AbstractHandler { + public static String COMMAND_ID = "eu.modelwriter.marker.command.countforresource"; + + public CountMarkersInResourceHandler() { + super(); + } + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + ISelection selection = MarkerFactory.getSelection(); + if (selection instanceof ITreeSelection) { + ITreeSelection treeSelection = (ITreeSelection) selection; + if (treeSelection.getFirstElement() instanceof IOpenable + || treeSelection.getFirstElement() instanceof IFile) { + IResource resource = + ((IAdaptable) treeSelection.getFirstElement()).getAdapter(IResource.class); + List markers = MarkerFactory.findMarkers(resource); + MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), "Marker Count", null, + markers.size() + " marker(s)", MessageDialog.INFORMATION, new String[] {"OK"}, 0); + dialog.open(); + } + } + return null; + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/DeleteAllHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/DeleteAllHandler.java new file mode 100644 index 00000000..6067fa7b --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/DeleteAllHandler.java @@ -0,0 +1,226 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.command; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.presentation.EcoreEditor; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ITreeSelection; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.part.MultiPageEditorPart; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; +import eu.modelwriter.marker.ui.internal.wizards.selectionwizard.SelectionWizard; + +public class DeleteAllHandler extends AbstractHandler { + public static String COMMAND_ID = "eu.modelwriter.marker.command.deleteall"; + + IEditorPart editor; + IFile file; + ISelection selection; + private ArrayList candidateToTypeChanging; + + private void deleteFromAlloyXML(final IMarker beDeleted) { + AlloyUtilities.removeMarkerFromRepository(beDeleted); + if (MarkUtilities.getGroupId(beDeleted) == null + || MarkUtilities.getLeaderId(beDeleted) != null) { + AlloyUtilities.removeTypeFromMarker(beDeleted); + AlloyUtilities.removeRelationOfMarker(beDeleted); + } + } + + private void deleteMarkers() { + this.editor = + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + this.file = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() + .getActiveEditor().getEditorInput().getAdapter(IFile.class); + this.selection = + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection(); + + try { + final IMarker beDeleted = this.getMarker(); + if (beDeleted != null && beDeleted.exists()) { + final MessageDialog warningDialog = + new MessageDialog(MarkerActivator.getShell(), "Warning!", null, + "If you delete markers, all relations of these markers has been removed! Do you want to continue to delete markers?", + MessageDialog.WARNING, new String[] {"YES", "NO"}, 0); + if (warningDialog.open() != 0) { + return; + } + + this.findCandidateToTypeChangingMarkers(beDeleted); + final String sourceIdOfSelectedMarker = MarkUtilities.getSourceId(beDeleted); + + for (final IMarker iMarker : this.candidateToTypeChanging) { + AnnotationFactory.convertAnnotationType(iMarker, true, + MarkUtilities.compare(MarkUtilities.getSourceId(iMarker), sourceIdOfSelectedMarker), + AlloyUtilities.getTotalTargetCount(iMarker)); + } + final String markerText = MarkUtilities.getText(beDeleted); + + if (MarkUtilities.getGroupId(beDeleted) != null) { + final String markerGroupId = MarkUtilities.getGroupId(beDeleted); + final List markers = + MarkerFactory.findMarkersByGroupId(this.file, markerGroupId); + + for (int i = markers.size() - 1; i >= 0; i--) { + this.deleteFromAlloyXML(markers.get(i)); + AnnotationFactory.removeAnnotation(markers.get(i)); + markers.get(i).delete(); + } + } else { + this.deleteFromAlloyXML(beDeleted); + AnnotationFactory.removeAnnotation(beDeleted); + beDeleted.delete(); + } + final MessageDialog dialog = + new MessageDialog(MarkerActivator.getShell(), "Mark will be deleted by this wizard", + null, "\"" + markerText + "\" has been selected to be unmarked", + MessageDialog.INFORMATION, new String[] {"OK"}, 0); + dialog.open(); + } + + } catch (final CoreException e) { + e.printStackTrace(); + } + } + + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + this.candidateToTypeChanging = new ArrayList(); + this.deleteMarkers(); + this.refresh(); + if (AlloyUtilities.isExists()) { + this.candidateToTypeChanging = new ArrayList(); + this.deleteMarkers(); + this.refresh(); + } else { + final MessageDialog infoDialog = new MessageDialog(MarkerActivator.getShell(), + "System Information", null, "You dont have any registered alloy file to system.", + MessageDialog.INFORMATION, new String[] {"OK"}, 0); + infoDialog.open(); + } + return null; + } + + /** + * @param selectedMarker from text + */ + private void findCandidateToTypeChangingMarkers(final IMarker selectedMarker) { + final Map fieldsSources = + AlloyUtilities.getRelationsOfSecondSideMarker(selectedMarker); + final ArrayList relationsSources = + AlloyUtilities.getSourcesOfMarkerAtRelations(selectedMarker); + + for (final IMarker iMarker : fieldsSources.keySet()) { + this.candidateToTypeChanging.add(iMarker); + } + + for (final IMarker iMarker : relationsSources) { + this.candidateToTypeChanging.add(iMarker); + } + } + + private IMarker getMarker() { + IMarker beDeleted = null; + if (this.selection instanceof ITextSelection) { + final TextSelection textSelection = (TextSelection) this.selection; + + final ArrayList markerList = + MarkerFactory.findMarkersInSelection(this.file, textSelection); + if (markerList != null) { + if (markerList.size() == 1) { + beDeleted = markerList.get(0); + } else if (markerList.size() > 1) { + final SelectionWizard selectionWizard = new SelectionWizard(markerList); + final WizardDialog selectionDialog = + new WizardDialog(MarkerActivator.getShell(), selectionWizard); + if (selectionDialog.open() == 1) { + return null; + } + beDeleted = selectionWizard.getSelectedMarker(); + } + } + } else if (this.selection instanceof ITreeSelection) { + final ITreeSelection treeSelection = (ITreeSelection) this.selection; + if (this.selection != null && this.editor instanceof EcoreEditor) { + if (this.selection != null + && ((ITreeSelection) this.selection).getFirstElement() instanceof IMarker) { + beDeleted = (IMarker) ((ITreeSelection) this.selection).getFirstElement(); + } else if (treeSelection.getFirstElement() instanceof ENamedElement + && ((ENamedElement) treeSelection.getFirstElement()).getName() != null + && !((ENamedElement) treeSelection.getFirstElement()).getName().isEmpty()) { + + final URI uri = EcoreUtil.getURI((ENamedElement) treeSelection.getFirstElement()); + + beDeleted = MarkerFactory.findMarkersByUri(this.file, uri.toString()); + } else if (!((EObject) treeSelection.getFirstElement() instanceof EModelElement)) { + final URI uri = EcoreUtil.getURI((EObject) treeSelection.getFirstElement()); + beDeleted = MarkerFactory.findMarkersByUri(this.file, uri.toString()); + } + } + } + return beDeleted; + } + + private void refresh() { + ITextEditor iteEditor = null; + if (this.editor instanceof EcoreEditor) { + final EcoreEditor ecEditor = (EcoreEditor) this.editor; + ecEditor.getViewer().refresh(); + } else { + if (this.editor instanceof ITextEditor) { + iteEditor = (ITextEditor) this.editor; + } else { + final MultiPageEditorPart mpepEditor = (MultiPageEditorPart) this.editor; + final IEditorPart[] editors = mpepEditor.findEditors(mpepEditor.getEditorInput()); + iteEditor = (ITextEditor) editors[0]; + } + final IDocumentProvider idp = iteEditor.getDocumentProvider(); + try { + idp.resetDocument(iteEditor.getEditorInput()); + } catch (final CoreException e) { + e.printStackTrace(); + } + } + MarkerFactory.refreshProjectExp(); + if (Activator.getDefault().getWorkbench().getWorkbenchWindows()[0].getActivePage() + .findView(Visualization.ID) != null) { + Visualization.showViz(); + } + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/DeleteAllTraceElementsHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/DeleteAllTraceElementsHandler.java new file mode 100644 index 00000000..f9373236 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/DeleteAllTraceElementsHandler.java @@ -0,0 +1,92 @@ +package eu.modelwriter.marker.command; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.emf.ecore.presentation.EcoreEditor; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.part.MultiPageEditorPart; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; + +import eu.modelwriter.configuration.alloy.reasoning.AlloyOtherSolutionReasoning; +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; + +public class DeleteAllTraceElementsHandler extends AbstractHandler { + public static String COMMAND_ID = "eu.modelwriter.marker.command.deleteAllTraceElements"; + + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + final MessageDialog warningDialog = new MessageDialog(MarkerActivator.getShell(), "Warning!", + null, "You are about to delete all markers! Do you want to continue?", + MessageDialog.WARNING, new String[] {"Yes", "No"}, 0); + if (warningDialog.open() != 0) { + return null; + } + + if (AlloyUtilities.isExists()) { + AlloyOtherSolutionReasoning.getInstance().finish(); + + AlloyUtilities.clearRepository(); + AlloyUtilities.clearRelation(); + AlloyUtilities.clearSigs(); + AlloyUtilities.clearFields(); + + try { + ResourcesPlugin.getWorkspace().getRoot().deleteMarkers(MarkerFactory.MARKER_MARKING, true, + IResource.DEPTH_INFINITE); + } catch (final CoreException e) { + e.printStackTrace(); + } + + refreshActiveEditor(); + } else { + final MessageDialog infoDialog = new MessageDialog(MarkerActivator.getShell(), + "System Information", null, "You dont have any registered alloy file to system.", + MessageDialog.INFORMATION, new String[] {"OK"}, 0); + infoDialog.open(); + } + return null; + } + + private void refreshActiveEditor() { + IEditorPart editor = Activator.getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + if (editor == null) { + return; + } + + ITextEditor iteEditor = null; + if (editor instanceof EcoreEditor) { + final EcoreEditor ecEditor = (EcoreEditor) editor; + ecEditor.getViewer().refresh(); + } else { + if (editor instanceof ITextEditor) { + iteEditor = (ITextEditor) editor; + } else if (editor instanceof MultiPageEditorPart) { + final MultiPageEditorPart mpepEditor = (MultiPageEditorPart) editor; + final IEditorPart[] editors = mpepEditor.findEditors(mpepEditor.getEditorInput()); + iteEditor = (ITextEditor) editors[0]; + } + if (iteEditor != null) { + final IDocumentProvider idp = iteEditor.getDocumentProvider(); + try { + idp.resetDocument(iteEditor.getEditorInput()); + } catch (final CoreException e) { + e.printStackTrace(); + } + } + } + MarkerFactory.refreshProjectExp(); + if (Activator.getDefault().getWorkbench().getWorkbenchWindows()[0].getActivePage() + .findView(Visualization.ID) != null) { + Visualization.showViz(); + } + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/DeleteHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/DeleteHandler.java new file mode 100644 index 00000000..45c075b5 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/DeleteHandler.java @@ -0,0 +1,242 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.command; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.presentation.EcoreEditor; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ITreeSelection; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.part.MultiPageEditorPart; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; + +import eu.modelwriter.configuration.alloy.reasoning.AlloyOtherSolutionReasoning; +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; +import eu.modelwriter.marker.ui.internal.wizards.selectionwizard.SelectionWizard; + +@SuppressWarnings("restriction") +public class DeleteHandler extends AbstractHandler { + public static String COMMAND_ID = "eu.modelwriter.marker.command.delete"; + IEditorPart editor; + IFile file; + ISelection selection; + IMarker marker; + private ArrayList candidateToTypeChanging; + + private void checkImpactAndChangedMechanism(final IMarker beDeleted) { + if (MarkUtilities.getType(beDeleted) != null) { + final Map sourceRelationsOfDeleted = + AlloyUtilities.getRelationsOfSecondSideMarker(beDeleted); + for (final IMarker targetMarker : sourceRelationsOfDeleted.keySet()) { + if (AlloyUtilities.getRelationsOfFirstSideMarker(targetMarker).size() == 1) { + AlloyUtilities.unsetChanged(targetMarker); + } + } + } + } + + private void deleteFromAlloyXML(final IMarker beDeleted) { + checkImpactAndChangedMechanism(beDeleted); + AlloyUtilities.removeMarkerFromRepository(beDeleted); + if (MarkUtilities.getGroupId(beDeleted) == null + || MarkUtilities.getLeaderId(beDeleted) != null) { + AlloyUtilities.removeTypeFromMarker(beDeleted); + AlloyUtilities.removeRelationOfMarker(beDeleted); + } + } + + private void deleteMarker() { + try { + if (marker != null && marker.exists()) { + final MessageDialog warningDialog = + new MessageDialog(MarkerActivator.getShell(), "Warning!", null, + "If you delete marker, all relations of this marker has been removed! Do you want to continue to delete marker?", + MessageDialog.WARNING, new String[] {"YES", "NO"}, 0); + if (warningDialog.open() != 0) { + return; + } + + findCandidateToTypeChangingMarkers(marker); + final String sourceIdOfSelectedMarker = MarkUtilities.getSourceId(marker); + + for (final IMarker iMarker : candidateToTypeChanging) { + AnnotationFactory.convertAnnotationType(iMarker, true, + MarkUtilities.compare(MarkUtilities.getSourceId(iMarker), sourceIdOfSelectedMarker), + AlloyUtilities.getTotalTargetCount(iMarker)); + } + final String markerText = MarkUtilities.getText(marker); + + if (MarkUtilities.getLeaderId(marker) != null) { + final String markerGroupId = MarkUtilities.getGroupId(marker); + final List markers = MarkerFactory.findMarkersByGroupId(file, markerGroupId); + + for (int i = markers.size() - 1; i >= 0; i--) { + deleteFromAlloyXML(markers.get(i)); + AnnotationFactory.removeAnnotation(markers.get(i)); + markers.get(i).delete(); + } + } else { + deleteFromAlloyXML(marker); + AnnotationFactory.removeAnnotation(marker); + marker.delete(); + } + final MessageDialog dialog = + new MessageDialog(MarkerActivator.getShell(), "Mark will be deleted by this wizard", + null, "\"" + markerText + "\" has been selected to be unmarked", + MessageDialog.INFORMATION, new String[] {"OK"}, 0); + dialog.open(); + } + } catch (final CoreException e) { + e.printStackTrace(); + } + } + + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + AlloyOtherSolutionReasoning.getInstance().finish(); + + if (AlloyUtilities.isExists()) { + candidateToTypeChanging = new ArrayList(); + file = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor() + .getEditorInput().getAdapter(IFile.class); + selection = + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection(); + editor = + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + marker = getMarkerFromEditor(); + + deleteMarker(); + refresh(); + } else { + final MessageDialog infoDialog = new MessageDialog(MarkerActivator.getShell(), + "System Information", null, "You dont have any registered alloy file to system.", + MessageDialog.INFORMATION, new String[] {"OK"}, 0); + infoDialog.open(); + } + return null; + } + + /** + * @param selectedMarker from text + */ + private void findCandidateToTypeChangingMarkers(final IMarker selectedMarker) { + final Map fieldsSources = + AlloyUtilities.getRelationsOfSecondSideMarker(selectedMarker); + final ArrayList relationsSources = + AlloyUtilities.getSourcesOfMarkerAtRelations(selectedMarker); + + for (final IMarker iMarker : fieldsSources.keySet()) { + candidateToTypeChanging.add(iMarker); + } + + for (final IMarker iMarker : relationsSources) { + candidateToTypeChanging.add(iMarker); + } + } + + private IMarker getMarkerFromEditor() { + IMarker beDeleted = null; + if (selection != null) { + if (selection instanceof ITextSelection) { + final TextSelection textSelection = (TextSelection) selection; + + final ArrayList markerList = + MarkerFactory.findMarkersInSelection(file, textSelection); + if (markerList != null) { + if (markerList.size() == 1) { + beDeleted = markerList.get(0); + } else if (markerList.size() > 1) { + final SelectionWizard selectionWizard = new SelectionWizard(markerList); + final WizardDialog selectionDialog = + new WizardDialog(MarkerActivator.getShell(), selectionWizard); + if (selectionDialog.open() == 1) { + return null; + } + beDeleted = selectionWizard.getSelectedMarker(); + } + } + } else if (selection instanceof ITreeSelection) { + final ITreeSelection treeSelection = (ITreeSelection) selection; + if (((ITreeSelection) selection).getFirstElement() instanceof IMarker) { + beDeleted = (IMarker) ((ITreeSelection) selection).getFirstElement(); + } else if (editor instanceof EcoreEditor) { + if (treeSelection.getFirstElement() instanceof ENamedElement + && ((ENamedElement) treeSelection.getFirstElement()).getName() != null + && !((ENamedElement) treeSelection.getFirstElement()).getName().isEmpty()) { + + final URI uri = EcoreUtil.getURI((ENamedElement) treeSelection.getFirstElement()); + + beDeleted = MarkerFactory.findMarkersByUri(file, uri.toString()); + } else if (!((EObject) treeSelection.getFirstElement() instanceof EModelElement)) { + final URI uri = EcoreUtil.getURI((EObject) treeSelection.getFirstElement()); + beDeleted = MarkerFactory.findMarkersByUri(file, uri.toString()); + } + } else if (editor instanceof CompilationUnitEditor) { + beDeleted = MarkerFactory.findMarkerByOutlineTreeSelection(treeSelection, file); + } + } + } + return beDeleted; + } + + private void refresh() { + ITextEditor iteEditor = null; + if (editor instanceof EcoreEditor) { + final EcoreEditor ecEditor = (EcoreEditor) editor; + ecEditor.getViewer().refresh(); + } else { + if (editor instanceof ITextEditor) { + iteEditor = (ITextEditor) editor; + } else { + final MultiPageEditorPart mpepEditor = (MultiPageEditorPart) editor; + final IEditorPart[] editors = mpepEditor.findEditors(mpepEditor.getEditorInput()); + iteEditor = (ITextEditor) editors[0]; + } + final IDocumentProvider idp = iteEditor.getDocumentProvider(); + try { + idp.resetDocument(iteEditor.getEditorInput()); + } catch (final CoreException e) { + e.printStackTrace(); + } + } + MarkerFactory.refreshProjectExp(); + if (Activator.getDefault().getWorkbench().getWorkbenchWindows()[0].getActivePage() + .findView(Visualization.ID) != null) { + Visualization.showViz(); + } + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/EmfToAlloyHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/EmfToAlloyHandler.java new file mode 100644 index 00000000..eac11147 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/EmfToAlloyHandler.java @@ -0,0 +1,35 @@ +package eu.modelwriter.marker.command; + +import java.io.IOException; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IFile; +import org.eclipse.jface.dialogs.MessageDialog; + +import eu.modelwriter.configuration.emf2alloy.EMFToAlloy; +import eu.modelwriter.marker.MarkerActivator; + +public class EmfToAlloyHandler extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + try { + IFile file = AlloyParseUtil.getSelectedFile(); + if (file != null) { + EMFToAlloy emfToAlloy = new EMFToAlloy(file); + emfToAlloy.start(); + } + } catch (IOException e) { + final MessageDialog warningdialog = + new MessageDialog(MarkerActivator.getShell(), "Alloy Example To EMF", null, + e.getMessage(), MessageDialog.WARNING, new String[] {"OK"}, 0); + if (warningdialog.open() != 0) { + return null; + } + e.printStackTrace(); + } + return null; + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/LoadSpecificationFromEditorHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/LoadSpecificationFromEditorHandler.java new file mode 100644 index 00000000..2f9aecdc --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/LoadSpecificationFromEditorHandler.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.command; + +import org.eclipse.core.resources.IFile; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.ide.ResourceUtil; + +public class LoadSpecificationFromEditorHandler extends LoadSpecificationHandler { + @Override + public String getFilePath() { + IEditorPart editor; + editor = Activator.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage() + .getActiveEditor(); + String result = null; + final IFile file = ResourceUtil.getFile(editor.getEditorInput()); + result = file.getLocation().makeAbsolute().toOSString(); + return result; + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/LoadSpecificationFromFileSystemHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/LoadSpecificationFromFileSystemHandler.java new file mode 100644 index 00000000..9e87bbfc --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/LoadSpecificationFromFileSystemHandler.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.command; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.FileDialog; + +import eu.modelwriter.marker.MarkerActivator; + +public class LoadSpecificationFromFileSystemHandler extends LoadSpecificationHandler { + @Override + public String getFilePath() { + final String result; + final FileDialog dialog = new FileDialog(MarkerActivator.getShell(), SWT.OPEN); + dialog.setFilterExtensions(new String[] {"*.mw", "*.als"}); + result = dialog.open(); + if (result == null) { + return null; + } + return result; + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/LoadSpecificationFromProjectExplorerHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/LoadSpecificationFromProjectExplorerHandler.java new file mode 100644 index 00000000..128f0c29 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/LoadSpecificationFromProjectExplorerHandler.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.command; + +import org.eclipse.core.resources.IFile; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.ui.PlatformUI; + +public class LoadSpecificationFromProjectExplorerHandler extends LoadSpecificationHandler { + @Override + public String getFilePath() { + String result = null; + final ISelection selection = + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection(); + if (selection != null && selection instanceof TreeSelection) { + final TreeSelection treeSelection = (TreeSelection) selection; + final IFile file = (IFile) treeSelection.getFirstElement(); + result = file.getLocation().makeAbsolute().toOSString(); + } + return result; + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/LoadSpecificationHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/LoadSpecificationHandler.java new file mode 100644 index 00000000..4d205d91 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/LoadSpecificationHandler.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.command; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.dialogs.MessageDialog; + +import eu.modelwriter.configuration.alloy.trace.TraceException; +import eu.modelwriter.configuration.alloy.trace.TraceManager; +import eu.modelwriter.marker.MarkerActivator; + +public abstract class LoadSpecificationHandler extends AbstractHandler { + public static String COMMAND_ID = "eu.modelwriter.marker.command.parsealloy"; + + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + final MessageDialog warningdialog = + new MessageDialog(MarkerActivator.getShell(), "Mark Information", null, + "If new alloy file will be parsed , your all marker type will be lost !", + MessageDialog.WARNING, new String[] {"OK", "Cancel"}, 0); + if (warningdialog.open() != 0) { + return null; + } + + final String filePath = getFilePath(); + if (filePath == null) { + return null; + } + AlloyParseUtil.parse(filePath); + + try { + TraceManager.get().loadSpec(filePath); + } catch (final TraceException e) { + e.printStackTrace(); + } + return null; + } + + protected abstract String getFilePath(); +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MappingHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MappingHandler.java new file mode 100644 index 00000000..658933d7 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MappingHandler.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.command; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.dialogs.MessageDialog; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; +import eu.modelwriter.marker.ui.internal.wizards.mappingwizard.MarkerMapping; + +public class MappingHandler extends AbstractHandler { + public static String COMMAND_ID = "eu.modelwriter.marker.command.map"; + + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + if (AlloyUtilities.isExists()) { + MarkerMapping.getInstance().runWithSelection(); + if (Activator.getDefault().getWorkbench().getWorkbenchWindows()[0].getActivePage() + .findView(Visualization.ID) != null) { + Visualization.showViz(); + } + } else { + final MessageDialog infoDialog = new MessageDialog(MarkerActivator.getShell(), + "System Information", null, "You dont have any registered alloy file to system.", + MessageDialog.INFORMATION, new String[] {"OK"}, 0); + infoDialog.open(); + } + return null; + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MarkAllHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MarkAllHandler.java new file mode 100644 index 00000000..18e300e0 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MarkAllHandler.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.command; + +import java.util.UUID; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.PlatformUI; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class MarkAllHandler extends AbstractHandler { + public static String COMMAND_ID = "eu.modelwriter.marker.command.markall"; + + IEditorPart editor; + IFile file; + ISelection selection; + + private void addToAlloyXML(IMarker beAdded) { + AlloyUtilities.addMarkerToRepository(beAdded); + } + + private void createMarkers() { + this.editor = + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + this.file = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() + .getActiveEditor().getEditorInput().getAdapter(IFile.class); + this.selection = + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection(); + + ITextSelection textSelection = (ITextSelection) this.selection; + + if (MarkerFactory.findMarkerWithAbsolutePosition(this.file, textSelection.getOffset(), + textSelection.getOffset() + textSelection.getLength()) != null) { + + MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), "Mark Information", null, + "In these area, there is already a marker", MessageDialog.WARNING, new String[] {"OK"}, + 0); + dialog.open(); + } else { + String content = MarkerFactory.getCurrentEditorContent(); + int index = 0; + int offset = 0; + int length = textSelection.getLength(); + String id = UUID.randomUUID().toString(); + String leader_id = UUID.randomUUID().toString(); + + if (length != 0) { + while ((offset = + content.toLowerCase().indexOf(textSelection.getText().toLowerCase(), index)) != -1) { + TextSelection nextSelection = + new TextSelection(MarkerFactory.getDocument(), offset, length); + if (MarkerFactory.findMarkerWithAbsolutePosition(this.file, offset, + offset + length) == null) { + IMarker mymarker = MarkerFactory.createMarker(this.file, nextSelection); + MarkUtilities.setGroupId(mymarker, id); + if (textSelection.getOffset() == offset) { + MarkUtilities.setLeaderId(mymarker, leader_id); + } + AnnotationFactory.addAnnotation(mymarker, AnnotationFactory.ANNOTATION_MARKING); + this.addToAlloyXML(mymarker); + } + index = offset + length; + } + // MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), + // "Mark Information will be provided by this wizard.", null, + // "\"" + textSelection.getText() + "\" has been selected to be marked", + // MessageDialog.INFORMATION, new String[] {"OK"}, 0); + // dialog.open(); + } else { + MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), + "Mark Information will be provided by this wizard.", null, + "Please select a valid information", MessageDialog.INFORMATION, new String[] {"OK"}, 0); + dialog.open(); + } + } + } + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + if (AlloyUtilities.isExists()) { + this.createMarkers(); + this.refresh(); + } else { + MessageDialog infoDialog = new MessageDialog(MarkerActivator.getShell(), "System Information", + null, "You dont have any registered alloy file to system.", MessageDialog.INFORMATION, + new String[] {"OK"}, 0); + infoDialog.open(); + } + return null; + } + + private void refresh() { + MarkerFactory.refreshProjectExp(); + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MarkAllInWorkspaceHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MarkAllInWorkspaceHandler.java new file mode 100644 index 00000000..bad41711 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MarkAllInWorkspaceHandler.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.command; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IFile; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.ui.PlatformUI; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.marker.ui.internal.wizards.markallinwswizard.MarkAllInWsWizard; + +public class MarkAllInWorkspaceHandler extends AbstractHandler { + public static String COMMAND_ID = "eu.modelwriter.marker.command.markallinworkspace"; + + IFile file; + ISelection selection; + + private void createMarkersWs() { + ITextSelection textSelection = (ITextSelection) this.selection; + if (MarkerFactory.findMarkerWithAbsolutePosition(this.file, textSelection.getOffset(), + textSelection.getOffset() + textSelection.getLength()) != null) { + MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), "Mark Information", null, + "In these area, there is already a marker", MessageDialog.WARNING, new String[] {"OK"}, + 0); + dialog.open(); + return; + } else { + MarkAllInWsWizard markAllWsWizard = new MarkAllInWsWizard(textSelection, this.file); + WizardDialog selectionDialog = new WizardDialog(MarkerActivator.getShell(), markAllWsWizard); + selectionDialog.open(); + } + } + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + if (AlloyUtilities.isExists()) { + this.file = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() + .getActiveEditor().getEditorInput().getAdapter(IFile.class); + this.selection = + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection(); + + this.createMarkersWs(); + this.refresh(); + } else { + MessageDialog infoDialog = new MessageDialog(MarkerActivator.getShell(), "System Information", + null, "You dont have any registered alloy file to system.", MessageDialog.INFORMATION, + new String[] {"OK"}, 0); + infoDialog.open(); + } + return null; + } + + private void refresh() { + MarkerFactory.refreshProjectExp(); + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MarkHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MarkHandler.java new file mode 100644 index 00000000..c91454b0 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MarkHandler.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.command; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.presentation.EcoreEditor; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ITreeSelection; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.PlatformUI; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class MarkHandler extends AbstractHandler { + public static String COMMAND_ID = "eu.modelwriter.marker.command.mark"; + + IEditorPart editor; + IFile file; + ISelection selection; + + private void addToAlloyXML(final IMarker beAdded) { + AlloyUtilities.addMarkerToRepository(beAdded); + } + + private void createMarker() { + editor = + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + file = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() + .getActiveEditor().getEditorInput().getAdapter(IFile.class); + selection = + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection(); + + final IMarker beAdded = getMarker(); + @SuppressWarnings("unused") + String text = ""; + if (selection instanceof ITextSelection) { + if (beAdded != null && beAdded.exists()) { + text = ((ITextSelection) selection).getText(); + AnnotationFactory.addAnnotation(beAdded, AnnotationFactory.ANNOTATION_MARKING); + } + } else if (selection instanceof ITreeSelection) { + if (editor instanceof EcoreEditor) { + final ITreeSelection treeSelection = (ITreeSelection) selection; + if (beAdded != null && beAdded.exists()) { + if (treeSelection.getFirstElement() instanceof EModelElement) { + text = ((ENamedElement) treeSelection.getFirstElement()).getName(); + } else { + text = MarkUtilities.getText(beAdded); + } + } + } + } + + addToAlloyXML(beAdded); + + // MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), "Mark Information", + // null, + // "\"" + text + "\" has been selected to be marked", MessageDialog.INFORMATION, + // new String[] {"OK"}, 0); + // dialog.open(); + } + + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + if (AlloyUtilities.isExists()) { + createMarker(); + refresh(); + } else { + final MessageDialog infoDialog = new MessageDialog(MarkerActivator.getShell(), + "System Information", null, "You dont have any registered alloy file to system.", + MessageDialog.INFORMATION, new String[] {"OK"}, 0); + infoDialog.open(); + } + return null; + } + + private IMarker getMarker() { + IMarker beAdded = null; + if (selection instanceof ITextSelection) { + beAdded = MarkerFactory.createMarker(file, (ITextSelection) selection); + } else if (selection instanceof ITreeSelection) { + final ITreeSelection treeSelection = (ITreeSelection) selection; + beAdded = MarkerFactory.createMarker(file, treeSelection); + } + + return beAdded; + } + + private void refresh() { + MarkerFactory.refreshProjectExp(); + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MarkWithTypeHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MarkWithTypeHandler.java new file mode 100644 index 00000000..1d33053f --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MarkWithTypeHandler.java @@ -0,0 +1,149 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.command; + +import java.util.ArrayList; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.presentation.EcoreEditor; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ITreeSelection; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.PlatformUI; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; +import eu.modelwriter.marker.ui.internal.wizards.markerwizard.MarkerPage; +import eu.modelwriter.marker.ui.internal.wizards.markerwizard.MarkerWizard; +import eu.modelwriter.marker.ui.internal.wizards.selectionwizard.SelectionWizard; + +@SuppressWarnings("restriction") +public class MarkWithTypeHandler extends AbstractHandler { + public static String COMMAND_ID = "eu.modelwriter.marker.command.markwithtype"; + + IEditorPart editor; + IFile file; + ISelection selection; + + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + if (AlloyUtilities.isExists()) { + return markWithType(); + } else { + final MessageDialog infoDialog = new MessageDialog(MarkerActivator.getShell(), + "System Information", null, "You dont have any registered alloy file to system.", + MessageDialog.INFORMATION, new String[] {"OK"}, 0); + infoDialog.open(); + } + return null; + } + + private IMarker getMarker() { + IMarker selectedMarker = null; + if (selection != null) { + if (selection instanceof ITextSelection) { + final TextSelection textSelection = (TextSelection) selection; + + final ArrayList markerList = + MarkerFactory.findMarkersInSelection(file, textSelection); + if (markerList != null) { + if (markerList.size() == 1) { + selectedMarker = markerList.get(0); + } else if (markerList.size() > 1) { + final SelectionWizard selectionWizard = new SelectionWizard(markerList); + final WizardDialog selectionDialog = + new WizardDialog(MarkerActivator.getShell(), selectionWizard); + if (selectionDialog.open() == 1) { + return null; + } + selectedMarker = selectionWizard.getSelectedMarker(); + } + } + } else if (selection instanceof ITreeSelection) { + final ITreeSelection treeSelection = (ITreeSelection) selection; + if (((ITreeSelection) selection).getFirstElement() instanceof IMarker) { + selectedMarker = (IMarker) ((ITreeSelection) selection).getFirstElement(); + } else if (editor instanceof EcoreEditor) { + if (treeSelection.getFirstElement() instanceof ENamedElement + && ((ENamedElement) treeSelection.getFirstElement()).getName() != null + && !((ENamedElement) treeSelection.getFirstElement()).getName().isEmpty()) { + + final URI uri = EcoreUtil.getURI((ENamedElement) treeSelection.getFirstElement()); + + selectedMarker = MarkerFactory.findMarkersByUri(file, uri.toString()); + } else if (!((EObject) treeSelection.getFirstElement() instanceof EModelElement)) { + final URI uri = EcoreUtil.getURI((EObject) treeSelection.getFirstElement()); + selectedMarker = MarkerFactory.findMarkersByUri(file, uri.toString()); + } + } else if (editor instanceof CompilationUnitEditor) { + selectedMarker = MarkerFactory.findMarkerByOutlineTreeSelection(treeSelection, file); + } + } + } + return selectedMarker; + } + + private Object markWithType() { + file = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor() + .getEditorInput().getAdapter(IFile.class); + selection = + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection(); + editor = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + + if (!MarkerPage.isParsed()) { + final MessageDialog dialog = + new MessageDialog(MarkerActivator.getShell(), "Type Information", null, + "You dont have any marker type registered to system! \n" + + "Please parse an alloy file first", + MessageDialog.INFORMATION, new String[] {"OK"}, 0); + dialog.open(); + return null; + } + + final IMarker selectedMarker = getMarker(); + if (selectedMarker != null) { + final MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), "Mark Information", + null, "In these area, there is already a marker", MessageDialog.WARNING, + new String[] {"OK"}, 0); + dialog.open(); + return null; + } else if (selection instanceof ITextSelection + && ((ITextSelection) selection).getLength() == 0) { + final MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), "Mark Information", + null, "Please make a valid selection", MessageDialog.WARNING, new String[] {"OK"}, 0); + dialog.open(); + return null; + } + + final MarkerWizard markerWizard = new MarkerWizard(selection, file); + final WizardDialog dialog = new WizardDialog(MarkerActivator.getShell(), markerWizard); + dialog.open(); + + Visualization.showViz(); + return null; + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MarkerVisibilityHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MarkerVisibilityHandler.java new file mode 100644 index 00000000..93ea5b3e --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MarkerVisibilityHandler.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.command; + +import java.util.Map; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.ui.IDecoratorManager; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.commands.IElementUpdater; +import org.eclipse.ui.editors.text.EditorsUI; +import org.eclipse.ui.menus.UIElement; +import org.eclipse.ui.texteditor.AnnotationPreference; + +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class MarkerVisibilityHandler extends AbstractHandler implements IElementUpdater { + + public static String COMMAND_ID = "eu.modelwriter.marker.command.markervisibility"; + + private final AnnotationPreference prefMapping = EditorsUI.getAnnotationPreferenceLookup() + .getAnnotationPreference(AnnotationFactory.ANNOTATION_MAPPING); + + private final AnnotationPreference prefMarking = EditorsUI.getAnnotationPreferenceLookup() + .getAnnotationPreference(AnnotationFactory.ANNOTATION_MARKING); + + private final IPreferenceStore store = EditorsUI.getPreferenceStore(); + + private boolean isHidden; + + private IDecoratorManager decoratorManager; + + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + this.decoratorManager = Activator.getDefault().getWorkbench().getDecoratorManager(); + + if (!this.isHidden) { + this.isHidden = true; + this.setStore(false); + this.setDecorator(false); + } else { + this.isHidden = false; + this.setStore(true); + this.setDecorator(true); + } + this.store.needsSaving(); + + final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + final ICommandService commandService = window.getService(ICommandService.class); + if (commandService != null) { + commandService.refreshElements(COMMAND_ID, null); + } + return null; + } + + private void setDecorator(final boolean state) { + try { + this.decoratorManager.setEnabled(MarkerFactory.ECORE_DECORATOR, state); + this.decoratorManager.setEnabled(MarkerFactory.FILE_DECORATOR, state); + } catch (final CoreException e) { + e.printStackTrace(); + } + } + + private void setStore(final boolean state) { + this.store.setValue(this.prefMarking.getOverviewRulerPreferenceKey(), state); + this.store.setValue(this.prefMarking.getVerticalRulerPreferenceKey(), state); + this.store.setValue(this.prefMarking.getTextPreferenceKey(), state); + this.store.setValue(this.prefMapping.getOverviewRulerPreferenceKey(), state); + this.store.setValue(this.prefMapping.getVerticalRulerPreferenceKey(), state); + this.store.setValue(this.prefMapping.getTextPreferenceKey(), state); + if (state) { + this.store.setValue(this.prefMarking.getColorPreferenceKey(), "0,0,255"); + this.store.setValue(this.prefMapping.getColorPreferenceKey(), "255,0,0"); + } + } + + @Override + public void updateElement(final UIElement element, + @SuppressWarnings("rawtypes") final Map parameters) { + // are trace elements visible or not? determine and handle the action. + this.isHidden = !this.store.getBoolean(this.prefMarking.getTextPreferenceKey()); + if (!this.isHidden) { + element.setText("Hide Trace Elements"); + } else { + element.setText("Show Trace Elements"); + } + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MasterViewDeleteHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MasterViewDeleteHandler.java new file mode 100644 index 00000000..0158f434 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/MasterViewDeleteHandler.java @@ -0,0 +1,129 @@ +package eu.modelwriter.marker.command; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ITreeSelection; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.ui.IWorkbenchWindow; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class MasterViewDeleteHandler extends AbstractHandler { + + public static String COMMAND_ID = "eu.modelwriter.marker.command.masterviewdelete"; + + private final String MASTERVIEW_ID = "eu.modelwriter.marker.ui.views.masterview"; + + private final List delCandidates = new ArrayList(); + + private final List switchCandidates = new ArrayList(); + + private void deleteFromAlloyXML(final IMarker beDeleted) { + if (AlloyUtilities.isExists()) { + AlloyUtilities.removeMarkerFromRepository(beDeleted); + if (MarkUtilities.getGroupId(beDeleted) == null || MarkUtilities.getLeaderId(beDeleted) != null) { + AlloyUtilities.removeTypeFromMarker(beDeleted); + AlloyUtilities.removeRelationOfMarker(beDeleted); + } + } + } + + private void deleteSelections() { + for (final IMarker iMarker : this.delCandidates) { + this.deleteFromAlloyXML(iMarker); + AnnotationFactory.removeAnnotation(iMarker); + try { + iMarker.delete(); + } catch (final CoreException e) { + e.printStackTrace(); + } + } + } + + private void determineCandidateMarkers(final IMarker marker) { + if (MarkUtilities.getLeaderId(marker) != null) { // if the marker is + // leader marker, + // then take + // all + // of its group + final List foundMarkers = MarkerFactory.findMarkersByGroupId(marker.getResource(), + MarkUtilities.getGroupId(marker)); + if (!this.delCandidates.containsAll(foundMarkers)) { + this.delCandidates.addAll(foundMarkers); + } + } else { // if not, just take'em + if (!this.delCandidates.contains(marker)) { + this.delCandidates.add(marker); + } + } + } + + private void determineCandidateToSwitch() { + for (final IMarker candidate : this.delCandidates) { + + final Map withType = AlloyUtilities.getRelationsOfSecondSideMarker(candidate); + for (final IMarker iMarker : withType.keySet()) { + if (!this.delCandidates.contains(iMarker)) { + this.switchCandidates.add(iMarker); + } + } + + final ArrayList withoutType = AlloyUtilities.getSourcesOfMarkerAtRelations(candidate); + for (final IMarker iMarker : withoutType) { + if (!this.delCandidates.contains(iMarker)) { + this.switchCandidates.add(iMarker); + } + } + } + } + + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + // final MessageDialog dialog = new MessageDialog( + // Activator.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell(), + // "Warning", + // null, "Not implemented yet!", MessageDialog.WARNING, new String[] + // {"OK"}, 0); + // dialog.open(); + this.delCandidates.clear(); + this.switchCandidates.clear(); + final IWorkbenchWindow window = Activator.getDefault().getWorkbench().getActiveWorkbenchWindow(); + final ISelection selection = window.getSelectionService().getSelection(); + final String partId = window.getPartService().getActivePartReference().getId(); + + if (selection != null && selection instanceof ITreeSelection && partId.equals(this.MASTERVIEW_ID)) { + @SuppressWarnings("rawtypes") + final Iterator iterator = ((TreeSelection) selection).iterator(); + while (iterator.hasNext()) { + final Object element = iterator.next(); + if (element instanceof IMarker) { + this.determineCandidateMarkers((IMarker) element); + } + } + + this.determineCandidateToSwitch(); + this.switchColors(); + this.deleteSelections(); + } + return null; + } + + private void switchColors() { + for (final IMarker iMarker : this.switchCandidates) { + AnnotationFactory.convertAnnotationType(iMarker, true, false, + AlloyUtilities.getTotalTargetCount(iMarker)); + } + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/RunAsAlloyContributionItem.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/RunAsAlloyContributionItem.java new file mode 100644 index 00000000..ee84b8a6 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/RunAsAlloyContributionItem.java @@ -0,0 +1,116 @@ +package eu.modelwriter.marker.command; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.jface.action.ContributionItem; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.part.FileEditorInput; + +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4compiler.ast.Command; +import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution; +import eu.modelwriter.configuration.alloy2emf.AlloySolutionSelectionPage; +import eu.modelwriter.configuration.generation.GenerationWizard; +import eu.modelwriter.configuration.generation.GenerationWizardDialog; +import eu.modelwriter.configuration.internal.AlloyExecuter; + +public class RunAsAlloyContributionItem extends ContributionItem implements SelectionListener { + + private static AlloyExecuter alloyExecuter = new AlloyExecuter(); + private IEditorPart editor; + + public RunAsAlloyContributionItem() {} + + public RunAsAlloyContributionItem(String id) { + super(id); + } + + @Override + public void fill(Menu menu, int index) { + super.fill(menu, index); + int i = index; + // FIXME y this works on Sirius editor? + + try { + String filePath = ""; + IFile selectedFile = AlloyParseUtil.getSelectedFile(); + if (selectedFile == null) { + editor = Activator.getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + editor.doSave(new NullProgressMonitor()); + filePath = ((FileEditorInput) editor.getEditorInput()).getPath().toOSString(); + } else { + filePath = selectedFile.getRawLocation().toOSString(); + } + + alloyExecuter.parse(filePath); + final ConstList allCommands = alloyExecuter.getRunCommands(); + if (allCommands.size() > 0) { + for (final Command com : allCommands) { + final MenuItem menuItem = new MenuItem(menu, SWT.PUSH, i++); + menuItem.setText(com.toString()); + menuItem.setData("command", com); + menuItem.addSelectionListener(this); + } + } + } catch (Exception e) { + // e.printStackTrace(); + return; + } + } + + @Override + public void widgetSelected(SelectionEvent e) { + final MenuItem mi = (MenuItem) ((e.item != null) ? e.item : e.getSource()); + Command command = (Command) mi.getData("command"); + if (command == null) { + return; + } + try { + A4Solution solution = alloyExecuter.executeCommand(command); + if (solution != null) { + showWizard(solution, command.toString()); + } else { + String message = ""; + if (command.check) { + message = "No counterexample found. Assertion may be valid."; + } else { + message = "No instance found. Predicate may be inconsistent."; + } + final MessageDialog warningDialog = new MessageDialog(Activator.getShell(), "Result", null, + message, MessageDialog.WARNING, new String[] {"OK"}, 0); + warningDialog.open(); + } + } catch (Err e1) { + final MessageDialog warningDialog = new MessageDialog(Activator.getShell(), "Failed", null, + "Execution failed! \n" + e1.msg, MessageDialog.WARNING, new String[] {"OK"}, 0); + warningDialog.open(); + e1.printStackTrace(); + } + } + + private void showWizard(A4Solution solution, String commandName) { + GenerationWizard wizard = new GenerationWizard(null, commandName); + AlloySolutionSelectionPage page = new AlloySolutionSelectionPage(); + wizard.addPage(page); + page.setTitle("Alloy Solutions"); + GenerationWizardDialog dialog = new GenerationWizardDialog(null, wizard); + // dialog maximized + dialog.setPageSize(Display.getDefault().getBounds().width, + Display.getDefault().getPrimaryMonitor().getBounds().height); + // set the solution to show + page.setFirstSolution(solution); + dialog.open(); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) {} + +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/UpdateSpecificationFromEditorHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/UpdateSpecificationFromEditorHandler.java new file mode 100644 index 00000000..d8d8f3b6 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/UpdateSpecificationFromEditorHandler.java @@ -0,0 +1,18 @@ +package eu.modelwriter.marker.command; + +import org.eclipse.core.resources.IFile; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.ide.ResourceUtil; + +public class UpdateSpecificationFromEditorHandler extends UpdateSpecificationHandler { + @Override + protected String getFilePath() { + IEditorPart editor; + editor = Activator.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage() + .getActiveEditor(); + String result = null; + final IFile file = ResourceUtil.getFile(editor.getEditorInput()); + result = file.getLocation().makeAbsolute().toOSString(); + return result; + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/UpdateSpecificationFromProjectExplorerHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/UpdateSpecificationFromProjectExplorerHandler.java new file mode 100644 index 00000000..cb2a327c --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/UpdateSpecificationFromProjectExplorerHandler.java @@ -0,0 +1,21 @@ +package eu.modelwriter.marker.command; + +import org.eclipse.core.resources.IFile; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.ui.PlatformUI; + +public class UpdateSpecificationFromProjectExplorerHandler extends UpdateSpecificationHandler { + @Override + public String getFilePath() { + String result = null; + final ISelection selection = + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection(); + if (selection != null && selection instanceof TreeSelection) { + final TreeSelection treeSelection = (TreeSelection) selection; + final IFile file = (IFile) treeSelection.getFirstElement(); + result = file.getLocation().makeAbsolute().toOSString(); + } + return result; + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/UpdateSpecificationHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/UpdateSpecificationHandler.java new file mode 100644 index 00000000..33d02eb9 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/UpdateSpecificationHandler.java @@ -0,0 +1,84 @@ +package eu.modelwriter.marker.command; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.ide.ResourceUtil; + +import eu.modelwriter.configuration.alloy.reasoning.AlloyOtherSolutionReasoning; +import eu.modelwriter.configuration.alloy.trace.TraceException; +import eu.modelwriter.configuration.alloy.trace.TraceManager; +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.MarkerActivator; + +public abstract class UpdateSpecificationHandler extends AbstractHandler { + + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + final String filePath = getFilePath(); + if (filePath == null) { + return null; + } + + final IEditorPart editor = Activator.getDefault().getWorkbench().getActiveWorkbenchWindow() + .getActivePage().getActiveEditor();; + + if (editor == null) { + return null; + } + + if (editor.isDirty()) { + final IFile file = ResourceUtil.getFile(editor.getEditorInput()); + final MessageDialog warningdialog = + new MessageDialog(MarkerActivator.getShell(), "Save Specification", null, + file.getName() + + " has been modified. You must save file for update the specification. Do you want to save now?", + MessageDialog.WARNING, new String[] {"Yes", "No"}, 0); + if (warningdialog.open() != 0) { + return null; + } + + AlloyOtherSolutionReasoning.getInstance().finish(); + editor.doSave(new NullProgressMonitor()); + } + + final String content = getContent(filePath); + if (content == null) { + return null; + } + + AlloyUtilities.updateSpec(filePath, content); + + try { + TraceManager.get().loadSpec(filePath); + } catch (final TraceException e) { + e.printStackTrace(); + } + + final MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), "Status Information", + null, "Specification has been updated.", MessageDialog.INFORMATION, new String[] {"OK"}, 0); + dialog.open(); + + return null; + } + + private String getContent(final String filePath) { + try { + final byte[] encoded = Files.readAllBytes(Paths.get(filePath)); + return new String(encoded, "UTF-8"); + } catch (final IOException e) { + e.printStackTrace(); + } + return null; + } + + protected abstract String getFilePath(); +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/DropDownCommandHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/DropDownCommandHandler.java new file mode 100644 index 00000000..5482e180 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/DropDownCommandHandler.java @@ -0,0 +1,46 @@ +package eu.modelwriter.marker.command.visualization; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.ToolItem; + +public class DropDownCommandHandler extends AbstractHandler { + + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + // Sanity check. + if (null == event) { + return null; + } + + // Class check. + if (!(event.getTrigger() instanceof Event)) { + return null; + } + + final Event eventWidget = (Event) event.getTrigger(); + + // Makes sure event came from a ToolItem. + if (!(eventWidget.widget instanceof ToolItem)) { + return null; + } + + final ToolItem toolItem = (ToolItem) eventWidget.widget; + + // Creates fake selection event. + final Event newEvent = new Event(); + newEvent.button = 1; + newEvent.widget = toolItem; + newEvent.detail = SWT.ARROW; + newEvent.x = toolItem.getBounds().x; + newEvent.y = toolItem.getBounds().y + toolItem.getBounds().height; + + // Dispatches the event. + toolItem.notifyListeners(SWT.Selection, newEvent); + + return null; + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/OpenCloseEvaluatorHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/OpenCloseEvaluatorHandler.java new file mode 100644 index 00000000..8118bbca --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/OpenCloseEvaluatorHandler.java @@ -0,0 +1,39 @@ +package eu.modelwriter.marker.command.visualization; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.handlers.HandlerUtil; +import org.eclipse.ui.services.ISourceProviderService; + +import eu.modelwriter.configuration.alloy.analysis.provider.AnalysisSourceProvider; +import eu.modelwriter.configuration.alloy.analysis.provider.AnalysisSourceProvider.EvaluationState; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; + +public class OpenCloseEvaluatorHandler extends AbstractHandler { + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + final IWorkbenchWindow activeWorkbenchWindow = HandlerUtil.getActiveWorkbenchWindow(event); + final ISourceProviderService service = + activeWorkbenchWindow.getService(ISourceProviderService.class); + final AnalysisSourceProvider sourceProvider = + (AnalysisSourceProvider) service.getSourceProvider(AnalysisSourceProvider.ANALYSIS_STATE); + + final Thread thread = new Thread(new Runnable() { + @Override + public void run() { + if (sourceProvider.getEvaluationState() == EvaluationState.OPEN) { + Visualization.evaluatorOpen = false; + sourceProvider.setEvaluationState(EvaluationState.CLOSE); + } else if (sourceProvider.getEvaluationState() == EvaluationState.CLOSE) { + Visualization.evaluatorOpen = true; + sourceProvider.setEvaluationState(EvaluationState.OPEN); + } + Visualization.showViz(); + } + }); + thread.start(); + return true; + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/UpdateChangeAndImpactHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/UpdateChangeAndImpactHandler.java new file mode 100644 index 00000000..a8bbb137 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/UpdateChangeAndImpactHandler.java @@ -0,0 +1,93 @@ +package eu.modelwriter.marker.command.visualization; + +import java.util.ArrayList; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.presentation.EcoreEditor; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ITreeSelection; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.PlatformUI; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; +import eu.modelwriter.marker.ui.internal.wizards.selectionwizard.SelectionWizard; + +public class UpdateChangeAndImpactHandler extends AbstractHandler { + + IEditorPart editor; + IFile file; + ISelection selection; + + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + if (AlloyUtilities.isExists()) { + this.editor = + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + this.file = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() + .getActiveEditor().getEditorInput().getAdapter(IFile.class); + this.selection = + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection(); + AlloyUtilities.setImpactAndChanged(this.getMarkerFromEditor()); + Visualization.showViz(); + } + return null; + } + + private IMarker getMarkerFromEditor() { + IMarker beChanged = null; + if (this.selection instanceof ITextSelection) { + final TextSelection textSelection = (TextSelection) this.selection; + + final ArrayList markerList = + MarkerFactory.findMarkersInSelection(this.file, textSelection); + if (markerList != null) { + if (markerList.size() == 1) { + beChanged = markerList.get(0); + } else if (markerList.size() > 1) { + final SelectionWizard selectionWizard = new SelectionWizard(markerList); + final WizardDialog selectionDialog = + new WizardDialog(MarkerActivator.getShell(), selectionWizard); + if (selectionDialog.open() == 1) { + return null; + } + beChanged = selectionWizard.getSelectedMarker(); + } + } + } else if (this.selection instanceof ITreeSelection) { + final ITreeSelection treeSelection = (ITreeSelection) this.selection; + if (this.selection != null + && ((ITreeSelection) this.selection).getFirstElement() instanceof IMarker) { + beChanged = (IMarker) ((ITreeSelection) this.selection).getFirstElement(); + } else if (this.selection != null && this.editor instanceof EcoreEditor) { + if (treeSelection.getFirstElement() instanceof ENamedElement + && ((ENamedElement) treeSelection.getFirstElement()).getName() != null + && !((ENamedElement) treeSelection.getFirstElement()).getName().isEmpty()) { + + final URI uri = EcoreUtil.getURI((ENamedElement) treeSelection.getFirstElement()); + + beChanged = MarkerFactory.findMarkersByUri(this.file, uri.toString()); + } else if (!((EObject) treeSelection.getFirstElement() instanceof EModelElement)) { + final URI uri = EcoreUtil.getURI((EObject) treeSelection.getFirstElement()); + beChanged = MarkerFactory.findMarkersByUri(this.file, uri.toString()); + } + } + } + return beChanged; + } + +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/VizDiscoverAtomsHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/VizDiscoverAtomsHandler.java new file mode 100644 index 00000000..81edef70 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/VizDiscoverAtomsHandler.java @@ -0,0 +1,40 @@ +package eu.modelwriter.marker.command.visualization; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.handlers.HandlerUtil; +import org.eclipse.ui.services.ISourceProviderService; + +import eu.modelwriter.configuration.alloy.analysis.provider.AnalysisSourceProvider; +import eu.modelwriter.configuration.alloy.analysis.provider.AnalysisSourceProvider.ReasoningType; +import eu.modelwriter.configuration.alloy.discovery.AlloyDiscovering; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; + +public class VizDiscoverAtomsHandler extends AbstractHandler { + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + final IWorkbenchWindow activeWorkbenchWindow = HandlerUtil.getActiveWorkbenchWindow(event); + final ISourceProviderService service = + activeWorkbenchWindow.getService(ISourceProviderService.class); + final AnalysisSourceProvider sourceProvider = + (AnalysisSourceProvider) service.getSourceProvider(AnalysisSourceProvider.ANALYSIS_STATE); + sourceProvider.setActive(ReasoningType.DISCOVER_ATOM); + + final Thread thread = new Thread(new Runnable() { + @Override + public void run() { + final AlloyDiscovering alloyDiscovering = new AlloyDiscovering(); + final boolean discovering = + alloyDiscovering.discovering(); + if (!discovering) { + Visualization.sourceProvider.setPassive(); + } + Visualization.showViz(); + } + }); + thread.start(); + return true; + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/VizDiscoverRelationsHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/VizDiscoverRelationsHandler.java new file mode 100644 index 00000000..15bb36df --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/VizDiscoverRelationsHandler.java @@ -0,0 +1,40 @@ +package eu.modelwriter.marker.command.visualization; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.handlers.HandlerUtil; +import org.eclipse.ui.services.ISourceProviderService; + +import eu.modelwriter.configuration.alloy.analysis.provider.AnalysisSourceProvider; +import eu.modelwriter.configuration.alloy.analysis.provider.AnalysisSourceProvider.ReasoningType; +import eu.modelwriter.configuration.alloy.reasoning.AlloyReasoning; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; + +public class VizDiscoverRelationsHandler extends AbstractHandler { + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + final IWorkbenchWindow activeWorkbenchWindow = HandlerUtil.getActiveWorkbenchWindow(event); + final ISourceProviderService service = + activeWorkbenchWindow.getService(ISourceProviderService.class); + final AnalysisSourceProvider sourceProvider = + (AnalysisSourceProvider) service.getSourceProvider(AnalysisSourceProvider.ANALYSIS_STATE); + sourceProvider.setActive(ReasoningType.DISCOVER_RELATION); + + final Thread thread = new Thread(new Runnable() { + @Override + public void run() { + final AlloyReasoning alloyReasoning = new AlloyReasoning(); + final boolean reasoning = alloyReasoning.reasoning(); + if (!reasoning) { + sourceProvider.setPassive(); + } + + Visualization.showViz(); + } + }); + thread.start(); + return true; + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/VizNextSolutionHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/VizNextSolutionHandler.java new file mode 100644 index 00000000..7c02eeeb --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/VizNextSolutionHandler.java @@ -0,0 +1,62 @@ +package eu.modelwriter.marker.command.visualization; + +import javax.swing.JOptionPane; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.handlers.HandlerUtil; +import org.eclipse.ui.services.ISourceProviderService; + +import edu.mit.csail.sdg.alloy4.Err; +import eu.modelwriter.configuration.alloy.analysis.provider.AnalysisSourceProvider; +import eu.modelwriter.configuration.alloy.analysis.provider.AnalysisSourceProvider.ReasoningType; +import eu.modelwriter.configuration.alloy.discovery.AlloyOtherSolutionDiscovering; +import eu.modelwriter.configuration.alloy.reasoning.AlloyOtherSolutionReasoning; +import eu.modelwriter.configuration.specificreasoning.AlloyOtherSolutionReasoningForAtom; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; + +public class VizNextSolutionHandler extends AbstractHandler { + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + final IWorkbenchWindow activeWorkbenchWindow = HandlerUtil.getActiveWorkbenchWindow(event); + final ISourceProviderService service = + activeWorkbenchWindow.getService(ISourceProviderService.class); + final AnalysisSourceProvider sourceProvider = + (AnalysisSourceProvider) service.getSourceProvider(AnalysisSourceProvider.ANALYSIS_STATE); + + final Thread thread = new Thread(new Runnable() { + @Override + public void run() { + boolean success = true; + if (sourceProvider.getReasoningType() == ReasoningType.DISCOVER_RELATION) { + try { + success = AlloyOtherSolutionReasoning.getInstance().next(); + } catch (final Err e) { + success = false; + } + } else if (sourceProvider.getReasoningType() == ReasoningType.DISCOVER_ATOM) { + try { + success = AlloyOtherSolutionDiscovering.getInstance().next(); + } catch (final Err e) { + success = false; + } + } else if (sourceProvider.getReasoningType() == ReasoningType.DISCOVER_RELATION_FOR_ATOM) { + try { + success = AlloyOtherSolutionReasoningForAtom.getInstance().next(); + } catch (final Err e) { + success = false; + } + } + if (!success) { + JOptionPane.showMessageDialog(null, "There is not any other next solution.", + "Next Solution", JOptionPane.INFORMATION_MESSAGE); + } + Visualization.showViz(); + } + }); + thread.start(); + return true; + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/VizPreviousSolutionHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/VizPreviousSolutionHandler.java new file mode 100644 index 00000000..986676b1 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/VizPreviousSolutionHandler.java @@ -0,0 +1,62 @@ +package eu.modelwriter.marker.command.visualization; + +import javax.swing.JOptionPane; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.handlers.HandlerUtil; +import org.eclipse.ui.services.ISourceProviderService; + +import edu.mit.csail.sdg.alloy4.Err; +import eu.modelwriter.configuration.alloy.analysis.provider.AnalysisSourceProvider; +import eu.modelwriter.configuration.alloy.analysis.provider.AnalysisSourceProvider.ReasoningType; +import eu.modelwriter.configuration.alloy.discovery.AlloyOtherSolutionDiscovering; +import eu.modelwriter.configuration.alloy.reasoning.AlloyOtherSolutionReasoning; +import eu.modelwriter.configuration.specificreasoning.AlloyOtherSolutionReasoningForAtom; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; + +public class VizPreviousSolutionHandler extends AbstractHandler { + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + final IWorkbenchWindow activeWorkbenchWindow = HandlerUtil.getActiveWorkbenchWindow(event); + final ISourceProviderService service = + activeWorkbenchWindow.getService(ISourceProviderService.class); + final AnalysisSourceProvider sourceProvider = + (AnalysisSourceProvider) service.getSourceProvider(AnalysisSourceProvider.ANALYSIS_STATE); + + final Thread thread = new Thread(new Runnable() { + @Override + public void run() { + boolean success = true; + if (sourceProvider.getReasoningType() == ReasoningType.DISCOVER_RELATION) { + try { + success = AlloyOtherSolutionReasoning.getInstance().previous(); + } catch (final Err e) { + success = false; + } + } else if (sourceProvider.getReasoningType() == ReasoningType.DISCOVER_ATOM) { + try { + success = AlloyOtherSolutionDiscovering.getInstance().previous(); + } catch (final Err e) { + success = false; + } + } else if (sourceProvider.getReasoningType() == ReasoningType.DISCOVER_RELATION_FOR_ATOM) { + try { + success = AlloyOtherSolutionReasoningForAtom.getInstance().previous(); + } catch (final Err e) { + success = false; + } + } + if (!success) { + JOptionPane.showMessageDialog(null, "There is not any other previous solution.", + "Previous Solution", JOptionPane.INFORMATION_MESSAGE); + } + Visualization.showViz(); + } + }); + thread.start(); + return true; + } +} diff --git a/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/VizStopOtherSolutionHandler.java b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/VizStopOtherSolutionHandler.java new file mode 100644 index 00000000..cfef5e56 --- /dev/null +++ b/Source/eu.modelwriter.marker.command/src/eu/modelwriter/marker/command/visualization/VizStopOtherSolutionHandler.java @@ -0,0 +1,40 @@ +package eu.modelwriter.marker.command.visualization; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.handlers.HandlerUtil; +import org.eclipse.ui.services.ISourceProviderService; + +import eu.modelwriter.configuration.alloy.analysis.provider.AnalysisSourceProvider; +import eu.modelwriter.configuration.alloy.discovery.AlloyOtherSolutionDiscovering; +import eu.modelwriter.configuration.alloy.reasoning.AlloyOtherSolutionReasoning; +import eu.modelwriter.configuration.alloy.validation.AlloyValidator; +import eu.modelwriter.configuration.specificreasoning.AlloyOtherSolutionReasoningForAtom; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; + +public class VizStopOtherSolutionHandler extends AbstractHandler { + @Override + public Object execute(final ExecutionEvent event) throws ExecutionException { + final IWorkbenchWindow activeWorkbenchWindow = HandlerUtil.getActiveWorkbenchWindow(event); + final ISourceProviderService service = + activeWorkbenchWindow.getService(ISourceProviderService.class); + final AnalysisSourceProvider sourceProvider = + (AnalysisSourceProvider) service.getSourceProvider(AnalysisSourceProvider.ANALYSIS_STATE); + sourceProvider.setPassive(); + + final Thread thread = new Thread(new Runnable() { + @Override + public void run() { + AlloyValidator.isCanceled = true; + AlloyOtherSolutionReasoning.getInstance().finish(); + AlloyOtherSolutionDiscovering.getInstance().finish(); + AlloyOtherSolutionReasoningForAtom.getInstance().finish(); + Visualization.showViz(); + } + }); + thread.start(); + return true; + } +} diff --git a/Source/eu.modelwriter.marker.startup/.classpath b/Source/eu.modelwriter.marker.startup/.classpath new file mode 100644 index 00000000..eca7bdba --- /dev/null +++ b/Source/eu.modelwriter.marker.startup/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Source/eu.modelwriter.marker.startup/.gitignore b/Source/eu.modelwriter.marker.startup/.gitignore new file mode 100644 index 00000000..ae3c1726 --- /dev/null +++ b/Source/eu.modelwriter.marker.startup/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/Source/eu.modelwriter.marker.startup/.project b/Source/eu.modelwriter.marker.startup/.project new file mode 100644 index 00000000..8c0de358 --- /dev/null +++ b/Source/eu.modelwriter.marker.startup/.project @@ -0,0 +1,28 @@ + + + eu.modelwriter.marker.startup + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/Source/eu.modelwriter.marker.startup/.settings/org.eclipse.jdt.core.prefs b/Source/eu.modelwriter.marker.startup/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..0c68a61d --- /dev/null +++ b/Source/eu.modelwriter.marker.startup/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/Source/eu.modelwriter.marker.startup/.settings/org.eclipse.pde.core.prefs b/Source/eu.modelwriter.marker.startup/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 00000000..923c37fb --- /dev/null +++ b/Source/eu.modelwriter.marker.startup/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +resolve.requirebundle=false diff --git a/Source/eu.modelwriter.marker.startup/META-INF/MANIFEST.MF b/Source/eu.modelwriter.marker.startup/META-INF/MANIFEST.MF new file mode 100644 index 00000000..424c22f0 --- /dev/null +++ b/Source/eu.modelwriter.marker.startup/META-INF/MANIFEST.MF @@ -0,0 +1,15 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: ModelWriter Marker Startup +Bundle-SymbolicName: eu.modelwriter.marker.startup;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: eu.modelwriter.marker.startup.Activator +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.emf.ecore.editor, + org.eclipse.jface.text, + eu.modelwriter.marker, + eu.modelwriter.marker.ui, + org.eclipse.core.resources +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ActivationPolicy: lazy +Import-Package: eu.modelwriter.marker.command diff --git a/Source/eu.modelwriter.marker.startup/build.properties b/Source/eu.modelwriter.marker.startup/build.properties new file mode 100644 index 00000000..13cfef39 --- /dev/null +++ b/Source/eu.modelwriter.marker.startup/build.properties @@ -0,0 +1,25 @@ +############################################################################### +# Copyright (c) 2015 UNIT Information Technologies R&D Ltd +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Ferhat Erata - initial API and implementation +# H. Emre Kirmizi - initial API and implementation +# Serhat Celik - initial API and implementation +# U. Anil Ozturk - initial API and implementation +############################################################################### +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + build.properties,\ + bin/,\ + .settings/,\ + .project,\ + .classpath +additional.bundles = org.eclipse.jdt.core,\ + eu.modelwriter.marker.ui diff --git a/Source/eu.modelwriter.marker.startup/plugin.xml b/Source/eu.modelwriter.marker.startup/plugin.xml new file mode 100644 index 00000000..41e897cd --- /dev/null +++ b/Source/eu.modelwriter.marker.startup/plugin.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.marker.startup/src/eu/modelwriter/marker/model/SelectionChangeListener.java b/Source/eu.modelwriter.marker.startup/src/eu/modelwriter/marker/model/SelectionChangeListener.java new file mode 100644 index 00000000..fa82b00b --- /dev/null +++ b/Source/eu.modelwriter.marker.startup/src/eu/modelwriter/marker/model/SelectionChangeListener.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.model; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ITreeSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; + +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class SelectionChangeListener implements ISelectionChangedListener { + + private static SelectionChangeListener listener; + + public static IMarker preMarker = null; + public static ITreeSelection preSelection = null; + + public static SelectionChangeListener getInstance(final IFile eFile) { + if (SelectionChangeListener.listener == null) { + SelectionChangeListener.listener = new SelectionChangeListener(eFile); + } else { + SelectionChangeListener.listener.seteFile(eFile); + } + return SelectionChangeListener.listener; + } + + private IFile eFile; + + public SelectionChangeListener(final IFile eFile) { + this.eFile = eFile; + } + + @Override + public void selectionChanged(final SelectionChangedEvent event) { + if (SelectionChangeListener.preMarker != null && SelectionChangeListener.preMarker.exists()) { + try { + if (event.getSelection().isEmpty()) { + // Deleting marker for element removed. + SelectionChangeListener.preMarker.delete(); + } else { + if (SelectionChangeListener.preMarker.getAttribute("oldUri") == null) { + // Saving Uri of marker which before change + SelectionChangeListener.preMarker.setAttribute("oldUri", + SelectionChangeListener.preMarker.getAttribute("uri")); + } + + // Updating Uri of Marker + MarkUtilities.setUri(SelectionChangeListener.preMarker, EcoreUtil + .getURI((EObject) SelectionChangeListener.preSelection.getFirstElement()).toString()); + + String text = null; + + // According to selected element, setting the text. + // if (SelectionChangeListener.preSelection.getFirstElement() instanceof Identifiable) { + // text = MarkerFactory.reqIfToString( + // (Identifiable) SelectionChangeListener.preSelection.getFirstElement()); + // }else + if (SelectionChangeListener.preSelection.getFirstElement() instanceof ENamedElement) { + text = + ((ENamedElement) SelectionChangeListener.preSelection.getFirstElement()).getName(); + } else if (!(SelectionChangeListener.preSelection + .getFirstElement() instanceof EModelElement)) { + text = MarkerFactory + .instanceToString((EObject) SelectionChangeListener.preSelection.getFirstElement()); + } + + // Saving text of marker which before change + if (SelectionChangeListener.preMarker.getAttribute("oldText") == null) { + SelectionChangeListener.preMarker.setAttribute("oldText", + MarkUtilities.getText(SelectionChangeListener.preMarker)); + } + + // Updating marker text. + MarkUtilities.setText(SelectionChangeListener.preMarker, text); + + SelectionChangeListener.preMarker = null; + SelectionChangeListener.preSelection = null; + } + } catch (final CoreException e) { + e.printStackTrace(); + } + } + if (SelectionChangeListener.preSelection == null + || SelectionChangeListener.preSelection.getFirstElement() instanceof ENamedElement + // || SelectionChangeListener.preSelection.getFirstElement() instanceof Identifiable + || !(SelectionChangeListener.preSelection.getFirstElement() instanceof EModelElement)) { + SelectionChangeListener.preSelection = (ITreeSelection) event.getSelection(); + SelectionChangeListener.preMarker = MarkerFactory + .findMarkerByTreeSelection((ITreeSelection) event.getSelection(), this.eFile); + } else { + SelectionChangeListener.preSelection = (ITreeSelection) event.getSelection(); + } + } + + public void seteFile(final IFile eFile) { + this.eFile = eFile; + } +} diff --git a/Source/eu.modelwriter.marker.startup/src/eu/modelwriter/marker/startup/Activator.java b/Source/eu.modelwriter.marker.startup/src/eu/modelwriter/marker/startup/Activator.java new file mode 100644 index 00000000..436571c8 --- /dev/null +++ b/Source/eu.modelwriter.marker.startup/src/eu/modelwriter/marker/startup/Activator.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker.startup; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class Activator implements BundleActivator { + + private static BundleContext context; + + static BundleContext getContext() { + return context; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext bundleContext) throws Exception { + Activator.context = bundleContext; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext bundleContext) throws Exception { + Activator.context = null; + } +} diff --git a/Source/eu.modelwriter.marker.startup/src/eu/modelwriter/marker/startup/Startup.java b/Source/eu.modelwriter.marker.startup/src/eu/modelwriter/marker/startup/Startup.java new file mode 100644 index 00000000..e234b8ac --- /dev/null +++ b/Source/eu.modelwriter.marker.startup/src/eu/modelwriter/marker/startup/Startup.java @@ -0,0 +1,449 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.startup; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Scanner; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.emf.ecore.presentation.EcoreEditor; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.viewers.AbstractTreeViewer; +import org.eclipse.jface.viewers.DecoratingLabelProvider; +import org.eclipse.jface.viewers.ILabelDecorator; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ITreeSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.text.edits.InsertEdit; +import org.eclipse.text.edits.MalformedTreeException; +import org.eclipse.text.edits.RangeMarker; +import org.eclipse.text.edits.TextEdit; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.IPartListener2; +import org.eclipse.ui.IStartup; +import org.eclipse.ui.IViewReference; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPartReference; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.commands.ICommandService; + +import eu.modelwriter.marker.command.MarkerVisibilityHandler; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.marker.internal.MarkerUpdater; +import eu.modelwriter.marker.model.SelectionChangeListener; +import eu.modelwriter.marker.ui.internal.views.contextualview.ContextualView; + +public class Startup implements IStartup { + + public static IMarker preMarker = null; + + public static ITreeSelection preSelection = null; + private boolean isFirst = true; + private IEditorPart lastEditor; + private IWorkbenchWindow window = null; + + @Override + public void earlyStartup() { + System.out.println("My plugin has been early started"); + final IWorkbench workbench = PlatformUI.getWorkbench(); + workbench.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + window = workbench.getActiveWorkbenchWindow(); + if (window != null) { + IEditorPart part = window.getActivePage().getActiveEditor(); + lastEditor = part; + Startup.this.initContextualView(part); + if (part instanceof EcoreEditor) { + Startup.this.initSelectionChangeListener((EcoreEditor) part); + Startup.this.iniResourceChangeListener((EcoreEditor) part); + } + window.getActivePage().addPartListener(new IPartListener2() { + @Override + public void partActivated(IWorkbenchPartReference partRef) { + if (partRef instanceof IViewReference) { + return; + } + + if (partRef.getPart(false) instanceof IEditorPart) { + IEditorPart editor = (IEditorPart) partRef.getPart(false); + if (isFirst == false && lastEditor != null + && !lastEditor + .equals(window.getActivePage().getActiveEditor())) { + ContextualView.refreshTree(); + } + if (editor instanceof EcoreEditor) { + EcoreEditor eEditor = (EcoreEditor) editor; + Startup.this.initDecoratingLabelProvider(eEditor); + Startup.this.initSelectionChangeListener(eEditor); + + eEditor.getViewer().refresh(); + + // When change model, fix Xml file + Startup.this.iniResourceChangeListener(eEditor); + } + lastEditor = window.getActivePage().getActiveEditor(); + } + } + + @Override + public void partBroughtToTop(IWorkbenchPartReference partRef) {} + + @Override + public void partClosed(IWorkbenchPartReference partRef) { + IEditorPart editor; + if (partRef.getPart(false) instanceof IEditorPart) { + editor = (IEditorPart) partRef.getPart(false); + } else { + return; + } + + if (editor instanceof EcoreEditor) { + EcoreEditor eEditor = (EcoreEditor) editor; + IFileEditorInput input = (IFileEditorInput) eEditor.getEditorInput(); + IFile eFile = input.getFile(); + List list = MarkerFactory.findMarkers(eFile); + for (IMarker iMarker : list) { + try { + // If marker has old Uri and Text, setting these again. + if (iMarker.getAttribute("oldText") != null + && iMarker.getAttribute("oldUri") != null) { + iMarker.setAttribute(IMarker.TEXT, iMarker.getAttribute("oldText")); + iMarker.setAttribute(IMarker.MESSAGE, iMarker.getAttribute("oldText")); + iMarker.setAttribute("uri", iMarker.getAttribute("oldUri")); + + // Clearing old Text and Uri. + iMarker.setAttribute("oldText", null); + iMarker.setAttribute("oldUri", null); + } + } catch (CoreException e) { + e.printStackTrace(); + } + } + } + // Removing SelectionChangeListener from editor. + Startup.this.removeSelectionChangeListener(partRef); + + SelectionChangeListener.preMarker = null; + SelectionChangeListener.preSelection = null; + + ContextualView.refreshTree(); + } + + @Override + public void partDeactivated(IWorkbenchPartReference partRef) { + Startup.this.removeSelectionChangeListener(partRef); + } + + @Override + public void partHidden(IWorkbenchPartReference partRef) {} + + @Override + public void partInputChanged(IWorkbenchPartReference partRef) {} + + @Override + public void partOpened(IWorkbenchPartReference partRef) {} + + @Override + public void partVisible(IWorkbenchPartReference partRef) {} + }); + + // If the an EcoreEditor is already opened before the part listener added. + IEditorPart editor = window.getActivePage().getActiveEditor(); + if (editor instanceof EcoreEditor) { + Startup.this.initDecoratingLabelProvider((EcoreEditor) editor); + } + + // Update Marker Visibility label + final ICommandService commandService = window.getService(ICommandService.class); + if (commandService != null) { + commandService.refreshElements(MarkerVisibilityHandler.COMMAND_ID, null); + } + } + isFirst = false; + } + }); + } + + private void iniResourceChangeListener(EcoreEditor eEditor) { + IFileEditorInput input = (IFileEditorInput) eEditor.getEditorInput(); + IFile eFile = input.getFile(); + ResourcesPlugin.getWorkspace().addResourceChangeListener(new IResourceChangeListener() { + + @Override + public void resourceChanged(IResourceChangeEvent event) { + IFileEditorInput input = (IFileEditorInput) eEditor.getEditorInput(); + IFile file = input.getFile(); + IResourceDelta delta = event.getDelta().findMember(file.getFullPath()); + if (delta == null) { + return; + } + int flags = delta.getFlags(); + if (delta.getKind() == IResourceDelta.CHANGED && (flags & IResourceDelta.CONTENT) != 0) { + + List list = MarkerFactory.findMarkers(eFile); + + if (eFile.getFileExtension().equals("ecore")) { + for (IMarker iMarker : list) { + setOldTextAndUri(iMarker); + try { + MarkerFactory.updateMarkerfromXMLForModel(iMarker, eFile); + } catch (Exception e) { + // System.out.println( + // e.toString() + " ->updateMarkerfromXMLForModel in resourceChange in StartUp"); + } + try { + if (iMarker != null && MarkUtilities.getLinenumber(iMarker) == -1) { + try { + // MarkerUpdater.updateTargetsToDelete(iMarker); + // MarkerUpdater.updateSourcesToDelete(iMarker); + } catch (Exception e) { + // System.out.println(e.toString() + // + " ->updateTargetsToDelete && updateSourcesToDelete - + // updateMarkerfromXMLForModel in resourceChange in StartUp"); + } + iMarker.delete(); + } else { + MarkerUpdater.update(iMarker); + // MarkerUpdater.updateTargets(iMarker); + // MarkerUpdater.updateSources(iMarker); + } + } catch (CoreException e) { + e.printStackTrace(); + } + } + } else if (eFile.getFileExtension().equals("reqif")) { + for (IMarker iMarker : list) { + setOldTextAndUri(iMarker); + try { + MarkerFactory.updateMarkerfromXMLForReqIf(iMarker, eFile); + } catch (Exception e) { + // System.out.println( + // e.toString() + " ->updateMarkerfromXMLForReqIf in resourceChange in StartUp"); + } + try { + if (iMarker != null && MarkUtilities.getLinenumber(iMarker) == -1) { + try { + // MarkerUpdater.updateTargetsToDelete(iMarker); + // MarkerUpdater.updateSourcesToDelete(iMarker); + } catch (Exception e) { + // System.out.println(e.toString() + // + " ->updateTargetsToDelete && updateSourcesToDelete - + // updateMarkerfromXMLForReqIf in resourceChange in StartUp"); + } + iMarker.delete(); + } else { + MarkerUpdater.update(iMarker); + // MarkerUpdater.updateTargets(iMarker); + // MarkerUpdater.updateSources(iMarker); + } + + } catch (CoreException e) { + e.printStackTrace(); + } + } + } else { + for (IMarker iMarker : list) { + setOldTextAndUri(iMarker); + try { + MarkerFactory.updateMarkerfromXMLForInstance(iMarker, eFile); + } catch (Exception e) { + // System.out.println(e.toString() + // + " ->updateMarkerfromXMLForInstance in resourceChange in StartUp"); + } + try { + if (iMarker != null && MarkUtilities.getLinenumber(iMarker) == -1) { + try { + // MarkerUpdater.updateTargetsToDelete(iMarker); + // MarkerUpdater.updateSourcesToDelete(iMarker); + } catch (Exception e) { + // System.out.println(e.toString() + // + " ->updateTargetsToDelete && updateSourcesToDelete - + // updateMarkerfromXMLForInstance in resourceChange in StartUp"); + } + iMarker.delete(); + } else { + MarkerUpdater.update(iMarker); + // MarkerUpdater.updateTargets(iMarker); + // MarkerUpdater.updateSources(iMarker); + } + } catch (CoreException e) { + e.printStackTrace(); + } + } + } + } + } + + public void setOldTextAndUri(IMarker iMarker) { + try { + if (iMarker.getAttribute("oldText") != null && iMarker.getAttribute("oldUri") != null) { + // Clearing old Text and Uri. + iMarker.setAttribute("oldText", null); + iMarker.setAttribute("oldUri", null); + } + } catch (CoreException e) { + e.printStackTrace(); + } + } + }, IResourceChangeEvent.POST_BUILD); + } + + /** + * Initializes decorator for given EcoreEditor. + */ + private void initDecoratingLabelProvider(EcoreEditor eEditor) { + TreeViewer treeViewer = (TreeViewer) eEditor.getViewer(); + ILabelProvider labelProvider = (ILabelProvider) treeViewer.getLabelProvider(); + + if (labelProvider instanceof DecoratingLabelProvider) { + return; + } else { + ILabelDecorator decorator = + window.getWorkbench().getDecoratorManager().getLabelDecorator(); + treeViewer.setLabelProvider(new DecoratingLabelProvider(labelProvider, decorator)); + } + } + + private void initContextualView(IEditorPart editor) { + if (editor == null) { + return; + } + IFile file = editor.getEditorInput().getAdapter(IFile.class); + TreeViewer treeViewer = ContextualView.getTreeViewer(); + if (treeViewer != null) { + // Finding all markers in given file. + ArrayList allMarkers; + allMarkers = MarkerFactory.findMarkersAsArrayList(file); + if (allMarkers == null) { + return; + } + Iterator iter = allMarkers.iterator(); + while (iter.hasNext()) { + IMarker marker = iter.next(); + if (MarkUtilities.getLeaderId(marker) == null && MarkUtilities.getGroupId(marker) != null) { + iter.remove(); + } + } + if (!treeViewer.getTree().isDisposed()) { + treeViewer.setInput(allMarkers.toArray()); + } + treeViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS); + } + } + + @SuppressWarnings("unused") + private boolean initResourceChangeListener(EcoreEditor eEditor) { + ResourcesPlugin.getWorkspace().addResourceChangeListener(new IResourceChangeListener() { + + @Override + public void resourceChanged(IResourceChangeEvent event) { + IFileEditorInput input = (IFileEditorInput) eEditor.getEditorInput(); + IFile file = input.getFile(); + IResourceDelta delta = event.getDelta().findMember(file.getFullPath()); + int flags = delta.getFlags(); + if (delta != null && delta.getKind() == IResourceDelta.CHANGED + && (flags & IResourceDelta.CONTENT) != 0) { + + Scanner scanner = null; + try { + scanner = new Scanner(file.getContents(), "UTF-8"); + } catch (CoreException e) { + e.printStackTrace(); + } + IDocument document = new Document(scanner.useDelimiter("\\A").next()); + System.out.println("Document before change:\n" + document.get()); + scanner.close(); + + InsertEdit edit = new InsertEdit(0, document.get()); + List list = MarkerFactory.findMarkers(file); + HashMap mapRangeMarker = new HashMap(); + HashMap mapMarker = new HashMap(); + for (IMarker iMarker : list) { + try { + int offset = MarkUtilities.getStart(iMarker); + int length = MarkUtilities.getLength(iMarker); + String id = MarkUtilities.getSourceId(iMarker); + RangeMarker rm = new RangeMarker(offset, length); + mapRangeMarker.put(id, rm); + + rm.apply(document); + mapMarker.put(id, iMarker); + } catch (MalformedTreeException | BadLocationException e) { + e.printStackTrace(); + } + } + + edit = new InsertEdit(5, "#FERHAT#"); + try { + edit.apply(document, TextEdit.UPDATE_REGIONS); + } catch (MalformedTreeException | BadLocationException e1) { + e1.printStackTrace(); + } + + System.out.println("========================="); + System.out.println("New Document:\n" + document.get()); + + for (Map.Entry entry : mapRangeMarker.entrySet()) { + IMarker marker = mapMarker.get(entry.getKey()); + int start = entry.getValue().getOffset(); + int end = entry.getValue().getOffset() + entry.getValue().getLength(); + System.out.println("Old Start: " + MarkUtilities.getStart(marker) + " - " + "Old End: " + + MarkUtilities.getEnd(marker)); + MarkUtilities.setStart(marker, start); + MarkUtilities.setEnd(marker, end); + System.out.println("New Start: " + start + " - " + "New End: " + end); + } + } + } + }, IResourceChangeEvent.POST_BUILD); + return false; + } + + private boolean initSelectionChangeListener(EcoreEditor eEditor) { + IFileEditorInput eInput = (IFileEditorInput) eEditor.getEditorInput(); + IFile eFile = eInput.getFile(); + // Adding SelectionChangeListener to editor. + eEditor.getViewer().addSelectionChangedListener(SelectionChangeListener.getInstance(eFile)); + + return false; + } + + private void removeSelectionChangeListener(IWorkbenchPartReference partRef) { + if (partRef.getPart(false) instanceof IEditorPart) { + IEditorPart editor = (IEditorPart) partRef.getPart(false); + initContextualView(editor); + if (editor instanceof EcoreEditor) { + EcoreEditor eEditor = (EcoreEditor) editor; + IFileEditorInput eInput = (IFileEditorInput) eEditor.getEditorInput(); + IFile eFile = eInput.getFile(); + // Removing SelectionChangeListener from editor. + ((EcoreEditor) editor).getViewer() + .removeSelectionChangedListener(SelectionChangeListener.getInstance(eFile)); + } + } + } +} diff --git a/Source/eu.modelwriter.marker.ui/.classpath b/Source/eu.modelwriter.marker.ui/.classpath new file mode 100644 index 00000000..eca7bdba --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Source/eu.modelwriter.marker.ui/.gitignore b/Source/eu.modelwriter.marker.ui/.gitignore new file mode 100644 index 00000000..ae3c1726 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/Source/eu.modelwriter.marker.ui/.project b/Source/eu.modelwriter.marker.ui/.project new file mode 100644 index 00000000..d8084f13 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/.project @@ -0,0 +1,28 @@ + + + eu.modelwriter.marker.ui + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/Source/eu.modelwriter.marker.ui/.settings/org.eclipse.jdt.core.prefs b/Source/eu.modelwriter.marker.ui/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..0c68a61d --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/Source/eu.modelwriter.marker.ui/.settings/org.eclipse.pde.core.prefs b/Source/eu.modelwriter.marker.ui/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 00000000..923c37fb --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +resolve.requirebundle=false diff --git a/Source/eu.modelwriter.marker.ui/META-INF/MANIFEST.MF b/Source/eu.modelwriter.marker.ui/META-INF/MANIFEST.MF new file mode 100644 index 00000000..decd7a35 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/META-INF/MANIFEST.MF @@ -0,0 +1,29 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: eu.modelwriter.marker.ui +Bundle-SymbolicName: eu.modelwriter.marker.ui;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: eu.modelwriter.marker.ui.Activator +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.jface.text, + org.eclipse.emf.ecore.editor, + org.eclipse.ui.editors, + eu.modelwriter.marker, + eu.modelwriter.configuration;bundle-version="1.0.0", + eu.modelwriter.alloyanalyzer;bundle-version="1.0.0", + org.eclipse.core.resources, + org.eclipse.jdt.core, + org.eclipse.jdt.ui, + eu.modelwriter.traceability.core.persistence +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ActivationPolicy: lazy +Export-Package: eu.modelwriter.marker.ui, + eu.modelwriter.marker.ui.internal.views.contextualview, + eu.modelwriter.marker.ui.internal.views.visualizationview, + eu.modelwriter.marker.ui.internal.views.visualizationview.commands, + eu.modelwriter.marker.ui.internal.wizards.launchwizard, + eu.modelwriter.marker.ui.internal.wizards.mappingwizard, + eu.modelwriter.marker.ui.internal.wizards.markallinwswizard, + eu.modelwriter.marker.ui.internal.wizards.markerwizard, + eu.modelwriter.marker.ui.internal.wizards.selectionwizard +Bundle-ClassPath: . diff --git a/Source/eu.modelwriter.marker.ui/build.properties b/Source/eu.modelwriter.marker.ui/build.properties new file mode 100644 index 00000000..dd7d81b5 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/build.properties @@ -0,0 +1,24 @@ +############################################################################### +# Copyright (c) 2015 UNIT Information Technologies R&D Ltd +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Ferhat Erata - initial API and implementation +# H. Emre Kirmizi - initial API and implementation +# Serhat Celik - initial API and implementation +# U. Anil Ozturk - initial API and implementation +############################################################################### +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + lib/,\ + build.properties,\ + bin/,\ + .settings/,\ + .project,\ + .classpath diff --git a/Source/eu.modelwriter.marker.ui/examples/EcoreExample/Library1.xmi b/Source/eu.modelwriter.marker.ui/examples/EcoreExample/Library1.xmi new file mode 100644 index 00000000..172510bf --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/examples/EcoreExample/Library1.xmi @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/Source/eu.modelwriter.marker.ui/examples/EcoreExample/extlibrary.ecore b/Source/eu.modelwriter.marker.ui/examples/EcoreExample/extlibrary.ecore new file mode 100644 index 00000000..4d637438 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/examples/EcoreExample/extlibrary.ecore @@ -0,0 +1,107 @@ + + + + + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.marker.ui/examples/ReqifExample/RMF_CustomerRequirementsSpecification.reqif b/Source/eu.modelwriter.marker.ui/examples/ReqifExample/RMF_CustomerRequirementsSpecification.reqif new file mode 100644 index 00000000..5fa44ad9 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/examples/ReqifExample/RMF_CustomerRequirementsSpecification.reqif @@ -0,0 +1,1015 @@ + + + + + Created by: broerkens + 2013-06-05T19:55:02.103+02:00 + ProR (http://pror.org) + 1.0.1 + ProR (http://pror.org) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rmf-fb146138-f0a1-4fe1-9333-199a7c8bd5a4 + + + + + + + + + rmf-fb146138-f0a1-4fe1-9333-199a7c8bd5a4 + + + + + + + + + rmf-91af4973-33cb-4ec5-9921-a1a3da728fec + + + + + rmf-a9729862-1ce3-4778-9e08-6470b37f5dd4 + + + + + + + + + rmf-072922ed-83e2-4602-a861-46caf3d9ee43 + + + + + rmf-f7ee8b16-a9a0-4ba2-8e25-3a68dae5ab42 + + + + + rmf-66fd26ec-904d-4791-9243-deccf4cc2a4c + + + rmf-5150a68c-fc5c-4161-9383-2669c6f988c4 + + + + + + + rmf-fb146138-f0a1-4fe1-9333-199a7c8bd5a4 + + + + + + + + + rmf-fb146138-f0a1-4fe1-9333-199a7c8bd5a4 + + + + + rmf-fb146138-f0a1-4fe1-9333-199a7c8bd5a4 + + + + + + + + + rmf-fb146138-f0a1-4fe1-9333-199a7c8bd5a4 + + + + + + + + + rmf-c3d2ed18-7a16-4714-98bd-b3054b2f53e2 + + + + + + + + + + + rmf-219ee7f9-9784-404b-93b6-c3e95803c31c + + + + + rmf-daefe238-f3d8-4a05-a319-e9abd2e7530b + + + + + rmf-3586d74e-3bb0-4bf3-8032-7afa67bcd4d8 + + + + + + + rmf-75facb8b-706d-43e8-b58b-cffbd920c262 + + + + + rmf-77d18f52-ff28-4e72-be96-aff19963a744 + + + rmf-5150a68c-fc5c-4161-9383-2669c6f988c4 + + + + + rmf-caf1c63d-2ddb-4c7b-8fcd-2a669b1b4d74 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + rmf-75facb8b-706d-43e8-b58b-cffbd920c262 + + + + + rmf-caf1c63d-2ddb-4c7b-8fcd-2a669b1b4d74 + + + + + + + rmf-58671d65-2b2c-45a6-9df9-7557a55591e0 + + + + + rmf-cd7f60ed-5655-4d60-9f9b-024da2bd3e21 + + + + + rmf-8a2218f3-5c1b-4670-9c3b-e69595f56df3 + + + + + + + rmf-58671d65-2b2c-45a6-9df9-7557a55591e0 + + + + + rmf-cd7f60ed-5655-4d60-9f9b-024da2bd3e21 + + + + + rmf-8a2218f3-5c1b-4670-9c3b-e69595f56df3 + + + + + + + rmf-75facb8b-706d-43e8-b58b-cffbd920c262 + + + + + rmf-15590c9e-e14c-4db9-ade7-f1c0ee2369f1 + + + rmf-5150a68c-fc5c-4161-9383-2669c6f988c4 + + + + + rmf-caf1c63d-2ddb-4c7b-8fcd-2a669b1b4d74 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + rmf-75facb8b-706d-43e8-b58b-cffbd920c262 + + + + + rmf-15590c9e-e14c-4db9-ade7-f1c0ee2369f1 + + + rmf-5150a68c-fc5c-4161-9383-2669c6f988c4 + + + + + rmf-caf1c63d-2ddb-4c7b-8fcd-2a669b1b4d74 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + rmf-75facb8b-706d-43e8-b58b-cffbd920c262 + + + + + rmf-20621e2f-ea20-4aeb-9758-babf83dfa2eb + + + rmf-5150a68c-fc5c-4161-9383-2669c6f988c4 + + + + + rmf-caf1c63d-2ddb-4c7b-8fcd-2a669b1b4d74 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + rmf-219ee7f9-9784-404b-93b6-c3e95803c31c + + + + + rmf-daefe238-f3d8-4a05-a319-e9abd2e7530b + + + + + rmf-3586d74e-3bb0-4bf3-8032-7afa67bcd4d8 + + + + + + + rmf-75facb8b-706d-43e8-b58b-cffbd920c262 + + + + + rmf-77d18f52-ff28-4e72-be96-aff19963a744 + + + rmf-5150a68c-fc5c-4161-9383-2669c6f988c4 + + + + + rmf-caf1c63d-2ddb-4c7b-8fcd-2a669b1b4d74 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + rmf-75facb8b-706d-43e8-b58b-cffbd920c262 + + + + + rmf-15590c9e-e14c-4db9-ade7-f1c0ee2369f1 + + + rmf-5150a68c-fc5c-4161-9383-2669c6f988c4 + + + + + rmf-caf1c63d-2ddb-4c7b-8fcd-2a669b1b4d74 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + rmf-75facb8b-706d-43e8-b58b-cffbd920c262 + + + + + rmf-15590c9e-e14c-4db9-ade7-f1c0ee2369f1 + + + rmf-5150a68c-fc5c-4161-9383-2669c6f988c4 + + + + + rmf-caf1c63d-2ddb-4c7b-8fcd-2a669b1b4d74 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + rmf-219ee7f9-9784-404b-93b6-c3e95803c31c + + + + + rmf-daefe238-f3d8-4a05-a319-e9abd2e7530b + + + + + rmf-3586d74e-3bb0-4bf3-8032-7afa67bcd4d8 + + + + + + + rmf-75facb8b-706d-43e8-b58b-cffbd920c262 + + + + + rmf-77d18f52-ff28-4e72-be96-aff19963a744 + + + rmf-5150a68c-fc5c-4161-9383-2669c6f988c4 + + + + + rmf-caf1c63d-2ddb-4c7b-8fcd-2a669b1b4d74 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + rmf-75facb8b-706d-43e8-b58b-cffbd920c262 + + + + + rmf-caf1c63d-2ddb-4c7b-8fcd-2a669b1b4d74 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + rmf-75facb8b-706d-43e8-b58b-cffbd920c262 + + + + + rmf-15590c9e-e14c-4db9-ade7-f1c0ee2369f1 + + + rmf-5150a68c-fc5c-4161-9383-2669c6f988c4 + + + + + rmf-caf1c63d-2ddb-4c7b-8fcd-2a669b1b4d74 + + + + + + + rmf-a188de38-8682-43d1-95c0-e4f818f18995 + + + + + rmf-877b7e93-6650-4c08-91a0-c089ccff23a8 + + + + + + + + + rmf-469d5c3d-c697-40a6-b9f0-977d984cef23 + + + rmf-ffe7ce07-7098-434f-a1e1-7d88d6ade42b + + + + + rmf-46b238ac-b8b3-4230-b32c-be9707f8b691 + + + rmf-daa34638-061a-45e0-9f2e-35afd6c271e0 + + + rmf-a5248a1f-1c78-4fec-92ac-1163f12712c8 + + + + + + + rmf-469d5c3d-c697-40a6-b9f0-977d984cef23 + + + rmf-ffe7ce07-7098-434f-a1e1-7d88d6ade42b + + + + + rmf-46b238ac-b8b3-4230-b32c-be9707f8b691 + + + rmf-4ae63c6f-fa76-48e9-8def-c323f38c148a + + + rmf-a5248a1f-1c78-4fec-92ac-1163f12712c8 + + + + + + + rmf-469d5c3d-c697-40a6-b9f0-977d984cef23 + + + rmf-ffe7ce07-7098-434f-a1e1-7d88d6ade42b + + + + + rmf-46b238ac-b8b3-4230-b32c-be9707f8b691 + + + rmf-03dcf3ff-56b0-47b4-bb0f-79c5fc2dd1ed + + + rmf-a5248a1f-1c78-4fec-92ac-1163f12712c8 + + + + + + + + + rmf-da47fa51-2baa-4cc4-9260-a6e0518d1fed + + + + + rmf-972f7367-4799-4265-97cf-436855a9d141 + + + + + rmf-daa34638-061a-45e0-9f2e-35afd6c271e0 + + + + + rmf-06585be7-6195-4726-bac8-4442405615c8 + + + + + rmf-ca127803-35cb-4fc2-a877-7db32b1c625d + + + + + rmf-374b6cb7-20d6-40e1-bdfd-7ec83bc0d680 + + + + + + + rmf-d9c5c6f1-29f4-45db-8880-005b645c0898 + + + + + rmf-f08fad06-2d2c-4cc8-bfb4-0bad21fb165d + + + + + rmf-998f782c-0914-48ab-84d2-4bcbdac42de8 + + + + + rmf-709e797b-80c2-4c9e-830a-4cfcba2face4 + + + + + rmf-8d28ded4-589d-4eda-8583-d7aee1a5d4ad + + + + + rmf-10e731ff-e9f1-4c48-8f5b-283259551f4f + + + + + + + rmf-4c97c990-b5b8-40f4-a446-c2bb3cbaba8b + + + + + rmf-88674113-ad7b-4a29-9545-358712f7d2c1 + + + + + rmf-fe016219-4e31-4e12-9573-91a7843bfdd5 + + + + + + + rmf-18b2b98b-3827-4dde-b6e8-64d8e4b59fbb + + + + + rmf-2a56876a-652b-4326-afb0-a94ed8d826f8 + + + + + + + + + rmf-4ae63c6f-fa76-48e9-8def-c323f38c148a + + + + + rmf-167dd84e-4217-4842-92ae-7896e4392330 + + + + + rmf-184a288d-ab7f-4bec-9e48-fab078b4cbc2 + + + + + + + rmf-ff321f43-8287-4a7e-aa35-5fc07df39506 + + + + + rmf-bbc32ba7-1e72-49f0-b829-b7187469aecc + + + + + rmf-6fa46c90-9da8-4d7e-b29c-64362ed6a95d + + + + + rmf-0b865124-37d7-4944-9d19-d65a392a7022 + + + + + rmf-14a6c61a-2077-4777-98ce-1c9ef5569c37 + + + + + rmf-2704c247-cfd6-4f5b-99fa-9fd90ad962ed + + + + + + + rmf-7383d331-43b3-453a-b796-ccc3425cbf3e + + + + + rmf-cc39f3c7-4bcd-4654-9d93-763680c810c1 + + + + + + + + + rmf-03dcf3ff-56b0-47b4-bb0f-79c5fc2dd1ed + + + + + rmf-2f2a6915-f6c9-44c6-ae52-42f8113fefd1 + + + + + rmf-8d8ed8d8-c592-4967-bdf2-b3a690c3f028 + + + + + + + rmf-4748fd33-ff33-478c-a498-c8b6f4f00da2 + + + + + rmf-2f4a3ce9-6840-4421-8d78-d4f934e07d15 + + + + + + + rmf-f0293d66-ef17-4f91-afb7-e99059efaeb6 + + + + + rmf-a4fb8ab7-94a7-452d-ac51-7c0a7f3ab5a4 + + + + + + + + + + + + + rmf-da47fa51-2baa-4cc4-9260-a6e0518d1fed + + + + + rmf-972f7367-4799-4265-97cf-436855a9d141 + + + + + rmf-bddec400-cb00-479b-94df-758e11a93c5d + + + + + rmf-46b238ac-b8b3-4230-b32c-be9707f8b691 + + + + + rmf-e5ef19d9-cb4a-4647-a90b-c3be0c71ed3e + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ID + Description + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.marker.ui/examples/ReqifExample/RMF_SoftwareRequirementsSpecification.reqif b/Source/eu.modelwriter.marker.ui/examples/ReqifExample/RMF_SoftwareRequirementsSpecification.reqif new file mode 100644 index 00000000..b77aa837 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/examples/ReqifExample/RMF_SoftwareRequirementsSpecification.reqif @@ -0,0 +1,1851 @@ + + + + + Created by: broerkens + 2013-06-05T19:46:16.795+02:00 + ProR (http://pror.org) + 1.0.1 + ProR (http://pror.org) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rmf-fa6300d0-9e8b-4b57-a6ff-10a6bc76e604 + + + + + rmf-1d2c140f-97e9-4d11-9554-63b2bee2dc3c + + + + + rmf-fa6300d0-9e8b-4b57-a6ff-10a6bc76e604 + + + + + rmf-fa6300d0-9e8b-4b57-a6ff-10a6bc76e604 + + + + + rmf-cf80ba48-e543-46d8-99b0-acbdc6541dd9 + + + + + rmf-4a32761e-e015-4696-9578-0be539234b9f + + + + + rmf-6e670f38-1929-4146-861e-882b4b93bc84 + + + + + rmf-fa6300d0-9e8b-4b57-a6ff-10a6bc76e604 + + + + + + + + + rmf-fa6300d0-9e8b-4b57-a6ff-10a6bc76e604 + + + + + + + + + rmf-95898f85-f196-475f-8d35-f8db9d9e2dd0 + + + + + rmf-1d2c140f-97e9-4d11-9554-63b2bee2dc3c + + + + + + + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-865b84f0-9116-4b14-a2b9-034ece715cfe + + + + + rmf-8d8693e2-8851-44ec-ac00-343f614049a7 + + + rmf-db7072bd-787f-43f2-a1b4-a62be59cdce6 + + + + + rmf-0f3f6982-0e71-4f95-b645-10567f212bd2 + + + rmf-f91c4793-2f18-44a8-a202-056f2788ef2a + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-d1d72ec9-23ee-4a7f-8471-1d8cca0635d9 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-d1d72ec9-23ee-4a7f-8471-1d8cca0635d9 + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-865b84f0-9116-4b14-a2b9-034ece715cfe + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-8d8693e2-8851-44ec-ac00-343f614049a7 + + + rmf-db7072bd-787f-43f2-a1b4-a62be59cdce6 + + + + + rmf-0f3f6982-0e71-4f95-b645-10567f212bd2 + + + rmf-f91c4793-2f18-44a8-a202-056f2788ef2a + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-d1d72ec9-23ee-4a7f-8471-1d8cca0635d9 + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-865b84f0-9116-4b14-a2b9-034ece715cfe + + + + + rmf-8d8693e2-8851-44ec-ac00-343f614049a7 + + + rmf-db7072bd-787f-43f2-a1b4-a62be59cdce6 + + + + + rmf-0f3f6982-0e71-4f95-b645-10567f212bd2 + + + rmf-f91c4793-2f18-44a8-a202-056f2788ef2a + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-9cda8d7a-80a7-4096-96ca-3ab1393f4bb7 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-f91c4793-2f18-44a8-a202-056f2788ef2a + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-8d8693e2-8851-44ec-ac00-343f614049a7 + + + rmf-db7072bd-787f-43f2-a1b4-a62be59cdce6 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-8d8693e2-8851-44ec-ac00-343f614049a7 + + + rmf-db7072bd-787f-43f2-a1b4-a62be59cdce6 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-865b84f0-9116-4b14-a2b9-034ece715cfe + + + + + rmf-9cda8d7a-80a7-4096-96ca-3ab1393f4bb7 + + + + + rmf-8d8693e2-8851-44ec-ac00-343f614049a7 + + + rmf-db7072bd-787f-43f2-a1b4-a62be59cdce6 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-9cda8d7a-80a7-4096-96ca-3ab1393f4bb7 + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-865b84f0-9116-4b14-a2b9-034ece715cfe + + + + + rmf-8d8693e2-8851-44ec-ac00-343f614049a7 + + + rmf-db7072bd-787f-43f2-a1b4-a62be59cdce6 + + + + + rmf-f91c4793-2f18-44a8-a202-056f2788ef2a + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-d1d72ec9-23ee-4a7f-8471-1d8cca0635d9 + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-865b84f0-9116-4b14-a2b9-034ece715cfe + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-865b84f0-9116-4b14-a2b9-034ece715cfe + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-865b84f0-9116-4b14-a2b9-034ece715cfe + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-9cda8d7a-80a7-4096-96ca-3ab1393f4bb7 + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-865b84f0-9116-4b14-a2b9-034ece715cfe + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-9cda8d7a-80a7-4096-96ca-3ab1393f4bb7 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-9cda8d7a-80a7-4096-96ca-3ab1393f4bb7 + + + + + rmf-db7072bd-787f-43f2-a1b4-a62be59cdce6 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-db7072bd-787f-43f2-a1b4-a62be59cdce6 + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-9cda8d7a-80a7-4096-96ca-3ab1393f4bb7 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-9cda8d7a-80a7-4096-96ca-3ab1393f4bb7 + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-865b84f0-9116-4b14-a2b9-034ece715cfe + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-865b84f0-9116-4b14-a2b9-034ece715cfe + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-9cda8d7a-80a7-4096-96ca-3ab1393f4bb7 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + + + rmf-29caa81f-0653-4754-b564-b6e97a73658e + + + + + rmf-b37ec177-5ebb-4b78-8626-b453cf6e1784 + + + + + rmf-98d872e4-145b-4520-8430-f51ff773b6a4 + + + + + rmf-226476e2-82e5-462b-9955-631e82efe981 + + + + + rmf-266b5236-5142-4459-9f9e-f3e5becf1fdc + + + + + rmf-0ea65654-db66-4b72-a8fb-4fc8fcb6126b + + + + + rmf-77744838-24e1-4ced-8e84-b3ecf2cd51a9 + + + + + rmf-666df803-95e6-43cc-889d-96e0b9e81b79 + + + + + rmf-45e2f0ea-c771-4c27-bddc-cd9b3c963f9f + + + + + rmf-e9ab0b39-e81a-4ca1-b574-17cb84b2ceb2 + + + + + rmf-cf7052f0-3fc8-4681-9d5c-f4e0bf216bb6 + + + + + rmf-8dd54590-45a1-4be4-bc12-e16655b02eed + + + + + rmf-914d3b59-8e52-4784-983a-04abde259980 + + + + + rmf-706411cc-9a88-430c-b4df-46512530fce2 + + + + + + + rmf-88c96539-c829-4ea1-9a45-7125ad76715e + + + + + rmf-3daf6f18-b4c4-4dec-b936-8d42c5c37767 + + + + + rmf-ef553dbe-9bdf-40ee-9692-b393b351b280 + + + + + rmf-0f906c4c-449b-4a9e-a4b8-42e035516025 + + + + + + + + + rmf-1a4974f1-89e3-4c38-8694-fa2e846a3fd6 + + + + + rmf-61903909-b396-4673-bdb1-7c1f412d7cf3 + + + + + + + rmf-d0dabe58-8ef8-4403-b979-fd86192ebd10 + + + + + rmf-c37dae6d-0393-4975-9350-ac2ede0677f9 + + + + + + rmf-bc4b5966-07b2-4ae0-bb16-7529ff660f98 + + + + + + + rmf-dc2e5fae-12a1-43ae-be30-73a97febac1f + + + + + rmf-32368ba3-e7b5-449d-85af-466aa280036e + + + + + rmf-2f5c544a-3b6c-4bd8-b395-3c2fa556a73a + + + + + rmf-1ab93c91-3fa3-48ce-b3a3-a7f7a3ee9a40 + + + + + + + rmf-1d92c7ca-2895-40a0-9797-2771e3b109ea + + + + + rmf-1f82b4a3-848b-41a6-b907-a7fbdbdf02ec + + + + + rmf-f0fabd82-5c39-4cdb-a590-223ac71f6c92 + + + + + + rmf-d2799faa-2541-43e4-bf9b-b4efabb13f65 + + + + + rmf-ed717550-6fad-43e1-accc-a6e85805eb4c + + + + + + + + + rmf-a3222eed-eaeb-443b-a0f5-cdfeceaf0c63 + + + + + rmf-bfe30c91-65b9-45c2-b80c-cbf237fd8140 + + + + + + + rmf-209e4b7d-65f4-41f0-9789-41235b228b1b + + + + + rmf-c8af1f71-4f7a-4d2c-b404-702572a1fa80 + + + + + + + rmf-ed6aec59-6ebe-4ebb-accb-597859db7424 + + + + + + + rmf-da90477e-d906-4d3f-bc2e-c727464bda40 + + + + + rmf-6ea23d71-6703-4471-9ed3-fabcfcf4b6a3 + + + + + rmf-a1dce487-12e8-4d65-945d-83d143f76d15 + + + + + rmf-7672d601-9035-4b83-83a5-8980d04ebfce + + + + + rmf-d9a46d65-4708-4d4c-bd6d-47566f5d4269 + + + + + rmf-b75dd3a4-6272-4b1c-9dc7-23657c6354f0 + + + + + rmf-3abb1510-285c-4e64-a921-d2379c18dae8 + + + + + rmf-9543e66f-bbd6-4c85-a28e-9f62ae7433d8 + + + + + rmf-1fc1412f-703c-4259-8b54-ca989d71ca97 + + + + + rmf-8a4b5f33-0b7e-404f-bd79-223e790705bd + + + + + rmf-468d274f-73dd-44a1-b6c3-b56dfa0088fc + + + + + + + rmf-b9e0a4e4-f73a-489b-bea0-45de9e1693f0 + + + + + rmf-2a06c9fe-201b-4d1f-b028-0579ba57a5f0 + + + + + rmf-bc6e9b80-45bd-4b38-8327-10cdbe38ceb8 + + + + + rmf-5af4a260-839d-4e98-a9ce-2195395ae47a + + + + + rmf-69e035b3-02fd-436a-83bd-d83effcd0387 + + + + + rmf-7fc15d18-596a-445b-aa71-d753ae814ae8 + + + + + rmf-69055d2c-a6ee-4ee8-8e49-bd727d0ea04a + + + + + rmf-c7e8299b-4938-4943-b8d1-d522b9c236e9 + + + + + rmf-b53c6fdd-9154-48de-ba81-b8c475123795 + + + + + + + + + rmf-bf80257b-429a-4425-9212-161391b150fc + + + + + rmf-09a634a7-59ef-4c87-aeaa-12856f46bbf0 + + + + + rmf-0ad4019b-2034-4689-92bd-c869fe23d120 + + + + + + + rmf-c6a2b4ce-d751-4079-ad03-ffa89f94241d + + + + + rmf-ebfd53fd-c581-4eba-935d-4450d9f8925d + + + + + rmf-2c3d9b2b-70c7-47a4-8e7e-97391904f0b1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Title + Description + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.marker.ui/examples/ReqifExample/RMF_SoftwareSpecification.reqif b/Source/eu.modelwriter.marker.ui/examples/ReqifExample/RMF_SoftwareSpecification.reqif new file mode 100644 index 00000000..da05c771 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/examples/ReqifExample/RMF_SoftwareSpecification.reqif @@ -0,0 +1,969 @@ + + + + + Created by: broerkens + 2013-06-05T19:46:16.795+02:00 + ProR (http://pror.org) + 1.0.1 + ProR (http://pror.org) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rmf-fa6300d0-9e8b-4b57-a6ff-10a6bc76e604 + + + + + rmf-1d2c140f-97e9-4d11-9554-63b2bee2dc3c + + + + + rmf-fa6300d0-9e8b-4b57-a6ff-10a6bc76e604 + + + + + rmf-fa6300d0-9e8b-4b57-a6ff-10a6bc76e604 + + + + + rmf-cf80ba48-e543-46d8-99b0-acbdc6541dd9 + + + + + rmf-4a32761e-e015-4696-9578-0be539234b9f + + + + + rmf-6e670f38-1929-4146-861e-882b4b93bc84 + + + + + rmf-fa6300d0-9e8b-4b57-a6ff-10a6bc76e604 + + + + + + + + + rmf-fa6300d0-9e8b-4b57-a6ff-10a6bc76e604 + + + + + + + + + rmf-95898f85-f196-475f-8d35-f8db9d9e2dd0 + + + + + rmf-1d2c140f-97e9-4d11-9554-63b2bee2dc3c + + + + + + + + + rmf-fa6300d0-9e8b-4b57-a6ff-10a6bc76e604 + + + + + rmf-fa6300d0-9e8b-4b57-a6ff-10a6bc76e604 + + + + + rmf-fa6300d0-9e8b-4b57-a6ff-10a6bc76e604 + + + + + rmf-fa6300d0-9e8b-4b57-a6ff-10a6bc76e604 + + + + + + + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-dbae7385-ede7-4feb-a9f7-0307021a2ba3 + + + + + rmf-69dda60a-262f-405f-9716-6b35c34d502b + + + + + rmf-f9375e1b-668c-4625-8ade-bc061ba737ef + + + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-865b84f0-9116-4b14-a2b9-034ece715cfe + + + + + rmf-9cda8d7a-80a7-4096-96ca-3ab1393f4bb7 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + rmf-f9375e1b-668c-4625-8ade-bc061ba737ef + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-865b84f0-9116-4b14-a2b9-034ece715cfe + + + + + rmf-9cda8d7a-80a7-4096-96ca-3ab1393f4bb7 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-865b84f0-9116-4b14-a2b9-034ece715cfe + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-865b84f0-9116-4b14-a2b9-034ece715cfe + + + + + rmf-9cda8d7a-80a7-4096-96ca-3ab1393f4bb7 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-150a04f0-8369-4faa-b884-b1477b1764e8 + + + + + rmf-865b84f0-9116-4b14-a2b9-034ece715cfe + + + + + rmf-9cda8d7a-80a7-4096-96ca-3ab1393f4bb7 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-dbae7385-ede7-4feb-a9f7-0307021a2ba3 + + + + + rmf-69dda60a-262f-405f-9716-6b35c34d502b + + + + + rmf-19b3693b-4688-4a80-b67f-fa01171fdcd3 + + + + + rmf-f9375e1b-668c-4625-8ade-bc061ba737ef + + + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + rmf-f9375e1b-668c-4625-8ade-bc061ba737ef + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-9cda8d7a-80a7-4096-96ca-3ab1393f4bb7 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-cc50ba36-d57a-4a45-87d0-d40a50f159d3 + + + + + rmf-e021cb76-2196-4285-96b2-a95035812994 + + + + + rmf-3e0b6fad-930b-4d9e-92fd-b84619282414 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + rmf-b029ab42-aeb9-420e-ba50-95038d07b56d + + + + + rmf-0b23aa34-c242-41a0-9157-6062df61ff98 + + + + + rmf-e7aa3d46-6556-45bd-969b-d7534fa97ad1 + + + + + + + + + rmf-29caa81f-0653-4754-b564-b6e97a73658e + + + + + rmf-b37ec177-5ebb-4b78-8626-b453cf6e1784 + + + + + rmf-2aba2be7-4153-4909-ab3e-c7322dddfc77 + + + + + rmf-b4682a3d-17b7-49e3-8703-81175b8fd1ec + + + + + rmf-3de105c1-9def-41d5-9252-67196b67e0a9 + + + + + rmf-eb9f8597-1fff-499f-9cbb-00259875e19f + + + + + + + rmf-78d13d85-c868-43c5-981c-23af115a0397 + + + + + rmf-1eda0fe9-c976-4502-83fc-3b1066511482 + + + + + rmf-4f387840-7f53-433c-a608-f4ca23181bbb + + + + + rmf-4a9f332a-7567-4bf7-a5d2-382e413ebb44 + + + + + rmf-886c647d-d99e-4209-a416-9b0b24d41e98 + + + + + + + rmf-5fd31c09-ebe1-4016-a16a-87f5b80c6503 + + + + + rmf-c5759d26-3eb3-4fc7-8352-a75ef527a6e2 + + + + + + rmf-b9828d53-7998-4e13-a9de-a03349bef120 + + + + + rmf-229840aa-e229-4455-a54d-959cca090ab2 + + + + + + rmf-d63cd70d-8704-4a3c-ad53-e5e7a2ddc24c + + + + + rmf-22102d12-a2e5-4cdc-8114-f31791fb4664 + + + + + + rmf-5f8ea0c0-ea0d-4619-9d4f-ecd77c405b5e + + + + + rmf-fcbb65a6-3ebb-4d09-beeb-acdf9f429ef2 + + + + + + rmf-c667befa-2101-42a2-9cd0-6fa6df9e4b5a + + + + + + rmf-9937088b-72c6-48f9-b662-0c4839df68fb + + + + + + rmf-6ad8d85a-af3a-4424-bf02-c4e8e7cb60fc + + + + + rmf-0ac87315-2f7e-4505-bd24-e970eb0131a0 + + + + + + + rmf-87ffc8f5-606b-4367-b9a0-1ebc14cf88b5 + + + + + rmf-e5b0521a-4b1e-4ce1-9114-836f6ca704ae + + + + + + + rmf-46d3e044-7b70-4a24-9974-41b9bea68cfb + + + + + + rmf-dcc7ce51-0136-44c2-be64-4059dfd57cf2 + + + + + rmf-467ab4be-b9a1-4628-9390-8bd257028291 + + + + + + + rmf-c0bab682-eaa5-4965-9c11-a8bffd2770a4 + + + + + rmf-ec76d21c-6f26-4751-877b-e08cfbc6aee7 + + + + + rmf-c6e51277-1e5d-4d99-bc39-e8640268e262 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Title + Description + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.marker.ui/examples/ReqifExample/RMF_lastChanged_Specification.reqif b/Source/eu.modelwriter.marker.ui/examples/ReqifExample/RMF_lastChanged_Specification.reqif new file mode 100644 index 00000000..8cabf8f5 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/examples/ReqifExample/RMF_lastChanged_Specification.reqif @@ -0,0 +1,480 @@ + + + + + Created by: lukas + 2013-06-21T14:04:20.944+02:00 + ProR (http://pror.org) + 1.0.1 + ProR (http://pror.org) + + + + + + + + + + + + + + rmf-65899d3f-1253-4864-8ec9-21003dcbb0aa + + + + + rmf-65899d3f-1253-4864-8ec9-21003dcbb0aa + + + + + + + + + rmf-65899d3f-1253-4864-8ec9-21003dcbb0aa + + + + + + + + + rmf-b04a30c7-7a5d-4518-9035-3f9bc6e8dbf3 + + + + + + + + + + + rmf-2733875e-81d6-4ccb-99af-9b4f1aaebd5e + + + + + rmf-9acad2f7-476f-4ed6-80fa-c8038a47196f + + + + + rmf-3a4c2e51-e941-439c-9599-4b7ca2e663b5 + + + + + + + rmf-2733875e-81d6-4ccb-99af-9b4f1aaebd5e + + + + + rmf-9acad2f7-476f-4ed6-80fa-c8038a47196f + + + + + rmf-3a4c2e51-e941-439c-9599-4b7ca2e663b5 + + + + + + + rmf-2733875e-81d6-4ccb-99af-9b4f1aaebd5e + + + + + rmf-9acad2f7-476f-4ed6-80fa-c8038a47196f + + + + + rmf-3a4c2e51-e941-439c-9599-4b7ca2e663b5 + + + + + + + rmf-2733875e-81d6-4ccb-99af-9b4f1aaebd5e + + + + + rmf-9acad2f7-476f-4ed6-80fa-c8038a47196f + + + + + rmf-3a4c2e51-e941-439c-9599-4b7ca2e663b5 + + + + + + + rmf-2733875e-81d6-4ccb-99af-9b4f1aaebd5e + + + + + rmf-9acad2f7-476f-4ed6-80fa-c8038a47196f + + + + + rmf-3a4c2e51-e941-439c-9599-4b7ca2e663b5 + + + + + + + rmf-2733875e-81d6-4ccb-99af-9b4f1aaebd5e + + + + + rmf-9acad2f7-476f-4ed6-80fa-c8038a47196f + + + + + rmf-3a4c2e51-e941-439c-9599-4b7ca2e663b5 + + + + + + + rmf-2733875e-81d6-4ccb-99af-9b4f1aaebd5e + + + + + rmf-9acad2f7-476f-4ed6-80fa-c8038a47196f + + + + + rmf-3a4c2e51-e941-439c-9599-4b7ca2e663b5 + + + + + + + rmf-2733875e-81d6-4ccb-99af-9b4f1aaebd5e + + + + + rmf-9acad2f7-476f-4ed6-80fa-c8038a47196f + + + + + rmf-3a4c2e51-e941-439c-9599-4b7ca2e663b5 + + + + + + + rmf-2733875e-81d6-4ccb-99af-9b4f1aaebd5e + + + + + rmf-9acad2f7-476f-4ed6-80fa-c8038a47196f + + + + + rmf-3a4c2e51-e941-439c-9599-4b7ca2e663b5 + + + + + + + rmf-2733875e-81d6-4ccb-99af-9b4f1aaebd5e + + + + + rmf-9acad2f7-476f-4ed6-80fa-c8038a47196f + + + + + rmf-3a4c2e51-e941-439c-9599-4b7ca2e663b5 + + + + + + + rmf-2733875e-81d6-4ccb-99af-9b4f1aaebd5e + + + + + rmf-9acad2f7-476f-4ed6-80fa-c8038a47196f + + + + + rmf-3a4c2e51-e941-439c-9599-4b7ca2e663b5 + + + + + + + rmf-2733875e-81d6-4ccb-99af-9b4f1aaebd5e + + + + + rmf-3a4c2e51-e941-439c-9599-4b7ca2e663b5 + + + + + + + rmf-2733875e-81d6-4ccb-99af-9b4f1aaebd5e + + + + + rmf-3a4c2e51-e941-439c-9599-4b7ca2e663b5 + + + + + + + rmf-2733875e-81d6-4ccb-99af-9b4f1aaebd5e + + + + + rmf-9acad2f7-476f-4ed6-80fa-c8038a47196f + + + + + rmf-3a4c2e51-e941-439c-9599-4b7ca2e663b5 + + + + + + + rmf-2733875e-81d6-4ccb-99af-9b4f1aaebd5e + + + + + rmf-3a4c2e51-e941-439c-9599-4b7ca2e663b5 + + + + + + + rmf-2733875e-81d6-4ccb-99af-9b4f1aaebd5e + + + + + rmf-3a4c2e51-e941-439c-9599-4b7ca2e663b5 + + + + + + + rmf-6ea1d948-4f1b-4a3d-8e20-e3a22b382fb0 + + + + + rmf-d69d2ef8-2528-45eb-a7cb-fbd8f6d7be89 + + + + + + + rmf-6ea1d948-4f1b-4a3d-8e20-e3a22b382fb0 + + + + + rmf-d69d2ef8-2528-45eb-a7cb-fbd8f6d7be89 + + + + + + + + + rmf-9ec634e3-348c-4297-8192-9627b44ea5ba + + + + + rmf-01632d0b-a7d5-47c2-aa5e-edd9e0c55aa2 + + + + + rmf-71d2a259-84a0-43f5-aadd-6c795fe5c378 + + + + + rmf-d7131a9f-56ae-43bd-a91e-eae74131754a + + + + + rmf-9cc93e54-9264-4c2c-a80c-7200d3b7bdb0 + + + + + rmf-22eeaa9a-d3c5-4b29-aba6-39fdeff5cf0b + + + + + rmf-19330b84-628d-498b-bc5d-64ad0ac43d96 + + + + + rmf-67d02249-3dcb-4a07-86b1-4b014112bedf + + + + + rmf-0bc954a2-a10c-4a6e-be91-fbab7b537090 + + + + + rmf-559e6dcb-525e-4d0e-b106-900e3c4d612c + + + + + + + rmf-a6761494-4bba-4a33-898d-2d69fb94e85b + + + + + rmf-899ece15-efa7-49cb-8225-61a88589f2c4 + + + + + rmf-540d5b91-6cba-4b39-9b7c-3ea9e0f0143c + + + + + rmf-18fcf3fc-80dd-4802-9bf3-55768d4de639 + + + + + + + rmf-7306e3e4-2888-43c1-9ae5-056ac348d141 + + + + + rmf-474f20ff-bbe0-4abb-8139-ebc296bd4e31 + + + + + rmf-827445d4-646c-427f-93be-b603bb1270f9 + + + + + rmf-cdd2a151-da85-47bf-bb06-16a6871f4d81 + + + + + + + + rmf-a901b508-79e5-4c01-b22a-018629eb02bd + + + + + rmf-357c820a-67f5-41e1-a691-632d8af5f50a + + + + + + + + + + + + + + + + + + + + + + + + + + + + Description + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.marker.ui/examples/TextExample/Java.java b/Source/eu.modelwriter.marker.ui/examples/TextExample/Java.java new file mode 100644 index 00000000..acda7c41 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/examples/TextExample/Java.java @@ -0,0 +1,37 @@ +package eu.modelwriter.marker.ui.internal.wizards.examplewizard.examples.TextExample; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class Java implements BundleActivator { + + private static BundleContext context; + + static BundleContext getContext() { + return Java.context; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(final BundleContext bundleContext) throws Exception { + Java.context = bundleContext; + + + } + + /* + * (non-Javadoc) + * + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + @Override + public void stop(final BundleContext bundleContext) throws Exception { + Java.context = null; + } + + +} diff --git a/Source/eu.modelwriter.marker.ui/examples/TextExample/Markdown.md b/Source/eu.modelwriter.marker.ui/examples/TextExample/Markdown.md new file mode 100644 index 00000000..d7592ab0 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/examples/TextExample/Markdown.md @@ -0,0 +1,67 @@ +#Customer Requirements Specification + +##UC-1 Create a new SpecObject + +Note that the Specification Editor is the main interface for users. Therefore, creating SpecObjects in this editor is the main success scenario. + +###Precondition + +ReqIF model exists and is open. + +###Main Success Scenario + +We assume that a Specification exists and is open (not required for alternative scenario) + +Open a row's context menu (or in the empty editor space) + +Select the Child or Sibling submenu. + +Select the desired Spec Object Type (or none) from the submenu. + +This results in a new SpecHierarchy being created that is linked to a newly created SpecObject with the correct type. + +###Alternative 1: Create in Outline + +The same workflow works for elements that are shown underneath "Specifications" in the outilne. + +It is also possible to create children of the "SpecObjects" folder in the outline, but in this case, no SpecHirarchy will be created. + +###Alternative 2: Keyboard Shortcut + +The keyboard shortcut Ctrl-Enter will create a SpecHierarchy sibling to the currently selected element and immediately go into edit mode in the currently selected column. + +##UC-2 Edit SpecObject + +###Precondition + +A ReqIF model exists, is open and at least one SpecObject exisits. + +###Main Success Scenario + +We assume that a Specification exists and is open (not required for alternative scenario) + +Double click on the cell in the Specification Editor to be edited. + +Alternatively, hit enter or space in that cell + +In both cases, the double-clicked / selected cell will switch to edit mode. + +Note that some cells may not be editable, in which case nothing will happen. + +###Alternative 1: Edit in Properties View + +A selected element (no matter whether in Specification Editor or Outline or elsewhere) will be shown in the Properties View, where editing of all values is possible. + +##UC-3 Delete SpecObject + +###Precondition + +A ReqIF model exists, is open and at least one SpecObject exists. + +###Main Success Scenario + +If an element is deleted from the specification (so essentially a SpecHierarchy), and no references to the associated SpecObject exist, then that SpecObject should be deleted as well. Otherwise, only the SpecHierarchy will be removed. + +###Alternative 1: Delete in SpecObjects folder in Outline + +If the SpecObject is deleted from the SpecObjects folder in the ouline, it will be removed, no matter what. This may result in SpecHierarchies that are not referencing any SpecObjects. \ No newline at end of file diff --git a/Source/eu.modelwriter.marker.ui/examples/TextExample/Modelwriter.mw b/Source/eu.modelwriter.marker.ui/examples/TextExample/Modelwriter.mw new file mode 100644 index 00000000..8f96c729 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/examples/TextExample/Modelwriter.mw @@ -0,0 +1,3 @@ +The objective of the ModelWriter project is to bring a quantum leap in the productivity of technical authors (such as software or systems engineers, project managers, business developers, etc.) who are engaged in authoring documents of a technical nature. The project also aims to improve the quality (consistency, completeness) of these documents that, in turn, will enhance the quality of companies� products, e.g. via a reduction of cost of product defects. Finally, ModelWriter aims also to allow companies to further exploit, recycle and valorise their own internal knowledge, which is currently left unexploited in technical documents that are seen as a sequence of words only. To achieve this, the project envisions an integrated authoring environment called "ModelWriter", which will be locally used by each author / contributor. + +This will combine two parts, a semantic word processor (= the "Writer" part), which resembles a typical word processor but capable of "understanding" pieces of text and transparently creating models of contents out of them, and a Knowledge Capture Tool (= the "Model" part), which resembles a spreadsheet table, or other familiar information modelling tools. \ No newline at end of file diff --git a/Source/eu.modelwriter.marker.ui/examples/TextExample/Text.txt b/Source/eu.modelwriter.marker.ui/examples/TextExample/Text.txt new file mode 100644 index 00000000..8f96c729 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/examples/TextExample/Text.txt @@ -0,0 +1,3 @@ +The objective of the ModelWriter project is to bring a quantum leap in the productivity of technical authors (such as software or systems engineers, project managers, business developers, etc.) who are engaged in authoring documents of a technical nature. The project also aims to improve the quality (consistency, completeness) of these documents that, in turn, will enhance the quality of companies� products, e.g. via a reduction of cost of product defects. Finally, ModelWriter aims also to allow companies to further exploit, recycle and valorise their own internal knowledge, which is currently left unexploited in technical documents that are seen as a sequence of words only. To achieve this, the project envisions an integrated authoring environment called "ModelWriter", which will be locally used by each author / contributor. + +This will combine two parts, a semantic word processor (= the "Writer" part), which resembles a typical word processor but capable of "understanding" pieces of text and transparently creating models of contents out of them, and a Knowledge Capture Tool (= the "Model" part), which resembles a spreadsheet table, or other familiar information modelling tools. \ No newline at end of file diff --git a/Source/eu.modelwriter.marker.ui/examples/TextExample/XML.xml b/Source/eu.modelwriter.marker.ui/examples/TextExample/XML.xml new file mode 100644 index 00000000..e3d1fe87 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/examples/TextExample/XML.xml @@ -0,0 +1,120 @@ + + + + Gambardella, Matthew + XML Developer's Guide + Computer + 44.95 + 2000-10-01 + An in-depth look at creating applications + with XML. + + + Ralls, Kim + Midnight Rain + Fantasy + 5.95 + 2000-12-16 + A former architect battles corporate zombies, + an evil sorceress, and her own childhood to become queen + of the world. + + + Corets, Eva + Maeve Ascendant + Fantasy + 5.95 + 2000-11-17 + After the collapse of a nanotechnology + society in England, the young survivors lay the + foundation for a new society. + + + Corets, Eva + Oberon's Legacy + Fantasy + 5.95 + 2001-03-10 + In post-apocalypse England, the mysterious + agent known only as Oberon helps to create a new life + for the inhabitants of London. Sequel to Maeve + Ascendant. + + + Corets, Eva + The Sundered Grail + Fantasy + 5.95 + 2001-09-10 + The two daughters of Maeve, half-sisters, + battle one another for control of England. Sequel to + Oberon's Legacy. + + + Randall, Cynthia + Lover Birds + Romance + 4.95 + 2000-09-02 + When Carla meets Paul at an ornithology + conference, tempers fly as feathers get ruffled. + + + Thurman, Paula + Splish Splash + Romance + 4.95 + 2000-11-02 + A deep sea diver finds true love twenty + thousand leagues beneath the sea. + + + Knorr, Stefan + Creepy Crawlies + Horror + 4.95 + 2000-12-06 + An anthology of horror stories about roaches, + centipedes, scorpions and other insects. + + + Kress, Peter + Paradox Lost + Science Fiction + 6.95 + 2000-11-02 + After an inadvertant trip through a Heisenberg + Uncertainty Device, James Salway discovers the problems + of being quantum. + + + O'Brien, Tim + Microsoft .NET: The Programming Bible + Computer + 36.95 + 2000-12-09 + Microsoft's .NET initiative is explored in + detail in this deep programmer's reference. + + + O'Brien, Tim + MSXML3: A Comprehensive Guide + Computer + 36.95 + 2000-12-01 + The Microsoft MSXML3 parser is covered in + detail, with attention to XML DOM interfaces, XSLT processing, + SAX and more. + + + Galos, Mike + Visual Studio 7: A Comprehensive Guide + Computer + 49.95 + 2001-04-16 + Microsoft Visual Studio 7 is explored in depth, + looking at how Visual Basic, Visual C++, C#, and ASP+ are + integrated into a comprehensive development + environment. + + \ No newline at end of file diff --git a/Source/eu.modelwriter.marker.ui/lib/alloy4.2.jar b/Source/eu.modelwriter.marker.ui/lib/alloy4.2.jar new file mode 100644 index 00000000..3be21612 Binary files /dev/null and b/Source/eu.modelwriter.marker.ui/lib/alloy4.2.jar differ diff --git a/Source/eu.modelwriter.marker.ui/plugin.xml b/Source/eu.modelwriter.marker.ui/plugin.xml new file mode 100644 index 00000000..287063b6 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/plugin.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Creates the Model Writer example projects. + + + + + + diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/Activator.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/Activator.java new file mode 100644 index 00000000..fc74417a --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/Activator.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +import eu.modelwriter.configuration.alloy.trace.TraceException; +import eu.modelwriter.configuration.alloy.trace.TraceManager; +import eu.modelwriter.marker.ui.internal.views.visualizationview.commands.TraceObserver; +import eu.modelwriter.marker.ui.internal.views.visualizationview.commands.VisualizationActionListenerFactory; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "eu.modelwriter.marker.ui"; //$NON-NLS-1$ + + // The shared instance + private static Activator plugin; + + /** + * The constructor + */ + public Activator() {} + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + try { + TraceManager.get().loadSpec(getDefault().getDialogSettings().get("alloyFile")); + } catch (TraceException | NullPointerException e) { + // No need to handle + } + VisualizationActionListenerFactory.get().registerListener(TraceObserver.get()); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + VisualizationActionListenerFactory.get().unregisterListener(TraceObserver.get()); + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + + public static Shell getShell() { + return getActiveWorkbenchWindow().getShell(); + } + + public static IWorkbenchWindow getActiveWorkbenchWindow() { + return PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + } + + /** + * Always good to have this static method as when dealing with IResources having a interface to + * get the editor is very handy + * + * @return + */ + public static IEditorPart getEditor() { + return getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + } + + public static MessageDialog infoDialogOK(String title, String message) { + return new MessageDialog(getShell(), title, null, message, MessageDialog.INFORMATION, 0, "OK"); + } + + public static MessageDialog infoDialogYESNO(String title, String message) { + return new MessageDialog(getShell(), title, null, message, MessageDialog.INFORMATION, 0, "Yes", + "No"); + } + + public static MessageDialog errorDialogOK(String title, String message) { + return new MessageDialog(getShell(), title, null, message, MessageDialog.ERROR, 0, "Yes", "No"); + } + + public static MessageDialog errorDialogYESNO(String title, String message) { + return new MessageDialog(getShell(), title, null, message, MessageDialog.ERROR, 0, "Yes", "No"); + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/hyperlinkdetectors/MarkerMappingActionHyperlink.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/hyperlinkdetectors/MarkerMappingActionHyperlink.java new file mode 100644 index 00000000..958a62a7 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/hyperlinkdetectors/MarkerMappingActionHyperlink.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.hyperlinkdetectors; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.hyperlink.IHyperlink; + +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.marker.ui.internal.wizards.mappingwizard.MarkerMapping; + +public class MarkerMappingActionHyperlink implements IHyperlink { + + private final IRegion fUrlRegion; + + public MarkerMappingActionHyperlink(final IRegion urlRegion) { + this.fUrlRegion = urlRegion; + } + + @Override + public IRegion getHyperlinkRegion() { + return this.fUrlRegion; + } + + @Override + public String getHyperlinkText() { + return "Open Mapping Wizard"; + } + + @Override + public String getTypeLabel() { + return null; + } + + @Override + public void open() { + + final IFile file = MarkerActivator.getEditor().getEditorInput().getAdapter(IFile.class); + + final int start = this.fUrlRegion.getOffset(); + final int end = this.fUrlRegion.getOffset() + this.fUrlRegion.getLength(); + final IMarker beMapped = MarkerFactory.findMarkerWithAbsolutePosition(file, start, end); + + if (beMapped != null) { + MarkerMapping.getInstance().runWithMarker(beMapped); + } else { + final MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), "Mark Information", + null, "Something goes wrong with this text fragments", MessageDialog.WARNING, + new String[] {"OK"}, 0); + dialog.open(); + } + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/hyperlinkdetectors/MarkerMappingActionHyperlinkDetector.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/hyperlinkdetectors/MarkerMappingActionHyperlinkDetector.java new file mode 100644 index 00000000..f3de0e8d --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/hyperlinkdetectors/MarkerMappingActionHyperlinkDetector.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.hyperlinkdetectors; + +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector; +import org.eclipse.jface.text.hyperlink.IHyperlink; +import org.eclipse.jface.text.hyperlink.IHyperlinkDetector; + +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class MarkerMappingActionHyperlinkDetector extends AbstractHyperlinkDetector + implements IHyperlinkDetector { + + @Override + public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, + boolean canShowMultipleHyperlinks) { + + int offset = region.getOffset(); + int length = region.getLength(); + if (offset == 0 && length == 0) + return null; + + if (MarkerActivator.getEditor() == null || MarkerActivator.getEditor().getEditorInput() == null) + return null; + + IFile file = (IFile) MarkerActivator.getEditor().getEditorInput().getAdapter(IFile.class); + + List markedList = MarkerFactory.findMarkers(file); + for (IMarker iMarker : markedList) { + // look for keyword + // detect region containing keyword + IRegion targetRegion = new Region(MarkUtilities.getStart(iMarker), + MarkUtilities.getLength(iMarker)); + if ((targetRegion.getOffset() <= offset) + && ((targetRegion.getOffset() + targetRegion.getLength()) > offset)) { + // create link + return new IHyperlink[] {new MarkerMappingActionHyperlink(targetRegion)}; + } + } + return null; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/preferences/MarkerTypePreferencePage.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/preferences/MarkerTypePreferencePage.java new file mode 100644 index 00000000..ca1b26e5 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/preferences/MarkerTypePreferencePage.java @@ -0,0 +1,199 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.preferences; + +import java.io.IOException; +import java.util.ArrayList; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.PlatformUI; + +import eu.modelwriter.configuration.alloy.AlloyParser; +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.Serialization; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.marker.internal.MarkerTypeElement; +import eu.modelwriter.marker.ui.internal.wizards.markerwizard.MarkerPage; +import eu.modelwriter.marker.ui.internal.wizards.markerwizard.MarkerTreeViewContentProvider; +import eu.modelwriter.marker.ui.internal.wizards.markerwizard.MarkerTreeViewLabelProvider; + +public class MarkerTypePreferencePage extends PreferencePage implements IWorkbenchPreferencePage { + private Table table; + + Label lblNewLabel; + + public MarkerTypePreferencePage() {} + + @Override + protected Control createContents(final Composite parent) { + final Composite container = new Composite(parent, SWT.NULL); + + final TreeViewer treeViewer = new TreeViewer(container, SWT.BORDER); + final Tree tree = treeViewer.getTree(); + tree.setBounds(10, 32, 232, 280); + + final MarkerTreeViewContentProvider treeViewerContentProvider = + new MarkerTreeViewContentProvider(); + + treeViewer.setLabelProvider(new MarkerTreeViewLabelProvider()); + treeViewer.setContentProvider(treeViewerContentProvider); + + final TableViewer tableViewer = new TableViewer(container, SWT.BORDER | SWT.FULL_SELECTION); + this.table = tableViewer.getTable(); + this.table.setBounds(254, 32, 365, 280); + + tableViewer.setContentProvider(ArrayContentProvider.getInstance()); + new RefColumn().addColumnTo(tableViewer); + + final Button btnParseAlloy = new Button(container, SWT.NONE); + btnParseAlloy.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(final SelectionEvent e) { + + final MessageDialog warningdialog = + new MessageDialog(MarkerActivator.getShell(), "Mark Information", null, + "If new alloy file will be parsed , your all marker type will be lost !", + MessageDialog.WARNING, new String[] {"OK", "Cancel"}, 0); + if (warningdialog.open() == 1) { + return; + } + + final FileDialog dialog = new FileDialog( + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.OPEN); + dialog.setFilterExtensions(new String[] {"*.mw", "*.als"}); + final String result = dialog.open(); + if (result == null) { + return; + } + + for (final IResource iResource : ResourcesPlugin.getWorkspace().getRoot().getProjects()) { + boolean isClosed = false; + try { + if (!((IProject) iResource).isOpen()) { + isClosed = true; + ((IProject) iResource).open(new NullProgressMonitor()); + } + for (final IMarker iMarker : MarkerFactory.findMarkersAsArrayList(iResource)) { + if (MarkUtilities.getType(iMarker) != null) { + MarkUtilities.setType(iMarker, null); + } + } + if (isClosed == true) { + ((IProject) iResource).close(new NullProgressMonitor()); + } + } catch (final CoreException e1) { + e1.printStackTrace(); + } + } + + MarkerPage.settings.put("alloyFile", result); + + final AlloyParser parser = new AlloyParser(result); + final ArrayList roots = parser.getTypes(); + final ArrayList rels = parser.getRels(); + + final MarkerTypeElement systemRoot = new MarkerTypeElement("universe"); + for (final MarkerTypeElement root : roots) { + systemRoot.getChildren().add(root); + } + + try { + MarkerPage.settings.put("universe", Serialization.getInstance().toString(systemRoot)); + final Object[] array = new Object[1]; + array[0] = systemRoot; + treeViewer.setInput(array); + treeViewer.expandAll(); + MarkerPage.settings.put("rels", Serialization.getInstance().toString(rels)); + tableViewer.setInput(rels); + // auto size columns + final TableColumn[] columns = tableViewer.getTable().getColumns(); + for (int i = 0; i < columns.length; i++) { + columns[i].pack(); + } + MarkerTypePreferencePage.this.lblNewLabel.setText(result); + MarkerTypePreferencePage.this.lblNewLabel.setToolTipText(result); + } catch (final IOException e1) { + e1.printStackTrace(); + } + } + }); + btnParseAlloy.setBounds(10, 320, 75, 25); + btnParseAlloy.setText("Specification"); + + final Label lblMarkerTypes = new Label(container, SWT.NONE); + lblMarkerTypes.setBounds(10, 10, 75, 15); + lblMarkerTypes.setText("Sets"); + + final Label lblRelations = new Label(container, SWT.NONE); + lblRelations.setBounds(254, 10, 55, 15); + lblRelations.setText("Relations"); + + this.lblNewLabel = new Label(container, SWT.WRAP); + this.lblNewLabel.setBounds(91, 325, 498, 72); + if (MarkerPage.settings.get("alloyFile") != null) { + this.lblNewLabel.setText(MarkerPage.settings.get("alloyFile")); + } + this.lblNewLabel.setToolTipText(MarkerPage.settings.get("alloyFile")); + + try { + final String savedTree = MarkerPage.settings.get("universe"); + if (savedTree != null) { + final Object[] array = new Object[1]; + array[0] = Serialization.getInstance().fromString(savedTree); + treeViewer.setInput(array); + treeViewer.expandAll(); + } + + final String rels = MarkerPage.settings.get("rels"); + if (rels != null) { + tableViewer.setInput(Serialization.getInstance().fromString(rels)); + // auto size columns + final TableColumn[] columns = tableViewer.getTable().getColumns(); + for (int i = 0; i < columns.length; i++) { + columns[i].pack(); + } + } + } catch (final IOException e1) { + e1.printStackTrace(); + } catch (final ClassNotFoundException e) { + e.printStackTrace(); + } + + return container; + } + + @Override + public void init(final IWorkbench workbench) {} +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/preferences/ModelWriterPreferencePage.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/preferences/ModelWriterPreferencePage.java new file mode 100644 index 00000000..80db487b --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/preferences/ModelWriterPreferencePage.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.preferences; + +import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +public class ModelWriterPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { + + /** + * Create the preference page. + */ + public ModelWriterPreferencePage() {} + + /** + * Create contents of the preference page. + * + * @param parent + */ + @Override + public Control createContents(Composite parent) { + Composite container = new Composite(parent, SWT.NULL); + container.setLayout(new FormLayout()); + + return container; + } + + /** + * Initialize the preference page. + */ + @Override + public void init(IWorkbench workbench) {} +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/preferences/RefColumn.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/preferences/RefColumn.java new file mode 100644 index 00000000..93f9bc66 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/preferences/RefColumn.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.preferences; + +public class RefColumn extends RefColumnLabelProvider { + + @Override + public String getText(Object element) { + + return (String)element; + } + + @Override + public String getTitle() { + + return "References"; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/preferences/RefColumnLabelProvider.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/preferences/RefColumnLabelProvider.java new file mode 100644 index 00000000..fd80ec76 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/preferences/RefColumnLabelProvider.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.preferences; + +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.TableColumn; + +import eu.modelwriter.marker.MarkerActivator; + +public abstract class RefColumnLabelProvider extends ColumnLabelProvider { + + @Override + public Image getImage(Object element) { + ImageRegistry imageRegistry = MarkerActivator.getDefault().getImageRegistry(); + return imageRegistry.get(MarkerActivator.Images.IMAGE_RELATION_ID); + } + + public abstract String getText(Object element); + + public abstract String getTitle(); + + public TableViewerColumn addColumnTo(TableViewer viewer) { + TableViewerColumn tableViewerColumn = new TableViewerColumn(viewer, SWT.NONE); + TableColumn column = tableViewerColumn.getColumn(); + column.setMoveable(true); + column.setText(getTitle()); + column.setResizable(true); + tableViewerColumn.setLabelProvider(this); + return tableViewerColumn; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/contextualview/ContextualView.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/contextualview/ContextualView.java new file mode 100644 index 00000000..3c27ba33 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/contextualview/ContextualView.java @@ -0,0 +1,304 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.views.contextualview; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.viewers.DecoratingLabelProvider; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ILabelDecorator; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.ide.ResourceUtil; +import org.eclipse.ui.part.ViewPart; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.marker.ui.Activator; + +public class ContextualView extends ViewPart { + + public static final String ID = "eu.modelwriter.marker.ui.views.contextualview"; + private static final String MARKERS_ID = "org.eclipse.ui.ide.MarkersView"; + private static TreeViewer treeViewer; + + public static TreeViewer getTreeViewer() { + return ContextualView.treeViewer; + } + + public static void refreshTree() { + if (ContextualView.treeViewer == null) { + return; + } + if (Activator.getActiveWorkbenchWindow() == null) { + return; + } + if (Activator.getActiveWorkbenchWindow().getActivePage() == null) { + return; + } + + if (!ContextualView.treeViewer.getTree().isDisposed()) { + if (Activator.getActiveWorkbenchWindow().getActivePage().getActiveEditor() == null) { + ContextualView.treeViewer.setInput(new IMarker[0]); + return; + } + + final IFile file = Activator.getActiveWorkbenchWindow().getActivePage().getActiveEditor() + .getEditorInput().getAdapter(IFile.class); + ArrayList allMarkers; + allMarkers = MarkerFactory.findMarkersAsArrayList(file); + final Iterator iter = allMarkers.iterator(); + while (iter.hasNext()) { + final Object marker = iter.next(); + if (MarkUtilities.getLeaderId((IMarker) marker) == null + && MarkUtilities.getGroupId((IMarker) marker) != null) { + iter.remove(); + } + } + ContextualView.treeViewer.setInput(allMarkers.toArray()); + } + } + + private HashMap candidateToDel; + + private Tree tree; + private ArrayList candidateToTypeChanging; + private ArrayList checkIfHasSource; + + public ContextualView() { + this.candidateToDel = new HashMap<>(); + } + + @Override + public void createPartControl(final Composite parent) { + + ContextualView.treeViewer = new TreeViewer(parent, SWT.BORDER | SWT.MULTI); + this.tree = ContextualView.treeViewer.getTree(); + ContextualView.treeViewer.setContentProvider(new ContextualViewTreeContentProvider()); + + final ContextualViewTreeLabelProvider baseLabelprovider = new ContextualViewTreeLabelProvider(); + final ILabelDecorator decorator = + PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator(); + ContextualView.treeViewer + .setLabelProvider(new DecoratingLabelProvider(baseLabelprovider, decorator)); + this.getSite().setSelectionProvider(ContextualView.treeViewer); + + this.registerContextMenu(); + + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + ResourcesPlugin.getWorkspace().addResourceChangeListener(new IResourceChangeListener() { + @Override + public void resourceChanged(final IResourceChangeEvent event) { + if (event.findMarkerDeltas(MarkerFactory.MARKER_MARKING, true).length != 0) { + if (!ContextualView.this.tree.isDisposed()) { + ContextualView.refreshTree(); + } + } + } + }, IResourceChangeEvent.POST_CHANGE); + } + }); + + ContextualView.treeViewer.addDoubleClickListener(new IDoubleClickListener() { + + @Override + public void doubleClick(final DoubleClickEvent event) { + final IStructuredSelection selection = (IStructuredSelection) event.getSelection(); + final IMarker selected = (IMarker) selection.getFirstElement(); + try { + IDE.openEditor(Activator.getActiveWorkbenchWindow().getActivePage(), MarkerFactory + .findMarkerBySourceId(selected.getResource(), MarkUtilities.getSourceId(selected))); + // final IWorkbenchPage page = + // PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + // IViewPart viewPart = page.findView(TargetView.ID); + // if (viewPart == null) { + // viewPart = page.showView(TargetView.ID); + // } + // if (viewPart instanceof TargetView) { + // if (MarkUtilities.getType(selected) != null) { + // final Map targets = + // AlloyUtilities.getRelationsOfFirstSideMarker(selected); + // TargetView.setColumns(targets.keySet()); + // } else { + // final ArrayList targets = + // AlloyUtilities.getTargetsOfMarkerAtRelations(selected); + // TargetView.setColumns(targets); + // } + // } + // viewPart = page.findView(SourceView.ID); + // if (viewPart == null) { + // viewPart = page.showView(SourceView.ID); + // } + // if (viewPart instanceof SourceView) { + // if (MarkUtilities.getType(selected) != null) { + // final ArrayList sources = AlloyUtilities.getSumSources(selected); + // SourceView.setColumns(sources); + // } else { + // final ArrayList sources = + // AlloyUtilities.getSourcesOfMarkerAtRelations(selected); + // SourceView.setColumns(sources); + // } + // } + } catch (final PartInitException e) { + e.printStackTrace(); + } + } + }); + + this.tree.addKeyListener(new KeyListener() { + + @Override + public void keyPressed(final KeyEvent e) { + if (e.keyCode == SWT.DEL) { + final IStructuredSelection selection = ContextualView.treeViewer.getStructuredSelection(); + if (selection.isEmpty()) { + return; + } else { + final IEditorPart editor = PlatformUI.getWorkbench().getActiveWorkbenchWindow() + .getActivePage().getActiveEditor(); + final TreeItem[] items = ContextualView.treeViewer.getTree().getSelection(); + final List listItems = Arrays.asList(items); + ContextualView.this.candidateToDel = new HashMap<>(); + ContextualView.this.candidateToTypeChanging = new ArrayList<>(); + ContextualView.this.checkIfHasSource = new ArrayList<>(); + for (final TreeItem treeItem : listItems) { + final IMarker iMarker = (IMarker) treeItem.getData(); + if (MarkUtilities.getGroupId(iMarker) == null) { + AnnotationFactory.removeAnnotation(iMarker); + ContextualView.this.candidateToDel.put(MarkUtilities.getSourceId(iMarker), iMarker); + ContextualView.this.checkIfHasSource.add(iMarker); + } else if (MarkUtilities.getLeaderId(iMarker) != null) { + ContextualView.this.checkIfHasSource.add(iMarker); + final IFile file = ResourceUtil.getFile(editor.getEditorInput()); + final List listOfGroup = + MarkerFactory.findMarkersByGroupId(file, MarkUtilities.getGroupId(iMarker)); + for (final IMarker iMarker2 : listOfGroup) { + AnnotationFactory.removeAnnotation(iMarker2); + ContextualView.this.candidateToDel.put(MarkUtilities.getSourceId(iMarker2), + iMarker2); + } + } else { + if (ContextualView.this.candidateToDel.containsValue(iMarker)) { + continue; + } + AnnotationFactory.removeAnnotation(iMarker); + ContextualView.this.candidateToDel.put(MarkUtilities.getSourceId(iMarker), iMarker); + } + } + } + try { + for (final IMarker iMarker : ContextualView.this.checkIfHasSource) { + ContextualView.this.findCandidateToTypeChangingMarkers(iMarker); + } + for (final IMarker candidateMarker : ContextualView.this.candidateToTypeChanging) { + if (!ContextualView.this.candidateToDel.containsValue(candidateMarker)) { + AnnotationFactory.convertAnnotationType(candidateMarker, true, false, + AlloyUtilities.getTotalTargetCount(candidateMarker)); + } + } + for (final Map.Entry entry : ContextualView.this.candidateToDel + .entrySet()) { + ContextualView.this.deleteFromAlloyXML(entry.getValue()); + entry.getValue().delete(); + } + } catch (final CoreException e2) { + e2.printStackTrace(); + } + } + } + + @Override + public void keyReleased(final KeyEvent e) {} + }); + } + + private void deleteFromAlloyXML(final IMarker beDeleted) { + if (AlloyUtilities.isExists()) { + AlloyUtilities.removeMarkerFromRepository(beDeleted); + if (MarkUtilities.getGroupId(beDeleted) == null + || MarkUtilities.getLeaderId(beDeleted) != null) { + AlloyUtilities.removeTypeFromMarker(beDeleted); + AlloyUtilities.removeRelationOfMarker(beDeleted); + } + } + } + + /** + * @param selectedMarker from text + */ + private void findCandidateToTypeChangingMarkers(final IMarker selectedMarker) { + + final Map fieldsSources = + AlloyUtilities.getRelationsOfSecondSideMarker(selectedMarker); + final ArrayList relationsSources = + AlloyUtilities.getSourcesOfMarkerAtRelations(selectedMarker); + + for (final IMarker iMarker : fieldsSources.keySet()) { + if (!this.candidateToTypeChanging.contains(iMarker)) { + this.candidateToTypeChanging.add(iMarker); + } + } + + for (final IMarker iMarker : relationsSources) { + if (!this.candidateToTypeChanging.contains(iMarker)) { + this.candidateToTypeChanging.add(iMarker); + } + } + } + + private void registerContextMenu() { + final MenuManager contextMenu = new MenuManager(); + contextMenu.setRemoveAllWhenShown(true); + this.getSite().registerContextMenu(contextMenu, ContextualView.treeViewer); + // Add in the entries for all markers views if this has a different if + if (!this.getSite().getId().equals(ContextualView.MARKERS_ID)) { + this.getSite().registerContextMenu(ContextualView.MARKERS_ID, contextMenu, ContextualView.treeViewer); + } + final Control control = ContextualView.treeViewer.getControl(); + final Menu menu = contextMenu.createContextMenu(control); + control.setMenu(menu); + } + + @Override + public void setFocus() { + this.tree.setFocus(); + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/contextualview/ContextualViewTreeContentProvider.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/contextualview/ContextualViewTreeContentProvider.java new file mode 100644 index 00000000..16b3e6ea --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/contextualview/ContextualViewTreeContentProvider.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.views.contextualview; + +import java.util.List; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class ContextualViewTreeContentProvider implements ITreeContentProvider { + + @Override + public void dispose() {} + + @Override + public Object[] getChildren(Object parentElement) { + if (parentElement instanceof IMarker) { + IMarker iMarker = (IMarker) parentElement; + List groupElements = MarkerFactory.findMarkersByGroupId(iMarker.getResource(), + MarkUtilities.getGroupId(iMarker)); + groupElements.remove(iMarker); + + return groupElements.toArray(); + } else { + return null; + } + } + + @Override + public Object[] getElements(Object inputElement) { + if (inputElement instanceof Object[]) { + return (Object[]) inputElement; + } else { + return new Object[0]; + } + } + + @Override + public Object getParent(Object element) { + return null; + } + + @Override + public boolean hasChildren(Object element) { + if (element instanceof IMarker) { + IMarker iMarker = (IMarker) element; + if ((MarkUtilities.getLeaderId(iMarker) != null)) { + return true; + } + } + return false; + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {} +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/contextualview/ContextualViewTreeLabelProvider.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/contextualview/ContextualViewTreeLabelProvider.java new file mode 100644 index 00000000..81a189e9 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/contextualview/ContextualViewTreeLabelProvider.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.views.contextualview; + +import java.net.URL; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; +import org.osgi.framework.Bundle; + +import eu.modelwriter.marker.internal.MarkUtilities; + +public class ContextualViewTreeLabelProvider extends LabelProvider { + + public static ImageDescriptor getImageDescriptor(final String bundleID, final String path) { + assert(bundleID != null) : "No bundle defined"; + assert(path != null) : "No path defined"; + + // if the bundle is not ready then there is no image + final Bundle bundle = Platform.getBundle(bundleID); + final int bundleState = bundle.getState(); + if ((bundleState != Bundle.ACTIVE) && (bundleState != Bundle.STARTING) + && (bundleState != Bundle.RESOLVED)) { + return null; + } + + // look for the image (this will check both the plugin and fragment + // folders + final URL imagePath = FileLocator.find(bundle, new Path(path), null); + + if (imagePath != null) { + return ImageDescriptor.createFromURL(imagePath); + } + + return null; + } + + private ImageDescriptor mDescriptor = ContextualViewTreeLabelProvider + .getImageDescriptor("org.eclipse.ui", "/icons/full/eview16/tasks_tsk.gif"); + + @Override + public Image getImage(Object element) { + return this.mDescriptor.createImage(); + } + + @Override + public String getText(Object element) { + if (element instanceof IMarker) { + IMarker iMarker = (IMarker) element; + if (MarkUtilities.getType(iMarker) == null) + return MarkUtilities.getText(iMarker); + return MarkUtilities.getText(iMarker) + " [T: " + MarkUtilities.getType(iMarker) + "]"; + } else { + return "Unknown type: " + element.getClass(); + } + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/masterview/MasterView.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/masterview/MasterView.java new file mode 100644 index 00000000..bf5da70d --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/masterview/MasterView.java @@ -0,0 +1,123 @@ +package eu.modelwriter.marker.ui.internal.views.masterview; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.part.ViewPart; + +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.marker.ui.Activator; +import eu.modelwriter.marker.ui.internal.views.contextualview.ContextualView; + +public class MasterView extends ViewPart { + + private static final String MARKERS_ID = "org.eclipse.ui.ide.MarkersView"; + + private TreeViewer treeViewer; + + public MasterView() { + super(); + } + + @Override + public void createPartControl(final Composite parent) { + this.treeViewer = new TreeViewer(parent, SWT.BORDER | SWT.MULTI); + this.treeViewer.setContentProvider(new MasterViewContentProvider()); + this.treeViewer.setLabelProvider(new MasterViewLabelProvider()); + this.getSite().setSelectionProvider(this.treeViewer); + + this.refreshTree(); + // this.getSite().setSelectionProvider(this.treeViewer); + this.registerContextMenu(); + + this.treeViewer.addDoubleClickListener(new IDoubleClickListener() { + + @Override + public void doubleClick(final DoubleClickEvent event) { + final IStructuredSelection selection = (IStructuredSelection) event.getSelection(); + final IMarker selected = (IMarker) selection.getFirstElement(); + try { + final IWorkbenchPage page = Activator.getActiveWorkbenchWindow().getActivePage(); + IDE.openEditor(page, MarkerFactory.findMarkerBySourceId(selected.getResource(), + MarkUtilities.getSourceId(selected))); + } catch (final PartInitException e) { + e.printStackTrace(); + } + } + }); + + Activator.getActiveWorkbenchWindow().getWorkbench().getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + ResourcesPlugin.getWorkspace().addResourceChangeListener(new IResourceChangeListener() { + @Override + public void resourceChanged(final IResourceChangeEvent event) { + if (event.findMarkerDeltas(MarkerFactory.MARKER_MARKING, true).length != 0) { + if (!MasterView.this.treeViewer.getTree().isDisposed()) { + MasterView.this.refreshTree(); + } + } + } + }, IResourceChangeEvent.POST_CHANGE); + } + }); + } + + protected void refreshTree() { + if (this.treeViewer == null) { + return; + } + + if (!this.treeViewer.getTree().isDisposed()) { + ArrayList allMarkers = new ArrayList<>(); + allMarkers.addAll(MarkerFactory.findMarkers(ResourcesPlugin.getWorkspace().getRoot())); + final Iterator iter = allMarkers.iterator(); + while (iter.hasNext()) { + final Object marker = iter.next(); + if (MarkUtilities.getLeaderId((IMarker) marker) == null + && MarkUtilities.getGroupId((IMarker) marker) != null) { + iter.remove(); + } + } + this.treeViewer.setInput(allMarkers.toArray()); + } + } + + private void registerContextMenu() { + final MenuManager contextMenu = new MenuManager(); + contextMenu.setRemoveAllWhenShown(true); + this.getSite().registerContextMenu(contextMenu, this.treeViewer); + // Add in the entries for all markers views if this has a different if + if (!this.getSite().getId().equals(MARKERS_ID)) { + this.getSite().registerContextMenu(MARKERS_ID, contextMenu, this.treeViewer); + } + final Control control = this.treeViewer.getControl(); + final Menu menu = contextMenu.createContextMenu(control); + control.setMenu(menu); + } + + @Override + public void setFocus() { + this.treeViewer.getTree().setFocus(); + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/masterview/MasterViewContentProvider.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/masterview/MasterViewContentProvider.java new file mode 100644 index 00000000..465ac142 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/masterview/MasterViewContentProvider.java @@ -0,0 +1,58 @@ +package eu.modelwriter.marker.ui.internal.views.masterview; + +import java.util.List; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class MasterViewContentProvider implements ITreeContentProvider { + + @Override + public void dispose() {} + + @Override + public Object[] getChildren(final Object parentElement) { + if (parentElement instanceof IMarker) { + final IMarker iMarker = (IMarker) parentElement; + final List groupElements = MarkerFactory.findMarkersByGroupId(iMarker.getResource(), + MarkUtilities.getGroupId(iMarker)); + groupElements.remove(iMarker); + + return groupElements.toArray(); + } else { + return null; + } + } + + @Override + public Object[] getElements(final Object inputElement) { + if (inputElement instanceof Object[]) { + return (Object[]) inputElement; + } else { + return new Object[0]; + } + } + + @Override + public Object getParent(final Object element) { + return null; + } + + @Override + public boolean hasChildren(final Object element) { + if (element instanceof IMarker) { + final IMarker iMarker = (IMarker) element; + if (MarkUtilities.getLeaderId(iMarker) != null) { + return true; + } + } + return false; + } + + @Override + public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) {} +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/masterview/MasterViewLabelProvider.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/masterview/MasterViewLabelProvider.java new file mode 100644 index 00000000..f050ee0e --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/masterview/MasterViewLabelProvider.java @@ -0,0 +1,61 @@ +package eu.modelwriter.marker.ui.internal.views.masterview; + +import java.net.URL; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; +import org.osgi.framework.Bundle; + +import eu.modelwriter.marker.internal.MarkUtilities; + +public class MasterViewLabelProvider extends LabelProvider { + + public static ImageDescriptor getImageDescriptor(final String bundleID, final String path) { + assert bundleID != null : "No bundle defined"; + assert path != null : "No path defined"; + + // if the bundle is not ready then there is no image + final Bundle bundle = Platform.getBundle(bundleID); + final int bundleState = bundle.getState(); + if (bundleState != Bundle.ACTIVE && bundleState != Bundle.STARTING + && bundleState != Bundle.RESOLVED) { + return null; + } + + // look for the image (this will check both the plugin and fragment + // folders + final URL imagePath = FileLocator.find(bundle, new Path(path), null); + + if (imagePath != null) { + return ImageDescriptor.createFromURL(imagePath); + } + + return null; + } + + private final ImageDescriptor mDescriptor = + getImageDescriptor("org.eclipse.ui", "/icons/full/eview16/tasks_tsk.gif"); + + @Override + public Image getImage(final Object element) { + return this.mDescriptor.createImage(); + } + + @Override + public String getText(final Object element) { + if (element instanceof IMarker) { + final IMarker iMarker = (IMarker) element; + if (MarkUtilities.getType(iMarker) == null) { + return MarkUtilities.getText(iMarker); + } + return MarkUtilities.getText(iMarker) + " [T: " + MarkUtilities.getType(iMarker) + "]"; + } else { + return "Unknown type: " + element.getClass(); + } + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/propertiesview/DetailPropertySource.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/propertiesview/DetailPropertySource.java new file mode 100644 index 00000000..33887ff1 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/propertiesview/DetailPropertySource.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.views.propertiesview; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.ui.views.properties.IPropertyDescriptor; +import org.eclipse.ui.views.properties.IPropertySource; +import org.eclipse.ui.views.properties.PropertyDescriptor; + +import eu.modelwriter.marker.internal.MarkUtilities; + +public class DetailPropertySource implements IPropertySource { + private static final Object ID = new Object(); + private static final Object LENGTH = new Object(); + private static final Object LINE_NUMBER = new Object(); + private static final Object OFFSET = new Object(); + private static final Object PATH = new Object(); + private static final Object TEXT = new Object(); + private static final Object TYPE = new Object(); + private IMarker marker; + + public DetailPropertySource(IMarker marker) { + this.marker = marker; + } + + @Override + public Object getEditableValue() { + return null; + } + + @Override + public IPropertyDescriptor[] getPropertyDescriptors() { + return new IPropertyDescriptor[] {new PropertyDescriptor(DetailPropertySource.ID, "ID"), + new PropertyDescriptor(DetailPropertySource.LENGTH, "Length"), + new PropertyDescriptor(DetailPropertySource.LINE_NUMBER, "Line Number"), + new PropertyDescriptor(DetailPropertySource.OFFSET, "Offset"), + new PropertyDescriptor(DetailPropertySource.PATH, "Path"), + new PropertyDescriptor(DetailPropertySource.TEXT, "Text"), + new PropertyDescriptor(DetailPropertySource.TYPE, "Type")}; + } + + @Override + public Object getPropertyValue(Object id) { + if (this.marker != null) { + if (DetailPropertySource.ID.equals(id)) { + return MarkUtilities.getSourceId(this.marker); + } else if (DetailPropertySource.LENGTH.equals(id)) { + return MarkUtilities.getLength(this.marker); + } else if (DetailPropertySource.LINE_NUMBER.equals(id)) { + return MarkUtilities.getLinenumber(this.marker); + } else if (DetailPropertySource.OFFSET.equals(id)) { + return MarkUtilities.getStart(this.marker); + } else if (DetailPropertySource.PATH.equals(id)) { + return MarkUtilities.getPath(this.marker); + } else if (DetailPropertySource.TEXT.equals(id)) { + return MarkUtilities.getText(this.marker); + } else if (DetailPropertySource.TYPE.equals(id)) { + return MarkUtilities.getType(this.marker); + } + } + return ""; + } + + @Override + public boolean isPropertySet(Object id) { + return false; + } + + @Override + public void resetPropertyValue(Object id) {} + + @Override + public void setPropertyValue(Object id, Object value) {} +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/propertiesview/MarkerPropertyAdapterFactory.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/propertiesview/MarkerPropertyAdapterFactory.java new file mode 100644 index 00000000..094d3baf --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/propertiesview/MarkerPropertyAdapterFactory.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.views.propertiesview; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.ui.views.properties.IPropertySource; + +public class MarkerPropertyAdapterFactory implements IAdapterFactory { + + @Override + @SuppressWarnings("unchecked") + public T getAdapter(Object adaptableObject, Class adapterType) { + if ((adapterType == IPropertySource.class) && (adaptableObject instanceof IMarker)) { + return (T) new DetailPropertySource((IMarker) adaptableObject); + } else { + return (T) new DetailPropertySource(null); + } + } + + @Override + public Class[] getAdapterList() { + return new Class[] {IPropertySource.class}; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/EvaluatorPanel.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/EvaluatorPanel.java new file mode 100644 index 00000000..73383b74 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/EvaluatorPanel.java @@ -0,0 +1,29 @@ +package eu.modelwriter.marker.ui.internal.views.visualizationview; + +import java.io.File; + +import javax.swing.JScrollPane; + +import edu.mit.csail.sdg.alloy4.OurConsole; +import eu.modelwriter.configuration.alloy.evaluator.Evaluator; + +public final class EvaluatorPanel { + private EvaluatorPanel() {} + + public static JScrollPane getInstance(final String xmlPath) { + final Evaluator evaluator = new Evaluator(); + final JScrollPane instance = new OurConsole(evaluator, true, "Expression Evaluator Pane"); + /* + * final JScrollPane instance = new OurConsole(evaluator, true, "The ", true, + * "Alloy Evaluator ", false, + * "allows you to type\nin Alloy expressions and see their values.\nFor example, ", true, + * "univ", false, + * " shows the list of all atoms.\n(You can press UP and DOWN to recall old inputs).\n"); + */ + try { + evaluator.compute(new File(xmlPath)); + } catch (final Exception ex) { + } // exception should not happen + return instance; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/Visualization.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/Visualization.java new file mode 100644 index 00000000..9fd3f395 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/Visualization.java @@ -0,0 +1,495 @@ +package eu.modelwriter.marker.ui.internal.views.visualizationview; + +import java.awt.Cursor; +import java.awt.Frame; +import java.awt.Point; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; + +import javax.swing.JComponent; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.swt.SWT; +import org.eclipse.swt.awt.SWT_AWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; +import org.eclipse.ui.services.ISourceProviderService; + +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.OurBorder; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4graph.GraphEdge; +import edu.mit.csail.sdg.alloy4graph.GraphViewer; +import edu.mit.csail.sdg.alloy4viz.AlloyAtom; +import edu.mit.csail.sdg.alloy4viz.AlloyInstance; +import edu.mit.csail.sdg.alloy4viz.AlloyTuple; +import edu.mit.csail.sdg.alloy4viz.StaticInstanceReader; +import edu.mit.csail.sdg.alloy4viz.VizGraphPanel; +import edu.mit.csail.sdg.alloy4viz.VizState; +import eu.modelwriter.configuration.alloy.analysis.provider.AnalysisSourceProvider; +import eu.modelwriter.configuration.alloy.analysis.provider.AnalysisSourceProvider.AnalysisState; +import eu.modelwriter.configuration.alloy.discovery.AlloyOtherSolutionDiscovering; +import eu.modelwriter.configuration.alloy.reasoning.AlloyOtherSolutionReasoning; +import eu.modelwriter.configuration.alloy.trace.TraceManager; +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.ui.Activator; +import eu.modelwriter.marker.ui.internal.views.visualizationview.commands.VisualizationActionListenerFactory; + +public class Visualization extends ViewPart { + + public static final String ID = "eu.modelwriter.marker.ui.views.visualizationview"; + private static VizState myState = null; + private static VizGraphPanel graph; + private static JPanel graphPanel; + private static GraphViewer viewer; + private static Frame frame; + private static File f = null; + public static Object rightClickedAnnotation; + final static String xmlFileName = Util.canon(AlloyUtilities.getLocation()); + public static Composite container; + public static AnalysisSourceProvider sourceProvider; + public static String relation; + private static JScrollPane evaluatorPanel; + public static boolean evaluatorOpen = false; + + public enum AnalysisMenuItems { + validate("Check Consistency"), + discoverRelation("Reason on Relations"), + discoverRelationForAtom("Reasoning for Atom"), + discoverAtom("Discover Atoms"), + acceptReasonedRelation("Accept Reasoning"), + acceptTracedRelation("Accept Reasoning"), + interpretAtom("Interpret Atom"), + interpretTracedAtom("Interpret Atom"), + previousSolution("Previous Solution"), + nextSolution("Next Solution"), + stopAnalysis("Stop Analysis"), + clearAllReasoned("Clear All Reasoned Tuples"), + acceptAllReasoned("Accept All Reasoned Tuples"); + + JMenuItem menuItem = null; + + AnalysisMenuItems(final String title) { + menuItem = new JMenuItem(title); + }; + + void addToMenu(final JMenu menu) { + menu.add(menuItem, ordinal()); + } + + JMenuItem getItem() { + return menuItem; + } + }; + + public enum ModelWriterMenuItems { + addRemoveType("Change Type"), + createNewAtom("Create New Atom"), + createInstanceElement("Create New Atom"), + deleteAtom("Delete Atom"), + mapping("Map Atom"), + removeRelation("Remove Relation"), + resolve("Resolve"); + + JMenuItem menuItem = null; + + ModelWriterMenuItems(final String title) { + menuItem = new JMenuItem(title); + }; + + void addToMenu(final JMenu menu) { + menu.add(menuItem, ordinal()); + } + + JMenuItem getItem() { + return menuItem; + } + } + + public static final JMenu modelWriterMenu = new JMenu("Management"); + private static final JMenu analysisMenu = new JMenu("Analysis"); + private static final JMenuItem refreshMenuItem = new JMenuItem("Refresh"); + + public static IMarker getMarker(final AlloyAtom highLightedAtom) { + if (highLightedAtom.isDashed) { + return null; + } + + final String atomType = highLightedAtom.getType().getName(); + final String stringIndex = highLightedAtom.toString().substring(atomType.length()); + int index = 0; + if (!stringIndex.isEmpty()) { + index = Integer.parseInt(stringIndex); + } + + final IMarker marker = AlloyUtilities.findMarker(atomType, index); + + return marker; + } + + private static MouseAdapter getMouseAdapter() { + return new MouseAdapter() { + @Override + public void mouseClicked(final MouseEvent e) { + super.mouseClicked(e); + if (e.getClickCount() > 1) { + final Object annotation = Visualization.viewer.alloyGetAnnotationAtXY(e.getX(), e.getY()); + + if (annotation instanceof AlloyAtom) { + final IMarker marker = Visualization.getMarker((AlloyAtom) annotation); + if (marker == null) { + return; + } + MarkUtilities.focusMarker(marker); + } + } + } + + /** + * when mouse exited from graph
+ * (not from AlloyAtom or not from AlloyTuple) + */ + @Override + public void mouseExited(final MouseEvent e) { + Visualization.frame.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + final Object annotation = Visualization.viewer.alloyGetAnnotationAtXY(e.getX(), e.getY()); + if (annotation == null) { + final JMenu modelWriterMenu = (JMenu) Visualization.viewer.pop.getComponent(0); + if (!Visualization.viewer.pop.isShowing()) { + modelWriterMenu.setVisible(false); + } + } + } + + @Override + public void mousePressed(final MouseEvent e) { + switch (e.getButton()) { + case MouseEvent.BUTTON3: // right click + final Object curState = Visualization.sourceProvider.getCurrentState() + .get(AnalysisSourceProvider.ANALYSIS_STATE); + Visualization.rightClickedAnnotation = + Visualization.viewer.alloyGetAnnotationAtXY(e.getX(), e.getY()); + AlloyTuple tuple = null; + AlloyAtom atom = null; + AlloyAtom leftAtom = null; + AlloyAtom rightAtom = null; + if (Visualization.rightClickedAnnotation instanceof AlloyAtom) { + atom = (AlloyAtom) Visualization.rightClickedAnnotation; + } else if (Visualization.rightClickedAnnotation instanceof AlloyTuple) { + tuple = (AlloyTuple) Visualization.rightClickedAnnotation; + leftAtom = tuple.getStart(); + rightAtom = tuple.getEnd(); + + try { + final Field field = GraphViewer.class.getDeclaredField("selected"); + field.setAccessible(true); + if (field.get(Visualization.viewer) instanceof GraphEdge) { + final GraphEdge edge = (GraphEdge) field.get(Visualization.viewer); + Visualization.relation = + edge.group.toString().substring(0, edge.group.toString().indexOf(":") - 1); + } + } catch (NoSuchFieldException | SecurityException | IllegalArgumentException + | IllegalAccessException e1) { + e1.printStackTrace(); + } + } + final boolean onAtom = atom != null; + final boolean atomReasoned = onAtom && atom.isDashed; + final boolean onRelation = tuple != null; + final boolean relationReasoned = onRelation && tuple.isDashed; + final boolean onEmptyArea = !onAtom && !onRelation; + final boolean resolve = + onRelation && leftAtom.changed && rightAtom.impacted.size() != 0; + final boolean analysisActive = curState.equals(AnalysisState.ACTIVE.toString()); + final boolean hasSolution = + AlloyOtherSolutionReasoning.getInstance().getCurrentSolution() != null + || AlloyOtherSolutionDiscovering.getInstance().getCurrentSolution() != null; + final boolean anyReasoned = AlloyUtilities.isAnyReasoned(); + + Visualization.modelWriterMenu.setVisible(!atomReasoned || onRelation || onEmptyArea); + ModelWriterMenuItems.addRemoveType.getItem().setVisible(onAtom); + ModelWriterMenuItems.createNewAtom.getItem() + .setVisible(onEmptyArea && !TraceManager.get().hasInstance()); + ModelWriterMenuItems.deleteAtom.getItem().setVisible(onAtom); + ModelWriterMenuItems.mapping.getItem().setVisible(onAtom); + ModelWriterMenuItems.removeRelation.getItem().setVisible(onRelation); + ModelWriterMenuItems.resolve.getItem().setVisible(onAtom && atom.changed || resolve); + ModelWriterMenuItems.createInstanceElement.getItem() + .setVisible(onEmptyArea && TraceManager.get().hasInstance()); + + Visualization.analysisMenu + .setVisible(onAtom || onRelation && anyReasoned && relationReasoned || onEmptyArea); + AnalysisMenuItems.validate.getItem().setVisible(onEmptyArea); + AnalysisMenuItems.discoverRelation.getItem().setVisible(onEmptyArea && !analysisActive); + AnalysisMenuItems.acceptReasonedRelation.getItem() + .setVisible(relationReasoned && !TraceManager.get().hasInstance()); + AnalysisMenuItems.previousSolution.getItem() + .setVisible(onEmptyArea && analysisActive && hasSolution); + AnalysisMenuItems.nextSolution.getItem() + .setVisible(onEmptyArea && analysisActive && hasSolution); + AnalysisMenuItems.stopAnalysis.getItem().setVisible(onEmptyArea && analysisActive); + AnalysisMenuItems.discoverAtom.getItem().setVisible(onEmptyArea && !analysisActive); + AnalysisMenuItems.clearAllReasoned.getItem().setVisible(onEmptyArea && anyReasoned); + AnalysisMenuItems.interpretAtom.getItem().setVisible( + atomReasoned && !TraceManager.get().hasSigTrace(atom.getType().getName())); + AnalysisMenuItems.interpretTracedAtom.getItem().setVisible( + atomReasoned && TraceManager.get().hasSigTrace(atom.getType().getName())); + AnalysisMenuItems.acceptTracedRelation.getItem() + .setVisible(TraceManager.get().hasInstance() && relationReasoned); + AnalysisMenuItems.acceptAllReasoned.getItem() + .setVisible(TraceManager.get().hasInstance() && onEmptyArea && anyReasoned); + AnalysisMenuItems.discoverRelationForAtom.getItem() + .setVisible(onAtom && !analysisActive); + + if (e.getSource() instanceof GraphViewer) { + Visualization.viewer.alloyPopup(Visualization.viewer, e.getX(), e.getY()); + } else { + Visualization.viewer.alloyPopup(Visualization.graphPanel, e.getX(), e.getY()); + } + default: + break; + } + } + }; + } + + private static MouseMotionAdapter getMouseMotionAdapter() { + return new MouseMotionAdapter() { + @Override + public void mouseMoved(final MouseEvent e) { + JComponent cmpnt = null; + String tooltip = null; + try { + final Object annotation = Visualization.viewer.alloyGetAnnotationAtXY(e.getX(), e.getY()); + cmpnt = (JComponent) e.getComponent(); + + if (annotation instanceof AlloyAtom) { + final IMarker marker = Visualization.getMarker((AlloyAtom) annotation); + if (marker == null) { + return; + } + + Visualization.frame.setCursor(new Cursor(Cursor.HAND_CURSOR)); + tooltip = MarkUtilities.getText(marker); + } else if (annotation instanceof AlloyTuple) { + final AlloyTuple tuple = (AlloyTuple) annotation; + + final AlloyAtom highLightedAtomStart = tuple.getStart(); + final AlloyAtom highLightedAtomEnd = tuple.getEnd(); + + final IMarker markerStart = Visualization.getMarker(highLightedAtomStart); + final IMarker markerEnd = Visualization.getMarker(highLightedAtomEnd); + + if (markerStart == null || markerEnd == null) { + return; + } + + tooltip = + MarkUtilities.getText(markerStart) + " --> " + MarkUtilities.getText(markerEnd); + Visualization.frame.setCursor(new Cursor(Cursor.HAND_CURSOR)); + } else { + /** + * when mouse exited from AlloyAtom or from AlloyTuple + */ + Visualization.frame.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + + } catch (final Exception ex) { + System.err.println("onMouseMoved failed"); + // ex.printStackTrace(); + } finally { + cmpnt.setToolTipText(tooltip); + } + } + }; + } + + public static void showViz() { + Point lastLocation = new Point(0, 0); + if (Visualization.container == null) { + return; + } + if (!AlloyUtilities.isExists()) { + if (Visualization.frame != null) { + if (Visualization.frame.getComponentCount() > 0) { + Visualization.frame.removeAll(); + } + Visualization.frame.add(new JPanel()); + } else if (Visualization.frame == null) { + Visualization.frame = SWT_AWT.new_Frame(Visualization.container); + Visualization.frame.add(new JPanel()); + } + return; + } else { + if (Visualization.frame == null) { + Visualization.frame = SWT_AWT.new_Frame(Visualization.container); + } + } + + Visualization.f = new File(Visualization.xmlFileName); + try { + if (!Visualization.f.exists()) { + throw new IOException("File " + Visualization.xmlFileName + " does not exist."); + } + final AlloyInstance instance = StaticInstanceReader.parseInstance(Visualization.f); + + AlloyUtilities.setAllImpactsAndChanges(instance); + AlloyUtilities.setAllReasonedTuples(instance); + AlloyUtilities.setAllReasonedAtoms(instance); + + Visualization.myState = new VizState(instance); + + // FE + Visualization.myState.mergeArrows.put(null, false); + + if (Visualization.graphPanel != null) { + lastLocation = Visualization.graphPanel.getLocation(); + } + + try { + /* + * TODO BUG + * + * A Fatal Error occurs while setting GTK look and feel on Ubuntu 16.04 + * (com.sun.java.swing.plaf.gtk.GTKLookAndFeel). + * + */ + final String LaF = UIManager.getSystemLookAndFeelClassName(); + if ("com.sun.java.swing.plaf.gtk.GTKLookAndFeel".equals(LaF)) { + UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); + } else { + UIManager.setLookAndFeel(LaF); + } + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException + | UnsupportedLookAndFeelException e1) { + + e1.printStackTrace(); + } + Visualization.graph = new VizGraphPanel(Visualization.myState, false); + Visualization.graphPanel = Visualization.graph.getGraphPanel(); + Visualization.graphPanel.setLocation(lastLocation); + Visualization.viewer = Visualization.graph.alloyGetViewer(); + Visualization.frame.removeAll(); + + JComponent frameInput; + if (Visualization.evaluatorOpen) { + final JSplitPane splitPane = new JSplitPane(); + splitPane.setRightComponent(Visualization.graph); + splitPane.setLeftComponent(Visualization.evaluatorPanel); + splitPane.setDividerLocation(400); + Visualization.evaluatorPanel.requestFocusInWindow(); + Visualization.evaluatorPanel.setBorder(new OurBorder(false, false, false, false)); + + frameInput = splitPane; + } else { + frameInput = Visualization.graph; + Visualization.graph.requestFocusInWindow(); + } + + Visualization.frame.add(frameInput); + Visualization.frame.setVisible(true); + Visualization.frame.setAlwaysOnTop(true); + Visualization.graph.alloyGetViewer().alloyRepaint(); + + final ISourceProviderService service = + Activator.getDefault().getWorkbench().getService(ISourceProviderService.class); + Visualization.sourceProvider = + (AnalysisSourceProvider) service.getSourceProvider(AnalysisSourceProvider.ANALYSIS_STATE); + } catch (final Err e1) { + e1.printStackTrace(); + } catch (final IOException e) { + e.printStackTrace(); + } + + Visualization.graph.alloyGetViewer().pop.add(Visualization.modelWriterMenu, 0); + Visualization.graph.alloyGetViewer().pop.add(Visualization.analysisMenu, 1); + Visualization.graph.alloyGetViewer().pop.add(Visualization.refreshMenuItem, 2); + + Visualization.graph.alloyGetViewer() + .addMouseMotionListener(Visualization.getMouseMotionAdapter()); + Visualization.graphPanel.addMouseMotionListener(Visualization.getMouseMotionAdapter()); + Visualization.graph.alloyGetViewer().addMouseListener(Visualization.getMouseAdapter()); + Visualization.graphPanel.addMouseListener(Visualization.getMouseAdapter()); + } + + private static void createPopupMenu() { + for (final ModelWriterMenuItems items : ModelWriterMenuItems.values()) { + items.addToMenu(Visualization.modelWriterMenu); + } + + for (final AnalysisMenuItems items : AnalysisMenuItems.values()) { + items.addToMenu(Visualization.analysisMenu); + } + + Visualization.refreshMenuItem + .addActionListener(VisualizationActionListenerFactory.refreshActionListener()); + ModelWriterMenuItems.addRemoveType.getItem() + .addActionListener(VisualizationActionListenerFactory.addRemoveTypeActionListener()); + ModelWriterMenuItems.createNewAtom.getItem() + .addActionListener(VisualizationActionListenerFactory.createNewAtomActionListener()); + ModelWriterMenuItems.deleteAtom.getItem() + .addActionListener(VisualizationActionListenerFactory.deleteAtomActionListener()); + ModelWriterMenuItems.mapping.getItem() + .addActionListener(VisualizationActionListenerFactory.mappingActionListener()); + ModelWriterMenuItems.removeRelation.getItem() + .addActionListener(VisualizationActionListenerFactory.removeRelationActionListener()); + ModelWriterMenuItems.resolve.getItem() + .addActionListener(VisualizationActionListenerFactory.resolveActionListener()); + ModelWriterMenuItems.createInstanceElement.getItem().addActionListener( + VisualizationActionListenerFactory.createInstanceElementActionListener()); + + AnalysisMenuItems.validate.getItem() + .addActionListener(VisualizationActionListenerFactory.validateActionListener()); + AnalysisMenuItems.discoverRelation.getItem() + .addActionListener(VisualizationActionListenerFactory.discoverRelationActionListener()); + AnalysisMenuItems.acceptReasonedRelation.getItem().addActionListener( + VisualizationActionListenerFactory.acceptReasonedRelationActionListener()); + AnalysisMenuItems.nextSolution.getItem() + .addActionListener(VisualizationActionListenerFactory.nextSolutionActionListener()); + AnalysisMenuItems.previousSolution.getItem() + .addActionListener(VisualizationActionListenerFactory.previousSolutionActionListener()); + AnalysisMenuItems.stopAnalysis.getItem() + .addActionListener(VisualizationActionListenerFactory.stopAnalysisActionListener()); + AnalysisMenuItems.discoverAtom.getItem() + .addActionListener(VisualizationActionListenerFactory.discoverAtomActionListener()); + AnalysisMenuItems.clearAllReasoned.getItem() + .addActionListener(VisualizationActionListenerFactory.clearAllReasonedActionListener()); + AnalysisMenuItems.interpretAtom.getItem().addActionListener( + VisualizationActionListenerFactory.interpretAtomMenuItemActionListener()); + AnalysisMenuItems.interpretTracedAtom.getItem().addActionListener( + VisualizationActionListenerFactory.acceptAtomAsEMFMenuItemActionListener()); + AnalysisMenuItems.acceptTracedRelation.getItem().addActionListener( + VisualizationActionListenerFactory.acceptRelationAsEMFMenuItemActionListener()); + AnalysisMenuItems.acceptAllReasoned.getItem() + .addActionListener(VisualizationActionListenerFactory.acceptAllReasonedListener()); + AnalysisMenuItems.discoverRelationForAtom.getItem().addActionListener( + VisualizationActionListenerFactory.discoverRelationForAtomActionListener()); + } + + @Override + public void createPartControl(final Composite parent) { + Visualization.container = new Composite(parent, SWT.EMBEDDED | SWT.NO_BACKGROUND); + Visualization.frame = null; + Visualization.f = null; + Visualization.graph = null; + Visualization.myState = null; + Visualization.evaluatorPanel = EvaluatorPanel.getInstance(Visualization.xmlFileName); + Visualization.showViz(); + Visualization.createPopupMenu(); + } + + @Override + public void setFocus() {} +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/AddRemoveTypeCommand.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/AddRemoveTypeCommand.java new file mode 100644 index 00000000..0364a7a1 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/AddRemoveTypeCommand.java @@ -0,0 +1,153 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.views.visualizationview.commands; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.wizard.WizardDialog; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.marker.ui.Activator; +import eu.modelwriter.marker.ui.internal.wizards.mappingwizard.ActionSelectionDialog; +import eu.modelwriter.marker.ui.internal.wizards.markerwizard.MarkerPage; +import eu.modelwriter.marker.ui.internal.wizards.markerwizard.MarkerWizard; + +public class AddRemoveTypeCommand implements Runnable { + private ArrayList candidateToTypeChanging; + private final IMarker marker; + + public AddRemoveTypeCommand(final IMarker marker) { + this.marker = marker; + } + + private void addRemoveType() { + if (!MarkerPage.isParsed()) { + final MessageDialog parseCtrlDialog = + new MessageDialog(Activator.getShell(), "Type Information", null, + "You dont have any marker type registered to system! \n" + + "Please parse an alloy file first", + MessageDialog.INFORMATION, new String[] {"OK"}, 0); + parseCtrlDialog.open(); + return; + } + + final ActionSelectionDialog actionSelectionDialog = + new ActionSelectionDialog(Activator.getShell()); + actionSelectionDialog.open(); + if (actionSelectionDialog.getReturnCode() == IDialogConstants.CANCEL_ID) { + return; + } + + IMarker selectedMarker = this.marker; + selectedMarker = MarkUtilities.getLeaderOfMarker(selectedMarker); + + if (selectedMarker != null && selectedMarker.exists()) { + this.findCandidateToTypeChangingMarkers(selectedMarker); + if (actionSelectionDialog.getReturnCode() == IDialogConstants.YES_ID) { + AddRemoveTypeCommand.addType(selectedMarker); + } else if (actionSelectionDialog.getReturnCode() == IDialogConstants.NO_ID) { + final MessageDialog warningDialog = + new MessageDialog(Activator.getShell(), "Warning!", null, + "If you remove marker's type, all relations of this marker has been removed! Do you want to continue to remove marker's type?", + MessageDialog.WARNING, new String[] {"YES", "NO"}, 0); + final int returnCode = warningDialog.open(); + if (returnCode != 0) { + return; + } + this.removeType(selectedMarker); + } + } else { + final MessageDialog dialog = + new MessageDialog(Activator.getShell(), "There is no marker in this position", null, + "Please select valid marker", MessageDialog.INFORMATION, new String[] {"OK"}, 0); + dialog.open(); + return; + } + } + + private static void addType(final IMarker selectedMarker) { + final MarkerWizard markerWizard = new MarkerWizard(selectedMarker); + final WizardDialog dialog = new WizardDialog(Activator.getShell(), markerWizard); + dialog.open(); + } + + /** + * @param selectedMarker from text + */ + private void findCandidateToTypeChangingMarkers(final IMarker selectedMarker) { + this.candidateToTypeChanging.add(selectedMarker); + + final Map fieldsSources = + AlloyUtilities.getRelationsOfSecondSideMarker(selectedMarker); + final ArrayList relationsSources = + AlloyUtilities.getSourcesOfMarkerAtRelations(selectedMarker); + + for (final IMarker iMarker : fieldsSources.keySet()) { + this.candidateToTypeChanging.add(iMarker); + } + + for (final IMarker iMarker : relationsSources) { + this.candidateToTypeChanging.add(iMarker); + } + } + + private void removeType(IMarker selectedMarker) { + selectedMarker = AnnotationFactory.convertAnnotationType(selectedMarker, true, true, + AlloyUtilities.getTotalTargetCount(selectedMarker)); + + IMarker marker = null; + for (int i = 1; i < this.candidateToTypeChanging.size(); i++) { + marker = this.candidateToTypeChanging.get(i); + AnnotationFactory.convertAnnotationType(marker, true, + MarkUtilities.compare(marker, selectedMarker), + AlloyUtilities.getTotalTargetCount(marker)); + } + AlloyUtilities.removeAllRelationsOfMarker(selectedMarker); + AlloyUtilities.removeRelationOfMarker(selectedMarker); + if (MarkUtilities.getGroupId(selectedMarker) != null) { + final List group = MarkerFactory.findMarkersByGroupId(selectedMarker.getResource(), + MarkUtilities.getGroupId(selectedMarker)); + for (final IMarker iMarker : group) { + AlloyUtilities.removeTypeFromMarker(iMarker); + MarkUtilities.setType(iMarker, null); + } + } else { + AlloyUtilities.removeTypeFromMarker(selectedMarker); + MarkUtilities.setType(selectedMarker, null); + } + + final MessageDialog removeSuccessDialog = new MessageDialog(Activator.getShell(), + "Removing Type Action", null, "Selected marker's type has been removed.", + MessageDialog.INFORMATION, new String[] {"OK"}, 0); + removeSuccessDialog.open(); + } + + @Override + public void run() { + if (AlloyUtilities.isExists()) { + this.candidateToTypeChanging = new ArrayList(); + this.addRemoveType(); + } else { + final MessageDialog infoDialog = new MessageDialog(Activator.getShell(), "System Information", + null, "You dont have any registered alloy file to system.", MessageDialog.INFORMATION, + new String[] {"OK"}, 0); + infoDialog.open(); + } + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/CreateInstanceElementCommand.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/CreateInstanceElementCommand.java new file mode 100644 index 00000000..4f6cd2fe --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/CreateInstanceElementCommand.java @@ -0,0 +1,14 @@ +package eu.modelwriter.marker.ui.internal.views.visualizationview.commands; + +import eu.modelwriter.configuration.generation.GenerationWizardDialog; +import eu.modelwriter.marker.ui.Activator; +import eu.modelwriter.marker.ui.internal.wizards.creatinginstanceelement.CreateInstanceElementWizard; + +public class CreateInstanceElementCommand implements Runnable { + @Override + public void run() { + final CreateInstanceElementWizard wizard = new CreateInstanceElementWizard(); + final GenerationWizardDialog dialog = new GenerationWizardDialog(Activator.getShell(), wizard); + dialog.open(); + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/CreateNewAtomCommand.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/CreateNewAtomCommand.java new file mode 100644 index 00000000..63d1ae3d --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/CreateNewAtomCommand.java @@ -0,0 +1,16 @@ +package eu.modelwriter.marker.ui.internal.views.visualizationview.commands; + +import org.eclipse.jface.wizard.WizardDialog; + +import eu.modelwriter.marker.ui.Activator; +import eu.modelwriter.marker.ui.internal.wizards.creatingatomwizard.CreatingAtomWizard; + +public class CreateNewAtomCommand implements Runnable { + @Override + public void run() { + final CreatingAtomWizard wizard = new CreatingAtomWizard(); + final WizardDialog dialog = new WizardDialog( + Activator.getDefault().getWorkbench().getWorkbenchWindows()[0].getShell(), wizard); + dialog.open(); + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/DeleteAtomCommand.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/DeleteAtomCommand.java new file mode 100644 index 00000000..4c654f91 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/DeleteAtomCommand.java @@ -0,0 +1,167 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.views.visualizationview.commands; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.emf.ecore.presentation.EcoreEditor; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.part.MultiPageEditorPart; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.marker.ui.Activator; + +public class DeleteAtomCommand implements Runnable { + private IEditorPart editor; + private final IMarker marker; + private ArrayList candidateToTypeChanging; + + public DeleteAtomCommand(final IMarker marker) { + this.marker = marker; + } + + private void checkImpactAndChangedMechanism(final IMarker beDeleted) { + if (MarkUtilities.getType(beDeleted) != null) { + final Map sourceRelationsOfDeleted = + AlloyUtilities.getRelationsOfSecondSideMarker(beDeleted); + for (final IMarker targetMarker : sourceRelationsOfDeleted.keySet()) { + if (AlloyUtilities.getRelationsOfFirstSideMarker(targetMarker).size() == 1) { + AlloyUtilities.unsetChanged(targetMarker); + } + } + } + } + + private void deleteFromAlloyXML(final IMarker beDeleted) { + checkImpactAndChangedMechanism(beDeleted); + AlloyUtilities.removeMarkerFromRepository(beDeleted); + if (MarkUtilities.getGroupId(beDeleted) == null + || MarkUtilities.getLeaderId(beDeleted) != null) { + AlloyUtilities.removeTypeFromMarker(beDeleted); + AlloyUtilities.removeRelationOfMarker(beDeleted); + } + } + + private void deleteMarker() { + try { + final IMarker beDeleted = marker; + if (beDeleted != null && beDeleted.exists()) { + final MessageDialog warningDialog = + new MessageDialog(Activator.getShell(), "Warning!", null, + "If you delete marker, all relations of this marker has been removed! Do you want to continue to delete marker?", + MessageDialog.WARNING, new String[] {"YES", "NO"}, 0); + if (warningDialog.open() != 0) { + return; + } + + findCandidateToTypeChangingMarkers(beDeleted); + final String sourceIdOfSelectedMarker = MarkUtilities.getSourceId(beDeleted); + + for (final IMarker iMarker : candidateToTypeChanging) { + AnnotationFactory.convertAnnotationType(iMarker, true, + MarkUtilities.compare(MarkUtilities.getSourceId(iMarker), sourceIdOfSelectedMarker), + AlloyUtilities.getTotalTargetCount(iMarker)); + } + final String markerText = MarkUtilities.getText(beDeleted); + + if (MarkUtilities.getLeaderId(beDeleted) != null) { + final String markerGroupId = MarkUtilities.getGroupId(beDeleted); + final List markers = + MarkerFactory.findMarkersByGroupId(beDeleted.getResource(), markerGroupId); + + for (int i = markers.size() - 1; i >= 0; i--) { + deleteFromAlloyXML(markers.get(i)); + AnnotationFactory.removeAnnotation(markers.get(i)); + markers.get(i).delete(); + } + } else { + deleteFromAlloyXML(beDeleted); + AnnotationFactory.removeAnnotation(beDeleted); + beDeleted.delete(); + } + final MessageDialog dialog = + new MessageDialog(Activator.getShell(), "Mark will be deleted by this wizard", null, + "\"" + markerText + "\" has been selected to be unmarked", + MessageDialog.INFORMATION, new String[] {"OK"}, 0); + dialog.open(); + } + } catch (final CoreException e) { + e.printStackTrace(); + } + } + + /** + * @param selectedMarker from text + */ + private void findCandidateToTypeChangingMarkers(final IMarker selectedMarker) { + final Map fieldsSources = + AlloyUtilities.getRelationsOfSecondSideMarker(selectedMarker); + final ArrayList relationsSources = + AlloyUtilities.getSourcesOfMarkerAtRelations(selectedMarker); + + for (final IMarker iMarker : fieldsSources.keySet()) { + candidateToTypeChanging.add(iMarker); + } + + for (final IMarker iMarker : relationsSources) { + candidateToTypeChanging.add(iMarker); + } + } + + private void refresh() { + ITextEditor iteEditor = null; + if (editor instanceof EcoreEditor) { + final EcoreEditor ecEditor = (EcoreEditor) editor; + ecEditor.getViewer().refresh(); + } else { + if (editor instanceof ITextEditor) { + iteEditor = (ITextEditor) editor; + } else { + final MultiPageEditorPart mpepEditor = (MultiPageEditorPart) editor; + final IEditorPart[] editors = mpepEditor.findEditors(mpepEditor.getEditorInput()); + iteEditor = (ITextEditor) editors[0]; + } + final IDocumentProvider idp = iteEditor.getDocumentProvider(); + try { + idp.resetDocument(iteEditor.getEditorInput()); + } catch (final CoreException e) { + e.printStackTrace(); + } + } + MarkerFactory.refreshProjectExp(); + } + + @Override + public void run() { + // FIXME + // editor = MarkerFactory.getOpenEditorOfMarker(marker); + if (AlloyUtilities.isExists()) { + candidateToTypeChanging = new ArrayList(); + deleteMarker(); + // this.refresh(); + } else { + final MessageDialog infoDialog = new MessageDialog(Activator.getShell(), "System Information", + null, "You dont have any registered alloy file to system.", MessageDialog.INFORMATION, + new String[] {"OK"}, 0); + infoDialog.open(); + } + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/MappingCommand.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/MappingCommand.java new file mode 100644 index 00000000..8650834e --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/MappingCommand.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.views.visualizationview.commands; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.wizard.WizardDialog; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.ui.Activator; +import eu.modelwriter.marker.ui.internal.wizards.mappingwizard.MappingWizard; + +public class MappingCommand implements Runnable { + private final IMarker marker; + + public MappingCommand(final IMarker marker) { + this.marker = marker; + } + + private static void chooseForAction(final IMarker iMarker) { + if (MarkUtilities.getType(iMarker) != null) { + MappingCommand.goForRelPage(iMarker); + } else { + MappingCommand.goForMapPage(iMarker); + } + } + + private static void goForMapPage(final IMarker iMarker) { + final MappingWizard relationWizard = new MappingWizard(iMarker, false); + final WizardDialog dialog = new WizardDialog(Activator.getShell(), relationWizard); + dialog.open(); + } + + private static void goForRelPage(final IMarker iMarker) { + final MappingWizard relationWizard = new MappingWizard(iMarker, true); + final WizardDialog dialog = new WizardDialog(Activator.getShell(), relationWizard); + dialog.open(); + } + + @Override + public void run() { + if (AlloyUtilities.isExists()) { + if (this.marker != null && this.marker.exists()) { + MappingCommand.chooseForAction(this.marker); + } else { + final MessageDialog dialog = + new MessageDialog(Activator.getShell(), "There is no marker in this position", null, + "Please select valid marker", MessageDialog.INFORMATION, new String[] {"OK"}, 0); + dialog.open(); + } + } else { + final MessageDialog infoDialog = new MessageDialog(Activator.getShell(), "System Information", + null, "You dont have any registered alloy file to system.", MessageDialog.INFORMATION, + new String[] {"OK"}, 0); + infoDialog.open(); + } + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/RemoveRelationCommand.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/RemoveRelationCommand.java new file mode 100644 index 00000000..69c43eb9 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/RemoveRelationCommand.java @@ -0,0 +1,33 @@ +package eu.modelwriter.marker.ui.internal.views.visualizationview.commands; + +import java.util.Map; + +import org.eclipse.core.resources.IMarker; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.internal.AnnotationFactory; + +public class RemoveRelationCommand implements Runnable { + private final String relation; + private IMarker fromMarker; + private final IMarker toMarker; + + public RemoveRelationCommand(final IMarker fromMarker, final IMarker toMarker, + final String relation) { + this.fromMarker = fromMarker; + this.toMarker = toMarker; + this.relation = relation; + } + + @Override + public void run() { + AlloyUtilities.removeFieldOfMarkers(this.fromMarker, this.toMarker, this.relation); + this.fromMarker = AnnotationFactory.convertAnnotationType(this.fromMarker, false, false, + AlloyUtilities.getTotalTargetCount(this.fromMarker)); + final Map relationsOfSelected = + AlloyUtilities.getRelationsOfFirstSideMarker(this.fromMarker); + if (relationsOfSelected.isEmpty()) { + AlloyUtilities.unsetChanged(this.fromMarker); + } + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/ResolveCommand.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/ResolveCommand.java new file mode 100644 index 00000000..2d90c0a3 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/ResolveCommand.java @@ -0,0 +1,29 @@ +package eu.modelwriter.marker.ui.internal.views.visualizationview.commands; + +import edu.mit.csail.sdg.alloy4viz.AlloyAtom; +import edu.mit.csail.sdg.alloy4viz.AlloyTuple; +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; + +public class ResolveCommand implements Runnable { + private final Object rightClickedAnnotation; + + public ResolveCommand(final Object rightClickedAnnotation) { + this.rightClickedAnnotation = rightClickedAnnotation; + } + + @Override + public void run() { + if (this.rightClickedAnnotation instanceof AlloyTuple) { + final AlloyTuple tuple = (AlloyTuple) this.rightClickedAnnotation; + final AlloyAtom fromAtom = tuple.getStart(); + final AlloyAtom toAtom = tuple.getEnd(); + AlloyUtilities.unsetImpactAndChanged(Visualization.getMarker(fromAtom), + Visualization.getMarker(toAtom)); + } else { + final AlloyAtom atom = (AlloyAtom) this.rightClickedAnnotation; + AlloyUtilities.unsetChangedAndAllImpacted(Visualization.getMarker(atom)); + } + return; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/TraceObserver.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/TraceObserver.java new file mode 100644 index 00000000..5acb55ac --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/TraceObserver.java @@ -0,0 +1,258 @@ +package eu.modelwriter.marker.ui.internal.views.visualizationview.commands; + +import java.io.IOException; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.jface.dialogs.MessageDialog; + +import edu.mit.csail.sdg.alloy4viz.AlloyAtom; +import eu.modelwriter.configuration.alloy.trace.TraceException; +import eu.modelwriter.configuration.alloy.trace.TraceManager; +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.configuration.internal.EcoreUtilities; +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.ui.Activator; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; +import eu.modelwriter.traceability.core.persistence.TupleType; + +public class TraceObserver implements VisualizationChangeListener { + + private static TraceObserver mInstance = null; + + public static TraceObserver get() { + if (TraceObserver.mInstance == null) { + TraceObserver.mInstance = new TraceObserver(); + } + return TraceObserver.mInstance; + } + + @Override + public void onRelationRemoved(final IMarker startMarker, final IMarker endMarker, + final String relation) { + // TODO onRelationRemoved implementation + } + + @Override + public void onAtomRemoved(final String sigTypeName, final String relUri) { + Activator.getDefault().getWorkbench().getDisplay().syncExec(new Runnable() { + @Override + public void run() { + if (!sigTypeName.isEmpty() && !relUri.isEmpty()) { + final MessageDialog dialog = Activator.infoDialogYESNO("Caution", + "This atom had a trace, do you want to delete corresponding ecore element?"); + if (dialog.open() == 0) { + try { + TraceManager.get().deleteEObject(sigTypeName, relUri); + } catch (IOException | TraceException e) { + e.printStackTrace(); + } + } + } + } + }); + } + + @Override + public void onAllReasonedAccepted() { + Activator.getDefault().getWorkbench().getDisplay().syncExec(new Runnable() { + @Override + public void run() { + for (final String atomName : AlloyUtilities.getAllReasonedAtoms()) { + try { + interpretAtom(atomName, true); + } catch (final Exception e) { + e.printStackTrace(); + } + } + for (final Entry entry : AlloyUtilities.getAllReasonedTuples() + .entrySet()) { + final TupleType tuple = entry.getKey(); + if (!tuple.getAtom().get(0).isReasoned() && !tuple.getAtom().get(1).isReasoned()) { + final IMarker fromMarker = + AlloyUtilities.findMarkerByID(tuple.getAtom().get(0).getLabel()); + final IMarker toMarker = + AlloyUtilities.findMarkerByID(tuple.getAtom().get(1).getLabel()); + try { + createRelation(fromMarker, toMarker, entry.getValue()); + AnnotationFactory.convertAnnotationType(fromMarker, false, false, + AlloyUtilities.getTotalTargetCount(fromMarker)); + } catch (final TraceException e) { + e.printStackTrace(); + } + } + } + Visualization.showViz(); + } + }); + } + + @Override + public void onReasonedRelationAccepted(final AlloyAtom fromAtom, final AlloyAtom toAtom, + final String relation) { + Activator.getDefault().getWorkbench().getDisplay().syncExec(new Runnable() { + @Override + public void run() { + try { + IMarker fromMarker = Visualization.getMarker(fromAtom); + IMarker toMarker = Visualization.getMarker(toAtom); + if (fromMarker == null) + fromMarker = interpretAtom(fromAtom.getOriginalName(), false); + + if (toMarker == null) + toMarker = interpretAtom(toAtom.getOriginalName(), false); + + if (fromMarker != null && toMarker != null && !relation + .equals(TraceManager.get().getContainmentRelation(fromMarker, toMarker))) { + createRelation(fromMarker, toMarker, relation); + AnnotationFactory.convertAnnotationType(fromMarker, false, false, + AlloyUtilities.getTotalTargetCount(fromMarker)); + } + } catch (final TraceException e) { + Activator.errorDialogOK("Error", e.getMessage()); + } finally { + Visualization.showViz(); + } + } + }); + } + + @Override + public void onAtomAccepted(final AlloyAtom alloyAtom) { + Activator.getDefault().getWorkbench().getDisplay().syncExec(new Runnable() { + @Override + public void run() { + try { + interpretAtom(alloyAtom.getOriginalName(), true); + } catch (final TraceException e) { + Activator.errorDialogOK("Error", e.getMessage()); + } finally { + Visualization.showViz(); + } + } + }); + } + + public IMarker interpretAtom(final String atomName, final boolean createRelations) + throws TraceException { + String sigTypeName = atomName; + int index = 0; + if (atomName.contains("$")) { + sigTypeName = atomName.substring(0, atomName.indexOf("$")); + index = Integer.parseInt(atomName.substring(sigTypeName.length() + 1)); + } + + String containmentRelation = null; + IMarker sourceMarker = null; + IMarker marker = null; + + marker = AlloyUtilities.findMarkerByID(AlloyUtilities.getAtomId(sigTypeName, index)); + if (marker != null) + return marker; + + final Map firstSides = + AlloyUtilities.getReasonedRelationsOfSSAtom(sigTypeName, index); + + if (firstSides.isEmpty()) { + sourceMarker = null; + } else { + final Object parent = findContainer(sigTypeName, firstSides); + containmentRelation = firstSides.get(parent); + if (parent instanceof String) { + // Need to interpret the parent + firstSides.remove(parent); + sourceMarker = interpretAtom((String) parent, true); + } else if (parent instanceof IMarker) { + firstSides.remove(parent); + sourceMarker = (IMarker) parent; + } else { + sourceMarker = null; + } + } + EObject eObject = TraceManager.get().createEObject(sigTypeName, atomName, sourceMarker); + marker = TraceManager.get().createMarkerForEObject(eObject); + if (marker != null) { + AlloyUtilities.addMarkerToRepository(marker); + AlloyUtilities.bindAtomToMarker(sigTypeName, index, marker); + if (containmentRelation != null && sourceMarker != null) { + AlloyUtilities.resetReasoned(sourceMarker, marker, containmentRelation); + AnnotationFactory.convertAnnotationType(sourceMarker, false, false, + AlloyUtilities.getTotalTargetCount(sourceMarker)); + } + + final Map secondSides = + AlloyUtilities.getReasonedRelationsOfFSAtom(sigTypeName, index); + if (createRelations && (!secondSides.isEmpty() || !firstSides.isEmpty())) { + MessageDialog dialog = Activator.infoDialogYESNO("Warning", + "Do you want to accept relations of " + atomName + " ?"); + if (dialog.open() == 0) { + createRelations(marker, secondSides); + createRelations(firstSides, marker); + AnnotationFactory.convertAnnotationType(marker, false, false, + AlloyUtilities.getTotalTargetCount(marker)); + } + } + } else { + // No marker no EObject + EObject container = eObject.eContainer(); + EcoreUtil.delete(eObject); + EcoreUtilities.saveResource(container); + } + return marker; + } + + private void createRelations(final Map firstSides, final IMarker marker) + throws TraceException { + for (final Entry entry : firstSides.entrySet()) { + if (entry.getKey() instanceof IMarker) { + createRelation((IMarker) entry.getKey(), marker, entry.getValue()); + } else { + // Atom has no marker, need to create one + interpretAtom((String) entry.getKey(), true); + } + } + } + + private void createRelations(IMarker marker, final Map secondSides) + throws TraceException { + for (final Entry entry : secondSides.entrySet()) { + if (entry.getKey() instanceof IMarker) { + createRelation(marker, (IMarker) entry.getKey(), entry.getValue()); + } else { + // Atom has no marker, need to create one + interpretAtom((String) entry.getKey(), true); + } + } + } + + private void createRelation(IMarker fromMarker, final IMarker toMarker, final String relationName) + throws TraceException { + TraceManager.get().createReference(fromMarker, toMarker, relationName); + AlloyUtilities.resetReasoned(fromMarker, toMarker, relationName); + } + + private Object findContainer(final String sigTypeName, final Map firstSides) + throws TraceException { + Set containers = TraceManager.get().getContainerSigTypes(sigTypeName); + for (Object object : firstSides.keySet()) { + if (object instanceof IMarker) { + IMarker iMarker = (IMarker) object; + String markerType = iMarker.getAttribute(MarkUtilities.MARKER_TYPE, ""); + if (containers.contains(markerType)) + return iMarker; + } else if (object instanceof String) { + String atomName = (String) object; + String type = + atomName.contains("$") ? atomName.substring(0, atomName.indexOf("$")) : atomName; + if (containers.contains(type)) + return type; + } + } + return null; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/VisualizationActionListenerFactory.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/VisualizationActionListenerFactory.java new file mode 100644 index 00000000..3bcbf92a --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/VisualizationActionListenerFactory.java @@ -0,0 +1,505 @@ +package eu.modelwriter.marker.ui.internal.views.visualizationview.commands; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.HashSet; +import java.util.Set; + +import javax.swing.JOptionPane; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.swt.widgets.Display; + +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4viz.AlloyAtom; +import edu.mit.csail.sdg.alloy4viz.AlloyTuple; +import eu.modelwriter.configuration.alloy.analysis.provider.AnalysisSourceProvider.ReasoningType; +import eu.modelwriter.configuration.alloy.discovery.AlloyDiscovering; +import eu.modelwriter.configuration.alloy.discovery.AlloyOtherSolutionDiscovering; +import eu.modelwriter.configuration.alloy.reasoning.AlloyOtherSolutionReasoning; +import eu.modelwriter.configuration.alloy.reasoning.AlloyReasoning; +import eu.modelwriter.configuration.alloy.validation.AlloyValidator; +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.configuration.specificreasoning.AlloyOtherSolutionReasoningForAtom; +import eu.modelwriter.configuration.specificreasoning.AlloyReasoningForAtom; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.ui.Activator; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; +import eu.modelwriter.marker.ui.internal.wizards.interpretationwizard.InterpretationWizard; + +public class VisualizationActionListenerFactory { + private static VisualizationActionListenerFactory instance; + + public static Set listeners = + new HashSet(); + + private VisualizationActionListenerFactory() {} + + public static VisualizationActionListenerFactory get() { + if (VisualizationActionListenerFactory.instance == null) { + VisualizationActionListenerFactory.instance = new VisualizationActionListenerFactory(); + } + return VisualizationActionListenerFactory.instance; + } + + public void registerListener(final VisualizationChangeListener listener) { + if (listener != null) { + synchronized (VisualizationActionListenerFactory.listeners) { + VisualizationActionListenerFactory.listeners.add(listener); + } + } + } + + public void unregisterListener(final VisualizationChangeListener listener) { + synchronized (VisualizationActionListenerFactory.listeners) { + VisualizationActionListenerFactory.listeners.remove(listener); + } + } + + public static ActionListener refreshActionListener() { + return new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + Visualization.showViz(); + } + }; + } + + public static ActionListener addRemoveTypeActionListener() { + return new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + final IMarker marker = + Visualization.getMarker((AlloyAtom) Visualization.rightClickedAnnotation); + Display.getDefault().syncExec(new AddRemoveTypeCommand(marker)); + Visualization.showViz(); + AlloyOtherSolutionReasoning.getInstance().finish(); + } + }; + } + + public static ActionListener createNewAtomActionListener() { + return new ActionListener() { + @Override + public void actionPerformed(final ActionEvent arg0) { + Display.getDefault().syncExec(new CreateNewAtomCommand()); + Visualization.showViz(); + AlloyOtherSolutionReasoning.getInstance().finish(); + } + }; + } + + public static ActionListener deleteAtomActionListener() { + return new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + final IMarker marker = + Visualization.getMarker((AlloyAtom) Visualization.rightClickedAnnotation); + final String sigTypeName = marker.getAttribute(MarkUtilities.MARKER_TYPE, ""); + final String relUri = marker.getAttribute(MarkUtilities.RELATIVE_URI, ""); + Display.getDefault().syncExec(new DeleteAtomCommand(marker)); + Visualization.showViz(); + AlloyOtherSolutionReasoning.getInstance().finish(); + for (final VisualizationChangeListener listener : VisualizationActionListenerFactory.listeners) { + listener.onAtomRemoved(sigTypeName, relUri); + } + } + }; + } + + public static ActionListener mappingActionListener() { + return new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + Display.getDefault().syncExec(new MappingCommand( + Visualization.getMarker((AlloyAtom) Visualization.rightClickedAnnotation))); + Visualization.showViz(); + AlloyOtherSolutionReasoning.getInstance().finish(); + } + }; + } + + public static ActionListener removeRelationActionListener() { + return new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + final IMarker startMarker = + Visualization.getMarker(((AlloyTuple) Visualization.rightClickedAnnotation).getStart()); + final IMarker endMarker = + Visualization.getMarker(((AlloyTuple) Visualization.rightClickedAnnotation).getEnd()); + final String relation = Visualization.relation; + Display.getDefault().syncExec(new RemoveRelationCommand(startMarker, endMarker, relation)); + Visualization.showViz(); + AlloyOtherSolutionReasoning.getInstance().finish(); + for (final VisualizationChangeListener listener : VisualizationActionListenerFactory.listeners) { + listener.onRelationRemoved(startMarker, endMarker, relation); + } + } + }; + } + + + public static ActionListener resolveActionListener() { + return new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + Display.getDefault().syncExec(new ResolveCommand(Visualization.rightClickedAnnotation)); + Visualization.showViz(); + } + }; + } + + public static ActionListener validateActionListener() { + return new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + if (AlloyValidator.validate()) { + JOptionPane.showMessageDialog(null, "Instance is consistent.", "Consistency Check", + JOptionPane.INFORMATION_MESSAGE); + } else { + JOptionPane.showMessageDialog(null, "Instance is inconsistent.", "Consistency Check", + JOptionPane.WARNING_MESSAGE); + } + + } + }; + } + + public static ActionListener discoverRelationActionListener() { + return new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent e) { + Activator.getDefault().getWorkbench().getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + Visualization.sourceProvider.setActive(ReasoningType.DISCOVER_RELATION); + } + }); + + final AlloyReasoning alloyReasoning = new AlloyReasoning(); + final boolean reasoning = alloyReasoning.reasoning(); + if (!reasoning) { + JOptionPane.showMessageDialog(null, "There is not any reasoning.", "Reason on Relations", + JOptionPane.INFORMATION_MESSAGE); + Visualization.sourceProvider.setPassive(); + } + Visualization.showViz(); + } + + }; + } + + public static ActionListener discoverRelationForAtomActionListener() { + return new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent e) { + Activator.getDefault().getWorkbench().getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + Visualization.sourceProvider.setActive(ReasoningType.DISCOVER_RELATION_FOR_ATOM); + } + }); + final AlloyAtom alloyAtom = (AlloyAtom) Visualization.rightClickedAnnotation; + + final String atomType = alloyAtom.getType().getName(); + String atomName = alloyAtom.toString(); + final String numIndex = atomName.substring(atomType.length()); + atomName = numIndex.isEmpty() ? atomName + "0" : atomName; + + final AlloyReasoningForAtom alloyReasoningForAtom = new AlloyReasoningForAtom(); + final boolean reasoning = alloyReasoningForAtom.reasoning(atomName, atomType); + if (!reasoning) { + JOptionPane.showMessageDialog(null, "There is not any reasoning for atom.", + "Reasoning for Atom", JOptionPane.INFORMATION_MESSAGE); + Visualization.sourceProvider.setPassive(); + } + Visualization.showViz(); + } + + }; + } + + public static ActionListener acceptReasonedRelationActionListener() { + return new ActionListener() { + IMarker selectedMarker; + + private void showWizard() { + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + final InterpretationWizard wizard = new InterpretationWizard(); + final WizardDialog dialog = new WizardDialog( + Activator.getDefault().getWorkbench().getWorkbenchWindows()[0].getShell(), wizard); + dialog.open(); + selectedMarker = wizard.getSelectedMarker(); + } + }); + } + + private IMarker interpretAtom(final AlloyAtom atom) { + showWizard(); + if (selectedMarker == null) { + return null; + } + + final String sigTypeName = atom.getType().getName(); + final String stringIndex = atom.toString().substring(sigTypeName.length()); + int index = 0; + if (!stringIndex.isEmpty()) { + index = Integer.parseInt(stringIndex); + } + + AlloyUtilities.bindAtomToMarker(sigTypeName, index, selectedMarker); + Visualization.showViz(); + return selectedMarker; + } + + @Override + public void actionPerformed(final ActionEvent e) { + if (Visualization.container == null) { + return; + } + final AlloyTuple tuple = (AlloyTuple) Visualization.rightClickedAnnotation; + final AlloyAtom fromAtom = tuple.getStart(); + final AlloyAtom toAtom = tuple.getEnd(); + IMarker fromMarker = Visualization.getMarker(fromAtom); + IMarker toMarker = Visualization.getMarker(toAtom); + + if (fromMarker == null) { + fromMarker = interpretAtom(fromAtom); + } else if (toMarker == null) { + toMarker = interpretAtom(toAtom); + } + + AlloyUtilities.resetReasoned(fromMarker, toMarker, Visualization.relation); + Visualization.showViz(); + } + }; + } + + public static ActionListener discoverAtomActionListener() { + return new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + Activator.getDefault().getWorkbench().getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + Visualization.sourceProvider.setActive(ReasoningType.DISCOVER_ATOM); + } + }); + + final AlloyDiscovering alloyDiscovering = new AlloyDiscovering(); + final boolean discovering = alloyDiscovering.discovering(); + if (!discovering) { + JOptionPane.showMessageDialog(null, "There is not any discovering.", + "Discovering on Atoms", JOptionPane.INFORMATION_MESSAGE); + Visualization.sourceProvider.setPassive(); + } + Visualization.showViz(); + } + }; + } + + public static ActionListener nextSolutionActionListener() { + return new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + boolean success = true; + if (Visualization.sourceProvider.getReasoningType() == ReasoningType.DISCOVER_RELATION) { + try { + success = AlloyOtherSolutionReasoning.getInstance().next(); + } catch (final Err e1) { + success = false; + } + } else if (Visualization.sourceProvider.getReasoningType() == ReasoningType.DISCOVER_ATOM) { + try { + success = AlloyOtherSolutionDiscovering.getInstance().next(); + } catch (final Err e1) { + success = false; + } + } else if (Visualization.sourceProvider + .getReasoningType() == ReasoningType.DISCOVER_RELATION_FOR_ATOM) { + try { + success = AlloyOtherSolutionReasoningForAtom.getInstance().next(); + } catch (final Err e1) { + success = false; + } + } + if (!success) { + JOptionPane.showMessageDialog(null, "There is not any other next solution.", + "Next Solution", JOptionPane.INFORMATION_MESSAGE); + } + Visualization.showViz(); + } + }; + } + + public static ActionListener previousSolutionActionListener() { + return new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + boolean success = true; + if (Visualization.sourceProvider.getReasoningType() == ReasoningType.DISCOVER_RELATION) { + try { + success = AlloyOtherSolutionReasoning.getInstance().previous(); + } catch (final Err e1) { + success = false; + } + } else if (Visualization.sourceProvider.getReasoningType() == ReasoningType.DISCOVER_ATOM) { + try { + success = AlloyOtherSolutionDiscovering.getInstance().previous(); + } catch (final Err e1) { + success = false; + } + } else if (Visualization.sourceProvider + .getReasoningType() == ReasoningType.DISCOVER_RELATION_FOR_ATOM) { + try { + success = AlloyOtherSolutionReasoningForAtom.getInstance().previous(); + } catch (final Err e1) { + success = false; + } + } + if (!success) { + JOptionPane.showMessageDialog(null, "There is not any other previous solution.", + "Previous Solution", JOptionPane.INFORMATION_MESSAGE); + } + Visualization.showViz(); + } + }; + } + + public static ActionListener stopAnalysisActionListener() { + return new ActionListener() { + @Override + public void actionPerformed(final ActionEvent e) { + Activator.getDefault().getWorkbench().getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + Visualization.sourceProvider.setPassive(); + } + }); + + AlloyOtherSolutionReasoning.getInstance().finish(); + Visualization.showViz(); + } + + }; + } + + public static ActionListener clearAllReasonedActionListener() { + return new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent e) { + AlloyUtilities.clearAllReasonedTuplesAndAtoms(); + Visualization.showViz(); + AlloyOtherSolutionReasoning.getInstance().finish(); + + Activator.getDefault().getWorkbench().getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + Visualization.sourceProvider.setPassive(); + } + }); + } + }; + } + + + public static ActionListener interpretAtomMenuItemActionListener() { + return new ActionListener() { + + IMarker selectedMarker; + + @Override + public void actionPerformed(final ActionEvent e) { + final AlloyAtom alloyAtom = (AlloyAtom) Visualization.rightClickedAnnotation; + + showWizard(); + if (selectedMarker == null) { + return; + } + + final String sigTypeName = alloyAtom.getType().getName(); + final String stringIndex = alloyAtom.toString().substring(sigTypeName.length()); + int index = 0; + if (!stringIndex.isEmpty()) { + index = Integer.parseInt(stringIndex); + } + + AlloyUtilities.bindAtomToMarker(sigTypeName, index, selectedMarker); + Visualization.showViz(); + } + + private void showWizard() { + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + final InterpretationWizard wizard = new InterpretationWizard(); + final WizardDialog dialog = new WizardDialog( + Activator.getDefault().getWorkbench().getWorkbenchWindows()[0].getShell(), wizard); + dialog.open(); + selectedMarker = wizard.getSelectedMarker(); + } + }); + } + }; + } + + public static ActionListener acceptAtomAsEMFMenuItemActionListener() { + return new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent e) { + final AlloyAtom alloyAtom = (AlloyAtom) Visualization.rightClickedAnnotation; + for (final VisualizationChangeListener listener : VisualizationActionListenerFactory.listeners) { + listener.onAtomAccepted(alloyAtom); + } + } + }; + } + + public static ActionListener acceptRelationAsEMFMenuItemActionListener() { + return new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent e) { + final AlloyTuple tuple = (AlloyTuple) Visualization.rightClickedAnnotation; + final AlloyAtom fromAtom = tuple.getStart(); + final AlloyAtom toAtom = tuple.getEnd(); + for (final VisualizationChangeListener listener : VisualizationActionListenerFactory.listeners) { + listener.onReasonedRelationAccepted(fromAtom, toAtom, Visualization.relation); + } + } + }; + } + + public static ActionListener acceptAllReasonedListener() { + return new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent e) { + AlloyOtherSolutionReasoningForAtom.getInstance().finish(); + for (final VisualizationChangeListener listener : VisualizationActionListenerFactory.listeners) { + listener.onAllReasonedAccepted(); + } + } + }; + } + + public static ActionListener createInstanceElementActionListener() { + return new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent e) { + Activator.getDefault().getWorkbench().getDisplay() + .asyncExec(new CreateInstanceElementCommand()); + } + }; + + } + +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/VisualizationChangeListener.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/VisualizationChangeListener.java new file mode 100644 index 00000000..3d0314eb --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/views/visualizationview/commands/VisualizationChangeListener.java @@ -0,0 +1,48 @@ +package eu.modelwriter.marker.ui.internal.views.visualizationview.commands; + +import org.eclipse.core.resources.IMarker; + +import edu.mit.csail.sdg.alloy4viz.AlloyAtom; + +public interface VisualizationChangeListener { + + /** + * When a relation has deleted + * + * @param startMarker + * @param endMarker + * @param relation + */ + void onRelationRemoved(IMarker startMarker, IMarker endMarker, String relation); + + /** + * When an atom has deleted. Parameters will be empty if this atom has no trace with an ecore + * element. + * + * @param sigTypeName, deleted atoms sig type + * @param relUri, relative uri @EObject that traced by this atom + */ + void onAtomRemoved(String sigTypeName, String relUri); + + /** + * When interpreting a relation that has a tuple of non-reasoned atom to reasoned atom. + * + * @param fromMarker Non-reasoned atom's marker + * @param toAtom The atom + * @param relation relation name + */ + void onReasonedRelationAccepted(AlloyAtom fromAtom, AlloyAtom toAtom, String relation); + + /** + * When interpreting an atom + * + * @param alloyAtom + */ + void onAtomAccepted(AlloyAtom alloyAtom); + + /** + * When accepting all reasoned tuples + */ + void onAllReasonedAccepted(); + +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatingatomwizard/CreatingAtomWizard.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatingatomwizard/CreatingAtomWizard.java new file mode 100644 index 00000000..c6b6fed4 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatingatomwizard/CreatingAtomWizard.java @@ -0,0 +1,109 @@ +package eu.modelwriter.marker.ui.internal.wizards.creatingatomwizard; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.swt.widgets.Composite; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.marker.internal.MarkerTypeElement; + +public class CreatingAtomWizard extends Wizard { + + private UntypedMarkerPage untypedMarkerPage; + private MarkerTypesPage markerTypesPage; + private final ArrayList candidateToTypeChanging = new ArrayList(); + + public CreatingAtomWizard() {} + + @Override + public void addPages() { + this.untypedMarkerPage = new UntypedMarkerPage(); + this.addPage(this.untypedMarkerPage); + this.markerTypesPage = new MarkerTypesPage(); + this.addPage(this.markerTypesPage); + } + + @Override + public boolean canFinish() { + if (this.markerTypesPage.isPageComplete()) { + return true; + } else { + return false; + } + } + + @Override + public void createPageControls(final Composite pageContainer) { + this.untypedMarkerPage.setPageComplete(false); + this.markerTypesPage.setPageComplete(false); + super.createPageControls(pageContainer); + } + + private void findCandidateToTypeChangingMarkers(final IMarker iMarker) { + this.candidateToTypeChanging.add(iMarker); + + final ArrayList relationsSources = AlloyUtilities.getSourcesOfMarkerAtRelations(iMarker); + + for (final IMarker marker : relationsSources) { + this.candidateToTypeChanging.add(marker); + } + } + + @Override + public IWizardPage getStartingPage() { + return this.untypedMarkerPage; + } + + @Override + public String getWindowTitle() { + return "Create Atom"; + } + + @Override + public boolean performFinish() { + IMarker iMarker = + (IMarker) ((TreeSelection) this.untypedMarkerPage.getSelection()).getFirstElement(); + final String markerType = ((MarkerTypeElement) ((TreeSelection) this.markerTypesPage.getSelection()) + .getFirstElement()).getType(); + + this.findCandidateToTypeChangingMarkers(iMarker); + iMarker = AnnotationFactory.convertAnnotationType(iMarker, true, true, + AlloyUtilities.getTotalTargetCount(iMarker)); + + IMarker mMarker = null; + for (int i = 1; i < this.candidateToTypeChanging.size(); i++) { + mMarker = this.candidateToTypeChanging.get(i); + AnnotationFactory.convertAnnotationType(mMarker, true, + MarkUtilities.compare(mMarker, iMarker), AlloyUtilities.getTotalTargetCount(mMarker)); + } + + AlloyUtilities.removeAllRelationsOfMarker(iMarker); + AlloyUtilities.removeRelationOfMarker(iMarker); + if (MarkUtilities.getGroupId(iMarker) != null) { + final List list = MarkerFactory.findMarkersByGroupId(iMarker.getResource(), + MarkUtilities.getGroupId(iMarker)); + for (final IMarker marker : list) { + AlloyUtilities.removeTypeFromMarker(marker); + MarkUtilities.setType(marker, markerType); + if (MarkUtilities.getLeaderId(marker) != null) { + AlloyUtilities.addTypeToMarker(marker); + } + AlloyUtilities.addMarkerToRepository(marker); + } + } else { + AlloyUtilities.removeTypeFromMarker(iMarker); + MarkUtilities.setType(iMarker, markerType); + AlloyUtilities.addTypeToMarker(iMarker); + AlloyUtilities.addMarkerToRepository(iMarker); + } + return true; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatingatomwizard/CreatingAtomWizardContentProvider.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatingatomwizard/CreatingAtomWizardContentProvider.java new file mode 100644 index 00000000..2d77de24 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatingatomwizard/CreatingAtomWizardContentProvider.java @@ -0,0 +1,68 @@ +package eu.modelwriter.marker.ui.internal.wizards.creatingatomwizard; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +import eu.modelwriter.marker.internal.MarkerFactory; + +public class CreatingAtomWizardContentProvider implements ITreeContentProvider { + + @Override + public void dispose() {} + + @Override + public Object[] getChildren(Object parentElement) { + if (parentElement instanceof IProject) { + IProject iProject = (IProject) parentElement; + try { + return iProject.members(); + } catch (CoreException e) { + e.printStackTrace(); + } + } else if (parentElement instanceof IFolder) { + IFolder iFolder = (IFolder) parentElement; + try { + return iFolder.members(); + } catch (CoreException e) { + e.printStackTrace(); + } + } else if (parentElement instanceof IFile) { + IFile iFile = (IFile) parentElement; + return MarkerFactory.findUntypedMarkers(iFile).toArray(); + } else { + return null; + } + return null; + } + + @Override + public Object[] getElements(Object inputElement) { + if (inputElement instanceof Object[]) { + return (Object[]) inputElement; + } else { + return new Object[0]; + } + } + + @Override + public Object getParent(Object element) { + return null; + } + + @Override + public boolean hasChildren(Object element) { + if (element instanceof IResource) { + return true; + } else { + return false; + } + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {} +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatingatomwizard/CreatingAtomWizardFilter.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatingatomwizard/CreatingAtomWizardFilter.java new file mode 100644 index 00000000..f25454c0 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatingatomwizard/CreatingAtomWizardFilter.java @@ -0,0 +1,54 @@ +package eu.modelwriter.marker.ui.internal.wizards.creatingatomwizard; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; + +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class CreatingAtomWizardFilter extends ViewerFilter { + + @Override + public boolean select(Viewer viewer, Object parentElement, Object element) { + if (element instanceof IProject) { + IProject iProject = (IProject) element; + try { + if (iProject.isOpen() && iProject.members().length != 0 + && !MarkerFactory.findUntypedMarkers(iProject).isEmpty()) { + return true; + } + } catch (CoreException e) { + e.printStackTrace(); + } + return false; + } else if (element instanceof IFolder) { + IFolder iFolder = (IFolder) element; + try { + if (iFolder.members().length != 0 && !MarkerFactory.findUntypedMarkers(iFolder).isEmpty()) { + return true; + } + } catch (CoreException e) { + e.printStackTrace(); + } + return false; + } else if (element instanceof IFile) { + IFile iFile = (IFile) element; + if (!MarkerFactory.findUntypedMarkers(iFile).isEmpty()) { + return true; + } + return false; + } else if (element instanceof IMarker) { + IMarker iMarker = (IMarker) element; + if (MarkUtilities.getType(iMarker) == null) { + return true; + } + return false; + } + return false; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatingatomwizard/CreatingAtomWizardLabelProvider.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatingatomwizard/CreatingAtomWizardLabelProvider.java new file mode 100644 index 00000000..89e106b7 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatingatomwizard/CreatingAtomWizardLabelProvider.java @@ -0,0 +1,50 @@ +package eu.modelwriter.marker.ui.internal.wizards.creatingatomwizard; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.ide.IDE.SharedImages; + +import eu.modelwriter.marker.internal.MarkUtilities; + +public class CreatingAtomWizardLabelProvider extends LabelProvider { + + @Override + public Image getImage(Object element) { + if (element instanceof IProject) { + if (((IProject) element).isOpen()) { + return PlatformUI.getWorkbench().getSharedImages().getImage(SharedImages.IMG_OBJ_PROJECT); + } else { + return PlatformUI.getWorkbench().getSharedImages() + .getImage(SharedImages.IMG_OBJ_PROJECT_CLOSED); + } + } else if (element instanceof IFolder) { + return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER); + } else if (element instanceof IFile) { + return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE); + } else if (element instanceof IMarker) { + return PlatformUI.getWorkbench().getSharedImages().getImage(SharedImages.IMG_OPEN_MARKER); + } + + return null; + } + + @Override + public String getText(Object element) { + if (element instanceof IResource) { + IResource iResource = (IResource) element; + return iResource.getName(); + } else if (element instanceof IMarker) { + IMarker iMarker = (IMarker) element; + return MarkUtilities.getText(iMarker); + } else { + return "Unknown type: " + element.getClass(); + } + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatingatomwizard/MarkerTypesPage.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatingatomwizard/MarkerTypesPage.java new file mode 100644 index 00000000..757a0c46 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatingatomwizard/MarkerTypesPage.java @@ -0,0 +1,73 @@ +package eu.modelwriter.marker.ui.internal.wizards.creatingatomwizard; + +import java.io.IOException; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; + +import eu.modelwriter.marker.Serialization; +import eu.modelwriter.marker.internal.MarkerTypeElement; +import eu.modelwriter.marker.ui.Activator; +import eu.modelwriter.marker.ui.internal.wizards.markerwizard.MarkerTreeViewContentProvider; +import eu.modelwriter.marker.ui.internal.wizards.markerwizard.MarkerTreeViewLabelProvider; + +public class MarkerTypesPage extends WizardPage { + + private ISelection selection; + + protected MarkerTypesPage() { + super("Marker Types Page"); + this.setTitle("Marker Types"); + this.setDescription("Marker types for this atom"); + } + + @Override + public void createControl(Composite parent) { + Composite container = new Composite(parent, SWT.NONE); + this.setControl(container); + container.setLayout(new FillLayout(SWT.HORIZONTAL)); + + TreeViewer treeViewer = new TreeViewer(container, SWT.BORDER); + treeViewer.setUseHashlookup(true); + treeViewer.setLabelProvider(new MarkerTreeViewLabelProvider()); + treeViewer.setContentProvider(new MarkerTreeViewContentProvider()); + + String savedTree = Activator.getDefault().getDialogSettings().get("universe"); + try { + Object[] array = new Object[1]; + if (savedTree != null) { + array[0] = Serialization.getInstance().fromString(savedTree); + treeViewer.setInput(array); + } + } catch (IOException | ClassNotFoundException e) { + e.printStackTrace(); + } + + treeViewer.addSelectionChangedListener(new ISelectionChangedListener() { + + @Override + public void selectionChanged(SelectionChangedEvent event) { + String markerType = + ((MarkerTypeElement) ((TreeSelection) event.getSelection()).getFirstElement()) + .getType(); + if (markerType.equals("universe") || markerType.endsWith("{abs}")) { + MarkerTypesPage.this.setPageComplete(false); + } else { + MarkerTypesPage.this.selection = event.getSelection(); + MarkerTypesPage.this.setPageComplete(true); + } + } + }); + } + + public ISelection getSelection() { + return this.selection; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatingatomwizard/UntypedMarkerPage.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatingatomwizard/UntypedMarkerPage.java new file mode 100644 index 00000000..c83a569a --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatingatomwizard/UntypedMarkerPage.java @@ -0,0 +1,56 @@ +package eu.modelwriter.marker.ui.internal.wizards.creatingatomwizard; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; + +public class UntypedMarkerPage extends WizardPage { + + private ISelection selection; + + protected UntypedMarkerPage() { + super("Markers Page"); + this.setTitle("Markers"); + this.setDescription("Untyped Markes For Create Atom"); + } + + @Override + public void createControl(Composite parent) { + Composite container = new Composite(parent, SWT.NONE); + this.setControl(container); + container.setLayout(new FillLayout(SWT.HORIZONTAL)); + + TreeViewer treeViewer = new TreeViewer(container, SWT.BORDER); + treeViewer.setUseHashlookup(true); + treeViewer.setLabelProvider(new CreatingAtomWizardLabelProvider()); + treeViewer.setContentProvider(new CreatingAtomWizardContentProvider()); + treeViewer.setInput(ResourcesPlugin.getWorkspace().getRoot().getProjects()); + treeViewer.setFilters(new ViewerFilter[] {new CreatingAtomWizardFilter()}); + + treeViewer.addSelectionChangedListener(new ISelectionChangedListener() { + + @Override + public void selectionChanged(SelectionChangedEvent event) { + if (((TreeSelection) event.getSelection()).getFirstElement() instanceof IMarker) { + UntypedMarkerPage.this.selection = event.getSelection(); + UntypedMarkerPage.this.setPageComplete(true); + } else { + UntypedMarkerPage.this.setPageComplete(false); + } + } + }); + } + + public ISelection getSelection() { + return this.selection; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/AttributePage.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/AttributePage.java new file mode 100644 index 00000000..0d3b5f65 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/AttributePage.java @@ -0,0 +1,25 @@ +package eu.modelwriter.marker.ui.internal.wizards.creatinginstanceelement; + +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; + +public class AttributePage extends WizardPage { + + + protected AttributePage() { + super("Attributes"); + this.setTitle("Attributes"); + this.setDescription(""); + } + + @Override + public void createControl(Composite parent) { + Composite container = new Composite(parent, SWT.NONE); + this.setControl(container); + container.setLayout(new FillLayout(SWT.HORIZONTAL)); + + } + +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/ContainerSelectionPage.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/ContainerSelectionPage.java new file mode 100644 index 00000000..e9273b9f --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/ContainerSelectionPage.java @@ -0,0 +1,74 @@ +package eu.modelwriter.marker.ui.internal.wizards.creatinginstanceelement; + +import java.util.Iterator; +import java.util.Set; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; + +import eu.modelwriter.configuration.generation.GenerationWizardPage; +import eu.modelwriter.configuration.internal.AlloyUtilities; + +public class ContainerSelectionPage extends GenerationWizardPage { + + private ISelection selection; + private TreeViewer treeViewer; + + protected ContainerSelectionPage() { + super("Containers"); + setTitle("Containers"); + setDescription("Select a container for new element"); + } + + @Override + public void createControl(Composite parent) { + Composite container = new Composite(parent, SWT.NONE); + setControl(container); + container.setLayout(new FillLayout(SWT.HORIZONTAL)); + + treeViewer = new TreeViewer(container, SWT.BORDER); + treeViewer.setUseHashlookup(true); + treeViewer.setLabelProvider(new SigTypeLabelProvider()); + treeViewer.setContentProvider(new SigTypeContentProvider()); + treeViewer.setInput(ResourcesPlugin.getWorkspace().getRoot().getProjects()); + + treeViewer.addSelectionChangedListener(new ISelectionChangedListener() { + + @Override + public void selectionChanged(SelectionChangedEvent event) { + if (((TreeSelection) event.getSelection()).getFirstElement() instanceof IMarker) { + selection = event.getSelection(); + ContainerSelectionPage.this.setPageComplete(true); + } else { + ContainerSelectionPage.this.setPageComplete(false); + } + } + }); + } + + public ISelection getSelection() { + return selection; + } + + public IMarker getSelectedMarker() { + return (IMarker) ((TreeSelection) getSelection()).getFirstElement(); + } + + public void setSigType(Set containerSigTypes) { + for (Iterator iterator = containerSigTypes.iterator(); iterator.hasNext();) { + String sigType = (String) iterator.next(); + containerSigTypes + .addAll(AlloyUtilities.getAllChildNames(AlloyUtilities.getSigTypeIdByName(sigType))); + } + treeViewer.setFilters(new ViewerFilter[] {new SigTypeFilter(containerSigTypes)}); + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/CreateInstanceElementWizard.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/CreateInstanceElementWizard.java new file mode 100644 index 00000000..569d8355 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/CreateInstanceElementWizard.java @@ -0,0 +1,102 @@ +package eu.modelwriter.marker.ui.internal.wizards.creatinginstanceelement; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.swt.widgets.Composite; + +import eu.modelwriter.configuration.alloy.trace.TraceException; +import eu.modelwriter.configuration.alloy.trace.TraceManager; +import eu.modelwriter.configuration.generation.GenerationWizard; +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.configuration.internal.EcoreUtilities; +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.marker.ui.internal.views.visualizationview.Visualization; + +public class CreateInstanceElementWizard extends GenerationWizard { + + public CreateInstanceElementWizard() { + super(null, "Create Instance Element"); + } + + private TypeSelectionPage typeSelectionPage; + private ContainerSelectionPage containerSelectionPage; + + @Override + public void addPages() { + typeSelectionPage = new TypeSelectionPage(); + addPage(typeSelectionPage); + containerSelectionPage = new ContainerSelectionPage(); + addPage(containerSelectionPage); + } + + @Override + public boolean canFinish() { + IWizardPage page = getContainer().getCurrentPage(); + if (page instanceof TypeSelectionPage) { + TypeSelectionPage typePage = ((TypeSelectionPage) page); + if (typePage.isPageComplete()) + return !typePage.canFlipToNextPage(); + else + return false; + } else if (page instanceof ContainerSelectionPage) + return page.isPageComplete(); + return false; + } + + @Override + public void createPageControls(final Composite pageContainer) { + typeSelectionPage.setPageComplete(false); + containerSelectionPage.setPageComplete(false); + super.createPageControls(pageContainer); + } + + @Override + public IWizardPage getStartingPage() { + return typeSelectionPage; + } + + @Override + public String getWindowTitle() { + return "Create Instance Element"; + } + + @Override + public boolean performFinish() { + final String sigTypeName = typeSelectionPage.getSelectedType(); + IMarker containerMarker = null; + if (containerSelectionPage.isPageComplete()) + containerMarker = containerSelectionPage.getSelectedMarker(); + + try { + EObject eObject = TraceManager.get().createEObject(sigTypeName, "", containerMarker); + IMarker marker = TraceManager.get().createMarkerForEObject(eObject); + if (marker == null) { + return false; + } + AlloyUtilities.addTypeToMarker(marker); + AlloyUtilities.addMarkerToRepository(marker); + String atomName = AlloyUtilities.getAtomNameById(MarkUtilities.getSourceId(marker)); + EcoreUtilities.eSetAttributeByName(eObject, "name", atomName); + EcoreUtilities.saveResource(eObject); + MarkUtilities.setText(marker, MarkerFactory.instanceToString(eObject)); + int index = Integer.parseInt(atomName.toString().substring(sigTypeName.length() + 1)); + AlloyUtilities.bindAtomToMarker(sigTypeName, index, marker); + if (containerMarker != null) { + String relation = TraceManager.get().getContainmentRelation(containerMarker, marker); + AlloyUtilities.addRelation2Markers(containerMarker, marker, relation); + AnnotationFactory.convertAnnotationType(containerMarker, false, false, + AlloyUtilities.getTotalTargetCount(containerMarker)); + } + } catch (TraceException e) { + e.printStackTrace(); + return false; + } finally { + Visualization.showViz(); + } + return true; + } + +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/SigTypeContentProvider.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/SigTypeContentProvider.java new file mode 100644 index 00000000..32c980c7 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/SigTypeContentProvider.java @@ -0,0 +1,68 @@ +package eu.modelwriter.marker.ui.internal.wizards.creatinginstanceelement; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +import eu.modelwriter.marker.internal.MarkerFactory; + +public class SigTypeContentProvider implements ITreeContentProvider { + + @Override + public void dispose() {} + + @Override + public Object[] getChildren(Object parentElement) { + if (parentElement instanceof IProject) { + IProject iProject = (IProject) parentElement; + try { + return iProject.members(); + } catch (CoreException e) { + e.printStackTrace(); + } + } else if (parentElement instanceof IFolder) { + IFolder iFolder = (IFolder) parentElement; + try { + return iFolder.members(); + } catch (CoreException e) { + e.printStackTrace(); + } + } else if (parentElement instanceof IFile) { + IFile iFile = (IFile) parentElement; + return MarkerFactory.findMarkers(iFile).toArray(); + } else { + return null; + } + return null; + } + + @Override + public Object[] getElements(Object inputElement) { + if (inputElement instanceof Object[]) { + return (Object[]) inputElement; + } else { + return new Object[0]; + } + } + + @Override + public Object getParent(Object element) { + return null; + } + + @Override + public boolean hasChildren(Object element) { + if (element instanceof IResource) { + return true; + } else { + return false; + } + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {} +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/SigTypeFilter.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/SigTypeFilter.java new file mode 100644 index 00000000..0b4a3719 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/SigTypeFilter.java @@ -0,0 +1,62 @@ +package eu.modelwriter.marker.ui.internal.wizards.creatinginstanceelement; + +import java.util.Set; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; + +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class SigTypeFilter extends ViewerFilter { + + private Set containerSigTypes; + + public SigTypeFilter(Set containerSigTypes) { + this.containerSigTypes = containerSigTypes; + } + + @Override + public boolean select(Viewer viewer, Object parentElement, Object element) { + if (element instanceof IProject) { + IProject iProject = (IProject) element; + try { + if (iProject.isOpen() && iProject.members().length != 0 + && !MarkerFactory.findMarkers(iProject).isEmpty()) { + return true; + } + } catch (CoreException e) { + e.printStackTrace(); + } + return false; + } else if (element instanceof IFolder) { + IFolder iFolder = (IFolder) element; + try { + if (iFolder.members().length != 0 && !MarkerFactory.findMarkers(iFolder).isEmpty()) { + return true; + } + } catch (CoreException e) { + e.printStackTrace(); + } + return false; + } else if (element instanceof IFile) { + IFile iFile = (IFile) element; + if (!MarkerFactory.findMarkers(iFile).isEmpty()) { + return true; + } + return false; + } else if (element instanceof IMarker) { + IMarker iMarker = (IMarker) element; + if (containerSigTypes.contains(MarkUtilities.getType(iMarker))) { + return true; + } + return false; + } + return false; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/SigTypeLabelProvider.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/SigTypeLabelProvider.java new file mode 100644 index 00000000..40a022cc --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/SigTypeLabelProvider.java @@ -0,0 +1,51 @@ +package eu.modelwriter.marker.ui.internal.wizards.creatinginstanceelement; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.ide.IDE.SharedImages; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.internal.MarkUtilities; + +public class SigTypeLabelProvider extends LabelProvider { + + @Override + public Image getImage(Object element) { + if (element instanceof IProject) { + if (((IProject) element).isOpen()) { + return PlatformUI.getWorkbench().getSharedImages().getImage(SharedImages.IMG_OBJ_PROJECT); + } else { + return PlatformUI.getWorkbench().getSharedImages() + .getImage(SharedImages.IMG_OBJ_PROJECT_CLOSED); + } + } else if (element instanceof IFolder) { + return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER); + } else if (element instanceof IFile) { + return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE); + } else if (element instanceof IMarker) { + return PlatformUI.getWorkbench().getSharedImages().getImage(SharedImages.IMG_OPEN_MARKER); + } + + return null; + } + + @Override + public String getText(Object element) { + if (element instanceof IResource) { + IResource iResource = (IResource) element; + return iResource.getName(); + } else if (element instanceof IMarker) { + IMarker iMarker = (IMarker) element; + return AlloyUtilities.getAtomNameById(MarkUtilities.getSourceId(iMarker));// MarkUtilities.getText(iMarker); + } else { + return "Unknown type: " + element.getClass(); + } + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/TypeSelectionPage.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/TypeSelectionPage.java new file mode 100644 index 00000000..5f25947f --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/creatinginstanceelement/TypeSelectionPage.java @@ -0,0 +1,111 @@ +package eu.modelwriter.marker.ui.internal.wizards.creatinginstanceelement; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; + +import eu.modelwriter.configuration.alloy.trace.LoadItem; +import eu.modelwriter.configuration.alloy.trace.TraceManager; +import eu.modelwriter.configuration.generation.GenerationWizardPage; +import eu.modelwriter.marker.Serialization; +import eu.modelwriter.marker.internal.MarkerTypeElement; +import eu.modelwriter.marker.ui.Activator; +import eu.modelwriter.marker.ui.internal.wizards.markerwizard.MarkerTreeViewContentProvider; +import eu.modelwriter.marker.ui.internal.wizards.markerwizard.MarkerTreeViewLabelProvider; + +public class TypeSelectionPage extends GenerationWizardPage { + + private List allEClasses = new ArrayList(); + private Set containerSigTypes; + private ISelection selection; + private boolean canFlip = false; + + protected TypeSelectionPage() { + super("Types Page"); + setTitle("Types"); + setDescription("Select type for this element"); + } + + @Override + public void createControl(Composite parent) { + Composite container = new Composite(parent, SWT.NONE); + setControl(container); + container.setLayout(new FillLayout(SWT.HORIZONTAL)); + + TreeViewer treeViewer = new TreeViewer(container, SWT.BORDER); + treeViewer.setUseHashlookup(true); + treeViewer.setLabelProvider(new MarkerTreeViewLabelProvider()); + treeViewer.setContentProvider(new MarkerTreeViewContentProvider()); + + String savedTree = Activator.getDefault().getDialogSettings().get("universe"); + try { + Object[] array = new Object[1]; + if (savedTree != null) { + array[0] = Serialization.getInstance().fromString(savedTree); + treeViewer.setInput(array); + } + } catch (IOException | ClassNotFoundException e) { + e.printStackTrace(); + } + + for (LoadItem loadItem : TraceManager.get().getLoads()) { + allEClasses.addAll(loadItem.getAllEClasses().values()); + } + + treeViewer.addSelectionChangedListener(new ISelectionChangedListener() { + + @Override + public void selectionChanged(SelectionChangedEvent event) { + String markerType = + ((MarkerTypeElement) ((TreeSelection) event.getSelection()).getFirstElement()) + .getType(); + if (markerType.equals("universe") || markerType.endsWith("{abs}")) { + TypeSelectionPage.this.setPageComplete(false); + canFlip = false; + } else { + selection = event.getSelection(); + containerSigTypes = TraceManager.get().findContainers(allEClasses, getSelectedType()); + canFlip = !containerSigTypes.isEmpty(); + TypeSelectionPage.this.setPageComplete(true); + getContainer().updateButtons(); + } + } + }); + + } + + + @Override + public boolean canFlipToNextPage() { + return canFlip; + } + + public ISelection getSelection() { + return selection; + } + + public String getSelectedType() { + return ((MarkerTypeElement) ((TreeSelection) getSelection()).getFirstElement()).getType(); + } + + @Override + public boolean nextPressed() throws Exception { + if (!containerSigTypes.isEmpty()) { + ContainerSelectionPage nextPage = (ContainerSelectionPage) getNextPage(); + nextPage.setSigType(containerSigTypes); + } + + return super.nextPressed(); + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/examplewizard/NewModelWriterExampleWizard.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/examplewizard/NewModelWriterExampleWizard.java new file mode 100644 index 00000000..cda365bb --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/examplewizard/NewModelWriterExampleWizard.java @@ -0,0 +1,107 @@ +package eu.modelwriter.marker.ui.internal.wizards.examplewizard; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.emf.common.CommonPlugin; +import org.eclipse.emf.common.ui.wizard.AbstractExampleInstallerWizard; +import org.eclipse.emf.common.util.URI; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.ui.IWorkbench; + +public class NewModelWriterExampleWizard extends AbstractExampleInstallerWizard { + private static NewModelWriterExampleWizardPage mwPage; + List projectDescriptors; + List filesToOpen; + + public NewModelWriterExampleWizard() { + super(); + this.setWindowTitle("Create New Model Writer Example"); + this.projectDescriptors = new ArrayList<>(); + this.filesToOpen = new ArrayList<>(); + } + + @Override + public void addPages() { + NewModelWriterExampleWizard.mwPage = new NewModelWriterExampleWizardPage(this, "mwPage", + "Model Writer Example Page", (ImageDescriptor) null); + this.addPage(NewModelWriterExampleWizard.mwPage); + } + + @Override + protected List getFilesToOpen() { + return this.filesToOpen; + } + + @Override + public IWizardPage getNextPage(final IWizardPage page) { + this.setForcePreviousAndNextButtons(false); + return NewModelWriterExampleWizard.mwPage; + } + + @Override + protected List getProjectDescriptors() { + return this.projectDescriptors; + } + + @Override + public void init(final IWorkbench workbench, final IStructuredSelection selection) { + super.init(workbench, selection); + this.setWindowTitle("ModelWriter Example Wizard"); + + final AbstractExampleInstallerWizard.ProjectDescriptor pd0 = + new AbstractExampleInstallerWizard.ProjectDescriptor(); + pd0.setDescription("Creates all ModelWriter example projects."); + pd0.setName("ModelWriter Examples"); + pd0.setContentURI(CommonPlugin.resolve(URI.createURI( // full path + "platform:/plugin/eu.modelwriter.marker.ui/examples/"))); + this.getProjectDescriptors().add(pd0); + + // final AbstractExampleInstallerWizard.ProjectDescriptor pd1 = + // new AbstractExampleInstallerWizard.ProjectDescriptor(); + // pd1.setDescription("Creates ModelWriter Ecore example projects."); + // pd1.setName("ModelWriter Ecore Example"); + // pd1.setContentURI(CommonPlugin.resolve(URI.createURI( // full path + // "platform:/plugin/eu.modelwriter.marker.ui/examples/EcoreExample"))); + // this.getProjectDescriptors().add(pd1); + // + // final AbstractExampleInstallerWizard.ProjectDescriptor pd2 = + // new AbstractExampleInstallerWizard.ProjectDescriptor(); + // pd2.setDescription("Creates ModelWriter Reqif example projects."); + // pd2.setName("ModelWriter Reqif Example"); + // pd2.setContentURI(CommonPlugin.resolve(URI.createURI( // full path + // "platform:/plugin/eu.modelwriter.marker.ui/examples/ReqifExample"))); + // this.getProjectDescriptors().add(pd2); + // + // final AbstractExampleInstallerWizard.ProjectDescriptor pd3 = + // new AbstractExampleInstallerWizard.ProjectDescriptor(); + // pd3.setDescription("Creates ModelWriter Text example projects."); + // pd3.setName("ModelWriter Text Example"); + // pd3.setContentURI(CommonPlugin.resolve(URI.createURI( // full path + // "platform:/plugin/eu.modelwriter.marker.ui/examples/TextExample"))); + // this.getProjectDescriptors().add(pd3); + + final AbstractExampleInstallerWizard.FileToOpen fto = + new AbstractExampleInstallerWizard.FileToOpen(); + fto.setEditorID(""); + fto.setLocation(CommonPlugin // full path + .resolve(URI.createURI( + "platform:/plugin/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/examplewizard/examples/qwe.xml")) + .toFileString()); + this.getFilesToOpen().add(fto); + } + + @Override + public boolean performFinish() { + try { + this.installProjectFromDirectory(this.getProjectDescriptors().get(0), + new NullProgressMonitor()); + } catch (final Exception e) { + e.printStackTrace(); + } + return true; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/examplewizard/NewModelWriterExampleWizardPage.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/examplewizard/NewModelWriterExampleWizardPage.java new file mode 100644 index 00000000..e4daccc3 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/examplewizard/NewModelWriterExampleWizardPage.java @@ -0,0 +1,31 @@ +package eu.modelwriter.marker.ui.internal.wizards.examplewizard; + +import org.eclipse.emf.common.ui.wizard.AbstractExampleInstallerWizard; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.List; + +public class NewModelWriterExampleWizardPage extends AbstractExampleInstallerWizard.ProjectPage { + Composite container; + + public NewModelWriterExampleWizardPage( + final AbstractExampleInstallerWizard abstractExampleInstallerWizard, final String pageName, + final String title, final ImageDescriptor titleImage) { + abstractExampleInstallerWizard.super(pageName, title, titleImage); + } + + /** + * Create contents of the wizard. + * + * @param parent + */ + @Override + public void createControl(final Composite parent) { + super.createControl(parent); + } + + public List getProjectList() { + this.projectList = new org.eclipse.swt.widgets.List(this.container, 0); + return this.projectList; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/interpretationwizard/InterpretationWizard.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/interpretationwizard/InterpretationWizard.java new file mode 100644 index 00000000..6e8ab887 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/interpretationwizard/InterpretationWizard.java @@ -0,0 +1,77 @@ +package eu.modelwriter.marker.ui.internal.wizards.interpretationwizard; + +import java.util.ArrayList; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.wizard.Wizard; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkUtilities; + +public class InterpretationWizard extends Wizard { + + private SelectionPage selectionPage; + + private IMarker selectedMarker; + + public InterpretationWizard() { + setWindowTitle("Interpretation of Atom"); + } + + @Override + public void addPages() { + selectionPage = new SelectionPage("Selection Page"); + addPage(selectionPage); + } + + private ArrayList findCandidateToTypeChangingMarkers(final IMarker iMarker) { + final ArrayList candidateToTypeChanging = new ArrayList<>(); + candidateToTypeChanging.add(iMarker); + + final ArrayList relationsSources = + AlloyUtilities.getSourcesOfMarkerAtRelations(iMarker); + + for (final IMarker marker : relationsSources) { + candidateToTypeChanging.add(marker); + } + return candidateToTypeChanging; + } + + public IMarker getSelectedMarker() { + return selectedMarker; + } + + @Override + public boolean performFinish() { + if (selectionPage.getSelection() instanceof IMarker) { + selectedMarker = (IMarker) selectionPage.getSelection(); + } + + if (selectedMarker == null) + return false; + + final ArrayList candidateToTypeChanging = + findCandidateToTypeChangingMarkers(selectedMarker); + selectedMarker = AnnotationFactory.convertAnnotationType(selectedMarker, true, true, + AlloyUtilities.getTotalTargetCount(selectedMarker)); + + IMarker mMarker = null; + for (int i = 1; i < candidateToTypeChanging.size(); i++) { + mMarker = candidateToTypeChanging.get(i); + AnnotationFactory.convertAnnotationType(mMarker, true, + MarkUtilities.compare(mMarker, selectedMarker), + AlloyUtilities.getTotalTargetCount(mMarker)); + } + AlloyUtilities.removeAllRelationsOfMarker(selectedMarker); + AlloyUtilities.removeRelationOfMarker(selectedMarker); + + return true; + } + + @Override + public boolean canFinish() { + return selectionPage.isPageComplete(); + } + +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/interpretationwizard/SelectionPage.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/interpretationwizard/SelectionPage.java new file mode 100644 index 00000000..84d43bb9 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/interpretationwizard/SelectionPage.java @@ -0,0 +1,60 @@ +package eu.modelwriter.marker.ui.internal.wizards.interpretationwizard; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ITreeSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; + +import eu.modelwriter.marker.ui.internal.wizards.creatingatomwizard.CreatingAtomWizardContentProvider; +import eu.modelwriter.marker.ui.internal.wizards.creatingatomwizard.CreatingAtomWizardFilter; +import eu.modelwriter.marker.ui.internal.wizards.creatingatomwizard.CreatingAtomWizardLabelProvider; + +public class SelectionPage extends WizardPage { + + private TreeViewer treeViewer; + + protected SelectionPage(final String pageName) { + super(pageName); + setTitle("Trace Elements"); + } + + @Override + public void createControl(final Composite parent) { + final Composite container = new Composite(parent, SWT.NONE); + setControl(container); + container.setLayout(new FillLayout(SWT.HORIZONTAL)); + + treeViewer = new TreeViewer(container, SWT.BORDER); + treeViewer.setUseHashlookup(true); + treeViewer.setLabelProvider(new CreatingAtomWizardLabelProvider()); + treeViewer.setContentProvider(new CreatingAtomWizardContentProvider()); + treeViewer.setInput(ResourcesPlugin.getWorkspace().getRoot().getProjects()); + treeViewer.setFilters(new ViewerFilter[] {new CreatingAtomWizardFilter()}); + + treeViewer.addSelectionChangedListener(new ISelectionChangedListener() { + + @Override + public void selectionChanged(final SelectionChangedEvent event) { + if (((TreeSelection) event.getSelection()).getFirstElement() instanceof IMarker) { + SelectionPage.this.setPageComplete(true); + } else { + SelectionPage.this.setPageComplete(false); + } + } + }); + + setPageComplete(false); + } + + public Object getSelection() { + return ((ITreeSelection) treeViewer.getSelection()).getFirstElement(); + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/launchwizard/LaunchWizard.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/launchwizard/LaunchWizard.java new file mode 100644 index 00000000..4b867bce --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/launchwizard/LaunchWizard.java @@ -0,0 +1,42 @@ +package eu.modelwriter.marker.ui.internal.wizards.launchwizard; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.wizard.Wizard; + +public class LaunchWizard extends Wizard { + + private LaunchWizardPage page; + + private final List commands; + + private String selectedCommand; + + public LaunchWizard() { + this.commands = new ArrayList(); + this.setWindowTitle("Commands For Launch"); + } + + public LaunchWizard(final List commands) { + this.commands = commands; + this.setWindowTitle("Commands For Launch"); + } + + @Override + public void addPages() { + super.addPages(); + this.page = new LaunchWizardPage(this.commands); + this.addPage(this.page); + } + + public String getSelection() { + return this.selectedCommand; + } + + @Override + public boolean performFinish() { + this.selectedCommand = this.page.getSelection(); + return true; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/launchwizard/LaunchWizardPage.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/launchwizard/LaunchWizardPage.java new file mode 100644 index 00000000..a5f00a74 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/launchwizard/LaunchWizardPage.java @@ -0,0 +1,38 @@ +package eu.modelwriter.marker.ui.internal.wizards.launchwizard; + +import java.util.List; + +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; + +public class LaunchWizardPage extends WizardPage { + + private final List commandList; + + private org.eclipse.swt.widgets.List list; + + public LaunchWizardPage(final List commands) { + super("Launch Wizard"); + this.commandList = commands; + } + + @Override + public void createControl(final Composite parent) { + final Composite container = new Composite(parent, SWT.NULL); + this.setControl(container); + container.setLayout(new FillLayout(SWT.HORIZONTAL)); + + this.list = + new org.eclipse.swt.widgets.List(container, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); + + for (final String command : this.commandList) { + this.list.add(command); + } + } + + public String getSelection() { + return this.list.getSelection()[0]; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/ActionSelectionDialog.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/ActionSelectionDialog.java new file mode 100644 index 00000000..736006e9 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/ActionSelectionDialog.java @@ -0,0 +1,66 @@ +package eu.modelwriter.marker.ui.internal.wizards.mappingwizard; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; + +public class ActionSelectionDialog extends Dialog { + + /** + * Create the dialog. + * + * @param parentShell + */ + public ActionSelectionDialog(final Shell parentShell) { + super(parentShell); + this.setShellStyle(SWT.DIALOG_TRIM); + } + + @Override + protected void buttonPressed(final int buttonId) { + this.setReturnCode(buttonId); + this.close(); + } + + /** + * Create contents of the button bar. + * + * @param parent + */ + @Override + protected void createButtonsForButtonBar(final Composite parent) { + this.createButton(parent, IDialogConstants.YES_ID, "Add Type", true); + this.createButton(parent, IDialogConstants.NO_ID, "Remove Current Type", false); + } + + /** + * Create contents of the dialog. + * + * @param parent + */ + @Override + protected Control createDialogArea(final Composite parent) { + final Composite container = (Composite) super.createDialogArea(parent); + container.setToolTipText(""); + container.setLayout(null); + + final Label lblNewLabel = new Label(container, SWT.NONE); + lblNewLabel.setBounds(31, 10, 317, 13); + lblNewLabel.setText("Which action do you want to do ?!"); + + return container; + } + + /** + * Return the initial size of the dialog. + */ + @Override + protected Point getInitialSize() { + return new Point(284, 123); + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/MappingWizard.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/MappingWizard.java new file mode 100644 index 00000000..56f0ffe6 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/MappingWizard.java @@ -0,0 +1,164 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.wizards.mappingwizard; + +import java.util.ArrayList; +import java.util.Iterator; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.swt.widgets.Composite; + +import eu.modelwriter.configuration.alloy.reasoning.AlloyOtherSolutionReasoning; +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkUtilities; + +public class MappingWizard extends Wizard { + + public static ArrayList beforeCheckedMarkers; + + public IMarker selectedMarker; + private MarkerMatchPage markerMatchPage; + private RelationsWizardPage relationWizardPage; + + private ArrayList listOfSome; + + boolean isIndirect; + + public MappingWizard(final IMarker selectedMarker, final boolean isIndirect) { + this.selectedMarker = selectedMarker; + this.isIndirect = isIndirect; + this.setNeedsProgressMonitor(true); + } + + @Override + public void addPages() { + if (this.isIndirect) { + this.relationWizardPage = new RelationsWizardPage(this.selectedMarker); + this.addPage(this.relationWizardPage); + } + this.markerMatchPage = new MarkerMatchPage(this.selectedMarker, this.isIndirect); + this.addPage(this.markerMatchPage); + } + + private void addRelationsOfNewCheckeds(final ArrayList newCheckeds) { + for (final IMarker checkedMarker : newCheckeds) { + if (this.isIndirect) { + AlloyUtilities.addRelation2Markers(this.selectedMarker, checkedMarker, + RelationsWizardPage.selectedRelation.substring(0, + RelationsWizardPage.selectedRelation.indexOf(" "))); + } else { + AlloyUtilities.addMapping2RelationType(this.selectedMarker, checkedMarker); + } + } + AnnotationFactory.convertAnnotationType(this.selectedMarker, false, false, + AlloyUtilities.getTotalTargetCount(this.selectedMarker)); + } + + @Override + public boolean canFinish() { + if (this.markerMatchPage.isPageComplete()) { + return true; + } else { + return false; + } + } + + @Override + public void createPageControls(final Composite pageContainer) { + if (this.isIndirect) { + this.relationWizardPage.setPageComplete(false); + } + this.markerMatchPage.setPageComplete(false); + } + + private void findUnCheckedsAndNewCheckeds() { + final Iterator listOfSomeIter = this.listOfSome.iterator(); + + while (listOfSomeIter.hasNext()) { + final IMarker someMarker = listOfSomeIter.next(); + + final Iterator beforeMarkerIter = MappingWizard.beforeCheckedMarkers.iterator(); + while (beforeMarkerIter.hasNext()) { + final IMarker beforeMarker = beforeMarkerIter.next(); + if (MarkUtilities.compare(someMarker, beforeMarker)) { + listOfSomeIter.remove(); + beforeMarkerIter.remove(); + break; + } + } + } + } + + public MarkerMatchPage getMarkerMatchPage() { + if (MarkerMatchPage.markTreeViewer != null + && !MarkerMatchPage.markTreeViewer.getTree().isDisposed()) { + MarkerMatchPage.markTreeViewer + .setFilters(new ViewerFilter[] {new WizardTreeViewFilter(this.isIndirect)}); + // TODO Look here maybe there is a little bug + this.markerMatchPage.initCheckedElements(); + MarkerMatchPage.markTreeViewer.collapseAll(); + } + return this.markerMatchPage; + } + + public RelationsWizardPage getRelationWizardPage() { + return this.relationWizardPage; + } + + @Override + public IWizardPage getStartingPage() { + if (this.isIndirect) { + return this.relationWizardPage; + } else { + return this.markerMatchPage; + } + } + + @Override + public String getWindowTitle() { + return "Create a trace relation"; + } + + @Override + public boolean performFinish() { + AlloyOtherSolutionReasoning.getInstance().finish(); + + this.listOfSome = MarkerMatchPage.checkedElements; + + this.findUnCheckedsAndNewCheckeds(); + this.addRelationsOfNewCheckeds(this.listOfSome); + this.removeRelationsOfUncheckeds(MappingWizard.beforeCheckedMarkers); + this.refreshUI(); + + return true; + } + + private void refreshUI() { + AnnotationFactory.convertAnnotationType(this.selectedMarker, false, false, + AlloyUtilities.getTotalTargetCount(this.selectedMarker)); + } + + private void removeRelationsOfUncheckeds(final ArrayList unCheckeds) { + for (final IMarker unCheckedMarker : unCheckeds) { + if (this.isIndirect) { + AlloyUtilities.removeFieldOfMarkers(this.selectedMarker, unCheckedMarker, + RelationsWizardPage.selectedRelation.substring(0, + RelationsWizardPage.selectedRelation.indexOf(" "))); + } else { + AlloyUtilities.removeMappingFromRelationType(this.selectedMarker, unCheckedMarker); + } + } + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/MarkerMapping.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/MarkerMapping.java new file mode 100644 index 00000000..c92f971c --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/MarkerMapping.java @@ -0,0 +1,155 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.wizards.mappingwizard; + +import java.util.ArrayList; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.presentation.EcoreEditor; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ITreeSelection; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.PlatformUI; + +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.marker.ui.internal.wizards.selectionwizard.SelectionWizard; + +@SuppressWarnings("restriction") +public class MarkerMapping { + private static IMarker marker; + private static MarkerMapping manager; + + public static MarkerMapping getInstance() { + if (MarkerMapping.manager == null) { + MarkerMapping.manager = new MarkerMapping(); + } + return MarkerMapping.manager; + } + + IEditorPart editor; + IFile file; + ISelection selection; + + private MarkerMapping() {} + + private void chooseForAction(final IMarker iMarker) { + if (MarkUtilities.getType(iMarker) != null) { + goForRelPage(iMarker); + } else { + goForMapPage(iMarker); + } + } + + private IMarker getMarker() { + IMarker iMarker = null; + if (selection != null) { + if (selection instanceof ITextSelection) { + final TextSelection textSelection = (TextSelection) selection; + + final ArrayList markerList = + MarkerFactory.findMarkersInSelection(file, textSelection); + if (markerList != null) { + if (markerList.size() == 1) { + iMarker = markerList.get(0); + } else if (markerList.size() > 1) { + final SelectionWizard selectionWizard = new SelectionWizard(markerList); + final WizardDialog selectionDialog = + new WizardDialog(MarkerActivator.getShell(), selectionWizard); + if (selectionDialog.open() == 1) { + return null; + } + iMarker = selectionWizard.getSelectedMarker(); + } + } + } else if (selection instanceof ITreeSelection) { + final ITreeSelection treeSelection = (ITreeSelection) selection; + if (((ITreeSelection) selection).getFirstElement() instanceof IMarker) { + iMarker = (IMarker) ((ITreeSelection) selection).getFirstElement(); + } else if (editor instanceof EcoreEditor) { + if (treeSelection.getFirstElement() instanceof ENamedElement + && ((ENamedElement) treeSelection.getFirstElement()).getName() != null + && !((ENamedElement) treeSelection.getFirstElement()).getName().isEmpty()) { + + final URI uri = EcoreUtil.getURI((ENamedElement) treeSelection.getFirstElement()); + + iMarker = MarkerFactory.findMarkersByUri(file, uri.toString()); + } else if (!((EObject) treeSelection.getFirstElement() instanceof EModelElement)) { + final URI uri = EcoreUtil.getURI((EObject) treeSelection.getFirstElement()); + iMarker = MarkerFactory.findMarkersByUri(file, uri.toString()); + } + } else if (editor instanceof CompilationUnitEditor) { + iMarker = MarkerFactory.findMarkerByOutlineTreeSelection(treeSelection, file); + } + } + } + return iMarker; + } + + private void goForMapPage(final IMarker iMarker) { + final MappingWizard relationWizard = new MappingWizard(iMarker, false); + + final WizardDialog dialog = new WizardDialog(MarkerActivator.getShell(), relationWizard); + dialog.open(); + } + + private void goForRelPage(final IMarker iMarker) { + final MappingWizard relationWizard = new MappingWizard(iMarker, true); + + final WizardDialog dialog = new WizardDialog(MarkerActivator.getShell(), relationWizard); + dialog.open(); + } + + private void run() { + if (MarkerMapping.marker != null && MarkerMapping.marker.exists()) { + chooseForAction(MarkerMapping.marker); + } else { + final MessageDialog dialog = + new MessageDialog(MarkerActivator.getShell(), "There is no marker in this position", null, + "Please select valid marker", MessageDialog.INFORMATION, new String[] {"OK"}, 0); + dialog.open(); + } + } + + /** + * it takes marker and then it runs mapping + * + * @param marker + */ + public void runWithMarker(final IMarker marker) { + MarkerMapping.marker = marker; + run(); + } + + /** + * it gets active editor and selection, and find marker then it runs mapping + */ + public void runWithSelection() { + selection = MarkerFactory.getSelection(); + file = MarkerActivator.getEditor().getEditorInput().getAdapter(IFile.class); + editor = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + + MarkerMapping.marker = getMarker(); + run(); + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/MarkerMatchPage.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/MarkerMatchPage.java new file mode 100644 index 00000000..e929b1f2 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/MarkerMatchPage.java @@ -0,0 +1,229 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.wizards.mappingwizard; + +import java.util.ArrayList; +import java.util.Iterator; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.viewers.CheckStateChangedEvent; +import org.eclipse.jface.viewers.CheckboxTreeViewer; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.ICheckStateListener; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeViewerListener; +import org.eclipse.jface.viewers.TreeExpansionEvent; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class MarkerMatchPage extends WizardPage { + public static ArrayList checkedElements; + public static CheckboxTreeViewer markTreeViewer = null; + public static IMarker selectedMarker; + boolean isIndirect; + + public MarkerMatchPage(IMarker selectedMarker, boolean isIndirect) { + super("Markers Page"); + this.setTitle("Markers"); + this.setDescription("\"" + MarkUtilities.getText(selectedMarker) + "\""); + MarkerMatchPage.selectedMarker = selectedMarker; + this.isIndirect = isIndirect; + } + + @Override + public void createControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NONE); + composite.setLayout(new GridLayout(1, false)); + this.setControl(composite); + + this.initCheckedElements(); + + MarkerMatchPage.markTreeViewer = new CheckboxTreeViewer(composite); + MarkerMatchPage.markTreeViewer.getTree().setLayoutData(new GridData(GridData.FILL_BOTH)); + + WizardTreeViewContentProvider treeViewerContentProvider = new WizardTreeViewContentProvider(); + + MarkerMatchPage.markTreeViewer.setLabelProvider(new WizardTreeViewLabelProvider()); + MarkerMatchPage.markTreeViewer.setContentProvider(treeViewerContentProvider); + ViewerFilter[] filter = new ViewerFilter[] {new WizardTreeViewFilter(this.isIndirect)}; + MarkerMatchPage.markTreeViewer.setInput(ResourcesPlugin.getWorkspace().getRoot().getProjects()); + MarkerMatchPage.markTreeViewer.setFilters(filter); + + if (MappingWizard.beforeCheckedMarkers.size() != 0) { + for (IMarker checkedMarker : MappingWizard.beforeCheckedMarkers) { + MarkerMatchPage.markTreeViewer.setChecked(checkedMarker, true); + } + } + + MarkerMatchPage.markTreeViewer.addTreeListener(new ITreeViewerListener() { + + @Override + public void treeCollapsed(TreeExpansionEvent event) {} + + @Override + public void treeExpanded(TreeExpansionEvent event) { + + final Object element = event.getElement(); + final Object[] children = treeViewerContentProvider.getChildren(element); + for (Object child : children) { + + for (IMarker checkedMarker : MarkerMatchPage.checkedElements) { + if (child instanceof IMarker && MarkUtilities.compare(checkedMarker, (IMarker) child)) { + MarkerMatchPage.markTreeViewer.setChecked(child, true); + } + } + } + } + }); + + // When user checks a checkbox in the tree, check all its children + MarkerMatchPage.markTreeViewer.addCheckStateListener(new ICheckStateListener() { + @Override + public void checkStateChanged(CheckStateChangedEvent event) { + if (event.getChecked()) { + // . . . check all its children + if (event.getElement() instanceof IProject && !((IProject) event.getElement()).isOpen()) { + return; + } + MarkerMatchPage.markTreeViewer.setSubtreeChecked(event.getElement(), true); + if (event.getElement() instanceof IResource) { + IResource iResource = (IResource) event.getElement(); + for (IMarker iMarker : MarkerFactory.findMarkers(iResource)) { + if (MarkUtilities.getGroupId(iMarker) != null + && MarkUtilities.getLeaderId(iMarker) == null) { + continue; + } + if (MarkUtilities.getType(MarkerMatchPage.selectedMarker) != null) { + if (MarkUtilities.getType(iMarker) != null) { + for (String type : WizardTreeViewFilter.suitableTypes) { + if (type.substring(type.indexOf("/") + 1) + .equals(MarkUtilities.getType(iMarker))) { + if (!MarkerMatchPage.checkedElements.contains(iMarker) + && !MarkUtilities.compare(iMarker, MarkerMatchPage.selectedMarker)) { + MarkerMatchPage.checkedElements.add(iMarker); + } + } + } + } + } else { + if (!MarkerMatchPage.checkedElements.contains(iMarker) + && !MarkUtilities.compare(iMarker, MarkerMatchPage.selectedMarker)) { + MarkerMatchPage.checkedElements.add(iMarker); + } + } + } + } else if (event.getElement() instanceof IMarker) { + IMarker iMarker = (IMarker) event.getElement(); + MarkerMatchPage.checkedElements.add(iMarker); + } + } else { + if (event.getElement() instanceof IProject && !((IProject) event.getElement()).isOpen()) { + return; + } + MarkerMatchPage.markTreeViewer.setSubtreeChecked(event.getElement(), false); + if (event.getElement() instanceof IResource) { + IResource iResource = (IResource) event.getElement(); + for (IMarker iMarker : MarkerFactory.findMarkers(iResource)) { + Iterator iter = MarkerMatchPage.checkedElements.iterator(); + while (iter.hasNext()) { + IMarker checkedMarker = iter.next(); + try { + if (checkedMarker.getAttribute(IMarker.SOURCE_ID) + .equals(iMarker.getAttribute(IMarker.SOURCE_ID))) { + iter.remove(); + break; + } + } catch (CoreException e) { + e.printStackTrace(); + } + } + } + } else if (event.getElement() instanceof IMarker) { + IMarker iMarker = (IMarker) event.getElement(); + Iterator iter = MarkerMatchPage.checkedElements.iterator(); + while (iter.hasNext()) { + IMarker checkedMarker = iter.next(); + try { + if (checkedMarker.getAttribute(IMarker.SOURCE_ID) + .equals(iMarker.getAttribute(IMarker.SOURCE_ID))) { + iter.remove(); + break; + } + } catch (CoreException e) { + e.printStackTrace(); + } + } + } + } + MarkerMatchPage.this.setPageComplete(true); + } + }); + + markTreeViewer.addDoubleClickListener(new IDoubleClickListener() { + + @Override + public void doubleClick(DoubleClickEvent event) { + IStructuredSelection selection = (IStructuredSelection) event.getSelection(); + Object firstElement = selection.getFirstElement(); + if (markTreeViewer.isExpandable(firstElement)) { + boolean expanded = markTreeViewer.getExpandedState(firstElement); + markTreeViewer.setExpandedState(firstElement, !expanded); + } + + } + }); + + Button filterButton = new Button(composite, SWT.CHECK); + filterButton.setText("&Show only files that contain Marker(s)"); + filterButton.setSelection(true); + + filterButton.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent event) { + boolean isPressed = ((Button) event.widget).getSelection(); + if (isPressed) { + MarkerMatchPage.markTreeViewer.setFilters(filter); + } else { + MarkerMatchPage.markTreeViewer.resetFilters(); + } + } + }); + } + + protected void initCheckedElements() { + if (this.isIndirect) { + MappingWizard.beforeCheckedMarkers = AlloyUtilities.getSecondSideMarkerIdsByMarkerAndRelation( + selectedMarker, RelationsWizardPage.selectedRelation.substring(0, + RelationsWizardPage.selectedRelation.indexOf(" "))); + } else { + MappingWizard.beforeCheckedMarkers = + AlloyUtilities.getSecondSideMarkerIdsByMarkerAndRelationV2(selectedMarker); + } + MarkerMatchPage.checkedElements = new ArrayList<>(MappingWizard.beforeCheckedMarkers); + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/RelationsWizardPage.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/RelationsWizardPage.java new file mode 100644 index 00000000..2df88b90 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/RelationsWizardPage.java @@ -0,0 +1,145 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.wizards.mappingwizard; + +import java.io.IOException; +import java.util.ArrayList; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.Serialization; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.ui.internal.preferences.RefColumn; +import eu.modelwriter.marker.ui.internal.wizards.markerwizard.MarkerPage; + +public class RelationsWizardPage extends WizardPage { + public static String selectedRelation; + private TableViewer tableViewer; + private Table table; + private final IMarker selectedMarker; + boolean isIndirect; + + /** + * Create the wizard. + */ + public RelationsWizardPage(final IMarker selectedMarker) { + super("Relations Page"); + this.setTitle("Relations"); + String str = null; + if (MarkUtilities.getType(selectedMarker) != null) { + str = "{" + AlloyUtilities.getAtomNameById(MarkUtilities.getSourceId(selectedMarker)) + "}"; + } + this.setDescription("Suitable relations for selected trace element " + str); + this.selectedMarker = selectedMarker; + } + + /** + * Create contents of the wizard. + * + * @param parent + */ + @Override + public void createControl(final Composite parent) { + final Composite container = new Composite(parent, SWT.NULL); + + this.setControl(container); + container.setLayout(new FillLayout(SWT.HORIZONTAL)); + + this.tableViewer = new TableViewer(container, SWT.BORDER | SWT.FULL_SELECTION); + this.table = this.tableViewer.getTable(); + + this.tableViewer.setContentProvider(ArrayContentProvider.getInstance()); + new RefColumn().addColumnTo(this.tableViewer); + + this.tableViewer.addDoubleClickListener(new IDoubleClickListener() { + + @Override + public void doubleClick(final DoubleClickEvent event) { + if (RelationsWizardPage.this.getNextPage() != null) { + RelationsWizardPage.this.getContainer().showPage(RelationsWizardPage.this.getNextPage()); + } + + } + }); + + final String rels = MarkerPage.settings.get("rels"); + if (rels != null) { + try { + String markerType = MarkUtilities.getType(this.selectedMarker); + final ArrayList suitableRelationTypes = AlloyUtilities.getRelationTypesForFirstSide(markerType); + final ArrayList relsList = Serialization.getInstance().fromString(rels); + final ArrayList filteredRelations = new ArrayList(); + + for (final String rel : relsList) { + for (final String suitableRel : suitableRelationTypes) { + ArrayList allParentIds = AlloyUtilities + .getAllParentIds(AlloyUtilities.getSigTypeIdByName(markerType)); + for (int id : allParentIds) { + String sigName = AlloyUtilities.getSigNameById(id); + if (rel.substring(0, rel.indexOf(":")).trim().equals(suitableRel) + && rel.substring(rel.indexOf(":") + 1, rel.indexOf("->")).trim().equals(sigName)) { + filteredRelations.add(rel); + } + } + } + } + this.tableViewer.setInput(filteredRelations); + final TableColumn[] columns = this.tableViewer.getTable().getColumns(); + for (int i = 0; i < columns.length; i++) { + columns[i].pack(); + } + + } catch (final ClassNotFoundException e) { + e.printStackTrace(); + } catch (final IOException e) { + e.printStackTrace(); + } + } + + this.tableViewer.addSelectionChangedListener(new ISelectionChangedListener() { + + @Override + public void selectionChanged(final SelectionChangedEvent event) { + final StructuredSelection sel = (StructuredSelection) event.getSelection(); + RelationsWizardPage.selectedRelation = sel.getFirstElement().toString(); + RelationsWizardPage.this.setPageComplete(true); + } + }); + } + + @Override + public IWizardPage getNextPage() { + return ((MappingWizard) this.getWizard()).getMarkerMatchPage(); + } + + public Table getTable() { + return this.table; + } + + public void setTable(final Table table) { + this.table = table; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/WizardTreeViewContentProvider.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/WizardTreeViewContentProvider.java new file mode 100644 index 00000000..6ca723b4 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/WizardTreeViewContentProvider.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.wizards.mappingwizard; + +import java.util.ArrayList; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class WizardTreeViewContentProvider implements ITreeContentProvider { + + @Override + public void dispose() {} + + @Override + public Object[] getChildren(Object parentElement) { + + if (parentElement instanceof IProject) { + if (((IProject) parentElement).isOpen()) { + try { + return ((IProject) parentElement).members(); + } catch (CoreException e) { + e.printStackTrace(); + } + } + } else if (parentElement instanceof IFolder) { + try { + return ((IFolder) parentElement).members(); + } catch (CoreException e) { + e.printStackTrace(); + } + } else if (parentElement instanceof IFile) { + ArrayList markers = MarkerFactory.findMarkersAsArrayList((IFile) parentElement); + + for (int i = markers.size() - 1; i >= 0; i--) { + + if (MarkUtilities.compare(markers.get(i), MarkerMatchPage.selectedMarker) + || ((MarkUtilities.getGroupId(markers.get(i)) != null) + && (MarkUtilities.getLeaderId(markers.get(i)) == null))) { + markers.remove(i); + } + } + return markers.toArray(); + + } else { + return null; + } + return null; + } + + @Override + public Object[] getElements(Object inputElement) { + + if (inputElement instanceof Object[]) { + return (Object[]) inputElement; + } else { + return new Object[0]; + } + } + + @Override + public Object getParent(Object element) { + return null; + } + + @Override + public boolean hasChildren(Object element) { + + if (element instanceof IProject) { + try { + if (((IProject) element).isOpen()) { + if (((IProject) element).members().length != 0) { + return true; + } else { + return false; + } + } + } catch (CoreException e) { + e.printStackTrace(); + } + } else if (element instanceof IMarker) { + return false; + } else if (element instanceof IFolder) { + try { + if (((IFolder) element).members().length != 0) { + return true; + } else { + return false; + } + } catch (CoreException e) { + e.printStackTrace(); + } + } else if (element instanceof IFile) { + if (!(MarkerFactory.findMarkers((IFile) element)).isEmpty()) { + return true; + } else { + return false; + } + } + + return false; + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {} +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/WizardTreeViewFilter.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/WizardTreeViewFilter.java new file mode 100644 index 00000000..e0dcea28 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/WizardTreeViewFilter.java @@ -0,0 +1,132 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.wizards.mappingwizard; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class WizardTreeViewFilter extends ViewerFilter { + public static ArrayList suitableTypes; + private boolean isIndirect; + + public WizardTreeViewFilter(boolean isIndirect) { + this.isIndirect = isIndirect; + if (isIndirect) { + WizardTreeViewFilter.suitableTypes = AlloyUtilities.getSuitableSecondSideTypesOfRelation( + RelationsWizardPage.selectedRelation.substring(0, + RelationsWizardPage.selectedRelation.indexOf(" ")), + RelationsWizardPage.selectedRelation.substring( + RelationsWizardPage.selectedRelation.indexOf(": ") + 2, + RelationsWizardPage.selectedRelation.indexOf(" ->"))); + } + } + + @Override + public boolean select(Viewer viewer, Object parentElement, Object element) { + String groupIdOfSelected = MarkUtilities.getGroupId(MarkerMatchPage.selectedMarker); + if (element instanceof IResource) { + if (element instanceof IProject) { + IProject project = (IProject) element; + if (!project.isOpen()) { + return false; + } + } + List list = MarkerFactory.findMarkers((IResource) element); + if (list.isEmpty()) { + return false; + } + // ikisinde de gecerli + if (groupIdOfSelected != null) { + if (MarkerFactory.findMarkerBySourceId((IResource) element, + MarkUtilities.getSourceId(MarkerMatchPage.selectedMarker)) != null + && MarkerFactory.findMarkersByGroupId((IResource) element, groupIdOfSelected) + .size() == list.size()) { + return false; + } + } else { + if (MarkerFactory.findMarkerBySourceId((IResource) element, + MarkUtilities.getSourceId(MarkerMatchPage.selectedMarker)) != null + && list.size() == 1) { + return false; + } + } + if (this.isIndirect) { // selected marker tipli ise + for (IMarker iMarker : list) { + if (MarkUtilities.getType(iMarker) != null) { // hicbirinin tipi yoksa + for (String type : WizardTreeViewFilter.suitableTypes) { + if (type.substring(type.indexOf("/") + 1).equals(MarkUtilities.getType(iMarker))) { + if (MarkUtilities.getGroupId(iMarker) != null) { // kendi grubundan degilse + if (MarkUtilities.getGroupId(MarkerMatchPage.selectedMarker) != null) { + if (!MarkUtilities.getGroupId(iMarker).equals(groupIdOfSelected)) { + return true; + } + } else if (!MarkUtilities.compare(iMarker, MarkerMatchPage.selectedMarker)) { + return true; // kendisi degilse + } + } else if (!MarkUtilities.compare(iMarker, MarkerMatchPage.selectedMarker)) { + return true; // kendisi degilse + } + } + } + } + } + } else { + return true; + } + return false; + } else if (element instanceof IMarker) { + IMarker marker = (IMarker) element; + if (this.isIndirect) { + if (MarkUtilities.getType(marker) == null) { + return false; + } else { // tipi varsa + for (String type : WizardTreeViewFilter.suitableTypes) { + if (type.substring(type.indexOf("/") + 1).equals(MarkUtilities.getType(marker))) { + if (MarkUtilities.getGroupId(marker) != null) { // kendi grubundan degilse + if (MarkUtilities.getGroupId(MarkerMatchPage.selectedMarker) != null) { + if (!MarkUtilities.getGroupId(marker).equals(groupIdOfSelected)) { + return true; + } else { + return false; + } + } else if (!MarkUtilities.compare(marker, MarkerMatchPage.selectedMarker)) { + return true; // kendisi degilse + } + } else if (!MarkUtilities.compare(marker, MarkerMatchPage.selectedMarker)) { + return true; // kendisi degilse + } + } + } + return false; + } + } else { + if (groupIdOfSelected != null && MarkUtilities.getGroupId(marker) != null + && groupIdOfSelected.equals(MarkUtilities.getGroupId(marker))) { + return false; // kendi grubundan biriyse + } + if (MarkUtilities.compare(marker, MarkerMatchPage.selectedMarker)) { + return false; // kendisiyse + } + } + } + return true; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/WizardTreeViewLabelProvider.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/WizardTreeViewLabelProvider.java new file mode 100644 index 00000000..be5bdf83 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/mappingwizard/WizardTreeViewLabelProvider.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.wizards.mappingwizard; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.ide.IDE.SharedImages; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.internal.MarkUtilities; + +public class WizardTreeViewLabelProvider extends LabelProvider { + + @Override + public Image getImage(final Object element) { + if (element instanceof IProject) { + if (((IProject) element).isOpen()) { + return PlatformUI.getWorkbench().getSharedImages().getImage(SharedImages.IMG_OBJ_PROJECT); + } else { + return PlatformUI.getWorkbench().getSharedImages() + .getImage(SharedImages.IMG_OBJ_PROJECT_CLOSED); + } + } else if (element instanceof IFolder) { + return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER); + } else if (element instanceof IFile) { + return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE); + } else if (element instanceof IMarker) { + return PlatformUI.getWorkbench().getSharedImages().getImage(SharedImages.IMG_OPEN_MARKER); + } + + return null; + } + + @Override + public String getText(final Object element) { + + if (element instanceof IResource) { + return ((IResource) element).getName(); + } else if (element instanceof IMarker) { + String str; + if (MarkUtilities.getType((IMarker) element) != null) { + str = MarkUtilities.getText((IMarker) element) + " {" + + AlloyUtilities.getAtomNameById(MarkUtilities.getSourceId((IMarker) element)) + "}"; + return str; + } else { + return MarkUtilities.getText((IMarker) element); + } + } else { + return "Unknown type: " + element.getClass(); + } + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markallinwswizard/MarkAllInWsContentProvider.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markallinwswizard/MarkAllInWsContentProvider.java new file mode 100644 index 00000000..7f7efc22 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markallinwswizard/MarkAllInWsContentProvider.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.wizards.markallinwswizard; + +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +public class MarkAllInWsContentProvider implements ITreeContentProvider { + + @Override + public void dispose() {} + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {} + + @Override + public Object[] getElements(Object inputElement) { + if (inputElement instanceof Object[]) { + return (Object[]) inputElement; + } else { + return new Object[0]; + } + } + + @Override + public Object[] getChildren(Object parentElement) { + if (parentElement instanceof IProject) { + if (((IProject) parentElement).isOpen()) { + try { + return ((IProject) parentElement).members(); + } catch (CoreException e) { + e.printStackTrace(); + } + } + } else if (parentElement instanceof IFolder) { + try { + return ((IFolder) parentElement).members(); + } catch (CoreException e) { + e.printStackTrace(); + } + } + return null; + } + + @Override + public Object getParent(Object element) { + return null; + } + + @Override + public boolean hasChildren(Object element) { + if (element instanceof IProject) { + try { + if (((IProject) element).isOpen()) { + if (((IProject) element).members().length != 0) + return true; + else + return false; + } + } catch (CoreException e) { + e.printStackTrace(); + } + } else if (element instanceof IFolder) { + try { + if (((IFolder) element).members().length != 0) + return true; + else + return false; + } catch (CoreException e) { + e.printStackTrace(); + } + } + return false; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markallinwswizard/MarkAllInWsLabelProvider.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markallinwswizard/MarkAllInWsLabelProvider.java new file mode 100644 index 00000000..28a09f08 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markallinwswizard/MarkAllInWsLabelProvider.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.wizards.markallinwswizard; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.ide.IDE.SharedImages; + +public class MarkAllInWsLabelProvider extends LabelProvider { + + @Override + public String getText(Object element) { + if (element instanceof IResource) { + return ((IResource) element).getName(); + } + return "Unknown type: " + element.getClass(); + } + + @Override + public Image getImage(Object element) { + if (element instanceof IProject) + if (((IProject) element).isOpen()) + return PlatformUI.getWorkbench().getSharedImages().getImage(SharedImages.IMG_OBJ_PROJECT); + else + return PlatformUI.getWorkbench().getSharedImages() + .getImage(SharedImages.IMG_OBJ_PROJECT_CLOSED); + else if (element instanceof IFolder) + return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER); + else if (element instanceof IFile) + return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE); + return null; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markallinwswizard/MarkAllInWsPage.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markallinwswizard/MarkAllInWsPage.java new file mode 100644 index 00000000..7447da0f --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markallinwswizard/MarkAllInWsPage.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.wizards.markallinwswizard; + +import java.util.ArrayList; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.jface.viewers.CheckStateChangedEvent; +import org.eclipse.jface.viewers.CheckboxTreeViewer; +import org.eclipse.jface.viewers.ICheckStateListener; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; + +public class MarkAllInWsPage extends WizardPage { + + public static CheckboxTreeViewer checkboxTreeViewer; + private ArrayList closedProjects; + + public MarkAllInWsPage() { + super("Mark All In Workspace by Selection"); + this.closedProjects = new ArrayList(); + } + + @Override + public void createControl(Composite parent) { + Composite container = new Composite(parent, SWT.NULL); + setControl(container); + container.setLayout(new FillLayout(SWT.HORIZONTAL)); + + checkboxTreeViewer = new CheckboxTreeViewer(container, SWT.BORDER); + + MarkAllInWsContentProvider treeViewerContentProvider = new MarkAllInWsContentProvider(); + + checkboxTreeViewer.setLabelProvider(new MarkAllInWsLabelProvider()); + checkboxTreeViewer.setContentProvider(treeViewerContentProvider); + IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); + for (IProject iProject : projects) { + if (!iProject.isOpen()) { + this.closedProjects.add(iProject); + } + } + checkboxTreeViewer.setInput(ResourcesPlugin.getWorkspace().getRoot().getProjects()); + checkboxTreeViewer.setGrayedElements(this.closedProjects.toArray()); + + checkboxTreeViewer.addCheckStateListener(new ICheckStateListener() { + + @Override + public void checkStateChanged(CheckStateChangedEvent event) { + if (event.getChecked()) { + if (((event.getElement() instanceof IProject) + && !((IProject) event.getElement()).isOpen())) { + return; + } + checkboxTreeViewer.setSubtreeChecked(event.getElement(), true); + } else { + if (((event.getElement() instanceof IProject) + && !((IProject) event.getElement()).isOpen())) { + return; + } + checkboxTreeViewer.setSubtreeChecked(event.getElement(), false); + } + setPageComplete(true); + } + }); + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markallinwswizard/MarkAllInWsWizard.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markallinwswizard/MarkAllInWsWizard.java new file mode 100644 index 00000000..fbc5a832 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markallinwswizard/MarkAllInWsWizard.java @@ -0,0 +1,153 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.wizards.markallinwswizard; + +import java.util.Scanner; +import java.util.UUID; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.dialogs.ProgressMonitorDialog; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.swt.graphics.Image; + +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; +import eu.modelwriter.marker.ui.Activator; + +public class MarkAllInWsWizard extends Wizard { + + private final IFile file; + private MarkAllInWsPage page; + private final ITextSelection textSelection; + + public MarkAllInWsWizard(final ITextSelection textSelection, final IFile file) { + super(); + this.textSelection = textSelection; + this.file = file; + } + + @Override + public void addPages() { + this.page = new MarkAllInWsPage(); + super.addPages(); + this.addPage(this.page); + } + + private void addToAlloyXML(final IMarker mymarker) { + AlloyUtilities.addMarkerToRepository(mymarker); + } + + @Override + public String getWindowTitle() { + return "Mark All In Workspace"; + } + + @Override + public boolean performFinish() { + final Object[] checkedElements = MarkAllInWsPage.checkboxTreeViewer.getCheckedElements(); + final String text = this.textSelection.getText(); + final String leader_id = UUID.randomUUID().toString(); + boolean success = false; + + final Image image = MarkerActivator.getDefault().getImageRegistry() + .get(MarkerActivator.Images.IMAGE_MODELWRITER_ID); + final ProgressMonitorDialog pmd = new ProgressMonitorDialog( + Activator.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell()); + ProgressMonitorDialog.setDefaultImage(image); + pmd.open(); + final IProgressMonitor pmdmoni = pmd.getProgressMonitor(); + try { + pmdmoni.beginTask("Marking", checkedElements.length); + for (int i = 0; i < checkedElements.length && !pmdmoni.isCanceled(); i++) { + try { + if (checkedElements[i] instanceof IFile) { + final IFile iFile = (IFile) checkedElements[i]; + pmdmoni.subTask(iFile.getName()); + pmdmoni.worked(1); + + if (!iFile.getFileExtension().equals("xmi") && !iFile.getFileExtension().equals("ecore") + && !iFile.getFileExtension().equals("reqif")) { + final String charSet = iFile.getCharset(); + final Scanner scanner = new Scanner(iFile.getContents(), charSet); + final IDocument document = new Document(scanner.useDelimiter("\\A").next()); + scanner.close(); + + final String fullText = document.get(); + boolean hasLeader = false; + int index = 0; + int offset = 0; + final int lenght = this.textSelection.getLength(); + final String id = UUID.randomUUID().toString(); + + if (lenght != 0) { + while ((offset = fullText.indexOf(text, index)) != -1) { + final TextSelection nextSelection = new TextSelection(document, offset, lenght); + if (MarkerFactory.findMarkerByOffset(iFile, offset) == null) { + final IMarker mymarker = MarkerFactory.createMarker(iFile, nextSelection); + MarkUtilities.setGroupId(mymarker, id); + if (!iFile.equals(this.file)) { + if (hasLeader == false) { + MarkUtilities.setLeaderId(mymarker, leader_id); + hasLeader = true; + } + } else { + if (this.textSelection.getOffset() == offset) { + MarkUtilities.setLeaderId(mymarker, leader_id); + } + } + + this.addToAlloyXML(mymarker); + AnnotationFactory.addAnnotation(mymarker, AnnotationFactory.ANNOTATION_MARKING); + } + index = offset + lenght; + } + } + success = true; + } else { + final MessageDialog dialog = + new MessageDialog(MarkerActivator.getShell(), "Mark All In Workspace", null, + iFile.getName() + " doesn't supported for this command.", + MessageDialog.INFORMATION, new String[] {"OK"}, 0); + dialog.open(); + MarkAllInWsPage.checkboxTreeViewer.setChecked(iFile, false); + } + } + } catch (final CoreException e) { + e.printStackTrace(); + } + } + } finally { + pmdmoni.done(); + } + pmd.close(); + + if (success == true) { + final MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), + "Mark All In Workspace", null, "Selected project(s) have been marked by selected text", + MessageDialog.INFORMATION, new String[] {"OK"}, 0); + dialog.open(); + return true; + } else { + return false; + } + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markerwizard/MarkerPage.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markerwizard/MarkerPage.java new file mode 100644 index 00000000..6256b7da --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markerwizard/MarkerPage.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.wizards.markerwizard; + +import java.io.IOException; + +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; + +import eu.modelwriter.marker.Serialization; +import eu.modelwriter.marker.ui.Activator; + +public class MarkerPage extends WizardPage { + public static TreeViewer markTreeViewer = null; + public static IDialogSettings settings = Activator.getDefault().getDialogSettings(); + + public static boolean isParsed() { + return MarkerPage.settings.get("alloyFile") != null; + } + + private String savedTree; + private final IDoubleClickListener doubleClickListener; + + public MarkerPage(final IDoubleClickListener doubleClickListener) { + super("Create a Trace Element with Type"); + this.doubleClickListener = doubleClickListener; + } + + @Override + public void createControl(final Composite parent) { + final Composite composite = new Composite(parent, SWT.NONE); + composite.setLayout(new GridLayout(1, false)); + + MarkerPage.markTreeViewer = new TreeViewer(composite); + MarkerPage.markTreeViewer.getTree().setLayoutData(new GridData(GridData.FILL_BOTH)); + + final MarkerTreeViewContentProvider treeViewerContentProvider = + new MarkerTreeViewContentProvider(); + + MarkerPage.markTreeViewer.setLabelProvider(new MarkerTreeViewLabelProvider()); + MarkerPage.markTreeViewer.setContentProvider(treeViewerContentProvider); + MarkerPage.markTreeViewer.addDoubleClickListener(this.doubleClickListener); + + this.savedTree = MarkerPage.settings.get("universe"); + try { + final Object[] array = new Object[1]; + if (this.savedTree != null) { + // hic sig yoksa univ cikmasin + array[0] = Serialization.getInstance().fromString(this.savedTree); + MarkerPage.markTreeViewer.setInput(array); + } + } catch (final ClassNotFoundException e) { + e.printStackTrace(); + } catch (final IOException e) { + e.printStackTrace(); + } + MarkerPage.markTreeViewer.expandAll(); + this.setPageComplete(true); + this.setControl(composite); + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markerwizard/MarkerTreeViewContentProvider.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markerwizard/MarkerTreeViewContentProvider.java new file mode 100644 index 00000000..1d711c8f --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markerwizard/MarkerTreeViewContentProvider.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.wizards.markerwizard; + +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +import eu.modelwriter.marker.internal.MarkerTypeElement; + +public class MarkerTreeViewContentProvider implements ITreeContentProvider { + + @Override + public void dispose() {} + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {} + + @Override + public Object[] getElements(Object inputElement) { + if (inputElement instanceof Object[]) { + return (Object[]) inputElement; + } else { + return new Object[0]; + } + } + + @Override + public Object[] getChildren(Object parentElement) { + if (parentElement instanceof MarkerTypeElement) { + MarkerTypeElement type = (MarkerTypeElement) parentElement; + return type.getChildren().toArray(); + } + return null; + } + + @Override + public Object getParent(Object element) { + return null; + } + + @Override + public boolean hasChildren(Object element) { + if (element instanceof MarkerTypeElement) { + MarkerTypeElement type = (MarkerTypeElement) element; + return !type.getChildren().isEmpty(); + } + return false; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markerwizard/MarkerTreeViewLabelProvider.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markerwizard/MarkerTreeViewLabelProvider.java new file mode 100644 index 00000000..1dada1f5 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markerwizard/MarkerTreeViewLabelProvider.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.wizards.markerwizard; + +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; + +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.internal.MarkerTypeElement; + +public class MarkerTreeViewLabelProvider extends LabelProvider { + + @Override + public Image getImage(Object element) { + ImageRegistry imageRegistry = MarkerActivator.getDefault().getImageRegistry(); + return imageRegistry.get(MarkerActivator.Images.IMAGE_SIG_ID); + + } + + @Override + public String getText(Object element) { + if (element instanceof MarkerTypeElement) { + MarkerTypeElement typeElement = (MarkerTypeElement) element; + return typeElement.getType(); + } + return null; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markerwizard/MarkerWizard.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markerwizard/MarkerWizard.java new file mode 100644 index 00000000..79959ed0 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/markerwizard/MarkerWizard.java @@ -0,0 +1,178 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.wizards.markerwizard; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.wizard.Wizard; + +import eu.modelwriter.configuration.alloy.reasoning.AlloyOtherSolutionReasoning; +import eu.modelwriter.configuration.internal.AlloyUtilities; +import eu.modelwriter.configuration.internal.CreateMarkerWithType; +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.internal.AnnotationFactory; +import eu.modelwriter.marker.internal.MarkUtilities; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class MarkerWizard extends Wizard { + + private MarkerPage page; + private ISelection selection; + private IFile file; + private IMarker selectedMarker; + private ArrayList candidateToTypeChanging; + + public MarkerWizard(final IMarker marker) { + super(); + this.selectedMarker = marker; + } + + public MarkerWizard(final ISelection selection, final IFile file) { + super(); + this.selection = selection; + this.file = file; + } + + @Override + public void addPages() { + this.page = new MarkerPage(this.getDoubleClickListener()); + this.addPage(this.page); + } + + private void findCandidateToTypeChangingMarkers(final IMarker selectedMarker) { + this.candidateToTypeChanging.add(selectedMarker); + + final Map fieldsSources = + AlloyUtilities.getRelationsOfSecondSideMarker(selectedMarker); + final ArrayList relationsSources = + AlloyUtilities.getSourcesOfMarkerAtRelations(selectedMarker); + + for (final IMarker iMarker : fieldsSources.keySet()) { + this.candidateToTypeChanging.add(iMarker); + } + + for (final IMarker iMarker : relationsSources) { + this.candidateToTypeChanging.add(iMarker); + } + } + + private IDoubleClickListener getDoubleClickListener() { + return new IDoubleClickListener() { + @Override + public void doubleClick(final DoubleClickEvent event) { + final IStructuredSelection selection = (IStructuredSelection) event.getSelection(); + final Object firstElement = selection.getFirstElement(); + if (MarkerPage.markTreeViewer.isExpandable(firstElement)) { + final boolean expanded = MarkerPage.markTreeViewer.getExpandedState(firstElement); + MarkerPage.markTreeViewer.setExpandedState(firstElement, !expanded); + } else { + MarkerWizard.this.performFinish(); + MarkerWizard.this.getContainer().getShell().close(); + } + } + }; + } + + @Override + public String getWindowTitle() { + return "Create a Trace Element with Type"; + } + + @Override + public boolean performFinish() { + AlloyOtherSolutionReasoning.getInstance().finish(); + + this.candidateToTypeChanging = new ArrayList(); + if (MarkerPage.markTreeViewer.getTree().getSelection().length == 1) { + if (MarkerPage.markTreeViewer.getTree().getSelection()[0].getText().endsWith("{abs}")) { + final MessageDialog dialog = + new MessageDialog(MarkerActivator.getShell(), "Trace Type Information", null, + "Selected type is not appropriate because it is marked as Abstact", + MessageDialog.INFORMATION, new String[] {"OK"}, 0); + dialog.open(); + return false; + } + + if (!MarkerPage.markTreeViewer.getTree().getItems()[0] + .equals(MarkerPage.markTreeViewer.getTree().getSelection()[0])) { + if (this.selection != null) { + CreateMarkerWithType.createMarker(this.file, this.selection, + MarkerPage.markTreeViewer.getTree().getSelection()[0].getText()); + // MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), + // "Marker Type Information", null, "Marker has been created with selected type", + // MessageDialog.INFORMATION, new String[] {"OK"}, 0); + // dialog.open(); + } else { + this.findCandidateToTypeChangingMarkers(this.selectedMarker); + this.selectedMarker = + AnnotationFactory.convertAnnotationType(this.selectedMarker, true, true, + AlloyUtilities.getTotalTargetCount(this.selectedMarker)); + + IMarker marker = null; + for (int i = 1; i < this.candidateToTypeChanging.size(); i++) { + marker = this.candidateToTypeChanging.get(i); + AnnotationFactory.convertAnnotationType(marker, true, + MarkUtilities.compare(marker, this.selectedMarker), + AlloyUtilities.getTotalTargetCount(marker)); + } + AlloyUtilities.removeAllRelationsOfMarker(this.selectedMarker); + AlloyUtilities.removeRelationOfMarker(this.selectedMarker); + if (MarkUtilities.getGroupId(this.selectedMarker) != null) { + final List list = MarkerFactory.findMarkersByGroupId( + this.selectedMarker.getResource(), MarkUtilities.getGroupId(this.selectedMarker)); + for (final IMarker iMarker : list) { + AlloyUtilities.removeTypeFromMarker(iMarker); + MarkUtilities.setType(iMarker, + MarkerPage.markTreeViewer.getTree().getSelection()[0].getText()); + if (MarkUtilities.getLeaderId(iMarker) != null) { + AlloyUtilities.addTypeToMarker(iMarker); + } + AlloyUtilities.addMarkerToRepository(this.selectedMarker); + } + } else { + AlloyUtilities.removeTypeFromMarker(this.selectedMarker); + MarkUtilities.setType(this.selectedMarker, + MarkerPage.markTreeViewer.getTree().getSelection()[0].getText()); + AlloyUtilities.addTypeToMarker(this.selectedMarker); + AlloyUtilities.addMarkerToRepository(this.selectedMarker); + } + + // MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), + // "Marker Type Information", null, "Selected type added to selected marker", + // MessageDialog.INFORMATION, new String[] {"OK"}, 0); + // dialog.open(); + } + return true; + } else { + final MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), + "Trace Type Information", null, "Please select a valid marker type.", + MessageDialog.INFORMATION, new String[] {"OK"}, 0); + dialog.open(); + return false; + } + } else { + final MessageDialog dialog = + new MessageDialog(MarkerActivator.getShell(), "Trace Type Information", null, + "Please select one trace type.", MessageDialog.INFORMATION, new String[] {"OK"}, 0); + dialog.open(); + return false; + } + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/selectionwizard/Column.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/selectionwizard/Column.java new file mode 100644 index 00000000..b1ba296a --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/selectionwizard/Column.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.wizards.selectionwizard; + +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.TableColumn; + +public abstract class Column extends ColumnLabelProvider { + + public abstract String getText(Object element); + + public abstract String getTitle(); + + public TableViewerColumn addColumnTo(TableViewer viewer) { + TableViewerColumn tableViewerColumn = new TableViewerColumn(viewer, SWT.NONE); + TableColumn column = tableViewerColumn.getColumn(); + column.setText(getTitle()); + tableViewerColumn.setLabelProvider(this); + return tableViewerColumn; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/selectionwizard/MarkerColumn.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/selectionwizard/MarkerColumn.java new file mode 100644 index 00000000..714649d8 --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/selectionwizard/MarkerColumn.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.wizards.selectionwizard; + +import org.eclipse.core.resources.IMarker; + +import eu.modelwriter.marker.internal.MarkUtilities; + +public class MarkerColumn extends Column { + + public MarkerColumn() {} + + @Override + public String getText(Object element) { + if (element instanceof IMarker) { + return MarkUtilities.getText((IMarker) element); + } + return ""; + } + + @Override + public String getTitle() { + return "Marker"; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/selectionwizard/SelectionWizard.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/selectionwizard/SelectionWizard.java new file mode 100644 index 00000000..0da3064f --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/selectionwizard/SelectionWizard.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.wizards.selectionwizard; + +import java.util.ArrayList; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.swt.widgets.TableItem; + +public class SelectionWizard extends Wizard { + ArrayList candidateList; + private IMarker selectedMarker; + + private SelectionWizardPage deletingWizardPage; + + public SelectionWizard() { + this.candidateList = new ArrayList(); + setWindowTitle("Select Marker"); + } + + public SelectionWizard(ArrayList candidateList) { + setWindowTitle("Select Marker"); + this.candidateList = candidateList; + } + + @Override + public void addPages() { + deletingWizardPage = new SelectionWizardPage(candidateList); + super.addPages(); + this.addPage(deletingWizardPage); + } + + @Override + public boolean performFinish() { + TableItem selectedItem = deletingWizardPage.getTable().getSelection()[0]; + this.selectedMarker = (IMarker) selectedItem.getData(); + return true; + } + + public IMarker getSelectedMarker() { + return this.selectedMarker; + } +} diff --git a/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/selectionwizard/SelectionWizardPage.java b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/selectionwizard/SelectionWizardPage.java new file mode 100644 index 00000000..c7b0a05c --- /dev/null +++ b/Source/eu.modelwriter.marker.ui/src/eu/modelwriter/marker/ui/internal/wizards/selectionwizard/SelectionWizardPage.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker.ui.internal.wizards.selectionwizard; + +import java.util.ArrayList; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; + +public class SelectionWizardPage extends WizardPage { + private Table table; + private ArrayList candidateList; + + /** + * Create the wizard. + */ + SelectionWizardPage() { + super("wizardPage"); + } + + /** + * Create the wizard. + * + * @param candidateList + */ + public SelectionWizardPage(ArrayList candidateList) { + super("wizardPage"); + this.candidateList = candidateList; + setTitle("Markers"); + setDescription("All markers in selection"); + } + + /** + * Create contents of the wizard. + * + * @param parent + */ + public void createControl(Composite parent) { + Composite container = new Composite(parent, SWT.NULL); + + setControl(container); + container.setLayout(new GridLayout(1, false)); + + TableViewer tableViewer = new TableViewer(container, SWT.BORDER | SWT.FULL_SELECTION); + table = tableViewer.getTable(); + table.setLinesVisible(true); + table.setHeaderVisible(true); + table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); + + tableViewer.setContentProvider(ArrayContentProvider.getInstance()); + tableViewer.setInput(candidateList); + tableViewer.setLabelProvider(new MarkerColumn()); + // auto size columns + TableColumn[] columns = tableViewer.getTable().getColumns(); + for (int i = 0; i < columns.length; i++) { + columns[i].pack(); + } + } + + public Table getTable() { + return this.table; + } +} diff --git a/Source/eu.modelwriter.marker/.classpath b/Source/eu.modelwriter.marker/.classpath new file mode 100644 index 00000000..eca7bdba --- /dev/null +++ b/Source/eu.modelwriter.marker/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Source/eu.modelwriter.marker/.gitignore b/Source/eu.modelwriter.marker/.gitignore new file mode 100644 index 00000000..ae3c1726 --- /dev/null +++ b/Source/eu.modelwriter.marker/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/Source/eu.modelwriter.marker/.project b/Source/eu.modelwriter.marker/.project new file mode 100644 index 00000000..8f15c9e2 --- /dev/null +++ b/Source/eu.modelwriter.marker/.project @@ -0,0 +1,28 @@ + + + eu.modelwriter.marker + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/Source/eu.modelwriter.marker/.settings/org.eclipse.jdt.core.prefs b/Source/eu.modelwriter.marker/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..0c68a61d --- /dev/null +++ b/Source/eu.modelwriter.marker/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/Source/eu.modelwriter.marker/.settings/org.eclipse.pde.core.prefs b/Source/eu.modelwriter.marker/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 00000000..923c37fb --- /dev/null +++ b/Source/eu.modelwriter.marker/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +resolve.requirebundle=false diff --git a/Source/eu.modelwriter.marker/META-INF/MANIFEST.MF b/Source/eu.modelwriter.marker/META-INF/MANIFEST.MF new file mode 100644 index 00000000..79f29a41 --- /dev/null +++ b/Source/eu.modelwriter.marker/META-INF/MANIFEST.MF @@ -0,0 +1,46 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Marker +Bundle-SymbolicName: eu.modelwriter.marker;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: eu.modelwriter.marker.MarkerActivator +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.emf.ecore.editor, + org.eclipse.jface.text, + org.eclipse.ui.workbench.texteditor, + org.eclipse.ui.editors, + org.eclipse.ui.navigator.resources, + org.eclipse.ui.navigator;bundle-version="3.6.0", + org.eclipse.jdt.ui, + org.eclipse.jdt.core, + org.eclipse.core.resources, + org.eclipse.emf.ecore.xmi +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ActivationPolicy: lazy +Export-Package: eu.modelwriter.marker; + uses:="org.osgi.framework, + org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.jface.resource, + org.eclipse.swt.widgets, + org.eclipse.core.resources, + org.eclipse.ui.plugin", + eu.modelwriter.marker.internal; + uses:="org.eclipse.emf.ecore, + org.eclipse.ui, + eu.modelwriter.traceability.core.persistence, + org.eclipse.ui.texteditor, + org.eclipse.emf.common.util, + org.eclipse.jface.text, + org.eclipse.core.resources, + org.eclipse.rmf.reqif10, + org.eclipse.jface.viewers", + eu.modelwriter.marker.model.decorators;uses:="org.eclipse.jface.viewers", + eu.modelwriter.marker.xml; + uses:="org.xml.sax.ext, + org.xml.sax.helpers, + org.w3c.dom, + javax.xml.stream, + org.xml.sax" +Import-Package: eu.modelwriter.traceability.core.persistence, + eu.modelwriter.traceability.core.persistence.internal diff --git a/Source/eu.modelwriter.marker/build.properties b/Source/eu.modelwriter.marker/build.properties new file mode 100644 index 00000000..fdd79964 --- /dev/null +++ b/Source/eu.modelwriter.marker/build.properties @@ -0,0 +1,24 @@ +############################################################################### +# Copyright (c) 2015 UNIT Information Technologies R&D Ltd +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Ferhat Erata - initial API and implementation +# H. Emre Kirmizi - initial API and implementation +# Serhat Celik - initial API and implementation +# U. Anil Ozturk - initial API and implementation +############################################################################### +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + build.properties,\ + icons/,\ + bin/,\ + .project,\ + .settings/,\ + .classpath diff --git a/Source/eu.modelwriter.marker/icons/Annotation.gif b/Source/eu.modelwriter.marker/icons/Annotation.gif new file mode 100644 index 00000000..018ebb4e Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/Annotation.gif differ diff --git a/Source/eu.modelwriter.marker/icons/Black.gif b/Source/eu.modelwriter.marker/icons/Black.gif new file mode 100644 index 00000000..018ebb4e Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/Black.gif differ diff --git a/Source/eu.modelwriter.marker/icons/Delete.gif b/Source/eu.modelwriter.marker/icons/Delete.gif new file mode 100644 index 00000000..00de7502 Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/Delete.gif differ diff --git a/Source/eu.modelwriter.marker/icons/Link.gif b/Source/eu.modelwriter.marker/icons/Link.gif new file mode 100644 index 00000000..6161758b Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/Link.gif differ diff --git a/Source/eu.modelwriter.marker/icons/Menu.gif b/Source/eu.modelwriter.marker/icons/Menu.gif new file mode 100644 index 00000000..0b4fbc11 Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/Menu.gif differ diff --git a/Source/eu.modelwriter.marker/icons/Red.gif b/Source/eu.modelwriter.marker/icons/Red.gif new file mode 100644 index 00000000..c800d7e8 Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/Red.gif differ diff --git a/Source/eu.modelwriter.marker/icons/alloylogo.gif b/Source/eu.modelwriter.marker/icons/alloylogo.gif new file mode 100644 index 00000000..062b96a7 Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/alloylogo.gif differ diff --git a/Source/eu.modelwriter.marker/icons/evaluator.png b/Source/eu.modelwriter.marker/icons/evaluator.png new file mode 100644 index 00000000..41155be4 Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/evaluator.png differ diff --git a/Source/eu.modelwriter.marker/icons/hierarchy.png b/Source/eu.modelwriter.marker/icons/hierarchy.png new file mode 100644 index 00000000..63877798 Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/hierarchy.png differ diff --git a/Source/eu.modelwriter.marker/icons/modelwriter.gif b/Source/eu.modelwriter.marker/icons/modelwriter.gif new file mode 100644 index 00000000..44c3e0dd Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/modelwriter.gif differ diff --git a/Source/eu.modelwriter.marker/icons/mw_file.gif b/Source/eu.modelwriter.marker/icons/mw_file.gif new file mode 100644 index 00000000..b6e1dd54 Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/mw_file.gif differ diff --git a/Source/eu.modelwriter.marker/icons/next.png b/Source/eu.modelwriter.marker/icons/next.png new file mode 100644 index 00000000..ad328fa8 Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/next.png differ diff --git a/Source/eu.modelwriter.marker/icons/previous.png b/Source/eu.modelwriter.marker/icons/previous.png new file mode 100644 index 00000000..dbde64e5 Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/previous.png differ diff --git a/Source/eu.modelwriter.marker/icons/refresh.gif b/Source/eu.modelwriter.marker/icons/refresh.gif new file mode 100644 index 00000000..e3831471 Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/refresh.gif differ diff --git a/Source/eu.modelwriter.marker/icons/relation.png b/Source/eu.modelwriter.marker/icons/relation.png new file mode 100644 index 00000000..dbddee88 Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/relation.png differ diff --git a/Source/eu.modelwriter.marker/icons/sig.png b/Source/eu.modelwriter.marker/icons/sig.png new file mode 100644 index 00000000..5e343d63 Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/sig.png differ diff --git a/Source/eu.modelwriter.marker/icons/start.png b/Source/eu.modelwriter.marker/icons/start.png new file mode 100644 index 00000000..d205c14a Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/start.png differ diff --git a/Source/eu.modelwriter.marker/icons/stop.png b/Source/eu.modelwriter.marker/icons/stop.png new file mode 100644 index 00000000..bd10d3bb Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/stop.png differ diff --git a/Source/eu.modelwriter.marker/icons/trash.png b/Source/eu.modelwriter.marker/icons/trash.png new file mode 100644 index 00000000..3ad95511 Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/trash.png differ diff --git a/Source/eu.modelwriter.marker/icons/updateSpec.png b/Source/eu.modelwriter.marker/icons/updateSpec.png new file mode 100644 index 00000000..cb3cc30e Binary files /dev/null and b/Source/eu.modelwriter.marker/icons/updateSpec.png differ diff --git a/Source/eu.modelwriter.marker/plugin.xml b/Source/eu.modelwriter.marker/plugin.xml new file mode 100644 index 00000000..df6b4592 --- /dev/null +++ b/Source/eu.modelwriter.marker/plugin.xml @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/Logger.java b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/Logger.java new file mode 100644 index 00000000..dcb9b17b --- /dev/null +++ b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/Logger.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * @author Mete + * + */ +public class Logger { + public static void logInfo(String message) { + log(IStatus.INFO, IStatus.OK, message, null); + } + + public static void logError(Throwable exception) { + logError("MW Marker Unexpected Exception", exception); + } + + public static void logError(String message, Throwable exception) { + log(IStatus.ERROR, IStatus.OK, message, exception); + } + + public static void log(int severity, int code, String message, Throwable exception) { + log(createStatus(severity, code, message, exception)); + } + + /** + * @param severity IStatus.OK, IStatus.WARNING, IStatus.ERROR,IStatus.INFO, or IStatus.CANCEL + * @param code the plug-in-specific status code or IStatus.OK + * @param message a human-readable message, localized to the current locale + * @param exception a low-level exception, or null if not applicable + * @return + */ + public static IStatus createStatus(int severity, int code, String message, Throwable exception) { + return new Status(severity, MarkerActivator.PLUGIN_ID, code, message, exception); + } + + public static void log(IStatus status) { + MarkerActivator.getDefault().getLog().log(status); + } +} diff --git a/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/MarkerActivator.java b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/MarkerActivator.java new file mode 100644 index 00000000..23015193 --- /dev/null +++ b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/MarkerActivator.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker; + +import java.util.Arrays; +import java.util.Iterator; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class MarkerActivator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "eu.modelwriter.markers"; //$NON-NLS-1$ + + // The shared instance + private static MarkerActivator plugin; + + public class Images { + public static final String IMAGE_BLACK_ID = "eu.modelwriter.markers.black.image"; + public static final String IMAGE_RED_ID = "eu.modelwriter.markers.red.image"; + public static final String IMAGE_MENU_ID = "eu.modelwriter.markers.menu.image"; + public static final String IMAGE_LINK_ID = "eu.modelwriter.markers.link.image"; + public static final String IMAGE_DELETE_ID = "eu.modelwriter.markers.delete.image"; + public static final String IMAGE_ANNOTATION_ID = "eu.modelwriter.markers.annotation.image"; + public static final String IMAGE_SIG_ID = "eu.modelwriter.markers.sig.image"; + public static final String IMAGE_RELATION_ID = "eu.modelwriter.markers.relation.image"; + public static final String IMAGE_MODELWRITER_ID = "eu.modelwriter.markers.modelwriter.image"; + } + + /** + * The constructor + */ + public MarkerActivator() {} + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework. BundleContext ) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework. BundleContext ) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static MarkerActivator getDefault() { + return plugin; + } + + /** + * Returns an image descriptor for the image file at the given plug-in relative path + * + * @param path the path + * @return the image descriptor + */ + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(PLUGIN_ID, path); + } + + @Override + protected ImageRegistry createImageRegistry() { + String[] images = new String[] {Images.IMAGE_BLACK_ID, "/icons/Black.gif", Images.IMAGE_RED_ID, + "/icons/Red.gif", Images.IMAGE_MENU_ID, "/icons/Menu.gif", Images.IMAGE_LINK_ID, + "/icons/Link.gif", Images.IMAGE_DELETE_ID, "/icons/Delete.gif", Images.IMAGE_ANNOTATION_ID, + "/icons/Annotation.gif", Images.IMAGE_SIG_ID, "/icons/sig.png", Images.IMAGE_RELATION_ID, + "/icons/relation.png", Images.IMAGE_MODELWRITER_ID, "/icons/modelwriter.gif"}; + ImageRegistry imageRegistry = super.createImageRegistry(); + Iterator i = Arrays.asList(images).iterator(); + while (i.hasNext()) { + String id = i.next(); + String imagePath = i.next(); + imageRegistry.put(id, ImageDescriptor.createFromFile(getClass(), imagePath)); + } + return imageRegistry; + } + + public static Shell getShell() { + return getActiveWorkbenchWindow().getShell(); + } + + public static IWorkbenchWindow getActiveWorkbenchWindow() { + return PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + } + + /** + * Always good to have this static method as when dealing with IResources having a interface to + * get the editor is very handy + * + * @return + */ + public static IEditorPart getEditor() { + return getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + } +} diff --git a/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/MarkerResourceManager.java b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/MarkerResourceManager.java new file mode 100644 index 00000000..6a941705 --- /dev/null +++ b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/MarkerResourceManager.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker; + +public abstract class MarkerResourceManager extends ResourceManager { + + private MarkerResourceManager(int eventMask) { + super(eventMask); + } + +} diff --git a/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/ResourceDeltaPrinter.java b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/ResourceDeltaPrinter.java new file mode 100644 index 00000000..ea0c39c7 --- /dev/null +++ b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/ResourceDeltaPrinter.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IMarkerDelta; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; + +public class ResourceDeltaPrinter implements IResourceDeltaVisitor { + public boolean visit(IResourceDelta delta) { + IResource res = delta.getResource(); + switch (delta.getKind()) { + case IResourceDelta.ADDED: + System.out.print("Resource "); + System.out.print(res.getFullPath()); + System.out.println(" was added."); + break; + case IResourceDelta.REMOVED: + System.out.print("Resource "); + System.out.print(res.getFullPath()); + System.out.println(" was removed."); + break; + case IResourceDelta.CHANGED: + System.out.print("Resource "); + System.out.print(delta.getFullPath()); + System.out.println(" has changed."); + int flags = delta.getFlags(); + if ((flags & IResourceDelta.CONTENT) != 0) { + System.out.println("--> Content Change"); + } + if ((flags & IResourceDelta.REPLACED) != 0) { + System.out.println("--> Content Replaced"); + } + if ((flags & IResourceDelta.MARKERS) != 0) { + System.out.println("--> Marker Change"); + IMarkerDelta[] markers = delta.getMarkerDeltas(); + // if interested in markers, check these deltas + for (IMarkerDelta iMarkerDelta : markers) { + System.out.println(iMarkerDelta.getAttribute(IMarker.CHAR_START)); + switch (iMarkerDelta.getKind()) { + case IResourceDelta.ADDED: + System.out.println("Added"); + break; + case IResourceDelta.REMOVED: + System.out.println("Removed"); + break; + case IResourceDelta.CHANGED: + System.out.println("Changed"); + break; + } + } + } + break; + } + return true; // visit the children + } +} diff --git a/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/ResourceManager.java b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/ResourceManager.java new file mode 100644 index 00000000..9d7c129c --- /dev/null +++ b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/ResourceManager.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker; + +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.ResourcesPlugin; + +// plug-in must be loaded for resource change listener to work +class ResourceManager implements IResourceChangeListener { + private static ResourceManager manager; + + public ResourceManager(int eventMask) { + ResourcesPlugin.getWorkspace().addResourceChangeListener(this, eventMask); + } + + public static void shutdown() { + if (manager != null) { + ResourcesPlugin.getWorkspace().removeResourceChangeListener(manager); + manager = null; + } + } + + public static ResourceManager getManager(int eventMask) { + if (manager == null) + manager = new ResourceManager(eventMask); + return manager; + } + + public void printAllResourceChanges() { + new ResourceDeltaPrinter(); + } + + @Override + public void resourceChanged(IResourceChangeEvent event) { + throw new UnsupportedOperationException(); + } + +} diff --git a/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/Serialization.java b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/Serialization.java new file mode 100644 index 00000000..72db5a39 --- /dev/null +++ b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/Serialization.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Base64; + +public class Serialization { + + private static Serialization instance = null; + + protected Serialization() { + // Exists only to defeat instantiation. + } + + public static Serialization getInstance() { + if (instance == null) { + instance = new Serialization(); + } + return instance; + } + + /** Read the object from Base64 string. */ + @SuppressWarnings({"unchecked"}) + public T fromString(String string) throws IOException, ClassNotFoundException { + byte[] data = Base64.getDecoder().decode(string); + ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data)); + T object = (T) ois.readObject(); + ois.close(); + return object; + } + + /** Write the object to a Base64 string. */ + public String toString(T object) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(object); + oos.close(); + return Base64.getEncoder().encodeToString(baos.toByteArray()); + } +} diff --git a/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/internal/AnnotationFactory.java b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/internal/AnnotationFactory.java new file mode 100644 index 00000000..2d17d111 --- /dev/null +++ b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/internal/AnnotationFactory.java @@ -0,0 +1,252 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.internal; + +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.emf.ecore.presentation.EcoreEditor; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.swt.SWTException; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.part.MultiPageEditorPart; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.MarkerUtilities; +import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel; +import org.eclipse.ui.texteditor.SimpleMarkerAnnotation; + +public class AnnotationFactory { + + public static final String ANNOTATION_MAPPING = "eu.modelwriter.marker.annotation.mapping"; + // Annotation IDs + public static final String ANNOTATION_MARKING = "eu.modelwriter.marker.annotation.marking"; + + // TODO selection + public static void addAnnotation(final IMarker marker, final String annotationType) { + // The DocumentProvider enables to get the document currently loaded in + // the editor + try { + if (marker == null) { + // final MessageDialog dialog = new MessageDialog(new Shell(), + // "There is not exist marker to change annotation. (Marker is null)!", null, + // "Please check .modelwriter/persistence.xml file", MessageDialog.INFORMATION, + // new String[] {"OK"}, 0); + // dialog.open(); + return; + } + + final IEditorPart editor = MarkerFactory.getOpenEditorOfMarker(marker); + + if (editor == null) { + // final MessageDialog dialog = + // new MessageDialog(new Shell(), "There is no editor to refresh. (Editor is null)!", null, + // "Please make sure about source marker's editor is open", MessageDialog.INFORMATION, + // new String[] {"OK"}, 0); + // dialog.open(); + return; + } + + int start; + start = MarkUtilities.getStart(marker); + final int length = MarkUtilities.getLength(marker); + EcoreEditor ecEditor; + MultiPageEditorPart mpepEditor; + ITextEditor iteEditor = null; + if (editor instanceof EcoreEditor) { + final IFileEditorInput input = (IFileEditorInput) editor.getEditorInput(); + final IFile file = input.getFile(); + final ResourceMarkerAnnotationModel rmam = new ResourceMarkerAnnotationModel(file); + final SimpleMarkerAnnotation ma = new SimpleMarkerAnnotation(annotationType, marker); + rmam.addAnnotation(ma, new Position(start, length)); + + ecEditor = (EcoreEditor) editor; + ecEditor.getViewer().refresh(); + } else { + if (editor instanceof ITextEditor) { + iteEditor = (ITextEditor) editor; + } else { + mpepEditor = (MultiPageEditorPart) editor; + final IEditorPart[] editors = mpepEditor.findEditors(mpepEditor.getEditorInput()); + iteEditor = (ITextEditor) editors[0]; + } + final IDocumentProvider idp = iteEditor.getDocumentProvider(); + // This is the document we want to connect to. This is taken from the + // current editor input. + final IDocument document = idp.getDocument(iteEditor.getEditorInput()); + + // The IannotationModel enables to add/remove/change annoatation to a + // Document loaded in an Editor + final IAnnotationModel iamf = idp.getAnnotationModel(iteEditor.getEditorInput()); + + // Note: The annotation type id specify that you want to create one of + // your annotations + final SimpleMarkerAnnotation ma = new SimpleMarkerAnnotation(annotationType, marker); + + // Finally add the new annotation to the model + iamf.connect(document); + iamf.addAnnotation(ma, new Position(start, length)); + iamf.disconnect(document); + // idp.resetDocument(iteEditor.getEditorInput()); + } + } catch (final Exception e) { + e.printStackTrace(); + } + } + + public static void removeAnnotation(final IMarker marker) { + // The DocumentProvider enables to get the document currently loaded in + // the editor + if (marker == null) { + // final MessageDialog dialog = new MessageDialog(new Shell(), + // "There is not exist marker to change annotation. (Marker is null)!", null, + // "Please check .modelwriter/persistence.xml file", MessageDialog.INFORMATION, + // new String[] {"OK"}, 0); + // dialog.open(); + return; + } + + final IEditorPart editor = MarkerFactory.getOpenEditorOfMarker(marker); + + if (editor == null) { + // final MessageDialog dialog = + // new MessageDialog(new Shell(), "There is no editor to refresh. (Editor is null)!", null, + // "Please make sure about source marker's editor is open", MessageDialog.INFORMATION, + // new String[] {"OK"}, 0); + // dialog.open(); + return; + } + + EcoreEditor ecEditor; + MultiPageEditorPart mpepEditor; + ITextEditor iteEditor = null; + + if (editor instanceof EcoreEditor) { + final IFileEditorInput input = (IFileEditorInput) editor.getEditorInput(); + final IFile file = input.getFile(); + final ResourceMarkerAnnotationModel rmam = new ResourceMarkerAnnotationModel(file); + final Iterator iter = rmam.getAnnotationIterator(); + Annotation beRemoved = null; + + while (iter.hasNext()) { + beRemoved = iter.next(); + if (rmam.getPosition(beRemoved).getOffset() == MarkUtilities.getStart(marker) + && rmam.getPosition(beRemoved).getLength() == MarkUtilities.getLength(marker)) { + rmam.removeAnnotation(beRemoved); + } + } + ecEditor = (EcoreEditor) editor; + try { + ecEditor.getViewer().refresh(); + } catch (final SWTException e) { + e.printStackTrace(); + } + } else { + if (editor instanceof ITextEditor) { + iteEditor = (ITextEditor) editor; + } else { + mpepEditor = (MultiPageEditorPart) editor; + final IEditorPart[] editors = mpepEditor.findEditors(mpepEditor.getEditorInput()); + iteEditor = (ITextEditor) editors[0]; + } + final IDocumentProvider idp = iteEditor.getDocumentProvider(); + + // This is the document we want to connect to. This is taken from the + // current editor input. + final IDocument document = idp.getDocument(iteEditor.getEditorInput()); + + // The IannotationModel enables to add/remove/change annoatation to a + // Document loaded in an Editor + final IAnnotationModel iamf = idp.getAnnotationModel(iteEditor.getEditorInput()); + + // Note: The annotation type id specify that you want to create one of + // your annotations + final Iterator iter = iamf.getAnnotationIterator(); + Annotation beRemoved = null; + + while (iter.hasNext()) { + beRemoved = iter.next(); + if (iamf.getPosition(beRemoved).getOffset() == MarkUtilities.getStart(marker) + && iamf.getPosition(beRemoved).getLength() == MarkUtilities.getLength(marker)) { + iamf.connect(document); + iamf.removeAnnotation(beRemoved); + iamf.disconnect(document); + } + } + } + // Finally add the new annotation to the model + } + + /** + * These type is referred to {@link MarkerFactory.ANNOTATION_MARKING} and + * {@link MarkerFactory.ANNOTATION_MAPPING} + * + * Note : if you send selected marker with candidateMarkersToTypeChanging array, you must get + * selected marker from this method primarily. + * + * @param marker this parameter has miscellaneous meanings. + * @param beforeDelete this parameter is used for distinguish between add/remove type action and + * others. + */ + public static IMarker convertAnnotationType(final IMarker marker, final boolean beforeDelete, + final boolean isSelectedMarker, final int targetCount) { + IMarker newMarker = marker; + try { + final IMarker leaderMarker = MarkUtilities.getLeaderOfMarker(marker); + if (leaderMarker == null) { + return null; + } + int tc = -1; + + if (isSelectedMarker) { + tc = 0; + } else { + if (beforeDelete) { + tc = targetCount - 1; + } else { + tc = targetCount; + } + } + + final IResource res = leaderMarker.getResource(); + if (tc > 0 && leaderMarker.exists() + && leaderMarker.getType().equals(MarkerFactory.MARKER_MARKING)) { + final Map attributes = leaderMarker.getAttributes(); + AnnotationFactory.removeAnnotation(leaderMarker); + leaderMarker.delete(); + MarkerUtilities.createMarker(res, attributes, MarkerFactory.MARKER_MAPPING); + newMarker = + MarkerFactory.findMarkerBySourceId(res, (String) attributes.get(IMarker.SOURCE_ID)); + AnnotationFactory.addAnnotation(newMarker, AnnotationFactory.ANNOTATION_MAPPING); + } else if (tc == 0 && leaderMarker.exists() + && leaderMarker.getType().equals(MarkerFactory.MARKER_MAPPING)) { + final Map attributes = leaderMarker.getAttributes(); + AnnotationFactory.removeAnnotation(leaderMarker); + leaderMarker.delete(); + MarkerUtilities.createMarker(res, attributes, MarkerFactory.MARKER_MARKING); + newMarker = + MarkerFactory.findMarkerBySourceId(res, (String) attributes.get(IMarker.SOURCE_ID)); + AnnotationFactory.addAnnotation(newMarker, AnnotationFactory.ANNOTATION_MARKING); + } + } catch (final CoreException e) { + e.printStackTrace(); + } + return newMarker; + } +} diff --git a/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/internal/MarkElement.java b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/internal/MarkElement.java new file mode 100644 index 00000000..0b086bd0 --- /dev/null +++ b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/internal/MarkElement.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +/** + * + */ +package eu.modelwriter.marker.internal; + +import org.eclipse.core.resources.IMarker; + +/** + * @author Ferhat Erata + * + */ +public class MarkElement implements java.io.Serializable { + + private static final long serialVersionUID = 1L; + private String sourceId; + private String path; + + /** + * this constructs mark element for given IMarker + * + * @param iMarker + */ + public MarkElement(IMarker iMarker) { + this.sourceId = MarkUtilities.getSourceId(iMarker); + this.path = MarkUtilities.getPath(iMarker); + } + + /** + * + * @return markElement as {@link IMarker} + */ + public IMarker getiMarker() { + return MarkUtilities.getiMarker(sourceId, path); + } +} + diff --git a/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/internal/MarkUtilities.java b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/internal/MarkUtilities.java new file mode 100644 index 00000000..2c3a8e8b --- /dev/null +++ b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/internal/MarkUtilities.java @@ -0,0 +1,397 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.internal; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Path; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.ide.IDE; + +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.Serialization; + +public final class MarkUtilities { + private static transient String TARGET_ATTRIBUTE_NAME = "TARGET_MARKED_ELEMENT"; + private static transient String SOURCE_ATTRIBUTE_NAME = "SOURCE_MARKED_ELEMENT"; + + public static final String GROUP_ID = "GROUP_ID"; + public static final String LEADER_ID = "LEADER_ID"; + public static final String MARKER_TYPE = "MARKER_TYPE"; + public static final String URI = "uri"; + public static final String RELATIVE_URI = "REL_URI"; + + /** + * Compares two marker with their sourceIds + * + * @param iMarker1 + * @param iMarker2 + * @return true if equals, false otherwise + */ + public static boolean compare(final IMarker iMarker1, final IMarker iMarker2) { + if (MarkUtilities.getSourceId(iMarker1).equals(MarkUtilities.getSourceId(iMarker2))) { + return true; + } + return false; + } + + public static boolean compare(final String sourceId1, final String sourceId2) { + if (sourceId1.equals(sourceId2)) { + return true; + } + return false; + } + + public static void focusMarker(final IMarker marker) { + Display.getDefault().syncExec(new Runnable() { + + @Override + public void run() { + try { + IDE.openEditor( + MarkerActivator.getDefault().getWorkbench().getWorkbenchWindows()[0].getActivePage(), + marker); + } catch (final PartInitException e1) { + + e1.printStackTrace(); + } + } + }); + } + + public static int getEnd(final IMarker iMarker) { + try { + return (int) iMarker.getAttribute(IMarker.CHAR_END); + } catch (final CoreException e) { + e.printStackTrace(); + } + return -1; + } + + public static String getGroupId(final IMarker iMarker) { + try { + return (String) iMarker.getAttribute(MarkUtilities.GROUP_ID); + } catch (final CoreException e) { + e.printStackTrace(); + } + return null; + } + + /** + * + * @param sourceId + * @param path + * @return IMarker + */ + public static IMarker getiMarker(final String sourceId, final String path) { + final IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path)); + return MarkerFactory.findMarkerBySourceId(file, sourceId); + } + + public static String getLeaderId(final IMarker iMarker) { + try { + return (String) iMarker.getAttribute(MarkUtilities.LEADER_ID); + } catch (final CoreException e) { + e.printStackTrace(); + } + return null; + } + + /** + * @param marker + * @return If marker has not group, returns the marker.
+ * If marker has a group and it is a leader, returns the marker,
+ * Otherwise find and returns it's leader + */ + public static IMarker getLeaderOfMarker(final IMarker marker) { + if (MarkUtilities.getGroupId(marker) == null) { + return marker; + } + + if (MarkUtilities.getLeaderId(marker) != null) { + return marker; + } + + if (MarkUtilities.getGroupId(marker) != null) { + final Iterator groupMarkers = MarkerFactory + .findMarkersByGroupId(marker.getResource(), MarkUtilities.getGroupId(marker)).iterator(); + while (groupMarkers.hasNext()) { + final IMarker iMarker = groupMarkers.next(); + if (MarkUtilities.getLeaderId(iMarker) != null) { + return iMarker; + } + } + } + + return marker; + } + + public static int getLength(final IMarker iMarker) { + try { + return (int) iMarker.getAttribute(IMarker.CHAR_END) - MarkUtilities.getStart(iMarker); + } catch (final CoreException e) { + e.printStackTrace(); + } + return -1; + } + + public static int getLinenumber(final IMarker iMarker) { + try { + return (int) iMarker.getAttribute(IMarker.LOCATION); + } catch (final CoreException e) { + e.printStackTrace(); + } + return -1; + } + + public static String getMessage(final IMarker iMarker) { + try { + return (String) iMarker.getAttribute(IMarker.MESSAGE); + } catch (final CoreException e) { + e.printStackTrace(); + } + return null; + } + + public static String getPath(final IMarker iMarker) { + return iMarker.getResource().getFullPath().toString(); + } + + public static String getSourceAttributeName() { + return MarkUtilities.SOURCE_ATTRIBUTE_NAME; + } + + public static String getSourceId(final IMarker iMarker) { + try { + return (String) iMarker.getAttribute(IMarker.SOURCE_ID); + } catch (final CoreException e) { + e.printStackTrace(); + } + return null; + } + + /** + * @param iMarker + * @return If marker has not any source returns new ArrayList, else returns list of sourceF + * elements + */ + public static ArrayList getSourceList(final IMarker iMarker) { + ArrayList sourceList = new ArrayList<>(); + try { + if (iMarker.getAttribute(MarkUtilities.getSourceAttributeName()) != null) { + sourceList = Serialization.getInstance() + .fromString((String) iMarker.getAttribute(MarkUtilities.getSourceAttributeName())); + } + } catch (ClassNotFoundException | IOException | CoreException e) { + e.printStackTrace(); + } + return sourceList; + } + + public static int getStart(final IMarker iMarker) { + try { + return (int) iMarker.getAttribute(IMarker.CHAR_START); + } catch (final CoreException e) { + e.printStackTrace(); + } + return -1; + } + + public static String getTargetAttributeName() { + return MarkUtilities.TARGET_ATTRIBUTE_NAME; + } + + /** + * @param iMarker + * @return If marker has not any target returns new ArrayList, else returns list of target + * elements + */ + public static ArrayList getTargetList(final IMarker iMarker) { + ArrayList targetList = new ArrayList<>(); + try { + if (iMarker.getAttribute(MarkUtilities.getTargetAttributeName()) != null) { + targetList = Serialization.getInstance() + .fromString((String) iMarker.getAttribute(MarkUtilities.getTargetAttributeName())); + } + } catch (ClassNotFoundException | IOException | CoreException e) { + e.printStackTrace(); + } + return targetList; + } + + public static String getText(final IMarker iMarker) { + try { + return (String) iMarker.getAttribute(IMarker.TEXT); + } catch (final CoreException e) { + e.printStackTrace(); + } + return null; + } + + public static String getType(final IMarker iMarker) { + try { + return (String) iMarker.getAttribute(MarkUtilities.MARKER_TYPE); + } catch (final CoreException e) { + e.printStackTrace(); + } + return null; + } + + public static String getUri(final IMarker iMarker) { + try { + if (iMarker.getAttribute(URI) != null) { + return iMarker.getAttribute(URI).toString(); + } + } catch (final CoreException e) { + e.printStackTrace(); + } + return null; + } + + public static String getXpath(final IMarker iMarker) { + try { + return (String) iMarker.getAttribute("xpath"); + } catch (final CoreException e) { + e.printStackTrace(); + } + return null; + } + + public static void setEnd(final IMarker iMarker, final int end) { + try { + iMarker.setAttribute(IMarker.CHAR_END, end); + } catch (final CoreException e) { + e.printStackTrace(); + } + } + + public static void setGroupId(final IMarker iMarker, final String groupId) { + try { + iMarker.setAttribute(MarkUtilities.GROUP_ID, groupId); + } catch (final CoreException e) { + e.printStackTrace(); + } + } + + public static void setLeaderId(final IMarker iMarker, final String leaderId) { + try { + iMarker.setAttribute(MarkUtilities.LEADER_ID, leaderId); + } catch (final CoreException e) { + e.printStackTrace(); + } + } + + public static void setLinenumber(final IMarker iMarker, final int linenumber) { + try { + iMarker.setAttribute(IMarker.LOCATION, linenumber); + } catch (final CoreException e) { + e.printStackTrace(); + } + } + + private static void setMessage(final IMarker iMarker, final String type) { + try { + iMarker.setAttribute(IMarker.MESSAGE, + type == null ? "Marker Type : non-type" : "Marker Type : " + type); + } catch (final CoreException e) { + e.printStackTrace(); + } + } + + public static void setSourceId(final IMarker imarker, final String id) { + try { + imarker.setAttribute(IMarker.SOURCE_ID, id); + } catch (final CoreException e) { + e.printStackTrace(); + } + } + + /** + * Sets the MarkElement.getSourceAttributeName() named attribute of marker with given parameter + * sourceList + * + * @param iMarker + * @param sourceList + */ + public static void setSourceList(final IMarker iMarker, final ArrayList sourceList) { + try { + iMarker.setAttribute(MarkUtilities.getSourceAttributeName(), + Serialization.getInstance().toString(sourceList)); + } catch (CoreException | IOException e) { + e.printStackTrace(); + } + } + + public static void setStart(final IMarker iMarker, final int start) { + try { + iMarker.setAttribute(IMarker.CHAR_START, start); + } catch (final CoreException e) { + e.printStackTrace(); + } + } + + /** + * Sets the MarkElement.getTargetAttributeName() named attribute of marker with given parameter + * targetList + * + * @param iMarker + * @param sourceList + */ + public static void setTargetList(final IMarker iMarker, final ArrayList targetList) { + try { + iMarker.setAttribute(MarkUtilities.getTargetAttributeName(), + Serialization.getInstance().toString(targetList)); + } catch (CoreException | IOException e) { + e.printStackTrace(); + } + } + + public static void setText(final IMarker iMarker, final String text) { + try { + iMarker.setAttribute(IMarker.TEXT, text); + } catch (final CoreException e) { + e.printStackTrace(); + } + } + + public static void setType(final IMarker iMarker, final String type) { + try { + iMarker.setAttribute(MarkUtilities.MARKER_TYPE, type); + MarkUtilities.setMessage(iMarker, type); + } catch (final CoreException e) { + e.printStackTrace(); + } + } + + public static void setUri(final IMarker iMarker, final String uri) { + try { + iMarker.setAttribute(URI, uri); + } catch (final CoreException e) { + e.printStackTrace(); + } + } + + public static String setXpath(final IMarker iMarker, final String xPath) { + try { + iMarker.setAttribute("xpath", xPath); + } catch (final CoreException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/internal/MarkerFactory.java b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/internal/MarkerFactory.java new file mode 100644 index 00000000..6b99d086 --- /dev/null +++ b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/internal/MarkerFactory.java @@ -0,0 +1,1443 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.internal; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Scanner; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.presentation.EcoreEditor; +import org.eclipse.emf.ecore.resource.impl.ResourceFactoryImpl; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl; +import org.eclipse.jdt.core.IField; +import org.eclipse.jdt.core.IInitializer; +import org.eclipse.jdt.core.IMethod; +import org.eclipse.jdt.core.ISourceRange; +import org.eclipse.jdt.core.IType; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.viewers.IElementComparer; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ITreeSelection; +import org.eclipse.jface.viewers.TreePath; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IEditorReference; +import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.navigator.resources.ProjectExplorer; +import org.eclipse.ui.part.MultiPageEditorPart; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.MarkerUtilities; + +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.xml.EventMemento; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; + +@SuppressWarnings("restriction") +public class MarkerFactory { + + public static final String TARGETVIEW_REF = "eu.modelwriter.marker.command.targetviewrefresh"; + public static final String SOURCEVIEW_REF = "eu.modelwriter.marker.command.sourceviewrefresh"; + public static final String MASTERVIEW_REF = "eu.modelwriter.marker.command.masterviewrefresh"; + + public static final String ECORE_DECORATOR = + "eu.modelwriter.model.decorators.decorator.ecore.red"; + public static final String FILE_DECORATOR = "eu.modelwriter.writer.markers.filedecorator"; + + // Marker ID + public static final String MARKER_MARKING = "eu.modelwriter.marker.marking"; + public static final String MARKER_MAPPING = "eu.modelwriter.marker.mapping"; + + /** + * Creates a Ecore Marker from tree selection + * + * @param selection + * @param file + * @param res + * @param editor + * @return + */ + private static IMarker createEcoreMarker(final ITreeSelection selection, final IFile file, + final IResource res, final IEditorPart editor) { + + IMarker marker = null; + + final ENamedElement element = (ENamedElement) selection.getFirstElement(); + final String selectedText = element.getName(); + + final URI uri = EcoreUtil.getURI(element); + System.out.println(uri); + + final String[] uriSplits = uri.toString().split("/"); + final List uriSplitsList = Arrays.asList(uriSplits); + int indexOfStream = uriSplitsList.indexOf("") + 1; + + final XMLInputFactory factory = XMLInputFactory.newInstance(); + try { + final XMLStreamReader streamReader = + factory.createXMLStreamReader(new FileReader(res.getLocation().toFile())); + + EventMemento memento = null; + EventMemento current = null; + @SuppressWarnings("unused") + String elementName = null; + while (streamReader.hasNext()) { + + if (streamReader.getEventType() == XMLStreamConstants.START_ELEMENT) { + final String name = streamReader.getAttributeValue(null, "name"); + if (name != null && name.equals(uriSplitsList.get(indexOfStream))) { + indexOfStream++; + + if (uriSplitsList.size() == indexOfStream) { + elementName = streamReader.getName().toString(); + break; + } + } + } + memento = new EventMemento(streamReader); + streamReader.next(); + current = new EventMemento(streamReader); + } + + // JFace Text Document object is created to get character offsets from line numbers. + + final int[] offsetStartEnd = + MarkerFactory.getStartEndOffsetFromXML(streamReader, file, memento, current); + final int start = offsetStartEnd[0]; + final int end = offsetStartEnd[1]; + + // Create Marker + final HashMap map = new HashMap<>(); + MarkerUtilities.setLineNumber(map, current.getLineNumber()); + MarkerUtilities.setMessage(map, "Marker Type : non-type"); + MarkerUtilities.setCharStart(map, start); + MarkerUtilities.setCharEnd(map, end); + map.put(IMarker.TEXT, selectedText); + map.put(IMarker.LOCATION, current.getLineNumber()); + map.put(IMarker.SOURCE_ID, MarkerFactory.generateId()); + map.put(MarkUtilities.URI, uri.toString()); + map.put(MarkUtilities.RELATIVE_URI, + EcoreUtil.getRelativeURIFragmentPath(EcoreUtil.getRootContainer(element), element)); + marker = file.createMarker(MarkerFactory.MARKER_MARKING); + if (marker.exists()) { + try { + marker.setAttributes(map); + } catch (final CoreException e) { + // You need to handle the case where the marker no longer exists + e.printStackTrace(); + } + } + + AnnotationFactory.addAnnotation(marker, AnnotationFactory.ANNOTATION_MARKING); + + } catch (final XMLStreamException e) { + e.printStackTrace(); + } catch (final FileNotFoundException e) { + e.printStackTrace(); + } catch (final CoreException e1) { + e1.printStackTrace(); + } + return marker; + } + + /** + * Gets eobject and its xmi file, and returns created marker + * + * @param eObject which marker will be created for + * @param iFile xmi file + * @param type marker type + * @return + */ + public static IMarker createInstanceMarker(final EObject eObject, final IFile iFile, + final String type) { + IMarker marker = null; + + if (!(eObject instanceof EModelElement)) { + final URI uri = EcoreUtil.getURI(eObject); + final String[] fragments = uri.fragment().split("/"); + + final ArrayList pieces = new ArrayList<>(); + try { + for (int i = 0; i < fragments.length; i++) { + if (fragments[i].isEmpty()) { + continue; + } + + final int dot = fragments[i].lastIndexOf("."); + if (dot == -1) { + pieces.add(fragments[i].substring(1, fragments[i].length())); + pieces.add("0"); + } else { + pieces.add(fragments[i].substring(1, dot)); + pieces.add(fragments[i].substring(dot + 1, fragments[i].length())); + } + } + } catch (final Exception e) { + // e.printStackTrace(); + } + + File file = null; + final IPath location = iFile.getLocation(); + if (location != null) { + file = location.toFile(); + } + + try { + final XMLInputFactory factory = XMLInputFactory.newInstance(); + + final XMLStreamReader streamReader = factory.createXMLStreamReader(new FileReader(file)); + + EventMemento memento = null; + EventMemento current = null; + int count = 0; + int elementCount = 0; + String name = null; + String startElementName = null; + int startElementCount = 0; + + while (streamReader.hasNext()) { + + if (streamReader.getEventType() == XMLStreamConstants.START_ELEMENT) { + if (pieces.isEmpty()) { + break; + } + + name = streamReader.getLocalName().toString(); + + startElementName = (String) pieces.get(count); + boolean same = true; + if (startElementName.contains("[")) { + for (int j = 0; j < streamReader.getAttributeCount(); j++) { + final String attributeName = streamReader.getAttributeName(j).getLocalPart(); + final String attributeValue = streamReader.getAttributeValue(j); + final String attributeString = attributeName + "=\'" + attributeValue + "\'"; + if (!attributeName.equals("type") && !startElementName.contains(attributeString)) { + same = false; + } + } + startElementName = startElementName.substring(0, startElementName.indexOf('[')); + } + startElementCount = Integer.parseInt((String) pieces.get(count + 1)); + + if (name.equals(startElementName) && same) { + if (elementCount == startElementCount && pieces.size() - 2 == count) { + break; + } + + if (elementCount != startElementCount) { + elementCount++; + } else if (pieces.size() - 2 != count) { + count += 2; + elementCount = 0; + } + } + } + memento = new EventMemento(streamReader); + streamReader.next(); + current = new EventMemento(streamReader); + } + + // JFace Text Document object is created to get character offsets from line numbers. + final int[] offsetStartEnd = + MarkerFactory.getStartEndOffsetFromXML(streamReader, iFile, memento, current); + final int start = offsetStartEnd[0]; + final int end = offsetStartEnd[1]; + + if (MarkerFactory.findMarkerWithAbsolutePosition(iFile, start, end) != null) { + // final MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), + // "Mark Information", null, "In these area, there is already a marker", + // MessageDialog.WARNING, new String[] {"OK"}, 0); + // dialog.open(); + + return null; + } + + final String text = MarkerFactory.instanceToString(eObject); + + final HashMap map = new HashMap<>(); + MarkerUtilities.setLineNumber(map, current.getLineNumber()); + MarkerUtilities.setMessage(map, "Marker Type : " + type); + MarkerUtilities.setCharStart(map, start); + MarkerUtilities.setCharEnd(map, end); + map.put(IMarker.TEXT, text); + map.put(IMarker.LOCATION, current.getLineNumber()); + map.put(IMarker.SOURCE_ID, MarkerFactory.generateId()); + map.put(MarkUtilities.MARKER_TYPE, type); + map.put(MarkUtilities.URI, uri.toString()); + map.put(MarkUtilities.RELATIVE_URI, + EcoreUtil.getRelativeURIFragmentPath(EcoreUtil.getRootContainer(eObject), eObject)); + marker = iFile.createMarker(MarkerFactory.MARKER_MARKING); + if (marker.exists()) { + try { + marker.setAttributes(map); + } catch (final CoreException e) { + // You need to handle the case where the marker no longer exists + e.printStackTrace(); + } + } + + AnnotationFactory.addAnnotation(marker, AnnotationFactory.ANNOTATION_MARKING); + + } catch (final XMLStreamException e) { + e.printStackTrace(); + } catch (final FileNotFoundException e) { + e.printStackTrace(); + } catch (final CoreException e1) { + e1.printStackTrace(); + } + } + return marker; + } + + /** + * Creates an Instance Marker from tree selection + * + * @param selection + * @param file + * @param res + * @param editor + * @return + */ + private static IMarker createInstanceMarker(final ITreeSelection selection, final IFile file, + final IResource res, final IEditorPart editor) { + + IMarker marker = null; + + final EObject element = (EObject) selection.getFirstElement(); + + if (!(element instanceof EModelElement)) { + final URI uri = EcoreUtil.getURI(element); + + final String[] uriSplits = uri.toString().split("/"); + final List uriSplitsList = Arrays.asList(uriSplits); + final int indexOfStream = uriSplitsList.indexOf("") + 1; + final ArrayList pieces = new ArrayList<>(); + try { + for (int i = indexOfStream; i < uriSplits.length; i++) { + int dot = 0; + dot = uriSplits[i].lastIndexOf("."); + pieces.add(uriSplits[i].substring(1, dot)); + pieces.add(uriSplits[i].substring(dot + 1, uriSplits[i].length())); + } + } catch (final Exception e) { + // e.printStackTrace(); + } + + try { + final XMLInputFactory factory = XMLInputFactory.newInstance(); + + final XMLStreamReader streamReader = + factory.createXMLStreamReader(new FileReader(res.getLocation().toFile())); + + EventMemento memento = null; + EventMemento current = null; + int count = 0; + int elementCount = 0; + String name = null; + String startElementName = null; + int startElementCount = 0; + + while (streamReader.hasNext()) { + + if (streamReader.getEventType() == XMLStreamConstants.START_ELEMENT) { + + if (pieces.isEmpty()) { + break; + } + + name = streamReader.getLocalName().toString(); + + startElementName = (String) pieces.get(count); + startElementCount = Integer.parseInt((String) pieces.get(count + 1)); + + if (name.equals(startElementName)) { + if (elementCount == startElementCount && pieces.size() - 2 == count) { + break; + } + + if (elementCount != startElementCount) { + elementCount++; + } else if (pieces.size() - 2 != count) { + count += 2; + elementCount = 0; + } + } + } + memento = new EventMemento(streamReader); + streamReader.next(); + current = new EventMemento(streamReader); + } + + // JFace Text Document object is created to get character offsets from line numbers. + final int[] offsetStartEnd = + MarkerFactory.getStartEndOffsetFromXML(streamReader, file, memento, current); + final int start = offsetStartEnd[0]; + final int end = offsetStartEnd[1]; + + if (MarkerFactory.findMarkerWithAbsolutePosition(file, start, end) != null) { + // final MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), + // "Mark Information", null, "In these area, there is already a marker", + // MessageDialog.WARNING, new String[] {"OK"}, 0); + // dialog.open(); + + return null; + } + + final String text = MarkerFactory.instanceToString(element); + + final HashMap map = new HashMap<>(); + MarkerUtilities.setLineNumber(map, current.getLineNumber()); + MarkerUtilities.setMessage(map, "Marker Type : non-type"); + MarkerUtilities.setCharStart(map, start); + MarkerUtilities.setCharEnd(map, end); + map.put(IMarker.TEXT, text); + map.put(IMarker.LOCATION, current.getLineNumber()); + map.put(IMarker.SOURCE_ID, MarkerFactory.generateId()); + map.put(MarkUtilities.URI, uri.toString()); + map.put(MarkUtilities.RELATIVE_URI, + EcoreUtil.getRelativeURIFragmentPath(EcoreUtil.getRootContainer(element), element)); + marker = file.createMarker(MarkerFactory.MARKER_MARKING); + if (marker.exists()) { + try { + marker.setAttributes(map); + } catch (final CoreException e) { + // You need to handle the case where the marker no longer exists + e.printStackTrace(); + } + } + + AnnotationFactory.addAnnotation(marker, AnnotationFactory.ANNOTATION_MARKING); + + } catch (final XMLStreamException e) { + e.printStackTrace(); + } catch (final FileNotFoundException e) { + e.printStackTrace(); + } catch (final CoreException e1) { + e1.printStackTrace(); + } + } + return marker; + } + + /** + * Creates a Marker from TextSelection + */ + public static IMarker createMarker(final IResource resource, final ITextSelection selection) { + try { + IMarker createdMarker = null; + + if (selection != null && !selection.getText().isEmpty()) { + + if (MarkerFactory.findMarkerWithAbsolutePosition(resource, selection.getOffset(), + selection.getOffset() + selection.getLength()) != null) { + + final MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), + "Mark Information", null, "In these area, there is already a marker", + MessageDialog.WARNING, new String[] {"OK"}, 0); + dialog.open(); + + return null; + } + + final int start = selection.getOffset(); + final int end = selection.getOffset() + selection.getLength(); + + final HashMap map = new HashMap<>(); + + MarkerUtilities.setLineNumber(map, selection.getStartLine()); + MarkerUtilities.setMessage(map, "Marker Type : non-type"); + MarkerUtilities.setCharStart(map, start); + MarkerUtilities.setCharEnd(map, end); + map.put(IMarker.TEXT, selection.getText()); + map.put(IMarker.LOCATION, selection.getStartLine()); + map.put(IMarker.SOURCE_ID, MarkerFactory.generateId()); + map.put(MarkUtilities.MARKER_TYPE, null); + MarkerUtilities.createMarker(resource, map, MarkerFactory.MARKER_MARKING); + + createdMarker = MarkerFactory.findMarkerWithAbsolutePosition(resource, start, end); + + } else { + final MessageDialog dialog = + new MessageDialog(MarkerActivator.getShell(), "Mark Information", null, + "Please perform a valid selection", MessageDialog.WARNING, new String[] {"OK"}, 0); + dialog.open(); + } + return createdMarker; + } catch (final CoreException e) { + e.printStackTrace(); + } + return null; + } + + /** + * Creates a Marker from TreeSelection + */ + @SuppressWarnings({"resource"}) + public static IMarker createMarker(final IResource res, final ITreeSelection selection) { + if (selection == null) { + final MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), "Mark Information", + null, "Please perform a valid selection", MessageDialog.WARNING, new String[] {"OK"}, 0); + dialog.open(); + return null; + } else if (MarkerFactory.findMarkerByTreeSelection(selection, res) != null) { + final MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), "Mark Information", + null, "In these area, there is already a marker", MessageDialog.WARNING, + new String[] {"OK"}, 0); + dialog.open(); + return null; + } + + // Fetch IResource + final IWorkbench workbench = PlatformUI.getWorkbench(); + final IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); + final IWorkbenchPage page = window.getActivePage(); + final IEditorPart editor = page.getActiveEditor(); + final IFileEditorInput input = (IFileEditorInput) editor.getEditorInput(); + final IFile file = input.getFile(); + + IMarker marker = null; + if (MarkerActivator.getEditor() instanceof EcoreEditor + && selection.getFirstElement() instanceof ENamedElement + && ((ENamedElement) selection.getFirstElement()).getName() != null + && !((ENamedElement) selection.getFirstElement()).getName().isEmpty()) { + + marker = MarkerFactory.createEcoreMarker(selection, file, res, editor); + + } else if (editor instanceof EcoreEditor && selection.getFirstElement() != null) { + marker = MarkerFactory.createInstanceMarker(selection, file, res, editor); + } else if (editor instanceof CompilationUnitEditor) { + final Object element = selection.getFirstElement(); + + String content = null; + try { + content = new Scanner(file.getContents()).useDelimiter("\\Z").next(); + } catch (final CoreException e1) { + e1.printStackTrace(); + } + int startOffset = 0; + int length = 0; + + if (element instanceof IField) { + final IField field = (IField) element; + try { + final ISourceRange nameRange = field.getNameRange(); + final int nameStartOffset = nameRange.getOffset(); + final int nameEndOffset = nameStartOffset + nameRange.getLength(); + + final ISourceRange sourceRange = field.getSourceRange(); + startOffset = + field.getJavadocRange().getOffset() + field.getJavadocRange().getLength() + 1; + if (nameEndOffset + 1 == sourceRange.getOffset() + sourceRange.getLength()) { + length = sourceRange.getOffset() + sourceRange.getLength() - startOffset; + } else { + final int indexOfAssignment = content.indexOf("=", nameEndOffset); + length = indexOfAssignment - startOffset; + } + + } catch (final JavaModelException e) { + e.printStackTrace(); + } + } else if (element instanceof IInitializer) { + final IInitializer initializer = (IInitializer) element; + try { + final ISourceRange sourceRange = initializer.getSourceRange(); + startOffset = initializer.getJavadocRange().getOffset() + + initializer.getJavadocRange().getLength() + 1; + length = sourceRange.getLength(); + } catch (final JavaModelException e) { + e.printStackTrace(); + } + } else if (element instanceof IMethod) { + final IMethod method = (IMethod) element; + try { + final ISourceRange nameRange = method.getNameRange(); + final int nameStartOffset = nameRange.getOffset(); + final int nameEndOffset = nameStartOffset + nameRange.getLength(); + + final ISourceRange sourceRange = method.getSourceRange(); + startOffset = + method.getJavadocRange().getOffset() + method.getJavadocRange().getLength() + 1; + if (content.toCharArray()[sourceRange.getOffset() + sourceRange.getLength() - 1] == '}') { + final int indexOfParanthesis = content.indexOf("{", nameEndOffset); + length = indexOfParanthesis - startOffset; + } else if (content.toCharArray()[sourceRange.getOffset() + sourceRange.getLength() + - 1] == ';') { + length = sourceRange.getLength(); + } + + } catch (final JavaModelException e) { + e.printStackTrace(); + } + } else if (element instanceof IType) { + final IType type = (IType) element; + try { + final ISourceRange nameRange = type.getNameRange(); + final int nameStartOffset = nameRange.getOffset(); + final int nameEndOffset = nameStartOffset + nameRange.getLength(); + + final int indexOfParanthesis = content.indexOf("{", nameEndOffset); + + startOffset = type.getJavadocRange().getOffset() + type.getJavadocRange().getLength() + 1; + length = indexOfParanthesis - startOffset; + } catch (final JavaModelException e) { + e.printStackTrace(); + } + } + + final IDocument document = new Document(content); + final TextSelection textSelection = new TextSelection(document, startOffset, length); + return MarkerFactory.createMarker(file, textSelection); + + } else { + final MessageDialog dialog = new MessageDialog(MarkerActivator.getShell(), "Mark Information", + null, "Please perform a valid selection", MessageDialog.WARNING, new String[] {"OK"}, 0); + dialog.open(); + } + return marker; + } + + /** + * Creates a ReqIf Marker from tree selection + * + * @param selection + * @param file + * @param res + * @param editor + * @return + */ + // private static IMarker createReqIfMarker(final ITreeSelection selection, final IFile file, + // final IResource res, final IEditorPart editor) { + // + // IMarker marker = null; + // + // final Identifiable element = (Identifiable) selection.getFirstElement(); + // final URI uri = EcoreUtil.getURI(element); + // + // final String attributeValue = MarkerFactory.reqIfToString(element); + // + // final String identifier = element.getIdentifier(); + // if (identifier != null && !identifier.isEmpty()) { + // final XMLInputFactory factory = XMLInputFactory.newInstance(); + // try { + // final XMLStreamReader streamReader = + // factory.createXMLStreamReader(new FileReader(res.getLocation().toFile())); + // + // EventMemento memento = null; + // EventMemento current = null; + // while (streamReader.hasNext()) { + // if (streamReader.getEventType() == XMLStreamConstants.START_ELEMENT) { + // final String name = streamReader.getAttributeValue(null, "IDENTIFIER"); + // if (name != null && name.equals(identifier)) { + // break; + // } + // } + // memento = new EventMemento(streamReader); + // streamReader.next(); + // current = new EventMemento(streamReader); + // } + // streamReader.close(); + // + // // JFace Text Document object is created to get character offsets from line numbers. + // final int[] offsetStartEnd = + // MarkerFactory.getStartEndOffsetFromXML(streamReader, file, memento, current); + // final int start = offsetStartEnd[0]; + // final int end = offsetStartEnd[1]; + // + // String text = null; + // if (element.isSetIdentifier()) { + // text = element.getIdentifier(); + // } + // if (text == null) { + // text = element.toString(); + // } + // + // final HashMap map = new HashMap<>(); + // MarkerUtilities.setLineNumber(map, current.getLineNumber()); + // MarkerUtilities.setMessage(map, "Marker Type : non-type"); + // MarkerUtilities.setCharStart(map, start); + // MarkerUtilities.setCharEnd(map, end); + // map.put(IMarker.TEXT, attributeValue); + // map.put(IMarker.LOCATION, current.getLineNumber()); + // map.put(IMarker.SOURCE_ID, MarkerFactory.generateId()); + // map.put(MarkUtilities.URI, uri.toString()); + // marker = file.createMarker(MarkerFactory.MARKER_MARKING); + // if (marker.exists()) { + // try { + // marker.setAttributes(map); + // } catch (final CoreException e) { + // // You need to handle the case where the marker no longer exists + // e.printStackTrace(); + // } + // } + // + // AnnotationFactory.addAnnotation(marker, AnnotationFactory.ANNOTATION_MARKING); + // + // } catch (final XMLStreamException e) { + // e.printStackTrace(); + // } catch (final FileNotFoundException e) { + // e.printStackTrace(); + // } catch (final CoreException e1) { + // e1.printStackTrace(); + // } + // } + // return marker; + // } + + /** + * Find a marker for given offset on given resource + * + * @param resource + * @param offset + * @return + */ + public static IMarker findMarkerByOffset(final IResource resource, final int offset) { + final IMarker marker = null; + final List mList = MarkerFactory.findMarkers(resource); + int start; + int end; + for (final IMarker iMarker : mList) { + start = MarkUtilities.getStart(iMarker); + end = MarkUtilities.getEnd(iMarker); + if (offset <= end && offset >= start) { + return iMarker; + } + } + return marker; + } + + /** + * Find a marker by its source id on resource + * + * @param resource + * @param id + * @return + */ + public static IMarker findMarkerBySourceId(final IResource resource, final String id) { + final IMarker marker = null; + final List mList = MarkerFactory.findMarkers(resource); + for (final IMarker iMarker : mList) { + if (id.equals(MarkUtilities.getSourceId(iMarker))) { + return iMarker; + } + } + return marker; + } + + @SuppressWarnings("resource") + public static IMarker findMarkerByOutlineTreeSelection(final ITreeSelection treeSelection, + final IFile file) { + final Object element = treeSelection.getFirstElement(); + + String content = null; + try { + content = new Scanner(file.getContents()).useDelimiter("\\Z").next(); + } catch (final CoreException e1) { + e1.printStackTrace(); + } + int startOffset = 0; + + if (element instanceof IField) { + final IField field = (IField) element; + try { + final ISourceRange nameRange = field.getNameRange(); + final int nameStartOffset = nameRange.getOffset(); + final int nameEndOffset = nameStartOffset + nameRange.getLength(); + + final ISourceRange sourceRange = field.getSourceRange(); + if (nameEndOffset + 1 == sourceRange.getOffset() + sourceRange.getLength()) { + startOffset = sourceRange.getOffset(); + } else { + startOffset = sourceRange.getOffset(); + } + + } catch (final JavaModelException e) { + e.printStackTrace(); + } + } else if (element instanceof IInitializer) { + final IInitializer initializer = (IInitializer) element; + try { + final ISourceRange sourceRange = initializer.getSourceRange(); + startOffset = sourceRange.getOffset(); + } catch (final JavaModelException e) { + e.printStackTrace(); + } + } else if (element instanceof IMethod) { + final IMethod method = (IMethod) element; + try { + final ISourceRange sourceRange = method.getSourceRange(); + if (content.toCharArray()[sourceRange.getOffset() + sourceRange.getLength() - 1] == '}') { + startOffset = sourceRange.getOffset(); + } else if (content.toCharArray()[sourceRange.getOffset() + sourceRange.getLength() + - 1] == ';') { + startOffset = sourceRange.getOffset(); + } + + } catch (final JavaModelException e) { + e.printStackTrace(); + } + } else if (element instanceof IType) { + final IType type = (IType) element; + try { + final ISourceRange sourceRange = type.getSourceRange(); + startOffset = sourceRange.getOffset(); + } catch (final JavaModelException e) { + e.printStackTrace(); + } + } + return MarkerFactory.findMarkerByOffset(file, startOffset); + } + + /** + * Finds a marker for given selection on the tree + * + * @param treeSelection + * @param resource + * @return + */ + public static IMarker findMarkerByTreeSelection(final ITreeSelection treeSelection, + final IResource resource) { + final Object o = treeSelection.getFirstElement(); + if (o != null && o instanceof EObject) { + final String uri = EcoreUtil.getURI((EObject) o).toString(); + + final List markers = MarkerFactory.findMarkers(resource); + + for (final IMarker iMarker : markers) { + if (uri.equals(MarkUtilities.getUri(iMarker))) { + return iMarker; + } + } + } + return null; + } + + /** + * @param resource + * @param xpath + * @return + */ + public static IMarker findMarkerByXpath(final IResource resource, final String xpath) { + final IMarker marker = null; + if (xpath == null || xpath.isEmpty()) { + return null; + } + final List mList = MarkerFactory.findMarkers(resource); + for (final IMarker iMarker : mList) { + if (xpath.equals(MarkUtilities.getXpath(iMarker))) { + return iMarker; + } + } + return marker; + } + + /** + * Returns a list of markers that are linked to the resource or any sub resource of the resource + * + * @param resource + * @return + */ + public static List findMarkers(final IResource resource) { + try { + if (resource == null) { + return new ArrayList<>(); + } + return Arrays.asList( + resource.findMarkers(MarkerFactory.MARKER_MARKING, true, IResource.DEPTH_INFINITE)); + } catch (final CoreException e) { + return new ArrayList<>(); + } + } + + /** + * Returns a list of a resources markers + * + * @param resource + * @return + */ + public static ArrayList findMarkersAsArrayList(final IResource resource) { + try { + if (resource == null) { + return new ArrayList<>(); + } + final ArrayList myMarkerList = new ArrayList<>(); + IMarker[] list; + list = resource.findMarkers(MarkerFactory.MARKER_MARKING, true, IResource.DEPTH_INFINITE); + + for (final IMarker iMarker : list) { + myMarkerList.add(iMarker); + } + return myMarkerList; + } catch (final CoreException e) { + e.printStackTrace(); + } + return new ArrayList<>(); + } + + /** + * Find group of markers which means all of them are depended each other by same group + * + * @param resource + * @param groupId + * @return List of markers which have got same group + */ + public static List findMarkersByGroupId(final IResource resource, final String groupId) { + final List groupMarkers = new ArrayList<>(); + final List markerList = MarkerFactory.findMarkers(resource); + for (final IMarker iMarker : markerList) { + if (MarkUtilities.getGroupId(iMarker) != null + && groupId.equals(MarkUtilities.getGroupId(iMarker))) { + groupMarkers.add(iMarker); + } + } + return groupMarkers; + } + + /** + * @param resource + * @param uri + * @return + */ + public static IMarker findMarkersByUri(final IResource resource, final String uri) { + + final List markerList = MarkerFactory.findMarkers(resource); + for (final IMarker iMarker : markerList) { + if (uri.equals(MarkUtilities.getUri(iMarker))) { + return iMarker; + } + } + return null; + } + + /** + * @param resource + * @param selection + * @returns list of markers which are found by selection + */ + public static ArrayList findMarkersInSelection(final IResource resource, + final ITextSelection selection) { + final ArrayList markerListInArea = new ArrayList<>(); + final ArrayList markerList = MarkerFactory.findMarkersAsArrayList(resource); + + if (markerList.isEmpty()) { + return null; + } + final int textStart = selection.getOffset(); + final int textEnd = textStart + selection.getLength(); + + for (final IMarker iMarker : markerList) { + final int markerStart = MarkUtilities.getStart(iMarker); + final int markerEnd = MarkUtilities.getEnd(iMarker); + if (textStart >= markerStart && textStart <= markerEnd + || textEnd >= markerStart && textEnd <= markerEnd + || markerStart >= textStart && markerStart <= textEnd + || markerEnd >= textStart && markerEnd <= textEnd) { + + markerListInArea.add(iMarker); + } + } + return markerListInArea; + } + + /** + * @param resource + * @param textStart + * @param textEnd + * @return + */ + public static IMarker findMarkerWithAbsolutePosition(final IResource resource, + final int textStart, final int textEnd) { + final IMarker marker = null; + final ArrayList markerList = MarkerFactory.findMarkersAsArrayList(resource); + + if (markerList.isEmpty()) { + return null; + } + + for (final IMarker iMarker : markerList) { + final int markerStart = MarkUtilities.getStart(iMarker); + final int markerEnd = MarkUtilities.getEnd(iMarker); + if (textStart == markerStart && textEnd == markerEnd) { + return iMarker; + } + } + return marker; + } + + /** + * @param iResource + * @return list of untyped markers for given resource + */ + public static ArrayList findUntypedMarkers(final IResource iResource) { + ArrayList listOfMarkers = new ArrayList<>(); + listOfMarkers = MarkerFactory.findMarkersAsArrayList(iResource); + final Iterator iter = listOfMarkers.iterator(); + while (iter.hasNext()) { + final IMarker iMarker = iter.next(); + if (MarkUtilities.getType(iMarker) != null) { + iter.remove(); + } + } + return listOfMarkers; + } + + public static String generateId() { + final String base = "0000"; + final DocumentRoot documentRoot = MarkerUpdater.getDocumentRoot(); + int nextId = documentRoot.getAlloy().getRepository().getNextId(); + + String id = base + nextId; + id = id.substring(id.length() - 5); + + documentRoot.getAlloy().getRepository().setNextId(++nextId); + MarkerUpdater.writeDocumentRoot(documentRoot); + + return id; + } + + public static String generateId(final DocumentRoot documentRoot) { + final String base = "0000"; + int nextId = documentRoot.getAlloy().getRepository().getNextId(); + + String id = base + nextId; + id = id.substring(id.length() - 5); + + documentRoot.getAlloy().getRepository().setNextId(++nextId); + MarkerUpdater.writeDocumentRoot(documentRoot); + + return id; + } + + /** + * @returns the document content + */ + public static String getCurrentEditorContent() { + return MarkerFactory.getDocument().get(); + } + + /** + * @returns the document for current editor + */ + public static IDocument getDocument() { + MultiPageEditorPart mpepEditor; + ITextEditor iteEditor; + if (MarkerActivator.getEditor() instanceof MultiPageEditorPart) { + mpepEditor = (MultiPageEditorPart) MarkerActivator.getEditor(); + final IEditorPart[] editors = mpepEditor.findEditors(mpepEditor.getEditorInput()); + iteEditor = (ITextEditor) editors[0]; + } else { + iteEditor = (ITextEditor) MarkerActivator.getEditor(); + } + final IDocumentProvider idp = iteEditor.getDocumentProvider(); + return idp.getDocument(iteEditor.getEditorInput()); + + } + + /** + * Note: it compares marker's resource file name and open editors' file name. + * + * @param marker + * @return if marker's editor is open, return editor, else return null + */ + public static IEditorPart getOpenEditorOfMarker(final IMarker marker) { + final IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows(); + for (final IWorkbenchWindow iWorkbenchWindow : windows) { + final IWorkbenchPage[] pages = iWorkbenchWindow.getPages(); + for (final IWorkbenchPage iWorkbenchPage : pages) { + final IEditorReference[] editors = iWorkbenchPage.getEditorReferences(); + for (final IEditorReference iEditorReference : editors) { + try { + if (iEditorReference instanceof IFileEditorInput) { + final IFileEditorInput input = (IFileEditorInput) iEditorReference.getEditorInput(); + final IFile file = input.getFile(); + // TODO Caused by: java.lang.NullPointerException when delete marker on ecore editor. + if (file.getFullPath().equals(marker.getResource().getFullPath())) { + return iEditorReference.getEditor(false); + } + } + } catch (final PartInitException e) { + e.printStackTrace(); + } + } + } + } + return null; + } + + /** + * @param selections + * @return + */ + public static String getQualifiedName(final ITreeSelection selections) { + final TreePath[] paths = selections.getPaths(); + + // Consider only not empty and single selection + if (selections.isEmpty() || selections.size() > 1) { + return null; + } + + final TreePath path = paths[0]; + IElementComparer comparer = null; + if (selections instanceof TreeSelection) { + comparer = ((TreeSelection) selections).getElementComparer(); + } + System.out.println(path.hashCode(comparer)); + for (int i = 1; i < path.getSegmentCount(); i++) { + if (path.getSegment(i) instanceof ResourceFactoryImpl) { + final EcoreResourceFactoryImpl eResourceFactory = + (EcoreResourceFactoryImpl) path.getSegment(i); + System.out + .println(eResourceFactory.getClass().getName() + ": " + eResourceFactory.toString()); + } else if (path.getSegment(i) instanceof ENamedElement) { + final ENamedElement namedElement = (ENamedElement) path.getSegment(i); + System.out.println(namedElement.getClass().getName() + ": " + namedElement.getName()); + } else { + System.out.println("?"); + } + } + return null; + } + + /** + * @returns current selection + */ + public static ISelection getSelection() { + return MarkerActivator.getActiveWorkbenchWindow().getSelectionService().getSelection(); + } + + /** + * Returns character offsets from line numbers from JFace Text Document object. + */ + private static int[] getStartEndOffsetFromXML(final XMLStreamReader streamReader, + final IFile file, final EventMemento memento, final EventMemento current) { + final int[] offsetStartEnd = new int[2]; + try { + String charsetName = streamReader.getCharacterEncodingScheme(); + if (charsetName == null) { + charsetName = "UTF-8"; + } + final Scanner scanner = new Scanner(file.getContents(), charsetName); + final IDocument document = new Document(scanner.useDelimiter("\\A").next()); + scanner.close(); + + int start = 0; + int end = 0; + + final IRegion startRegion = document.getLineInformation(memento.getLineNumber() - 1); + start = startRegion.getOffset() + memento.getColumnNumber() - 2; + final IRegion endRegion = document.getLineInformation(current.getLineNumber()); + end = endRegion.getOffset() - 1; + + offsetStartEnd[0] = start; + offsetStartEnd[1] = end; + + } catch (final BadLocationException e1) { + // e1.printStackTrace(); + System.out + .println(e1.toString() + " --> in MarkerFactory's getStartEndOffsetFromXML function"); + } catch (final CoreException e) { + e.printStackTrace(); + } + return offsetStartEnd; + } + + /** + * Returns the text of element which given from Instance + */ + public static String instanceToString(final EObject element) { + final EClass clazz = element.eClass(); + String text = clazz.getName() + " "; + + final EList structuralFeatures = clazz.getEStructuralFeatures(); + for (final EStructuralFeature eStructuralFeature : structuralFeatures) { + if (!(eStructuralFeature instanceof EReference)) { + text += eStructuralFeature.getName() + " = " + element.eGet(eStructuralFeature) + " "; + } + } + return text == null ? "" : text; + } + + /** + * This method refresh Project Explorer View when the actions (Mark/Mark All/Delete/Delete All) + * have been completed. + * + */ + public static void refreshProjectExp() { + try { + ResourcesPlugin.getWorkspace().getRoot().refreshLocal(IResource.DEPTH_INFINITE, null); + final IViewPart viewPart = PlatformUI.getWorkbench().getWorkbenchWindows()[0].getActivePage() + .findView("org.eclipse.ui.navigator.ProjectExplorer"); + if (viewPart == null) { + return; + } + ((ProjectExplorer) viewPart).getCommonViewer().refresh(); + } catch (final CoreException e) { + e.printStackTrace(); + } + } + + /** + * Returns the text of element which given from Reqif + */ + // public static String reqIfToString(final Identifiable element) { + // AttributeValueString attribute = null; + // String attributeValue = null; + // if (element instanceof SpecHierarchy) { + // final SpecHierarchy specHierarchy = (SpecHierarchy) element; + // final Iterator iter = specHierarchy.getObject().getValues().iterator(); + // while (iter.hasNext()) { + // final Object next = iter.next(); + // if (next instanceof AttributeValueString) { + // attribute = (AttributeValueString) next; + // attributeValue = attribute.getTheValue(); + // break; + // } + // } + // } else { + // final TreeIterator iter = element.eAllContents(); + // + // while (iter.hasNext()) { + // final EObject next = iter.next(); + // if (next instanceof AttributeValueString) { + // attribute = (AttributeValueString) next; + // attributeValue = attribute.getTheValue(); + // break; + // } + // } + // } + // return attributeValue; + // } + + /** + * For the given marker this method updates its XML location + * + * @param marker + * @param res + */ + public static void updateMarkerfromXMLForInstance(final IMarker marker, final IResource res) { + + try { + final String[] uriSplits = MarkUtilities.getUri(marker).split("/"); + final List uriSplitsList = Arrays.asList(uriSplits); + final int indexOfStream = uriSplitsList.indexOf("") + 1; + final ArrayList pieces = new ArrayList<>(); + for (int i = indexOfStream; i < uriSplits.length; i++) { + int dot = 0; + dot = uriSplits[i].lastIndexOf("."); + pieces.add(uriSplits[i].substring(1, dot)); + pieces.add(uriSplits[i].substring(dot + 1, uriSplits[i].length())); + } + + final XMLInputFactory factory = XMLInputFactory.newInstance(); + + final XMLStreamReader streamReader = + factory.createXMLStreamReader(new FileReader(res.getLocation().toFile())); + + EventMemento memento = null; + EventMemento current = null; + int count = 0; + int elementCount = 0; + String name = null; + String startElementName = null; + int startElementCount = 0; + + while (streamReader.hasNext()) { + + if (streamReader.getEventType() == XMLStreamConstants.START_ELEMENT) { + + name = streamReader.getLocalName().toString(); + + startElementName = (String) pieces.get(count); + startElementCount = Integer.parseInt((String) pieces.get(count + 1)); + + if (name.equals(startElementName)) { + if (elementCount == startElementCount && pieces.size() - 2 == count) { + break; + } + + if (elementCount != startElementCount) { + elementCount++; + } else if (pieces.size() - 2 != count) { + count += 2; + elementCount = 0; + } + } + + } + memento = new EventMemento(streamReader); + streamReader.next(); + current = new EventMemento(streamReader); + } + + final IFile file = (IFile) res; + + // JFace Text Document object is created to get character offsets from line numbers. + final int[] offsetStartEnd = + MarkerFactory.getStartEndOffsetFromXML(streamReader, file, memento, current); + final int start = offsetStartEnd[0]; + final int end = offsetStartEnd[1]; + + MarkUtilities.setStart(marker, start); + MarkUtilities.setEnd(marker, end); + MarkUtilities.setLinenumber(marker, current.getLineNumber()); + + } catch (final XMLStreamException e) { + e.printStackTrace(); + } catch (final FileNotFoundException e) { + e.printStackTrace(); + } + } + + /** + * For the given marker this method updates its XML location + * + * @param marker + * @param res + */ + public static void updateMarkerfromXMLForModel(final IMarker marker, final IResource res) { + try { + final String[] uriSplits = MarkUtilities.getUri(marker).split("/"); + final List uriSplitsList = Arrays.asList(uriSplits); + int indexOfStream = uriSplitsList.indexOf("") + 1; + + final XMLInputFactory factory = XMLInputFactory.newInstance(); + + final XMLStreamReader streamReader = + factory.createXMLStreamReader(new FileReader(res.getLocation().toFile())); + + EventMemento memento = null; + EventMemento current = null; + while (streamReader.hasNext()) { + + if (streamReader.getEventType() == XMLStreamConstants.START_ELEMENT) { + final String name = streamReader.getAttributeValue(null, "name"); + if (name != null && name.equals(uriSplitsList.get(indexOfStream))) { + indexOfStream++; + + if (uriSplitsList.size() == indexOfStream) { + break; + } + } + } + memento = new EventMemento(streamReader); + streamReader.next(); + current = new EventMemento(streamReader); + + } + + final IFile file = (IFile) res; + + // JFace Text Document object is created to get character offsets from line numbers. + final int[] offsetStartEnd = + MarkerFactory.getStartEndOffsetFromXML(streamReader, file, memento, current); + final int start = offsetStartEnd[0]; + final int end = offsetStartEnd[1]; + + // Create Marker + MarkUtilities.setStart(marker, start); + MarkUtilities.setEnd(marker, end); + MarkUtilities.setLinenumber(marker, current.getLineNumber()); + + } catch (final XMLStreamException e) { + e.printStackTrace(); + } catch (final FileNotFoundException e) { + e.printStackTrace(); + } + } + + /** + * For the given marker this method updates its XML location + * + * @param marker + * @param res + */ + public static void updateMarkerfromXMLForReqIf(final IMarker marker, final IResource res) { + + final XMLInputFactory factory = XMLInputFactory.newInstance(); + try { + final String uri = MarkUtilities.getUri(marker); + final String identifier = uri.substring(uri.lastIndexOf("#") + 1, uri.length()); + final XMLStreamReader streamReader = + factory.createXMLStreamReader(new FileReader(res.getLocation().toFile())); + + EventMemento memento = null; + EventMemento current = null; + while (streamReader.hasNext()) { + if (streamReader.getEventType() == XMLStreamConstants.START_ELEMENT) { + final String name = streamReader.getAttributeValue(null, "IDENTIFIER"); + if (name != null && name.equals(identifier)) { + break; + } + } + memento = new EventMemento(streamReader); + streamReader.next(); + current = new EventMemento(streamReader); + } + streamReader.close(); + + final IFile file = (IFile) res; + + // JFace Text Document object is created to get character offsets from line numbers. + final int[] offsetStartEnd = + MarkerFactory.getStartEndOffsetFromXML(streamReader, file, memento, current); + final int start = offsetStartEnd[0]; + final int end = offsetStartEnd[1]; + + MarkUtilities.setStart(marker, start); + MarkUtilities.setEnd(marker, end); + MarkUtilities.setLinenumber(marker, current.getLineNumber()); + + } catch (final XMLStreamException e) { + e.printStackTrace(); + } catch (final FileNotFoundException e) { + e.printStackTrace(); + } + } +} diff --git a/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/internal/MarkerTypeElement.java b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/internal/MarkerTypeElement.java new file mode 100644 index 00000000..5f90f175 --- /dev/null +++ b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/internal/MarkerTypeElement.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.internal; + +import java.io.Serializable; +import java.util.ArrayList; + +@SuppressWarnings("serial") +public class MarkerTypeElement implements Serializable { + + private String type; + private ArrayList children = new ArrayList(); + + public MarkerTypeElement(String type) { + this.type = type; + } + + public MarkerTypeElement(String type, ArrayList children) { + super(); + this.type = type; + this.children = children; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public ArrayList getChildren() { + return children; + } + + public void setChildren(ArrayList children) { + this.children = children; + } +} diff --git a/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/internal/MarkerUpdater.java b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/internal/MarkerUpdater.java new file mode 100644 index 00000000..c1140e7a --- /dev/null +++ b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/internal/MarkerUpdater.java @@ -0,0 +1,404 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.marker.internal; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.commands.Command; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.NotEnabledException; +import org.eclipse.core.commands.NotHandledException; +import org.eclipse.core.commands.common.NotDefinedException; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.URI; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.Position; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.services.IServiceLocator; +import org.eclipse.ui.texteditor.IMarkerUpdater; +import org.eclipse.ui.texteditor.MarkerUtilities; + +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.traceability.core.persistence.AlloyType; +import eu.modelwriter.traceability.core.persistence.DocumentRoot; +import eu.modelwriter.traceability.core.persistence.EntryType; +import eu.modelwriter.traceability.core.persistence.ItemType; +import eu.modelwriter.traceability.core.persistence.internal.ModelIO; + +/** + * Returns the attributes for which this updater is responsible.If the result is null, the updater + * assumes responsibility for any attributes. + * + * @author anil.ozturk + * + */ +public class MarkerUpdater implements IMarkerUpdater { + public static String baseFileDirectory = ResourcesPlugin.getWorkspace().getRoot().getLocation() + + " .modelwriter persistence.xml".replace(" ", System.getProperty("file.separator")); + + public static DocumentRoot getDocumentRoot() { + @SuppressWarnings("rawtypes") + final ModelIO modelIO = new ModelIO<>(); + @SuppressWarnings("rawtypes") + List list = null; + try { + list = modelIO.read(MarkerUpdater.getUri()); + } catch (final IOException e) { + return null; + } + if (list.isEmpty()) { + return null; + } + final DocumentRoot documentRoot = (DocumentRoot) list.get(0); + return documentRoot; + } + + public static String getLocation() { + return MarkerUpdater.baseFileDirectory; + } + + public static URI getUri() { + return URI.createFileURI(MarkerUpdater.getLocation()); + } + + public static void update(final IMarker marker) { + final DocumentRoot documentRoot = MarkerUpdater.getDocumentRoot(); + final AlloyType alloyType = documentRoot.getAlloy(); + + final EList atoms = alloyType.getRepository().getItem(); + + for (final ItemType itemType : atoms) { + if (itemType.getId().equals(MarkUtilities.getSourceId(marker))) { + final EList entries = itemType.getEntry(); + for (final EntryType entryType : entries) { + if (entryType.getKey().equals("text")) { + entryType.setValue(MarkUtilities.getText(marker)); + } else if (entryType.getKey().equals("resource")) { + entryType.setValue(MarkUtilities.getPath(marker)); + } else if (entryType.getKey().equals("uri")) { + entryType.setValue(MarkUtilities.getUri(marker)); + } else if (entryType.getKey().equals("offset")) { + entryType.setValue(Integer.toString(MarkUtilities.getStart(marker))); + } + } + break; + } + } + MarkerUpdater.writeDocumentRoot(documentRoot); + + } + + public static void updateSources(final IMarker marker) { + if (MarkUtilities.getSourceList(marker).size() != 0) { + final ArrayList sourceElements = MarkUtilities.getSourceList(marker); + + for (final MarkElement sourceElement : sourceElements) { + + final IMarker sourceMarker = sourceElement.getiMarker(); + + if (sourceMarker != null && sourceMarker.exists() + && MarkUtilities.getTargetList(sourceMarker).size() != 0) { + final ArrayList targetElementsofSource = + MarkUtilities.getTargetList(sourceMarker); + + for (final MarkElement targetElementofSource : targetElementsofSource) { + if (targetElementofSource.getiMarker() != null + && MarkUtilities.compare(targetElementofSource.getiMarker(), marker)) { + MarkUtilities.setText(targetElementofSource.getiMarker(), + MarkUtilities.getText(marker)); + MarkUtilities.setLinenumber(targetElementofSource.getiMarker(), + MarkUtilities.getLinenumber(marker)); + MarkUtilities.setStart(targetElementofSource.getiMarker(), + MarkUtilities.getStart(marker)); + MarkUtilities.setEnd(targetElementofSource.getiMarker(), + MarkUtilities.getEnd(marker)); + } + } + MarkUtilities.setTargetList(sourceMarker, targetElementsofSource); + } + } + } + } + + public static void updateSourcesToAllDelete(final IMarker marker) { + if (MarkUtilities.getSourceList(marker).size() != 0) { + final ArrayList sourceElements = MarkUtilities.getSourceList(marker); + + for (final MarkElement sourceElement : sourceElements) { + + final IMarker sourceMarker = sourceElement.getiMarker(); + List groupSourceMarkers = new ArrayList(); + + if (MarkUtilities.getGroupId(sourceMarker) != null) { + groupSourceMarkers = MarkerFactory.findMarkersByGroupId(sourceMarker.getResource(), + MarkUtilities.getGroupId(sourceMarker)); + } + if (groupSourceMarkers.isEmpty()) { + groupSourceMarkers.add(sourceMarker); + } + + for (final IMarker groupSourceMarker : groupSourceMarkers) { + + if (MarkUtilities.getTargetList(groupSourceMarker).size() != 0) { + final ArrayList targetElementsofSource = + MarkUtilities.getTargetList(groupSourceMarker); + + for (int i = targetElementsofSource.size() - 1; i >= 0; i--) { + if (MarkUtilities.compare(targetElementsofSource.get(i).getiMarker(), marker)) { + targetElementsofSource.remove(i); + } + } + MarkUtilities.setTargetList(groupSourceMarker, targetElementsofSource); + } + } + } + } + } + + public static void updateSourcesToDelete(final IMarker beDeleted) { + try { + if (MarkUtilities.getSourceList(beDeleted).size() != 0) { + final ArrayList sourceElements = MarkUtilities.getSourceList(beDeleted); + + for (final MarkElement sourceElement : sourceElements) { + + final IMarker sourceMarker = sourceElement.getiMarker(); + List groupSourceMarkers = new ArrayList(); + + if (MarkUtilities.getGroupId(sourceMarker) != null) { + groupSourceMarkers = MarkerFactory.findMarkersByGroupId(sourceMarker.getResource(), + MarkUtilities.getGroupId(sourceMarker)); + } + if (groupSourceMarkers.isEmpty()) { + groupSourceMarkers.add(sourceMarker); + } + + for (final IMarker groupSourceMarker : groupSourceMarkers) { + + if (MarkUtilities.getTargetList(groupSourceMarker).size() != 0) { + final ArrayList targetElementsofSource = + MarkUtilities.getTargetList(groupSourceMarker); + + for (int i = targetElementsofSource.size() - 1; i >= 0; i--) { + if (MarkUtilities.compare(targetElementsofSource.get(i).getiMarker(), beDeleted)) { + targetElementsofSource.remove(i); + } + } + MarkUtilities.setTargetList(groupSourceMarker, targetElementsofSource); + + if (groupSourceMarker.getType().equals(MarkerFactory.MARKER_MAPPING) + && targetElementsofSource.size() == 0) { + // final IEditorPart part = + IDE.openEditor(MarkerActivator.getActiveWorkbenchWindow().getActivePage(), + groupSourceMarker, false); + final Map attributes = groupSourceMarker.getAttributes(); + final IResource res = groupSourceMarker.getResource(); + AnnotationFactory.removeAnnotation(groupSourceMarker); + groupSourceMarker.delete(); + MarkerUtilities.createMarker(res, attributes, MarkerFactory.MARKER_MARKING); + final IMarker newMarker = MarkerFactory.findMarkerBySourceId(res, + (String) attributes.get(IMarker.SOURCE_ID)); + AnnotationFactory.addAnnotation(newMarker, AnnotationFactory.ANNOTATION_MARKING); + } + } + } + } + } + } catch (final CoreException e) { + e.printStackTrace(); + } + } + + public static void updateTargets(final IMarker marker) { + if (MarkUtilities.getTargetList(marker).size() != 0) { + final ArrayList targetElements = MarkUtilities.getTargetList(marker); + + for (final MarkElement targetElement : targetElements) { + + final IMarker targetMarker = targetElement.getiMarker(); + + if (targetMarker != null && targetMarker.exists() + && MarkUtilities.getSourceList(targetMarker).size() != 0) { + final ArrayList sourceElementsofTarget = + MarkUtilities.getSourceList(targetMarker); + + for (final MarkElement sourceElementofTarget : sourceElementsofTarget) { + if (sourceElementofTarget.getiMarker() != null + && MarkUtilities.compare(sourceElementofTarget.getiMarker(), marker)) { + MarkUtilities.setText(sourceElementofTarget.getiMarker(), + MarkUtilities.getText(marker)); + MarkUtilities.setLinenumber(sourceElementofTarget.getiMarker(), + MarkUtilities.getLinenumber(marker)); + MarkUtilities.setStart(sourceElementofTarget.getiMarker(), + MarkUtilities.getStart(marker)); + MarkUtilities.setEnd(sourceElementofTarget.getiMarker(), + MarkUtilities.getEnd(marker)); + } + } + MarkUtilities.setSourceList(targetMarker, sourceElementsofTarget); + } + } + } + } + + public static void updateTargetsToAllDelete(final IMarker marker) { + if (MarkUtilities.getTargetList(marker).size() != 0) { + final ArrayList targetElements = MarkUtilities.getTargetList(marker); + + for (final MarkElement targetElement : targetElements) { + + final IMarker targetMarker = targetElement.getiMarker(); + + List groupTargetMarkers = new ArrayList(); + + if (MarkUtilities.getGroupId(targetMarker) != null) { + groupTargetMarkers = MarkerFactory.findMarkersByGroupId(targetMarker.getResource(), + MarkUtilities.getGroupId(targetMarker)); + } + if (groupTargetMarkers.isEmpty()) { + groupTargetMarkers.add(targetMarker); + } + + for (final IMarker groupTargetMarker : groupTargetMarkers) { + + if (MarkUtilities.getSourceList(groupTargetMarker).size() != 0) { + + final ArrayList sourceElementsofTarget = + MarkUtilities.getSourceList(groupTargetMarker); + + for (int i = sourceElementsofTarget.size() - 1; i >= 0; i--) { + if (MarkUtilities.compare(sourceElementsofTarget.get(i).getiMarker(), marker)) { + sourceElementsofTarget.remove(i); + } + } + MarkUtilities.setSourceList(groupTargetMarker, sourceElementsofTarget); + } + } + } + } + } + + public static void updateTargetsToDelete(final IMarker beDeleted) { + if (MarkUtilities.getTargetList(beDeleted).size() != 0) { + final ArrayList targetElements = MarkUtilities.getTargetList(beDeleted); + + for (final MarkElement targetElement : targetElements) { + + final IMarker targetMarker = targetElement.getiMarker(); + List groupTargetMarkers = new ArrayList(); + + if (MarkUtilities.getGroupId(targetMarker) != null) { + groupTargetMarkers = MarkerFactory.findMarkersByGroupId(targetMarker.getResource(), + MarkUtilities.getGroupId(targetMarker)); + } + if (groupTargetMarkers.isEmpty()) { + groupTargetMarkers.add(targetMarker); + } + + for (final IMarker groupTargetMarker : groupTargetMarkers) { + + if (MarkUtilities.getSourceList(groupTargetMarker).size() != 0) { + + final ArrayList sourceElementsofTarget = + MarkUtilities.getSourceList(groupTargetMarker); + + for (int i = sourceElementsofTarget.size() - 1; i >= 0; i--) { + if (MarkUtilities.compare(sourceElementsofTarget.get(i).getiMarker(), beDeleted)) { + sourceElementsofTarget.remove(i); + } + } + MarkUtilities.setSourceList(groupTargetMarker, sourceElementsofTarget); + } + } + } + } + } + + @SuppressWarnings("unchecked") + public static void writeDocumentRoot(final DocumentRoot documentRoot) { + @SuppressWarnings("rawtypes") + final ModelIO modelIO = new ModelIO<>(); + modelIO.write(MarkerUpdater.getUri(), documentRoot); + } + + String markerType = MarkerFactory.MARKER_MARKING; + + @Override + public String[] getAttribute() { + return null; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.texteditor.IMarkerUpdater#getMarkerType() + * + */ + @Override + public String getMarkerType() { + return this.markerType; + } + + @Override + public boolean updateMarker(final IMarker marker, final IDocument doc, final Position position) { + try { + this.markerType = marker.getType(); + final int start = position.getOffset(); + final int end = position.getOffset() + position.getLength(); + + if (!MarkUtilities.getText(marker).equals(doc.get(start, position.getLength()))) { + // text of marker is changed + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + + final IServiceLocator serviceLocator = PlatformUI.getWorkbench(); + final ICommandService commandService = serviceLocator.getService(ICommandService.class); + + try { + final Command command = + commandService.getCommand("eu.modelwriter.marker.command.updatechangeandimpact"); + command.executeWithChecks(new ExecutionEvent()); + } catch (ExecutionException | NotDefinedException | NotEnabledException + | NotHandledException e1) { + e1.printStackTrace(); + } + } + }); + } + + MarkUtilities.setStart(marker, start); + MarkUtilities.setEnd(marker, end); + MarkUtilities.setLinenumber(marker, doc.getLineOfOffset(start)); + MarkUtilities.setText(marker, doc.get(start, position.getLength())); + + MarkerUpdater.update(marker); + // TODO When the update action completed, you must trigger the Visualization.showViz method + // for refreshing the view. + + return true; + } catch (CoreException | BadLocationException e) { + return false; + } + } +} diff --git a/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/model/decorators/EcoreModelDecorator.java b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/model/decorators/EcoreModelDecorator.java new file mode 100644 index 00000000..32e9a1d9 --- /dev/null +++ b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/model/decorators/EcoreModelDecorator.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker.model.decorators; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EClassifier; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.jface.viewers.IDecoration; +import org.eclipse.jface.viewers.ILightweightLabelDecorator; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Color; +import org.eclipse.ui.plugin.AbstractUIPlugin; + +import eu.modelwriter.marker.MarkerActivator; +import eu.modelwriter.marker.internal.MarkerFactory; + +public class EcoreModelDecorator extends LabelProvider implements ILightweightLabelDecorator { + private static Color color_blue = new Color(null, 30, 144, 255); + private static Color color_maroon = new Color(null, 176, 48, 96); + + @Override + public void decorate(Object resource, IDecoration decoration) { + + if (resource instanceof ENamedElement) { + ENamedElement namedElement = (ENamedElement) resource; + Resource eResource = namedElement.eResource(); + if (eResource == null) + return; + URI eUri = eResource.getURI(); + IResource iResource = null; + if (eUri.isPlatformResource()) { + String platformString = eUri.toPlatformString(true); + iResource = ResourcesPlugin.getWorkspace().getRoot().findMember(platformString); + } + if (iResource == null) + return; + + AbstractUIPlugin plugin = MarkerActivator.getDefault(); + ImageRegistry imageRegistry = plugin.getImageRegistry(); + IMarker marker = null; + URI uri = EcoreUtil.getURI(namedElement); + marker = MarkerFactory.findMarkersByUri(iResource, uri.toString()); + + if (marker != null) { + try { + if (marker.getType().equals(MarkerFactory.MARKER_MARKING)) { + decoration.addOverlay( + ImageDescriptor + .createFromImage(imageRegistry.get(MarkerActivator.Images.IMAGE_BLACK_ID)), + IDecoration.BOTTOM_RIGHT); + decoration.setForegroundColor(color_blue); + } else { + decoration.addOverlay( + ImageDescriptor + .createFromImage(imageRegistry.get(MarkerActivator.Images.IMAGE_RED_ID)), + IDecoration.BOTTOM_RIGHT); + decoration.setForegroundColor(color_maroon); + } + } catch (CoreException e) { + e.printStackTrace(); + } + // EClass or EDataType + if (namedElement instanceof EClassifier) { + System.out.println("Classifier: " + namedElement.getName()); + EClassifier eC = (EClassifier) namedElement; + System.out.println(eC.getEPackage().getNsURI()); + System.out.println(eC.getClassifierID()); + } + if (namedElement instanceof EStructuralFeature) { + System.out.println("Structural Feature: " + namedElement.getName()); + EStructuralFeature eS = (EStructuralFeature) namedElement; + System.out.println(eS.getEContainingClass().getName()); + System.out.println(eS.getFeatureID()); + } + } + } else if (resource instanceof EObject) { + EObject element = (EObject) resource; + URI eUri = EcoreUtil.getURI(element); + + Resource eResource = element.eResource(); + if (eResource == null) + return; + IResource iResource = null; + if (eUri.isPlatformResource()) { + String platformString = eUri.toPlatformString(true); + iResource = ResourcesPlugin.getWorkspace().getRoot().findMember(platformString); + } + if (iResource == null) + return; + + AbstractUIPlugin plugin = MarkerActivator.getDefault(); + ImageRegistry imageRegistry = plugin.getImageRegistry(); + try { + IMarker marker = MarkerFactory.findMarkersByUri(iResource, eUri.toString()); + if (marker != null) { + if (marker.getType().equals(MarkerFactory.MARKER_MARKING)) { + decoration.addOverlay( + ImageDescriptor + .createFromImage(imageRegistry.get(MarkerActivator.Images.IMAGE_BLACK_ID)), + IDecoration.BOTTOM_RIGHT); + decoration.setForegroundColor(color_blue); + } else { + decoration.addOverlay( + ImageDescriptor + .createFromImage(imageRegistry.get(MarkerActivator.Images.IMAGE_RED_ID)), + IDecoration.BOTTOM_RIGHT); + decoration.setForegroundColor(color_maroon); + } + } + } catch (CoreException e) { + e.printStackTrace(); + } + } + } +} diff --git a/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/model/decorators/FileDecorator.java b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/model/decorators/FileDecorator.java new file mode 100644 index 00000000..8e48e1fd --- /dev/null +++ b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/model/decorators/FileDecorator.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker.model.decorators; + +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.IDecoration; +import org.eclipse.jface.viewers.ILightweightLabelDecorator; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Color; + +import eu.modelwriter.marker.internal.MarkerFactory; + +public class FileDecorator extends LabelProvider implements ILightweightLabelDecorator { + + public static final String ICON = "/icons/Black.gif"; + private static Color color = new Color(null, 255, 192, 0); + + @Override + public void decorate(Object resource, IDecoration decoration) { + int markers = MarkerFactory.findMarkers((IResource) resource).size(); + if (markers > 0) { + decoration.addOverlay(ImageDescriptor.createFromFile(FileDecorator.class, ICON), + IDecoration.TOP_RIGHT); + decoration.setForegroundColor(color); + } else { + decoration.addOverlay(null); + decoration.setForegroundColor(new Color(null, 0, 0, 0, 0)); + } + } +} diff --git a/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/xml/EventMemento.java b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/xml/EventMemento.java new file mode 100644 index 00000000..ed80e40d --- /dev/null +++ b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/xml/EventMemento.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker.xml; + +import javax.xml.stream.XMLStreamReader; + +public class EventMemento { + private int eventType; + private int characterOffset; + private int columnNumber; + private int lineNumber; + + public int getEventType() { + return eventType; + } + + public int getCharacterOffset() { + return characterOffset; + } + + public int getColumnNumber() { + return columnNumber; + } + + public int getLineNumber() { + return lineNumber; + } + + public EventMemento(XMLStreamReader xmlr) { + eventType = xmlr.getEventType(); + characterOffset = xmlr.getLocation().getCharacterOffset(); + columnNumber = xmlr.getLocation().getColumnNumber(); + lineNumber = xmlr.getLocation().getLineNumber(); + } +} diff --git a/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/xml/Sax2Dom.java b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/xml/Sax2Dom.java new file mode 100644 index 00000000..158d2289 --- /dev/null +++ b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/xml/Sax2Dom.java @@ -0,0 +1,190 @@ +package eu.modelwriter.marker.xml; + +/* + * Copyright 2004, 2015 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +// Revised from xmlbeans + +import org.w3c.dom.Node; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.ProcessingInstruction; +import org.w3c.dom.Comment; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.ContentHandler; +import org.xml.sax.helpers.DefaultHandler; +import org.xml.sax.ext.LexicalHandler; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.DocumentBuilderFactory; +import java.util.Stack; +import java.util.Vector; + +public class Sax2Dom extends DefaultHandler implements ContentHandler, LexicalHandler { + public static final String EMPTYSTRING = ""; + public static final String XML_PREFIX = "xml"; + public static final String XMLNS_PREFIX = "xmlns"; + public static final String XMLNS_STRING = "xmlns:"; + public static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/"; + + private Node _root = null; + private Document _document = null; + private Stack _nodeStk = new Stack(); + private Vector _namespaceDecls = null; + + public Sax2Dom() throws ParserConfigurationException { + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + _document = factory.newDocumentBuilder().newDocument(); + _root = _document; + } + + public Sax2Dom(Node root) throws ParserConfigurationException { + _root = root; + if (root instanceof Document) { + _document = (Document) root; + } else if (root != null) { + _document = root.getOwnerDocument(); + } else { + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + _document = factory.newDocumentBuilder().newDocument(); + _root = _document; + } + } + + public Node getDOM() { + return _root; + } + + public void characters(char[] ch, int start, int length) { + final Node last = _nodeStk.peek(); + + // No text nodes can be children of root (DOM006 exception) + if (last != _document) { + final String text = new String(ch, start, length); + last.appendChild(_document.createTextNode(text)); + } + } + + public void startDocument() { + _nodeStk.push(_root); + } + + public void endDocument() { + _nodeStk.pop(); + } + + public void startElement(String namespace, String localName, String qName, Attributes attrs) { + final Element tmp = (Element) _document.createElementNS(namespace, qName); + + // Add name space declarations first + if (_namespaceDecls != null) { + final int nDecls = _namespaceDecls.size(); + for (int i = 0; i < nDecls; i++) { + final String prefix = (String) _namespaceDecls.elementAt(i++); + + if (prefix == null || prefix.equals(EMPTYSTRING)) { + tmp.setAttributeNS(XMLNS_URI, XMLNS_PREFIX, (String) _namespaceDecls.elementAt(i)); + } else { + tmp.setAttributeNS(XMLNS_URI, XMLNS_STRING + prefix, + (String) _namespaceDecls.elementAt(i)); + } + } + _namespaceDecls.clear(); + } + + // Add attributes to element + final int nattrs = attrs.getLength(); + for (int i = 0; i < nattrs; i++) { + if (attrs.getLocalName(i) == null) { + tmp.setAttribute(attrs.getQName(i), attrs.getValue(i)); + } else { + tmp.setAttributeNS(attrs.getURI(i), attrs.getQName(i), attrs.getValue(i)); + } + } + + // Append this new node onto current stack node + Node last = _nodeStk.peek(); + last.appendChild(tmp); + + // Push this node onto stack + _nodeStk.push(tmp); + } + + public void endElement(String namespace, String localName, String qName) { + _nodeStk.pop(); + } + + public void startPrefixMapping(String prefix, String uri) { + if (_namespaceDecls == null) { + _namespaceDecls = new Vector(2); + } + _namespaceDecls.addElement(prefix); + _namespaceDecls.addElement(uri); + } + + public void endPrefixMapping(String prefix) { + // do nothing + } + + /** + * This class is only used internally so this method should never be called. + */ + public void ignorableWhitespace(char[] ch, int start, int length) {} + + /** + * adds processing instruction node to DOM. + */ + public void processingInstruction(String target, String data) { + final Node last = (Node) _nodeStk.peek(); + ProcessingInstruction pi = _document.createProcessingInstruction(target, data); + if (pi != null) + last.appendChild(pi); + } + + /** + * This class is only used internally so this method should never be called. + */ + public void setDocumentLocator(Locator locator) {} + + /** + * This class is only used internally so this method should never be called. + */ + public void skippedEntity(String name) {} + + + /** + * Lexical Handler method to create comment node in DOM tree. + */ + public void comment(char[] ch, int start, int length) { + final Node last = (Node) _nodeStk.peek(); + Comment comment = _document.createComment(new String(ch, start, length)); + if (comment != null) + last.appendChild(comment); + } + + // Lexical Handler methods- not implemented + public void startCDATA() {} + + public void endCDATA() {} + + public void startEntity(java.lang.String name) {} + + public void endEntity(String name) {} + + public void startDTD(String name, String publicId, String systemId) throws SAXException {} + + public void endDTD() {} +} diff --git a/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/xml/XMLDOMHelper.java b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/xml/XMLDOMHelper.java new file mode 100644 index 00000000..cf888b81 --- /dev/null +++ b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/xml/XMLDOMHelper.java @@ -0,0 +1,415 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker.xml; + +import java.io.File; +import java.io.IOException; +import java.util.Stack; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +public class XMLDOMHelper { + + public static String findNodeAndGetXPath(String qName, String fileName) { + return getFullXPath(findNode(qName, fileName)); + } + + public static Node findNode(String qName, String fileName) { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setValidating(false); + DocumentBuilder db; + Document doc; + try { + db = dbf.newDocumentBuilder(); + doc = db.parse(new File(fileName)); + Node node = findNode(qName, doc); + if (node != null) { + return node; + } + + } catch (ParserConfigurationException e) { + e.printStackTrace(); + } catch (SAXException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + public static Node findNodeByXpath(String xpathExpression, String fileName) { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setValidating(false); + DocumentBuilder db; + Document doc; + try { + db = dbf.newDocumentBuilder(); + doc = db.parse(new File(fileName)); + XPath xpath = XPathFactory.newInstance().newXPath(); + NodeList nodes = (NodeList) xpath.evaluate(xpathExpression, doc, XPathConstants.NODESET); + for (int i = 0; i < nodes.getLength(); i++) { + System.out.print(nodes.item(i).getNodeName() + " "); + } + if (nodes.getLength() > 1) + return nodes.item(0); + } catch (ParserConfigurationException e) { + e.printStackTrace(); + } catch (SAXException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + return null; + } + + /** + * Constructs a XPath query to the supplied node. + * + * {@code + * + * + * + * Harry Potter and the Philosopher's Stone + * 0747532745 + * + * children + * stone + * + * + * + * Harry Potter and the Chamber of Secrets + * 0747538484 + * + * children + * secrets + * + * + * + * Harry Potter and the Prisoner of Azkaban + * 0747546290 + * + * children + * prisoner + * + * + * + * } + * + * Title node of "Harry Potter and the Chamber of Secrets": * + * + *
+   * bookstore/book[@id='2']/title[1]
+   * 
+ * + * Second tag node of "Harry Potter and the Prisoner of Azkaban": + * + *
+   * bookstore/book[@id='3']/tags[1]/tag[2]
+   * 
+ * + * @param n + * @return + */ + public static String getXPath(Node n) { + // abort early + if (null == n) + return null; + + // declarations + Node parent = null; + Stack hierarchy = new Stack(); + StringBuffer buffer = new StringBuffer(); + + // push element on stack + hierarchy.push(n); + + parent = n.getParentNode(); + while (null != parent && parent.getNodeType() != Node.DOCUMENT_NODE) { + // push on stack + hierarchy.push(parent); + + // get parent of parent + parent = parent.getParentNode(); + } + + // construct xpath + Object obj = null; + while (!hierarchy.isEmpty() && null != (obj = hierarchy.pop())) { + Node node = (Node) obj; + boolean handled = false; + + // only consider elements + if (node.getNodeType() == Node.ELEMENT_NODE) { + Element e = (Element) node; + + // is this the root element? + if (buffer.length() == 0) { + // root element - simply append element name + buffer.append(node.getLocalName()); + } else { + // child element - append slash and element name + buffer.append("/"); + buffer.append(node.getLocalName()); + + if (node.hasAttributes()) { + // see if the element has a name or id attribute + if (e.hasAttribute("id")) { + // id attribute found - use that + buffer.append("[@id='" + e.getAttribute("id") + "']"); + handled = true; + } else if (e.hasAttribute("name") && e.getAttribute("name") != null + && !e.getAttribute("name").isEmpty()) { + // name attribute found - use that + buffer.append("[@name='" + e.getAttribute("name") + "']"); + handled = true; + } + } + + if (!handled) { + // no known attribute we could use - get sibling index + int prev_siblings = 1; + Node prev_sibling = node.getPreviousSibling(); + while (null != prev_sibling) { + if (prev_sibling.getNodeType() == node.getNodeType()) { + if (prev_sibling.getLocalName().equalsIgnoreCase(node.getLocalName())) { + prev_siblings++; + } + } + prev_sibling = prev_sibling.getPreviousSibling(); + } + buffer.append("[" + prev_siblings + "]"); + } + } + } + } + + // return buffer + return buffer.toString(); + } + + public static String getFullXPath(Node n) { + // abort early + if (null == n) + return null; + + // declarations + Node parent = null; + Stack hierarchy = new Stack(); + StringBuffer buffer = new StringBuffer(); + + // push element on stack + hierarchy.push(n); + + switch (n.getNodeType()) { + case Node.ATTRIBUTE_NODE: + parent = ((Attr) n).getOwnerElement(); + break; + case Node.ELEMENT_NODE: + parent = n.getParentNode(); + break; + case Node.DOCUMENT_NODE: + parent = n.getParentNode(); + break; + default: + throw new IllegalStateException("Unexpected Node type" + n.getNodeType()); + } + + while (null != parent && parent.getNodeType() != Node.DOCUMENT_NODE) { + // push on stack + hierarchy.push(parent); + + // get parent of parent + parent = parent.getParentNode(); + } + + // construct xpath + Object obj = null; + while (!hierarchy.isEmpty() && null != (obj = hierarchy.pop())) { + Node node = (Node) obj; + boolean handled = false; + + if (node.getNodeType() == Node.ELEMENT_NODE) { + Element e = (Element) node; + + // is this the root element? + if (buffer.length() == 0) { + // root element - simply append element name + buffer.append(node.getNodeName()); + } else { + // child element - append slash and element name + buffer.append("/"); + buffer.append(node.getNodeName()); + + if (node.hasAttributes()) { + // see if the element has a name or id attribute + if (e.hasAttribute("id")) { + // id attribute found - use that + buffer.append("[@id='" + e.getAttribute("id") + "']"); + handled = true; + } else if (e.hasAttribute("name") && e.getAttribute("name") != null + && !e.getAttribute("name").isEmpty()) { + // name attribute found - use that + buffer.append("[@name='" + e.getAttribute("name") + "']"); + handled = true; + } + } + + if (!handled) { + // no known attribute we could use - get sibling index + int prev_siblings = 1; + Node prev_sibling = node.getPreviousSibling(); + while (null != prev_sibling) { + if (prev_sibling.getNodeType() == node.getNodeType()) { + if (prev_sibling.getNodeName().equalsIgnoreCase(node.getNodeName())) { + prev_siblings++; + } + } + prev_sibling = prev_sibling.getPreviousSibling(); + } + buffer.append("[" + prev_siblings + "]"); + } + } + } else if (node.getNodeType() == Node.ATTRIBUTE_NODE) { + buffer.append("/@"); + buffer.append(node.getNodeName()); + } + } + // return buffer + return buffer.toString(); + } + + public static void printlnCommon(Node n) { + System.out.print(" nodeName=\"" + n.getNodeName() + "\""); + + String val = n.getNamespaceURI(); + if (val != null) { + System.out.print(" uri=\"" + val + "\""); + } + + val = n.getPrefix(); + + if (val != null) { + System.out.print(" pre=\"" + val + "\""); + } + + val = n.getLocalName(); + if (val != null) { + System.out.print(" local=\"" + val + "\""); + } + + val = n.getNodeValue(); + if (val != null) { + System.out.print(" nodeValue="); + if (val.trim().equals("")) { + // Whitespace + System.out.print("[WS]"); + } else { + System.out.print("\"" + n.getNodeValue() + "\""); + } + } + System.out.println(); + } + + /** + * Find the named subnode in a node's sublist. + *
    + *
  • Ignores comments and processing instructions. + *
  • Ignores TEXT nodes (likely to exist and contain ignorable whitespace, if not validating. + *
  • Ignores CDATA nodes and EntityRef nodes. + *
  • Examines element nodes to find one with the specified name. + *
+ * + * @param name the tag name for the element to find + * @param node the element node to start searching from + * @return the Node found + */ + public static Node findNode(String name, Node node) { + // get all child nodes + NodeList list = node.getChildNodes(); + + for (int i = 0; i < list.getLength(); i++) { + // get child node + Node childNode = list.item(i); + + if (childNode.getNodeType() == Node.ELEMENT_NODE) { + Element element = (Element) childNode; + if (element.hasAttributes()) { + if (element.hasAttribute("id") && element.getAttribute("id") != null + && !element.getAttribute("id").isEmpty() && element.getAttribute("id").equals(name)) { + return element; + } else if (element.hasAttribute("name") && element.getAttribute("name") != null + && !element.getAttribute("name").isEmpty() + && element.getAttribute("name").equals(name)) { + return element; + } + } + } + // visit child node + Node temp = findNode(name, childNode); + if (temp != null) + return temp; + } + return null; + } + + /** + * Return the text that a node contains. This routine: + *
    + *
  • Ignores comments and processing instructions. + *
  • Concatenates TEXT nodes, CDATA nodes, and the results of recursively processing EntityRef + * nodes. + *
  • Ignores any element nodes in the sublist. (Other possible options are to recurse into + * element sublists or throw an exception.) + *
+ * + * @param node a DOM node + * @return a String representing its contents + */ + public static String getText(Node node) { + StringBuffer result = new StringBuffer(); + if (!node.hasChildNodes()) + return ""; + + NodeList list = node.getChildNodes(); + for (int i = 0; i < list.getLength(); i++) { + Node subnode = list.item(i); + if (subnode.getNodeType() == Node.TEXT_NODE) { + result.append(subnode.getNodeValue()); + } else if (subnode.getNodeType() == Node.CDATA_SECTION_NODE) { + result.append(subnode.getNodeValue()); + } else if (subnode.getNodeType() == Node.ENTITY_REFERENCE_NODE) { + // Recurse into the subtree for text + // (and ignore comments) + result.append(getText(subnode)); + } + } + + return result.toString(); + } +} diff --git a/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/xml/XMLStreamHelper.java b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/xml/XMLStreamHelper.java new file mode 100644 index 00000000..e4c48706 --- /dev/null +++ b/Source/eu.modelwriter.marker/src/eu/modelwriter/marker/xml/XMLStreamHelper.java @@ -0,0 +1,160 @@ +/******************************************************************************* + * Copyright (c) 2015 UNIT Information Technologies R&D Ltd + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ferhat Erata - initial API and implementation + * H. Emre Kirmizi - initial API and implementation + * Serhat Celik - initial API and implementation + * U. Anil Ozturk - initial API and implementation + *******************************************************************************/ +package eu.modelwriter.marker.xml; + +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamReader; + +public class XMLStreamHelper { + + public static void printEvent(XMLStreamReader xmlr, boolean showEvents) { + if (showEvents) { + System.out.print("EVENT:[" + xmlr.getLocation().getLineNumber() + "][" + + xmlr.getLocation().getColumnNumber() + "] [" + getEventTypeName(xmlr.getEventType()) + + "]"); + System.out.print(" ["); + } + switch (xmlr.getEventType()) { + case XMLStreamConstants.START_ELEMENT: + System.out.print("<"); + printName(xmlr); + printNamespaces(xmlr); + printAttributes(xmlr); + System.out.print(">"); + break; + case XMLStreamConstants.END_ELEMENT: + System.out.print(""); + break; + case XMLStreamConstants.SPACE: + case XMLStreamConstants.CHARACTERS: + int start = xmlr.getTextStart(); + int length = xmlr.getTextLength(); + System.out.print(new String(xmlr.getTextCharacters(), start, length)); + break; + case XMLStreamConstants.PROCESSING_INSTRUCTION: + System.out.print(""); + break; + case XMLStreamConstants.CDATA: + System.out.print(""); + break; + case XMLStreamConstants.COMMENT: + System.out.print(""); + break; + case XMLStreamConstants.ENTITY_REFERENCE: + System.out.print(xmlr.getLocalName() + "="); + if (xmlr.hasText()) + System.out.print("[" + xmlr.getText() + "]"); + break; + case XMLStreamConstants.START_DOCUMENT: + System.out.print(""); + break; + } + System.out.println("]"); + } + + private static String getEventTypeName(int eventType) { + switch (eventType) { + case XMLStreamConstants.START_ELEMENT: + return "START_ELEMENT"; + case XMLStreamConstants.END_ELEMENT: + return "END_ELEMENT"; + case XMLStreamConstants.SPACE: + return "SPACE"; + case XMLStreamConstants.CHARACTERS: + return "CHARACTERS"; + case XMLStreamConstants.PROCESSING_INSTRUCTION: + return "PROCESSING_INSTRUCTION"; + case XMLStreamConstants.CDATA: + return "CDATA"; + case XMLStreamConstants.COMMENT: + return "COMMENT"; + case XMLStreamConstants.ENTITY_REFERENCE: + return "ENTITY_REFERENCE"; + case XMLStreamConstants.START_DOCUMENT: + return "START_DOCUMENT"; + case XMLStreamConstants.END_DOCUMENT: + return "END_DOCUMENT"; + } + return null; + } + + protected static void printName(XMLStreamReader xmlr) { + if (xmlr.hasName()) { + String prefix = xmlr.getPrefix(); + String uri = xmlr.getNamespaceURI(); + String localName = xmlr.getLocalName(); + printName(prefix, uri, localName); + } + } + + protected static void printName(String prefix, String uri, String localName) { + if (uri != null && !("".equals(uri))) + System.out.print("['" + uri + "']:"); + if (prefix != null) + System.out.print(prefix + ":"); + if (localName != null) + System.out.print(localName); + } + + protected static void printAttributes(XMLStreamReader xmlr) { + for (int i = 0; i < xmlr.getAttributeCount(); i++) { + printAttribute(xmlr, i); + } + } + + protected static void printAttribute(XMLStreamReader xmlr, int index) { + String prefix = xmlr.getAttributePrefix(index); + String namespace = xmlr.getAttributeNamespace(index); + String localName = xmlr.getAttributeLocalName(index); + String value = xmlr.getAttributeValue(index); + System.out.print(" "); + printName(prefix, namespace, localName); + System.out.print("='" + value + "'"); + } + + protected static void printNamespaces(XMLStreamReader xmlr) { + for (int i = 0; i < xmlr.getNamespaceCount(); i++) { + printNamespace(xmlr, i); + } + } + + protected static void printNamespace(XMLStreamReader xmlr, int index) { + String prefix = xmlr.getNamespacePrefix(index); + String uri = xmlr.getNamespaceURI(index); + System.out.print(" "); + if (prefix == null) + System.out.print("xmlns='" + uri + "'"); + else + System.out.print("xmlns:" + prefix + "='" + uri + "'"); + } +} diff --git a/Source/eu.modelwriter.model/.classpath b/Source/eu.modelwriter.model/.classpath new file mode 100644 index 00000000..fceb4801 --- /dev/null +++ b/Source/eu.modelwriter.model/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/Source/eu.modelwriter.model/.gitignore b/Source/eu.modelwriter.model/.gitignore new file mode 100644 index 00000000..ae3c1726 --- /dev/null +++ b/Source/eu.modelwriter.model/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/Source/eu.modelwriter.model/.project b/Source/eu.modelwriter.model/.project new file mode 100644 index 00000000..7bd1cde7 --- /dev/null +++ b/Source/eu.modelwriter.model/.project @@ -0,0 +1,17 @@ + + + eu.modelwriter.model + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/Source/eu.modelwriter.model/.settings/org.eclipse.jdt.core.prefs b/Source/eu.modelwriter.model/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..3a215370 --- /dev/null +++ b/Source/eu.modelwriter.model/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/Source/eu.modelwriter.model/src/eu/modelwriter/model/Atom.java b/Source/eu.modelwriter.model/src/eu/modelwriter/model/Atom.java new file mode 100644 index 00000000..cc1c5998 --- /dev/null +++ b/Source/eu.modelwriter.model/src/eu/modelwriter/model/Atom.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.model; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Random; + +public class Atom extends ModelElement { + private static int[] randomUniqueNumbers = + new Random().ints(0, 1000).distinct().limit(1000).toArray(); + private static int atomCount = 0; + private final LinkedHashMap tuplesIn; + + public Atom(final List relationSets, final String id, final Serializable data, + final BOUND bound) { + super(relationSets, id, data, bound); + this.tuplesIn = new LinkedHashMap(); + this.setLabel(); + } + + protected void addTuplesIn(final Tuple tuple) { + this.tuplesIn.put(tuple.getID(), tuple); + } + + protected List getTuplesIn() { + return new ArrayList(this.tuplesIn.values()); + } + + protected void setLabel() { + String label; + if (this.getRelationSets().size() == 0) { + label = "(Univ)\n"; + } else { + label = "(" + this.relationSetsToString() + ")\n"; + } + label += "[" + Atom.randomUniqueNumbers[Atom.atomCount++] + "]"; + this.setLabel(label); + } + + @Override + protected void setRelationSets(final List relationSets) { + super.setRelationSets(relationSets); + this.setLabel(); + } + + @Override + public String toString() { + this.setLabel(); + return this.getLabel(); + } +} diff --git a/Source/eu.modelwriter.model/src/eu/modelwriter/model/IModelElement.java b/Source/eu.modelwriter.model/src/eu/modelwriter/model/IModelElement.java new file mode 100644 index 00000000..0e1e3423 --- /dev/null +++ b/Source/eu.modelwriter.model/src/eu/modelwriter/model/IModelElement.java @@ -0,0 +1,13 @@ +package eu.modelwriter.model; + +import java.util.HashMap; + +public interface IModelElement { + public Object getAttribute(final String key); + + public HashMap getAttributes(); + + public void setAttribute(final String key, final Object value); + + public void setAttributes(final HashMap newAttributes); +} diff --git a/Source/eu.modelwriter.model/src/eu/modelwriter/model/ModelElement.java b/Source/eu.modelwriter.model/src/eu/modelwriter/model/ModelElement.java new file mode 100644 index 00000000..10b2a09b --- /dev/null +++ b/Source/eu.modelwriter.model/src/eu/modelwriter/model/ModelElement.java @@ -0,0 +1,135 @@ +package eu.modelwriter.model; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map.Entry; + +public class ModelElement implements IModelElement { + public static enum BOUND { + LOWER_BOUND, UPPER_BOUND, EXACT_BOUND + } + + private final static String RELATION_SETS = "RELATION_SETS"; + private final static String IDENTIFIER = "ID"; + private final static String LABEL = "LABEL"; + private final static String DATA = "DATA"; + private final static String BOUND = "BOUND"; + + private final HashMap attributes = new HashMap<>(); + + public ModelElement() {} + + protected ModelElement(final List relationSets, final String id, + final Serializable data, final BOUND bound) { + this.setRelationSets(relationSets); + this.setID(id); + this.setData(data); + this.setBound(bound); + } + + @Override + protected Object clone() { + final ModelElement cloneElement = + new ModelElement(this.getRelationSets(), this.getID(), this.getData(), this.getBound()) {}; + cloneElement.setAttributes(this.attributes); + return cloneElement; + } + + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof ModelElement)) { + return false; + } + return ((ModelElement) obj).getID().equals(this.getID()); + } + + @Override + public Object getAttribute(final String key) { + return this.attributes.get(key); + } + + @Override + public HashMap getAttributes() { + return this.attributes; + } + + public BOUND getBound() { + return (BOUND) this.getAttribute(ModelElement.BOUND); + } + + public Serializable getData() { + return (Serializable) this.getAttribute(ModelElement.DATA); + } + + public String getID() { + return (String) this.getAttribute(ModelElement.IDENTIFIER); + } + + public String getLabel() { + return (String) this.getAttribute(ModelElement.LABEL); + } + + @SuppressWarnings("unchecked") + public List getRelationSets() { + return (List) this.getAttribute(ModelElement.RELATION_SETS); + } + + public List getRelationSetsNames() { + final List relationSetsNames = new ArrayList(); + for (final RelationSet relationSet : this.getRelationSets()) { + relationSetsNames.add(relationSet.getName()); + } + return relationSetsNames; + } + + @Override + public int hashCode() { + return this.getID().hashCode(); + } + + public String relationSetsToString() { + return String.join(", ", this.getRelationSetsNames()); + } + + @Override + public void setAttribute(final String key, final Object value) { + if (key.equals(ModelElement.IDENTIFIER) || key.equals(ModelElement.LABEL) + || key.equals(ModelElement.DATA) || key.equals(ModelElement.BOUND) + || key.equals(ModelElement.RELATION_SETS)) { + return; + } + this.attributes.put(key, value); + } + + @Override + public void setAttributes(final HashMap newAttributes) { + for (final Entry entry : newAttributes.entrySet()) { + this.setAttribute(entry.getKey(), entry.getValue()); + } + } + + protected void setBound(final BOUND bound) { + this.attributes.put(ModelElement.BOUND, bound); + } + + protected void setData(final Serializable data) { + this.attributes.put(ModelElement.DATA, data); + } + + protected void setID(final String id) { + this.attributes.put(ModelElement.IDENTIFIER, id); + } + + protected void setLabel(final String label) { + this.attributes.put(ModelElement.LABEL, label); + } + + protected void setRelationSets(final List relationSets) { + this.attributes.put(ModelElement.RELATION_SETS, relationSets); + } +} diff --git a/Source/eu.modelwriter.model/src/eu/modelwriter/model/ModelManager.java b/Source/eu.modelwriter.model/src/eu/modelwriter/model/ModelManager.java new file mode 100644 index 00000000..0bce9d26 --- /dev/null +++ b/Source/eu.modelwriter.model/src/eu/modelwriter/model/ModelManager.java @@ -0,0 +1,250 @@ +package eu.modelwriter.model; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import eu.modelwriter.model.ModelElement.BOUND; +import eu.modelwriter.model.exception.InvalidArityException; +import eu.modelwriter.model.exception.NoSuchModelElementException; +import eu.modelwriter.model.observer.Subject; +import eu.modelwriter.model.observer.UpdateType; + +public class ModelManager extends Subject { + private static ModelManager manager; + private static final Universe universe = new Universe(); + + public static ModelManager getInstance() { + if (ModelManager.manager == null) { + ModelManager.manager = new ModelManager(); + } + return ModelManager.manager; + } + + public Atom addAtom(List relationSets, final Serializable data, final BOUND bound) + throws InvalidArityException { + if (relationSets == null) { + relationSets = Arrays.asList(new RelationSet[] {}); + } + + final Atom atom; + final String id = UUID.randomUUID().toString(); + atom = new Atom(relationSets, id, data, bound); + + if (relationSets.size() == 0) { + ModelManager.universe.addStrayedAtom(atom); + } else { + ModelManager.universe.addAtom(atom); + for (int i = 0; i < relationSets.size(); i++) { + final Tuple unaryTuple = this.addTuple(relationSets.get(i), data, bound, 1, atom); + atom.addTuplesIn(unaryTuple); + relationSets.get(i).addTuple(unaryTuple); + } + } + this.notifyAllObservers(atom, UpdateType.ADD_ATOM); + return atom; + } + + public RelationSet addRelationSet(final String name, final int arity) { + final RelationSet relationSet = new RelationSet(name, arity); + ModelManager.universe.addRelationSet(relationSet); + return relationSet; + } + + public Tuple addTuple(final RelationSet relationSet, final Serializable data, final BOUND bound, + final int arity, final Atom... atoms) throws InvalidArityException { + if (arity != atoms.length) { + throw new InvalidArityException(); + } + + final List relationSets; + if (relationSet == null) { + relationSets = Arrays.asList(new RelationSet[] {}); + } else { + relationSets = Arrays.asList(new RelationSet[] {relationSet}); + } + + final Tuple tuple; + final String id = UUID.randomUUID().toString(); + tuple = new Tuple(relationSet, id, data, bound, arity, atoms); + + if (relationSets.size() == 0) { + ModelManager.universe.addStrayedTuple(tuple); + } else { + ModelManager.universe.addTuple(tuple); + try { + relationSet.addTuple(tuple); + } catch (final InvalidArityException e) { + e.printStackTrace(); + } + } + this.notifyAllObservers(tuple, UpdateType.ADD_TUPLE); + return tuple; + } + + public void boundAboutToChange(final ModelElement modelElement, final String string) + throws NoSuchModelElementException { + if (modelElement instanceof Atom) { + final Atom atom = this.getAtom(modelElement.getID()); + for (final Tuple tuple : atom.getTuplesIn()) { + if (tuple.getArity() == 1) { + tuple.setBound(BOUND.valueOf(string)); + this.notifyAllObservers(tuple, UpdateType.valueOf(string)); + } + } + } else if (modelElement instanceof Tuple) { + final Tuple tuple = this.getTuple(modelElement.getID()); + tuple.setBound(BOUND.valueOf(string)); + this.notifyAllObservers(tuple, UpdateType.valueOf(string)); + } + } + + public void changeRelationSetsOfAtom(final String id, final List newRelationSetsNames) + throws InvalidArityException, NoSuchModelElementException { + final Atom atom = this.getAtom(id); + final Iterator tuplesInIter = atom.getTuplesIn().iterator(); + while (tuplesInIter.hasNext()) { + final Tuple tuple = tuplesInIter.next(); + if (tuple.getArity() == 1) { + this.removeTuple(tuple.getID()); + tuplesInIter.remove(); + } + } + final List newRelationSets = this.getRelationSets(newRelationSetsNames); + for (final RelationSet relationSet : newRelationSets) { + final Tuple tuple = this.addTuple(relationSet, atom.getData(), atom.getBound(), 1, atom); + atom.addTuplesIn(tuple); + relationSet.addTuple(tuple); + } + atom.setRelationSets(newRelationSets); + this.notifyAllObservers(atom, UpdateType.CHANGE_RELATION_SETS); + } + + public List getAllAtoms() { + return Stream.concat(ModelManager.universe.getStrayedAtoms().stream(), + ModelManager.universe.getAtoms().stream()).collect(Collectors.toList()); + } + + public List getAllRelationSetsNames() { + final List relationSetsNames = new ArrayList(); + for (final RelationSet relationSet : ModelManager.universe.getRelationSets()) { + relationSetsNames.add(relationSet.getName()); + } + return relationSetsNames; + } + + public List getAllTuples() { + return Stream.concat(ModelManager.universe.getStrayedTuples().stream(), + ModelManager.universe.getTuples().stream()).collect(Collectors.toList()); + } + + public Atom getAtom(final String id) throws NoSuchModelElementException { + if (ModelManager.universe.containsStrayedAtom(id)) { + return ModelManager.universe.getStrayedAtom(id); + } else if (ModelManager.universe.containsAtom(id)) { + return ModelManager.universe.getAtom(id); + } + throw new NoSuchModelElementException(); + } + + public List getNaryRelationSetNames() { + final List naryRelationNames = new ArrayList(); + for (final RelationSet relationSet : ModelManager.universe.getRelationSets()) { + if (relationSet.getArity() > 1) { + naryRelationNames.add(relationSet.getName()); + } + } + return naryRelationNames; + } + + public RelationSet getRelationSet(final String relationSetName) { + return ModelManager.universe.getRelationSet(relationSetName); + } + + public List getRelationSets() { + return ModelManager.universe.getRelationSets(); + } + + public List getRelationSets(final List relationSetNames) { + final List relationSets = new ArrayList(); + for (final String relationSetName : relationSetNames) { + final RelationSet relationSet = this.getRelationSet(relationSetName); + if (relationSet != null) { + relationSets.add(relationSet); + } + } + return relationSets; + } + + public Tuple getTuple(final String id) throws NoSuchModelElementException { + if (ModelManager.universe.containsStrayedTuple(id)) { + return ModelManager.universe.getStrayedTuple(id); + } else if (ModelManager.universe.containsTuple(id)) { + return ModelManager.universe.getTuple(id); + } + throw new NoSuchModelElementException(); + } + + public List getUnaryRelationSetNames() { + final List unaryRelationSetNames = new ArrayList(); + unaryRelationSetNames.add("Univ"); + for (final RelationSet relationSet : ModelManager.universe.getRelationSets()) { + if (relationSet.getArity() == 1) { + unaryRelationSetNames.add(relationSet.getName()); + } + } + return unaryRelationSetNames; + } + + public boolean removeAtom(final String id) throws NoSuchModelElementException { + boolean removed = false; + final Atom atom = this.getAtom(id); + if (atom.getRelationSets().size() == 0) { + removed = ModelManager.universe.removeStrayedAtom(id); + } else { + removed = ModelManager.universe.removeAtom(id); + for (final Tuple tupleIn : atom.getTuplesIn()) { + this.removeTuple(tupleIn.getID()); + } + } + if (removed) { + this.notifyAllObservers(atom, UpdateType.REMOVE_ATOM); + return true; + } + throw new NoSuchModelElementException(); + } + + public boolean removeModelElement(final ModelElement element) throws NoSuchModelElementException { + if (element instanceof Atom) { + return this.removeAtom(element.getID()); + } else if (element instanceof Tuple) { + return this.removeTuple(element.getID()); + } + throw new NoSuchModelElementException(); + } + + public boolean removeTuple(final String id) throws NoSuchModelElementException { + boolean removed = false; + final Tuple tuple = this.getTuple(id); + if (tuple.getRelationSets().size() == 0) { + removed = ModelManager.universe.removeStrayedTuple(id); + } else { + removed = ModelManager.universe.removeTuple(id); + final Iterator relationSetIter = tuple.getRelationSets().iterator(); + while (relationSetIter.hasNext()) { + final RelationSet relationSet = relationSetIter.next(); + relationSet.removeTuple(tuple.getID()); + } + } + if (removed) { + this.notifyAllObservers(tuple, UpdateType.REMOVE_TUPLE); + return true; + } + throw new NoSuchModelElementException(); + } +} diff --git a/Source/eu.modelwriter.model/src/eu/modelwriter/model/RelationSet.java b/Source/eu.modelwriter.model/src/eu/modelwriter/model/RelationSet.java new file mode 100644 index 00000000..16f37b03 --- /dev/null +++ b/Source/eu.modelwriter.model/src/eu/modelwriter/model/RelationSet.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.model; + +import java.util.ArrayList; +import java.util.LinkedHashMap; + +import eu.modelwriter.model.exception.InvalidArityException; + +public class RelationSet { + private final LinkedHashMap tuples; + private final String name; + private final int arity; + + public RelationSet(final String name, final int arity) { + this.name = name; + this.arity = arity; + this.tuples = new LinkedHashMap(arity); + } + + protected void addTuple(final Tuple newTuple) throws InvalidArityException { + if (newTuple.getArity() != this.arity) { + throw new InvalidArityException(); + } + this.tuples.put(newTuple.getID(), newTuple); + } + + public boolean contains(final String tupleID) { + return this.tuples.containsKey(tupleID); + } + + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof RelationSet)) { + return false; + } + return this.getName().equals(((RelationSet) obj).getName()); + } + + public int getArity() { + return this.arity; + } + + public String getName() { + return this.name; + } + + public int getTupleCount() { + return this.tuples.size(); + } + + public ArrayList getTuples() { + return new ArrayList(this.tuples.values()); + } + + @Override + public int hashCode() { + return this.getName().hashCode(); + } + + protected void removeTuple(final String id) { + this.tuples.remove(id); + } + + @Override + public String toString() { + String ts = "\n"; + for (final Tuple tuple : this.getTuples()) { + ts += tuple.toString() + "\n"; + } + return this.name + "={" + ts + "};"; + } +} diff --git a/Source/eu.modelwriter.model/src/eu/modelwriter/model/Tuple.java b/Source/eu.modelwriter.model/src/eu/modelwriter/model/Tuple.java new file mode 100644 index 00000000..b6c3fef8 --- /dev/null +++ b/Source/eu.modelwriter.model/src/eu/modelwriter/model/Tuple.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.model; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import eu.modelwriter.model.exception.InvalidArityException; + +public class Tuple extends ModelElement { + /** + * LinkedList is needed because atoms must be sorted. + */ + private final LinkedList atoms; + private final int arity; + + public Tuple(final RelationSet relationSet, final String id, final Serializable data, + final BOUND bound, final int arity, final Atom... atoms) throws InvalidArityException { + super(Arrays.asList(new RelationSet[] {relationSet}), id, data, bound); + this.setLabel(relationSet.getName()); + this.arity = arity; + this.atoms = new LinkedList(); + this.addAtoms(atoms); + } + + private void addAtoms(final Atom... atoms) throws InvalidArityException { + if (atoms == null) { + return; + } + if (atoms.length != this.arity) { + throw new InvalidArityException(); + } + for (final Atom atom : atoms) { + this.atoms.add(atom); + } + } + + public boolean contains(final String atomID) { + for (final Atom atom : this.atoms) { + if (atom.getID().equals(atomID)) { + return true; + } + } + return false; + } + + public int getArity() { + return this.arity; + } + + public Atom getAtom(final int index) { + return this.atoms.get(index); + } + + public List getAtomLabels() { + final List atomLabels = new ArrayList(); + for (final Atom atom : this.atoms) { + atomLabels.add(atom.getLabel()); + } + return atomLabels; + } + + protected List getAtoms() { + return this.atoms; + } + + public List getAtomsCopy() { + return new ArrayList(this.atoms); + } + + public String[] getTypes() { + final String[] types = new String[this.arity]; + for (int i = 0; i < this.arity; i++) { + types[i] = this.atoms.get(i).relationSetsToString(); + } + return types; + } + + @Override + public String toString() { + return this.getID() + ":(" + String.join(", ", this.getAtomLabels()) + ")"; + } +} diff --git a/Source/eu.modelwriter.model/src/eu/modelwriter/model/Universe.java b/Source/eu.modelwriter.model/src/eu/modelwriter/model/Universe.java new file mode 100644 index 00000000..59a5e930 --- /dev/null +++ b/Source/eu.modelwriter.model/src/eu/modelwriter/model/Universe.java @@ -0,0 +1,151 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.model; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; + +public class Universe { + private final LinkedHashMap strayedAtoms; + private final LinkedHashMap strayedTuples; + private final LinkedHashMap relationSets; + private final LinkedHashMap tuples; + private final LinkedHashMap atoms; + + protected Universe() { + this.strayedAtoms = new LinkedHashMap(); + this.strayedTuples = new LinkedHashMap(); + this.relationSets = new LinkedHashMap(); + this.tuples = new LinkedHashMap(); + this.atoms = new LinkedHashMap(); + } + + protected void addAtom(final Atom atom) { + this.atoms.put(atom.getID(), atom); + } + + protected void addRelationSet(final RelationSet newRelationSet) { + this.relationSets.put(newRelationSet.getName(), newRelationSet); + } + + protected void addStrayedAtom(final Atom strayedAtom) { + this.strayedAtoms.put(strayedAtom.getID(), strayedAtom); + } + + protected void addStrayedTuple(final Tuple strayedTuple) { + this.strayedTuples.put(strayedTuple.getID(), strayedTuple); + } + + protected void addTuple(final Tuple tuple) { + this.tuples.put(tuple.getID(), tuple); + } + + protected boolean containsAtom(final String id) { + return this.atoms.containsKey(id); + } + + protected boolean containsRelationSet(final String relationSetName) { + return this.relationSets.containsKey(relationSetName); + } + + protected boolean containsStrayedAtom(final String id) { + return this.strayedAtoms.containsKey(id); + } + + protected boolean containsStrayedTuple(final String id) { + return this.strayedTuples.containsKey(id); + } + + protected boolean containsTuple(final String id) { + return this.tuples.containsKey(id); + } + + protected Atom getAtom(final String id) { + return this.atoms.get(id); + } + + protected List getAtoms() { + return new ArrayList(this.atoms.values()); + } + + protected RelationSet getRelationSet(final String relationSetName) { + return this.relationSets.get(relationSetName); + } + + protected List getRelationSets() { + return new ArrayList(this.relationSets.values()); + } + + protected Atom getStrayedAtom(final String id) { + return this.strayedAtoms.get(id); + } + + protected List getStrayedAtoms() { + return new ArrayList(this.strayedAtoms.values()); + } + + protected Tuple getStrayedTuple(final String id) { + return this.strayedTuples.get(id); + } + + protected List getStrayedTuples() { + return new ArrayList(this.strayedTuples.values()); + } + + protected Tuple getTuple(final String id) { + return this.tuples.get(id); + } + + protected List getTuples() { + return new ArrayList(this.tuples.values()); + } + + protected boolean removeAtom(final String id) { + if (this.containsAtom(id)) { + this.atoms.remove(id); + return true; + } + return false; + } + + protected boolean removeRelationSet(final String relationSetName) { + if (this.containsRelationSet(relationSetName)) { + this.relationSets.remove(relationSetName); + return true; + } + return false; + } + + protected boolean removeStrayedAtom(final String id) { + if (this.containsStrayedAtom(id)) { + this.strayedAtoms.remove(id); + return true; + } + return false; + } + + protected boolean removeStrayedTuple(final String id) { + if (this.containsStrayedTuple(id)) { + this.strayedTuples.remove(id); + return true; + } + return false; + } + + protected boolean removeTuple(final String id) { + if (this.containsTuple(id)) { + this.tuples.remove(id); + return true; + } + return false; + } +} diff --git a/Source/eu.modelwriter.model/src/eu/modelwriter/model/example/ExampleGenerator.java b/Source/eu.modelwriter.model/src/eu/modelwriter/model/example/ExampleGenerator.java new file mode 100644 index 00000000..507250a8 --- /dev/null +++ b/Source/eu.modelwriter.model/src/eu/modelwriter/model/example/ExampleGenerator.java @@ -0,0 +1,144 @@ +/******************************************************************************* + * Copyright (c) 2016 UNIT Information Technologies R&D Ltd All rights reserved. This program and + * the accompanying materials are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Ferhat Erata - initial API and implementation H. Emre Kirmizi - initial API and + * implementation Serhat Celik - initial API and implementation U. Anil Ozturk - initial API and + * implementation + *******************************************************************************/ +package eu.modelwriter.model.example; + +import java.util.Arrays; + +import eu.modelwriter.model.Atom; +import eu.modelwriter.model.ModelElement; +import eu.modelwriter.model.ModelManager; +import eu.modelwriter.model.RelationSet; +import eu.modelwriter.model.exception.InvalidArityException; + +public class ExampleGenerator { + + public static ModelManager createFileSystemExample() { + final ModelManager manager = ModelManager.getInstance(); + + try { + manager.addRelationSet("Object", 1); + final RelationSet Directory = manager.addRelationSet("Directory", 1); + final RelationSet Root = manager.addRelationSet("Root", 1); + manager.addRelationSet("File", 1); + final RelationSet Word = manager.addRelationSet("Word", 1); + final RelationSet Alias = manager.addRelationSet("Alias", 1); + + final RelationSet List = manager.addRelationSet("List", 1); + final RelationSet EmptyList = manager.addRelationSet("EmptyList", 1); + + manager.addAtom(Arrays.asList(new RelationSet[] {List, EmptyList}), null, + ModelElement.BOUND.LOWER_BOUND); + + /** Atoms **/ + final Atom Root$0 = manager.addAtom(Arrays.asList(new RelationSet[] {Root}), null, + ModelElement.BOUND.LOWER_BOUND); + + final Atom Directory$0 = manager.addAtom(Arrays.asList(new RelationSet[] {Directory}), null, + ModelElement.BOUND.LOWER_BOUND); + final Atom Directory$1 = manager.addAtom(Arrays.asList(new RelationSet[] {Directory}), null, + ModelElement.BOUND.LOWER_BOUND); + + final Atom Alias$0 = manager.addAtom(Arrays.asList(new RelationSet[] {Alias}), null, + ModelElement.BOUND.LOWER_BOUND); + final Atom Alias$1 = manager.addAtom(Arrays.asList(new RelationSet[] {Alias}), null, + ModelElement.BOUND.LOWER_BOUND); + final Atom Alias$2 = manager.addAtom(Arrays.asList(new RelationSet[] {Alias}), null, + ModelElement.BOUND.LOWER_BOUND); + + final Atom Word$0 = manager.addAtom(Arrays.asList(new RelationSet[] {Word}), null, + ModelElement.BOUND.LOWER_BOUND); + final Atom Word$1 = manager.addAtom(Arrays.asList(new RelationSet[] {Word}), null, + ModelElement.BOUND.LOWER_BOUND); + final Atom Word$2 = manager.addAtom(Arrays.asList(new RelationSet[] {Word}), null, + ModelElement.BOUND.LOWER_BOUND); + final Atom Word$3 = manager.addAtom(Arrays.asList(new RelationSet[] {Word}), null, + ModelElement.BOUND.LOWER_BOUND); + + final Atom Universe$0 = manager.addAtom(null, null, ModelElement.BOUND.LOWER_BOUND); + final Atom Universe$1 = manager.addAtom(null, null, ModelElement.BOUND.LOWER_BOUND); + final Atom Universe$2 = manager.addAtom(null, null, ModelElement.BOUND.LOWER_BOUND); + /** Atoms **/ + + final RelationSet contents = manager.addRelationSet("contents", 2); + final RelationSet refs = manager.addRelationSet("refs", 2); + + manager.addTuple(contents, null, ModelElement.BOUND.LOWER_BOUND, 2, Root$0, Alias$0); + manager.addTuple(contents, null, ModelElement.BOUND.LOWER_BOUND, 2, Root$0, Directory$0); + manager.addTuple(contents, null, ModelElement.BOUND.LOWER_BOUND, 2, Root$0, Alias$1); + manager.addTuple(contents, null, ModelElement.BOUND.LOWER_BOUND, 2, Directory$0, Word$0); + manager.addTuple(contents, null, ModelElement.BOUND.LOWER_BOUND, 2, Directory$0, Directory$1); + manager.addTuple(contents, null, ModelElement.BOUND.LOWER_BOUND, 2, Directory$1, Word$1); + manager.addTuple(contents, null, ModelElement.BOUND.LOWER_BOUND, 2, Directory$1, Word$2); + manager.addTuple(contents, null, ModelElement.BOUND.LOWER_BOUND, 2, Directory$1, Word$3); + manager.addTuple(contents, null, ModelElement.BOUND.LOWER_BOUND, 2, Directory$1, Alias$2); + + manager.addTuple(refs, null, ModelElement.BOUND.LOWER_BOUND, 2, Alias$2, Word$0); + manager.addTuple(refs, null, ModelElement.BOUND.LOWER_BOUND, 2, Alias$2, Word$1); + manager.addTuple(refs, null, ModelElement.BOUND.LOWER_BOUND, 2, Alias$2, Word$2); + manager.addTuple(refs, null, ModelElement.BOUND.LOWER_BOUND, 2, Alias$2, Word$3); + + manager.addTuple(contents, null, ModelElement.BOUND.LOWER_BOUND, 2, Universe$0, Universe$1); + manager.addTuple(refs, null, ModelElement.BOUND.LOWER_BOUND, 2, Universe$2, Universe$1); + + manager.addTuple(contents, null, ModelElement.BOUND.LOWER_BOUND, 2, Word$0, Directory$0); + // refs.addTuple("",null,2,Tuple.BOUND.LOWER, Universe$1, Universe$0)); + manager.addTuple(contents, null, ModelElement.BOUND.LOWER_BOUND, 2, Universe$2, Universe$2); + } catch (final InvalidArityException e) { + e.printStackTrace(); + } + return manager; + } + + public static ModelManager createInExample() { + final ModelManager manager = ModelManager.getInstance(); + + try { + final RelationSet Ferhat = manager.addRelationSet("Ferhat", 1); + final RelationSet Anil = manager.addRelationSet("Anil", 1); + final RelationSet Serhat = manager.addRelationSet("Serhat", 1); + + final Atom Ferhat$0 = manager.addAtom(Arrays.asList(new RelationSet[] {Ferhat}), null, + ModelElement.BOUND.LOWER_BOUND); + final Atom Ferhat$1 = manager.addAtom(Arrays.asList(new RelationSet[] {Ferhat}), null, + ModelElement.BOUND.LOWER_BOUND); + final Atom Ferhat$2 = manager.addAtom(Arrays.asList(new RelationSet[] {Ferhat}), null, + ModelElement.BOUND.LOWER_BOUND); + + final Atom Anil$0 = manager.addAtom(Arrays.asList(new RelationSet[] {Anil}), null, + ModelElement.BOUND.LOWER_BOUND); + + manager.addAtom(Arrays.asList(new RelationSet[] {Serhat}), null, + ModelElement.BOUND.LOWER_BOUND); + manager.addAtom(Arrays.asList(new RelationSet[] {Serhat}), null, + ModelElement.BOUND.LOWER_BOUND); + manager.addAtom(Arrays.asList(new RelationSet[] {Serhat}), null, + ModelElement.BOUND.LOWER_BOUND); + manager.addAtom(Arrays.asList(new RelationSet[] {Serhat}), null, + ModelElement.BOUND.LOWER_BOUND); + final Atom Serhat$4 = manager.addAtom(Arrays.asList(new RelationSet[] {Serhat}), null, + ModelElement.BOUND.LOWER_BOUND); + final Atom Serhat$5 = manager.addAtom(Arrays.asList(new RelationSet[] {Serhat}), null, + ModelElement.BOUND.LOWER_BOUND); + final Atom Serhat$6 = manager.addAtom(Arrays.asList(new RelationSet[] {Serhat}), null, + ModelElement.BOUND.LOWER_BOUND); + + final RelationSet emre = manager.addRelationSet("emre", 2); + + manager.addTuple(emre, null, ModelElement.BOUND.LOWER_BOUND, 2, Ferhat$0, Serhat$6); + manager.addTuple(emre, null, ModelElement.BOUND.LOWER_BOUND, 2, Ferhat$1, Serhat$5); + manager.addTuple(emre, null, ModelElement.BOUND.LOWER_BOUND, 2, Ferhat$2, Serhat$4); + manager.addTuple(emre, null, ModelElement.BOUND.LOWER_BOUND, 2, Ferhat$0, Anil$0); + } catch (final InvalidArityException e) { + e.printStackTrace(); + } + return manager; + } +} diff --git a/Source/eu.modelwriter.model/src/eu/modelwriter/model/exception/InvalidArityException.java b/Source/eu.modelwriter.model/src/eu/modelwriter/model/exception/InvalidArityException.java new file mode 100644 index 00000000..d395ec0d --- /dev/null +++ b/Source/eu.modelwriter.model/src/eu/modelwriter/model/exception/InvalidArityException.java @@ -0,0 +1,11 @@ +package eu.modelwriter.model.exception; + +public class InvalidArityException extends Exception { + + private static final long serialVersionUID = 8892715346352339032L; + + @Override + public String getMessage() { + return "Tuple arity is not equal with Relation arity."; + } +} diff --git a/Source/eu.modelwriter.model/src/eu/modelwriter/model/exception/NoSuchModelElementException.java b/Source/eu.modelwriter.model/src/eu/modelwriter/model/exception/NoSuchModelElementException.java new file mode 100644 index 00000000..4b82befa --- /dev/null +++ b/Source/eu.modelwriter.model/src/eu/modelwriter/model/exception/NoSuchModelElementException.java @@ -0,0 +1,11 @@ +package eu.modelwriter.model.exception; + +public class NoSuchModelElementException extends Exception { + + private static final long serialVersionUID = 13053687922656638L; + + @Override + public String getMessage() { + return "Element cannot be found in the universe."; + } +} diff --git a/Source/eu.modelwriter.model/src/eu/modelwriter/model/observer/Observer.java b/Source/eu.modelwriter.model/src/eu/modelwriter/model/observer/Observer.java new file mode 100644 index 00000000..a2c6e030 --- /dev/null +++ b/Source/eu.modelwriter.model/src/eu/modelwriter/model/observer/Observer.java @@ -0,0 +1,5 @@ +package eu.modelwriter.model.observer; + +public interface Observer { + public void update(Object updatedObject, Object updateType); +} diff --git a/Source/eu.modelwriter.model/src/eu/modelwriter/model/observer/Subject.java b/Source/eu.modelwriter.model/src/eu/modelwriter/model/observer/Subject.java new file mode 100644 index 00000000..8c6fe1ac --- /dev/null +++ b/Source/eu.modelwriter.model/src/eu/modelwriter/model/observer/Subject.java @@ -0,0 +1,31 @@ +package eu.modelwriter.model.observer; + +import java.util.ArrayList; +import java.util.List; + +public class Subject { + private final List observers = new ArrayList(); + + public void addObserver(final Observer o) { + if (o == null) { + throw new NullPointerException(); + } + if (!this.observers.contains(o)) { + this.observers.add(o); + } + } + + public void clearObservers() { + this.observers.clear(); + } + + public void deleteObserver(final Observer o) { + this.observers.remove(o); + } + + public void notifyAllObservers(final Object updatedObject, final Object updateType) { + for (int i = this.observers.size() - 1; i >= 0; i--) { + this.observers.get(i).update(updatedObject, updateType); + } + } +} diff --git a/Source/eu.modelwriter.model/src/eu/modelwriter/model/observer/UpdateType.java b/Source/eu.modelwriter.model/src/eu/modelwriter/model/observer/UpdateType.java new file mode 100644 index 00000000..8796122e --- /dev/null +++ b/Source/eu.modelwriter.model/src/eu/modelwriter/model/observer/UpdateType.java @@ -0,0 +1,5 @@ +package eu.modelwriter.model.observer; + +public enum UpdateType { + ADD_RELATION, REMOVE_RELATION, ADD_TUPLE, REMOVE_TUPLE, ADD_ATOM, REMOVE_ATOM, UPPER_BOUND, LOWER_BOUND,CHANGE_RELATION_SETS; +} diff --git a/Source/eu.modelwriter.projectmanagement/.classpath b/Source/eu.modelwriter.projectmanagement/.classpath new file mode 100644 index 00000000..9815911d --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/.classpath @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.projectmanagement/.gitignore b/Source/eu.modelwriter.projectmanagement/.gitignore new file mode 100644 index 00000000..ae3c1726 --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/Source/eu.modelwriter.projectmanagement/.project b/Source/eu.modelwriter.projectmanagement/.project new file mode 100644 index 00000000..4f6a9c7c --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/.project @@ -0,0 +1,28 @@ + + + eu.modelwriter.projectmanagement + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/Source/eu.modelwriter.projectmanagement/.settings/org.eclipse.jdt.core.prefs b/Source/eu.modelwriter.projectmanagement/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..0c68a61d --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/Source/eu.modelwriter.projectmanagement/META-INF/MANIFEST.MF b/Source/eu.modelwriter.projectmanagement/META-INF/MANIFEST.MF new file mode 100644 index 00000000..ff6110f0 --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/META-INF/MANIFEST.MF @@ -0,0 +1,20 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: ModelWriter Project Management +Bundle-SymbolicName: eu.modelwriter.projectmanagement;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: eu.modelwriter.projectmanagement.Activator +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.jface, + org.eclipse.egit.github.core;bundle-version="4.0.0", + eu.modelwriter.marker.command;bundle-version="1.0.0" +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ActivationPolicy: lazy +Bundle-ClassPath: ., + lib/dom4j-1.6.1.jar, + lib/poi-3.9-20121203.jar, + lib/poi-ooxml-3.9-20121203.jar, + lib/poi-ooxml-schemas-3.9-20121203.jar, + lib/xmlbeans-2.3.0.jar +Import-Package: org.eclipse.core.resources diff --git a/Source/eu.modelwriter.projectmanagement/build.properties b/Source/eu.modelwriter.projectmanagement/build.properties new file mode 100644 index 00000000..1f34622b --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/build.properties @@ -0,0 +1,12 @@ +source.. = src/ +output.. = bin/ +bin.includes = plugin.xml,\ + META-INF/,\ + .,\ + icons/,\ + docs/,\ + lib/dom4j-1.6.1.jar,\ + lib/poi-3.9-20121203.jar,\ + lib/poi-ooxml-3.9-20121203.jar,\ + lib/poi-ooxml-schemas-3.9-20121203.jar,\ + lib/xmlbeans-2.3.0.jar diff --git a/Source/eu.modelwriter.projectmanagement/docs/D1.5.1 Minutes of the User Requirements Review meeting.docx b/Source/eu.modelwriter.projectmanagement/docs/D1.5.1 Minutes of the User Requirements Review meeting.docx new file mode 100644 index 00000000..baee3f8d Binary files /dev/null and b/Source/eu.modelwriter.projectmanagement/docs/D1.5.1 Minutes of the User Requirements Review meeting.docx differ diff --git a/Source/eu.modelwriter.projectmanagement/docs/D1.5.2 User Requirements Document (URD).docx b/Source/eu.modelwriter.projectmanagement/docs/D1.5.2 User Requirements Document (URD).docx new file mode 100644 index 00000000..558c72b3 Binary files /dev/null and b/Source/eu.modelwriter.projectmanagement/docs/D1.5.2 User Requirements Document (URD).docx differ diff --git a/Source/eu.modelwriter.projectmanagement/docs/D1.6.1 Minutes of the Software Requirements Review meeting.docx b/Source/eu.modelwriter.projectmanagement/docs/D1.6.1 Minutes of the Software Requirements Review meeting.docx new file mode 100644 index 00000000..23a7b039 Binary files /dev/null and b/Source/eu.modelwriter.projectmanagement/docs/D1.6.1 Minutes of the Software Requirements Review meeting.docx differ diff --git a/Source/eu.modelwriter.projectmanagement/docs/D1.6.2 Software Requirements Document (SRD).docx b/Source/eu.modelwriter.projectmanagement/docs/D1.6.2 Software Requirements Document (SRD).docx new file mode 100644 index 00000000..ca821828 Binary files /dev/null and b/Source/eu.modelwriter.projectmanagement/docs/D1.6.2 Software Requirements Document (SRD).docx differ diff --git a/Source/eu.modelwriter.projectmanagement/docs/Deliverables - Changes.md b/Source/eu.modelwriter.projectmanagement/docs/Deliverables - Changes.md new file mode 100644 index 00000000..abe9062e --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/docs/Deliverables - Changes.md @@ -0,0 +1,133 @@ +| Origin | Month | Deliverable | Type | Access | Leader +|:-------- |:----- |:----------- |:------- |:------- |:------- +| D1.1.1 | [M9] | D1.1.1 Evaluation Methods & Tools | Doc. | Public | HISBIM +| D1.2.1 | [M13] | D1.2.1 Industrial Use Cases for Belgian Consortium | Doc. | Public | SOGETI +| D1.2.2 | [M13] | D1.2.2 Corpus for Belgian Use Cases (Public) | SW | Public | SOGETI +| D1.2.3 | [M13] | D1.2.3 Corpus for Belgian Use Cases (Private) | SW | Private | SOGETI +| D1.3.1 | [M8] | D1.3.1 Industrial Use Cases for French Consortium | Doc. | Public | AIRBUS +| D1.3.2 | [M8] | D1.3.2 Corpus for French Use Cases (Public) | SW | Public | AIRBUS +| D1.3.3 | [M8] | D1.3.3 Corpus for French Use Cases (Private) | SW | Private | AIRBUS +| D1.4.1 | [M8] | D1.4.1 Industrial Use Cases for Turkish Consortium | Doc. | Public | MANTIS +| D1.4.2 | [M8] | D1.4.2 Corpus for Turkish Use Cases (Public) | SW | Public | MANTIS +| D1.4.3 | [M8] | D1.4.3 Corpus for Turkish Use Cases (Private) | SW | Private | MANTIS +| D1.6.1 | [M8] | D1.5.1 Minutes of the User Requirements Review meeting | Doc. | Public | HISBIM +| D1.5.1 | [M8] | D1.5.2 User Requirements Document (URD) | Doc. | Public | UNIT +| D1.8.1 | [M9] | D1.6.1 Minutes of the Software Requirements Review meeting | Doc. | Public | AIRBUS +| D1.7.1 | [M9] | D1.6.2 Software Requirements Document (SRD) | Doc. | Public | KOCSISTEM +| D1.9.1-1 | [M17] | D1.7.1-1 Annual Product Owner Review - 1 | Doc. | Public | AIRBUS +| D1.9.1-2 | [M27] | D1.7.1-2 Annual Product Owner Review - 2 | Doc. | Public | AIRBUS +| D1.9.1-3 | [M37] | D1.7.1-3 Annual Product Owner Review - 3 | Doc. | Public | AIRBUS +| D1.10.1 | [M9] | D1.8.1 Technical Risk Assessment Document | Doc. | Public | OBEO +| D2.1.1 | [M10] | D2.1.1 Software Requirements - Evaluation of the NLP requirements set by the use cases | Doc. | Public | LORIA +| D2.4.1 | [M12] | D2.1.2 Corpora (Text, Knowledge, Bi-Texts) and Documentation | Doc. | Public | LORIA +| D2.2.1 | [M15] | D2.2.1 Overview and comparison of existing deep semantic parsers | Doc. | Public | LORIA +| D2.3.1 | [M8] | D2.3.1 Overview and comparison of existing generators | Doc. | Public | LORIA +| D2.5.1 | [M14] | D2.4.1 Specification of the Knowledge Representation Language| Doc. | Public | LORIA +| D2.5.2-1 | [M18] | D2.5.1-1 Semantic Parser and Documentation (release 1) | SW | Public | LORIA +| D2.5.2-2 | [M27] | D2.5.1-2 Semantic Parser and Documentation (release 2) | SW | Public | LORIA +| D2.5.2-3 | [M33] | D2.5.1-3 Semantic Parser and Documentation (release 3) | SW | Public | LORIA +| D2.5.3-1 | [M16] | D2.5.2-1 Natural Language Generator and Documentation (release 1) | SW | Public | LORIA +| D2.5.3-2 | [M22] | D2.5.2-2 Natural Language Generator and Documentation (release 2) | SW | Public | LORIA +| D2.5.3-3 | [M30] | D2.5.2-3 Natural Language Generator and Documentation (release 3) | SW | Public | LORIA +| D3.1.1 | [M8] | D3.1.1 Review of model-to-model transformation approaches and technologies | Doc. | Public | UNIT +| D3.2.1 | [M8] | D3.2.1 M2M Transformation Framework architectural design document | Doc. | Public | UNIT +| D3.3.1 | [M5] | DELETE | Doc. | Public | UNIT +| D3.3.2-1 | [M10] | D3.3.1-1 Transformation Manager component (release 1) | SW | Public | UNIT +| D3.3.2-2 | [M22] | D3.3.1-2 Transformation Manager component (release 2) | SW | Public | UNIT +| D3.3.2-3 | [M32] | D3.3.1-3 Transformation Manager component (release 3) | SW | Public | UNIT +| D3.4.1 | [M6] | DELETE | Doc. | Public | UNIT +| D3.4.2-1 | [M10] | D3.4.1-1 Configuration Manager component (release 1) | SW | Public | UNIT +| D3.4.2-2 | [M22] | D3.4.1-2 Configuration Manager component (release 2) | SW | Public | UNIT +| D3.4.2-3 | [M32] | D3.4.1-3 Configuration Manager component (release 3) | SW | Public | UNIT +| D3.5.1 | [M7] | DELETE | Doc. | Public | UNIT +| D3.5.2-1 | [M10] | D3.5.1-1 Traceability Manager component (release 1) | SW | Public | UNIT +| D3.5.2-2 | [M22] | D3.5.1-2 Traceability Manager component (release 2) | SW | Public | UNIT +| D3.5.2-3 | [M32] | D3.5.1-3 Traceability Manager component (release 3) | SW | Public | UNIT +| D3.6.1 | [M8] | DELETE | Doc. | Public | UNIT +| D3.6.2-1 | [M10] | D3.6.1-1 Synchronization Manager component (release 1) | SW | Public | UNIT +| D3.6.2-2 | [M22] | D3.6.1-2 Synchronization Manager component (release 2) | SW | Public | UNIT +| D3.6.2-3 | [M32] | D3.6.1-3 Synchronization Manager component (release 3) | SW | Public | UNIT +| D3.7.1 | [M20] | D3.7.1 Model-to-model transformations (from user-visible models to KB-stored models) design document | SW | Public | MANTIS +| D3.8.1-1 | [M13] | D3.8.1-1 Source code of each m2m transformation (release 1) | SW | Public | UNIT +| D3.8.1-2 | [M23] | D3.8.1-2 Source code of each m2m transformation (release 2) | SW | Public | UNIT +| D3.8.1-3 | [M33] | D3.8.1-3 Source code of each m2m transformation (release 3) | SW | Public | UNIT +| D3.9.1 | [M34] | D3.9.1 Test-plan for the M2M Transformation Framework | Doc. | Public | MANTIS +| D3.9.2 | [M35] | D3.9.2 Field experiment concerning ModelWriter model transformations | SW | Public | UNIT +| D4.1.1 | [M9] | D4.1.1 Knowledge Base Design document | Doc. | Public | MANTIS +| D4.2.1 | [M9] | D4.2.1 Interface Control Document (ICD) | Doc. | Public | KOCSISTEM +| D4.3.1-1 | [M13] | D4.3.1-1 Knowledge Base (release 1) | SW | Public | MANTIS +| D4.3.1-2 | [M23] | D4.3.1-2 Knowledge Base (release 2) | SW | Public | MANTIS +| D4.3.1-3 | [M33] | D4.3.1-3 Knowledge Base (release 3) | SW | Public | MANTIS +| D4.4.1 | [M35] | D4.4.1 Technical Note for ModelWriter-assisted Quality Review of Requirements | Doc. | Public | MANTIS +| D4.4.2 | [M35] | D4.4.2 Proof-of-concept model checker | SW | Public | MANTIS +| D4.5.1 | [M13] | D4.5.1 Technical Note for KB serialization and reuse | Doc. | Public | MANTIS +| D4.6.1 | [M20] | D4.6.1 Technical Note for ModelWriter-assisted Comparison of 2 Documents | Doc. | Public | OBEO +| D4.6.2-1 | [M13] | D4.6.2-1 Proof-of-concept semantic comparison engine (release 1) | SW | Public | OBEO +| D4.6.2-2 | [M23] | D4.6.2-2 Proof-of-concept semantic comparison engine (release 2) | SW | Public | OBEO +| D4.6.2-3 | [M33] | D4.6.2-3 Proof-of-concept semantic comparison engine (release 3) | SW | Public | OBEO +| D4.7.1 | [M14] | D4.7.1 Future ModelWriter-Enabled Use Cases | Doc. | Public | MANTIS +| D5.1.1-1 | [M13] | DELETE | Doc. | Private | UNIT +| D5.1.1-2 | [M25] | DELETE | Doc. | Private | UNIT +| D5.1.1-3 | [M37] | DELETE | Doc. | Private | UNIT +| D5.2.1 | [M2] | DELETE | Doc. | Public | UNIT +| D5.2.1-1 | [M12] | DELETE | Doc. | Public | UNIT +| D5.2.1-2 | [M24] | DELETE | Doc. | Public | UNIT +| D5.4.1 | [M4] | DELETE | Doc. | Public | UNIT +| D5.5.1 | [M4] | DELETE | Doc. | Public | UNIT +| D5.6.1 | [M4] | DELETE | Doc. | Public | UNIT +| D5.7.1 | [M4] | DELETE | Doc. | Public | UNIT +| D5.8.1 | [37] | DELETE | Doc. | Public | UNIT +| D5.8.2 | [37] | DELETE | Doc. | Public | UNIT +| NEW | [M1] | D5.1.1 Project Kick-Off Report and Project Management Plan | Doc. | Public | UNIT +| NEW | [M8] | D5.2.1 Project Progress Report (first half year) | Doc. | Private | UNIT +| NEW | [M13] | D5.2.2 Project Progress Report (second half year) | Doc. | Private | UNIT +| NEW | [M19] | D5.2.3 Project Progress Report (third half year) | Doc. | Private | UNIT +| NEW | [M25] | D5.2.4 Project Progress Report (fourth half year) | Doc. | Private | UNIT +| NEW | [M31] | D5.2.5 Project Progress Report (fifth half year) | Doc. | Private | UNIT +| NEW | [M37] | D5.3.1 Final Project Report | Doc. | Private | UNIT +| NEW | [M37] | D5.3.2 Updated State-of-the-art (Public Deliverable) | Doc. | Public | UNIT +| D6.1.1 | [M7] | D6.1.1 Prototype Core ModelWriter | SW | Public | OBEO +| D6.2.1 | [M8] | D6.2.1 Architectural Design Document (ADD) | Doc. | Public | OBEO +| D6.3.1-1 | [M10] | D6.3.1-1 Writer enhancements (release 1) | SW | Public | KOCSISTEM +| D6.3.1-2 | [M20] | D6.3.1-2 Writer enhancements (release 2) | SW | Public | KOCSISTEM +| D6.3.1-3 | [M34] | D6.3.1-3 Writer enhancements (release 3) | SW | Public | KOCSISTEM +| D6.4.1 | [M9] | D6.4.1 Ergonomics Guidelines document for the Writer Part | Doc. | Public | OBEO +| D6.4.2-1 | [M12] | D6.4.2-1 User Interface for the Writer part (release 1) | SW | Public | OBEO +| D6.4.2-2 | [M20] | D6.4.2-2 User Interface for the Writer part (release 2) | SW | Public | OBEO +| D6.4.2-3 | [M34] | D6.4.2-3 User Interface for the Writer part (release 3) | SW | Public | OBEO +| D6.4.3-1 | [M12] | D6.4.3-1 IDE-integrated User Interface to handle Sync issues (major release 1) | SW | Public | OBEO +| D6.4.3-2 | [M20] | D6.4.3-2 IDE-integrated User Interface to handle Sync issues (major release 2) | SW | Public | OBEO +| D6.4.3-3 | [M34] | D6.4.3-3 IDE-integrated User Interface to handle Sync issues (major release 3) | SW | Public | OBEO +| D6.5.1-1 | [M12] | D6.5.1-1 Acceptance Test Plan (release 1) | Doc. | Public | KOCSISTEM +| D6.5.1-2 | [M20] | D6.5.1-2 Acceptance Test Plan (release 2) | Doc. | Public | KOCSISTEM +| D6.5.1-3 | [M34] | D6.5.1-3 Acceptance Test Plan (release 3) | Doc. | Public | KOCSISTEM +| D6.5.2-1 | [M12] | D6.5.2-1 Automated Acceptance Tests (release 1) | SW | Public | KOCSISTEM +| D6.5.2-2 | [M20] | D6.5.2-2 Automated Acceptance Tests (release 2) | SW | Public | KOCSISTEM +| D6.5.2-3 | [M34] | D6.5.2-3 Automated Acceptance Tests (release 3) | SW | Public | KOCSISTEM +| D6.6.1-1 | [M14] | D6.6.1-1 Acceptance Test Procedures (release 1) | Doc. | Public | KOCSISTEM +| D6.6.1-2 | [M20] | D6.6.1-2 Acceptance Test Procedures (release 2) | Doc. | Public | KOCSISTEM +| D6.6.1-3 | [M34] | D6.6.1-3 Acceptance Test Procedures (release 3) | Doc. | Public | KOCSISTEM +| D6.7.1-1 | [M16] | D6.7.1-1 ModelWriter major release (release 1) | SW | Public | OBEO +| D6.7.1-2 | [M26] | D6.7.1-2 ModelWriter major release (release 2) | SW | Public | OBEO +| D6.7.1-3 | [M36] | D6.7.1-3 ModelWriter major release (release 3) | SW | Public | OBEO +| D2.5.4-1 | [M18] | D6.7.2-1 WP2 Integration in ModelWriter and Documentation (release 1) | SW | Public | OBEO +| D2.5.4-2 | [M26] | D6.7.2-2 WP2 Integration in ModelWriter and Documentation (release 2) | SW | Public | OBEO +| D2.5.4-3 | [M31] | D6.7.2-3 WP2 Integration in ModelWriter and Documentation (release 3) | SW | Public | OBEO +| D6.8.1-1 | [M17] | D6.8.1-1 Evaluation report (release 1) | Doc. | Public | KOCSISTEM +| D6.8.1-2 | [M27] | D6.8.1-2 Evaluation report (release 2) | Doc. | Public | KOCSISTEM +| D6.8.1-3 | [M37] | D6.8.1-3 Evaluation report (release 3) | Doc. | Public | KOCSISTEM +| D7.1.1 | [M6] | D7.1.1 Dissemination Plan | Doc. | Public | OBEO +| D7.2.1-1 | [M8] | D7.2.1-1 Exploitation and Marketing Plan (release 1) | Doc. | Public | AIRBUS +| D7.2.1-2 | [M22] | D7.2.1-2 Exploitation and Marketing Plan (release 2) | Doc. | Public | AIRBUS +| D7.2.1-3 | [M34] | D7.2.1-3 Exploitation and Marketing Plan (release 3) | Doc. | Public | AIRBUS +| D7.2.2 | [M7] | DELETE | Doc. | Public | AIRBUS +| D7.2.3 | [M34] | D7.2.2 Roadmap for future exploitation and pre-competition survey| Doc. | Public | HISBIM +| D7.3.1 | [M31] | D7.3.1 Newsletter - International Conference Announcement | Doc. | Public | UNIT +| D7.4.1 | [M8] | D7.4.1 ModelWriter-ITEA website | SW | Public | OBEO +| D7.5.1 | [M10] | D7.5.1 Technical-oriented talk about the principles and benefits of the ModelWriter-ITEA approach and tooling | Doc. | Public | OBEO +| D7.5.2 | [M10] | D7.5.2 Research-oriented talk about the principles and benefits of the ModelWriter-ITEA approach and tooling | Doc. | Public | UNIT +| D7.6.1 | [M10] | DELETE | SW | Public | UNIT +| D7.6.2 | [M10] | D7.6.1 ModelWriter-ITEA's LinkedIn Group | SW | Public | UNIT +| D7.6.3 | [M10] | D7.6.2 ModelWriter-ITEA's Twitter Group | SW | Public | UNIT +| D7.6.4 | [M10] | DELETE | SW | Public | UNIT +| D7.7.1 | [M34] | D7.7.1 ModelWriter and standardization activities | SW | Public | LORIA diff --git a/Source/eu.modelwriter.projectmanagement/docs/Deliverables - Updated.md b/Source/eu.modelwriter.projectmanagement/docs/Deliverables - Updated.md new file mode 100644 index 00000000..7d598fa2 --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/docs/Deliverables - Updated.md @@ -0,0 +1,114 @@ +| Month | Deliverable | Type | Access | Leader +|:----- |:----------- |:------- |:------- |:------- +| [M9] | D1.1.1 Evaluation Methods & Tools | Doc. | Public | HISBIM +| [M13] | D1.2.1 Industrial Use Cases for Belgian Consortium | Doc. | Public | SOGETI +| [M13] | D1.2.2 Corpus for Belgian Use Cases (public) | SW | Public | SOGETI +| [M13] | D1.2.3 Corpus for Belgian Use Cases (Private) | SW | Private | SOGETI +| [M8] | D1.3.1 Industrial Use Cases for French Consortium | Doc. | Public | AIRBUS +| [M8] | D1.3.2 Corpus for French Use Cases (public) | SW | Public | AIRBUS +| [M8] | D1.3.3 Corpus for French Use Cases (Private) | SW | Private | AIRBUS +| [M8] | D1.4.1 Industrial Use Cases for Turkish Consortium | Doc. | Public | MANTIS +| [M8] | D1.4.2 Corpus for Turkish Use Cases (public) | SW | Public | MANTIS +| [M8] | D1.4.3 Corpus for Turkish Use Cases (Private) | SW | Private | MANTIS +| [M8] | D1.5.1 Minutes of the User Requirements Review meeting | Doc. | Public | HISBIM +| [M8] | D1.5.2 User Requirements Document (URD) | Doc. | Public | UNIT +| [M9] | D1.6.1 Minutes of the Software Requirements Review meeting | Doc. | Public | AIRBUS +| [M9] | D1.6.2 Software Requirements Document (SRD) | Doc. | Public | KOCSISTEM +| [M17] | D1.7.1-1 Annual Product Owner Review - 1 | Doc. | Public | AIRBUS +| [M27] | D1.7.1-2 Annual Product Owner Review - 2 | Doc. | Public | AIRBUS +| [M37] | D1.7.1-3 Annual Product Owner Review - 3 | Doc. | Public | AIRBUS +| [M9] | D1.8.1 Technical Risk Assessment Document | Doc. | Public | OBEO +| [M10] | D2.1.1 Software Requirements - Evaluation of the NLP requirements set by the use cases | Doc. | Public | LORIA +| [M12] | D2.1.2 Corpora (Text, Knowledge, Bi-Texts) and Documentation | Doc. | Public | LORIA +| [M15] | D2.2.1 Overview and comparison of existing deep semantic parsers | Doc. | Public | LORIA +| [M8] | D2.3.1 Overview and comparison of existing generators | Doc. | Public | LORIA +| [M14] | D2.4.1 Specification of the Knowledge Representation Language| Doc. | Public | LORIA +| [M18] | D2.5.1-1 Semantic Parser and Documentation (release 1) | SW | Public | LORIA +| [M27] | D2.5.1-2 Semantic Parser and Documentation (release 2) | SW | Public | LORIA +| [M33] | D2.5.1-3 Semantic Parser and Documentation (release 3) | SW | Public | LORIA +| [M16] | D2.5.2-1 Natural Language Generator and Documentation (release 1) | SW | Public | LORIA +| [M22] | D2.5.2-2 Natural Language Generator and Documentation (release 2) | SW | Public | LORIA +| [M30] | D2.5.2-3 Natural Language Generator and Documentation (release 3) | SW | Public | LORIA +| [M8] | D3.1.1 Review of model-to-model transformation approaches and technologies | Doc. | Public | UNIT +| [M8] | D3.2.1 M2M Transformation Framework architectural design document | Doc. | Public | UNIT +| [M10] | D3.3.1-1 Transformation Manager component (release 1) | SW | Public | UNIT +| [M22] | D3.3.1-2 Transformation Manager component (release 2) | SW | Public | UNIT +| [M32] | D3.3.1-3 Transformation Manager component (release 3) | SW | Public | UNIT +| [M10] | D3.4.1-1 Configuration Manager component (release 1) | SW | Public | UNIT +| [M22] | D3.4.1-2 Configuration Manager component (release 2) | SW | Public | UNIT +| [M32] | D3.4.1-3 Configuration Manager component (release 3) | SW | Public | UNIT +| [M10] | D3.5.1-1 Traceability Manager component (release 1) | SW | Public | UNIT +| [M22] | D3.5.1-2 Traceability Manager component (release 2) | SW | Public | UNIT +| [M32] | D3.5.1-3 Traceability Manager component (release 3) | SW | Public | UNIT +| [M10] | D3.6.1-1 Synchronization Manager component (release 1) | SW | Public | UNIT +| [M22] | D3.6.1-2 Synchronization Manager component (release 2) | SW | Public | UNIT +| [M32] | D3.6.1-3 Synchronization Manager component (release 3) | SW | Public | UNIT +| [M20] | D3.7.1 Model-to-model transformations (from user-visible models to KB-stored models) design document | SW | Public | MANTIS +| [M13] | D3.8.1-1 Source code of each m2m transformation (release 1) | SW | Public | UNIT +| [M23] | D3.8.1-3 Source code of each m2m transformation (release 2) | SW | Public | UNIT +| [M33] | D3.8.1-3 Source code of each m2m transformation (release 3) | SW | Public | UNIT +| [M34] | D3.9.1 Test-plan for the M2M Transformation Framework | Doc. | Public | MANTIS +| [M35] | D3.9.2 Field experiment concerning ModelWriter model transformations | SW | Public | UNIT +| [M9] | D4.1.1 Knowledge Base Design document | Doc. | Public | MANTIS +| [M9] | D4.2.1 Interface Control Document (ICD) | Doc. | Public | KOCSISTEM +| [M13] | D4.3.1-1 Knowledge Base (release 1) | SW | Public | MANTIS +| [M23] | D4.3.1-2 Knowledge Base (release 2) | SW | Public | MANTIS +| [M33] | D4.3.1-3 Knowledge Base (release 3) | SW | Public | MANTIS +| [M35] | D4.4.1 Technical Note for ModelWriter-assisted Quality Review of Requirements | Doc. | Public | MANTIS +| [M35] | D4.4.2 Proof-of-concept model checker | SW | Public | MANTIS +| [M13] | D4.5.1 Technical Note for KB serialization and reuse | Doc. | Public | MANTIS +| [M20] | D4.6.1 Technical Note for ModelWriter-assisted Comparison of 2 Documents | Doc. | Public | OBEO +| [M13] | D4.6.2-1 Proof-of-concept semantic comparison engine (release 1) | SW | Public | OBEO +| [M23] | D4.6.2-2 Proof-of-concept semantic comparison engine (release 2) | SW | Public | OBEO +| [M33] | D4.6.2-3 Proof-of-concept semantic comparison engine (release 3) | SW | Public | OBEO +| [M14] | D4.7.1 Future ModelWriter-Enabled Use Cases | Doc. | Public | MANTIS +| [M1] | D5.1.1 Project Kick-Off Report and Project Management Plan | Doc. | Public | UNIT +| [M8] | D5.2.1 Project Progress Report (first half year) | Doc. | Private | UNIT +| [M13] | D5.2.2 Project Progress Report (second half year) | Doc. | Private | UNIT +| [M19] | D5.2.3 Project Progress Report (third half year) | Doc. | Private | UNIT +| [M25] | D5.2.4 Project Progress Report (fourth half year) | Doc. | Private | UNIT +| [M31] | D5.2.5 Project Progress Report (fifth half year) | Doc. | Private | UNIT +| [M37] | D5.3.1 Final Project Report | Doc. | Private | UNIT +| [M37] | D5.3.2 Updated State-of-the-art (Public Deliverable) | Doc. | Public | UNIT +| [M7] | D6.1.1 Prototype Core ModelWriter | SW | Public | OBEO +| [M8] | D6.2.1 Architectural Design Document (ADD) | Doc. | Public | OBEO +| [M10] | D6.3.1-1 Writer enhancements (release 1) | SW | Public | KOCSISTEM +| [M20] | D6.3.1-2 Writer enhancements (release 2) | SW | Public | KOCSISTEM +| [M34] | D6.3.1-3 Writer enhancements (release 3) | SW | Public | KOCSISTEM +| [M9] | D6.4.1 Ergonomics Guidelines document for the Writer Part | Doc. | Public | OBEO +| [M12] | D6.4.2-1 User Interface for the Writer part (release 1) | SW | Public | OBEO +| [M20] | D6.4.2-2 User Interface for the Writer part (release 2) | SW | Public | OBEO +| [M34] | D6.4.2-3 User Interface for the Writer part (release 3) | SW | Public | OBEO +| [M12] | D6.4.3-1 IDE-integrated User Interface to handle Sync issues (major release 1) | SW | Public | OBEO +| [M20] | D6.4.3-2 IDE-integrated User Interface to handle Sync issues (major release 2) | SW | Public | OBEO +| [M34] | D6.4.3-3 IDE-integrated User Interface to handle Sync issues (major release 3) | SW | Public | OBEO +| [M12] | D6.5.1-1 Acceptance Test Plan (release 1) | Doc. | Public | KOCSISTEM +| [M20] | D6.5.1-2 Acceptance Test Plan (release 2) | Doc. | Public | KOCSISTEM +| [M34] | D6.5.1-3 Acceptance Test Plan (release 3) | Doc. | Public | KOCSISTEM +| [M12] | D6.5.2-1 Automated Acceptance Tests (release 1) | SW | Public | KOCSISTEM +| [M20] | D6.5.2-2 Automated Acceptance Tests (release 2) | SW | Public | KOCSISTEM +| [M34] | D6.5.2-3 Automated Acceptance Tests (release 3) | SW | Public | KOCSISTEM +| [M14] | D6.6.1-1 Acceptance Test Procedures (release 1) | Doc. | Public | KOCSISTEM +| [M20] | D6.6.1-2 Acceptance Test Procedures (release 2) | Doc. | Public | KOCSISTEM +| [M34] | D6.6.1-3 Acceptance Test Procedures (release 3) | Doc. | Public | KOCSISTEM +| [M16] | D6.7.1-1 ModelWriter major release (release 1) | SW | Public | OBEO +| [M26] | D6.7.1-2 ModelWriter major release (release 2) | SW | Public | OBEO +| [M36] | D6.7.1-3 ModelWriter major release (release 3) | SW | Public | OBEO +| [M18] | D6.7.2-1 WP2 Integration in ModelWriter and Documentation (release 1) | SW | Public | OBEO +| [M26] | D6.7.2-2 WP2 Integration in ModelWriter and Documentation (release 2) | SW | Public | OBEO +| [M31] | D6.7.2-3 WP2 Integration in ModelWriter and Documentation (release 3) | SW | Public | OBEO +| [M17] | D6.8.1-1 Evaluation report (release 1) | Doc. | Public | KOCSISTEM +| [M27] | D6.8.1-2 Evaluation report (release 2) | Doc. | Public | KOCSISTEM +| [M37] | D6.8.1-3 Evaluation report (release 3) | Doc. | Public | KOCSISTEM +| [M6] | D7.1.1 Dissemination Plan | Doc. | Public | OBEO +| [M8] | D7.2.1-1 Exploitation and Marketing Plan (release 1) | Doc. | Public | AIRBUS, HISBIM +| [M22] | D7.2.1-2 Exploitation and Marketing Plan (release 2) | Doc. | Public | AIRBUS, HISBIM +| [M34] | D7.2.1-3 Exploitation and Marketing Plan (release 3) | Doc. | Public | AIRBUS, HISBIM +| [M34] | D7.2.2 Roadmap for future exploitation and pre-competition survey| Doc. | Public | HISBIM +| [M31] | D7.3.1 Newsletter - International Conference Announcement | Doc. | Public | UNIT +| [M1] | D7.4.1 ModelWriter-ITEA website | SW | Public | OBEO +| [M10] | D7.5.1 Technical-oriented talk about the principles and benefits of the ModelWriter-ITEA approach and tooling | Doc. | Public | OBEO +| [M10] | D7.5.2 Research-oriented talk about the principles and benefits of the ModelWriter-ITEA approach and tooling | Doc. | Public | UNIT +| [M10] | D7.6.1 ModelWriter-ITEA's LinkedIn Group | SW | Public | UNIT +| [M10] | D7.6.2 ModelWriter-ITEA's Twitter Group | SW | Public | UNIT +| [M34] | D7.7.1 ModelWriter and standardization activities | SW | Public | LORIA diff --git a/Source/eu.modelwriter.projectmanagement/docs/Leaders.md b/Source/eu.modelwriter.projectmanagement/docs/Leaders.md new file mode 100644 index 00000000..edf5b97a --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/docs/Leaders.md @@ -0,0 +1,12 @@ +| Organization | Primary Contact +|:---- |:---- +| AIRBUS | +| HAVELSAN | +| HISBIM | +| KOCSISTEM | +| SOGETI | +| KUL1 | +| KUL2 | +| OBEO | +| MANTIS | +| UNIT | \ No newline at end of file diff --git a/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP1.md b/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP1.md new file mode 100644 index 00000000..e0d231f0 --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP1.md @@ -0,0 +1,107 @@ +|Origin| Task | +|:---- |:---- +| | HAVELSAN +|T1.1 | T1.1 - Evaluation Methods & Tools +|T1.2 | T1.2 - Industrial Use Cases for Belgian Consortium +|T1.3 | T1.3 - Industrial Use Cases for French Consortium +|T1.4 | T1.4 - Industrial Use Cases for Turkish Consortium +|T1.5 | T1.5 - Consolidated User Requirements and Review +|T1.6 | DELETE +|T1.7 | T1.6 - Software Requirements and Review +|T1.8 | DELETE +|T1.9 | T1.7 - Annual Product Review +|T1.10 | T1.8 - Technical Risk Assessment and Management +|T2.1 | DELETE +|T2.2 | DELETE +|T2.3 | DELETE +|T2.4 | DELETE +|T2.5 | DELETE +|T3.1 | DELETE +|T3.2 | DELETE +|T3.3 | DELETE +|T3.4 | DELETE +|T3.5 | DELETE +|T3.6 | DELETE +|T3.7 | DELETE +|T3.8 | DELETE +|T3.9 | DELETE +|T4.1 | DELETE +|T4.2 | DELETE +|T4.3 | DELETE +|T4.4 | DELETE +|T4.5 | DELETE +|T4.6 | DELETE +|T4.7 | DELETE +|T4.9 | DELETE +|T4.10 | DELETE +|T5.1 | DELETE +|T5.2 | DELETE +|T5.3 | DELETE +|T5.4 | DELETE +|T5.5 | DELETE +|T5.6 | DELETE +|T5.7 | DELETE +|T5.8 | DELETE +|T5.9 | DELETE +|T6.1 | DELETE +|T6.2 | DELETE +|T6.3 | DELETE +|T6.4 | DELETE +|T6.5 | DELETE +|T6.6 | DELETE +|T6.7 | DELETE +|T6.8 | DELETE +|T7.1 | DELETE +|T7.2 | DELETE +|T7.3 | DELETE +|T7.4 | DELETE +|T7.5 | DELETE +|T7.6 | DELETE +|T7.7 | DELETE +|EADS | AIRBUS +|KUL | KUL1 +|SA | SOGETI +|VUB | KUL2 +|Confidential | Private +|1h | DELETE +|2h | DELETE +|4h | DELETE +|8h | DELETE +|2d | DELETE +|3d | DELETE +|4d | DELETE +|5d | DELETE +|10d | DELETE +|Development | Development +|Management | Management +|WP1 | DELETE +|WP2 | DELETE +|WP3 | DELETE +|WP4 | DELETE +|WP5 | DELETE +|WP6 | DELETE +|WP7 | DELETE +|UC-BE-01 | DELETE +|UC-BE-02 | DELETE +|UC-FR-01 | DELETE +|UC-FR-02 | DELETE +|UC-FR-03 | DELETE +|UC-FR-04 | DELETE +|UC-TR-01 | DELETE +|UC-TR-02 | DELETE +|UC-TR-03 | DELETE +|UC-TR-04 | DELETE +|UC-TR-05 | DELETE +| | UC-BE-01 +| | UC-BE-02 +| | UC-FR-01 +| | UC-FR-02 +| | UC-FR-03 +| | UC-FR-04 +| | UC-TR-01 +| | UC-TR-02 +| | UC-TR-03 +| | UC-TR-04 +| | UC-TR-05 + + diff --git a/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP2.md b/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP2.md new file mode 100644 index 00000000..695e7529 --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP2.md @@ -0,0 +1,84 @@ +|Origin| Task | +|:---- |:---- +| | HAVELSAN +|T1.1 | DELETE +|T1.2 | DELETE +|T1.3 | DELETE +|T1.4 | DELETE +|T1.5 | DELETE +|T1.6 | DELETE +|T1.7 | DELETE +|T1.8 | DELETE +|T1.9 | DELETE +|T1.10 | DELETE +|T2.1 | T2.1 - Data Collection +|T2.2 | T2.2 - Hybrid approaches to semantic parsing +|T2.3 | T2.3 - Hybrid approaches to Natural Language Generation +|T2.4 | T2.4 - Definition of the target semantic representation language +|T2.5 | T2.5 - Development of the semantic parser and of the generator +|T3.1 | DELETE +|T3.2 | DELETE +|T3.3 | DELETE +|T3.4 | DELETE +|T3.5 | DELETE +|T3.6 | DELETE +|T3.7 | DELETE +|T3.8 | DELETE +|T3.9 | DELETE +|T4.1 | DELETE +|T4.2 | DELETE +|T4.3 | DELETE +|T4.4 | DELETE +|T4.5 | DELETE +|T4.6 | DELETE +|T4.7 | DELETE +|T4.9 | DELETE +|T4.10 | DELETE +|T5.1 | DELETE +|T5.2 | DELETE +|T5.3 | DELETE +|T5.4 | DELETE +|T5.5 | DELETE +|T5.6 | DELETE +|T5.7 | DELETE +|T5.8 | DELETE +|T5.9 | DELETE +|T6.1 | DELETE +|T6.2 | DELETE +|T6.3 | DELETE +|T6.4 | DELETE +|T6.5 | DELETE +|T6.6 | DELETE +|T6.7 | DELETE +|T6.8 | DELETE +|T7.1 | DELETE +|T7.2 | DELETE +|T7.3 | DELETE +|T7.4 | DELETE +|T7.5 | DELETE +|T7.6 | DELETE +|T7.7 | DELETE +|EADS | AIRBUS +|KUL | KUL1 +|SA | SOGETI +|VUB | KUL2 +|Confidential | Private +|1h | DELETE +|2h | DELETE +|4h | DELETE +|8h | DELETE +|2d | DELETE +|3d | DELETE +|4d | DELETE +|5d | DELETE +|10d | DELETE +|Development | Development +|Management | Management +|WP1 | DELETE +|WP2 | DELETE +|WP3 | DELETE +|WP4 | DELETE +|WP5 | DELETE +|WP6 | DELETE +|WP7 | DELETE + diff --git a/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP3.md b/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP3.md new file mode 100644 index 00000000..945a8960 --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP3.md @@ -0,0 +1,84 @@ +|Origin| Task | +|:---- |:---- +| | HAVELSAN +|T1.1 | DELETE +|T1.2 | DELETE +|T1.3 | DELETE +|T1.4 | DELETE +|T1.5 | DELETE +|T1.6 | DELETE +|T1.7 | DELETE +|T1.8 | DELETE +|T1.9 | DELETE +|T1.10 | DELETE +|T2.1 | DELETE +|T2.2 | DELETE +|T2.3 | DELETE +|T2.4 | DELETE +|T2.5 | DELETE +|T3.1 | T3.1 - Review of M2M transformation approaches +|T3.2 | T3.2 - Specification and design of the M2M Transformation Framework +|T3.3 | T3.3 - Development of the Transformation Manager component +|T3.4 | T3.4 - Development of the Configuration Manager (COM) component +|T3.5 | T3.5 - Development of the Traceability Manager component +|T3.6 | T3.6 - Development of the Synchronization Manager component +|T3.7 | T3.7 - Design of the model-to-model transformations +|T3.8 | T3.8 - Implementation of the model-to-model transformations +|T3.9 | T3.9 - Validation of the M2M Transformation Framework +|T4.1 | DELETE +|T4.2 | DELETE +|T4.3 | DELETE +|T4.4 | DELETE +|T4.5 | DELETE +|T4.6 | DELETE +|T4.7 | DELETE +|T4.9 | DELETE +|T4.10 | DELETE +|T5.1 | DELETE +|T5.2 | DELETE +|T5.3 | DELETE +|T5.4 | DELETE +|T5.5 | DELETE +|T5.6 | DELETE +|T5.7 | DELETE +|T5.8 | DELETE +|T5.9 | DELETE +|T6.1 | DELETE +|T6.2 | DELETE +|T6.3 | DELETE +|T6.4 | DELETE +|T6.5 | DELETE +|T6.6 | DELETE +|T6.7 | DELETE +|T6.8 | DELETE +|T7.1 | DELETE +|T7.2 | DELETE +|T7.3 | DELETE +|T7.4 | DELETE +|T7.5 | DELETE +|T7.6 | DELETE +|T7.7 | DELETE +|EADS | AIRBUS +|KUL | KUL1 +|SA | SOGETI +|VUB | KUL2 +|Confidential | Private +|1h | DELETE +|2h | DELETE +|4h | DELETE +|8h | DELETE +|2d | DELETE +|3d | DELETE +|4d | DELETE +|5d | DELETE +|10d | DELETE +|Development | Development +|Management | Management +|WP1 | DELETE +|WP2 | DELETE +|WP3 | DELETE +|WP4 | DELETE +|WP5 | DELETE +|WP6 | DELETE +|WP7 | DELETE + diff --git a/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP4.md b/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP4.md new file mode 100644 index 00000000..826f06e5 --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP4.md @@ -0,0 +1,84 @@ +|Origin| Task | +|:---- |:---- +| | HAVELSAN +|T1.1 | DELETE +|T1.2 | DELETE +|T1.3 | DELETE +|T1.4 | DELETE +|T1.5 | DELETE +|T1.6 | DELETE +|T1.7 | DELETE +|T1.8 | DELETE +|T1.9 | DELETE +|T1.10 | DELETE +|T2.1 | DELETE +|T2.2 | DELETE +|T2.3 | DELETE +|T2.4 | DELETE +|T2.5 | DELETE +|T3.1 | DELETE +|T3.2 | DELETE +|T3.3 | DELETE +|T3.4 | DELETE +|T3.5 | DELETE +|T3.6 | DELETE +|T3.7 | DELETE +|T3.8 | DELETE +|T3.9 | DELETE +| | T4.1 - Design of the Knowledge Base +| | T4.2 - API of the Knowledge Base +| | T4.3 - Implementation of the Knowledge Base +| | T4.4 - Plug-in #1: ModelWriter-assisted requirements review +| | T4.5 - Knowledge Base serialization and reuse plug-in +| | T4.6 - Plug-in #3: ModelWriter-assisted semantic comparison of 2 docs. +| | T4.7 - Plug-in #2: ModelWriter-assisted compliance review +| | T4.8 - Internal bi-directional synchronization mechanism +| | T4.9 - External sync. mechanism for collaborating ModelWriters +|T5.1 | DELETE +|T5.2 | DELETE +|T5.3 | DELETE +|T5.4 | DELETE +|T5.5 | DELETE +|T5.6 | DELETE +|T5.7 | DELETE +|T5.8 | DELETE +|T5.9 | DELETE +|T6.1 | DELETE +|T6.2 | DELETE +|T6.3 | DELETE +|T6.4 | DELETE +|T6.5 | DELETE +|T6.6 | DELETE +|T6.7 | DELETE +|T6.8 | DELETE +|T7.1 | DELETE +|T7.2 | DELETE +|T7.3 | DELETE +|T7.4 | DELETE +|T7.5 | DELETE +|T7.6 | DELETE +|T7.7 | DELETE +|EADS | AIRBUS +|KUL | KUL1 +|SA | SOGETI +|VUB | KUL2 +|Confidential | Private +|1h | DELETE +|2h | DELETE +|4h | DELETE +|8h | DELETE +|2d | DELETE +|3d | DELETE +|4d | DELETE +|5d | DELETE +|10d | DELETE +|Development | Development +|Management | Management +|WP1 | DELETE +|WP2 | DELETE +|WP3 | DELETE +|WP4 | DELETE +|WP5 | DELETE +|WP6 | DELETE +|WP7 | DELETE + diff --git a/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP5.md b/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP5.md new file mode 100644 index 00000000..0d9a333e --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP5.md @@ -0,0 +1,75 @@ +|Origin| Task | +|:---- |:---- +| | HAVELSAN +|T1.1 | DELETE +|T1.2 | DELETE +|T1.3 | DELETE +|T1.4 | DELETE +|T1.5 | DELETE +|T1.6 | DELETE +|T1.7 | DELETE +|T1.8 | DELETE +|T1.9 | DELETE +|T1.10 | DELETE +|T2.1 | DELETE +|T2.2 | DELETE +|T2.3 | DELETE +|T2.4 | DELETE +|T2.5 | DELETE +|T3.1 | DELETE +|T3.2 | DELETE +|T3.3 | DELETE +|T3.4 | DELETE +|T3.5 | DELETE +|T3.6 | DELETE +|T3.7 | DELETE +|T3.8 | DELETE +|T3.9 | DELETE +|T4.1 | DELETE +|T4.2 | DELETE +|T4.3 | DELETE +|T4.4 | DELETE +|T4.5 | DELETE +|T4.6 | DELETE +|T4.7 | DELETE +|T4.9 | DELETE +|T4.10 | DELETE +|T5.1 | T5.2 - Project Coordination and Reporting +|T5.2 | DELETE +|T5.3 | T5.3 - Project Controls +|T5.4 | DELETE +|T5.5 | T5.1 - Communication Management and Collaboration Infrastructure +|T5.6 | DELETE +|T5.7 | DELETE +|T5.8 | DELETE +|T5.9 | T5.4 - Closing Project +|T6.1 | DELETE +|T6.2 | DELETE +|T6.3 | DELETE +|T6.4 | DELETE +|T6.5 | DELETE +|T6.6 | DELETE +|T6.7 | DELETE +|T6.8 | DELETE +|T7.1 | DELETE +|T7.2 | DELETE +|T7.3 | DELETE +|T7.4 | DELETE +|T7.5 | DELETE +|T7.6 | DELETE +|T7.7 | DELETE +|EADS | AIRBUS +|KUL | KUL1 +|SA | SOGETI +|VUB | KUL2 +|Confidential | Private +|Development | Development +|Management | Management +|WP1 | DELETE +|WP2 | DELETE +|WP3 | DELETE +|WP4 | DELETE +|WP5 | DELETE +|WP6 | DELETE +|WP7 | DELETE + diff --git a/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP6.md b/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP6.md new file mode 100644 index 00000000..ad8485eb --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP6.md @@ -0,0 +1,84 @@ +|Origin| Task | +|:---- |:---- +| | HAVELSAN +|T1.1 | DELETE +|T1.2 | DELETE +|T1.3 | DELETE +|T1.4 | DELETE +|T1.5 | DELETE +|T1.6 | DELETE +|T1.7 | DELETE +|T1.8 | DELETE +|T1.9 | DELETE +|T1.10 | DELETE +|T2.1 | DELETE +|T2.2 | DELETE +|T2.3 | DELETE +|T2.4 | DELETE +|T2.5 | DELETE +|T3.1 | DELETE +|T3.2 | DELETE +|T3.3 | DELETE +|T3.4 | DELETE +|T3.5 | DELETE +|T3.6 | DELETE +|T3.7 | DELETE +|T3.8 | DELETE +|T3.9 | DELETE +|T4.1 | DELETE +|T4.2 | DELETE +|T4.3 | DELETE +|T4.4 | DELETE +|T4.5 | DELETE +|T4.6 | DELETE +|T4.7 | DELETE +|T4.9 | DELETE +|T4.10 | DELETE +|T5.1 | DELETE +|T5.2 | DELETE +|T5.3 | DELETE +|T5.4 | DELETE +|T5.5 | DELETE +|T5.6 | DELETE +|T5.7 | DELETE +|T5.8 | DELETE +|T5.9 | DELETE +|T6.1 | T6.1 - Experimental Prototyping +|T6.2 | T6.2 - Architectural Design +|T6.3 | T6.3 - Writer Part enhancements +|T6.4 | T6.4 - User Interfaces Implementation +|T6.5 | T6.5 - Acceptance Test Plan +|T6.6 | T6.6 - Acceptance Test Procedures +|T6.7 | T6.7 - ModelWriter Integration +|T6.8 | T6.8 - Cyclic Evaluation of Analysis Performance +|T7.1 | DELETE +|T7.2 | DELETE +|T7.3 | DELETE +|T7.4 | DELETE +|T7.5 | DELETE +|T7.6 | DELETE +|T7.7 | DELETE +|EADS | AIRBUS +|KUL | KUL1 +|SA | SOGETI +|VUB | KUL2 +|Confidential | Private +|1h | DELETE +|2h | DELETE +|4h | DELETE +|8h | DELETE +|2d | DELETE +|3d | DELETE +|4d | DELETE +|5d | DELETE +|10d | DELETE +|Development | Development +|Management | Management +|WP1 | DELETE +|WP2 | DELETE +|WP3 | DELETE +|WP4 | DELETE +|WP5 | DELETE +|WP6 | DELETE +|WP7 | DELETE + diff --git a/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP7.md b/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP7.md new file mode 100644 index 00000000..c7e45644 --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes - WP7.md @@ -0,0 +1,84 @@ +|Origin| Task | +|:---- |:---- +| | HAVELSAN +|T1.1 | DELETE +|T1.2 | DELETE +|T1.3 | DELETE +|T1.4 | DELETE +|T1.5 | DELETE +|T1.6 | DELETE +|T1.7 | DELETE +|T1.8 | DELETE +|T1.9 | DELETE +|T1.10 | DELETE +|T2.1 | DELETE +|T2.2 | DELETE +|T2.3 | DELETE +|T2.4 | DELETE +|T2.5 | DELETE +|T3.1 | DELETE +|T3.2 | DELETE +|T3.3 | DELETE +|T3.4 | DELETE +|T3.5 | DELETE +|T3.6 | DELETE +|T3.7 | DELETE +|T3.8 | DELETE +|T3.9 | DELETE +|T4.1 | DELETE +|T4.2 | DELETE +|T4.3 | DELETE +|T4.4 | DELETE +|T4.5 | DELETE +|T4.6 | DELETE +|T4.7 | DELETE +|T4.9 | DELETE +|T4.10 | DELETE +|T5.1 | DELETE +|T5.2 | DELETE +|T5.3 | DELETE +|T5.4 | DELETE +|T5.5 | DELETE +|T5.6 | DELETE +|T5.7 | DELETE +|T5.8 | DELETE +|T5.9 | DELETE +|T6.1 | DELETE +|T6.2 | DELETE +|T6.3 | DELETE +|T6.4 | DELETE +|T6.5 | DELETE +|T6.6 | DELETE +|T6.7 | DELETE +|T6.8 | DELETE +|T7.1 | T7.1 - Dissemination Plan +|T7.2 | T7.2 - Business Model & Exploitation Plan +|T7.3 | T7.3 - Workshops & Events +|T7.4 | T7.4 - ModelWriter-ITEA Consortium Website +|T7.5 | T7.5 - Community Forum & Open Source Campaign +|T7.6 | T7.6 - Social Networks +|T7.7 | T7.7 - Standardization +|EADS | AIRBUS +|KUL | KUL1 +|SA | SOGETI +|VUB | KUL2 +|Confidential | Private +|1h | DELETE +|2h | DELETE +|4h | DELETE +|8h | DELETE +|2d | DELETE +|3d | DELETE +|4d | DELETE +|5d | DELETE +|10d | DELETE +|Development | Development +|Management | Management +|WP1 | DELETE +|WP2 | DELETE +|WP3 | DELETE +|WP4 | DELETE +|WP5 | DELETE +|WP6 | DELETE +|WP7 | DELETE + diff --git a/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes.md b/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes.md new file mode 100644 index 00000000..af26222e --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/docs/Tasks - Changes.md @@ -0,0 +1,66 @@ +|Origin| Task | +|:---- |:---- +| | HAVELSAN +|T1.1 | T1.1 - Evaluation Methods & Tools +|T1.2 | T1.2 - Industrial Use Cases for Belgian Consortium +|T1.3 | T1.3 - Industrial Use Cases for French Consortium +|T1.4 | T1.4 - Industrial Use Cases for Turkish Consortium +|T1.5 | T1.5 - Consolidated User Requirements and Review +|T1.6 | DELETE +|T1.7 | T1.6 - Software Requirements and Review +|T1.8 | DELETE +|T1.9 | T1.7 - Annual Product Review +|T1.10 | T1.8 - Technical Risk Assessment and Management +|T2.1 | T2.1 - Data Collection +|T2.2 | T2.2 - Hybrid approaches to semantic parsing +|T2.3 | T2.3 - Hybrid approaches to Natural Language Generation +|T2.4 | T2.4 - Definition of the target semantic representation language +|T2.5 | T2.5 - Development of the semantic parser and of the generator +|T3.1 | T3.1 - Review of M2M transformation approaches +|T3.2 | T3.2 - Specification and design of the M2M Transformation Framework +|T3.3 | T3.3 - Development of the Transformation Manager component +|T3.4 | T3.4 - Development of the Configuration Manager (COM) component +|T3.5 | T3.5 - Development of the Traceability Manager component +|T3.6 | T3.6 - Development of the Synchronization Manager component +|T3.7 | T3.7 - Design of the model-to-model transformations +|T3.8 | T3.8 - Implementation of the model-to-model transformations +|T3.9 | T3.9 - Validation of the M2M Transformation Framework +|T4.1 | T4.1 - Design of the Knowledge Base +|T4.2 | T4.2 - API of the Knowledge Base +|T4.3 | T4.3 - Implementation of the Knowledge Base +|T4.4 | T4.4 - Plug-in #1: ModelWriter-assisted requirements review +|T4.5 | T4.5 - Knowledge Base serialization and reuse plug-in +|T4.6 | T4.6 - Plug-in #3: ModelWriter-assisted semantic comparison of 2 docs. +|T4.7 | T4.7 - Plug-in #2: ModelWriter-assisted compliance review +|T4.9 | T4.8 - Internal bi-directional synchronization mechanism +|T4.10 | T4.9 - External sync. mechanism for collaborating ModelWriters +|T5.1 | T5.2 - Project Coordination and Reporting +|T5.2 | DELETE +|T5.3 | T5.3 - Project Controls +|T5.4 | DELETE +|T5.5 | T5.1 - Communication Management and Collaboration Infrastructure +|T5.6 | DELETE +|T5.7 | DELETE +|T5.8 | DELETE +|T5.9 | T5.4 - Closing Project +|T6.1 | T6.1 - Experimental Prototyping +|T6.2 | T6.2 - Architectural Design +|T6.3 | T6.3 - Writer Part enhancements +|T6.4 | T6.4 - User Interfaces Implementation +|T6.5 | T6.5 - Acceptance Test Plan +|T6.6 | T6.6 - Acceptance Test Procedures +|T6.7 | T6.7 - ModelWriter Integration +|T6.8 | T6.8 - Cyclic Evaluation of Analysis Performance +|T7.1 | T7.1 - Dissemination Plan +|T7.2 | T7.2 - Business Model & Exploitation Plan +|T7.3 | T7.3 - Workshops & Events +|T7.4 | T7.4 - ModelWriter-ITEA Consortium Website +|T7.5 | T7.5 - Community Forum & Open Source Campaign +|T7.6 | T7.6 - Social Networks +|T7.7 | T7.7 - Standardization +|EADS | AIRBUS +|KUL | KUL1 +|SA | SOGETI +|VUB | KUL2 +|Confidential | Private + diff --git a/Source/eu.modelwriter.projectmanagement/docs/Tasks - Updated.md b/Source/eu.modelwriter.projectmanagement/docs/Tasks - Updated.md new file mode 100644 index 00000000..273064bb --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/docs/Tasks - Updated.md @@ -0,0 +1,52 @@ +| Task | +|:---- +| T1.1 - Evaluation Methods & Tools +| T1.2 - Industrial Use Cases for Belgian Consortium +| T1.3 - Industrial Use Cases for French Consortium +| T1.4 - Industrial Use Cases for Turkish Consortium +| T1.5 - Consolidated User Requirements +| T1.6 - Software Requirements and Review +| T1.7 - Annual Product Review +| T1.8 - Technical Risk Assessment and Management +| T2.1 - Data Collection +| T2.2 - Hybrid approaches to semantic parsing +| T2.3 - Hybrid approaches to Natural Language Generation +| T2.4 - Definition of the target semantic representation language +| T2.5 - Development of the semantic parser and of the generator +| T3.1 - Review of M2M transformation approaches +| T3.2 - Specification and design of the M2M Transformation Framework +| T3.3 - Development of the Transformation Manager component +| T3.4 - Development of the Configuration Manager (COM) component +| T3.5 - Development of the Traceability Manager component +| T3.6 - Development of the Synchronization Manager component +| T3.7 - Design of the model-to-model transformations +| T3.8 - Implementation of the model-to-model transformations +| T3.9 - Validation of the M2M Transformation Framework +| T4.1 - Design of the Knowledge Base +| T4.2 - API of the Knowledge Base +| T4.3 - Implementation of the Knowledge Base +| T4.4 - Plug-in #1: ModelWriter-assisted requirements review +| T4.5 - Knowledge Base serialization and reuse plug-in +| T4.6 - Plug-in #3: ModelWriter-assisted semantic comparison of 2 docs. +| T4.7 - Plug-in #2: ModelWriter-assisted compliance review +| T4.8 - Internal bi-directional synchronization mechanism +| T4.9 - External sync. mechanism for collaborating ModelWriters +| T5.1 - Communication Management and Collaboration Infrastructure +| T5.2 - Project Coordination and Reporting +| T5.3 - Project Controls +| T5.4 - Closing Project +| T6.1 - Experimental Prototyping +| T6.2 - Architectural Design +| T6.3 - Writer Part enhancements +| T6.4 - User Interfaces Implementation +| T6.5 - Acceptance Test Plan +| T6.6 - Acceptance Test Procedures +| T6.7 - ModelWriter Integration +| T6.8 - Cyclic Evaluation of Analysis Performance +| T7.1 - Dissemination Plan +| T7.2 - Business Model & Exploitation Plan +| T7.3 - Workshops & Events +| T7.4 - ModelWriter-ITEA Consortium Website +| T7.5 - Community Forum & Open Source Campaign +| T7.6 - Social Networks +| T7.7 - Standardization diff --git a/Source/eu.modelwriter.projectmanagement/docs/Untitled.usr b/Source/eu.modelwriter.projectmanagement/docs/Untitled.usr new file mode 100644 index 00000000..494c133d --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/docs/Untitled.usr @@ -0,0 +1 @@ +sds diff --git a/Source/eu.modelwriter.projectmanagement/docs/sample1.readme b/Source/eu.modelwriter.projectmanagement/docs/sample1.readme new file mode 100644 index 00000000..f49511da --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/docs/sample1.readme @@ -0,0 +1,17 @@ + + + SAMPLE README FILE + +1. SECTION 1 +This text is a placeholder for the section body. +1.1 Subsection + This text is a placeholder for the subsection body +2. SECTION 2 +This text is a placeholder for the section body. It is +a bit longer in order to span two lines. + 2.1 Subsection + This text is a placeholder for the subsection body + 2.2 Subsection + This text is a placeholder for the subsection body + + diff --git a/Source/eu.modelwriter.projectmanagement/docs/test.jav b/Source/eu.modelwriter.projectmanagement/docs/test.jav new file mode 100644 index 00000000..d1821c21 --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/docs/test.jav @@ -0,0 +1,56 @@ +package eu.modelwriter.projectmanagement; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "eu.modelwriter.projectmanagement"; //$NON-NLS-1$ + + // The shared instance + private static Activator plugin; + + /** + * The constructor + */ + public Activator() {boolean s + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + + + public static Activator getDefault() { + return plugin; + } + + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(PLUGIN_ID, path); + } +} diff --git a/Source/eu.modelwriter.projectmanagement/docs/test.md b/Source/eu.modelwriter.projectmanagement/docs/test.md new file mode 100644 index 00000000..9e377250 --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/docs/test.md @@ -0,0 +1,34 @@ +Hello all, +@ModelWriter/consortium + +This issue is about defining all the development good practices we need to apply on all the MW project plug-ins. + +Please feel free to discuss any related detail here. +Regards, +Marwa + + +## WP1 - Industrial Use Cases and Requirements (AIRBUS) + +![WP1 - Cost & Efforts](figures/wp1.png) + +### T1.1 - Evaluation Methods & Tools [UNIT + KOCSISTEM + AIRBUS + OBEO + HISBIM + MANTIS] + + +------------------------------------------------------- +**GOOD PRACTICES:** +------------------------------------------------------- +* In the workspace: + * Please set the right files encoding : to do so go to **Window -> Preferences -> Workspace** and choose the **UTF-8** encoding instead of the Cp1252 encoding as a default one + * Please add facilities actions to format well the content of your files: to do so go to **Window -> Preferences -> Java -> Editor -> Save Actions** and check the box to **format all lines** of the source code and the **Organize Imports** box. + +This will prevent some merge and rebase problems for other partners working on the same code. + +* Github process to keep the history clean and easy to read: + * Please configure correctly your git to display correctly your name/email commits + * Please use the command: **git pull --rebase** instead of **merging**. This will keep a linear readable history. + * For all work in progress please make a branch based on the current master branch and named **wip/< name of your current task >**. Then, when the task progress is finished please rebase on the master branch ensure that other partners are not working on the branch before deleting it from the repository. + * For each finished deliverable task please create a tag using the **deliverable code**, **name** and its **milestone** as a name (e.g + **D6.1.1-SoftwarePrototypeCoreModelWriter-M6**) + +**To Be Continued** during the project lifecycle... diff --git a/Source/eu.modelwriter.projectmanagement/docs/test.mpe b/Source/eu.modelwriter.projectmanagement/docs/test.mpe new file mode 100644 index 00000000..809adacb --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/docs/test.mpe @@ -0,0 +1 @@ +ssasas \ No newline at end of file diff --git a/Source/eu.modelwriter.projectmanagement/docs/test.readme b/Source/eu.modelwriter.projectmanagement/docs/test.readme new file mode 100644 index 00000000..f7715d64 --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/docs/test.readme @@ -0,0 +1,5 @@ + SAMPLE README FILE + + 1. SECTION s + +This text is a placeholder for the section body. \ No newline at end of file diff --git a/Source/eu.modelwriter.projectmanagement/icons/sample.gif b/Source/eu.modelwriter.projectmanagement/icons/sample.gif new file mode 100644 index 00000000..148c2fcf Binary files /dev/null and b/Source/eu.modelwriter.projectmanagement/icons/sample.gif differ diff --git a/Source/eu.modelwriter.projectmanagement/lib/dom4j-1.6.1.jar b/Source/eu.modelwriter.projectmanagement/lib/dom4j-1.6.1.jar new file mode 100644 index 00000000..c8c4dbb9 Binary files /dev/null and b/Source/eu.modelwriter.projectmanagement/lib/dom4j-1.6.1.jar differ diff --git a/Source/eu.modelwriter.projectmanagement/lib/poi-3.9-20121203.jar b/Source/eu.modelwriter.projectmanagement/lib/poi-3.9-20121203.jar new file mode 100644 index 00000000..0f462880 Binary files /dev/null and b/Source/eu.modelwriter.projectmanagement/lib/poi-3.9-20121203.jar differ diff --git a/Source/eu.modelwriter.projectmanagement/lib/poi-ooxml-3.9-20121203.jar b/Source/eu.modelwriter.projectmanagement/lib/poi-ooxml-3.9-20121203.jar new file mode 100644 index 00000000..8792d463 Binary files /dev/null and b/Source/eu.modelwriter.projectmanagement/lib/poi-ooxml-3.9-20121203.jar differ diff --git a/Source/eu.modelwriter.projectmanagement/lib/poi-ooxml-schemas-3.9-20121203.jar b/Source/eu.modelwriter.projectmanagement/lib/poi-ooxml-schemas-3.9-20121203.jar new file mode 100644 index 00000000..eda4ef49 Binary files /dev/null and b/Source/eu.modelwriter.projectmanagement/lib/poi-ooxml-schemas-3.9-20121203.jar differ diff --git a/Source/eu.modelwriter.projectmanagement/lib/xmlbeans-2.3.0.jar b/Source/eu.modelwriter.projectmanagement/lib/xmlbeans-2.3.0.jar new file mode 100644 index 00000000..ccd81634 Binary files /dev/null and b/Source/eu.modelwriter.projectmanagement/lib/xmlbeans-2.3.0.jar differ diff --git a/Source/eu.modelwriter.projectmanagement/plugin.xml b/Source/eu.modelwriter.projectmanagement/plugin.xml new file mode 100644 index 00000000..12e03a42 --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/plugin.xml @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/eu.modelwriter.projectmanagement/src/eu/modelwriter/projectmanagement/Activator.java b/Source/eu.modelwriter.projectmanagement/src/eu/modelwriter/projectmanagement/Activator.java new file mode 100644 index 00000000..970d4d70 --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/src/eu/modelwriter/projectmanagement/Activator.java @@ -0,0 +1,61 @@ +package eu.modelwriter.projectmanagement; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "eu.modelwriter.projectmanagement"; //$NON-NLS-1$ + + // The shared instance + private static Activator plugin; + + /** + * The constructor + */ + public Activator() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + + /** + * Returns an image descriptor for the image file at the given + * plug-in relative path + * + * @param path the path + * @return the image descriptor + */ + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(PLUGIN_ID, path); + } +} diff --git a/Source/eu.modelwriter.projectmanagement/src/eu/modelwriter/projectmanagement/dialogs/PasswordDialog.java b/Source/eu.modelwriter.projectmanagement/src/eu/modelwriter/projectmanagement/dialogs/PasswordDialog.java new file mode 100644 index 00000000..ec81519c --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/src/eu/modelwriter/projectmanagement/dialogs/PasswordDialog.java @@ -0,0 +1,90 @@ +package eu.modelwriter.projectmanagement.dialogs; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.layout.GridData; + +public class PasswordDialog extends Dialog { + private Text txtUser; + private Text txtPassword; + private String user = ""; + private String password = ""; + + public PasswordDialog(Shell parentShell) { + super(parentShell); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite container = (Composite) super.createDialogArea(parent); + GridLayout layout = new GridLayout(2, false); + layout.marginRight = 5; + layout.marginLeft = 10; + container.setLayout(layout); + + Label lblUser = new Label(container, SWT.NONE); + lblUser.setText("User:"); + + txtUser = new Text(container, SWT.BORDER); + txtUser.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); + txtUser.setText(user); + + Label lblPassword = new Label(container, SWT.NONE); + GridData gd_lblNewLabel = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); + gd_lblNewLabel.horizontalIndent = 1; + lblPassword.setLayoutData(gd_lblNewLabel); + lblPassword.setText("Password:"); + + txtPassword = new Text(container, SWT.BORDER | SWT.SINGLE | SWT.PASSWORD); + txtPassword.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); + txtPassword.setText(password); + return container; + } + + // override method to use "Login" as label for the OK button + @Override + protected void createButtonsForButtonBar(Composite parent) { + createButton(parent, IDialogConstants.OK_ID, "Login", true); + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); + } + + @Override + protected Point getInitialSize() { + return new Point(400, 150); + } + + @Override + protected void okPressed() { + // Copy data from SWT widgets into fields on button press. + // Reading data from the widgets later will cause an SWT + // widget disposed exception. + user = txtUser.getText(); + password = txtPassword.getText(); + super.okPressed(); + } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + +} diff --git a/Source/eu.modelwriter.projectmanagement/src/eu/modelwriter/projectmanagement/github/Constants.java b/Source/eu.modelwriter.projectmanagement/src/eu/modelwriter/projectmanagement/github/Constants.java new file mode 100644 index 00000000..33f08fd9 --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/src/eu/modelwriter/projectmanagement/github/Constants.java @@ -0,0 +1,8 @@ +package eu.modelwriter.projectmanagement.github; + +public final class Constants { + public static String USERNAME = ""; + public static String PASSWORD = ""; + public static String ORGANIZATION = "ModelWriter"; + public static String REPOSITORY = "Requirements"; +} diff --git a/Source/eu.modelwriter.projectmanagement/src/eu/modelwriter/projectmanagement/github/IssueManagement.java b/Source/eu.modelwriter.projectmanagement/src/eu/modelwriter/projectmanagement/github/IssueManagement.java new file mode 100644 index 00000000..8dc1ae58 --- /dev/null +++ b/Source/eu.modelwriter.projectmanagement/src/eu/modelwriter/projectmanagement/github/IssueManagement.java @@ -0,0 +1,245 @@ +package eu.modelwriter.projectmanagement.github; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.egit.github.core.Issue; +import org.eclipse.egit.github.core.Label; +import org.eclipse.egit.github.core.RepositoryId; +import org.eclipse.egit.github.core.client.GitHubClient; +import org.eclipse.egit.github.core.service.LabelService; +import org.eclipse.egit.github.core.service.IssueService; +import org.eclipse.egit.github.core.service.MilestoneService; + +public class IssueManagement { + + public static void main(String[] args) { + + } + + public static Map deliverables = new HashMap(); + + public static void UpdateAll() throws IOException { + + GitHubClient client = new GitHubClient(); + client.setCredentials("ferhaterata", ""); + + RepositoryId repositoryId = new RepositoryId("modelwriter", "WP7"); + + IssueManagement.updateTasks(client, repositoryId); + + // ModelWriterIssueManagement.loadDeliverableMap(client, repositoryId); + + // ModelWriterIssueManagement.updateDeliverables(client, repositoryId); + + + // org.eclipse.egit.github.core.client.RequestException: Validation + // Failed (422): Label resource with 'name' field already exists + } + + + private static void loadDeliverableMap(GitHubClient client, RepositoryId repositoryId) + throws IOException { + IssueService iService = new IssueService(client); + for (Issue issue : iService.getIssues(repositoryId, null)) { + deliverables.put(issue.getTitle().substring(0, issue.getTitle().indexOf(' ')), + issue.getNumber()); + } + } + + + public static void updateDeliverables(GitHubClient client, RepositoryId repositoryId) { + try { + URL url = new URL( + "platform:/plugin/eu.modelwriter.projectmanagement/docs/Deliverables - Changes.md"); + BufferedReader bufferedReader = + new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8")); + String line; + bufferedReader.readLine(); + bufferedReader.readLine(); + while ((line = bufferedReader.readLine()) != null) { + if (line.isEmpty()) + continue; + String[] strings = line.split("\\|"); + System.out.println(strings[1].trim() + " -> " + strings[3].trim() + " -Month: " + + strings[2].trim() + " -Type: " + strings[4].trim() + " -Access:" + strings[5].trim() + + " -Leader:" + strings[6].trim()); + String oldDeliverableCode = strings[1].trim(); + String changedTitle = strings[3].trim(); + if (changedTitle.equals("DELETE")) { + IssueService iService = new IssueService(client); + Issue issue = getIssueStartsWith(client, repositoryId, oldDeliverableCode); + issue.setTitle("DELETED: " + issue.getTitle()); + List